diff --git a/.all-contributorsrc b/.all-contributorsrc index a5c01829b06..ce3c46929f0 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -91,7 +91,6 @@ "login": "ajsantander", "name": "Alejandro Santander", "avatar_url": "https://avatars2.githubusercontent.com/u/550409?v=4", - "profile": "http://ajsantander.github.io/", "contributions": [ "content" ] @@ -423,7 +422,6 @@ "login": "carumusan", "name": "carumusan", "avatar_url": "https://avatars1.githubusercontent.com/u/879525?v=4", - "profile": "https://github.com/carumusan", "contributions": [ "content" ] @@ -1076,7 +1074,6 @@ "login": "its-VSP", "name": "SAI PRASHANTH VUPPALA", "avatar_url": "https://avatars0.githubusercontent.com/u/22447085?v=4", - "profile": "https://github.com/its-VSP", "contributions": [ "content", "translation" @@ -1160,7 +1157,6 @@ "login": "Sesamestrong", "name": "Sesamestrong", "avatar_url": "https://avatars3.githubusercontent.com/u/26335275?v=4", - "profile": "https://github.com/Sesamestrong", "contributions": [ "code" ] @@ -1178,7 +1174,6 @@ "login": "svanas", "name": "Stefan van As", "avatar_url": "https://avatars1.githubusercontent.com/u/787861?v=4", - "profile": "https://stackoverflow.com/story/svanas", "contributions": [ "content" ] @@ -1373,7 +1368,6 @@ "login": "mhatvan", "name": "Markus Hatvan", "avatar_url": "https://avatars2.githubusercontent.com/u/16797721?v=4", - "profile": "https://github.com/mhatvan", "contributions": [ "code" ] @@ -1886,7 +1880,6 @@ "login": "jcamilli", "name": "jcamilli", "avatar_url": "https://avatars3.githubusercontent.com/u/1952742?v=4", - "profile": "https://github.com/jcamilli", "contributions": [ "content" ] @@ -2031,7 +2024,6 @@ "login": "shreyashariharan3", "name": "shreyashariharan3", "avatar_url": "https://avatars3.githubusercontent.com/u/48186822?v=4", - "profile": "https://github.com/shreyashariharan3", "contributions": [ "content" ] @@ -2150,7 +2142,6 @@ "login": "mustafawm", "name": "mustafa", "avatar_url": "https://avatars0.githubusercontent.com/u/13101565?v=4", - "profile": "https://github.com/mustafawm", "contributions": [ "content" ] @@ -2190,7 +2181,6 @@ "login": "DrMad92", "name": "DrMad92", "avatar_url": "https://avatars2.githubusercontent.com/u/28419987?v=4", - "profile": "https://github.com/DrMad92", "contributions": [ "bug" ] @@ -2379,7 +2369,6 @@ "login": "Arnor1711", "name": "Alwin Stockinger", "avatar_url": "https://avatars2.githubusercontent.com/u/23365186?v=4", - "profile": "https://github.com/Arnor1711", "contributions": [ "bug", "content" @@ -2511,7 +2500,6 @@ "login": "Kristiyan96", "name": "Kristiyan", "avatar_url": "https://avatars3.githubusercontent.com/u/15987117?v=4", - "profile": "https://github.com/Kristiyan96", "contributions": [ "bug", "code" @@ -2968,7 +2956,6 @@ "login": "vemuez", "name": "Yussuf Elarif", "avatar_url": "https://avatars.githubusercontent.com/u/9627828?v=4", - "profile": "https://github.com/vemuez", "contributions": [ "bug" ] @@ -3088,7 +3075,6 @@ "login": "stuz5000", "name": "Stuart Reynolds", "avatar_url": "https://avatars.githubusercontent.com/u/7799980?v=4", - "profile": "https://github.com/stuz5000", "contributions": [ "ideas" ] @@ -3827,7 +3813,6 @@ "login": "davidplutus", "name": "davidplutus", "avatar_url": "https://avatars.githubusercontent.com/u/63456936?v=4", - "profile": "https://github.com/DavidPlutus", "contributions": [ "ideas" ] @@ -3909,7 +3894,6 @@ "login": "Uttam-Singhh", "name": "Uttam Singh", "avatar_url": "https://avatars.githubusercontent.com/u/63050765?v=4", - "profile": "https://uttam-singhh.github.io/Portfolio/", "contributions": [ "bug" ] @@ -4412,7 +4396,6 @@ "login": "smudgil", "name": "smudgil", "avatar_url": "https://avatars.githubusercontent.com/u/38195323?v=4", - "profile": "https://github.com/smudgil", "contributions": [ "content" ] @@ -4469,7 +4452,6 @@ "login": "matthewrkula", "name": "Matt Kula", "avatar_url": "https://avatars.githubusercontent.com/u/1483546?v=4", - "profile": "https://github.com/matthewrkula", "contributions": [ "bug" ] @@ -4920,7 +4902,6 @@ "login": "phatngluu", "name": "Phat Nguyen Luu", "avatar_url": "https://avatars.githubusercontent.com/u/44693107?v=4", - "profile": "https://github.com/phatngluu", "contributions": [ "doc" ] @@ -4929,7 +4910,6 @@ "login": "Andrew-Sofos", "name": "Andreas Sofos", "avatar_url": "https://avatars.githubusercontent.com/u/56540744?v=4", - "profile": "https://github.com/Andrew-Sofos", "contributions": [ "code" ] @@ -5159,7 +5139,6 @@ "login": "solarpunklabs", "name": "solarpunklabs", "avatar_url": "https://avatars.githubusercontent.com/u/84196983?v=4", - "profile": "https://github.com/solarpunklabs", "contributions": [ "ideas" ] @@ -5177,7 +5156,6 @@ "login": "shryasss", "name": "Shreyas Londhe", "avatar_url": "https://avatars.githubusercontent.com/u/62744899?v=4", - "profile": "https://github.com/shryasss", "contributions": [ "content" ] @@ -5370,7 +5348,6 @@ "login": "RedWolf4845", "name": "Samrat", "avatar_url": "https://avatars.githubusercontent.com/u/93679609?v=4", - "profile": "https://github.com/RedWolf4845", "contributions": [ "content" ] @@ -5577,7 +5554,6 @@ "login": "eulerbeat", "name": "Minimalist Optimalist", "avatar_url": "https://avatars.githubusercontent.com/u/52531715?v=4", - "profile": "https://github.com/eulerbeat", "contributions": [ "bug" ] @@ -5861,7 +5837,6 @@ "login": "decipherer2", "name": "decifer", "avatar_url": "https://avatars.githubusercontent.com/u/16278986?v=4", - "profile": "https://github.com/decipherer2", "contributions": [ "ideas" ] @@ -5908,7 +5883,6 @@ "login": "kum9748ar", "name": "Kumar Kalyan", "avatar_url": "https://avatars.githubusercontent.com/u/67071462?v=4", - "profile": "https://linktr.ee/kumarkalyan", "contributions": [ "bug", "doc", @@ -5920,7 +5894,6 @@ "login": "0xdie", "name": "0xdie", "avatar_url": "https://avatars.githubusercontent.com/u/94481845?v=4", - "profile": "https://github.com/0xdie", "contributions": [ "doc" ] @@ -6070,7 +6043,6 @@ "login": "neozapatista", "name": "neozapatista", "avatar_url": "https://avatars.githubusercontent.com/u/44417247?v=4", - "profile": "https://github.com/neozapatista", "contributions": [ "doc" ] @@ -6119,7 +6091,6 @@ "login": "Gobljn", "name": "Nicola Bonsi", "avatar_url": "https://avatars.githubusercontent.com/u/44135563?v=4", - "profile": "https://github.com/Gobljn", "contributions": [ "ideas" ] @@ -6194,7 +6165,6 @@ "login": "stefan-wuest", "name": "SW", "avatar_url": "https://avatars.githubusercontent.com/u/20667579?v=4", - "profile": "https://github.com/stefan-wuest", "contributions": [ "doc" ] @@ -6212,7 +6182,6 @@ "login": "Qazalin", "name": "Qazal Samani", "avatar_url": "https://avatars.githubusercontent.com/u/77887910?v=4", - "profile": "https://portfolio-qazalin.vercel.app/", "contributions": [ "doc" ] @@ -6490,7 +6459,6 @@ "login": "chuyeow", "name": "Cheah Chu Yeow", "avatar_url": "https://avatars.githubusercontent.com/u/213?v=4", - "profile": "http://blog.codefront.net/", "contributions": [ "content" ] @@ -6667,7 +6635,6 @@ "login": "bestpilotingalaxy", "name": "bestpilotingalaxy", "avatar_url": "https://avatars.githubusercontent.com/u/59182467?v=4", - "profile": "https://github.com/bestpilotingalaxy", "contributions": [ "doc" ] @@ -6686,7 +6653,6 @@ "login": "jamongeon1", "name": "jamongeon1", "avatar_url": "https://avatars.githubusercontent.com/u/94926423?v=4", - "profile": "https://github.com/jamongeon1", "contributions": [ "doc" ] @@ -6740,7 +6706,6 @@ "login": "Medzhidov-Omardibir", "name": "Medzhidov-Omardibir", "avatar_url": "https://avatars.githubusercontent.com/u/95706785?v=4", - "profile": "https://github.com/Medzhidov-Omardibir", "contributions": [ "doc" ] @@ -6749,7 +6714,6 @@ "login": "ApostolisGaros", "name": "ApoGrs", "avatar_url": "https://avatars.githubusercontent.com/u/45716978?v=4", - "profile": "https://github.com/ApostolisGaros", "contributions": [ "ideas" ] @@ -6911,7 +6875,6 @@ "login": "polarpunklabs", "name": "polarpunklabs", "avatar_url": "https://avatars.githubusercontent.com/u/84196983?v=4", - "profile": "https://github.com/polarpunklabs", "contributions": [ "doc" ] @@ -7283,7 +7246,6 @@ "login": "LieAlbertTriAdrian", "name": "Albert Lie Adrian", "avatar_url": "https://avatars.githubusercontent.com/u/12984659?v=4", - "profile": "https://github.com/LieAlbertTriAdrian", "contributions": [ "doc" ] @@ -7390,7 +7352,6 @@ "login": "JasonYan2015", "name": "Jason Yan", "avatar_url": "https://avatars.githubusercontent.com/u/17684609?v=4", - "profile": "https://github.com/JasonYan2015", "contributions": [ "doc", "translation" @@ -7505,7 +7466,6 @@ "login": "chadlohrli", "name": "chadlohrli", "avatar_url": "https://avatars.githubusercontent.com/u/9952172?v=4", - "profile": "https://github.com/chadlohrli", "contributions": [ "content" ] @@ -7551,7 +7511,6 @@ "login": "Choi-Jinhong", "name": "GNONG", "avatar_url": "https://avatars.githubusercontent.com/u/65050483?v=4", - "profile": "https://jinhongdev.tistory.com/", "contributions": [ "doc" ] @@ -7614,7 +7573,6 @@ "login": "LichuAcu", "name": "Lichu Acuña", "avatar_url": "https://avatars.githubusercontent.com/u/54295410?v=4", - "profile": "https://www.linkedin.com/in/lisandroea/?locale=en_US", "contributions": [ "doc" ] @@ -7635,7 +7593,8 @@ "avatar_url": "https://avatars.githubusercontent.com/u/65976143?v=4", "profile": "https://github.com/skaunov", "contributions": [ - "doc" + "doc", + "bug" ] }, { @@ -7849,7 +7808,6 @@ "login": "Seek4samurai", "name": "Gourav Singh Rawat", "avatar_url": "https://avatars.githubusercontent.com/u/69115613?v=4", - "profile": "https://seek4samurai.vercel.app/", "contributions": [ "doc", "ideas" @@ -7896,7 +7854,6 @@ "login": "TimGrey998", "name": "XOF", "avatar_url": "https://avatars.githubusercontent.com/u/57596934?v=4", - "profile": "https://github.com/TimGrey998", "contributions": [ "doc", "translation", @@ -7961,7 +7918,6 @@ "login": "tadeodao", "name": "tadeo", "avatar_url": "https://avatars.githubusercontent.com/u/94108039?v=4", - "profile": "https://github.com/tadeodao", "contributions": [ "doc" ] @@ -8120,7 +8076,6 @@ "login": "shelleyolivia", "name": "shelleyolivia", "avatar_url": "https://avatars.githubusercontent.com/u/108895606?v=4", - "profile": "https://github.com/shelleyolivia", "contributions": [ "doc", "ideas" @@ -8411,7 +8366,6 @@ "login": "linhuatan", "name": "linhuatan", "avatar_url": "https://avatars.githubusercontent.com/u/94831627?v=4", - "profile": "https://github.com/linhuatan", "contributions": [ "doc" ] @@ -8621,7 +8575,6 @@ "login": "ldlsalazar", "name": "Lorena De Leon Salazar", "avatar_url": "https://avatars.githubusercontent.com/u/112458077?v=4", - "profile": "https://github.com/ldlsalazar", "contributions": [ "translation" ] @@ -8827,7 +8780,6 @@ "login": "MHMasoon", "name": "MohammadHosein Masoon", "avatar_url": "https://avatars.githubusercontent.com/u/63204823?v=4", - "profile": "https://github.com/MHMasoon", "contributions": [ "doc" ] @@ -8890,7 +8842,6 @@ "login": "marcellamalune", "name": "Marcella", "avatar_url": "https://avatars.githubusercontent.com/u/63505124?v=4", - "profile": "https://github.com/marcellamalune", "contributions": [ "code" ] @@ -8917,7 +8868,6 @@ "login": "YasshhYadav", "name": "Yash Yadav", "avatar_url": "https://avatars.githubusercontent.com/u/91071840?v=4", - "profile": "https://github.com/YasshhYadav", "contributions": [ "doc" ] @@ -8935,7 +8885,6 @@ "login": "Master7130", "name": "Master7130", "avatar_url": "https://avatars.githubusercontent.com/u/85327930?v=4", - "profile": "https://github.com/Master7130", "contributions": [ "code" ] @@ -8971,7 +8920,6 @@ "login": "d1onys1us", "name": "d1onys1us", "avatar_url": "https://avatars.githubusercontent.com/u/13951458?v=4", - "profile": "https://github.com/d1onys1us", "contributions": [ "doc" ] @@ -8980,7 +8928,6 @@ "login": "thib-web3", "name": "Thibaut", "avatar_url": "https://avatars.githubusercontent.com/u/66329321?v=4", - "profile": "https://github.com/thib-web3", "contributions": [ "doc" ] @@ -9045,7 +8992,6 @@ "login": "bt3gl", "name": "♡", "avatar_url": "https://avatars.githubusercontent.com/u/1130416?v=4", - "profile": "https://github.com/bt3gl", "contributions": [ "doc" ] @@ -9189,7 +9135,6 @@ "login": "KurtMerbeth", "name": "KurtMerbeth", "avatar_url": "https://avatars.githubusercontent.com/u/22886639?v=4", - "profile": "https://github.com/KurtMerbeth", "contributions": [ "content" ] @@ -9742,7 +9687,6 @@ "login": "aguzmant103", "name": "aguzmant103", "avatar_url": "https://avatars.githubusercontent.com/u/67167307?v=4", - "profile": "https://github.com/aguzmant103", "contributions": [ "doc" ] @@ -9917,7 +9861,6 @@ "login": "machin3boy", "name": "machin3boy", "avatar_url": "https://avatars.githubusercontent.com/u/78896694?v=4", - "profile": "https://github.com/machin3boy", "contributions": [ "content" ] @@ -10246,7 +10189,6 @@ "login": "Tyler-233", "name": "Tyler-233", "avatar_url": "https://avatars.githubusercontent.com/u/44740396?v=4", - "profile": "https://github.com/Tyler-233", "contributions": [ "translation", "content" @@ -10383,7 +10325,6 @@ "login": "MwitahJob", "name": "Mwitah ", "avatar_url": "https://avatars.githubusercontent.com/u/136892656?v=4", - "profile": "https://github.com/MwitahJob", "contributions": [ "content" ] @@ -10438,7 +10379,6 @@ "login": "LadyDhaga", "name": "chinaman123", "avatar_url": "https://avatars.githubusercontent.com/u/106376368?v=4", - "profile": "https://github.com/LadyDhaga", "contributions": [ "ideas" ] @@ -10676,7 +10616,6 @@ "login": "Wilson-Wu1", "name": "Wilson Wu", "avatar_url": "https://avatars.githubusercontent.com/u/41039035?v=4", - "profile": "https://www.linkedin.com/in/wilson-wu-2021/", "contributions": [ "doc" ] @@ -10884,7 +10823,6 @@ "login": "fuzheng1998", "name": "Zheng Fu", "avatar_url": "https://avatars.githubusercontent.com/u/24203166?v=4", - "profile": "https://github.com/fuzheng1998", "contributions": [ "code" ] @@ -10992,7 +10930,6 @@ "login": "sminempepe", "name": "sminempepe", "avatar_url": "https://avatars.githubusercontent.com/u/76882704?v=4", - "profile": "https://github.com/sminempepe", "contributions": [ "doc" ] @@ -11821,7 +11758,6 @@ "login": "writegr", "name": "writegr", "avatar_url": "https://avatars.githubusercontent.com/u/167099595?v=4", - "profile": "https://github.com/writegr", "contributions": [ "bug" ] @@ -11958,7 +11894,6 @@ "login": "AbiPrescott", "name": "Abi Prescott", "avatar_url": "https://avatars.githubusercontent.com/u/140613896?v=4", - "profile": "https://github.com/AbiPrescott", "contributions": [ "bug" ] @@ -12084,7 +12019,6 @@ "login": "VikVM", "name": "VikVM", "avatar_url": "https://avatars.githubusercontent.com/u/60881781?v=4", - "profile": "https://github.com/VikVM", "contributions": [ "content" ] @@ -12734,7 +12668,6 @@ "login": "iusx", "name": "iusx", "avatar_url": "https://avatars.githubusercontent.com/u/57232813?v=4", - "profile": "https://jiangxue.org/~ritsu", "contributions": [ "code" ] @@ -12863,7 +12796,6 @@ "login": "CXYZTW", "name": "@karelxfi", "avatar_url": "https://avatars.githubusercontent.com/u/54091831?v=4", - "profile": "https://github.com/CXYZTW", "contributions": [ "tool" ] @@ -13075,7 +13007,6 @@ "login": "alcueca", "name": "Alberto Cuesta Cañada", "avatar_url": "https://avatars.githubusercontent.com/u/38806121?v=4", - "profile": "https://www.linkedin.com/in/albertocuesta/", "contributions": [ "maintenance" ] @@ -13513,7 +13444,6 @@ "login": "Parizval", "name": "Anmol Goyal", "avatar_url": "https://avatars.githubusercontent.com/u/48042530?v=4", - "profile": "https://github.com/Parizval", "contributions": [ "tool", "code", @@ -13942,7 +13872,8 @@ "avatar_url": "https://avatars.githubusercontent.com/u/139675749?v=4", "profile": "https://github.com/codebyankita", "contributions": [ - "content" + "content", + "research" ] }, { diff --git a/.eslintrc.json b/.eslintrc.json index 190ff1656e4..0c959230cb3 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,4 +1,5 @@ { + "root": true, "extends": ["eslint:recommended", "next/core-web-vitals", "prettier"], "env": { "es6": true, diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f6c945e5f27..a11dfed8c53 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -8,5 +8,5 @@ * @wackerow @pettinarip @minimalsm # Owners of specific files -/src/data/consensus-bounty-hunters.json @asanso @fredriksvantes +/src/data/*-bounty-hunters.json @fredriksvantes @0xMushow @bshastry @0xTylerHolmes /src/data/wallets/new-to-crypto.ts @konopkja @minimalsm diff --git a/README.md b/README.md index 901487b1306..c83fb6bb20f 100644 --- a/README.md +++ b/README.md @@ -236,7 +236,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d vrde
vrde

🖋 Richard McSorley
Richard McSorley

💻 - Alejandro Santander
Alejandro Santander

🖋 + Alejandro Santander
Alejandro Santander
🖋 Jason Carver
Jason Carver

🖋 Chaitanya Potti
Chaitanya Potti

🖋 chriseth
chriseth

🖋 👀 @@ -282,7 +282,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Sunghee Lee
Sunghee Lee

🖋 awallendahl
awallendahl

🖋 Boris Mann
Boris Mann

🖋 - carumusan
carumusan

🖋 + carumusan
carumusan
🖋 econoar
econoar

🖋 Gustavo Esquinca
Gustavo Esquinca

🖋 Javier Tarazaga
Javier Tarazaga

🖋 @@ -371,7 +371,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Pandiyaraja Ramamoorthy
Pandiyaraja Ramamoorthy

🖋 🌍 Archan Roychoudhury
Archan Roychoudhury

🖋 🌍 - SAI PRASHANTH VUPPALA
SAI PRASHANTH VUPPALA

🖋 🌍 + SAI PRASHANTH VUPPALA
SAI PRASHANTH VUPPALA
🖋 🌍 Sayid Almahdy
Sayid Almahdy

🌍 jeedani
jeedani

🌍 Akira
Akira

🌍 @@ -382,9 +382,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d mul53
mul53

💻 Apoorv Lathey
Apoorv Lathey

💻 Ken Sato
Ken Sato

🖋 - Sesamestrong
Sesamestrong

💻 + Sesamestrong
Sesamestrong
💻 ChrisK
ChrisK

🖋 - Stefan van As
Stefan van As

🖋 + Stefan van As
Stefan van As
🖋 Grégoire Jeanmart
Grégoire Jeanmart

🖋 @@ -411,7 +411,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Alex Singh
Alex Singh

🎨 Carl Fairclough
Carl Fairclough

🎨 💻 🐛 Kaven C
Kaven C

🖋 - Markus Hatvan
Markus Hatvan

💻 + Markus Hatvan
Markus Hatvan
💻 Evans Tucker
Evans Tucker

🖋 @@ -482,7 +482,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Aranha
Aranha

💻 Jung Sup (James) Yoo
Jung Sup (James) Yoo

🌍 Veit Progl
Veit Progl

🤔 - jcamilli
jcamilli

🖋 + jcamilli
jcamilli
🖋 Martin Holst Swende
Martin Holst Swende

🐛 @@ -504,7 +504,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d David Liu
David Liu

🖋 - shreyashariharan3
shreyashariharan3

🖋 + shreyashariharan3
shreyashariharan3
🖋 Adrián Calvo
Adrián Calvo

🖋 daviroo
daviroo

🖋 Wim Notredame
Wim Notredame

💻 @@ -519,13 +519,13 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d James Zaki
James Zaki

🖋 Greg Lang
Greg Lang

🖋 Matt Voska
Matt Voska

🐛 - mustafa
mustafa

🖋 + mustafa
mustafa
🖋 Paul Wackerow
Paul Wackerow

💻 🐛 📖 🎨 Attaphong Rattanaveerachanon
Attaphong Rattanaveerachanon

🐛 🖋 LoinLiao
LoinLiao

🖋 - DrMad92
DrMad92

🐛 + DrMad92
DrMad92
🐛 Patricio Palladino
Patricio Palladino

👀 🤔 David Murdoch
David Murdoch

👀 MashhoodIjaz
MashhoodIjaz

🐛 🖋 @@ -551,7 +551,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d alexsantee
alexsantee

🐛 🖋 peth-yursick
peth-yursick

🖋 - Alwin Stockinger
Alwin Stockinger

🐛 🖋 + Alwin Stockinger
Alwin Stockinger
🐛 🖋 Roberto Henríquez Perozo
Roberto Henríquez Perozo

🖋 strykerin
strykerin

🖋 jddxf
jddxf

🐛 🖋 @@ -569,7 +569,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Ryan Ghods
Ryan Ghods

🖋 Oliver
Oliver

🖋 - Kristiyan
Kristiyan

🐛 💻 + Kristiyan
Kristiyan
🐛 💻 Matthieu Riou
Matthieu Riou

🖋 pansay
pansay

🖋 🐛 eirtscience
eirtscience

🖋 @@ -631,7 +631,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Vedvardhan
Vedvardhan

🖋 🐛 - Yussuf Elarif
Yussuf Elarif

🐛 + Yussuf Elarif
Yussuf Elarif
🐛 David Awad
David Awad

🖋 Alex Beregszaszi
Alex Beregszaszi

🖋 Adam Goth
Adam Goth

🐛 🖋 @@ -648,7 +648,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d NilsKaden
NilsKaden

💻 - Stuart Reynolds
Stuart Reynolds

🤔 + Stuart Reynolds
Stuart Reynolds
🤔 Gwenael Le Bodic
Gwenael Le Bodic

🖋 Anurag Verma
Anurag Verma

🐛 💻 Nikolai Golub
Nikolai Golub

🖋 @@ -750,7 +750,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Vitaliy Hayda
Vitaliy Hayda

🐛 🖋 Ayushman Singh Chauhan
Ayushman Singh Chauhan

🐛 🖋 Keqi Huang
Keqi Huang

🐛 🖋 - davidplutus
davidplutus

🤔 + davidplutus
davidplutus
🤔 Karthickmerk
Karthickmerk

🤔 Sihong
Sihong

💻 AmirAliM
AmirAliM

🖋 @@ -761,7 +761,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Aditya Dhir
Aditya Dhir

🐛 Ammar Husain
Ammar Husain

🖋 🐛 miiiguel
miiiguel

🖋 - Uttam Singh
Uttam Singh

🐛 + Uttam Singh
Uttam Singh
🐛 Chase Wright
Chase Wright

🖋 @@ -831,7 +831,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Matt
Matt

🖋 ytrezq
ytrezq

📖 Ricky
Ricky

🐛 - smudgil
smudgil

🖋 + smudgil
smudgil
🖋 Don Cross
Don Cross

📖 Jackson Taylor
Jackson Taylor

🤔 MrBrain295
MrBrain295

🐛 📖 🤔 🖋 @@ -839,7 +839,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d SafePalWallet
SafePalWallet

🖋 Vishal Vaddadhi
Vishal Vaddadhi

🖋 - Matt Kula
Matt Kula

🐛 + Matt Kula
Matt Kula
🐛 Hamza Shahzad
Hamza Shahzad

💻 🐛 Mukul Kolpe
Mukul Kolpe

💻 🐛 📖 Corwin Smith
Corwin Smith

💻 @@ -901,8 +901,8 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Andrew Gallagher
Andrew Gallagher

🖋 💻 - Phat Nguyen Luu
Phat Nguyen Luu

📖 - Andreas Sofos
Andreas Sofos

💻 + Phat Nguyen Luu
Phat Nguyen Luu
📖 + Andreas Sofos
Andreas Sofos
💻 Felipe Selmo
Felipe Selmo

📖 Bingwei Qin
Bingwei Qin

📖 Mikko Ohtamaa
Mikko Ohtamaa

🤔 📖 @@ -933,11 +933,11 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Thomas Lisankie
Thomas Lisankie

📖 🐛 Tyler Ilunga
Tyler Ilunga

📖 Kasia Kosturek
Kasia Kosturek

📖 - solarpunklabs
solarpunklabs

🤔 + solarpunklabs
solarpunklabs
🤔 aakhtar3
aakhtar3

📖 - Shreyas Londhe
Shreyas Londhe

🖋 + Shreyas Londhe
Shreyas Londhe
🖋 Tim Beccue
Tim Beccue

🖋 Robert Joseph Wayne
Robert Joseph Wayne

📖 🖋 pdesmondflynn
pdesmondflynn

🖋 @@ -964,7 +964,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d SA KSH AM
SA KSH AM

🖋 - Samrat
Samrat

🖋 + Samrat
Samrat
🖋 Justin Shaw
Justin Shaw

🖋 💻 📖 🤔 meoww-bot
meoww-bot

📖 Philip Vu
Philip Vu

📖 @@ -992,7 +992,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Hendrik Eeckhaut
Hendrik Eeckhaut

📖 💻 Susannah Evans
Susannah Evans

📖 - Minimalist Optimalist
Minimalist Optimalist

🐛 + Minimalist Optimalist
Minimalist Optimalist
🐛 vluna
vluna

💻 🐛 🖋 Arghya Biswas
Arghya Biswas

💻 abhi-go
abhi-go

📖 @@ -1030,15 +1030,15 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d selfwithin
selfwithin

🤔 📖 Jonathan Joshua
Jonathan Joshua

📖 Patrick Aljord
Patrick Aljord

📖 - decifer
decifer

🤔 + decifer
decifer
🤔 aghArdeshir
aghArdeshir

💻 Michael Connell
Michael Connell

🖋 💻 🐛 Ahmed Mustafa Malik
Ahmed Mustafa Malik

💻 Gamaliel 'Yel' Padillo
Gamaliel 'Yel' Padillo

📖 - Kumar Kalyan
Kumar Kalyan

🐛 📖 💻 ️️️️♿️ - 0xdie
0xdie

📖 + Kumar Kalyan
Kumar Kalyan
🐛 📖 💻 ️️️️♿️ + 0xdie
0xdie
📖 Taimoor Ali
Taimoor Ali

📖 🐛 Andrej
Andrej

📖 🖋 Pascal Marco Caversaccio
Pascal Marco Caversaccio

📖 🖋 @@ -1058,14 +1058,14 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d juliangeissler
juliangeissler

📖 🐛 💻 Garric G. Nahapetian
Garric G. Nahapetian

🖋 Dmitriy Fishman
Dmitriy Fishman

📖 - neozapatista
neozapatista

📖 + neozapatista
neozapatista
📖 Factral
Factral

🌍 📖 🐛 💻 elshigori
elshigori

📖 EarthMan
EarthMan

🌍 📖 mohan-chinnappan-n
mohan-chinnappan-n

🤔 - Nicola Bonsi
Nicola Bonsi

🤔 + Nicola Bonsi
Nicola Bonsi
🤔 Yusuf Elnady
Yusuf Elnady

🖋 Aryan Keluskar
Aryan Keluskar

💻 Ling
Ling

🖋 📋 @@ -1075,9 +1075,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Tanmay Nagepatil
Tanmay Nagepatil

🤔 Brandon Harden
Brandon Harden

🖋 Snigdha Singh
Snigdha Singh

📖 - SW
SW

📖 + SW
SW
📖 Aaron Chen
Aaron Chen

🤔 - Qazal Samani
Qazal Samani

📖 + Qazal Samani
Qazal Samani
📖 yash
yash

🤔 @@ -1117,7 +1117,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Gerard Sans
Gerard Sans

🖋 - Cheah Chu Yeow
Cheah Chu Yeow

🖋 + Cheah Chu Yeow
Cheah Chu Yeow
🖋 Yan Luiz
Yan Luiz

🖋 Alexandre Chabrolin
Alexandre Chabrolin

🖋 Sergey Danilovich
Sergey Danilovich

🖋 📖 @@ -1140,11 +1140,11 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Rahul
Rahul

🤔 📖 🖋 Francisco J. Moreno
Francisco J. Moreno

🌍 📖 Zach
Zach

🖋 - bestpilotingalaxy
bestpilotingalaxy

📖 + bestpilotingalaxy
bestpilotingalaxy
📖 Afr Schoe
Afr Schoe

💻 📖 - jamongeon1
jamongeon1

📖 + jamongeon1
jamongeon1
📖 Jay
Jay

💻 Arnaud Spanneut
Arnaud Spanneut

🌍 yuliyu123
yuliyu123

🌍 @@ -1152,8 +1152,8 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Jason Manoloudis
Jason Manoloudis

📖 - Medzhidov-Omardibir
Medzhidov-Omardibir

📖 - ApoGrs
ApoGrs

🤔 + Medzhidov-Omardibir
Medzhidov-Omardibir
📖 + ApoGrs
ApoGrs
🤔 Mohammed Sadiq
Mohammed Sadiq

📖 Sahil sen
Sahil sen

📖 Collin K Cusce
Collin K Cusce

📖 🤔 @@ -1174,7 +1174,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Max Roslow
Max Roslow

📖 🌍 tnkrxyz
tnkrxyz

📖 Nuno Loureiro
Nuno Loureiro

💻 🎨 - polarpunklabs
polarpunklabs

📖 + polarpunklabs
polarpunklabs
📖 Neographer
Neographer

📖 Voll
Voll

📖 @@ -1226,7 +1226,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d B01AND
B01AND

📖 Ashwin Ramaswami
Ashwin Ramaswami

📖 - Albert Lie Adrian
Albert Lie Adrian

📖 + Albert Lie Adrian
Albert Lie Adrian
📖 Ishaan Parmar
Ishaan Parmar

💻 🎨 🤔 Tarun Batra
Tarun Batra

📖 🐛 Max
Max

📖 🐛 @@ -1239,7 +1239,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Tim Mustafin
Tim Mustafin

🤔 superphiz
superphiz

📖 🤔 seanlakers
seanlakers

🤔 - Jason Yan
Jason Yan

📖 🌍 + Jason Yan
Jason Yan
📖 🌍 mradkov
mradkov

📖 @@ -1255,14 +1255,14 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d booklearner
booklearner

📖 moretimeL
moretimeL

🖋 SuperDelphi
SuperDelphi

🖋 🌍 🐛 📖 - chadlohrli
chadlohrli

🖋 + chadlohrli
chadlohrli
🖋 Julius Degesys
Julius Degesys

📖 Nicolás Quiroz
Nicolás Quiroz

💻 🐛 wolz-CODElife
wolz-CODElife

📖 Mina Essam
Mina Essam

🤔 - GNONG
GNONG

📖 + GNONG
GNONG
📖 Sina Pilehchiha
Sina Pilehchiha

📖 thefrenchbrazilianguy
thefrenchbrazilianguy

📖 Anish Gupta
Anish Gupta

📖 @@ -1271,9 +1271,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Justyna Broniszewska
Justyna Broniszewska

📖 Elyanil Liranzo-Castro
Elyanil Liranzo-Castro

📖 - Lichu Acuña
Lichu Acuña

📖 + Lichu Acuña
Lichu Acuña
📖 Takamasa Arakawa
Takamasa Arakawa

💻 🐛 - skaunov
skaunov

📖 + skaunov
skaunov

📖 🐛 Paul Cowgill
Paul Cowgill

📖 zjiekai
zjiekai

📖 @@ -1302,14 +1302,14 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Jordi Pascual
Jordi Pascual

🌍 🐛 📖 Amith KK
Amith KK

📖 🐛 Arpit Ingle
Arpit Ingle

🤔 - Gourav Singh Rawat
Gourav Singh Rawat

📖 🤔 + Gourav Singh Rawat
Gourav Singh Rawat
📖 🤔 mempirate
mempirate

📖 🐛 Barukimang
Barukimang

📖 Kaan Uzdoğan
Kaan Uzdoğan

📖 Colin Kennedy
Colin Kennedy

📖 - XOF
XOF

📖 🌍 🐛 + XOF
XOF
📖 🌍 🐛 Manu kashyap
Manu kashyap

📖 Zhou Yang
Zhou Yang

📖 @@ -1318,7 +1318,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Stephen Fluin
Stephen Fluin

📖 hakuta
hakuta

📖 MiloBowman
MiloBowman

📖 - tadeo
tadeo

📖 + tadeo
tadeo
📖 Jorge Santana
Jorge Santana

🖋 rolodexter
rolodexter

📖 @@ -1341,7 +1341,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d moyed
moyed

📖 - shelleyolivia
shelleyolivia

📖 🤔 + shelleyolivia
shelleyolivia
📖 🤔 Sandy
Sandy

📖 NachoRoizman
NachoRoizman

📖 Iván Miragaya
Iván Miragaya

💻 @@ -1380,7 +1380,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d rogueassasin1729
rogueassasin1729

📖 Pandapip1
Pandapip1

📖 🤔 Aldi Zhupani
Aldi Zhupani

🐛 💻 - linhuatan
linhuatan

📖 + linhuatan
linhuatan
📖 Hugh
Hugh

📖 Kim Kwangtae
Kim Kwangtae

🖋 🤔 tobi4021
tobi4021

📖 @@ -1408,7 +1408,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d cam
cam

🐛 📖 calumtomeny
calumtomeny

📖 robertu
robertu

📖 🌍 - Lorena De Leon Salazar
Lorena De Leon Salazar

🌍 + Lorena De Leon Salazar
Lorena De Leon Salazar
🌍 James Adams
James Adams

📖 Eric Chen
Eric Chen

📖 @@ -1436,7 +1436,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Paul Lechocki
Paul Lechocki

📖 justalike
justalike

📖 grayliquid
grayliquid

📖 - MohammadHosein Masoon
MohammadHosein Masoon

📖 + MohammadHosein Masoon
MohammadHosein Masoon
📖 Patoshi
Patoshi

📖 @@ -1445,21 +1445,21 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d DamitusThyYeetus123
DamitusThyYeetus123

📖 matusame
matusame

🌍 Lohan
Lohan

💻 - Marcella
Marcella

💻 + Marcella
Marcella
💻 Leon Todd
Leon Todd

📖 Ladislas Fontaine
Ladislas Fontaine

📖 - Yash Yadav
Yash Yadav

📖 + Yash Yadav
Yash Yadav
📖 barro
barro

📖 - Master7130
Master7130

💻 + Master7130
Master7130
💻 Lude15
Lude15

🤔 Luke Fan
Luke Fan

📖 TABASCO
TABASCO

📖 - d1onys1us
d1onys1us

📖 - Thibaut
Thibaut

📖 + d1onys1us
d1onys1us
📖 + Thibaut
Thibaut
📖 Miguel
Miguel

💻 Ray Zhu
Ray Zhu

📖 Lucca Benedetti
Lucca Benedetti

📖 @@ -1468,7 +1468,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Aniruddha Sil
Aniruddha Sil

📖 💻 - ♡

📖 + ♡

📖 Luis Sebastian Urrutia Fuentes
Luis Sebastian Urrutia Fuentes

💻 jakubalsoori
jakubalsoori

📖 Wenceslas Sanchez
Wenceslas Sanchez

📖 @@ -1488,7 +1488,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Mille Codex
Mille Codex

📖 Gift Opia
Gift Opia

💻 Dhiraj Gagrai
Dhiraj Gagrai

💻 - KurtMerbeth
KurtMerbeth

🖋 + KurtMerbeth
KurtMerbeth
🖋 Sai Leela Rahul Pujari
Sai Leela Rahul Pujari

🖋 SkyWarrior123
SkyWarrior123

🖋 Yashovardhan Agrawal
Yashovardhan Agrawal

🔣 @@ -1567,7 +1567,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Daniel Olshansky
Daniel Olshansky

📖 🤔 - aguzmant103
aguzmant103

📖 + aguzmant103
aguzmant103
📖 Soheil
Soheil

💻 metadiver.eth
metadiver.eth

💻 Jacob
Jacob

🤔 📖 @@ -1590,7 +1590,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d damilola debel
damilola debel

🖋 Sarat Angajala
Sarat Angajala

📖 questions
questions

📆 💬 - machin3boy
machin3boy

🖋 + machin3boy
machin3boy
🖋 nethan
nethan

🖋 @@ -1638,7 +1638,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Maxime Dessez
Maxime Dessez

🐛 🌍 - Tyler-233
Tyler-233

🌍 🖋 + Tyler-233
Tyler-233
🌍 🖋 neodaoist
neodaoist

🖋 Atharva Deosthale
Atharva Deosthale

🖋 Kartik Chopra
Kartik Chopra

🖋 @@ -1657,7 +1657,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Suraj Anand
Suraj Anand

🖋 - Mwitah
Mwitah

🖋 + Mwitah
Mwitah
🖋 Tuckson
Tuckson

🖋 Akamig
Akamig

🖋 Peace Ojemeh
Peace Ojemeh

🖋 @@ -1665,7 +1665,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Gunal
Gunal

🖋 - chinaman123
chinaman123

🤔 + chinaman123
chinaman123
🤔 Alex
Alex

📖 🐛 Matthew
Matthew

🐛 📖 gokhan
gokhan

🐛 @@ -1697,7 +1697,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Robert
Robert

🖋 obsidian
obsidian

🖋 Fekry Aiad
Fekry Aiad

🤔 - Wilson Wu
Wilson Wu

📖 + Wilson Wu
Wilson Wu
📖 VAS
VAS

📖 @@ -1728,7 +1728,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d jeremyfritzen
jeremyfritzen

🖋 - Zheng Fu
Zheng Fu

💻 + Zheng Fu
Zheng Fu
💻 xiaolou86
xiaolou86

🖋 aztecEagle22
aztecEagle22

🖋 QIAN
QIAN

🖋 @@ -1742,7 +1742,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Tarun Mohandas Daryanani
Tarun Mohandas Daryanani

🖋 Shubh
Shubh

🖋 duckdegen
duckdegen

🖋 - sminempepe
sminempepe

📖 + sminempepe
sminempepe
📖 aslikaya
aslikaya

📖 🚧 @@ -1858,7 +1858,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Hayatti
Hayatti

🖋 🐛 🚧 Jeffrey Owoloko
Jeffrey Owoloko

🚧 Colin McKerracher
Colin McKerracher

🚧 - writegr
writegr

🐛 + writegr
writegr
🐛 Cardo
Cardo

🚧 shravanandoria
shravanandoria

🚧 @@ -1877,7 +1877,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Gernot Salzer
Gernot Salzer

🤔 lightclient
lightclient

🚧 Garen Woo
Garen Woo

🐛 - Abi Prescott
Abi Prescott

🐛 + Abi Prescott
Abi Prescott
🐛 skyminelabs
skyminelabs

🚧 @@ -1895,7 +1895,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d somethingstup
somethingstup

📖 woxjro
woxjro

🔧 bambooskySean
bambooskySean

💻 - VikVM
VikVM

🖋 + VikVM
VikVM
🖋 Omkar Kamale
Omkar Kamale

💻 @@ -1986,7 +1986,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Alexandria Roberts
Alexandria Roberts

💻 🖋 ⚠️ colin
colin

🖋 Jenish Thapa
Jenish Thapa

🤔 - iusx
iusx

💻 + iusx
iusx
💻 JJOptimist
JJOptimist

🐛 @@ -2004,7 +2004,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d otc group
otc group

🚧 Savio
Savio

🚧 💻 fuder.eth
fuder.eth

🚧 - @karelxfi
@karelxfi

🔧 + @karelxfi
@karelxfi
🔧 Oleg Gorbatiuk
Oleg Gorbatiuk

🖋 @@ -2035,7 +2035,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d 0xumarkhatab
0xumarkhatab

🚧 - Alberto Cuesta Cañada
Alberto Cuesta Cañada

🚧 + Alberto Cuesta Cañada
Alberto Cuesta Cañada
🚧 Co1nB3e
Co1nB3e

🚧 Revo Arya
Revo Arya

🚧 Teniola Fatunmbi
Teniola Fatunmbi

🚧 @@ -2097,7 +2097,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Bruce-Leung
Bruce-Leung

🐛 - Anmol Goyal
Anmol Goyal

🔧 💻 🚧 + Anmol Goyal
Anmol Goyal
🔧 💻 🚧 Ulaş Erdoğan
Ulaş Erdoğan

👀 Harsh Gupta
Harsh Gupta

🚧 Max Costa
Max Costa

🚧 @@ -2156,7 +2156,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Archit
Archit

🖋 Ivan Manchev
Ivan Manchev

🚧 Cypher Pepe
Cypher Pepe

🚧 - Ankita Virani (ankita.eth)
Ankita Virani (ankita.eth)

🖋 + Ankita Virani (ankita.eth)
Ankita Virani (ankita.eth)

🖋 🔬 Mikhail
Mikhail

🔧 diff --git a/app/[locale]/bug-bounty/page.tsx b/app/[locale]/bug-bounty/page.tsx index 98df167612f..764cad904d4 100644 --- a/app/[locale]/bug-bounty/page.tsx +++ b/app/[locale]/bug-bounty/page.tsx @@ -113,6 +113,7 @@ export default async function Page({ params }: { params: Promise }) { const { locale } = await params const t = await getTranslations({ namespace: "page-bug-bounty" }) + const tCommon = await getTranslations({ namespace: "common" }) const commitHistoryCache: CommitHistory = {} const { contributors, lastEditLocaleTimestamp } = @@ -304,39 +305,83 @@ export default async function Page({ params }: { params: Promise }) { - + {tCommon("item-logo", - + {tCommon("item-logo", - + {tCommon("item-logo", - + {tCommon("item-logo", - + {tCommon("item-logo", - + {tCommon("item-logo", - + {tCommon("item-logo", - + {tCommon("item-logo", - + {tCommon("item-logo", - + {tCommon("item-logo", - + {tCommon("item-logo",
diff --git a/app/[locale]/community/events/page-jsonld.tsx b/app/[locale]/community/events/page-jsonld.tsx index 128ecb97536..03dab23711d 100644 --- a/app/[locale]/community/events/page-jsonld.tsx +++ b/app/[locale]/community/events/page-jsonld.tsx @@ -8,9 +8,93 @@ import { getLocaleYear } from "@/lib/utils/date" import { ethereumCommunityOrganization, ethereumFoundationOrganization, + ethereumFoundationReference, } from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" +import { communityHubSchemas } from "@/data/community-hub-schemas" +import communityHubs from "@/data/community-hubs" + +function buildHubSchemaNodes( + hub: (typeof communityHubs)[number], + description: string +) { + const schema = communityHubSchemas[hub.id] + if (!schema) return [] + + const placeId = `#hub-location-${hub.id}` + const seriesId = `#coworking-series-${hub.id}` + + const serviceNode = { + "@type": "Service" as const, + name: "Ethereum Community Coworking and Events", + description, + provider: ethereumFoundationReference, + areaServed: { + "@type": "City" as const, + name: hub.location, + }, + } + + const placeNode: Record = { + "@type": "Place" as const, + "@id": placeId, + name: schema.hubName ?? `Ethereum Community Hub (${hub.location})`, + } + + if (schema.address) { + placeNode.address = { + "@type": "PostalAddress" as const, + streetAddress: schema.address.streetAddress, + addressLocality: schema.address.addressLocality, + ...(schema.address.postalCode && { + postalCode: schema.address.postalCode, + }), + addressCountry: schema.address.addressCountry, + } + } + + if (schema.containedInPlace) { + placeNode.containedInPlace = { + "@type": "LocalBusiness" as const, + name: schema.containedInPlace.name, + ...(schema.containedInPlace.url && { + url: schema.containedInPlace.url, + }), + } + } + + const eventNode = { + "@type": ["EventSeries", "Event"] as const, + "@id": seriesId, + name: schema.eventSeriesName ?? "Open Ethereum Coworking Hours", + description: schema.eventDescription, + isAccessibleForFree: true, + url: hub.coworkingSignupUrl, + eventStatus: "https://schema.org/EventScheduled", + eventAttendanceMode: "https://schema.org/OfflineEventAttendanceMode", + organizer: ethereumFoundationReference, + location: { "@id": placeId }, + eventSchedule: { + "@type": "Schedule" as const, + ...(schema.schedule.startDate && { + startDate: schema.schedule.startDate, + }), + ...(schema.schedule.startTime && { + startTime: schema.schedule.startTime, + }), + ...(schema.schedule.endTime && { + endTime: schema.schedule.endTime, + }), + repeatFrequency: schema.schedule.repeatFrequency, + byDay: schema.schedule.byDay, + scheduleTimezone: schema.schedule.scheduleTimezone, + }, + } + + return [serviceNode, placeNode, eventNode] +} + export default async function EventsJsonLD({ locale, contributors, @@ -30,6 +114,10 @@ export default async function EventsJsonLD({ url: contributor.html_url, })) + const hubSchemaNodes = communityHubs.flatMap((hub) => + buildHubSchemaNodes(hub, t(hub.descriptionKey)) + ) + const jsonLd = { "@context": "https://schema.org", "@graph": [ @@ -118,6 +206,7 @@ export default async function EventsJsonLD({ publisher: ethereumFoundationOrganization, reviewedBy: ethereumFoundationOrganization, }, + ...hubSchemaNodes, ], } diff --git a/app/[locale]/community/events/page.tsx b/app/[locale]/community/events/page.tsx index 61d19228c0c..ba60016670c 100644 --- a/app/[locale]/community/events/page.tsx +++ b/app/[locale]/community/events/page.tsx @@ -224,7 +224,13 @@ const Page = async ({ params }: { params: PageParams }) => { sizes="6rem" />
-

{location}

+

+ {location} + +   + {t("page-events-meta-ethereum-community-hub")} + +

{t(descriptionKey)}

{t(ctaKey)}

@@ -434,11 +440,7 @@ const Page = async ({ params }: { params: PageParams }) => {
- {t("item-logo", +

{t("page-events-support-ethereum-everywhere")} @@ -502,11 +504,7 @@ const Page = async ({ params }: { params: PageParams }) => {
- {t("item-logo", +

{t("page-events-support-geode-labs")} diff --git a/app/[locale]/community/support/page.tsx b/app/[locale]/community/support/page.tsx new file mode 100644 index 00000000000..40951908dc7 --- /dev/null +++ b/app/[locale]/community/support/page.tsx @@ -0,0 +1,423 @@ +import { BookOpen, HelpCircle, Shield, ShieldAlert } from "lucide-react" +import { getTranslations, setRequestLocale } from "next-intl/server" + +import type { PageParams } from "@/lib/types" + +import Breadcrumbs from "@/components/Breadcrumbs" +import FeedbackCard from "@/components/FeedbackCard" +import { SimpleHero } from "@/components/Hero" +import MainArticle from "@/components/MainArticle" +import { + Alert, + AlertContent, + AlertDescription, + AlertIcon, + AlertTitle, +} from "@/components/ui/alert" +import { ButtonLink } from "@/components/ui/buttons/Button" +import Link from "@/components/ui/Link" +import { Section } from "@/components/ui/section" +import WindowBox from "@/components/WindowBox" + +import { getMetadata } from "@/lib/utils/metadata" + +const EVENT_CATEGORY = "Support" + +export default async function Page({ params }: { params: PageParams }) { + const { locale } = params + + setRequestLocale(locale) + + const t = await getTranslations({ namespace: "page-community-support" }) + + return ( +
+ {/* Hero */} + } + title={t("page-community-support-hero-title")} + subtitle={ +
+

+ {t("page-community-support-hero-subtitle-1")} +

+

+ {t.rich("page-community-support-hero-subtitle-2", { + a: (chunks) => {chunks}, + })} +

+
+ } + /> + + + {/* Decentralization alert */} + + + + + + + {t("page-community-support-alert-title")} + + + {t("page-community-support-alert-description")} + + + + + {/* Section 1: Get help */} +
+

+ {t("page-community-support-get-help")} +

+
+ {/* Card 1: Something went wrong */} + {t("page-community-support-something-went-wrong")}

+ } + svg={} + className="h-fit" + > +
+

+ {t("page-community-support-something-went-wrong-description")} +

+ + {t("page-community-support-lost-funds-scam")} + + + {t("page-community-support-secure-remaining-funds")} + + + {t("page-community-support-report-scam")} + + + {t("page-community-support-trace-funds")} + + + {t("page-community-support-sent-wrong-address")} + + + {t("page-community-support-lost-wallet-access")} + + + {t("page-community-support-stuck-transaction")} + +
+ + + {/* Card 2: Protect yourself */} + {t("page-community-support-protect-yourself")}

} + svg={} + className="h-fit" + > +
+

+ {t("page-community-support-protect-yourself-description")} +

+ + {t("page-community-support-common-scam-tactics")} + + + {t("page-community-support-recovery-experts-scams")} + + + {t("page-community-support-identify-scam-tokens")} + + + {t("page-community-support-full-security-guide")} + + + {t("page-community-support-revoke-approvals")} + +
+ +
+ + + {/* Section 2: Learn */} +
+

+ {t("page-community-support-learn")} +

+
+ {/* Card 3: Using Ethereum */} + {t("page-community-support-using-ethereum")}} + svg={} + className="h-fit" + > +
+

+ {t("page-community-support-using-ethereum-description")} +

+ + {t("page-community-support-create-account")} + + + {t("page-community-support-use-wallet")} + + + {t("page-community-support-swap-tokens")} + + + {t("page-community-support-bridge-tokens")} + + + {t("page-community-support-revoke-token-access")} + +
+
+ + {/* Card 4: Common misconceptions */} + {t("page-community-support-common-misconceptions")} + } + svg={} + className="h-fit" + > +
+

+ {t( + "page-community-support-common-misconceptions-description" + )} +

+ + {t("page-community-support-is-ethereum-company")} + + + {t("page-community-support-recover-freeze-funds")} + + + {t("page-community-support-mine-ethereum")} + + + {t("page-community-support-is-support-team")} + +
+
+
+
+ + {/* Still need help? */} +
+
+

+ {t("page-community-support-still-need-help")} +

+

+ {t("page-community-support-still-need-help-description")} +

+ + {t("page-community-support-discord")} + +
+
+ + + +
+ ) +} + +export async function generateMetadata({ + params, +}: { + params: { locale: string } +}) { + const { locale } = params + + const t = await getTranslations({ + locale, + namespace: "page-community-support", + }) + + return await getMetadata({ + locale, + slug: ["community", "support"], + title: t("page-community-support-hero-title"), + description: t("page-community-support-meta-description"), + }) +} diff --git a/app/[locale]/error.tsx b/app/[locale]/error.tsx index 6f431803fd3..517b69c4fe6 100644 --- a/app/[locale]/error.tsx +++ b/app/[locale]/error.tsx @@ -1,6 +1,7 @@ "use client" import { useEffect, useState } from "react" +import * as Sentry from "@sentry/nextjs" import RefreshCW from "@/components/icons/refresh-cw.svg" import MainArticle from "@/components/MainArticle" @@ -23,8 +24,7 @@ export default function Error({ error }: { error: Error; reset: () => void }) { }, []) useEffect(() => { - // TODO: log the error to an error reporting service - console.error(error) + Sentry.captureException(error) }, [error]) return ( diff --git a/app/[locale]/wallets/find-wallet/page-jsonld.tsx b/app/[locale]/wallets/find-wallet/page-jsonld.tsx index 1bfbdcd7be0..4195c8f3734 100644 --- a/app/[locale]/wallets/find-wallet/page-jsonld.tsx +++ b/app/[locale]/wallets/find-wallet/page-jsonld.tsx @@ -1,6 +1,6 @@ import { getTranslations } from "next-intl/server" -import { FileContributor, Lang } from "@/lib/types" +import { FileContributor, Lang, WalletData } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" @@ -13,12 +13,14 @@ import { normalizeUrlForJsonLd } from "@/lib/utils/url" export default async function FindWalletPageJsonLD({ locale, contributors, + wallets, }: { locale: Lang | undefined contributors: FileContributor[] + wallets: WalletData[] }) { const t = await getTranslations({ - namespace: "page-find-wallet", + namespace: "page-wallets-find-wallet", }) const url = normalizeUrlForJsonLd(locale, `/wallets/find-wallet/`) @@ -29,14 +31,28 @@ export default async function FindWalletPageJsonLD({ url: contributor.html_url, })) + const platforms = (wallet: WalletData): string[] => { + const os: string[] = [] + if (wallet.ios) os.push("iOS") + if (wallet.android) os.push("Android") + if (wallet.linux) os.push("Linux") + if (wallet.windows) os.push("Windows") + if (wallet.macOS) os.push("macOS") + if (wallet.chromium) os.push("Chromium (Extension)") + if (wallet.firefox) os.push("Firefox") + if (wallet.hardware) os.push("Hardware") + return os + } + const jsonLd = { "@context": "https://schema.org", "@graph": [ { - "@type": "WebPage", + "@type": "CollectionPage", "@id": url, name: t("page-find-wallet-meta-title"), description: t("page-find-wallet-meta-description"), + image: "https://ethereum.org/images/wallets/wallet-hero.png", url: url, inLanguage: locale, contributor: contributorList, @@ -72,24 +88,62 @@ export default async function FindWalletPageJsonLD({ }, publisher: ethereumFoundationOrganization, reviewedBy: ethereumFoundationOrganization, - mainEntity: { "@id": `${url}#find-wallet` }, + mainEntity: { "@id": `${url}#wallet-list` }, }, { - "@type": "Article", - "@id": `${url}#find-wallet`, - headline: t("page-find-wallet-title"), + "@type": "ItemList", + "@id": `${url}#wallet-list`, + name: t("page-find-wallet-title"), description: t("page-find-wallet-meta-description"), - image: "https://ethereum.org/images/wallets/wallet-hero.png", - author: [ethereumCommunityOrganization], - publisher: ethereumFoundationOrganization, - contributor: contributorList, - reviewedBy: ethereumFoundationOrganization, - about: { - "@type": "Thing", - name: "Ethereum Wallet Finder", - description: - "Tool to find and compare Ethereum wallets based on features and requirements", - }, + numberOfItems: wallets.length, + itemListElement: wallets.map((wallet, index) => ({ + "@type": "ListItem", + position: index + 1, + item: { + "@type": "SoftwareApplication", + name: wallet.name, + url: wallet.url, + applicationCategory: "Cryptocurrency Wallet", + operatingSystem: platforms(wallet).join(", "), + offers: { + "@type": "Offer", + price: "0", + priceCurrency: "USD", + }, + additionalProperty: [ + { + "@type": "PropertyValue", + name: "Open Source", + value: wallet.open_source ? "Yes" : "No", + }, + { + "@type": "PropertyValue", + name: "Self Custody", + value: wallet.non_custodial ? "Yes" : "No", + }, + { + "@type": "PropertyValue", + name: "Hardware Wallet Support", + value: wallet.hardware_support ? "Yes" : "No", + }, + { + "@type": "PropertyValue", + name: "Layer 2 Support", + value: wallet.layer_2 ? "Yes" : "No", + }, + { + "@type": "PropertyValue", + name: "Staking", + value: wallet.staking ? "Yes" : "No", + }, + { + "@type": "PropertyValue", + name: "NFT Support", + value: wallet.nft_support ? "Yes" : "No", + }, + ], + }, + })), }, ], } diff --git a/app/[locale]/wallets/find-wallet/page.tsx b/app/[locale]/wallets/find-wallet/page.tsx index acfbe4f1cfb..4d911d30bc6 100644 --- a/app/[locale]/wallets/find-wallet/page.tsx +++ b/app/[locale]/wallets/find-wallet/page.tsx @@ -61,7 +61,11 @@ const Page = async ({ params }: { params: PageParams }) => { return ( <> - + diff --git a/docs/solutions/build-errors/mdx-compilation-crowdin-backtick-split.md b/docs/solutions/build-errors/mdx-compilation-crowdin-backtick-split.md new file mode 100644 index 00000000000..7c54bad2d42 --- /dev/null +++ b/docs/solutions/build-errors/mdx-compilation-crowdin-backtick-split.md @@ -0,0 +1,139 @@ +--- +title: MDX Compilation Error from Split Backticks in Translated Angle Bracket Expressions +date: 2026-02-19 +category: build-errors +tags: + - MDX + - translations + - Crowdin + - angle-brackets + - backticks + - i18n + - next-mdx-remote +severity: high +component: next-mdx-remote / Crowdin translations +symptoms: + - "Netlify build fails with: Expected a closing tag for `` before the end of `paragraph`" + - Build failure on translated pages only (not English source) + - Error points to lines where angle brackets appear outside backtick code spans +root_cause: Crowdin translation splits backtick wrapping around code expressions containing angle brackets, leaving bare , , etc. that MDX interprets as unclosed JSX tags +resolution_time: quick +--- + +# MDX Compilation Error from Split Backticks in Translated Angle Bracket Expressions + +## Problem Symptom + +Netlify build fails during static page generation with repeated errors like: + +``` +[next-mdx-remote] error compiling MDX: +Expected a closing tag for `` (436:204-436:207) before the end of `paragraph` +``` + +Affected pages (this instance): +- `/cs/developers/tutorials/ai-trading-agent` +- `/ja/developers/tutorials/ai-trading-agent` +- `/pt-br/developers/tutorials/ai-trading-agent` +- `/ur/developers/tutorials/ai-trading-agent` + +## Root Cause Analysis + +The English source uses backtick-wrapped code expressions containing angle brackets: + +```markdown +which in a C-derived language would be ` ? : `. +``` + +During Crowdin translation, translators inadvertently split the backtick pair. The backtick closes after `?`, leaving `` and `` as bare text: + +```markdown +# Broken (backtick closes too early): +který by v jazyce odvozeném od C byl ` ?` : `. + +# Fixed (single backtick pair wraps all angle brackets): +který by v jazyce odvozeném od C byl ` ? : `. +``` + +MDX (via `next-mdx-remote`) interprets bare `` and `` as opening JSX/HTML tags without corresponding closing tags, causing compilation failure. + +## Solution + +Re-wrap the angle-bracketed expressions inside a single backtick pair in each affected translation file. + +### Files Modified + +| Language | File | Line | +|----------|------|------| +| Czech | `public/content/translations/cs/developers/tutorials/ai-trading-agent/index.md` | 446 | +| Japanese | `public/content/translations/ja/developers/tutorials/ai-trading-agent/index.md` | 445 | +| Portuguese-BR | `public/content/translations/pt-br/developers/tutorials/ai-trading-agent/index.md` | 447 | +| Urdu | `public/content/translations/ur/developers/tutorials/ai-trading-agent/index.md` | 446 | + +### Before/After + +**Czech:** +```diff +- ` ?` : ` ++ ` ? : ` +``` + +**Japanese:** +```diff +- ` ?` : ` ++ ` ? : ` +``` + +**Portuguese-BR:** +```diff +- ` ?` : `.` ++ ` ? : `. +``` +(Also removed stray extra backtick at end) + +**Urdu:** +```diff +- ` ?` ہوگا : ` ++ ` ? : ` ہوگا +``` +(Reordered so angle brackets stay inside backticks) + +## Related Context + +### Prior Occurrences + +- **Commit `76675a5717`** ("fix: escape angle brackets in translated MDX files") — Fixed the same class of issue across 18 languages in an earlier import. This confirms it is a recurring pattern. +- **Commit `3ef2bbb91e`** ("i18n: post-import sanitization") — Ran the existing sanitizer on the same tutorial content. +- **Commit `01fd093439`** ("fix(i18n): post_import_sanitize on ai-trading-agents") — Latest sanitizer run, which did not catch this particular pattern. + +### Existing Sanitizer + +The project has `src/scripts/i18n/post_import_sanitize.ts` with functions like `fixAsciiGuillemets()` that handle `<<`/`>>` conversions. However, it does **not** currently detect split backtick wrapping around single angle bracket expressions like ``, ``, ``. + +## Prevention Strategies + +### 1. Add Sanitizer Rule (Recommended) + +Add a `fixBareAngleBrackets()` function to `post_import_sanitize.ts` that: +- Scans each line for bare `` patterns outside of backtick spans and code fences +- Compares with the English source to find the intended backtick-wrapped version +- Auto-fixes when the match is unambiguous; flags for manual review otherwise + +### 2. Pre-Build Validation + +Add a validation step that checks all translated MDX files for bare angle brackets outside code contexts before the build runs. This would catch issues before they reach Netlify. + +### 3. Crowdin Configuration + +- Lock inline code patterns containing angle brackets as "Do not translate" segments +- Add context notes warning translators about preserving backtick pairs around code expressions + +## Verification + +After applying fixes, confirm with a full build: + +```bash +pnpm build +``` + +Check that the 4 previously-failing pages no longer produce MDX compilation errors. diff --git a/docs/solutions/integration-issues/post-import-sanitizer-bugs-found-korean-review-pr-17166.md b/docs/solutions/integration-issues/post-import-sanitizer-bugs-found-korean-review-pr-17166.md new file mode 100644 index 00000000000..90799c1114c --- /dev/null +++ b/docs/solutions/integration-issues/post-import-sanitizer-bugs-found-korean-review-pr-17166.md @@ -0,0 +1,289 @@ +--- +title: "Korean (ko) Translation Import - Crowdin Artifact Sanitization" +date: 2026-02-28 +category: integration-issues +severity: critical +component: src/scripts/i18n/post_import_sanitize.ts +tags: + - crowdin + - i18n + - translation + - mdx-rendering + - markdown-artifacts + - sanitization + - ko-translation +related_prs: + - "17166" +status: resolved +description: | + Three new Crowdin translation artifact patterns discovered during Korean (ko) + translation import that break MDX rendering and navigation: + 1. Junk after heading anchors + 2. Backtick-wrapped links + 3. Missing link parentheses + Additional manual issues: ERC number garbling, semantic inversions, broken + cross-page links, garbled HTML in JSON translations, machine translation + artifacts. +solution_summary: | + - 3 new sanitizer functions in post_import_sanitize.ts + - 19 new unit tests added (150 total passing) + - Manual fixes applied to 9 files for non-automatable issues +test_file: tests/unit/sanitizer/standalone-fixes.spec.ts +test_coverage: "19 new unit tests (150 total passing)" +--- + +# Korean (ko) Translation Import: Crowdin Artifact Sanitization + +> **PR:** #17166 +> **Language:** Korean (ko) +> **Files reviewed:** 301 (255 markdown, 46 JSON) +> **Quality score:** 8.5/10 (post-fix) + +## Problem + +During review of Korean translation import PR #17166, three new deterministic +Crowdin artifact patterns were discovered that break MDX rendering and +navigation. These join the existing catalog of 16 known patterns documented in +[sanitizer-test-research.md](./sanitizer-test-research.md). + +### Pattern #17: Junk After Heading Anchors + +Crowdin treats the `{#anchor-id}` custom heading ID as translatable text and +appends its "translation" of the slug immediately after the closing brace: + +```markdown +## Before (broken) +## Dencun {#network-impact}네트워크-충격 + +## After (fixed) +## Dencun {#network-impact} +``` + +**Severity:** Critical -- breaks heading rendering and TOC generation. + +### Pattern #18: Backtick-Wrapped Links + +Crowdin wraps entire inline markdown links inside backticks, converting +clickable links into inert inline code: + +```markdown +## Before (broken) +이를 위해 `[배포](/developers/docs/smart-contracts/deploying/)`하기 전에 + +## After (fixed) +이를 위해 [배포](/developers/docs/smart-contracts/deploying/)하기 전에 +``` + +**Severity:** High -- breaks navigation. + +### Pattern #19: Missing Link Parentheses + +Crowdin strips the parentheses that delimit the URL in a markdown link: + +```markdown +## Before (broken) +- [EIP4844.com]https://www.eip4844.com/ + +## After (fixed) +- [EIP4844.com](https://www.eip4844.com/) +``` + +**Severity:** Critical -- breaks navigation. + +## Root Cause + +Crowdin's machine translation pipeline produces these artifacts because: + +1. **Heading anchors**: Crowdin treats `{#slug}` as translatable content and + generates a Korean "translation" of the slug text. +2. **Backtick wrapping**: Crowdin occasionally treats markdown link syntax as + code, wrapping it in backticks during the translation pass. +3. **Parenthesis stripping**: Crowdin's link parsing sometimes drops the `()` + delimiters when the translator edits the link text, leaving bare URLs. + +All three are deterministic and machine-detectable, making automated +remediation viable. + +## Solution + +### Automated Fixes (3 New Functions) + +All three functions live in `src/scripts/i18n/post_import_sanitize.ts` and +share the same structural pattern: split on code blocks first, skip +odd-indexed segments (code), then apply regex to prose segments only. + +#### 1. `fixJunkAfterHeadingAnchors` + +```typescript +function fixJunkAfterHeadingAnchors(content: string): { + content: string + fixCount: number +} +``` + +**Key regex:** `/(\{#-?[a-z0-9][-a-z0-9]*\})[ \t]*([^\s\n}][^\n]*)/g` + +- `[ \t]*` (horizontal whitespace only) is critical -- `\s*` would cross + newlines and eat subsequent paragraph content. +- `-?` before the anchor ID handles `{#-erc-777-vs-erc-20}` where Crowdin + generates a leading dash. +- Secondary filter: only strips text containing non-ASCII characters or + hyphenated Latin slugs, avoiding false positives on legitimate trailing + content. + +#### 2. `fixBacktickWrappedLinks` + +```typescript +function fixBacktickWrappedLinks(content: string): { + content: string + fixCount: number +} +``` + +**Key regex:** `` /`(\[[^\]]+\]\([^)]+\))`/g `` + +- Only matches when entire backtick span content is a complete markdown link. +- Legitimate inline code like `` `require()` `` does not match. +- Code-block split intentionally omits inline backticks from the splitter + pattern, since the targets being fixed are themselves backtick-delimited. + +#### 3. `fixMissingLinkParentheses` + +```typescript +function fixMissingLinkParentheses(content: string): { + content: string + fixCount: number +} +``` + +**Key regex:** `/(\[[^\]]+\])((?:https?:\/\/|\/)[^\s[\]()<>\u3000-\u9FFF\uAC00-\uD7AF]*)/g` + +- URL terminator includes Korean/CJK Unicode ranges to prevent absorbing + adjacent prose characters. +- Trailing punctuation stripping: `[:.,;!?]+$` is split off the URL and + re-appended as prose punctuation. +- Excludes reference-style links `[text][ref]`. + +### Integration + +The functions are wired into `processMarkdownFile` via the `applyFix` helper, +running after `fixBrokenMarkdownLinks` and before frontmatter normalization: + +```typescript +applyFix( + () => fixMissingLinkParentheses(content), + (n) => `Fixed ${n} links with missing parentheses` +) +applyFix( + () => fixBacktickWrappedLinks(content), + (n) => `Unwrapped ${n} backtick-wrapped markdown links` +) +applyFix( + () => fixJunkAfterHeadingAnchors(content), + (n) => `Removed ${n} junk text fragments after heading anchors` +) +``` + +All three are exported via the `_testOnly` object for unit testing. + +### Manual Fixes (9 Files) + +These required manual intervention because the defects were semantically +ambiguous or involved data corruption that regex cannot distinguish from valid +content: + +| File | Issue | Why Not Automatable | +|------|-------|---------------------| +| `ko/roadmap/dencun/index.md` | 6 junk anchors, 16 broken links | Links split across prose with no protocol prefix | +| `ko/roadmap/pectra/7702/index.md` | ERC-437->ERC-4337, Cons/Benefits swap, GitHub identifiers | Number garbling requires English source; semantic inversion | +| `ko/desci/index.md` | financial->scientific | Semantic inversion indistinguishable from valid translation | +| `ko/payments/index.md` | 5 broken links, brand names | Same link reconstruction problem as dencun | +| `ko/eth/supply/index.md` | Escaped bold, broken link | Mixed artifact types | +| `ko/erc-777/index.md` | Leading-dash anchor junk | Fixed manually before function was generalized | +| `page-layer-2-learn.json` | Garbled `` tags | JSON path, not markdown; separate validation | +| `page-layer-2-networks.json` | Nonsense label | Machine translation artifact | +| `page-what-is-ethereum.json` | Garbled tags + artifacts | JSON path limitation | + +## Key Implementation Details + +### `[ \t]*` vs `\s*` + +Using `\s*` in `fixJunkAfterHeadingAnchors` allows the regex to match across +newlines, incorrectly treating the first word of the next paragraph as junk. +The `[ \t]*` constraint ensures matching stays on the same line. This was +caught by integration tests. + +### Trailing Punctuation Stripping + +Crowdin sometimes produces `[text]https://url:` where `:` is Korean +sentence-final punctuation grafted onto the URL. The function splits off +`/[:.,;!?]+$/` before wrapping in parentheses and re-appends it as plain +text: `[text](https://url):` rather than `[text](https://url:)`. + +### Leading-Dash Anchors + +The anchor regex includes `-?` to handle `{#-erc-777-vs-erc-20}`. Crowdin +generates a leading hyphen when the source heading starts with a special +character. Without `-?`, such anchors would not match. + +### Code-Block Splitting Strategy + +All functions use `content.split(codeBlockPattern)` where the pattern is in a +capture group. JavaScript's `String.prototype.split` with a captured group +preserves delimiters in the array. Odd-indexed elements are code blocks +(skipped); even-indexed are prose (processed). + +`fixBacktickWrappedLinks` intentionally omits inline backticks from its +splitter -- including them would cause the targets to be skipped. + +## Test Coverage + +**File:** `tests/unit/sanitizer/standalone-fixes.spec.ts` + +| Function | Tests | Key Cases | +|----------|-------|-----------| +| `fixJunkAfterHeadingAnchors` | 6 | Korean junk, leading-dash anchors, multiple headings, clean pass-through, code blocks | +| `fixBacktickWrappedLinks` | 6 | Internal/external links, multiple per line, legitimate code unchanged, code blocks | +| `fixMissingLinkParentheses` | 7 | External URLs, internal paths, trailing punctuation, reference-style exclusion, code blocks | + +**Total:** 19 new tests, 150 passing across all sanitizer functions. + +## Prevention & Best Practices + +### Automated (Sanitizer Catches) + +- All three patterns run automatically on every Crowdin import +- Results logged with fix counts per file +- No manual intervention needed for these specific artifacts + +### Manual Review Still Needed + +- **Semantic inversions** (Benefits/Cons swap, financial/scientific) +- **ERC/EIP number garbling** (context-dependent; requires English source) +- **HTML tag corruption in JSON** (separate code path from markdown) +- **Machine translation nonsense** (requires fluency in target language) +- **Dropped glossary links** (detecting missing HTML requires source comparison) + +### Korean-Specific Guidance + +- Heading anchor junk is **almost always present** in Korean imports +- CJK languages (Korean, Chinese, Japanese) share similar Crowdin patterns +- Pages with many links (roadmap, ERC standards) need extra attention +- JSON translations should be checked for HTML tag integrity separately + +### Recommendations for Future Imports + +1. Always run sanitizer before manual review +2. Pay special attention to roadmap pages (dense link content) +3. Check JSON translations for `` / `` tag integrity +4. Run cross-language spot checks if a new pattern emerges in one locale + +## Related Documentation + +- [Sanitizer Test Research: Pattern Catalog](./sanitizer-test-research.md) -- Patterns #17-19 +- [Post-Import Sanitizer Bugs: Japanese Review](./post-import-sanitizer-bugs-found-japanese-review.md) -- Sibling review documenting 5 sanitizer design principles +- [Crowdin Import Review Agent Calibration](./crowdin-import-review-agent-calibration.md) -- Calibrated agent framework for translation reviews +- [Crowdin File Path Mapping and Review Workflow](./crowdin-file-path-mapping-and-review-workflow.md) -- 8-step worktree review workflow +- [Crowdin Translation Sanitizer: MDX Build Failures](../build-errors/crowdin-translation-sanitizer-mdx-fence-bugs.md) -- MDX-specific patterns from French review +- [Translation href Sync Issues](./translation-href-sync-issues.md) -- href corruption patterns in JSON files +- [Scaling Translation Review Pipeline](../translation-review/scaling-translation-review-pipeline.md) -- Strategic roadmap for 178 translation PRs diff --git a/docs/solutions/integration-issues/sanitizer-test-research.md b/docs/solutions/integration-issues/sanitizer-test-research.md index 323eab75b03..b52260d5026 100644 --- a/docs/solutions/integration-issues/sanitizer-test-research.md +++ b/docs/solutions/integration-issues/sanitizer-test-research.md @@ -25,15 +25,32 @@ | 15 | `fixBackslashBeforeClosingTag` too broad — strips `\` | fr #17125 | `\` in prose is a legitimate escape; stripping `\` exposes bare `` to MDX | Critical — breaks MDX compilation | | 16 | Asymmetric backtick pair (single-open, double-close) | ru #17127 | `` `self.`` `` — Crowdin doubles closing backtick, exposing `` as raw HTML | Critical — breaks MDX compilation | +| 17 | Junk text after heading anchors | ko #17166 | `{#network-impact}네트워크-충격` -- Crowdin appends translated anchor IDs | Critical -- breaks rendering | +| 18 | Backtick-wrapped markdown links | ko #17166 | `` `[text](/path)` `` -- links rendered as inline code | High -- breaks navigation | +| 19 | Missing parentheses in link syntax | ko #17166 | `[text]https://url` or `[text]/path/` -- parens stripped | Critical -- breaks navigation | +| 20 | Missing `` before `` in HTML lists | ko #17166 | `text.` -- Crowdin drops closing `` | Critical -- breaks MDX compilation | +| 21 | Image path `./` corrupted to `/.` | ko #17166 | `(/.computer.png)` instead of `(./computer.png)` | Critical -- ENOENT breaks build | +| 22 | Backtick split exposing bare `` or `` | ko #17166 | `` `<> ...` `) `` -- backtick closed early, `` exposed to MDX parser | Critical -- breaks MDX compilation | +| 23 | Inner quotes in JSX attribute break parsing | ko #17166 | `title="오해: "text""` -- `"` inside `title="..."` terminates attribute early | Critical -- breaks MDX compilation | +| 24 | `removeOrphanedClosingTags` strips valid `` | ko #17166 | ``...`` `CHAINID` ``...`` -- inline backtick split puts `` and `` in different segments, making `` look orphaned; sanitizer is not idempotent | Critical -- regression breaks MDX compilation | +| 25 | Tilde range notation triggers strikethrough | ko #17166 | `100만~200만 ... 65,536~97,152명` -- two `~` chars parsed as `` by remark-gfm | High -- garbled rendering | +| 26 | Bold markers not parsed when adjacent to non-Latin text | ko #17166 | `**단일 슬롯 최종 승인(SSF)**으로` -- MDX emphasis parser requires word boundary after closing `**`; fix converts ONLY non-Latin-adjacent cases to `` HTML tags to preserve josa attachment; lookbehind prevents cross-boundary matching between closing `**` on one line and opening `**` on the next | High -- asterisks render literally | +| 27 | Italic markers not parsed when adjacent to non-Latin text | ko #17166 | `_G_가`, `*S*라고` -- same word-boundary issue as bold but for single `*` and `_` italic syntax; fix converts to `` HTML tags; handles both asterisk and underscore variants | High -- asterisks/underscores render literally | +| 28 | Duplicate author frontmatter continuation line | pt-br #17122 | `author: Ori Pomerantz\n Ori Pomerantz` -- Crowdin duplicates the author name on an indented YAML continuation line; parsed value becomes "Ori Pomerantz Ori Pomerantz" | High -- broken frontmatter metadata | +| 29 | Broken markdown link: `}` instead of `]` | pt-br #17122 | `[Mais em staking withdrawals}(/staking/withdrawals/)` -- Crowdin replaces closing `]` with `}`, breaking the link | High -- breaks navigation | +| 30 | TNF ticker transposition for NFT | pt-br #17122 | `TNF` instead of `NFT` -- 37 occurrences across pt-br files; pt-br uses `NFT` (356 occurrences) confirming TNF is a Crowdin error | Medium -- wrong acronym | +| 31 | Translated inline code content with orphaned backticks | pt-br #17122 | EN: `` pass `wallet`, the compiled `` -> PT: `passar a carteira \`, o arquivo` -- Crowdin translates content inside backticks, breaking the code span and leaving orphaned backticks | High -- broken inline code, stray backtick in prose | +| 32 | False-positive "Exposed MDX tag" for PascalCase components | PR #17702 | `` flagged as exposed tag -- 384 false warnings across 72 files; DocLink is registered MDX component in MdComponents | Low -- false warning, no build impact | + ## Patterns Already Handled by Sanitizer (Confirmed Working) These patterns are covered by existing fix functions and should have regression tests: - **Duplicated headings** (`fixDuplicatedHeadings`) — `## Text? Text? {#id}` - **Broken markdown links** (`fixBrokenMarkdownLinks`) — `] (url)` space -- **Escaped bold/italic** (`fixEscapedBoldAndItalic`) — `\*\*text\*\*` +- **Escaped bold/italic** (`fixEscapedBoldAndItalic`) — `\*\*text\*\*`; uses lookbehind to skip `\*` used as multiplication (e.g., `operand\*operand`) - **ASCII guillemets** (`fixAsciiGuillemets`) — `<>` -- **Ticker transpositions** (`fixTickerTranspositions`) — `EHT` → `ETH` +- **Ticker transpositions** (`fixTickerTranspositions`) — `EHT` → `ETH`, `TNF` → `NFT`, `TNFs` → `NFTs`; uses alphanumeric-only boundaries to match adjacent to markdown `_` - **MDX angle brackets** (`escapeMdxAngleBrackets`) — `<5GB` - **Orphaned closing tags** (`removeOrphanedClosingTags`) — trailing `` - **Block component line breaks** (`fixBlockComponentLineBreaks`) @@ -50,6 +67,18 @@ These patterns are covered by existing fix functions and should have regression - **Backslash before closing tag** (`fixBackslashBeforeClosingTag`) — `\` → `` - **Catastrophic code fence drift detection** (`warnCatastrophicCodeFenceDrift`) — prose/code boundaries swapped - **Asymmetric backtick pairs** (`fixAsymmetricBackticks`) — `` `content`` `` → `` `content` `` (Crowdin doubles closing backtick) +- **Junk after heading anchors** (`fixJunkAfterHeadingAnchors`) — `{#id}translated-text` stripped (ko PR #17166) +- **Backtick-wrapped links** (`fixBacktickWrappedLinks`) — `` `[text](url)` `` → `[text](url)` (ko PR #17166) +- **Missing link parentheses** (`fixMissingLinkParentheses`) — `[text]https://url` → `[text](https://url)` (ko PR #17166) +- **Missing closing ``** (`fixMissingClosingEmTag`) — `text.` → `text.` (ko PR #17166) +- **Image path `./` corruption** (`fixImagePathDotSlash`) — `](/.file.png)` → `](./file.png)` (ko PR #17166) +- **Exposed MDX tags warning** (`warnExposedMdxTags`) — bare `` or `` outside backticks (ko PR #17166); PascalCase tags (``, etc.) are automatically treated as safe MDX components and skipped (PR #17702) +- **Inner quotes in JSX attributes** (`fixInnerQuotesInJsxAttributes`) — `title="text: "inner""` → `title="text: "inner""` (ko PR #17166) +- **Orphan tag idempotency** (`removeOrphanedClosingTags`) — fenced-only split + inline-stripped counting prevents false orphan detection when `` spans inline code (ko PR #17166) +- **Tilde strikethrough escape** (`escapeTildeStrikethrough`) — `100만~200만` → `100만\~200만` prevents remark-gfm `` (ko PR #17166) +- **Bold adjacent non-Latin** (`fixBoldAdjacentNonLatin`) — `**text**가` → `text가` converts ONLY non-Latin-adjacent cases to HTML tags; uses lookbehind to prevent cross-boundary matching (ko PR #17166) +- **Italic adjacent non-Latin** (`fixItalicAdjacentNonLatin`) — `*text*가` / `_text_가` → `text가` mirrors bold fix for single `*` and `_` italic syntax (ko PR #17166) +- **Translated inline code warning** (`warnTranslatedInlineCode`) — warns when inline code span count drops significantly OR when orphaned backticks are detected on a line; signals Crowdin translated content inside backticks (pt-br PR #17122) ## Recommendations for Future Sanitizer Iteration diff --git a/instrumentation-client.ts b/instrumentation-client.ts index 098f13db3bd..95f8d1dd4e3 100644 --- a/instrumentation-client.ts +++ b/instrumentation-client.ts @@ -33,6 +33,7 @@ Sentry.init({ debug: environment === "development", environment, enabled: environment === "production", + initialScope: { tags: { module: "app" } }, // Filter errors from browser extensions and third-party scripts denyUrls: [ @@ -51,18 +52,38 @@ Sentry.init({ /on proxy: trap returned falsish/i, /Cannot set property ethereum of #/, /Cannot set property isMetaMask of #<.+> which has only a getter/, - // Extension messaging errors + // Extension messaging errors (ETHORG-7E) /Could not establish connection\. Receiving end does not exist/, /Attempting to use a disconnected port object/, - // Resource loading errors - network/ad blocker issues, not actionable (ETHORG-A8) + /Invalid call to runtime\.sendMessage\(\)/, + // Resource loading errors - network/ad blocker issues, not actionable (ETHORG-A8, ETHORG-8N) /Event `Event` \(type=error\) captured as promise rejection/, + /NetworkError when attempting to fetch resource/, // WebView circular reference serialization failures - wallet app injections (ETHORG-72) /JSON\.stringify cannot serialize cyclic structures/, + // Extension IPC / DApp bridge errors (ETHORG-FN, ETHORG-AT) + /Object Not Found Matching Id:\d+/, + /DApp request timeout/, + // Cross-origin postMessage from extensions/embedded frames (ETHORG-87) + /^Error: invalid origin$/, + // Injected scripts from WebViews, adware, and OEM bloatware (ETHORG-14R, ETHORG-13N, ETHORG-JK, ETHORG-14B) + /LIDNotify is not defined/, + /tgetT is not defined/, + /zaloJSV2 is not defined/, + /onPagePause is not defined/, ], beforeSend(event) { + // Filter wallet extension JSON-RPC errors that have no stacktrace (ETHORG-7Q) + const values = event.exception?.values ?? [] + const hasNoStacktrace = values.every((v) => !v.stacktrace?.frames?.length) + if (hasNoStacktrace) { + const message = values[0]?.value ?? "" + if (/Internal JSON-RPC error/i.test(message)) return null + } + // Filter extension injection script errors not caught by denyUrls - const frames = event.exception?.values?.[0]?.stacktrace?.frames ?? [] + const frames = values.flatMap((v) => v.stacktrace?.frames ?? []) const isExtensionScript = frames.some((f) => { const filename = f.filename || "" const absPath = f.abs_path || "" @@ -85,34 +106,33 @@ Sentry.init({ }) return isExtensionScript ? null : event }, - // Normalize transaction names for parameterized routes to enable per-page analysis - // Sentry uses formats like "/:locale/:slug*" for catch-all routes + // Normalize transaction names to strip locale prefixes so all locales + // group under one page (e.g., "/en/staking/", "/ko/staking/" → "/staking/") beforeSendTransaction(event) { const op = event.contexts?.trace?.op - const transaction = event.transaction - - // Matches patterns like ":locale", ":slug*", ":id", ":post", etc. - const isParameterizedRoute = transaction && /:\w+/.test(transaction) - const isPageTransaction = op === "pageload" || op === "navigation" - - if (isParameterizedRoute && isPageTransaction) { - const url = event.request?.url || (event.tags?.url as string | undefined) - if (url) { - try { - const pathname = new URL(url).pathname - // Remove locale prefix (e.g., "/en/", "/fil/", "/zh-tw/", "/pt-br/"), keeping just the page path - // e.g., "/en/developers/docs" -> "/developers/docs" - // Only match complete path segments (must be followed by "/" or end of string) - const normalizedPath = pathname.replace( - /^\/[a-z]{2,3}(-[a-z]{2})?(?=\/|$)/, - "" - ) - event.transaction = normalizedPath || "/" - } catch { - // Keep original transaction name if URL parsing fails - } + if (op !== "pageload" && op !== "navigation") return event + + const localePrefix = /^\/[a-z]{2,3}(-[a-z]{2})?(?=\/|$)/ + + // Try to resolve from the actual URL first (most reliable) + const url = event.request?.url || (event.tags?.url as string | undefined) + if (url) { + try { + const pathname = new URL(url).pathname + event.transaction = pathname.replace(localePrefix, "") || "/" + return event + } catch { + // Fall through to transaction name normalization } } + + // Fallback: normalize the transaction name directly + // Handles parameterized names like "/:locale/:slug*" → "/:slug*" + if (event.transaction) { + event.transaction = + event.transaction.replace(localePrefix, "").replace(/^\/:locale/, "") || + "/" + } return event }, diff --git a/next.config.js b/next.config.js index 5e27317a94b..bb6ef6dfcc9 100644 --- a/next.config.js +++ b/next.config.js @@ -98,6 +98,11 @@ module.exports = (phase, { defaultConfig }) => { }, { protocol: "https", hostname: "pvvrtckedmrkyzfxubkk.supabase.co" }, { protocol: "https", hostname: "avatars.githubusercontent.com" }, + { protocol: "https", hostname: "avatars0.githubusercontent.com" }, + { protocol: "https", hostname: "avatars1.githubusercontent.com" }, + { protocol: "https", hostname: "avatars2.githubusercontent.com" }, + { protocol: "https", hostname: "avatars3.githubusercontent.com" }, + { protocol: "https", hostname: "avatars4.githubusercontent.com" }, { protocol: "https", hostname: "opengraph.githubassets.com" }, { protocol: "https", hostname: "github.com" }, { protocol: "https", hostname: "coin-images.coingecko.com" }, diff --git a/package.json b/package.json index 4e0ec380898..8e01cb2c502 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ethereum-org-website", - "version": "10.25.0", + "version": "10.26.0", "license": "MIT", "private": true, "scripts": { @@ -54,7 +54,7 @@ "@radix-ui/react-tabs": "^1.1.0", "@radix-ui/react-tooltip": "^1.1.2", "@rainbow-me/rainbowkit": "^2.2.3", - "@sentry/nextjs": "^10.5.0", + "@sentry/nextjs": "^10.41.0", "@socialgouv/matomo-next": "^1.8.0", "@tanstack/react-query": "^5.66.7", "@tanstack/react-table": "^8.19.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 50c2d302240..d0cbdaa79ee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -92,8 +92,8 @@ importers: specifier: ^2.2.3 version: 2.2.5(@tanstack/react-query@5.80.2(react@18.3.1))(@types/react@18.2.57)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.15.4(@netlify/blobs@10.4.1)(@tanstack/query-core@5.80.2)(@tanstack/react-query@5.80.2(react@18.3.1))(@types/react@18.2.57)(bufferutil@4.0.9)(react@18.3.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)) '@sentry/nextjs': - specifier: ^10.5.0 - version: 10.5.0(@opentelemetry/context-async-hooks@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.0.1(@opentelemetry/api@1.9.0))(next@14.2.35(@babel/core@7.27.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(webpack@5.99.9(esbuild@0.25.12)) + specifier: ^10.41.0 + version: 10.41.0(@opentelemetry/context-async-hooks@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.1(@opentelemetry/api@1.9.0))(next@14.2.35(@babel/core@7.27.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(webpack@5.99.9(esbuild@0.25.12)) '@socialgouv/matomo-next': specifier: ^1.8.0 version: 1.9.2(next@14.2.35(@babel/core@7.27.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) @@ -1777,6 +1777,11 @@ packages: '@fastify/busboy@3.2.0': resolution: {integrity: sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==} + '@fastify/otel@0.16.0': + resolution: {integrity: sha512-2304BdM5Q/kUvQC9qJO1KZq3Zn1WWsw+WWkVmFEaj1UE2hEIiuFqrPeglQOwEtw/ftngisqfQ3v70TWMmwhhHA==} + peerDependencies: + '@opentelemetry/api': ^1.9.0 + '@floating-ui/core@1.7.1': resolution: {integrity: sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==} @@ -2337,9 +2342,17 @@ packages: resolution: {integrity: sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==} engines: {node: '>=8.0.0'} - '@opentelemetry/api-logs@0.57.2': - resolution: {integrity: sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A==} - engines: {node: '>=14'} + '@opentelemetry/api-logs@0.207.0': + resolution: {integrity: sha512-lAb0jQRVyleQQGiuuvCOTDVspc14nx6XJjP4FspJ1sNARo3Regq4ZZbrc3rN4b1TYSuUCvgH+UXUPug4SLOqEQ==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/api-logs@0.208.0': + resolution: {integrity: sha512-CjruKY9V6NMssL/T1kAFgzosF1v9o6oeN+aX5JB/C/xPNtmgIJqcXHG7fA82Ou1zCpWGl4lROQUKwUNE1pMCyg==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/api-logs@0.211.0': + resolution: {integrity: sha512-swFdZq8MCdmdR22jTVGQDhwqDzcI4M10nhjXkLr1EsIzXgZBqm4ZlmmcWsg3TSNf+3mzgOiqveXmBLZuDi2Lgg==} + engines: {node: '>=8.0.0'} '@opentelemetry/api@1.9.0': resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} @@ -2357,6 +2370,12 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/context-async-hooks@2.5.1': + resolution: {integrity: sha512-MHbu8XxCHcBn6RwvCt2Vpn1WnLMNECfNKYB14LI5XypcgH4IE0/DiVifVR9tAkwPMyLXN8dOoPJfya3IryLQVw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/core@1.30.1': resolution: {integrity: sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==} engines: {node: '>=14'} @@ -2369,6 +2388,18 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/core@2.5.0': + resolution: {integrity: sha512-ka4H8OM6+DlUhSAZpONu0cPBtPPTQKxbxVzC4CzVx5+K4JnroJVBtDzLAMx4/3CDTJXRvVFhpFjtl4SaiTNoyQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/core@2.5.1': + resolution: {integrity: sha512-Dwlc+3HAZqpgTYq0MUyZABjFkcrKTePwuiFVLjahGD8cx3enqihmpAmdgNFO1R4m/sIe5afjJrA25Prqy4NXlA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/exporter-logs-otlp-http@0.203.0': resolution: {integrity: sha512-s0hys1ljqlMTbXx2XiplmMJg9wG570Z5lH7wMvrZX6lcODI56sG4HL03jklF63tBeyNwK2RV1/ntXGo3HgG4Qw==} engines: {node: ^18.19.0 || >=20.6.0} @@ -2381,134 +2412,134 @@ packages: peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-amqplib@0.50.0': - resolution: {integrity: sha512-kwNs/itehHG/qaQBcVrLNcvXVPW0I4FCOVtw3LHMLdYIqD7GJ6Yv2nX+a4YHjzbzIeRYj8iyMp0Bl7tlkidq5w==} + '@opentelemetry/instrumentation-amqplib@0.58.0': + resolution: {integrity: sha512-fjpQtH18J6GxzUZ+cwNhWUpb71u+DzT7rFkg5pLssDGaEber91Y2WNGdpVpwGivfEluMlNMZumzjEqfg8DeKXQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-connect@0.47.0': - resolution: {integrity: sha512-pjenvjR6+PMRb6/4X85L4OtkQCootgb/Jzh/l/Utu3SJHBid1F+gk9sTGU2FWuhhEfV6P7MZ7BmCdHXQjgJ42g==} + '@opentelemetry/instrumentation-connect@0.54.0': + resolution: {integrity: sha512-43RmbhUhqt3uuPnc16cX6NsxEASEtn8z/cYV8Zpt6EP4p2h9s4FNuJ4Q9BbEQ2C0YlCCB/2crO1ruVz/hWt8fA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-dataloader@0.21.0': - resolution: {integrity: sha512-Xu4CZ1bfhdkV3G6iVHFgKTgHx8GbKSqrTU01kcIJRGHpowVnyOPEv1CW5ow+9GU2X4Eki8zoNuVUenFc3RluxQ==} + '@opentelemetry/instrumentation-dataloader@0.28.0': + resolution: {integrity: sha512-ExXGBp0sUj8yhm6Znhf9jmuOaGDsYfDES3gswZnKr4MCqoBWQdEFn6EoDdt5u+RdbxQER+t43FoUihEfTSqsjA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-express@0.52.0': - resolution: {integrity: sha512-W7pizN0Wh1/cbNhhTf7C62NpyYw7VfCFTYg0DYieSTrtPBT1vmoSZei19wfKLnrMsz3sHayCg0HxCVL2c+cz5w==} + '@opentelemetry/instrumentation-express@0.59.0': + resolution: {integrity: sha512-pMKV/qnHiW/Q6pmbKkxt0eIhuNEtvJ7sUAyee192HErlr+a1Jx+FZ3WjfmzhQL1geewyGEiPGkmjjAgNY8TgDA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-fs@0.23.0': - resolution: {integrity: sha512-Puan+QopWHA/KNYvDfOZN6M/JtF6buXEyD934vrb8WhsX1/FuM7OtoMlQyIqAadnE8FqqDL4KDPiEfCQH6pQcQ==} + '@opentelemetry/instrumentation-fs@0.30.0': + resolution: {integrity: sha512-n3Cf8YhG7reaj5dncGlRIU7iT40bxPOjsBEA5Bc1a1g6e9Qvb+JFJ7SEiMlPbUw4PBmxE3h40ltE8LZ3zVt6OA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-generic-pool@0.47.0': - resolution: {integrity: sha512-UfHqf3zYK+CwDwEtTjaD12uUqGGTswZ7ofLBEdQ4sEJp9GHSSJMQ2hT3pgBxyKADzUdoxQAv/7NqvL42ZI+Qbw==} + '@opentelemetry/instrumentation-generic-pool@0.54.0': + resolution: {integrity: sha512-8dXMBzzmEdXfH/wjuRvcJnUFeWzZHUnExkmFJ2uPfa31wmpyBCMxO59yr8f/OXXgSogNgi/uPo9KW9H7LMIZ+g==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-graphql@0.51.0': - resolution: {integrity: sha512-LchkOu9X5DrXAnPI1+Z06h/EH/zC7D6sA86hhPrk3evLlsJTz0grPrkL/yUJM9Ty0CL/y2HSvmWQCjbJEz/ADg==} + '@opentelemetry/instrumentation-graphql@0.58.0': + resolution: {integrity: sha512-+yWVVY7fxOs3j2RixCbvue8vUuJ1inHxN2q1sduqDB0Wnkr4vOzVKRYl/Zy7B31/dcPS72D9lo/kltdOTBM3bQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-hapi@0.50.0': - resolution: {integrity: sha512-5xGusXOFQXKacrZmDbpHQzqYD1gIkrMWuwvlrEPkYOsjUqGUjl1HbxCsn5Y9bUXOCgP1Lj6A4PcKt1UiJ2MujA==} + '@opentelemetry/instrumentation-hapi@0.57.0': + resolution: {integrity: sha512-Os4THbvls8cTQTVA8ApLfZZztuuqGEeqog0XUnyRW7QVF0d/vOVBEcBCk1pazPFmllXGEdNbbat8e2fYIWdFbw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-http@0.203.0': - resolution: {integrity: sha512-y3uQAcCOAwnO6vEuNVocmpVzG3PER6/YZqbPbbffDdJ9te5NkHEkfSMNzlC3+v7KlE+WinPGc3N7MR30G1HY2g==} + '@opentelemetry/instrumentation-http@0.211.0': + resolution: {integrity: sha512-n0IaQ6oVll9PP84SjbOCwDjaJasWRHi6BLsbMLiT6tNj7QbVOkuA5sk/EfZczwI0j5uTKl1awQPivO/ldVtsqA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-ioredis@0.51.0': - resolution: {integrity: sha512-9IUws0XWCb80NovS+17eONXsw1ZJbHwYYMXiwsfR9TSurkLV5UNbRSKb9URHO+K+pIJILy9wCxvyiOneMr91Ig==} + '@opentelemetry/instrumentation-ioredis@0.59.0': + resolution: {integrity: sha512-875UxzBHWkW+P4Y45SoFM2AR8f8TzBMD8eO7QXGCyFSCUMP5s9vtt/BS8b/r2kqLyaRPK6mLbdnZznK3XzQWvw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-kafkajs@0.12.0': - resolution: {integrity: sha512-bIe4aSAAxytp88nzBstgr6M7ZiEpW6/D1/SuKXdxxuprf18taVvFL2H5BDNGZ7A14K27haHqzYqtCTqFXHZOYg==} + '@opentelemetry/instrumentation-kafkajs@0.20.0': + resolution: {integrity: sha512-yJXOuWZROzj7WmYCUiyT27tIfqBrVtl1/TwVbQyWPz7rL0r1Lu7kWjD0PiVeTCIL6CrIZ7M2s8eBxsTAOxbNvw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-knex@0.48.0': - resolution: {integrity: sha512-V5wuaBPv/lwGxuHjC6Na2JFRjtPgstw19jTFl1B1b6zvaX8zVDYUDaR5hL7glnQtUSCMktPttQsgK4dhXpddcA==} + '@opentelemetry/instrumentation-knex@0.55.0': + resolution: {integrity: sha512-FtTL5DUx5Ka/8VK6P1VwnlUXPa3nrb7REvm5ddLUIeXXq4tb9pKd+/ThB1xM/IjefkRSN3z8a5t7epYw1JLBJQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-koa@0.51.0': - resolution: {integrity: sha512-XNLWeMTMG1/EkQBbgPYzCeBD0cwOrfnn8ao4hWgLv0fNCFQu1kCsJYygz2cvKuCs340RlnG4i321hX7R8gj3Rg==} + '@opentelemetry/instrumentation-koa@0.59.0': + resolution: {integrity: sha512-K9o2skADV20Skdu5tG2bogPKiSpXh4KxfLjz6FuqIVvDJNibwSdu5UvyyBzRVp1rQMV6UmoIk6d3PyPtJbaGSg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: - '@opentelemetry/api': ^1.3.0 + '@opentelemetry/api': ^1.9.0 - '@opentelemetry/instrumentation-lru-memoizer@0.48.0': - resolution: {integrity: sha512-KUW29wfMlTPX1wFz+NNrmE7IzN7NWZDrmFWHM/VJcmFEuQGnnBuTIdsP55CnBDxKgQ/qqYFp4udQFNtjeFosPw==} + '@opentelemetry/instrumentation-lru-memoizer@0.55.0': + resolution: {integrity: sha512-FDBfT7yDGcspN0Cxbu/k8A0Pp1Jhv/m7BMTzXGpcb8ENl3tDj/51U65R5lWzUH15GaZA15HQ5A5wtafklxYj7g==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-mongodb@0.56.0': - resolution: {integrity: sha512-YG5IXUUmxX3Md2buVMvxm9NWlKADrnavI36hbJsihqqvBGsWnIfguf0rUP5Srr0pfPqhQjUP+agLMsvu0GmUpA==} + '@opentelemetry/instrumentation-mongodb@0.64.0': + resolution: {integrity: sha512-pFlCJjweTqVp7B220mCvCld1c1eYKZfQt1p3bxSbcReypKLJTwat+wbL2YZoX9jPi5X2O8tTKFEOahO5ehQGsA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-mongoose@0.50.0': - resolution: {integrity: sha512-Am8pk1Ct951r4qCiqkBcGmPIgGhoDiFcRtqPSLbJrUZqEPUsigjtMjoWDRLG1Ki1NHgOF7D0H7d+suWz1AAizw==} + '@opentelemetry/instrumentation-mongoose@0.57.0': + resolution: {integrity: sha512-MthiekrU/BAJc5JZoZeJmo0OTX6ycJMiP6sMOSRTkvz5BrPMYDqaJos0OgsLPL/HpcgHP7eo5pduETuLguOqcg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-mysql2@0.49.0': - resolution: {integrity: sha512-dCub9wc02mkJWNyHdVEZ7dvRzy295SmNJa+LrAJY2a/+tIiVBQqEAajFzKwp9zegVVnel9L+WORu34rGLQDzxA==} + '@opentelemetry/instrumentation-mysql2@0.57.0': + resolution: {integrity: sha512-nHSrYAwF7+aV1E1V9yOOP9TchOodb6fjn4gFvdrdQXiRE7cMuffyLLbCZlZd4wsspBzVwOXX8mpURdRserAhNA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-mysql@0.49.0': - resolution: {integrity: sha512-QU9IUNqNsrlfE3dJkZnFHqLjlndiU39ll/YAAEvWE40sGOCi9AtOF6rmEGzJ1IswoZ3oyePV7q2MP8SrhJfVAA==} + '@opentelemetry/instrumentation-mysql@0.57.0': + resolution: {integrity: sha512-HFS/+FcZ6Q7piM7Il7CzQ4VHhJvGMJWjx7EgCkP5AnTntSN5rb5Xi3TkYJHBKeR27A0QqPlGaCITi93fUDs++Q==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-pg@0.55.0': - resolution: {integrity: sha512-yfJ5bYE7CnkW/uNsnrwouG/FR7nmg09zdk2MSs7k0ZOMkDDAE3WBGpVFFApGgNu2U+gtzLgEzOQG4I/X+60hXw==} + '@opentelemetry/instrumentation-pg@0.63.0': + resolution: {integrity: sha512-dKm/ODNN3GgIQVlbD6ZPxwRc3kleLf95hrRWXM+l8wYo+vSeXtEpQPT53afEf6VFWDVzJK55VGn8KMLtSve/cg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-redis@0.51.0': - resolution: {integrity: sha512-uL/GtBA0u72YPPehwOvthAe+Wf8k3T+XQPBssJmTYl6fzuZjNq8zTfxVFhl9nRFjFVEe+CtiYNT0Q3AyqW1Z0A==} + '@opentelemetry/instrumentation-redis@0.59.0': + resolution: {integrity: sha512-JKv1KDDYA2chJ1PC3pLP+Q9ISMQk6h5ey+99mB57/ARk0vQPGZTTEb4h4/JlcEpy7AYT8HIGv7X6l+br03Neeg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-tedious@0.22.0': - resolution: {integrity: sha512-XrrNSUCyEjH1ax9t+Uo6lv0S2FCCykcF7hSxBMxKf7Xn0bPRxD3KyFUZy25aQXzbbbUHhtdxj3r2h88SfEM3aA==} + '@opentelemetry/instrumentation-tedious@0.30.0': + resolution: {integrity: sha512-bZy9Q8jFdycKQ2pAsyuHYUHNmCxCOGdG6eg1Mn75RvQDccq832sU5OWOBnc12EFUELI6icJkhR7+EQKMBam2GA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-undici@0.14.0': - resolution: {integrity: sha512-2HN+7ztxAReXuxzrtA3WboAKlfP5OsPA57KQn2AdYZbJ3zeRPcLXyW4uO/jpLE6PLm0QRtmeGCmfYpqRlwgSwg==} + '@opentelemetry/instrumentation-undici@0.21.0': + resolution: {integrity: sha512-gok0LPUOTz2FQ1YJMZzaHcOzDFyT64XJ8M9rNkugk923/p6lDGms/cRW1cqgqp6N6qcd6K6YdVHwPEhnx9BWbw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.7.0 @@ -2519,9 +2550,21 @@ packages: peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation@0.57.2': - resolution: {integrity: sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg==} - engines: {node: '>=14'} + '@opentelemetry/instrumentation@0.207.0': + resolution: {integrity: sha512-y6eeli9+TLKnznrR8AZlQMSJT7wILpXH+6EYq5Vf/4Ao+huI7EedxQHwRgVUOMLFbe7VFDvHJrX9/f4lcwnJsA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation@0.208.0': + resolution: {integrity: sha512-Eju0L4qWcQS+oXxi6pgh7zvE2byogAkcsVv0OjHF/97iOz1N/aKE6etSGowYkie+YA1uo6DNwdSxaaNnLvcRlA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation@0.211.0': + resolution: {integrity: sha512-h0nrZEC/zvI994nhg7EgQ8URIHt0uDTwN90r3qQUdZORS455bbx+YebnGeEuFghUT0HlJSrLF4iHw67f+odY+Q==} + engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 @@ -2549,8 +2592,8 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/redis-common@0.38.0': - resolution: {integrity: sha512-4Wc0AWURII2cfXVVoZ6vDqK+s5n4K5IssdrlVrvGsx6OEOKdghKtJZqXAHWFiZv4nTDLH2/2fldjIHY8clMOjQ==} + '@opentelemetry/redis-common@0.38.2': + resolution: {integrity: sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA==} engines: {node: ^18.19.0 || >=20.6.0} '@opentelemetry/resources@1.30.1': @@ -2565,6 +2608,12 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/resources@2.5.1': + resolution: {integrity: sha512-BViBCdE/GuXRlp9k7nS1w6wJvY5fnFX5XvuEtWsTAOQFIO89Eru7lGW3WbfbxtCuZ/GbrJfAziXG0w0dpxL7eQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/sdk-logs@0.203.0': resolution: {integrity: sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==} engines: {node: ^18.19.0 || >=20.6.0} @@ -2589,6 +2638,12 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/sdk-trace-base@2.5.1': + resolution: {integrity: sha512-iZH3Gw8cxQn0gjpOjJMmKLd9GIaNh/E3v3ST67vyzLSxHBs14HsG4dy7jMYyC5WXGdBVEcM7U/XTF5hCQxjDMw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/sdk-trace-node@1.30.1': resolution: {integrity: sha512-cBjYOINt1JxXdpw1e5MlHmFRc5fgj4GW/86vsKFxJCJ8AL4PdVtYH41gWwl4qd4uQjqEL1oJVrXkSy5cnduAnQ==} engines: {node: '>=14'} @@ -2609,8 +2664,12 @@ packages: resolution: {integrity: sha512-TtxJSRD8Ohxp6bKkhrm27JRHAxPczQA7idtcTOMYI+wQRRrfgqxHv1cFbCApcSnNjtXkmzFozn6jQtFrOmbjPQ==} engines: {node: '>=14'} - '@opentelemetry/sql-common@0.41.0': - resolution: {integrity: sha512-pmzXctVbEERbqSfiAgdes9Y63xjoOyXcD7B6IXBkVb+vbM7M9U98mn33nGXxPf4dfYR0M+vhcKRZmbSJ7HfqFA==} + '@opentelemetry/semantic-conventions@1.40.0': + resolution: {integrity: sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw==} + engines: {node: '>=14'} + + '@opentelemetry/sql-common@0.41.2': + resolution: {integrity: sha512-4mhWm3Z8z+i508zQJ7r6Xi7y4mmoJpdvH0fZPFRkWrdp5fq7hhZ2HhYokEOLkfqSMgPR4Z9EyB3DBkbKGOqZiQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.1.0 @@ -2657,8 +2716,8 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} - '@prisma/instrumentation@6.13.0': - resolution: {integrity: sha512-b97b0sBycGh89RQcqobSgjGl3jwPaC5cQIOFod6EX1v0zIxlXPmL3ckSXxoHpy+Js0QV/tgCzFvqicMJCtezBA==} + '@prisma/instrumentation@7.2.0': + resolution: {integrity: sha512-Rh9Z4x5kEj1OdARd7U18AtVrnL6rmLSI0qYShaB4W7Wx5BKbgzndWF+QnuzMb7GLfVdlT5aYCXoPQVYuYtVu0g==} peerDependencies: '@opentelemetry/api': ^1.8 @@ -3450,137 +3509,152 @@ packages: resolution: {integrity: sha512-lRLz1WZaDokMoUe299yP5JkInc3OgJuqNNlxb6j0q22umCiq6b5iDo2gRmFn93reirIvJxWIicQsGrHd93q8GQ==} engines: {node: '>=14'} - '@sentry-internal/browser-utils@10.5.0': - resolution: {integrity: sha512-4KIJdEj/8Ip9yqJleVSFe68r/U5bn5o/lYUwnFNEnDNxmpUbOlr7x3DXYuRFi1sfoMUxK9K1DrjnBkR7YYF00g==} + '@sentry-internal/browser-utils@10.41.0': + resolution: {integrity: sha512-Nsy7wqdWWqqNaoB/t5iqwAwTkHB73+UmyOU9k4OAmKuizSwj98h0fgPzoil3RgGzR7bjMxvaxXWKZyi//zEr0g==} engines: {node: '>=18'} - '@sentry-internal/feedback@10.5.0': - resolution: {integrity: sha512-x79P4VZwUxb1EGZb9OQ5EEgrDWFCUlrbzHBwV/oocQA5Ss1SFz5u6cP5Ak7yJtILiJtdGzAyAoQOy4GKD13D4Q==} + '@sentry-internal/feedback@10.41.0': + resolution: {integrity: sha512-fRWntZkEPVG7aBMjL7+NPpCTW9FW8RRmx7KZy8AzK51yCXhLwmM1aTR8RKJnz7zZC6XZozvhEXvtI9ud3b0LYA==} engines: {node: '>=18'} - '@sentry-internal/replay-canvas@10.5.0': - resolution: {integrity: sha512-5nrRKd5swefd9+sFXFZ/NeL3bz/VxBls3ubAQ3afak15FikkSyHq3oKRKpMOtDsiYKXE3Bc0y3rF5A+y3OXjIA==} + '@sentry-internal/replay-canvas@10.41.0': + resolution: {integrity: sha512-fVirArw97oTm851JwJ3R1fC5rL+E8G3qx2XMmwU890UzovBcPo//DMDCGG2kkS62VVlZJ01HWF96a0Trer245g==} engines: {node: '>=18'} - '@sentry-internal/replay@10.5.0': - resolution: {integrity: sha512-Dp4coE/nPzhFrYH3iVrpVKmhNJ1m/jGXMEDBCNg3wJZRszI41Hrj0jCAM0Y2S3Q4IxYOmFYaFbGtVpAznRyOHg==} + '@sentry-internal/replay@10.41.0': + resolution: {integrity: sha512-2CstiGYsE15nZ0K2HJB9SH2+/XcAvPf4erT3Y4/NNWogaz+g0RpRMpYM2ybHFX2x0sXggLXYrddHAUPFltiTjg==} engines: {node: '>=18'} - '@sentry/babel-plugin-component-annotate@4.1.0': - resolution: {integrity: sha512-UkcnqC7Bp9ODyoBN7BKcRotd1jz/I2vyruE/qjNfRC7UnP+jIRItUWYaXxQPON1fTw+N+egKdByk0M1y2OPv/Q==} - engines: {node: '>= 14'} + '@sentry/babel-plugin-component-annotate@5.1.1': + resolution: {integrity: sha512-x2wEpBHwsTyTF2rWsLKJlzrRF1TTIGOfX+ngdE+Yd5DBkoS58HwQv824QOviPGQRla4/ypISqAXzjdDPL/zalg==} + engines: {node: '>= 18'} - '@sentry/browser@10.5.0': - resolution: {integrity: sha512-o5pEJeZ/iZ7Fmaz2sIirThfnmSVNiP5ZYhacvcDi0qc288TmBbikCX3fXxq3xiSkhXfe1o5QIbNyovzfutyuVw==} + '@sentry/browser@10.41.0': + resolution: {integrity: sha512-7hwcgpl/RSCRAlSCDSq2U93MRa43W1E3z9pArmlSqraQ4pRIVhVRMhHwSyZZ8yPRlcRa16nIh7d04oZE3Zqniw==} engines: {node: '>=18'} - '@sentry/bundler-plugin-core@4.1.0': - resolution: {integrity: sha512-/5XBtCF6M+9frEXrrvfSWOdOC2q6I1L7oY7qbUVegNkp3kYVGihNZZnJIXGzo9rmwnA0IV7jI3o0pF/HDRqPeA==} - engines: {node: '>= 14'} + '@sentry/bundler-plugin-core@5.1.1': + resolution: {integrity: sha512-F+itpwR9DyQR7gEkrXd2tigREPTvtF5lC8qu6e4anxXYRTui1+dVR0fXNwjpyAZMhIesLfXRN7WY7ggdj7hi0Q==} + engines: {node: '>= 18'} - '@sentry/cli-darwin@2.51.1': - resolution: {integrity: sha512-R1u8IQdn/7Rr8sf6bVVr0vJT4OqwCFdYsS44Y3OoWGVJW2aAQTWRJOTlV4ueclVLAyUQzmgBjfR8AtiUhd/M5w==} + '@sentry/cli-darwin@2.58.5': + resolution: {integrity: sha512-lYrNzenZFJftfwSya7gwrHGxtE+Kob/e1sr9lmHMFOd4utDlmq0XFDllmdZAMf21fxcPRI1GL28ejZ3bId01fQ==} engines: {node: '>=10'} os: [darwin] - '@sentry/cli-linux-arm64@2.51.1': - resolution: {integrity: sha512-nvA/hdhsw4bKLhslgbBqqvETjXwN1FVmwHLOrRvRcejDO6zeIKUElDiL5UOjGG0NC+62AxyNw5ri8Wzp/7rg9Q==} + '@sentry/cli-linux-arm64@2.58.5': + resolution: {integrity: sha512-/4gywFeBqRB6tR/iGMRAJ3HRqY6Z7Yp4l8ZCbl0TDLAfHNxu7schEw4tSnm2/Hh9eNMiOVy4z58uzAWlZXAYBQ==} engines: {node: '>=10'} cpu: [arm64] os: [linux, freebsd, android] - '@sentry/cli-linux-arm@2.51.1': - resolution: {integrity: sha512-Klro17OmSSKOOSaxVKBBNPXet2+HrIDZUTSp8NRl4LQsIubdc1S/aQ79cH/g52Muwzpl3aFwPxyXw+46isfEgA==} + '@sentry/cli-linux-arm@2.58.5': + resolution: {integrity: sha512-KtHweSIomYL4WVDrBrYSYJricKAAzxUgX86kc6OnlikbyOhoK6Fy8Vs6vwd52P6dvWPjgrMpUYjW2M5pYXQDUw==} engines: {node: '>=10'} cpu: [arm] os: [linux, freebsd, android] - '@sentry/cli-linux-i686@2.51.1': - resolution: {integrity: sha512-jp4TmR8VXBdT9dLo6mHniQHN0xKnmJoPGVz9h9VDvO2Vp/8o96rBc555D4Am5wJOXmfuPlyjGcmwHlB3+kQRWw==} + '@sentry/cli-linux-i686@2.58.5': + resolution: {integrity: sha512-G7261dkmyxqlMdyvyP06b+RTIVzp1gZNgglj5UksxSouSUqRd/46W/2pQeOMPhloDYo9yLtCN2YFb3Mw4aUsWw==} engines: {node: '>=10'} cpu: [x86, ia32] os: [linux, freebsd, android] - '@sentry/cli-linux-x64@2.51.1': - resolution: {integrity: sha512-JuLt0MXM2KHNFmjqXjv23sly56mJmUQzGBWktkpY3r+jE08f5NLKPd5wQ6W/SoLXGIOKnwLz0WoUg7aBVyQdeQ==} + '@sentry/cli-linux-x64@2.58.5': + resolution: {integrity: sha512-rP04494RSmt86xChkQ+ecBNRYSPbyXc4u0IA7R7N1pSLCyO74e5w5Al+LnAq35cMfVbZgz5Sm0iGLjyiUu4I1g==} engines: {node: '>=10'} cpu: [x64] os: [linux, freebsd, android] - '@sentry/cli-win32-arm64@2.51.1': - resolution: {integrity: sha512-PiwjTdIFDazTQCTyDCutiSkt4omggYSKnO3HE1+LDjElsFrWY9pJs4fU3D40WAyE2oKu0MarjNH/WxYGdqEAlg==} + '@sentry/cli-win32-arm64@2.58.5': + resolution: {integrity: sha512-AOJ2nCXlQL1KBaCzv38m3i2VmSHNurUpm7xVKd6yAHX+ZoVBI8VT0EgvwmtJR2TY2N2hNCC7UrgRmdUsQ152bA==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@sentry/cli-win32-i686@2.51.1': - resolution: {integrity: sha512-TMvZZpeiI2HmrDFNVQ0uOiTuYKvjEGOZdmUxe3WlhZW82A/2Oka7sQ24ljcOovbmBOj5+fjCHRUMYvLMCWiysA==} + '@sentry/cli-win32-i686@2.58.5': + resolution: {integrity: sha512-EsuboLSOnlrN7MMPJ1eFvfMDm+BnzOaSWl8eYhNo8W/BIrmNgpRUdBwnWn9Q2UOjJj5ZopukmsiMYtU/D7ml9g==} engines: {node: '>=10'} cpu: [x86, ia32] os: [win32] - '@sentry/cli-win32-x64@2.51.1': - resolution: {integrity: sha512-v2hreYUPPTNK1/N7+DeX7XBN/zb7p539k+2Osf0HFyVBaoUC3Y3+KBwSf4ASsnmgTAK7HCGR+X0NH1vP+icw4w==} + '@sentry/cli-win32-x64@2.58.5': + resolution: {integrity: sha512-IZf+XIMiQwj+5NzqbOQfywlOitmCV424Vtf9c+ep61AaVScUFD1TSrQbOcJJv5xGxhlxNOMNgMeZhdexdzrKZg==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@sentry/cli@2.51.1': - resolution: {integrity: sha512-FU+54kNcKJABU0+ekvtnoXHM9zVrDe1zXVFbQT7mS0On0m1P0zFRGdzbnWe2XzpzuEAJXtK6aog/W+esRU9AIA==} + '@sentry/cli@2.58.5': + resolution: {integrity: sha512-tavJ7yGUZV+z3Ct2/ZB6mg339i08sAk6HDkgqmSRuQEu2iLS5sl9HIvuXfM6xjv8fwlgFOSy++WNABNAcGHUbg==} engines: {node: '>= 10'} hasBin: true - '@sentry/core@10.5.0': - resolution: {integrity: sha512-jTJ8NhZSKB2yj3QTVRXfCCngQzAOLThQUxCl9A7Mv+XF10tP7xbH/88MVQ5WiOr2IzcmrB9r2nmUe36BnMlLjA==} + '@sentry/core@10.41.0': + resolution: {integrity: sha512-TlYMUzyXdx2mICmEKFiCDPDw7fHB/3bIn5lJOOENPmF8SogLTTRiu+HhjIhWkZ9zM/fR3w7WT8qtE/ak7nr24Q==} engines: {node: '>=18'} - '@sentry/nextjs@10.5.0': - resolution: {integrity: sha512-CWozbPqbAX8qUx4DdVLgjEkjcG+JJ5vHyGczo8yiWVQQZAv/Ivd+TVxqAVMJiL68y+C4VQYfejGp64zsIYS3yw==} + '@sentry/nextjs@10.41.0': + resolution: {integrity: sha512-yVprYYb0RqKYhjznREGv5UOcqjlL4NOxyZJVAtA4qJFvfTNQnRFZQszVQ0e4G7NHe6F0Pg/HxUu6MkDBio0amQ==} engines: {node: '>=18'} peerDependencies: - next: ^13.2.0 || ^14.0 || ^15.0.0-rc.0 + next: ^13.2.0 || ^14.0 || ^15.0.0-rc.0 || ^16.0.0-0 - '@sentry/node-core@10.5.0': - resolution: {integrity: sha512-VC4FCKMvvbUT32apTE0exfI/WigqKskzQA+VdFz61Y+T7mTCADngNrOjG3ilVYPBU7R9KEEziEd/oKgencqkmQ==} + '@sentry/node-core@10.41.0': + resolution: {integrity: sha512-kJXQsREtyvg/y0BokloxMlGDz64diZmjYbidTv7sz6E+86KZAQejVmg5gdaGa9xohjhzoi9/DKtCgmVtdPVTjA==} engines: {node: '>=18'} peerDependencies: '@opentelemetry/api': ^1.9.0 - '@opentelemetry/context-async-hooks': ^1.30.1 || ^2.0.0 - '@opentelemetry/core': ^1.30.1 || ^2.0.0 + '@opentelemetry/context-async-hooks': ^1.30.1 || ^2.1.0 + '@opentelemetry/core': ^1.30.1 || ^2.1.0 '@opentelemetry/instrumentation': '>=0.57.1 <1' - '@opentelemetry/resources': ^1.30.1 || ^2.0.0 - '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.0.0 - '@opentelemetry/semantic-conventions': ^1.34.0 + '@opentelemetry/resources': ^1.30.1 || ^2.1.0 + '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 + '@opentelemetry/semantic-conventions': ^1.39.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@opentelemetry/context-async-hooks': + optional: true + '@opentelemetry/core': + optional: true + '@opentelemetry/instrumentation': + optional: true + '@opentelemetry/resources': + optional: true + '@opentelemetry/sdk-trace-base': + optional: true + '@opentelemetry/semantic-conventions': + optional: true - '@sentry/node@10.5.0': - resolution: {integrity: sha512-GqTkOc7tkWqRTKNjipysElh/bzIkhfLsvNGwH6+zel5kU15IdOCFtAqIri85ZLo9vbaIVtjQELXOzfo/5MMAFQ==} + '@sentry/node@10.41.0': + resolution: {integrity: sha512-DiMt+BPtRrgIwi4JeJRwB8l3jRYltxPyz0ngpU7vWKuXDGOm5cW0gWbWVSFKijU8ckVWtcW5xmCgL2tMrbHHrA==} engines: {node: '>=18'} - '@sentry/opentelemetry@10.5.0': - resolution: {integrity: sha512-/Qva5vngtuh79YUUBA8kbbrD6w/A+u1vy1jnLoPMKDxWTfNPqT4tCiOOmWYotnITaE3QO0UtXK/j7LMX8FhtUA==} + '@sentry/opentelemetry@10.41.0': + resolution: {integrity: sha512-nAprKdw8PvHPfT7eYRLSj6VOL+NlWEjdfKg7ZLnQPgRBdPOmi1mp+Kym2QIUoCF0MnaU6R80opNvQ0VYeOVrJQ==} engines: {node: '>=18'} peerDependencies: '@opentelemetry/api': ^1.9.0 - '@opentelemetry/context-async-hooks': ^1.30.1 || ^2.0.0 - '@opentelemetry/core': ^1.30.1 || ^2.0.0 - '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.0.0 - '@opentelemetry/semantic-conventions': ^1.34.0 + '@opentelemetry/context-async-hooks': ^1.30.1 || ^2.1.0 + '@opentelemetry/core': ^1.30.1 || ^2.1.0 + '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 + '@opentelemetry/semantic-conventions': ^1.39.0 - '@sentry/react@10.5.0': - resolution: {integrity: sha512-UHanvg+oIAvE/Hm76QCCdxYgb+tIuF0JszQoROApl5C5RxRfJJcU643pASQs6BDvrtxbuMQ/AHTacLTYpsn0cg==} + '@sentry/react@10.41.0': + resolution: {integrity: sha512-8GIDEtAh3cA16jIv9ETIHyqcwpVOXjPv5K0plCmMILze+7kz+jBW1KXHIMfCCuMj1w0FiYweZbHyz6Ak2tv5+w==} engines: {node: '>=18'} peerDependencies: react: ^16.14.0 || 17.x || 18.x || 19.x - '@sentry/vercel-edge@10.5.0': - resolution: {integrity: sha512-DoH+BrKyI9uVUHyEh6raSba2OUgQ0CLtFeitG0geU90VPgAlINNnjhNeKJPLp0rR3v1KesdHebnRNGUUlvXalA==} + '@sentry/vercel-edge@10.41.0': + resolution: {integrity: sha512-fgr+RwQNX7dZGk+/UFPYmekvpTpF+0fBMDemxR608QWQugeoTyOE00dplRw84k2ZeT/LvxY+9MSLmAdM38QmKw==} engines: {node: '>=18'} - '@sentry/webpack-plugin@4.1.0': - resolution: {integrity: sha512-YqfDfyGAuT/9YW1kgAPfD7kGUKQCh1E5co+qMdToxi/Mz4xsWJY02rFS5GrJixYktYJfSMze8NiRr89yJMxYHw==} - engines: {node: '>= 14'} + '@sentry/webpack-plugin@5.1.1': + resolution: {integrity: sha512-XgQg+t2aVrlQDfIiAEizqR/bsy6GtBygwgR+Kw11P/cYczj4W9PZ2IYqQEStBzHqnRTh5DbpyMcUNW2CujdA9A==} + engines: {node: '>= 18'} peerDependencies: - webpack: '>=4.40.0' + webpack: '>=5.0.0' '@smithy/abort-controller@4.0.4': resolution: {integrity: sha512-gJnEjZMvigPDQWHrW3oPrFhQtkrgqBkyjj3pCIdF3A5M6vsZODG93KNlfJprv6bp4245bdT32fsHK4kkH3KYDA==} @@ -4585,11 +4659,11 @@ packages: '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - '@types/pg-pool@2.0.6': - resolution: {integrity: sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==} + '@types/pg-pool@2.0.7': + resolution: {integrity: sha512-U4CwmGVQcbEuqpyju8/ptOKg6gEC+Tqsvj2xS9o1g71bUh8twxnC6ZL5rZKCsGN0iyH0CwgUyc9VR5owNQF9Ng==} - '@types/pg@8.15.4': - resolution: {integrity: sha512-I6UNVBAoYbvuWkkU3oosC8yxqH21f4/Jc4DK71JLG3dT2mdlGe1z+ep/LQGXaKaOgcvUrsQoPRqfgtMcvZiJhg==} + '@types/pg@8.15.6': + resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==} '@types/prop-types@15.7.14': resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} @@ -4614,9 +4688,6 @@ packages: '@types/semver@7.7.0': resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} - '@types/shimmer@1.2.0': - resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==} - '@types/tedious@4.0.14': resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==} @@ -5138,6 +5209,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + adjust-sourcemap-loader@4.0.0: resolution: {integrity: sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==} engines: {node: '>=8.9'} @@ -5361,6 +5437,10 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + base-x@5.0.1: resolution: {integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==} @@ -5415,6 +5495,10 @@ packages: brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@5.0.4: + resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} + engines: {node: 18 || 20 || >=22} + braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} @@ -5616,6 +5700,9 @@ packages: cjs-module-lexer@1.4.3: resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} + cjs-module-lexer@2.2.0: + resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} + class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} @@ -6818,15 +6905,14 @@ packages: deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true + glob@13.0.6: + resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + engines: {node: 18 || 20 || >=22} + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - glob@9.3.5: - resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} - engines: {node: '>=16 || 14 >=14.17'} - deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -7017,6 +7103,9 @@ packages: import-in-the-middle@1.14.2: resolution: {integrity: sha512-5tCuY9BV8ujfOpwtAGgsTx9CGUapcFMEEyByLv1B+v2+6DhAcw+Zr0nhQT7uwaZ7DiourxFEscghOR8e1aPLQw==} + import-in-the-middle@2.0.6: + resolution: {integrity: sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw==} + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -7477,6 +7566,10 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.2.6: + resolution: {integrity: sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -7492,10 +7585,6 @@ packages: magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} - magic-string@0.30.8: - resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==} - engines: {node: '>=12'} - make-dir@1.3.0: resolution: {integrity: sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==} engines: {node: '>=4'} @@ -7746,13 +7835,13 @@ packages: minimalistic-crypto-utils@1.0.1: resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + minimatch@10.2.4: + resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} + engines: {node: 18 || 20 || >=22} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimatch@8.0.4: - resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} - engines: {node: '>=16 || 14 >=14.17'} - minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -7760,14 +7849,14 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@4.2.8: - resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} - engines: {node: '>=8'} - minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + mipd@0.0.7: resolution: {integrity: sha512-aAPZPNDQ3uMTdKbuO2YmAw2TxLHO0moa4YKAyETM/DTj5FloZo+a+8tU+iv4GmW+sOxKLSRwcSFuczk+Cpt6fg==} peerDependencies: @@ -8102,6 +8191,10 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -8760,6 +8853,10 @@ packages: resolution: {integrity: sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==} engines: {node: '>=8.6.0'} + require-in-the-middle@8.0.1: + resolution: {integrity: sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==} + engines: {node: '>=9.3.0 || >=8.10.0 <9.0.0'} + require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} @@ -8783,10 +8880,6 @@ packages: engines: {node: '>= 0.4'} hasBin: true - resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - resolve@2.0.0-next.5: resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} hasBin: true @@ -8957,9 +9050,6 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shimmer@1.2.1: - resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==} - side-channel-list@1.0.0: resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} engines: {node: '>= 0.4'} @@ -9617,9 +9707,6 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} - unplugin@1.0.1: - resolution: {integrity: sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==} - unplugin@1.16.1: resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} engines: {node: '>=14.0.0'} @@ -9886,9 +9973,6 @@ packages: resolution: {integrity: sha512-ykKKus8lqlgXX/1WjudpIEjqsafjOTcOJqxnAbMLAu/KCsDCJ6GBtvscewvTkrn24HsnvFwrSCbenFrhtcCsAA==} engines: {node: '>=10.13.0'} - webpack-virtual-modules@0.5.0: - resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} - webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} @@ -12180,6 +12264,16 @@ snapshots: '@fastify/busboy@3.2.0': {} + '@fastify/otel@0.16.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.208.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 + minimatch: 10.2.4 + transitivePeerDependencies: + - supports-color + '@floating-ui/core@1.7.1': dependencies: '@floating-ui/utils': 0.2.9 @@ -12787,7 +12881,15 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs@0.57.2': + '@opentelemetry/api-logs@0.207.0': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/api-logs@0.208.0': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/api-logs@0.211.0': dependencies: '@opentelemetry/api': 1.9.0 @@ -12801,6 +12903,10 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 + '@opentelemetry/context-async-hooks@2.5.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -12811,6 +12917,16 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.40.0 + + '@opentelemetry/core@2.5.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/exporter-logs-otlp-http@0.203.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -12829,193 +12945,194 @@ snapshots: '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-amqplib@0.50.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-amqplib@0.58.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-connect@0.47.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-connect@0.54.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 '@types/connect': 3.4.38 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-dataloader@0.21.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-dataloader@0.28.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-express@0.52.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-express@0.59.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-fs@0.23.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-fs@0.30.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-generic-pool@0.47.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-generic-pool@0.54.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-graphql@0.51.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-graphql@0.58.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-hapi@0.50.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-hapi@0.57.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-http@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-http@0.211.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 forwarded-parse: 2.1.2 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-ioredis@0.51.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-ioredis@0.59.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/redis-common': 0.38.0 - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/redis-common': 0.38.2 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-kafkajs@0.12.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-kafkajs@0.20.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-knex@0.48.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-knex@0.55.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-koa@0.51.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-koa@0.59.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-lru-memoizer@0.48.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-lru-memoizer@0.55.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mongodb@0.56.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-mongodb@0.64.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mongoose@0.50.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-mongoose@0.57.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mysql2@0.49.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-mysql2@0.57.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - '@opentelemetry/sql-common': 0.41.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mysql@0.49.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-mysql@0.57.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 '@types/mysql': 2.15.27 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-pg@0.55.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-pg@0.63.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - '@opentelemetry/sql-common': 0.41.0(@opentelemetry/api@1.9.0) - '@types/pg': 8.15.4 - '@types/pg-pool': 2.0.6 + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.0) + '@types/pg': 8.15.6 + '@types/pg-pool': 2.0.7 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-redis@0.51.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-redis@0.59.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/redis-common': 0.38.0 - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/redis-common': 0.38.2 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-tedious@0.22.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-tedious@0.30.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 '@types/tedious': 4.0.14 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-undici@0.14.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-undici@0.21.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -13028,15 +13145,30 @@ snapshots: transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation@0.207.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.57.2 - '@types/shimmer': 1.2.0 - import-in-the-middle: 1.14.2 - require-in-the-middle: 7.5.2 - semver: 7.7.4 - shimmer: 1.2.1 + '@opentelemetry/api-logs': 0.207.0 + import-in-the-middle: 2.0.6 + require-in-the-middle: 8.0.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation@0.208.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.208.0 + import-in-the-middle: 2.0.6 + require-in-the-middle: 8.0.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation@0.211.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.211.0 + import-in-the-middle: 2.0.6 + require-in-the-middle: 8.0.1 transitivePeerDependencies: - supports-color @@ -13067,7 +13199,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) - '@opentelemetry/redis-common@0.38.0': {} + '@opentelemetry/redis-common@0.38.2': {} '@opentelemetry/resources@1.30.1(@opentelemetry/api@1.9.0)': dependencies: @@ -13081,6 +13213,12 @@ snapshots: '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/resources@2.5.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/sdk-logs@0.203.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -13108,6 +13246,13 @@ snapshots: '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/sdk-trace-base@2.5.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/sdk-trace-node@1.30.1(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -13129,10 +13274,12 @@ snapshots: '@opentelemetry/semantic-conventions@1.36.0': {} - '@opentelemetry/sql-common@0.41.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/semantic-conventions@1.40.0': {} + + '@opentelemetry/sql-common@0.41.2(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) '@paulmillr/qr@0.2.1': {} @@ -13160,10 +13307,10 @@ snapshots: '@polka/url@1.0.0-next.29': {} - '@prisma/instrumentation@6.13.0(@opentelemetry/api@1.9.0)': + '@prisma/instrumentation@7.2.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.207.0(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color @@ -14016,7 +14163,7 @@ snapshots: '@rollup/pluginutils@5.2.0(rollup@4.46.2)': dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.2 optionalDependencies: @@ -14172,73 +14319,72 @@ snapshots: transitivePeerDependencies: - encoding - '@sentry-internal/browser-utils@10.5.0': + '@sentry-internal/browser-utils@10.41.0': dependencies: - '@sentry/core': 10.5.0 + '@sentry/core': 10.41.0 - '@sentry-internal/feedback@10.5.0': + '@sentry-internal/feedback@10.41.0': dependencies: - '@sentry/core': 10.5.0 + '@sentry/core': 10.41.0 - '@sentry-internal/replay-canvas@10.5.0': + '@sentry-internal/replay-canvas@10.41.0': dependencies: - '@sentry-internal/replay': 10.5.0 - '@sentry/core': 10.5.0 + '@sentry-internal/replay': 10.41.0 + '@sentry/core': 10.41.0 - '@sentry-internal/replay@10.5.0': + '@sentry-internal/replay@10.41.0': dependencies: - '@sentry-internal/browser-utils': 10.5.0 - '@sentry/core': 10.5.0 + '@sentry-internal/browser-utils': 10.41.0 + '@sentry/core': 10.41.0 - '@sentry/babel-plugin-component-annotate@4.1.0': {} + '@sentry/babel-plugin-component-annotate@5.1.1': {} - '@sentry/browser@10.5.0': + '@sentry/browser@10.41.0': dependencies: - '@sentry-internal/browser-utils': 10.5.0 - '@sentry-internal/feedback': 10.5.0 - '@sentry-internal/replay': 10.5.0 - '@sentry-internal/replay-canvas': 10.5.0 - '@sentry/core': 10.5.0 + '@sentry-internal/browser-utils': 10.41.0 + '@sentry-internal/feedback': 10.41.0 + '@sentry-internal/replay': 10.41.0 + '@sentry-internal/replay-canvas': 10.41.0 + '@sentry/core': 10.41.0 - '@sentry/bundler-plugin-core@4.1.0': + '@sentry/bundler-plugin-core@5.1.1': dependencies: '@babel/core': 7.27.4 - '@sentry/babel-plugin-component-annotate': 4.1.0 - '@sentry/cli': 2.51.1 + '@sentry/babel-plugin-component-annotate': 5.1.1 + '@sentry/cli': 2.58.5 dotenv: 16.5.0 find-up: 5.0.0 - glob: 9.3.5 - magic-string: 0.30.8 - unplugin: 1.0.1 + glob: 13.0.6 + magic-string: 0.30.17 transitivePeerDependencies: - encoding - supports-color - '@sentry/cli-darwin@2.51.1': + '@sentry/cli-darwin@2.58.5': optional: true - '@sentry/cli-linux-arm64@2.51.1': + '@sentry/cli-linux-arm64@2.58.5': optional: true - '@sentry/cli-linux-arm@2.51.1': + '@sentry/cli-linux-arm@2.58.5': optional: true - '@sentry/cli-linux-i686@2.51.1': + '@sentry/cli-linux-i686@2.58.5': optional: true - '@sentry/cli-linux-x64@2.51.1': + '@sentry/cli-linux-x64@2.58.5': optional: true - '@sentry/cli-win32-arm64@2.51.1': + '@sentry/cli-win32-arm64@2.58.5': optional: true - '@sentry/cli-win32-i686@2.51.1': + '@sentry/cli-win32-i686@2.58.5': optional: true - '@sentry/cli-win32-x64@2.51.1': + '@sentry/cli-win32-x64@2.58.5': optional: true - '@sentry/cli@2.51.1': + '@sentry/cli@2.58.5': dependencies: https-proxy-agent: 5.0.1 node-fetch: 2.7.0 @@ -14246,35 +14392,34 @@ snapshots: proxy-from-env: 1.1.0 which: 2.0.2 optionalDependencies: - '@sentry/cli-darwin': 2.51.1 - '@sentry/cli-linux-arm': 2.51.1 - '@sentry/cli-linux-arm64': 2.51.1 - '@sentry/cli-linux-i686': 2.51.1 - '@sentry/cli-linux-x64': 2.51.1 - '@sentry/cli-win32-arm64': 2.51.1 - '@sentry/cli-win32-i686': 2.51.1 - '@sentry/cli-win32-x64': 2.51.1 + '@sentry/cli-darwin': 2.58.5 + '@sentry/cli-linux-arm': 2.58.5 + '@sentry/cli-linux-arm64': 2.58.5 + '@sentry/cli-linux-i686': 2.58.5 + '@sentry/cli-linux-x64': 2.58.5 + '@sentry/cli-win32-arm64': 2.58.5 + '@sentry/cli-win32-i686': 2.58.5 + '@sentry/cli-win32-x64': 2.58.5 transitivePeerDependencies: - encoding - supports-color - '@sentry/core@10.5.0': {} + '@sentry/core@10.41.0': {} - '@sentry/nextjs@10.5.0(@opentelemetry/context-async-hooks@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.0.1(@opentelemetry/api@1.9.0))(next@14.2.35(@babel/core@7.27.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(webpack@5.99.9(esbuild@0.25.12))': + '@sentry/nextjs@10.41.0(@opentelemetry/context-async-hooks@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.1(@opentelemetry/api@1.9.0))(next@14.2.35(@babel/core@7.27.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(webpack@5.99.9(esbuild@0.25.12))': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@rollup/plugin-commonjs': 28.0.1(rollup@4.46.2) - '@sentry-internal/browser-utils': 10.5.0 - '@sentry/core': 10.5.0 - '@sentry/node': 10.5.0 - '@sentry/opentelemetry': 10.5.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.36.0) - '@sentry/react': 10.5.0(react@18.3.1) - '@sentry/vercel-edge': 10.5.0 - '@sentry/webpack-plugin': 4.1.0(webpack@5.99.9(esbuild@0.25.12)) - chalk: 3.0.0 + '@sentry-internal/browser-utils': 10.41.0 + '@sentry/bundler-plugin-core': 5.1.1 + '@sentry/core': 10.41.0 + '@sentry/node': 10.41.0 + '@sentry/opentelemetry': 10.41.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) + '@sentry/react': 10.41.0(react@18.3.1) + '@sentry/vercel-edge': 10.41.0 + '@sentry/webpack-plugin': 5.1.1(webpack@5.99.9(esbuild@0.25.12)) next: 14.2.35(@babel/core@7.27.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - resolve: 1.22.8 rollup: 4.46.2 stacktrace-parser: 0.1.11 transitivePeerDependencies: @@ -14286,85 +14431,84 @@ snapshots: - supports-color - webpack - '@sentry/node-core@10.5.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.203.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.36.0)': + '@sentry/node-core@10.41.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.211.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)': dependencies: + '@sentry/core': 10.41.0 + '@sentry/opentelemetry': 10.41.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) + import-in-the-middle: 2.0.6 + optionalDependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - '@sentry/core': 10.5.0 - '@sentry/opentelemetry': 10.5.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.36.0) - import-in-the-middle: 1.14.2 + '@opentelemetry/context-async-hooks': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 - '@sentry/node@10.5.0': + '@sentry/node@10.41.0': dependencies: + '@fastify/otel': 0.16.0(@opentelemetry/api@1.9.0) '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-amqplib': 0.50.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-connect': 0.47.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-dataloader': 0.21.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-express': 0.52.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-fs': 0.23.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-generic-pool': 0.47.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-graphql': 0.51.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-hapi': 0.50.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-ioredis': 0.51.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-kafkajs': 0.12.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-knex': 0.48.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-koa': 0.51.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-lru-memoizer': 0.48.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mongodb': 0.56.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mongoose': 0.50.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mysql': 0.49.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mysql2': 0.49.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-pg': 0.55.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-redis': 0.51.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-tedious': 0.22.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-undici': 0.14.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - '@prisma/instrumentation': 6.13.0(@opentelemetry/api@1.9.0) - '@sentry/core': 10.5.0 - '@sentry/node-core': 10.5.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.203.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.36.0) - '@sentry/opentelemetry': 10.5.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.36.0) - import-in-the-middle: 1.14.2 - minimatch: 9.0.5 + '@opentelemetry/context-async-hooks': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-amqplib': 0.58.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-connect': 0.54.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-dataloader': 0.28.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-express': 0.59.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-fs': 0.30.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-generic-pool': 0.54.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-graphql': 0.58.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-hapi': 0.57.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-http': 0.211.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-ioredis': 0.59.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-kafkajs': 0.20.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-knex': 0.55.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-koa': 0.59.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-lru-memoizer': 0.55.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mongodb': 0.64.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mongoose': 0.57.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mysql': 0.57.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mysql2': 0.57.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-pg': 0.63.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-redis': 0.59.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-tedious': 0.30.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-undici': 0.21.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 + '@prisma/instrumentation': 7.2.0(@opentelemetry/api@1.9.0) + '@sentry/core': 10.41.0 + '@sentry/node-core': 10.41.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.211.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) + '@sentry/opentelemetry': 10.41.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) + import-in-the-middle: 2.0.6 transitivePeerDependencies: - supports-color - '@sentry/opentelemetry@10.5.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.0.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.36.0)': + '@sentry/opentelemetry@10.41.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - '@sentry/core': 10.5.0 + '@opentelemetry/context-async-hooks': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 + '@sentry/core': 10.41.0 - '@sentry/react@10.5.0(react@18.3.1)': + '@sentry/react@10.41.0(react@18.3.1)': dependencies: - '@sentry/browser': 10.5.0 - '@sentry/core': 10.5.0 - hoist-non-react-statics: 3.3.2 + '@sentry/browser': 10.41.0 + '@sentry/core': 10.41.0 react: 18.3.1 - '@sentry/vercel-edge@10.5.0': + '@sentry/vercel-edge@10.41.0': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@sentry/core': 10.5.0 + '@opentelemetry/resources': 2.5.1(@opentelemetry/api@1.9.0) + '@sentry/core': 10.41.0 - '@sentry/webpack-plugin@4.1.0(webpack@5.99.9(esbuild@0.25.12))': + '@sentry/webpack-plugin@5.1.1(webpack@5.99.9(esbuild@0.25.12))': dependencies: - '@sentry/bundler-plugin-core': 4.1.0 - unplugin: 1.0.1 + '@sentry/bundler-plugin-core': 5.1.1 uuid: 9.0.1 webpack: 5.99.9(esbuild@0.25.12) transitivePeerDependencies: @@ -15886,11 +16030,11 @@ snapshots: '@types/parse-json@4.0.2': {} - '@types/pg-pool@2.0.6': + '@types/pg-pool@2.0.7': dependencies: - '@types/pg': 8.15.4 + '@types/pg': 8.15.6 - '@types/pg@8.15.4': + '@types/pg@8.15.6': dependencies: '@types/node': 20.17.57 pg-protocol: 1.10.3 @@ -15918,8 +16062,6 @@ snapshots: '@types/semver@7.7.0': {} - '@types/shimmer@1.2.0': {} - '@types/tedious@4.0.14': dependencies: '@types/node': 20.17.57 @@ -16992,6 +17134,10 @@ snapshots: dependencies: acorn: 8.14.1 + acorn-import-attributes@1.9.5(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + acorn-jsx@5.3.2(acorn@8.14.1): dependencies: acorn: 8.14.1 @@ -17002,6 +17148,8 @@ snapshots: acorn@8.14.1: {} + acorn@8.16.0: {} + adjust-sourcemap-loader@4.0.0: dependencies: loader-utils: 2.0.4 @@ -17265,6 +17413,8 @@ snapshots: balanced-match@1.0.2: {} + balanced-match@4.0.4: {} + base-x@5.0.1: {} base64-js@1.5.1: {} @@ -17309,6 +17459,10 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.4: + dependencies: + balanced-match: 4.0.4 + braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -17517,6 +17671,8 @@ snapshots: cjs-module-lexer@1.4.3: {} + cjs-module-lexer@2.2.0: {} + class-variance-authority@0.7.1: dependencies: clsx: 2.1.1 @@ -18076,7 +18232,7 @@ snapshots: elliptic@6.6.1: dependencies: - bn.js: 4.12.3 + bn.js: 4.12.2 brorand: 1.1.0 hash.js: 1.1.7 hmac-drbg: 1.0.1 @@ -18986,6 +19142,12 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 + glob@13.0.6: + dependencies: + minimatch: 10.2.4 + minipass: 7.1.3 + path-scurry: 2.0.2 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -18995,13 +19157,6 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 - glob@9.3.5: - dependencies: - fs.realpath: 1.0.0 - minimatch: 8.0.4 - minipass: 4.2.8 - path-scurry: 1.11.1 - globals@11.12.0: {} globals@13.24.0: @@ -19239,6 +19394,13 @@ snapshots: cjs-module-lexer: 1.4.3 module-details-from-path: 1.0.4 + import-in-the-middle@2.0.6: + dependencies: + acorn: 8.16.0 + acorn-import-attributes: 1.9.5(acorn@8.16.0) + cjs-module-lexer: 2.2.0 + module-details-from-path: 1.0.4 + imurmurhash@0.1.4: {} indent-string@4.0.0: {} @@ -19399,7 +19561,7 @@ snapshots: is-reference@1.2.1: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 is-regex@1.2.1: dependencies: @@ -19685,6 +19847,8 @@ snapshots: lru-cache@10.4.3: {} + lru-cache@11.2.6: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -19699,10 +19863,6 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 - magic-string@0.30.8: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - make-dir@1.3.0: dependencies: pify: 3.0.0 @@ -20216,13 +20376,13 @@ snapshots: minimalistic-crypto-utils@1.0.1: {} - minimatch@3.1.2: + minimatch@10.2.4: dependencies: - brace-expansion: 1.1.11 + brace-expansion: 5.0.4 - minimatch@8.0.4: + minimatch@3.1.2: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 1.1.11 minimatch@9.0.5: dependencies: @@ -20230,10 +20390,10 @@ snapshots: minimist@1.2.8: {} - minipass@4.2.8: {} - minipass@7.1.2: {} + minipass@7.1.3: {} + mipd@0.0.7(typescript@5.8.3): optionalDependencies: typescript: 5.8.3 @@ -20623,6 +20783,11 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.2 + path-scurry@2.0.2: + dependencies: + lru-cache: 11.2.6 + minipass: 7.1.3 + path-type@4.0.0: {} pathval@2.0.0: {} @@ -21325,6 +21490,13 @@ snapshots: transitivePeerDependencies: - supports-color + require-in-the-middle@8.0.1: + dependencies: + debug: 4.4.3 + module-details-from-path: 1.0.4 + transitivePeerDependencies: + - supports-color + require-main-filename@2.0.0: {} requireindex@1.2.0: {} @@ -21347,12 +21519,6 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - resolve@1.22.8: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - resolve@2.0.0-next.5: dependencies: is-core-module: 2.16.1 @@ -21585,8 +21751,6 @@ snapshots: shebang-regex@3.0.0: {} - shimmer@1.2.1: {} - side-channel-list@1.0.0: dependencies: es-errors: 1.3.0 @@ -22338,13 +22502,6 @@ snapshots: universalify@2.0.1: {} - unplugin@1.0.1: - dependencies: - acorn: 8.14.1 - chokidar: 3.6.0 - webpack-sources: 3.3.2 - webpack-virtual-modules: 0.5.0 - unplugin@1.16.1: dependencies: acorn: 8.14.1 @@ -22672,8 +22829,6 @@ snapshots: webpack-sources@3.3.2: {} - webpack-virtual-modules@0.5.0: {} - webpack-virtual-modules@0.6.2: {} webpack@5.99.9(esbuild@0.25.12): diff --git a/public/content/community/grants/index.md b/public/content/community/grants/index.md index 6f98c4e0aaf..15e39a4726b 100644 --- a/public/content/community/grants/index.md +++ b/public/content/community/grants/index.md @@ -30,7 +30,6 @@ These resources compile and organize various grant opportunities across the Ethe These general platforms offer broad coverage of grants across the entire Web3 space and are useful starting points for anyone looking for funding: -- [Blockchain Grants](https://www.blockchaingrants.org/) - _Directory of blockchain and crypto grants_ - [Karma Funding Map](https://gap.karmahq.xyz/funding-map) - Directory of all the web3 grant programs, updated on weekly basis ### For developers and builders {#for-developers-and-builders} @@ -41,7 +40,6 @@ These general platforms offer broad coverage of grants across the entire Web3 sp ### For DeFi projects and financial applications {#for-defi-projects} -- [LlamaoGrants](https://wiki.defillama.com/wiki/LlamaoGrants) - _DeFi Llama's grant program directory_ - [AlphaGrowth Grants](https://alphagrowth.io/crypto-web3-grants-list) - _Comprehensive list of crypto and Web3 grants_ - [Uniswap Foundation Grants](https://www.uniswapfoundation.org/build) - _Unichain and Uniswap v4 grants and support for DeFi builders_ diff --git a/public/content/community/support/faq/index.md b/public/content/community/support/faq/index.md new file mode 100644 index 00000000000..30f4100e12e --- /dev/null +++ b/public/content/community/support/faq/index.md @@ -0,0 +1,78 @@ +--- +title: Frequently asked questions +description: Common Ethereum questions about wallets, transactions, staking, and more. +lang: en +--- + +# Frequently asked questions {#faq} + +## I sent crypto to the wrong address {#wrong-wallet} + +A transaction sent on Ethereum is irreversible. Unfortunately, if you sent ETH or tokens to the wrong wallet, there is no way to reverse the transaction. + +**What you can do:** + +- **If you know the owner of the address**, contact them directly and ask them to return the funds +- **If the address belongs to an exchange or known service**, contact their support team, as they may be able to help +- **If you sent tokens to a contract address**, check whether the contract has a withdrawal or recovery function (this is rare) + +In most cases, there is no way to recover the funds. No central organization, entity, or person owns Ethereum, which means no one can reverse transactions. Always double-check the recipient address before confirming. + +## I lost access to my wallet {#lost-wallet-access} + +Your recovery options depend on the type of wallet you use. + +### If you have your seed phrase (recovery phrase) + +You can restore your wallet in any compatible wallet app using your seed phrase. This is why it is critical to keep your seed phrase stored safely offline. Check your wallet provider's documentation for restore instructions. + +### If you have lost your seed phrase + +Without your seed phrase or private keys, your funds cannot be recovered. No one, including ethereum.org, can reset your password or restore access to a self-custody wallet. + +### If your account is on an exchange + +If your account is on a centralized exchange like Coinbase, Binance, or Kraken, contact the exchange's support team directly. They control accounts on their platform and may be able to help with password resets or account recovery. + + + + + + +**Never share your seed phrase with anyone** claiming to help you recover your wallet. This is one of the most common scam tactics. No legitimate service will ever ask for your seed phrase. + + + + + + + How to use a wallet + + +## My transaction is stuck or pending {#stuck-transaction} + +Transactions on Ethereum can get stuck when the gas fee you set was lower than what the network currently requires. Most wallets let you fix this: + +- **Speed up:** Resubmit the same transaction with a higher gas fee +- **Cancel:** Send a 0 ETH transaction to your own address using the same nonce as the pending transaction + +### Helpful guides + +- [How to speed up or cancel a pending transaction on MetaMask](https://support.metamask.io/transactions-and-gas/transactions/how-to-speed-up-or-cancel-a-pending-transaction/) +- [How to cancel pending Ethereum transactions](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) + +## How can I claim my Ethereum giveaway? {#giveaway-scam} + +Ethereum giveaways are scams designed to steal your ETH. Do not be tempted by offers that seem too good to be true. If you send ETH to a giveaway address, you will not receive a giveaway, and you will not be able to recover your funds. + +[More on scam prevention](/security/#common-scams) + +## How do I stake ETH? {#how-to-stake} + +To become a validator, you must stake 32 ETH in the Ethereum deposit contract and set up a validator node. You can also participate with less ETH through staking pools. + +More information is available on our [staking pages](/staking/) and at [the staking launchpad](https://launchpad.ethereum.org/). + +## How do I mine Ethereum? {#mining-ethereum} + +Ethereum mining is no longer possible. Mining was switched off when Ethereum moved from [proof-of-work](/glossary/#pow) to [proof-of-stake](/glossary/#pos) during [The Merge](/roadmap/merge/) in September 2022. Now, instead of miners, Ethereum has validators. Anyone may [stake](/glossary/#staking) ETH and receive staking rewards for running validator software to secure the network. diff --git a/public/content/community/support/index.md b/public/content/community/support/index.md deleted file mode 100644 index 197a90e8ee2..00000000000 --- a/public/content/community/support/index.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Ethereum support -description: Get support in the Ethereum ecosystem. -lang: en ---- - -# Ethereum support {#support} - -## Official Ethereum support {#official-support} - -Are you looking for the official Ethereum support? The first thing you should know is that Ethereum is decentralized. This means no central organization, entity, or person owns Ethereum, and because of this, no official support channels exist. - -Understanding the decentralized nature of Ethereum is vital because **anyone claiming to be official support for Ethereum is probably trying to scam you!** The best protection against scammers is educating yourself and taking security seriously. - - - Ethereum security and scam prevention - - - - Learn Ethereum fundamentals - - -Despite the lack of official support, many groups, communities, and projects across the Ethereum ecosystem are happy to help, and you can find a lot of useful information and resources on this page. Still have questions? Join the [ethereum.org Discord](https://discord.gg/ethereum-org), and we'll try to help. - -## Frequently asked questions {#faq} - -### I've sent ETH to the wrong wallet {#wrong-wallet} - -A transaction sent on Ethereum is irreversible. Unfortunately, if you've sent ETH to the wrong wallet, there is no way to recover these funds. No one central organization, entity, or person owns Ethereum, which means no one can reverse transactions. Therefore, it is vital always to double-check your transactions before sending them. - -### How can I claim my Ethereum giveaway? {#giveaway-scam} - -Ethereum giveaways are scams designed to steal your ETH. Do not be tempted by offers that seem too good to be true — if you send ETH to a giveaway address, you will not receive a giveaway, and you will not be able to recover your funds. - -[More on scam prevention](/security/#common-scams) - -### My transaction is stuck {#stuck-transaction} - -Transactions on Ethereum can sometimes get stuck if you have submitted a lower transaction fee than is required due to network demand. Many wallets provide an option to resubmit the same transaction with a higher transaction fee to allow the transaction to be processed. Alternatively, you can cancel a pending transaction by sending a transaction to your own address and using the same nonce as the pending transaction. - -[How to speed up or cancel a pending transaction on MetaMask](https://metamask.zendesk.com/hc/en-us/articles/360015489251-How-to-speed-up-or-cancel-a-pending-transaction) - -[How to cancel pending Ethereum transactions](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) - -### How do I mine Ethereum? {#mining-ethereum} - -Ethereum mining is no longer possible. Mining was switched off when Ethereum moved from [proof-of-work](/glossary/#pow) to [proof-of-stake](/glossary/#pos). Now, instead of miners, Ethereum has validators. Anyone may [stake](/glossary/#staking) ETH and receive staking rewards for running validator software to secure the network. - -### How do I become a staker / run a validator? {#how-to-stake} - -To become a validator, you must stake 32 ETH in the Ethereum deposit contract and set up a validator node. More information is available on our [staking pages](/staking) and at [the staking launchpad](https://launchpad.ethereum.org/). - -## Building dapps {#building-support} - -Building can be hard. Here are some development focused spaces with experienced Ethereum developers that are happy to help. - -- [Alchemy University](https://university.alchemy.com/#starter_code) -- [CryptoDevs discord](https://discord.com/invite/5W5tVb3) -- [Ethereum StackExchange](https://ethereum.stackexchange.com/) -- [Web3 University](https://www.web3.university/) -- [LearnWeb3](https://discord.com/invite/learnweb3) - -You can also find documentation and development guides in our [Ethereum developer resources](/developers/) section. - -### Tooling {#dapp-tooling} - -Does your question relate to a particular tool, project, or library? Most projects have chat servers or forums dedicated to supporting you. - -Here are some popular examples: - -- [Solidity Matrix](https://app.element.io/#/room/#solidity:matrix.org) -- [ethers.js](https://discord.gg/6jyGVDK6Jx) -- [web3.js](https://discord.gg/GsABYQu4sC) -- [Hardhat](https://discord.gg/xtrMGhmbfZ) -- [Alchemy](http://alchemy.com/discord) -- [Tenderly](https://discord.gg/fBvDJYR) - -## Running a node {#node-support} - -If you're running a node or validator, here are some communities that are dedicated to helping you get started. - -- [EthStaker discord](https://discord.gg/ethstaker) -- [EthStaker reddit](https://www.reddit.com/r/ethstaker) - -Most of the teams building Ethereum clients also have dedicated, public-facing, spaces where you can get support and ask questions. - -### Execution clients {#execution-clients} - -- [Geth](https://discord.gg/FqDzupGyYf) -- [Nethermind](https://discord.gg/YJx3pm8z5C) -- [Besu](https://discord.gg/p8djYngzKN) -- [Erigon](https://github.com/ledgerwatch/erigon/issues) -- [Reth](https://github.com/paradigmxyz/reth/discussions) - -### Consensus clients {#consensus-clients} - -- [Prysm](https://discord.gg/prysmaticlabs) -- [Nimbus](https://discord.gg/nSmEH3qgFv) -- [Lighthouse](https://discord.gg/cyAszAh) -- [Teku](https://discord.gg/7hPv2T6) -- [Lodestar](https://discord.gg/aMxzVcr) -- [Grandine](https://discord.gg/H9XCdUSyZd) - -You can also [learn how to run a node here](/developers/docs/nodes-and-clients/run-a-node/). diff --git a/public/content/community/support/misconceptions/index.md b/public/content/community/support/misconceptions/index.md new file mode 100644 index 00000000000..083ccaa64de --- /dev/null +++ b/public/content/community/support/misconceptions/index.md @@ -0,0 +1,73 @@ +--- +title: Common misconceptions about Ethereum +description: Clearing up the most common misunderstandings about how Ethereum works. +lang: en +--- + +# Common misconceptions about Ethereum {#misconceptions} + +## Is Ethereum a company? {#not-a-company} + +Ethereum is open-source, decentralized technology maintained by thousands of contributors worldwide. There is no company called "Ethereum" that manages accounts, holds funds, or provides customer support. + +The [Ethereum Foundation](https://ethereum.foundation/) is a non-profit organization that supports Ethereum's development, but it does not own or control the network. No single entity does. + +**[ethereum.org](/)** is a community-run educational resource. It is not an exchange, wallet, or financial institution. It does not hold any user funds and cannot access any accounts. + + + What is Ethereum? + + +## Can someone recover or freeze my funds? {#no-fund-access} + +Unlike a bank, there is no central authority on Ethereum that can freeze, seize, or recover funds. The person holding the private keys (or seed phrase) has full and sole control over a wallet. + +This means: + +- **No one can recover funds** you sent to the wrong address +- **No one can reverse** a transaction after it is confirmed +- **No one can freeze** your wallet or block your transactions +- **No one can reset your password** if you lose your seed phrase + +This is why protecting your seed phrase is critical. It is the only way to access your wallet. If it is lost or stolen, there is no recovery option. + + + Ethereum security and scam prevention + + +## Can I still mine Ethereum? {#no-mining} + +Ethereum switched from [proof-of-work](/glossary/#pow) to [proof-of-stake](/glossary/#pos) during [The Merge](/roadmap/merge/) in September 2022. Mining is no longer possible on Ethereum. + +The network is now secured by validators who [stake](/glossary/#staking) ETH. Anyone can participate: + +- **Solo staking:** Run your own validator with 32 ETH—[learn more](/staking/solo/) +- **Staking as a service:** Delegate node operation while keeping your keys—[learn more](/staking/saas/) +- **Pooled staking:** Stake with less than 32 ETH by joining a pool—[learn more](/staking/pools/) + + + Learn more about staking + + +## Is there an Ethereum support team? {#no-support-team} + +Looking for "official Ethereum support" is similar to looking for "official internet support." This of course doesn't exist, but depending on your issue you may be able to seek out support from your internet service provider, your router hardware manufacturer, or one of the companies behind the device, app or website you're using. + +Ethereum is similar. There is no company, support team, or help desk behind Ethereum as a whole, but depending on the issue you may find help by reaching out to your _wallet provider_, _staking service_, _exchange_, _financial institution_ or the _team maintaining an app_ you're using. + +Since Ethereum is publicly transparent by default, you may also find [block explorers](/developers/docs/data-and-analytics/block-explorers/), [analytics tools](/developers/tools/analytics/), and other [online investigation resources](/community/support/scams/#analyze) useful in looking into a problem directly. + +That said, no one from Ethereum or ethereum.org will ever: + +- Contact you via direct message +- Ask for your seed phrase or private keys +- Ask you to send ETH to verify your wallet +- Offer to help you recover funds for a fee + +**Anyone doing any of the above is trying to scam you.** + +If you need help, the real communities that can assist are listed on the [support page](/community/support/). These are volunteer-run, open communities—not official support channels. + + + Ethereum security and scam prevention + diff --git a/public/content/community/support/scams/index.md b/public/content/community/support/scams/index.md new file mode 100644 index 00000000000..f77c1d62403 --- /dev/null +++ b/public/content/community/support/scams/index.md @@ -0,0 +1,160 @@ +--- +title: Scam help & reporting +description: What to do if you have been scammed, how to secure your remaining assets, and where to report fraud. +lang: en +--- + +# I was scammed or lost funds {#scam-help} + +Cryptocurrency scams target people of all experience levels, including professionals in finance and technology. You are not alone, and being here is the right first step. + + + + + + +**No one can reverse blockchain transactions.** If someone contacts you claiming they can recover your funds for a fee, that is almost certainly a second scam. See [recovery scams](#recovery-scams) below. + + + + + +## Secure your remaining assets {#secure-assets} + +If you interacted with a scammer or suspect your wallet is compromised, take these steps immediately: + +1. **Move remaining funds** to a new, secure wallet that the scammer does not have access to +2. **Revoke token approvals.** Scammers often trick you into approving unlimited token spending. Revoking these permissions prevents further draining of your wallet +3. **Change passwords** on any exchange accounts that may be linked +4. **Enable two-factor authentication (2FA)** on all crypto-related accounts + +### How to revoke token approvals {#revoke-approvals} + +When you interact with a dapp or smart contract, you may have granted it permission to spend your tokens. If a scammer tricked you into approving a malicious contract, they can continue draining your tokens even after the initial scam. + +Use these tools to check and revoke approvals: + +- [Revoke.cash](https://revoke.cash/): connect your wallet to see all active approvals and revoke them +- [Revokescout](https://revoke.blockscout.com/): check and revoke approvals via Blockscout +- [Etherscan Token Approval Checker](https://etherscan.io/tokenapprovalchecker): check and revoke approvals via Etherscan + + + Step-by-step guide: How to revoke token access + + +## Report scam addresses and websites {#report} + +Reporting helps warn other users and may assist law enforcement investigations. Document everything: transaction hashes, wallet addresses, screenshots, and any communication with the scammer. + +### Report a scam address {#report-address} + +- [Chainabuse](https://www.chainabuse.com/): community-driven scam and fraud reporting database. Submit reports and search for known scam addresses +- [Etherscan report](https://info.etherscan.com/report-address/): flag an address on the most-used Ethereum block explorer +- [CryptoScamDB](https://cryptoscamdb.org/): open-source database tracking cryptocurrency scams + +### Report a scam website or social media account {#report-website} + +- [PhishTank](https://phishtank.org/): submit and verify phishing URLs +- [Google Safe Browsing](https://safebrowsing.google.com/safebrowsing/report_phish/): report phishing sites to Google so they get blocked in Chrome and other browsers +- [Netcraft](https://report.netcraft.com/report/mistake): report malicious and fraudulent websites +- Report directly on the social media platform where the scam occurred (Twitter/X, Discord, Telegram all have reporting features) + +### Report to law enforcement {#report-law-enforcement} + +- **United States:** [FBI Internet Crime Complaint Center (IC3)](https://www.ic3.gov/) +- **United Kingdom:** [Action Fraud](https://www.actionfraud.police.uk/) +- **European Union:** [Europol](https://www.europol.europa.eu/report-a-crime) +- **Other countries:** file a report with your local police. Cryptocurrency fraud is a crime in most jurisdictions + +## Analyze what happened {#analyze} + +Understanding where your funds went can help with reports and may support recovery efforts if the funds land on a centralized exchange. + +- [Blockscout](https://eth.blockscout.com/): open-source block explorer to look up any transaction hash or wallet address to see where funds were sent +- [Etherscan](https://etherscan.io/): look up any transaction hash or wallet address to see where funds were sent +- [Chainabuse lookup](https://www.chainabuse.com/): check if an address has already been reported by other victims +- [MetaSleuth](https://metasleuth.io/) by BlockSec: visual transaction tracing tool that maps fund flows + +**If funds were sent to a centralized exchange** (like Coinbase, Binance, Kraken), contact their support team immediately with the transaction details. Exchanges can sometimes freeze accounts flagged for fraud. + +## The hard truth {#hard-truth} + +Because Ethereum is decentralized, no central authority can reverse transactions or recover stolen funds. Once a transaction is confirmed on the blockchain, it is final. + +Reporting is still valuable. Reports help law enforcement track organized fraud rings, and flagging addresses on Chainabuse and Etherscan warns future potential victims. + +## Types of scams to watch for {#scam-types} + + + +Scammers create fake giveaways promising to multiply your ETH or give you free tokens. They often impersonate well-known figures like Vitalik Buterin. If you send ETH to a "giveaway" address, you will not receive anything back. + +**Remember:** Vitalik and other prominent figures will never ask you to send them ETH. + +[More on common scams](/security/#common-scams) + + + + + +Scammers impersonate Ethereum team members, moderators, or support agents on Discord, Telegram, and social media. They may send you direct messages offering help or claiming there is a problem with your account. + +**Remember:** + +- There is no "Ethereum support team" +- Real moderators will never DM you first +- Never share your seed phrase or private keys with anyone, for any reason +- Never click links sent in unsolicited messages + + + + + +Recovery scams specifically target people who have already lost funds. Scammers monitor social media for people talking about being scammed, then reach out posing as "blockchain investigators" or "crypto recovery experts." + +They promise to trace and recover your stolen crypto for an upfront fee. After you pay, they disappear. + +**No legitimate service can reverse blockchain transactions.** Anyone promising this is lying. This is one of the most common follow-up scams. + + + + + +Phishing sites look identical to real wallet apps, exchanges, or DeFi platforms. They trick you into entering your seed phrase or connecting your wallet, then drain your funds. + +**Protect yourself:** + +- Always verify the URL before connecting your wallet +- Bookmark the official sites you use regularly +- Never enter your seed phrase on any website. Legitimate apps never ask for it +- Use [PhishTank](https://phishtank.org/) to check suspicious URLs + + + How to identify scam tokens + + + + + + Full guide to Ethereum security and scam prevention + diff --git a/public/content/developers/docs/data-and-analytics/block-explorers/index.md b/public/content/developers/docs/data-and-analytics/block-explorers/index.md index 4902214c635..5a3951a2179 100644 --- a/public/content/developers/docs/data-and-analytics/block-explorers/index.md +++ b/public/content/developers/docs/data-and-analytics/block-explorers/index.md @@ -11,6 +11,14 @@ Block explorers are your portal to Ethereum's data. You can use them to see real You should understand the basic concepts of Ethereum so you can make sense of the data that a block explorer gives you. Start with [an intro to Ethereum](/developers/docs/intro-to-ethereum/). +## Open source tools {#open-source-tools} + +- [3xpl](https://3xpl.com/ethereum) - An ad-free Ethereum explorer that allows downloading its datasets (open-core: core modules are open source) +- [Beaconcha.in](https://beaconcha.in/) +- [Blockscout](https://eth.blockscout.com/) +- [lazy-etherscan](https://github.com/woxjro/lazy-etherscan) +- [Otterscan](https://otterscan.io/) + ## Services {#services} - [Blockchair](https://blockchair.com/ethereum) - Private Ethereum explorer. Also for sorting and filtering (mempool) data. Available in Spanish, French, Italian, Dutch, Portuguese, Russian, Chinese, and Farsi @@ -23,14 +31,6 @@ You should understand the basic concepts of Ethereum so you can make sense of th - [EthVM](https://www.ethvm.com/) - [OKLink](https://www.oklink.com/eth) -## Open source tools {#open-source-tools} - -- [3xpl](https://3xpl.com/ethereum) - An ad-free Ethereum explorer that allows downloading its datasets (open-core: core modules are open source) -- [Beaconcha.in](https://beaconcha.in/) -- [Blockscout](https://eth.blockscout.com/) -- [lazy-etherscan](https://github.com/woxjro/lazy-etherscan) -- [Otterscan](https://otterscan.io/) - ## Data {#data} Ethereum is transparent by design so everything is verifiable. Block explorers provide an interface for getting this information. And this is for both the main Ethereum network and the testnets, should you need that data. Data is divided into execution data and consensus data. The execution data refers to the transactions that have been executed in a specific block. The consensus data refers to the blocks themselves and the validators who proposed them. diff --git a/public/content/developers/docs/networking-layer/index.md b/public/content/developers/docs/networking-layer/index.md index a228056180d..07464c88ffe 100644 --- a/public/content/developers/docs/networking-layer/index.md +++ b/public/content/developers/docs/networking-layer/index.md @@ -146,8 +146,8 @@ A summary of the control flow is shown below, with the relevant networking stack Once the block has been attested by sufficient validators it is added to the head of the chain, justified and eventually finalized. -![](cons_client_net_layer.png) -![](exe_client_net_layer.png) +![Diagram of the Ethereum consensus client networking layer](cons_client_net_layer.png) +![Diagram of the Ethereum execution client networking layer](exe_client_net_layer.png) Network layer schematic for consensus and execution clients, from [ethresear.ch](https://ethresear.ch/t/eth1-eth2-client-relationship/7248) diff --git a/public/content/developers/docs/nodes-and-clients/node-architecture/index.md b/public/content/developers/docs/nodes-and-clients/node-architecture/index.md index 5986b52a043..a52ab204acc 100644 --- a/public/content/developers/docs/nodes-and-clients/node-architecture/index.md +++ b/public/content/developers/docs/nodes-and-clients/node-architecture/index.md @@ -10,7 +10,7 @@ When Ethereum was using [proof-of-work](/developers/docs/consensus-mechanisms/po The diagram below shows the relationship between the two Ethereum clients. The two clients connect to their own respective peer-to-peer (P2P) networks. Separate P2P networks are needed as the execution clients gossip transactions over their P2P network, enabling them to manage their local transaction pool, whilst the consensus clients gossip blocks over their P2P network, enabling consensus and chain growth. -![](node-architecture-text-background.png) +![Diagram of Ethereum node architecture showing execution and consensus layers](node-architecture-text-background.png) _There are several options for the execution client including Erigon, Nethermind, and Besu_. diff --git a/public/content/developers/docs/smart-contracts/testing/index.md b/public/content/developers/docs/smart-contracts/testing/index.md index 45c5f6f0c4c..a2497643ebc 100644 --- a/public/content/developers/docs/smart-contracts/testing/index.md +++ b/public/content/developers/docs/smart-contracts/testing/index.md @@ -311,6 +311,6 @@ The major difference is that bug bounty programs are open to the wider developer ## Tutorials: Smart contract testing on Ethereum {#tutorials} -- [Waffle: Dynamic mocking and testing contract calls](/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/) _– Advanced Waffle tutorial covering dynamic mocking and inter-contract call testing._ -- [Waffle: Hello world with Hardhat and ethers.js](/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/) _– Set up your first Waffle project with Hardhat and ethers.js._ -- [Testing a simple smart contract with Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) _– A beginner's guide to testing smart contract balance changes and events with Waffle._ +- [How to develop and test a dApp on a local, multi-client testnet](/developers/tutorials/develop-and-test-dapps-with-a-multi-client-local-eth-testnet/) _– Walkthrough of deploying a smart contract to a local testnet and performing tests._ +- [How to mock Solidity smart contracts for testing](/developers/tutorials/how-to-mock-solidity-contracts-for-testing/) _– Intermediate tutorial on how to use mock data and implement unit testing._ +- [How to use Echidna to test smart contracts](/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/) _– Advanced approached to fuzzing and smart contract testing._ diff --git a/public/content/developers/docs/standards/tokens/erc-20/index.md b/public/content/developers/docs/standards/tokens/erc-20/index.md index c19c3abfe8e..605aef615e9 100644 --- a/public/content/developers/docs/standards/tokens/erc-20/index.md +++ b/public/content/developers/docs/standards/tokens/erc-20/index.md @@ -195,4 +195,3 @@ Some alternative standards have come out of this issue such as [ERC-223](/develo - [ERC-20 with Safety Rails](/developers/tutorials/erc20-with-safety-rails/) _– How to add safeguards to ERC-20 tokens to help users avoid common mistakes._ - [Sending Tokens Using ethers.js](/developers/tutorials/send-token-ethersjs/) _– A beginner-friendly guide to transferring ERC-20 tokens using ethers.js._ - [Some tricks used by scam tokens and how to detect them](/developers/tutorials/scam-token-tricks/) _– A deep-dive into scam ERC-20 token patterns and how to identify them._ -- [Testing ERC-20 tokens with Waffle](/developers/tutorials/testing-erc-20-tokens-with-waffle/) _– How to write and run tests for ERC-20 smart contracts using Waffle._ diff --git a/public/content/developers/tutorials/creating-a-wagmi-ui-for-your-contract/index.md b/public/content/developers/tutorials/creating-a-wagmi-ui-for-your-contract/index.md index e4cd858de94..4613c5a35a3 100644 --- a/public/content/developers/tutorials/creating-a-wagmi-ui-for-your-contract/index.md +++ b/public/content/developers/tutorials/creating-a-wagmi-ui-for-your-contract/index.md @@ -9,50 +9,47 @@ lang: en sidebarDepth: 3 --- -You found a feature we need in the Ethereum ecosystem. You wrote the smart contracts to implement it, and maybe even some related code that runs offchain. This is great! Unfortunately, without a user interface you aren't going to have any users, and the last time you wrote a web site people used dial-up modems and JavaScript was new. +You found a feature we need in the Ethereum ecosystem. You wrote the smart contracts to implement it, and maybe even some related code that runs offchain. This is great! Unfortunately, without a user interface you aren't going to have any users, and the last time you wrote a website people used dial-up modems and JavaScript was new. -This article is for you. I assume you know programming, and maybe a bit of JavaScript and HTML, but that your user interface skills are rusty and out of date. Together we will go over a simple modern application so you'll see how it's done these days. +This article is for you. I assume you know programming, and maybe a bit of JavaScript and HTML, but that your user interface skills are rusty and outdated. Together we will go over a simple modern application so you'll see how it's done these days. ## Why is this important {#why-important} -In theory, you could just have people use [Etherscan](https://holesky.etherscan.io/address/0x432d810484add7454ddb3b5311f0ac2e95cecea8#writeContract) or [Blockscout](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=write_contract) to interact with your contracts. That will be great for the experienced Ethereans. But we are trying to serve [another billion people](https://blog.ethereum.org/2021/05/07/ethereum-for-the-next-billion). This won't happen without a great user experience, and a friendly user interface is a big part of that. +In theory, you could just have people use [Etherscan](https://sepolia.etherscan.io/address/0xC87506C66c7896366b9E988FE0aA5B6dDE77CFfA#readContract) or [Blockscout](https://eth-sepolia.blockscout.com/address/0xC87506C66c7896366b9E988FE0aA5B6dDE77CFfA?tab=read_write_contract) to interact with your contracts. That is great for the experienced Ethereans. But we are trying to serve [another billion people](https://blog.ethereum.org/2021/05/07/ethereum-for-the-next-billion). This won't happen without a great user experience, and a friendly user interface is a big part of that. ## Greeter application {#greeter-app} -There is a lot of theory behind for a modern UI works, and [a lot of good sites](https://react.dev/learn/thinking-in-react) [that explain it](https://wagmi.sh/core/getting-started). Instead of repeating the fine work done by those sites, I'm going to assume you prefer to learn by doing and start with an application you can play with. You still need the theory to get things done, and we'll get to it - we'll just go source file by source file, and discuss things as we get to them. +There is a lot of theory behind how modern UI works, and [a lot of good sites](https://react.dev/learn/thinking-in-react) [that explain it](https://wagmi.sh/core/getting-started). Instead of repeating the fine work done by those sites, I'm going to assume you prefer to learn by doing and start with an application you can play with. You still need the theory to get things done, and we'll get to it - we'll just go source file by source file, and discuss things as we get to them. ### Installation {#installation} -1. If necessary, add [the Holesky blockchain](https://chainlist.org/?search=holesky&testnets=true) to your wallet and [get test ETH](https://www.holeskyfaucet.io/). +1. The application uses the [Sepolia](https://sepolia.dev/) test network. If necessary, [get Sepolia test ETH](/developers/docs/networks/#sepolia) and [add Sepolia to your wallet](https://chainlist.org/chain/11155111). -1. Clone the github repository. +2. Clone the GitHub repository and install the necessary packages. ```sh - git clone https://github.com/qbzzt/20230801-modern-ui.git + git clone https://github.com/qbzzt/260301-modern-ui-web3.git + cd 260301-modern-ui-web3 + npm install ``` -1. Install the necessary packages. +3. The application uses free access points, which have performance limitations. If you want to use a [Node as a service](/developers/docs/nodes-and-clients/nodes-as-a-service/) provider, replace the URLs in [`src/wagmi.ts`](#wagmi-ts). - ```sh - cd 20230801-modern-ui - pnpm install - ``` - -1. Start the application. +4. Start the application. ```sh - pnpm dev + npm run dev ``` -1. Browse to the URL shown by the application. In most cases, that is [http://localhost:5173/](http://localhost:5173/). +5. Browse to the URL shown by the application. In most cases, that is [http://localhost:5173/](http://localhost:5173/). -1. You can see the contract source code, a slightly modified version of Hardhat's Greeter, [on a blockchain explorer](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=contract). +6. You can see the contract source code, a modified version of Hardhat's Greeter, [on a blockchain explorer](https://eth-sepolia.blockscout.com/address/0xC87506C66c7896366b9E988FE0aA5B6dDE77CFfA?tab=contract_code). ### File walk through {#file-walk-through} #### `index.html` {#index-html} -This file is standard HTML boilerplate except for this line, which imports the script file. +This file is a standard HTML boilerplate except for this line, which imports the script file. ```html @@ -60,25 +57,43 @@ This file is standard HTML boilerplate except for this line, which imports the s #### `src/main.tsx` {#main-tsx} -The file extension tells us that this file is a [React component](https://www.w3schools.com/react/react_components.asp) written in [TypeScript](https://www.typescriptlang.org/), an extension of JavaScript that supports [type checking](https://en.wikipedia.org/wiki/Type_system#Type_checking). TypeScript is compiled into JavaScript, so we can use it for client-side execution. +The file extension indicates that this is a [React component](https://www.w3schools.com/react/react_components.asp) written in [TypeScript](https://www.typescriptlang.org/), an extension of JavaScript that supports [type checking](https://en.wikipedia.org/wiki/Type_system#Type_checking). TypeScript is compiled to JavaScript, so we can use it on the client side. + +This file is mostly explained in case you are interested. Usually you do not modify this file, but [`src/App.tsx`](#app-tsx) and the files it imports. ```tsx -import '@rainbow-me/rainbowkit/styles.css' -import { RainbowKitProvider } from '@rainbow-me/rainbowkit' -import * as React from 'react' -import * as ReactDOM from 'react-dom/client' -import { WagmiConfig } from 'wagmi' -import { chains, config } from './wagmi' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import React from 'react' +import ReactDOM from 'react-dom/client' +import { WagmiProvider } from 'wagmi' ``` Import the library code we need. ```tsx -import { App } from './App' +import App from './App.tsx' ``` Import the React component that implements the application (see below). +```tsx +import { config } from './wagmi.ts' +``` + +Import the [wagmi](https://wagmi.sh/) configuration, which includes the blockchain configuration. + +```tsx +const queryClient = new QueryClient() +``` + +Creates a new instance of [React Query’s](https://tanstack.com/query/latest/docs/framework/react/overview) cache manager. This object will store: + +- Cached RPC calls +- Contract reads +- Background refetching state + +We need the cache manager because wagmi v3 uses React Query internally. + ```tsx ReactDOM.createRoot(document.getElementById('root')!).render( ``` @@ -92,16 +107,16 @@ Create the root React component. The parameter to `render` is [JSX](https://www. The application is going inside [a `React.StrictMode` component](https://react.dev/reference/react/StrictMode). This component tells the React library to insert additional debugging checks, which is useful during development. ```tsx - + ``` -The application is also inside [a `WagmiConfig` component](https://wagmi.sh/react/api/WagmiProvider). [The wagmi (we are going to make it) library](https://wagmi.sh/) connects the React UI definitions with [the viem library](https://viem.sh/) for writing an Ethereum decentralized application. +The application is also inside [a `WagmiProvider` component](https://wagmi.sh/react/api/WagmiProvider). [The wagmi (we are going to make it) library](https://wagmi.sh/) connects the React UI definitions with [the viem library](https://viem.sh/) for writing an Ethereum decentralized application. ```tsx - + ``` -And finally, [a `RainbowKitProvider` component](https://www.rainbowkit.com/). This component handles logging on and the communication between the wallet and the application. +And finally, add a React Query provider so any application component can use cached queries. ```tsx @@ -110,8 +125,8 @@ And finally, [a `RainbowKitProvider` component](https://www.rainbowkit.com/). Th Now we can have the component for the application, which actually implements the UI. The `/>` at the end of the component tells React that this component doesn't have any definitions inside it, as per the XML standard. ```tsx - - + + , ) ``` @@ -121,67 +136,186 @@ Of course, we have to close off the other components. #### `src/App.tsx` {#app-tsx} ```tsx -import { ConnectButton } from '@rainbow-me/rainbowkit' -import { useAccount } from 'wagmi' -import { Greeter } from './components/Greeter' +import { + useConnect, + useConnection, + useDisconnect, + useSwitchChain +} from 'wagmi' + +import { useEffect } from 'react' +import { Greeter } from './Greeter' +``` + +Import the libraries we need, as well as [the `Greeter` component](#greeter-tsx). + +```tsx +const SEPOLIA_CHAIN_ID = 11155111 +``` + +The Sepolia chain ID. -export function App() { +``` +function App() { ``` -This is the standard way to create a React component - define a function that is called every time it needs to be rendered. This function typically has some TypeScript or JavaScript code on top, followed by a `return` statement that returns the JSX code. +This is the standard way to create a React component: define a function that is called whenever it needs to be rendered. This function typically contains TypeScript or JavaScript code, followed by a `return` statement that returns the JSX code. ```tsx - const { isConnected } = useAccount() + const connection = useConnection() ``` -Here we use [`useAccount`](https://wagmi.sh/react/api/hooks/useAccount) to check if we are connected to a blockchain through a wallet or not. +Use [`useConnection`](https://wagmi.sh/react/api/hooks/useConnection) to get information related to the current connection, such as the address and `chainId`. -By convention, in React functions called `use...` are [hooks](https://www.w3schools.com/react/react_hooks.asp) that return some kind of data. When you use such hooks, not only does your component get the data, but when that data changes the component is re-rendered with the updated information. +By convention, in React functions called `use...` are [hooks](https://www.w3schools.com/react/react_hooks.asp). These functions don't just return data to the component; they also ensure it is re-rendered (the component function is executed again, and its output replaces the previous one in the HTML) when that data changes. + +```tsx + const { connectors, connect, status, error } = useConnect() +``` + +Use [`useConnect`](https://wagmi.sh/react/api/hooks/useConnect) to get information about the wallet connection. + +```tsx + const { disconnect } = useDisconnect() +``` + +[This hook](https://wagmi.sh/react/api/hooks/useDisconnect) gives us the function to disconnect from the wallet. + +```tsx + const { switchChain } = useSwitchChain() +``` + +[This hook](https://wagmi.sh/react/api/hooks/useSwitchChain) lets us switch chains. + +```tsx + useEffect(() => { +``` + +The React hook [`useEffect`](https://react.dev/reference/react/useEffect) lets you run a function whenever the value of a variable changes to synchronize an external system. + +```tsx + if (connection.status === 'connected' && + connection.chainId !== SEPOLIA_CHAIN_ID + ) { + switchChain({ chainId: SEPOLIA_CHAIN_ID }) + } +``` + +If we are connected, but not to the Sepolia blockchain, switch to Sepolia. + +```tsx + }, [connection.status, connection.chainId]) +``` + +Rerun the function every time either the connection status or the connection chainId changes. ```tsx return ( <> ``` -The JSX of a React component _has_ to return one component. When we have multiple components and we don't have anything that wraps up "naturally" we use an empty component (`<> ... `) to make them into a single component. +The JSX of a React component _must_ return a single HTML component. When we have multiple components and don't need a container to wrap them all, we use an empty component (`<> ... `) to combine them into a single component. ```tsx -

Greeter

- +

Connection

+
+ status: {connection.status} +
+ addresses: {JSON.stringify(connection.addresses)} +
+ chainId: {connection.chainId} +
``` -We get [the `ConnectButton` component](https://www.rainbowkit.com/docs/connect-button) from RainbowKit. When we are not connected, it gives us a `Connect Wallet` button that opens a modal that explains wallets and lets you choose which one you use. When we are connected, it displays the blockchain we use, our account address, and our ETH balance. We can use these displays to switch network or to disconnect. +Provide information about the current connection. Within JSX, `{}` means to evaluate the expression as JavaScript. ```tsx - {isConnected && ( + {connection.status === 'connected' && ( ``` -When we need to insert actual JavaScript (or TypeScript that will be compiled to JavaScript) into a JSX, we use brackets (`{}`). - -The syntax `a && b` is short for [`a ? b : a`](https://www.w3schools.com/react/react_es6_ternary.asp). That is, if `a` is true it evaluates to `b` and otherwise it evaluates to `a` (which can be `false`, `0`, etc). This is an easy way to tell React that a component should only be displayed if a certain condition is fulfilled. +The syntax `{ && } means "if the condition is `true`, evaluate to the value; if it isn't, evaluate to `false`". -In this case, we only want to show the user `Greeter` if the user is connected to a blockchain. +This is the standard way to put if statements inside JSX. ```tsx +
+
+``` + +JSX follows the XML standard, which is stricter than HTML. If a tag does not have a corresponding end tag, it _must_ have a slash (`/`) at the end to terminate it. + +Here we have two such tags, `` (which actually contains the HTML code that talks to the contract) and [`
` for a horizontal line](https://www.w3schools.com/tags/tag_hr.asp). + +```tsx + +
+ )} +``` + +If the user clicks this button, call the `disconnect` function. + +```tsx + {connection.status !== 'connected' && ( +``` + +If we are _not_ connected, show the necessary options to connect to the wallet. + +```tsx +
+

Connect

+ {connectors.map((connector) => ( +``` + +In `connectors` we have a list of connectors. We use [`map`](https://www.w3schools.com/jsref/jsref_map.asp) to turn it into a list of JSX buttons to display. + +```tsx + + ))} +``` + +The connector buttons. + +```tsx +
{status}
+
{error?.message}
+
)} - - ) -} ``` -#### `src/components/Greeter.tsx` {#greeter-tsx} +Provide additional information. The expression syntax `?.` tells JavaScript that if the variable is defined, evaluate to that field. If the variable is not defined, then this expression evaluates to `undefined`. + +The expression `error.message`, when there is no error, would raise an exception. Using `error?.message` lets us avoid this issue. + +#### `src/Greeter.tsx` {#greeter-tsx} -This file contains most of the UI functionality. It includes definitions that would normally be in multiple files, but as this is a tutorial the program is optimized for being easy to understand the first time, rather than performance or ease of maintenance. +This file contains most of the UI functionality. It includes definitions that would normally be in multiple files, but as this is a tutorial, the program is optimized for being easy to understand the first time, rather than performance or ease of maintenance. ```tsx -import { useState, ChangeEventHandler } from 'react' -import { useNetwork, +import { + useState, + useEffect, + } from 'react' +import { useChainId, + useAccount, useReadContract, - usePrepareContractWrite, - useContractWrite, - useContractEvent - } from 'wagmi' + useWriteContract, + useWatchContractEvent, + useSimulateContract + } from 'wagmi' ``` We use these library functions. Again, they are explained below where they are used. @@ -194,14 +328,16 @@ import { AddressType } from 'abitype' ```tsx let greeterABI = [ - . - . - . + { "type": "function", "name": "greet", ... }, + { "type": "function", "name": "setGreeting", ... }, + { "type": "event", "name": "SetGreeting", ... }, ] as const // greeterABI ``` The ABI for the `Greeter` contract. -If you are developing the contracts and UI at the same time you'd normally put them in the same repository and use the ABI generated by the Solidity compiler as a file in your application. However, this is not necessary here because the contract is already developed and not going to change. +If you are developing the contracts and UI at the same time, you'd normally put them in the same repository and use the ABI generated by the Solidity compiler as a file in your application. However, this is not necessary here because the contract is already developed and will not change. + +We use [`as const`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) to tell TypeScript that this is a _real_ constant. Normally, when you specify in JavaScript `const x = {"a": 1}`, you can change the value in `x`, you just can't assign to it. ```tsx type AddressPerBlockchainType = { @@ -209,38 +345,57 @@ type AddressPerBlockchainType = { } ``` -TypeScript is strongly typed. We use this definition to specify the address in which the `Greeter` contract is deployed on different chains. The key is a number (the chainId), and the value is an `AddressType` (an address). +TypeScript is strongly typed. We use this definition to specify the address where the `Greeter` contract is deployed across different chains. The key is a number (the chainId), and the value is an `AddressType` (an address). ```tsx -const contractAddrs: AddressPerBlockchainType = { - // Holesky - 17000: '0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8', - +const contractAddrs : AddressPerBlockchainType = { // Sepolia - 11155111: '0x7143d5c190F048C8d19fe325b748b081903E3BF0' + 11155111: '0xC87506C66c7896366b9E988FE0aA5B6dDE77CFfA' } ``` -The address of the contract on the two supported networks: [Holesky](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=contact_code) and [Sepolia](https://eth-sepolia.blockscout.com/address/0x7143d5c190F048C8d19fe325b748b081903E3BF0?tab=contact_code). +The address of the contract on [Sepolia](https://eth-sepolia.blockscout.com/address/0xC87506C66c7896366b9E988FE0aA5B6dDE77CFfA?tab=contract). + +##### `Timer` component {#timer-component} -Note: There is actually a third definition, for Redstone Holesky, it will be explained below. +The `Timer` component shows the number of seconds since a given time. This is important for usability purposes. When users do something, they expect an immediate reaction. In blockchains, this is often impossible because nothing happens until a transaction is placed in a block. One solution is to show how long it has been since the user performed the action, so the user can decide whether the time required is reasonable. ```tsx -type ShowObjectAttrsType = { - name: string, - object: any +type TimerProps = { + lastUpdate: Date } ``` -This type is used as a parameter to the `ShowObject` component (explained later). It includes the name of the object and its value, which are displayed for debugging purposes. +The `Timer` component takes one parameter, `lastUpdate`, which is the time of the last action. + +```tsx +const Timer = ({ lastUpdate }: TimerProps) => { + const [_, setNow] = useState(new Date()) +``` + +We need to have state (a variable tied to the component) and update it for the component to work correctly. But we never need to read it, so don't bother to do a variable. + +```tsx + useEffect(() => { + const id = setInterval(() => setNow(new Date()), 1000) + return () => clearInterval(id) + }, []) +``` + +The [`setInterval`](https://www.w3schools.com/jsref/met_win_setinterval.asp) function lets us schedule a function to run periodically. In this case, every second. The function calls `setNow` to update the state, so the `Timer` component will be re-rendered. We wrap this inside [`useEffect`](https://react.dev/reference/react/useEffect) with an empty dependency list so it'll happen just once, rather than each time the component is rendered. ```tsx -type ShowGreetingAttrsType = { - greeting: string | undefined + const secondsSinceUpdate = Math.floor( + (Date.now() - lastUpdate.getTime()) / 1000 + ) + + return ( + {secondsSinceUpdate} seconds ago + ) } ``` -At any moment in time we may either know what the greeting is (because we read it from the blockchain) or not know (because we haven't received it yet). So it is useful to have a type that can be either a string or nothing. +Calculate the number of seconds since the last update and return it. ##### `Greeter` component {#greeter-component} @@ -248,35 +403,34 @@ At any moment in time we may either know what the greeting is (because we read i const Greeter = () => { ``` -Finally, we get the define the component. +Finally, we get to define the component. ```tsx - const { chain } = useNetwork() + const chainId = useChainId() + const account = useAccount() ``` -Information about the chain we are using, courtesy of [wagmi](https://wagmi.sh/react/hooks/useNetwork). -Because this is a hook (`use...`), every time this information changes the component gets redrawn. +Information about the chain and account we are using, courtesy of [wagmi](https://wagmi.sh/). Because this is a hook (`use...`), the component is re-rendered whenever this information changes. ```tsx - const greeterAddr = chain && contractAddrs[chain.id] + const greeterAddr = chainId && contractAddrs[chainId] ``` -The address of the Greeter contract, which varies by chain (and which is `undefined` if we don't have chain information or we are on a chain without that contract). +The address of the Greeter contract, which is `undefined` if we don't have chain information, or we are on a chain without that contract. ```tsx const readResults = useReadContract({ address: greeterAddr, abi: greeterABI, - functionName: "greet" , // No arguments - watch: true + functionName: "greet", // No arguments }) ``` -[The `useReadContract` hook](https://wagmi.sh/react/api/hooks/useReadContract) reads information from a contract. You can see exactly what information it returns expand `readResults` in the UI. In this case we want it to keep looking so we'll be informed when the greeting changes. - -**Note:** We could listen to [`setGreeting` events](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=logs) to know when the greeting changes and update that way. However, while it may be more efficient, it will not apply in all cases. When the user switches to a different chain the greeting also changes, but that change is not accompanied by an event. We could have one part of the code listening for events and another to identify chain changes, but that would be more complicated than just setting [the `watch` parameter](https://wagmi.sh/react/api/hooks/useReadContract#watch-optional). +[The `useReadContract` hook](https://wagmi.sh/react/api/hooks/useReadContract) calls the `greet` function of [the contract](https://eth-sepolia.blockscout.com/address/0xC87506C66c7896366b9E988FE0aA5B6dDE77CFfA?tab=contract). ```tsx + const [ currentGreeting, setCurrentGreeting ] = + useState("Please wait while we fetch the greeting from the blockchain...") const [ newGreeting, setNewGreeting ] = useState("") ``` @@ -290,277 +444,302 @@ The `useState` hook returns a list with two values: In this case, we are using a state variable for the new greeting the user wants to set. ```tsx - const greetingChange : ChangeEventHandler = (evt) => - setNewGreeting(evt.target.value) + const [ lastSetterAddress, setLastSetterAddress ] = useState("") ``` -This is the event handler for when the new greeting input field changes. The type, [`ChangeEventHandler`](https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/forms_and_events/), specifies that this is handler for a value change of an HTML input element. The `` part is used because this is a [generic type](https://www.w3schools.com/typescript/typescript_basic_generics.php). +If multiple users are using the same contract at the same time, they might overwrite each other's greetings. This would look to the users as if the application is malfunctioning. If the application shows who last set the greeting, the user will know it was someone else and that the application is working correctly. ```tsx - const preparedTx = usePrepareContractWrite({ - address: greeterAddr, - abi: greeterABI, - functionName: 'setGreeting', - args: [ newGreeting ] - }) - const workingTx = useContractWrite(preparedTx.config) + const [ status, setStatus ] = useState("") + const [ statusTime, setStatusTime ] = useState(new Date()) ``` -This is the process to submit a blockchain transaction from the client perspective: +Users like to see that their actions have an immediate effect. However, on a blockchain, this is not the case. These state variables let us at least display something to users so they'll know their action is in progress. -1. Send the transaction to a node in the blockchain using [`eth_estimateGas`](https://docs.alchemy.com/reference/eth-estimategas). -2. Wait for a response from the node. -3. When the response is received, ask the user to sign the transaction through the wallet. This step _has_ to happen after the node response is received because the user is shown the gas cost of the transaction before signing it. -4. Wait for the user for approve. -5. Send the transaction again, this time using [`eth_sendRawTransaction`](https://docs.alchemy.com/reference/eth-sendrawtransaction). +```tsx + useEffect(() => { + if (readResults.data) { + setCurrentGreeting(readResults.data) + setStatus("Greeting fetched from blockchain") + } + }, [readResults.data]) +``` + +If `readResults` above changes the data and it's not set to a false value (`undefined`, for example), update the current greeting to the one read from the blockchain. Also, update the status. -Step 2 is likely to take a perceptible amount of time, during which users would wonder if their command was really received by the user interface and why they aren't being asked to sign the transaction already. That makes for bad user experience (UX). +```tsx + useWatchContractEvent({ + address: greeterAddr, + abi: greeterABI, + eventName: 'SetGreeting', + chainId, +``` -The solution is to use [prepare hooks](https://wagmi.sh/react/prepare-hooks). Every time that a parameter changes, immediately send the node the `eth_estimateGas` request. Then, when the user actually wants to send the transaction (in this case by pressing **Update greeting**), the gas cost is known and the user can see the wallet page immediately. +Listen to `SetGreeting` events. ```tsx - return ( + enabled: !!greeterAddr, ``` -Now we can finally create the actual HTML to return. +`!!` means that if the value is `false`, or a value that evaluates as false, such as `undefined`, `0`, or an empty string, the expression overall is `false`. For any other value, it is `true`. It's a way to convert values to booleans, because if there is no `greeterAddr`, we don't want to listen to events. ```tsx - <> -

Greeter

- { - !readResults.isError && !readResults.isLoading && - - } -
+ onLogs: logs => { + const greetingFromContract = logs[0].args.greeting + setCurrentGreeting(greetingFromContract) + setLastSetterAddress(logs[0].args.sender) + updateStatus("Greeting updated by event") + }, + }) ``` -Create a `ShowGreeting` component (explained below), but only if the greeting was read successfully from the blockchain. +When we see logs (which happens when we see a new event), it means that the greeting has been modified. In that case, we can update `currentGreeting` and `lastSetterAddress` to the new values. Also, we want to update the status display. ```tsx - + const updateStatus = (newStatus: string) => { + setStatus(newStatus) + setStatusTime(new Date()) + } ``` -This is the input text field where the user can set a new greeting. Every time the user presses a key, we call `greetingChange` which calls `setNewGreeting`. As `setNewGreeting` comes from the `useState` hook, it causes the `Greeter` component to be rendered again. This means that: +When we update the status we want to do two things: -- We need to specify `value` to keep the value of the new greeting, because otherwise it would turn back into the default, the empty string. -- `usePrepareContractWrite` is called every time `newGreeting` changes, which means it is always going to have the latest `newGreeting` in the prepared transaction. +1. Update the status string (`status`) +2. Update the time of last status update (`statusTime`) to now. ```tsx - + const greetingChange = (evt) => + setNewGreeting(evt.target.value) ``` -If there is no `workingTx.write` then we are still waiting for information necessary for sending the greeting update, so the button is disabled. If there is a `workingTx.write` value then that is the function to call to send the transaction. +This is the event handler for changes to the new greeting input field. We could specify the type of the `evt` parameter, but TypeScript is a type optional language. As this function is called only once, in an HTML event handler, I don't think it is necessary. ```tsx -
- - - - - ) -} + const { writeContractAsync } = useWriteContract() +``` + +The function to write to a contract. It is similar to [`writeContracts`](https://wagmi.sh/core/api/actions/writeContracts#writecontracts), but enables better status updates. + +```tsx + const simulation = useSimulateContract({ + address: greeterAddr, + abi: greeterABI, + functionName: 'setGreeting', + args: [newGreeting], + account: account.address + }) ``` -Finally, to help you see what we're doing, show the three objects we use: +This is the process to submit a blockchain transaction from the client perspective: -- `readResults` -- `preparedTx` -- `workingTx` +1. Send the transaction to a node in the blockchain using [`eth_estimateGas`](https://docs.alchemy.com/reference/eth-estimategas). +2. Wait for a response from the node. +3. When the response is received, ask the user to sign the transaction through the wallet. This step _has_ to happen after the node response is received because the user is shown the gas cost of the transaction before signing it. +4. Wait for the user to approve. +5. Send the transaction again, this time using [`eth_sendRawTransaction`](https://docs.alchemy.com/reference/eth-sendrawtransaction). -##### `ShowGreeting` component {#showgreeting-component} +Step 2 is likely to take a perceptible amount of time, during which users may wonder whether their command was received by the user interface and why they aren't being asked to sign the transaction yet. That creates a poor user experience (UX). -This component shows +One solution is to send out `eth_estimateGas` every time that a parameter changes. Then, when the user actually wants to send the transaction (in this case by pressing **Update greeting**), the gas cost is known, and the user can see the wallet page immediately. ```tsx -const ShowGreeting = (attrs : ShowGreetingAttrsType) => { + return ( ``` -A component function receives a parameter with all the attributes of the component. +Now we can finally create the actual HTML to return. ```tsx - return {attrs.greeting} -} + <> +

Greeter

+ {currentGreeting} ``` -##### `ShowObject` component {#showobject-component} - -For information purposes, we use the `ShowObject` component to show the important objects (`readResults` for reading the greeting and `preparedTx` and `workingTx` for transactions we create). +Show the current greeting. ```tsx -const ShowObject = (attrs: ShowObjectAttrsType ) => { - const keys = Object.keys(attrs.object) - const funs = keys.filter(k => typeof attrs.object[k] == "function") - return <> -
+ {lastSetterAddress && ( +

Last updated by { + lastSetterAddress === account.address ? "you" : lastSetterAddress + }

+ )} ``` -We don't want to clutter the UI with all the information, so to make it possible to view them or close them, we use a [`details`](https://www.w3schools.com/tags/tag_details.asp) tag. +If we know who set the greeting last, display that information. `Greeter` does not keep track of this information, and we don't want to look back for `SetGreeting` events, so we only get it once the greeting is changed while we are running. ```tsx - {attrs.name} -
-        {JSON.stringify(attrs.object, null, 2)}
+      
+ +
``` -Most of the fields are displayed using [`JSON.stringify`](https://www.w3schools.com/js/js_json_stringify.asp). +This is the input text field where the user can set a new greeting. Every time the user presses a key, we call `greetingChange`, which calls `setNewGreeting`. Since `setNewGreeting` comes from `useState`, it causes the `Greeter` component to be re-rendered. This means that: + +- We need to specify `value` to keep the value of the new greeting, because otherwise it would turn back into the default, the empty string. +- `simulation` is also updated every time `newGreeting` changes, which means that we'll get a simulation with the correct greeting. This could be relevant because the gas cost depends on the size of the call data, which depends on the length of the string. ```tsx -
- { funs.length > 0 && - <> - Functions: -
    + + ``` -React requires tags in the [DOM Tree](https://www.w3schools.com/js/js_htmldom.asp) to have distinct identifiers. This means that children of the same tag (in this case, [the unordered list](https://www.w3schools.com/tags/tag_ul.asp)), need different `key` attributes. +`writeContractAsync` only returns after the transaction is actually sent. This lets us show the user how long the transaction has been waiting to be included in the blockchain. ```tsx -
- - } -
- +

Status: {status}

+

Updated

+ + ) } ``` -End the various HTML tags. - -##### The final `export` {#the-final-export} +Show the status and how long it has been since it was updated. -```tsx -export { Greeter } +``` +export {Greeter} ``` -The `Greeter` component is the one we need to export for the application. +Export the component. #### `src/wagmi.ts` {#wagmi-ts} -Finally, various definitions related to WAGMI are in `src/wagmi.ts`. I am not going to explain everything here, because most of it is boilerplate you are unlikely to need to change. - -The code here isn't exactly the same as [on github](https://github.com/qbzzt/20230801-modern-ui/blob/main/src/wagmi.ts) because later in the article we add another chain ([Redstone Holesky](https://redstone.xyz/docs/network-info)). +Finally, various definitions related to wagmi are in `src/wagmi.ts`. I am not going to explain everything here, because most of it is boilerplate you are unlikely to need to change. ```ts -import { getDefaultWallets } from '@rainbow-me/rainbowkit' -import { configureChains, createConfig } from 'wagmi' -import { holesky, sepolia } from 'wagmi/chains' +import { http, webSocket, createConfig, fallback } from 'wagmi' +import { sepolia } from 'wagmi/chains' +import { injected } from 'wagmi/connectors' + +export const config = createConfig({ + chains: [sepolia], ``` -Import the blockchains the application supports. You can see the list of supported chains [in the viem github](https://github.com/wagmi-dev/viem/tree/main/src/chains/definitions). +The wagmi configuration includes the chains supported by this application. You can see the [list of available chains](https://wagmi.sh/core/api/chains). ```ts -import { publicProvider } from 'wagmi/providers/public' - -const walletConnectProjectId = 'c96e690bb92b6311e8e9b2a6a22df575' + connectors: [ + injected(), + ], ``` -To be able to use [WalletConnect](https://walletconnect.com/) you need a project ID for your application. You can get it [on cloud.walletconnect.com](https://cloud.walletconnect.com/sign-in). +[This connector](https://wagmi.sh/core/api/connectors/injected) lets us talk to a wallet installed in the browser. ```ts -const { chains, publicClient, webSocketPublicClient } = configureChains( - [ holesky, sepolia ], - [ - publicProvider(), - ], -) + transports: { + [sepolia.id]: http() +``` -const { connectors } = getDefaultWallets({ - appName: 'My wagmi + RainbowKit App', - chains, - projectId: walletConnectProjectId, -}) +The default HTTP endpoint that comes with Viem is good enough. If we want a different URL, we can use `http("https:// hostname ")` or `webSocket("wss:// hostname ")`. -export const config = createConfig({ - autoConnect: true, - connectors, - publicClient, - webSocketPublicClient, +```ts + }, + multiInjectedProviderDiscovery: false, }) - -export { chains } ``` -### Adding another blockchain {#add-blockchain} - -These days there are a lot of [L2 scaling solution](/layer-2/), and you might want to support some that viem does not support yet. To do it, you modify `src/wagmi.ts`. These instructions explain how to add [Redstone Holesky](https://redstone.xyz/docs/network-info). - -1. Import the `defineChain` type from viem. - - ```ts - import { defineChain } from 'viem' - ``` - -1. Add the network definition. - - ```ts - const redstoneHolesky = defineChain({ - id: 17_001, - name: 'Redstone Holesky', - network: 'redstone-holesky', - nativeCurrency: { - decimals: 18, - name: 'Ether', - symbol: 'ETH', - }, - rpcUrls: { - default: { - http: ['https://rpc.holesky.redstone.xyz'], - webSocket: ['wss://rpc.holesky.redstone.xyz/ws'], - }, - public: { - http: ['https://rpc.holesky.redstone.xyz'], - webSocket: ['wss://rpc.holesky.redstone.xyz/ws'], - }, - }, - blockExplorers: { - default: { name: 'Explorer', url: 'https://explorer.holesky.redstone.xyz' }, - }, - }) - ``` - -1. Add the new chain to the `configureChains` call. +## Adding another blockchain {#add-blockchain} + +These days there are a lot of [L2 scaling solutions](https://ethereum.org/layer-2/), and you might want to support some that viem does not support yet. To do it, you modify `src/wagmi.ts`. These instructions explain how to add [Optimism Sepolia](https://chainlist.org/chain/11155420). + +1. Edit `src/wagmi.ts` + + A. Import the `defineChain` type from viem. + + ```ts + import { defineChain } from 'viem' + ``` + + B. Add the network definition. You don't really need to do this for Optimism Sepolia, [it is already in `viem`](https://github.com/wevm/viem/blob/main/src/chains/definitions/optimismSepolia.ts), but this way you learn how to add a blockchain that is not in `viem`. + + ```ts + const optimismSepolia = defineChain({ + id: 11_155_420, + name: 'OP Sepolia', + nativeCurrency: { name: 'Sepolia Ether', symbol: 'ETH', decimals: 18 }, + rpcUrls: { + default: { + http: ['https://sepolia.optimism.io'], + webSocket: ['wss://optimism-sepolia.drpc.org'], + }, + }, + blockExplorers: { + default: { + name: 'Blockscout', + url: 'https://optimism-sepolia.blockscout.com', + apiUrl: 'https://optimism-sepolia.blockscout.com/api', + } + }, + }) + ``` + + C. Add the new chain to the `createConfig` call. + + ```ts + export const config = createConfig({ + chains: [sepolia, optimismSepolia], + connectors: [ + injected(), + ], + transports: { + [optimismSepolia.id]: http(), + [sepolia.id]: http() + }, + multiInjectedProviderDiscovery: false, + }) + ``` + +2. Edit `src/App.tsx` to comment out the automatic switch to Sepolia. On a production system, you'd probably show buttons with links to each of the blockchains you support. - ```ts - const { chains, publicClient, webSocketPublicClient } = configureChains( - [ holesky, sepolia, redstoneHolesky ], - [ publicProvider(), ], - ) - ``` + ```ts + /* + useEffect(() => { + if (connection.status === 'connected' && + connection.chainId !== SEPOLIA_CHAIN_ID + ) { + switchChain({ chainId: SEPOLIA_CHAIN_ID }) + } + }, [connection.status, connection.chainId]) + */ + ``` -1. Ensure that the application knows the address for your contracts on the new network. In this case, we modify `src/components/Greeter.tsx`: +3. Edit `src/Greeter.tsx` to ensure that the application knows the address for your contracts on the new network. ```ts - const contractAddrs : AddressPerBlockchainType = { - // Holesky - 17000: '0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8', - - // Redstone Holesky - 17001: '0x4919517f82a1B89a32392E1BF72ec827ba9986D3', + const contractAddrs: AddressPerBlockchainType = { + // Optimism Sepolia + 11155420: "0x4dd85791923E9294E934271522f63875EAe5806f", // Sepolia - 11155111: '0x7143d5c190F048C8d19fe325b748b081903E3BF0' + 11155111: "0x7143d5c190F048C8d19fe325b748b081903E3BF0", } ``` +4. In your browser. + + A. Browse to [ChainList](https://chainlist.org/chain/11155420?testnets=true) and click one of buttons on the right side of the table to add the chain to your wallet. + + B. In the application, **Disconnect** and then reconnect to change the blockchain. There are nicer ways to handle this, but they'd require application changes. + ## Conclusion {#conclusion} Of course, you don't really care about providing a user interface for `Greeter`. You want to create a user interface for your own contracts. To create your own application, run these steps: @@ -568,18 +747,17 @@ Of course, you don't really care about providing a user interface for `Greeter`. 1. Specify to create a wagmi application. ```sh copy - pnpm create wagmi + npm create wagmi ``` -1. Name the application. +2. Type `y` to proceed. -1. Select **React** framework. +3. Name the application. -1. Select the **Vite** variant. +4. Select **React** framework. -1. You can [add Rainbow kit](https://www.rainbowkit.com/docs/installation#manual-setup). +5. Select the **Vite** variant. Now go and make your contracts usable for the wide world. [See here for more of my work](https://cryptodocguy.pro/). - diff --git a/public/content/developers/tutorials/hello-world-smart-contract-fullstack/index.md b/public/content/developers/tutorials/hello-world-smart-contract-fullstack/index.md index 56b1e6c1b18..bbbf935bc4b 100644 --- a/public/content/developers/tutorials/hello-world-smart-contract-fullstack/index.md +++ b/public/content/developers/tutorials/hello-world-smart-contract-fullstack/index.md @@ -241,7 +241,7 @@ Do not name it `process.env` or `.env-custom` or anything else. - Follow [these instructions](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key) to export your private key - See below to get HTTP Alchemy API URL -![](./get-alchemy-api-key.gif) +![Animated walkthrough of getting an Alchemy API key](./get-alchemy-api-key.gif) Your `.env` should look like this: diff --git a/public/content/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md b/public/content/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md index 32237055abb..40503111b14 100644 --- a/public/content/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md +++ b/public/content/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md @@ -62,13 +62,13 @@ This will yield the same information as provided on Etherscan's transaction page #### Etherscan {#etherscan} -![](./etherscan_view.png) +![Screenshot of Etherscan transaction explorer view](./etherscan_view.png) [EF's contract page on Blockscout.](https://eth.blockscout.com/address/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe) #### Dune Analytics {#dune-analytics} -![](./dune_view.png) +![Screenshot of a Dune Analytics query dashboard](./dune_view.png) You can find dashboard [here](https://dune.com/paulapivat/Learn-Ethereum). Click on the table to see the query (also see above). @@ -146,7 +146,7 @@ ORDER BY block_time DESC` Here's the SQL output on Dune: -![](./list_of_txn.png) +![Screenshot of a list of Ethereum transactions](./list_of_txn.png) This single block being added to the chain changes the state of the Ethereum virtual machine ([EVM](/developers/docs/evm/)). Dozens sometimes, hundreds of transactions are verified at once. In this specific case, 222 transactions were included. @@ -165,7 +165,7 @@ FROM temp_table For block 12396854, out of 222 total transactions, 204 were successfully verified: -![](./successful_txn.png) +![Screenshot of a successful Ethereum transaction](./successful_txn.png) Transactions requests occur dozens of times per second, but blocks are committed approximately once every 15 seconds ([source](/developers/docs/blocks/)). @@ -173,11 +173,11 @@ To see that there is one block produced approximately every 15 seconds, we could The chart for Ethereum blocks produced per day (2016 - present) is: -![](./daily_blocks.png) +![Chart showing daily Ethereum block production](./daily_blocks.png) The average number of blocks produced daily over this time period is ~5,874: -![](./avg_daily_blocks.png) +![Chart showing daily Ethereum block production](./avg_daily_blocks.png) The queries are: @@ -214,7 +214,7 @@ Blocks are bounded in size. The maximum block size is dynamic and varies accordi One way to conceptualize block gas limit is to think of it as the **supply** of available block space in which to batch transactions. The block gas limit can be queried and visualized from 2016 to present day: -![](./avg_gas_limit.png) +![Chart showing average Ethereum gas limit over time](./avg_gas_limit.png) ```sql SELECT @@ -227,7 +227,7 @@ OFFSET 1 Then there is the actual gas used daily to pay for computing done on the Ethereum chain (i.e., sending transaction, calling a smart contract, minting an NFT). This is the **demand** for available Ethereum block space: -![](./daily_gas_used.png) +![Chart showing daily Ethereum gas used](./daily_gas_used.png) ```sql SELECT @@ -246,7 +246,7 @@ Therefore we can understand gas prices as a function of demand for Ethereum bloc Finally, we may want to query average daily gas prices for the Ethereum chain, however, doing so will result in an especially long query time, so we’ll filter our query to the average amount of gas paid per transaction by the Ethereum Foundation. -![](./ef_daily_gas.png) +![Chart showing Ethereum Foundation daily gas usage](./ef_daily_gas.png) We can see gas prices paid for all transactions made to the Ethereum Foundation address over the years. Here is the query: diff --git a/public/content/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md b/public/content/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md index 6150bde46af..497b460ede3 100644 --- a/public/content/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md +++ b/public/content/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md @@ -117,35 +117,35 @@ sudo systemctl start grafana-server When you've got Grafana running, it should be reachable at `localhost:3000`. Use your preferred browser to access this path, then login with the default credentials (user: `admin` and password: `admin`). When prompted, change the default password and save. -![](./grafana1.png) +![Grafana dashboard screenshot for Geth monitoring (panel 1)](./grafana1.png) You will be redirected to the Grafana home page. First, set up your source data. Click on the configuration icon in the left bar and select "Data sources". -![](./grafana2.png) +![Grafana dashboard screenshot for Geth monitoring (panel 2)](./grafana2.png) There aren't any data sources created yet, click on "Add data source" to define one. -![](./grafana3.png) +![Grafana dashboard screenshot for Geth monitoring (panel 3)](./grafana3.png) For this setup, select "InfluxDB" and proceed. -![](./grafana4.png) +![Grafana dashboard screenshot for Geth monitoring (panel 4)](./grafana4.png) Data source configuration is pretty straight forward if you are running tools on the same machine. You need to set the InfluxDB address and details for accessing the database. Refer to the picture below. -![](./grafana5.png) +![Grafana dashboard screenshot for Geth monitoring (panel 5)](./grafana5.png) If everything is complete and InfluxDB is reachable, click on "Save and test" and wait for the confirmation to pop up. -![](./grafana6.png) +![Grafana dashboard screenshot for Geth monitoring (panel 6)](./grafana6.png) Grafana is now set up to read data from InfluxDB. Now you need to create a dashboard which will interpret and display it. Dashboards properties are encoded in JSON files which can be created by anybody and easily imported. On the left bar, click on "Create and Import". -![](./grafana7.png) +![Grafana dashboard screenshot for Geth monitoring (panel 7)](./grafana7.png) For a Geth monitoring dashboard, copy the ID of [this dashboard](https://grafana.com/grafana/dashboards/13877/) and paste it in the "Import page" in Grafana. After saving the dashboard, it should look like this: -![](./grafana8.png) +![Grafana dashboard screenshot for Geth monitoring (panel 8)](./grafana8.png) You can modify your dashboards. Each panel can be edited, moved, removed or added. You can change your configurations. It's up to you! To learn more about how dashboards work, refer to [Grafana's documentation](https://grafana.com/docs/grafana/latest/dashboards/). You might also be interested in [Alerting](https://grafana.com/docs/grafana/latest/alerting/). This lets you set up alert notifications for when metrics reach certain values. Various communication channels are supported. diff --git a/public/content/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index 00a9ba4938c..00000000000 --- a/public/content/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1147 +0,0 @@ ---- -title: Testing ERC-20 tokens with Waffle -description: Learn how test Solidity smart contracts and use smart contract matchers with Waffle. -author: Vladislav Starostenko -tags: ["waffle", "smart contracts", "solidity", "testing", "erc-20"] -skill: intermediate -lang: en -published: 2020-10-16 ---- - -In this tutorial you will learn how to: - -- Write tests for smart contracts with Waffle -- Use some popular matchers to test smart contracts with Waffle - -Assumptions: - -- you can get around in a terminal, -- you can create a new `JavaScript` project, -- you've written a few lines of `Solidity` code, -- you've written a few tests in `JavaScript`, -- you’ve used `yarn` or `npm`, JavaScripts’s package installer. - -Again, if any of these are untrue, or you don’t plan to reproduce the code in this article, you can likely still follow along just fine. - -## A few words about Waffle {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io) is the most advanced library for writing and testing smart contracts. - -Works with the [JavaScript API](/developers/docs/apis/javascript/) ethers-js. - -You can read more details in the [Waffle documentation](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation) ! - -## The quick tutorial {#the-quick-tutorial} - -First things first, create new `JavaScript` or `TypeScript` project ( I'll use `TS`, but if you use `JS` it's not a problem ) : - -Somewhat like this : - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## Step #1: Install waffle in your project [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) {#step-1-install-waffle-in-your-project} - -To get started, install `ethereum-waffle`. In this tutorial, I'll use `yarn`, so to install `ethereum-waffle` run: - -```bash - yarn add --dev ethereum-waffle -``` - -## Step #2: Write a smart contract [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract) {#step-2-write-a-smart-contract} - -In this tutorial, I'll use [ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol) token from [OpenZeppelin](https://openzeppelin.com). - -So, add `OpenZeppelin` by installing it with `yarn`: - -```bash - yarn add @openzeppelin/contracts -D -``` - -Then create `BasicToken.sol` contract in `src` directory: - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Example class - a mock class derived from ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## Step #3: Compile your smart contract [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) {#step-3-compile-your-smart-contract} - -To compile your smart contract add the following entry in the `package.json` of your project : - -```json -{ - "scripts": { - "build": "waffle" - } -} -``` - -Also, add `waffle.json` file in the main directory of your project. - -An example of `waffle.json` configuration: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -You can read more about the Waffle configuration [here](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration). - -Then just run `yarn build` to compile your smart contract. - -You should see that Waffle compiled your contract and placed the resulting JSON output inside the `build` directory. - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;142:152:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2219:81:2;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;2219:81:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4255:166;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;4255:166:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;3262:98;;;:::i;:::-;;;;;;;;;;;;;;;;;;;4881:317;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;4881:317:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;3121:81;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;5593:215;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;5593:215:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;3418:117;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;3418:117:2;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;2413:85;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;2413:85:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6295:266;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;6295:266:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;3738:172;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;3738:172:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;3968:149;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;3968:149:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;2219:81;2256:13;2288:5;2281:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2219:81;:::o;4255:166::-;4338:4;4354:39;4363:12;:10;:12::i;:::-;4377:7;4386:6;4354:8;:39::i;:::-;4410:4;4403:11;;4255:166;;;;:::o;3262:98::-;3315:7;3341:12;;3334:19;;3262:98;:::o;4881:317::-;4987:4;5003:36;5013:6;5021:9;5032:6;5003:9;:36::i;:::-;5049:121;5058:6;5066:12;:10;:12::i;:::-;5080:89;5118:6;5080:89;;;;;;;;;;;;;;;;;:11;:19;5092:6;5080:19;;;;;;;;;;;;;;;:33;5100:12;:10;:12::i;:::-;5080:33;;;;;;;;;;;;;;;;:37;;:89;;;;;:::i;:::-;5049:8;:121::i;:::-;5187:4;5180:11;;4881:317;;;;;:::o;3121:81::-;3162:5;3186:9;;;;;;;;;;;3179:16;;3121:81;:::o;5593:215::-;5681:4;5697:83;5706:12;:10;:12::i;:::-;5720:7;5729:50;5768:10;5729:11;:25;5741:12;:10;:12::i;:::-;5729:25;;;;;;;;;;;;;;;:34;5755:7;5729:34;;;;;;;;;;;;;;;;:38;;:50;;;;:::i;:::-;5697:8;:83::i;:::-;5797:4;5790:11;;5593:215;;;;:::o;3418:117::-;3484:7;3510:9;:18;3520:7;3510:18;;;;;;;;;;;;;;;;3503:25;;3418:117;;;:::o;2413:85::-;2452:13;2484:7;2477:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2413:85;:::o;6295:266::-;6388:4;6404:129;6413:12;:10;:12::i;:::-;6427:7;6436:96;6475:15;6436:96;;;;;;;;;;;;;;;;;:11;:25;6448:12;:10;:12::i;:::-;6436:25;;;;;;;;;;;;;;;:34;6462:7;6436:34;;;;;;;;;;;;;;;;:38;;:96;;;;;:::i;:::-;6404:8;:129::i;:::-;6550:4;6543:11;;6295:266;;;;:::o;3738:172::-;3824:4;3840:42;3850:12;:10;:12::i;:::-;3864:9;3875:6;3840:9;:42::i;:::-;3899:4;3892:11;;3738:172;;;;:::o;3968:149::-;4057:7;4083:11;:18;4095:5;4083:18;;;;;;;;;;;;;;;:27;4102:7;4083:27;;;;;;;;;;;;;;;;4076:34;;3968:149;;;;:::o;590:104:0:-;643:15;677:10;670:17;;590:104;:::o;9357:340:2:-;9475:1;9458:19;;:5;:19;;;;9450:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9555:1;9536:21;;:7;:21;;;;9528:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9637:6;9607:11;:18;9619:5;9607:18;;;;;;;;;;;;;;;:27;9626:7;9607:27;;;;;;;;;;;;;;;:36;;;;9674:7;9658:32;;9667:5;9658:32;;;9683:6;9658:32;;;;;;;;;;;;;;;;;;9357:340;;;:::o;7035:530::-;7158:1;7140:20;;:6;:20;;;;7132:70;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7241:1;7220:23;;:9;:23;;;;7212:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7294:47;7315:6;7323:9;7334:6;7294:20;:47::i;:::-;7372:71;7394:6;7372:71;;;;;;;;;;;;;;;;;:9;:17;7382:6;7372:17;;;;;;;;;;;;;;;;:21;;:71;;;;;:::i;:::-;7352:9;:17;7362:6;7352:17;;;;;;;;;;;;;;;:91;;;;7476:32;7501:6;7476:9;:20;7486:9;7476:20;;;;;;;;;;;;;;;;:24;;:32;;;;:::i;:::-;7453:9;:20;7463:9;7453:20;;;;;;;;;;;;;;;:55;;;;7540:9;7523:35;;7532:6;7523:35;;;7551:6;7523:35;;;;;;;;;;;;;;;;;;7035:530;;;:::o;1746:187:1:-;1832:7;1864:1;1859;:6;;1867:12;1851:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;1851:29:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1890:9;1906:1;1902;:5;1890:17;;1925:1;1918:8;;;1746:187;;;;;:::o;874:176::-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;10695:92:2:-;;;;:::o" - } - }, - "bytecode": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033" - } -``` - -
- -## Step #4: Test your smart contract [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-test-your-smart-contract} - -### Step #4.1 Install necessary dependencies [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-1} - -After we have successfully authored a Smart Contract we can test it. We will use `Waffle` to do it. - -Tests in `Waffle` are written using `Mocha` alongside with `Chai`. We can use a different test environment, but `Waffle` matchers only work with `Chai`. - -So, we need to add `Chai` to our dependencies : - -```bash - yarn add --dev mocha chai -``` - -### Step #4.2 Create test file [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-2} - -To write our test we need to create `BasicToken.test.ts` file in our test directory. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -So, we use `deployContract` method from `Waffle` to deploy our token. As arguments, we should pass `wallet`, the compiled json file of our contract and default balance. - -`Waffle` also allows us to create a `wallet`, which makes it very easy to deploy a contract. - -You can read more about `wallet` [here](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets) and you can read more about the deploying function [here](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts). - -Let's write a simple test to check balance of our wallet. Since we submitted the value 1000 during the deployment our contract, the balance of our wallet must be 1000 tokens, which we can check in the first test. - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -To run the test use `yarn test` - -### Step #4.3 Emitting events [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events) {#step-4-3} - -In this tutorial, I want to show you the most useful matchers of `Waffle`, so let's start with the first one. - -`Waffle` allows us to test what events where emitted. - -In this tutorial, I'll test the `transfer` method of our contract. - -In this test, I'll make a transfer from one wallet to another and check whether the `Transfer` event was called. - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -Also, a big advantage of this matcher is that we can check which arguments this event was called with by adding `withArgs` to our test. - -This will allow us to be sure that our function is being called correctly! - -### Step #4.4 Revert with message [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message) {#step-4-4} - -`Waffle` allows us to test what message it was reverted with. - -We will use `revertedWith` matcher in our test to check it. - -We can write a test in which we will perform a transfer for an amount greater than we have on our wallet. -And then we'll check if the transaction reverted with the exact message! - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### Step #4.5 Change-token-balance [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance) {#step-4-5} - -`Waffle` allows us to check for changes in the balances of the wallets! - -We can use the `changeTokenBalance` matcher to check the balance change or the `changeTokenBalances` for a multiple account. - -The matcher can accept `numbers`, `strings` and `BigNumbers` as a balance change, while the address should be specified as a wallet or a contract. - -Let's write the next test: - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -The above is a test for a single wallet. - -And the next one for multiple wallets: - -```ts -it("Send transaction changes sender and receiver balances", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalances([wallet, walletTo], [-200, 200]) -}) -``` - -The transaction is expected to be passed as a callback (we need to check the balance before the call) or as a transaction response. - -## Congratulations {#congratulations} - -**Congratulations! You've made it through my tutorial. You've taken your first big step towards testing smart contracts with Waffle.** - -**Code from this tutorial you can be find [here](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website).** - -**More documentation about `Waffle` available [here](https://getwaffle.io).** diff --git a/public/content/developers/tutorials/the-graph-fixing-web3-data-querying/index.md b/public/content/developers/tutorials/the-graph-fixing-web3-data-querying/index.md index 575b9069f03..23bc8eeec99 100644 --- a/public/content/developers/tutorials/the-graph-fixing-web3-data-querying/index.md +++ b/public/content/developers/tutorials/the-graph-fixing-web3-data-querying/index.md @@ -83,7 +83,7 @@ First let's talk about GraphQL, originally designed and implemented by Facebook. ![GraphQL API vs. REST API](./graphql.jpg) -![](./graphql-query.gif) +![Animated demonstration of a GraphQL query in The Graph playground](./graphql-query.gif) The two images pretty much capture the essence of GraphQL. With the query on the right we can define exactly what data we want, so there we get everything in one request and nothing more than exactly what we need. A GraphQL server handles the fetching of all data required, so it is incredibly easy for the frontend consumer side to use. [This is a nice explanation](https://www.apollographql.com/blog/graphql-explained) of how exactly the server handles a query if you're interested. diff --git a/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index d7b3901c96c..00000000000 --- a/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,293 +0,0 @@ ---- -title: "Waffle: Dynamic mocking and testing contract calls" -description: Advanced Waffle tutorial for using dynamic mocking and testing contract calls -author: "Daniel Izdebski" -tags: ["waffle", "smart contracts", "solidity", "testing", "mocking"] -skill: intermediate -lang: en -published: 2020-11-14 ---- - -## What is this tutorial about? {#what-is-this-tutorial-about} - -In this tutorial you will learn how to: - -- use dynamic mocking -- test interactions between smart contracts - -Assumptions: - -- you already know how to write a simple smart contract in `Solidity` -- you know your way around `JavaScript` and `TypeScript` -- you've done other `Waffle` tutorials or know a thing or two about it - -## Dynamic mocking {#dynamic-mocking} - -Why is dynamic mocking useful? Well, it allows us to write unit tests instead of integration tests. What does it mean? It means that we don't have to worry about smart contracts' dependencies, thus we can test all of them in complete isolation. Let me show you how exactly you can do it. - -### **1. Project** {#1-project} - -Before we start we need to prepare a simple node.js project: - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# or if you're using npm -npm init -``` - -Let's start with adding typescript and test dependencies - mocha & chai: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# or if you're using npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Now let's add `Waffle` and `ethers`: - -```bash -yarn add --dev ethereum-waffle ethers -# or if you're using npm -npm install ethereum-waffle ethers --save-dev -``` - -Your project structure should look like this now: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Smart contract** {#2-smart-contract} - -To start dynamic mocking, we need a smart contract with dependencies. Don't worry, I've got you covered! - -Here's a simple smart contract written in `Solidity` whose sole purpose is to check if we're rich. It uses ERC20 token to check if we have enough tokens. Put it in `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -As we want to use dynamic mocking we don't need the whole ERC20, that's why we're using the IERC20 interface with only one function. - -It's time to build this contract! For that we will use `Waffle`. First, we're going to create a simple `waffle.json` config file which specifies compilation options. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Now we're ready to build the contract with Waffle: - -```bash -npx waffle -``` - -Easy, right? In `build/` folder two files corresponding to the contract and the interface appeared. We will use them later for testing. - -### **3. Testing** {#3-testing} - -Let's create a file called `AmIRichAlready.test.ts` for the actual testing. First of all, we have to handle the imports. We will need them for later: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -Except for JS dependencies, we need to import our built contract and interface: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle uses `chai` for testing. However, before we can use it, we have to inject Waffle's matchers into chai itself: - -```typescript -use(solidity) -``` - -We need to implement `beforeEach()` function that will reset the state of the contract before each test. Let's first think of what we need there. To deploy a contract we need two things: a wallet and a deployed ERC20 contract to pass it as an argument for the `AmIRichAlready` contract. - -Firstly we create a wallet: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Then we need to deploy an ERC20 contract. Here's the tricky part - we have only an interface. This is the part where Waffle comes to save us. Waffle has a magical `deployMockContract()` function that creates a contract using solely the _abi_ of the interface: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Now with both the wallet and the deployed ERC20, we can go ahead and deploy the `AmIRichAlready` contract: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -With all of that, our `beforeEach()` function is finished. So far your `AmIRichAlready.test.ts` file should look like this: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Let's write the first test for the `AmIRichAlready` contract. What do you think our test should be about? Yeah, you're right! We should check if we are already rich :) - -But wait a second. How will our mocked contract know what values to return? We haven't implemented any logic for the `balanceOf()` function. Again, Waffle can help here. Our mocked contract has some new fancy stuff to it now: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -With this knowledge we can finally write our first test: - -```typescript -it("returns false if the wallet has less than 1000000 tokens", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Let's break down this test into parts: - -1. We set our mock ERC20 contract to always return balance of 999999 tokens. -2. Check if the `contract.check()` method returns `false`. - -We're ready to fire up the beast: - -![One test passing](./test-one.png) - -So the test works, but... there's still some room for improvement. The `balanceOf()` function will always return 99999. We can improve it by specifying a wallet for which the function should return something - just like a real contract: - -```typescript -it("returns false if the wallet has less than 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -So far, we've tested only the case where we're not rich enough. Let's test the opposite instead: - -```typescript -it("returns true if the wallet has at least 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -You run the tests... - -![Two tests passing](test-two.png) - -...and here you are! Our contract seems to work as intended :) - -## Testing contract calls {#testing-contract-calls} - -Let's sum up what've done so far. We've tested the functionality of our `AmIRichAlready` contract and it seems to be working properly. That means we're done, right? Not exactly! Waffle allows us to test our contract even further. But how exactly? Well, in Waffle's arsenal there's a `calledOnContract()` and `calledOnContractWith()` matchers. They will allow us to check if our contract called the ERC20 mock contract. Here's a basic test with one of these matchers: - -```typescript -it("checks if contract called balanceOf on the ERC20 token", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -We can go even further and improve this test with the other matcher I told you about: - -```typescript -it("checks if contract called balanceOf with certain wallet on the ERC20 token", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Let's check if the tests are correct: - -![Three tests passing](test-three.png) - -Great, all tests are green. - -Testing contract calls with Waffle is super easy. And here's the best part. These matchers work with both normal and mocked contracts! It is because Waffle records and filters EVM calls rather than inject code, like it is the case of popular testing libraries for other technologies. - -## The Finish Line {#the-finish-line} - -Congrats! Now you know how to use Waffle to test contract calls and mock contracts dynamically. There are far more interesting features to discover. I recommend diving into Waffle's documentation. - -Waffle's documentation is available [here](https://ethereum-waffle.readthedocs.io/). - -Source code for this tutorial can be found [here](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Tutorials you may also be interested in: - -- [Testing smart contracts with Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-one.png b/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-one.png deleted file mode 100644 index ce773780c25..00000000000 Binary files a/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-one.png and /dev/null differ diff --git a/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-three.png b/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-three.png deleted file mode 100644 index 89e02d63399..00000000000 Binary files a/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-three.png and /dev/null differ diff --git a/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-two.png b/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-two.png deleted file mode 100644 index 2477c32bd91..00000000000 Binary files a/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-two.png and /dev/null differ diff --git a/public/content/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 306f32dc93c..00000000000 --- a/public/content/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,197 +0,0 @@ ---- -title: "Waffle say hello world tutorial with hardhat and ethers" -description: Make your first Waffle project with hardhat and ethers.js -author: "MiZiet" -tags: - ["waffle", "smart contracts", "solidity", "testing", "hardhat", "ethers.js"] -skill: beginner -lang: en -published: 2020-10-16 ---- - -In this [Waffle](https://ethereum-waffle.readthedocs.io) tutorial, we will learn how to set up a simple "Hello world" smart contract project, using [hardhat](https://hardhat.org/) and [ethers.js](https://docs.ethers.io/v5/). Then we will learn how to add a new functionality to our smart contract and how to test it with Waffle. - -Let's start by creating a new project: - -```bash -yarn init -``` - -or - -```bash -npm init -``` - -and installing required packages: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -or - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -Next step is creating a sample hardhat project by running `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Welcome to Hardhat v2.0.3 👷‍ - -? What do you want to do? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -Select `Create a sample project` - -Our project's structure should look like this: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Now let's talk about some of these files: {#now-lets-talk} - -- Greeter.sol - our smart contract written in solidity; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Our smart contract can be divided into three parts: - -1. constructor - where we declare a string type variable called `greeting`, -2. function greet - a function that will return the `greeting` when called, -3. function setGreeting - a function that allows us to change the `greeting` value. - -- sample-test.js - our tests file - -```js -describe("Greeter", function () { - it("Should return the new greeting once it's changed", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### Next step consists of compiling our contract and running tests: {#compiling-and-testing} - -Waffle tests use Mocha (a test framework) with Chai (an assertion library). All you have to do is run `npx hardhat test` and wait for the following message to appear. - -```bash -✓ Should return the new greeting once it's changed -``` - -### Everything looks great so far, let's add some more complexity to our project {#adding-complexity} - -Imagine a situation where someone adds an empty string as a greeting. It wouldn't be a warm greeting, right? -Let's make sure that doesn't happen: - -We want to use solidity's `revert` when someone passes an empty string. A good thing is that we can easily test this functionality with Waffle's chai matcher `to.be.revertedWith()`. - -```js -it("Should revert when passing an empty string", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -Looks like our new test didn't pass: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -Let's implement this functionality into our smart contract: - -```solidity -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -``` - -Now, our setGreeting function looks like this: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Let's run tests again: - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -Congrats! You made it :) - -### Conclusion {#conclusion} - -We made a simple project with Waffle, Hardhat and ethers.js. We learned how to set up a project, add a test and implement new functionality. - -For more great chai matchers to test your smart contracts, check [official Waffle's docs](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index 42665429206..00000000000 --- a/public/content/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Testing simple smart contract with Waffle library -description: Tutorial for beginners -author: Ewa Kowalska -tags: ["smart contracts", "solidity", "Waffle", "testing"] -skill: beginner -lang: en -published: 2021-02-26 ---- - -## In this tutorial you'll learn how to {#in-this-tutorial-youll-learn-how-to} - -- Test the changes of wallet balance -- Test emission of events with specified arguments -- Assert that a transaction was reverted - -## Assumptions {#assumptions} - -- You can create a new JavaScript or TypeScript project -- You have some basic experience with tests in JavaScript -- You have used some package managers like yarn or npm -- You possess very basic knowledge of smart contracts and Solidity - -## Getting started {#getting-started} - -The tutorial demonstrates test setup and run using yarn, but there is no problem if you prefer npm - I will provide proper references to the official Waffle [documentation](https://ethereum-waffle.readthedocs.io/en/latest/index.html). - -## Install Dependencies {#install-dependencies} - -[Add](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) ethereum-waffle and typescript dependencies to the dev dependencies of your project. - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## Example smart contract {#example-smart-contract} - -During the tutorial we'll work on a simple smart contract example - EtherSplitter. It does not much apart from allowing anyone to send some wei and split it evenly between two predefined receivers. -The split function requires the number of wei to be even, otherwise it will revert. For both receivers it performs a wei transfer followed by emission of the Transfer event. - -Place the snippet of EtherSplitter code in `src/EtherSplitter.sol`. - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Uneven wei amount not allowed'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## Compile the contract {#compile-the-contract} - -To [compile](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) the contract add the following entry to the package.json file: - -```json -"scripts": { - "build": "waffle" - } -``` - -Next, create the Waffle configuration file in the project root directory - `waffle.json` - and then paste the following configuration there: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Run `yarn build`. As the result, the `build` directory will appear with the EtherSplitter compiled contract in JSON format. - -## Test setup {#test-setup} - -Testing with Waffle requires using Chai matchers and Mocha, so you need to [add](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) them to your project. Update your package.json file and add the `test` entry in the scripts part: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -If you want to [execute](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) your tests, just run `yarn test` . - -## Testing {#testing} - -Now create the `test` directory and create the new file `test\EtherSplitter.test.ts`. -Copy the snippet below and paste it to our test file. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Ether Splitter", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // add the tests here -}) -``` - -A few words before we start. -The `MockProvider` comes up with a mock version of the blockchain. It also delivers mock wallets that will serve us for testing EtherSplitter contract. We can get up to ten wallets by calling `getWallets()` method on the provider. In the example, we get three wallets - for the sender and for two receivers. - -Next, we declare a variable called 'splitter' - this is our mock EtherSplitter contract. It is created before each execution of a single test by the `deployContract` method. This method simulates deployment of a contract from the wallet passed as the first parameter (sender's wallet in our case). The second parameter is the ABI and the bytecode of the tested contract - we pass there the json file of the compiled EtherSplitter contract from the `build` directory. The third parameter is an array with the contract's constructor arguments, which in our case, are the two addresses of the receivers. - -## changeBalances {#changebalances} - -First, we will check if the split method actually changes the balances of receivers' wallets. If we split 50 wei from senders account, we would expect the balances of both receivers to increase by 25 wei. We will use Waffle's `changeBalances` matcher: - -```ts -it("Changes accounts balances", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -As the first parameter of the matcher, we pass an array of receivers' wallets, and as the second - an array of expected increases on corresponding accounts. -If we wanted to check the balance of one specific wallet, we could also use `changeBalance` matcher, which does not require passing arrays, as in the example below: - -```ts -it("Changes account balance", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -Note that in both cases of `changeBalance` and `changeBalances` we pass the split function as a callback because the matcher needs to access the state of balances before and after the call. - -Next, we'll test if the Transfer event was emitted after each transfer of wei. We'll turn to another matcher from Waffle: - -## Emit {#emit} - -```ts -it("Emits event on the transfer to the first receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("Emits event on the transfer to the second receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -The `emit` matcher allows us to check if a contract emitted an event on calling a method. As the parameters to the `emit` matcher, we provide the mock contract that we predict to emit the event, along with the name of that event. In our case, the mock contract is `splitter` and the name of the event - `Transfer`. We can also verify the precise values of arguments that the event was emitted with - we pass as many arguments to `withArgs` matcher, as our event declaration expects. In case of EtherSplitter contract, we pass the addresses of the sender and the receiver along with the transferred wei amount. - -## revertedWith {#revertedwith} - -As the last example, we'll check if the transaction was reverted in case of uneven number of wei. We'll use `revertedWith` matcher: - -```ts -it("Reverts when Vei amount uneven", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Uneven wei amount not allowed" - ) -}) -``` - -The test, if passed, will assure us that the transaction was reverted indeed. However, there must be also an exact match between the messages that we passed in `require` statement and the message we expect in `revertedWith`. If we go back to the code of EtherSplitter contract, in the `require` statement for the wei amount, we provide the message: 'Uneven wei amount not allowed'. This matches the message we expect in our test. If they were not equal, the test would fail. - -## Congratulations! {#congratulations} - -You've made your first big step towards testing smart contracts with Waffle! diff --git a/public/content/roadmap/verkle-trees/index.md b/public/content/roadmap/verkle-trees/index.md index e716f444830..9f6042d3e6e 100644 --- a/public/content/roadmap/verkle-trees/index.md +++ b/public/content/roadmap/verkle-trees/index.md @@ -41,7 +41,7 @@ The witness size varies depending on the number of leaves it includes. Assuming Verkle trees are `(key,value)` pairs where the keys are 32-byte elements composed of a 31-byte _stem_ and a single byte _suffix_. These keys are organized into _extension_ nodes and _inner_ nodes. Extension nodes represent a single stem for 256 children with different suffixes. Inner nodes also have 256 children, but they can be other extension nodes. The main difference between the Verkle tree and the Merkle tree structure is that the Verkle tree is much flatter, meaning there are fewer intermediate nodes linking a leaf to the root, and therefore less data required to generate a proof. -![](./verkle.png) +![Diagram of a Verkle tree data structure](./verkle.png) [Read more about the structure of Verkle trees](https://blog.ethereum.org/2021/12/02/verkle-tree-structure) diff --git a/public/content/security/index.md b/public/content/security/index.md index da60fb99324..9ae1d4632b7 100644 --- a/public/content/security/index.md +++ b/public/content/security/index.md @@ -29,11 +29,11 @@ Misunderstandings about how crypto works can lead to costly mistakes. For exampl ## Wallet security {#wallet-security} -### Don't give out your private keys {#protect-private-keys} +### Never share your recovery phrase {#protect-private-keys} -**Never, for any reason, share your private keys!** +**Never, for any reason, share your recovery phrase or private keys!** -The private key to your wallet is a password to your Ethereum wallet. It is the only thing stopping someone who knows your wallet address from draining your account of all of its assets! +Your recovery phrase (also called secret recovery phrase or seed phrase) is the master key to your wallet. Anyone who has it can access all of your accounts and drain every asset. Private keys work the same way for individual accounts. No legitimate service, support agent, or website will ever ask you for these. What's an Ethereum wallet? diff --git a/public/content/translations/ar/community/support/faq/index.md b/public/content/translations/ar/community/support/faq/index.md new file mode 100644 index 00000000000..452a7a8e562 --- /dev/null +++ b/public/content/translations/ar/community/support/faq/index.md @@ -0,0 +1,77 @@ +--- +title: "الأسئلة المتداولة" +description: "أسئلة شائعة حول إيثريوم بشأن المحافظ والمعاملات وتجميد العملات والمزيد." +lang: ar +--- + +# الأسئلة الشائعة {#faq} + +## لقد أرسلت عملة رقمية إلى العنوان الخطأ {#wrong-wallet} + +المعاملة المرسلة على Ethereum لا رجعة فيها. للأسف، إذا أرسلت ETH أو رموزًا مميزة إلى المحفظة الخطأ، فلا توجد طريقة لعكس المعاملة. + +**ما الذي يمكنك فعله:** + +- **إذا كنت تعرف مالك العنوان**، فاتصل به مباشرة واطلب منه إعادة الأموال +- **إذا كان العنوان ينتمي إلى منصة تداول أو خدمة معروفة**، فاتصل بفريق الدعم الخاص بهم، فقد يتمكنون من المساعدة +- **إذا أرسلت رموزًا مميزة إلى عنوان عقد**، فتحقق مما إذا كان العقد يحتوي على وظيفة سحب أو استرداد (وهذا أمر نادر) + +في معظم الحالات، لا توجد طريقة لاسترداد الأموال. لا توجد منظمة مركزية أو كيان أو شخص يمتلك إيثريوم، مما يعني أنه لا يمكن لأحد عكس المعاملات. تحقق دائمًا من عنوان المستلم مرتين قبل التأكيد. + +## لقد فقدت الوصول إلى محفظتي {#lost-wallet-access} + +تعتمد خيارات الاسترداد الخاصة بك على نوع المحفظة التي تستخدمها. + +### إذا كانت لديك العبارة الأولية (عبارة الاسترداد) + +يمكنك استعادة محفظتك في أي تطبيق محفظة متوافق باستخدام العبارة الأولية الخاصة بك. لهذا السبب من الأهمية بمكان الحفاظ على العبارة الأولية الخاصة بك مخزنة بأمان في وضع عدم الاتصال. تحقق من وثائق مزود محفظتك للحصول على إرشادات الاستعادة. + +### إذا فقدت العبارة الأولية الخاصة بك + +بدون العبارة الأولية أو المفاتيح الخاصة، لا يمكن استرداد أموالك. لا يمكن لأي شخص، بما في ذلك ethereum.org، إعادة تعيين كلمة المرور الخاصة بك أو استعادة الوصول إلى محفظة ذاتية الحفظ. + +### إذا كان حسابك على منصة تداول + +إذا كان حسابك على منصة تداول مركزية مثل Coinbase أو Binance أو Kraken، فاتصل بفريق دعم المنصة مباشرة. إنهم يتحكمون في الحسابات على منصتهم وقد يتمكنون من المساعدة في إعادة تعيين كلمة المرور أو استرداد الحساب. + + + + + + +**لا تشارك العبارة الأولية الخاصة بك مع أي شخص** يدعي أنه يساعدك على استعادة محفظتك. هذه إحدى أكثر طرق الاحتيال شيوعًا. لن تطلب أي خدمة شرعية العبارة الأولية الخاصة بك أبدًا. + + + + + + كيفية استخدام محفظة + + +## معاملتي عالقة أو معلقة {#stuck-transaction} + +يمكن أن تتعثر المعاملات على شبكة إيثريوم عندما تكون رسوم الغاز التي حددتها أقل مما تتطلبه الشبكة حاليًا. تتيح لك معظم المحافظ إصلاح هذا: + +- **تسريع:** إعادة إرسال نفس المعاملة برسوم غاز أعلى +- **إلغاء:** أرسل معاملة بقيمة 0 ETH إلى عنوانك الخاص باستخدام نفس الـ nonce الخاص بالمعاملة المعلقة + +### أدلة مفيدة + +- [كيفية تسريع أو إلغاء معاملة معلقة على MetaMask](https://support.metamask.io/transactions-and-gas/transactions/how-to-speed-up-or-cancel-a-pending-transaction/) +- [كيفية إلغاء معاملات إيثريوم المعلقة](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) + +## كيف يمكنني المطالبة بمسابقتي لإيثريوم؟ {#giveaway-scam} + +هبات الإيثريوم هي عمليات احتيال مصممة لسرقة الإيثريوم الخاص بك. لا تنجذب إلى العروض التي تبدو جيدة لدرجة يصعب تصديقها. إذا أرسلت ETH إلى عنوان هبة، فلن تتلقى أي هبة، ولن تتمكن من استرداد أموالك. + +[المزيد عن منع الاحتيال](/security/#common-scams) + +## كيف أقوم بتجميد عملة ETH؟ كيفية تجميد العملات {#how-to-stake} + +لكي تصبح مدققًا، يجب عليك مشاركة 32 ETH في عقد إيداع Ethereum وإعداد عقدة مدقق. يمكنك أيضًا المشاركة بكمية أقل من ETH من خلال مجمعات تجميد العملات. + +يتوفر المزيد من المعلومات على [صفحات تجميد العملات](/staking/) الخاصة بنا وفي [منصة إطلاق تجميد العملات](https://launchpad.ethereum.org/). + +## كيف تعدين الإيثيريوم؟ تعدين إيثريوم {#mining-ethereum} + +لم يعد تعدين الإثيريوم ممكنًا. تم إيقاف التعدين عندما انتقل إيثريوم من [إثبات العمل](/glossary/#pow) إلى [إثبات الحصة](/glossary/#pos) خلال [الدمج](/roadmap/merge/) في سبتمبر 2022. الآن، بدلاً من القائمين بالتعدين، أصبح لدى إيثريوم أدوات التحقق من الصحة. يمكن لأي شخص [المشاركة](/glossary/#staking) بـ ETH والحصول على مكافآت المشاركة مقابل تشغيل برنامج المُدقِّق لتأمين الشبكة. diff --git a/public/content/translations/ar/community/support/misconceptions/index.md b/public/content/translations/ar/community/support/misconceptions/index.md new file mode 100644 index 00000000000..086097f63f8 --- /dev/null +++ b/public/content/translations/ar/community/support/misconceptions/index.md @@ -0,0 +1,73 @@ +--- +title: "مفاهيم خاطئة شائعة حول إيثريوم" +description: "توضيح المفاهيم الخاطئة الأكثر شيوعًا حول كيفية عمل إيثريوم." +lang: ar +--- + +# مفاهيم خاطئة شائعة حول إيثريوم {#misconceptions} + +## هل إيثريوم شركة؟ {#not-a-company} + +إيثريوم هي تقنية لامركزية مفتوحة المصدر، يشرف على صيانتها آلاف المساهمين من جميع أنحاء العالم. لا توجد شركة تسمى "إيثريوم" تدير الحسابات أو تحتفظ بالأموال أو تقدم دعمًا للعملاء. + +[مؤسسة إيثريوم](https://ethereum.foundation/) هي منظمة غير ربحية تدعم تطوير إيثريوم، لكنها لا تملك الشبكة أو تسيطر عليها. لا يوجد كيان واحد يفعل ذلك. + +**[ethereum.org](/)** هو مصدر تعليمي يديره المجتمع. إنه ليس منصة تداول أو محفظة أو مؤسسة مالية. إنه لا يحتفظ بأي أموال للمستخدمين ولا يمكنه الوصول إلى أي حسابات. + + + ما هو إيثريوم؟ + + +## هل يمكن لأحد استرداد أو تجميد أموالي؟ {#no-fund-access} + +على عكس البنك، لا توجد سلطة مركزية على إيثريوم يمكنها تجميد الأموال أو الاستيلاء عليها أو استردادها. الشخص الذي يحمل المفاتيح الخاصة (أو عبارة الأصل) لديه سيطرة كاملة وحصرية على المحفظة. + +هذا يعني: + +- **لا يمكن لأحد استرداد الأموال** التي أرسلتها إلى عنوان خاطئ +- **لا يمكن لأحد عكس** معاملة بعد تأكيدها +- **لا يمكن لأحد تجميد** محفظتك أو حظر معاملاتك +- **لا يمكن لأحد إعادة تعيين كلمة مرورك** إذا فقدت عبارة الأصل الخاصة بك + +لهذا السبب، فإن حماية عبارة الأصل الخاصة بك أمر بالغ الأهمية. إنها الطريقة الوحيدة للوصول إلى محفظتك. إذا ضاعت أو سُرقت، فلا يوجد خيار للاسترداد. + + + أمان إيثريوم ومنع الاحتيال + + +## هل لا يزال بإمكاني تعدين إيثريوم؟ {#no-mining} + +تحولت إيثريوم من [إثبات العمل](/glossary/#pow) إلى [إثبات الحصة](/glossary/#pos) خلال [الدمج](/roadmap/merge/) في سبتمبر 2022. لم يعد التنقيب ممكنًا على إيثريوم. + +الشبكة مؤمَّنة الآن بواسطة المدققين الذين [يجمدون](/glossary/#staking) عملات ETH. يمكن لأي شخص المشاركة: + +- **التجميد الفردي:** قم بتشغيل المدقق الخاص بك بـ 32 ETH—[اعرف المزيد](/staking/solo/) +- **تجميد العملات كخدمة:** تفويض تشغيل العقدة مع الاحتفاظ بمفاتيحك—[اعرف المزيد](/staking/saas/) +- **التجميد المجمّع:** جمّد أقل من 32 ETH بالانضمام إلى مجمّع—[اعرف المزيد](/staking/pools/) + + + تعرَّف على المزيد عن تجميد العملات + + +## هل يوجد فريق دعم لـ إيثريوم؟ {#no-support-team} + +البحث عن "دعم إيثريوم الرسمي" مماثل للبحث عن "دعم الإنترنت الرسمي". هذا بالطبع غير موجود، ولكن اعتمادًا على مشكلتك، قد تتمكن من طلب الدعم من مزود خدمة الإنترنت الخاص بك، أو الشركة المصنعة لجهاز التوجيه الخاص بك، أو إحدى الشركات التي تقف وراء الجهاز أو التطبيق أو موقع الويب الذي تستخدمه. + +إيثريوم مماثل. لا توجد شركة أو فريق دعم أو مكتب مساعدة وراء إيثريوم ككل، ولكن اعتمادًا على المشكلة، قد تجد المساعدة من خلال التواصل مع _مزود محفظتك_ أو _خدمة تجميد العملات_ أو _منصة التداول_ أو _المؤسسة المالية_ أو _الفريق الذي يشرف على صيانة التطبيق_ الذي تستخدمه. + +نظرًا لأن إيثريوم شفاف بشكل عام افتراضيًا، فقد تجد أيضًا [مستكشفات الكتل](/developers/docs/data-and-analytics/block-explorers/) و[أدوات التحليل](/developers/tools/analytics/) وغيرها من [مصادر التحقيق عبر الإنترنت](/community/support/scams/#analyze) مفيدة في البحث عن مشكلة مباشرةً. + +ومع ذلك، لن يقوم أي شخص من إيثريوم أو ethereum.org بما يلي: + +- الاتصال بك عبر رسالة مباشرة +- طلب عبارة الأصل أو مفاتيحك الخاصة +- أن يطلب منك إرسال ETH للتحقق من محفظتك +- عرض المساعدة في استرداد أموالك مقابل رسوم + +**أي شخص يفعل أيًا مما سبق يحاول الاحتيال عليك.** + +إذا كنت بحاجة إلى المساعدة، فإن المجتمعات الحقيقية التي يمكنها المساعدة مدرجة في [صفحة الدعم](/community/support/). هذه مجتمعات مفتوحة يديرها متطوعون، وليست قنوات دعم رسمية. + + + أمان إيثريوم ومنع الاحتيال + diff --git a/public/content/translations/ar/community/support/scams/index.md b/public/content/translations/ar/community/support/scams/index.md new file mode 100644 index 00000000000..c3eabbbbd49 --- /dev/null +++ b/public/content/translations/ar/community/support/scams/index.md @@ -0,0 +1,159 @@ +--- +title: "المساعدة في حالات الاحتيال والإبلاغ عنها" +description: "ماذا تفعل إذا تعرضت للاحتيال، وكيفية تأمين أصولك المتبقية، وأين تبلغ عن الاحتيال." +lang: ar +--- + +# لقد تعرضت للاحتيال أو فقدت أموالي {#scam-help} + +تستهدف عمليات الاحتيال بالعملات الرقمية الأشخاص من جميع مستويات الخبرة، بما في ذلك المحترفين في مجال التمويل والتكنولوجيا. أنت لست وحدك، ووجودك هنا هو الخطوة الأولى الصحيحة. + + + + + + +**لا يمكن لأحد عكس معاملات بلوكتشين.** إذا اتصل بك شخص ما مدعياً أنه يستطيع استرداد أموالك مقابل رسوم، فمن شبه المؤكد أن هذه عملية احتيال ثانية. انظر [عمليات الاحتيال الخاصة بالاسترداد](#recovery-scams) أدناه. + + + + +## تأمين أصولك المتبقية {#secure-assets} + +إذا تفاعلت مع محتال أو تشك في أن محفظتك قد تعرضت للاختراق، فاتخذ هذه الخطوات على الفور: + +1. **انقل الأموال المتبقية** إلى محفظة جديدة وآمنة لا يستطيع المحتال الوصول إليها +2. **إلغاء موافقات الرموز المميزة.** غالباً ما يخدعك المحتالون للموافقة على إنفاق غير محدود للرموز المميزة. يمنع إلغاء هذه الأذونات استنزاف محفظتك بشكل أكبر +3. **غيِّر كلمات المرور** على أي حسابات تداول قد تكون مرتبطة +4. **تمكين المصادقة الثنائية (2FA)** على جميع الحسابات المتعلقة بالعملات الرقمية + +### كيفية إلغاء موافقات الرموز المميزة {#revoke-approvals} + +عندما تتفاعل مع تطبيق لامركزي أو عقد ذكي، قد تكون قد منحته الإذن بإنفاق رموزك المميزة. إذا خدعك محتال للموافقة على عقد خبيث، فيمكنهم مواصلة استنزاف رموزك المميزة حتى بعد عملية الاحتيال الأولية. + +استخدم هذه الأدوات للتحقق من الموافقات وإلغائها: + +- [Revoke.cash](https://revoke.cash/): صِل محفظتك لرؤية جميع الموافقات النشطة وإلغائها +- [Revokescout](https://revoke.blockscout.com/): تحقق من الموافقات وألغِها عبر Blockscout +- [Etherscan Token Approval Checker](https://etherscan.io/tokenapprovalchecker): تحقق من الموافقات وألغِها عبر Etherscan + + + دليل تفصيلي: كيفية إلغاء الوصول إلى الرموز المميزة + + +## الإبلاغ عن عناوين الاحتيال ومواقعه الإلكترونية {#report} + +يساعد الإبلاغ في تحذير المستخدمين الآخرين وقد يساعد في تحقيقات إنفاذ القانون. وثِّق كل شيء: تجزئات (هاشات) المعاملات، وعناوين المحافظ، ولقطات الشاشة، وأي تواصل مع المحتال. + +### الإبلاغ عن عنوان احتيالي {#report-address} + +- [Chainabuse](https://www.chainabuse.com/): قاعدة بيانات للإبلاغ عن الاحتيال والعمليات الاحتيالية مدفوعة بالمجتمع. أرسل تقارير وابحث عن عناوين الاحتيال المعروفة +- [Etherscan report](https://info.etherscan.com/report-address/): ضع علامة على عنوان على مستكشف كتل إيثريوم الأكثر استخدامًا +- [CryptoScamDB](https://cryptoscamdb.org/): قاعدة بيانات مفتوحة المصدر لتتبع عمليات الاحتيال بالعملات الرقمية + +### الإبلاغ عن موقع إلكتروني أو حساب وسائط اجتماعية احتيالي {#report-website} + +- [PhishTank](https://phishtank.org/): أرسل عناوين URL للتصيد وتحقق منها +- [Google Safe Browsing](https://safebrowsing.google.com/safebrowsing/report_phish/): أبلغ عن مواقع التصيد الاحتيالي إلى Google حتى يتم حظرها في Chrome والمتصفحات الأخرى +- [Netcraft](https://report.netcraft.com/report/mistake): أبلغ عن المواقع الخبيثة والاحتيالية +- أبلغ مباشرة على منصة التواصل الاجتماعي التي وقع فيها الاحتيال (لدى Twitter/X و Discord و Telegram جميعها ميزات للإبلاغ) + +### الإبلاغ لسلطات إنفاذ القانون {#report-law-enforcement} + +- **الولايات المتحدة:** [مركز شكاوى جرائم الإنترنت التابع لمكتب التحقيقات الفيدرالي (IC3)](https://www.ic3.gov/) +- **المملكة المتحدة:** [Action Fraud](https://www.actionfraud.police.uk/) +- **الاتحاد الأوروبي:** [Europol](https://www.europol.europa.eu/report-a-crime) +- **بلدان أخرى:** قدِّم بلاغاً لدى الشرطة المحلية. يعتبر الاحتيال بالعملات الرقمية جريمة في معظم الولايات القضائية + +## حلل ما حدث {#analyze} + +يمكن أن يساعد فهم أين ذهبت أموالك في التقارير وقد يدعم جهود الاسترداد إذا وصلت الأموال إلى منصّة تداول مركزية. + +- [Blockscout](https://eth.blockscout.com/): مستكشف كتل مفتوح المصدر للبحث عن أي تجزئة (هاش) معاملة أو عنوان محفظة لمعرفة أين تم إرسال الأموال +- [Etherscan](https://etherscan.io/): ابحث عن أي تجزئة (هاش) معاملة أو عنوان محفظة لمعرفة أين تم إرسال الأموال +- [Chainabuse lookup](https://www.chainabuse.com/): تحقق مما إذا كان العنوان قد تم الإبلاغ عنه بالفعل من قبل ضحايا آخرين +- [MetaSleuth](https://metasleuth.io/) من BlockSec: أداة تتبع المعاملات المرئية التي ترسم تدفقات الأموال + +**إذا تم إرسال الأموال إلى منصّة تداول مركزية** (مثل Coinbase أو Binance أو Kraken)، فاتصل بفريق الدعم الخاص بهم على الفور مع تفاصيل المعاملة. يمكن لمنصات التداول أحياناً تجميد الحسابات التي تم الإبلاغ عنها على أنها احتيالية. + +## الحقيقة المرة {#hard-truth} + +لأن إيثريوم لامركزية، لا يمكن لأي سلطة مركزية عكس المعاملات أو استرداد الأموال المسروقة. بمجرد تأكيد المعاملة على بلوكتشين، تصبح نهائية. + +لا يزال الإبلاغ ذا قيمة. تساعد التقارير سلطات إنفاذ القانون على تتبع عصابات الاحتيال المنظمة، كما أن وضع علامات على العناوين في Chainabuse و Etherscan يحذر الضحايا المحتملين في المستقبل. + +## أنواع عمليات الاحتيال التي يجب الحذر منها {#scam-types} + + + +ينشئ المحتالون هدايا مزيفة يعدون فيها بمضاعفة عملات ETH الخاصة بك أو منحك رموزاً مميزة مجانية. غالباً ما ينتحلون شخصية شخصيات معروفة مثل فيتاليك بوتيرين. إذا أرسلت عملة ETH إلى عنوان "هدية"، فلن تسترد أي شيء. + +**تذكر:** فيتاليك والشخصيات البارزة الأخرى لن يطلبوا منك أبداً إرسال عملات ETH إليهم. + +[المزيد عن عمليات الاحتيال الشائعة](/security/#common-scams) + + + + +ينتحل المحتالون شخصية أعضاء فريق إيثريوم أو المشرفين أو وكلاء الدعم على Discord و Telegram ووسائل التواصل الاجتماعي. قد يرسلون لك رسائل مباشرة يعرضون فيها المساعدة أو يدعون وجود مشكلة في حسابك. + +**تذكر:** + +- لا يوجد "فريق دعم إيثريوم" +- لن يراسلك المشرفون الحقيقيون أولاً أبداً +- لا تشارك أبداً عبارة الأصل أو مفاتيحك الخاصة مع أي شخص ولأي سبب كان +- لا تنقر أبداً على الروابط المرسلة في رسائل غير مرغوب فيها + + + + +تستهدف عمليات الاحتيال الخاصة بالاسترداد على وجه التحديد الأشخاص الذين فقدوا أموالهم بالفعل. يراقب المحتالون وسائل التواصل الاجتماعي بحثاً عن الأشخاص الذين يتحدثون عن تعرضهم للاحتيال، ثم يتواصلون معهم متظاهرين بأنهم "محققو بلوكتشين" أو "خبراء استرداد العملات الرقمية". + +يعدون بتتبع واسترداد عملاتك الرقمية المسروقة مقابل رسوم مسبقة. بعد أن تدفع، يختفون. + +**لا يمكن لأي خدمة مشروعة عكس معاملات بلوكتشين.** أي شخص يعد بذلك فهو كاذب. هذه إحدى أكثر عمليات الاحتيال التكميلية شيوعاً. + + + + +تبدو مواقع التصيد الاحتيالي مطابقة لتطبيقات المحافظ الحقيقية أو منصات التداول أو منصات التمويل اللامركزي (DeFi). يخدعونك لإدخال عبارة الأصل الخاصة بك أو توصيل محفظتك، ثم يستنزفون أموالك. + +**احمِ نفسك:** + +- تحقق دائماً من عنوان URL قبل توصيل محفظتك +- ضع إشارة مرجعية على المواقع الرسمية التي تستخدمها بانتظام +- لا تدخل أبداً عبارة الأصل الخاصة بك على أي موقع ويب. التطبيقات المشروعة لا تطلبها أبداً +- استخدم [PhishTank](https://phishtank.org/) للتحقق من عناوين URL المشبوهة + + + كيفية التعرف على الرموز المميزة الاحتيالية + + + + + الدليل الكامل لأمان إيثريوم ومنع الاحتيال + diff --git a/public/content/translations/ar/developers/tutorials/ai-trading-agent/index.md b/public/content/translations/ar/developers/tutorials/ai-trading-agent/index.md new file mode 100644 index 00000000000..5755f1464fc --- /dev/null +++ b/public/content/translations/ar/developers/tutorials/ai-trading-agent/index.md @@ -0,0 +1,980 @@ +--- +title: "اصنع وكيل تداول الذكاء الاصطناعي الخاص بك على الإيثريوم" +description: "في هذا البرنامج التعليمي، ستتعلم كيفية إنشاء وكيل تداول بسيط للذكاء الاصطناعي. يقرأ هذا الوكيل المعلومات من سلسلة الكتل (blockchain)، ويطلب من LLM توصية بناءً على تلك المعلومات، وينفذ الصفقة التي يوصي بها LLM، ثم ينتظر ويكرر." +author: Ori Pomerantz +tags: [ "الذكاء الاصطناعي", "تداول", "وكيل", "python" ] +skill: intermediate +published: 2026-02-13 +lang: ar +sidebarDepth: 3 +--- + +في هذا البرنامج التعليمي، ستتعلم كيفية إنشاء وكيل تداول بسيط للذكاء الاصطناعي. يعمل هذا الوكيل باستخدام هذه الخطوات: + +1. قراءة الأسعار الحالية والسابقة لرمز مميز، بالإضافة إلى معلومات أخرى قد تكون ذات صلة +2. إنشاء استعلام بهذه المعلومات، بالإضافة إلى معلومات أساسية لشرح مدى صلتها بالموضوع +3. إرسال الاستعلام واستلام سعر متوقع +4. التداول بناءً على التوصية +5. انتظر وكرر + +يوضح هذا الوكيل كيفية قراءة المعلومات وترجمتها إلى استعلام ينتج عنه إجابة قابلة للاستخدام واستخدام تلك الإجابة. كل هذه خطوات مطلوبة لوكيل الذكاء الاصطناعي. يتم تنفيذ هذا الوكيل بلغة بايثون Python لأنها اللغة الأكثر شيوعًا المستخدمة في الذكاء الاصطناعي. + +## لماذا نفعل هذا؟ {#why-do-this} + +تسمح وكلاء التداول الآلي للمطورين باختيار وتنفيذ استراتيجية تداول. تسمح [وكلاء الذكاء الاصطناعي](/ai-agents) باستراتيجيات تداول أكثر تعقيدًا وديناميكية، ومن المحتمل استخدام معلومات وخوارزميات لم يفكر المطور في استخدامها. + +## الأدوات {#tools} + +يستخدم هذا البرنامج التعليمي [Python](https://www.python.org/) و[مكتبة Web3](https://web3py.readthedocs.io/en/stable/) و[Uniswap v3](https://github.com/Uniswap/v3-periphery) للحصول على عروض الأسعار والتداول. + +### لماذا لغة Python؟ {#python} + +اللغة الأكثر استخدامًا في الذكاء الاصطناعي هي [Python](https://www.python.org/)، لذلك نستخدمها هنا. لا تقلق إذا كنت لا تعرف لغة بايثون Python. اللغة واضحة جدًا، وسأشرح بالضبط ما تفعله. + +تُعد [مكتبة Web3](https://web3py.readthedocs.io/en/stable/) هي واجهة برمجة تطبيقات Ethereum API الأكثر شيوعًا في لغة Python. إنه سهل الاستخدام إلى حد ما. + +### التداول على سلسلة الكتل (blockchain) {#trading-on-blockchain} + +هناك [العديد من منصات التداول الموزعة (DEX)](/apps/categories/defi/) التي تتيح لك تداول الرموز المميزة على Ethereum. ومع ذلك، فإنها تميل إلى أن تكون لها أسعار صرف متشابهة بسبب [المراجحة](/developers/docs/smart-contracts/composability/#better-user-experience). + +تعتبر [Uniswap](https://app.uniswap.org/) منصة تداول لامركزية مستخدمة على نطاق واسع ويمكننا استخدامها لكل من عروض الأسعار (لرؤية القيم النسبية للرموز المميزة) والصفقات. + +### OpenAI {#openai} + +بالنسبة لنموذج لغوي كبير، اخترت أن أبدأ مع [OpenAI](https://openai.com/). لتشغيل التطبيق في هذا البرنامج التعليمي، ستحتاج إلى الدفع للوصول إلى واجهة برمجة التطبيقات API. الحد الأدنى للدفع وهو 5 دولارات هو أكثر من كافٍ. + +## التطوير، خطوة بخطوة {#step-by-step} + +لتبسيط التطوير، ننتقل على مراحل. كل خطوة هي فرع في GitHub. + +### البدء {#getting-started} + +هناك خطوات للبدء في استخدام UNIX أو Linux (بما في ذلك [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)) + +1. إذا لم يكن لديك بالفعل، فقم بتنزيل وتثبيت [Python](https://www.python.org/downloads/). + +2. استنسخ مستودع GitHub. + + ```sh + git clone https://github.com/qbzzt/260215-ai-agent.git -b 01-getting-started + cd 260215-ai-agent + ``` + +3. قم بتثبيت [`uv`](https://docs.astral.sh/uv/getting-started/installation/). قد يكون الأمر على نظامك مختلفًا. + + ```sh + pipx install uv + ``` + +4. قم بتنزيل المكتبات. + + ```sh + uv sync + ``` + +5. قم بتنشيط البيئة الافتراضية. + + ```sh + source .venv/bin/activate + ``` + +6. للتحقق من أن Python وWeb3 يعملان بشكل صحيح، قم بتشغيل `python3` وزوده بهذا البرنامج. يمكنك إدخاله في الموجه `>>>`؛ ليست هناك حاجة لإنشاء ملف. + + ```python + from web3 import Web3 + MAINNET_URL = "https://eth.drpc.org" + w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) + w3.eth.block_number + quit() + ``` + +### القراءة من سلسلة الكتل (blockchain) {#read-blockchain} + +الخطوة التالية هي القراءة من سلسلة الكتل (blockchain). للقيام بذلك، تحتاج إلى التغيير إلى الفرع `02-read-quote` ثم استخدام `uv` لتشغيل البرنامج. + +```sh +git checkout 02-read-quote +uv run agent.py +``` + +يجب أن تتلقى قائمة بكائنات `Quote`، لكل منها طابع زمني وسعر وأصل (حاليًا دائمًا `WETH/USDC`). + +إليك شرح سطر بسطر. + +```python +from web3 import Web3 +from web3.contract import Contract +from decimal import Decimal, ROUND_HALF_UP +from dataclasses import dataclass +from datetime import datetime, timezone +from pprint import pprint +import time +import functools +import sys +``` + +استورد المكتبات التي نحتاجها. يتم شرحها أدناه عند استخدامها. + +```python +print = functools.partial(print, flush=True) +``` + +يستبدل `print` في لغة Python بإصدار يقوم دائمًا بتفريغ الإخراج على الفور. هذا مفيد في نص برمجي طويل الأمد لأننا لا نريد انتظار تحديثات الحالة أو إخراج تصحيح الأخطاء. + +```python +MAINNET_URL = "https://eth.drpc.org" +``` + +عنوان URL للوصول إلى الشبكة الرئيسية (mainnet). يمكنك الحصول على واحدة من [العقدة كخدمة](/developers/docs/nodes-and-clients/nodes-as-a-service/) أو استخدام إحدى تلك المعلن عنها في [Chainlist](https://chainlist.org/chain/1). + +```python +BLOCK_TIME_SECONDS = 12 +MINUTE_BLOCKS = int(60 / BLOCK_TIME_SECONDS) +HOUR_BLOCKS = MINUTE_BLOCKS * 60 +DAY_BLOCKS = HOUR_BLOCKS * 24 +``` + +تحدث كتلة الشبكة الرئيسية لـ Ethereum عادةً كل اثنتي عشرة ثانية، لذا فهذه هي عدد الكتل التي نتوقع حدوثها في فترة زمنية. لاحظ أن هذا ليس رقمًا دقيقًا. عندما يكون [مقدم الكتلة](/developers/docs/consensus-mechanisms/pos/block-proposal/) معطلاً، يتم تخطي تلك الكتلة، ويكون وقت الكتلة التالية 24 ثانية. إذا أردنا الحصول على الكتلة الدقيقة للطابع الزمني، فسنستخدم [البحث الثنائي](https://en.wikipedia.org/wiki/Binary_search). ومع ذلك، هذا قريب بما فيه الكفاية لأغراضنا. التنبؤ بالمستقبل ليس علمًا دقيقًا. + +```python +CYCLE_BLOCKS = DAY_BLOCKS +``` + +حجم الدورة. نراجع عروض الأسعار مرة واحدة في كل دورة ونحاول تقدير القيمة في نهاية الدورة التالية. + +```python +# عنوان المجمع الذي نقرأ منه +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +``` + +تؤخذ قيم عروض الأسعار من مجمع Uniswap 3 USDC/WETH على العنوان [`0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`](https://eth.blockscout.com/address/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640?tab=read_write_contract). هذا العنوان موجود بالفعل في شكل المجموع الاختباري، ولكن من الأفضل استخدام [`Web3.to_checksum_address`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_checksum_address) لجعل الكود قابلاً لإعادة الاستخدام. + +```python +POOL_ABI = [ + { "name": "slot0", ... }, + { "name": "token0", ... }, + { "name": "token1", ... }, +] + +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... } +] +``` + +هذه هي [واجهات التطبيق الثنائية ABIs](https://docs.soliditylang.org/en/latest/abi-spec.html) للعقدين اللذين نحتاج إلى الاتصال بهما. للحفاظ على الكود موجزًا، نقوم بتضمين الوظائف التي نحتاج إلى استدعائها فقط. + +```python +w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) +``` + +قم ببدء مكتبة [`Web3`](https://web3py.readthedocs.io/en/stable/quickstart.html#remote-providers) واتصل بعقدة Ethereum. + +```python +@dataclass(frozen=True) +class ERC20Token: + address: str + symbol: str + decimals: int + contract: Contract +``` + +هذه إحدى طرق إنشاء فئة بيانات في لغة Python. يُستخدم نوع البيانات [`Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) للاتصال بالعقد. لاحظ `(frozen=True)`. في لغة بايثون Python، تُعرَّف [القيم المنطقية booleans](https://en.wikipedia.org/wiki/Boolean_data_type) على أنها `True` أو `False`، بأحرف كبيرة. فئة البيانات هذه `frozen`، مما يعني أنه لا يمكن تعديل الحقول. + +لاحظ المسافة البادئة. على عكس [اللغات المشتقة من C](https://en.wikipedia.org/wiki/List_of_C-family_programming_languages)، تستخدم لغة Python المسافة البادئة للإشارة إلى الكتل. يعرف مفسر Python أن التعريف التالي ليس جزءًا من فئة البيانات هذه لأنه لا يبدأ بنفس المسافة البادئة لحقول فئة البيانات. + +```python +@dataclass(frozen=True) +class PoolInfo: + address: str + token0: ERC20Token + token1: ERC20Token + contract: Contract + asset: str + decimal_factor: Decimal = 1 +``` + +يُستخدم النوع [`Decimal`](https://docs.python.org/3/library/decimal.html) للتعامل مع الكسور العشرية بدقة. + +```python + def get_price(self, block: int) -> Decimal: +``` + +هذه هي طريقة تعريف دالة في Python. التعريف بمسافة بادئة لإظهار أنه لا يزال جزءًا من `PoolInfo`. + +في دالة تعد جزءًا من فئة بيانات، يكون المعامل الأول دائمًا هو `self`، وهو مثيل فئة البيانات الذي تم استدعاؤه هنا. هنا يوجد معلمة أخرى، رقم الكتلة. + +```python + assert block <= w3.eth.block_number, "Block is in the future" +``` + +إذا استطعنا قراءة المستقبل، فلن نحتاج إلى الذكاء الاصطناعي للتداول. + +```python + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) +``` + +بناء الجملة لاستدعاء دالة على آلة الإيثريوم الافتراضية EVM من Web3 هو كالتالي: `.functions.().call()`. يمكن أن تكون المعلمات هي معلمات دالة آلة الإيثريوم الافتراضية EVM (إن وجدت؛ هنا لا توجد) أو [معلمات مسماة](https://en.wikipedia.org/wiki/Named_parameter) لتعديل سلوك سلسلة الكتل (blockchain). هنا نستخدم واحدًا، `block_identifier`، لتحديد [رقم الكتلة](/developers/docs/apis/json-rpc/#default-block) الذي نرغب في التشغيل فيه. + +النتيجة هي [هذه البنية، في شكل مصفوفة](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol#L56-L72). القيمة الأولى هي دالة لسعر الصرف بين الرمزين. + +```python + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 +``` + +لتقليل الحسابات على السلسلة، لا يقوم Uniswap v3 بتخزين عامل الصرف الفعلي بل جذره التربيعي. نظرًا لأن آلة إيثريوم الافتراضية (EVM) لا تدعم حسابات النقطة العائمة أو الكسور، فبدلاً من القيمة الفعلية، تكون الاستجابة price296 + +```python + # (token1 لكل token0) + return 1/(raw_price * self.decimal_factor) +``` + +السعر الخام الذي نحصل عليه هو عدد `token0` الذي نحصل عليه مقابل كل `token1`. في مجمعنا، `token0` هو USDC (عملة مستقرة بنفس قيمة الدولار الأمريكي) و`token1` هو [WETH](https://opensea.io/learn/blockchain/what-is-weth). القيمة التي نريدها حقًا هي عدد الدولارات لكل WETH، وليس العكس. + +العامل العشري هو النسبة بين [العوامل العشرية](https://docs.openzeppelin.com/contracts/4.x/erc20#a-note-on-decimals) للرمزين. + +```python +@dataclass(frozen=True) +class Quote: + timestamp: str + price: Decimal + asset: str +``` + +تمثل فئة البيانات هذه عرض سعر: سعر أصل معين في نقطة زمنية معينة. في هذه المرحلة، حقل `asset` غير ذي صلة لأننا نستخدم مجمعًا واحدًا وبالتالي لدينا أصل واحد. ومع ذلك، سنضيف المزيد من الأصول لاحقًا. + +```python +def read_token(address: str) -> ERC20Token: + token = w3.eth.contract(address=address, abi=ERC20_ABI) + symbol = token.functions.symbol().call() + decimals = token.functions.decimals().call() + + return ERC20Token( + address=address, + symbol=symbol, + decimals=decimals, + contract=token + ) +``` + +تأخذ هذه الدالة عنوانًا وتعيد معلومات حول عقد الرمز المميز في ذلك العنوان. لإنشاء [عقد Web3 `Contract` جديد](https://web3py.readthedocs.io/en/stable/web3.contract.html)، نوفر العنوان وواجهة التطبيق الثنائية ABI لـ `w3.eth.contract`. + +```python +def read_pool(address: str) -> PoolInfo: + pool_contract = w3.eth.contract(address=address, abi=POOL_ABI) + token0Address = pool_contract.functions.token0().call() + token1Address = pool_contract.functions.token1().call() + token0 = read_token(token0Address) + token1 = read_token(token1Address) + + return PoolInfo( + address=address, + asset=f"{token1.symbol}/{token0.symbol}", + token0=token0, + token1=token1, + contract=pool_contract, + decimal_factor=Decimal(10) ** Decimal(token0.decimals - token1.decimals) + ) +``` + +تعيد هذه الدالة كل ما نحتاجه حول [مجمع معين](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol). البناء `f""` هو [سلسلة نصية منسقة](https://docs.python.org/3/reference/lexical_analysis.html#f-strings). + +```python +def get_quote(pool: PoolInfo, block_number: int = None) -> Quote: +``` + +الحصول على كائن `Quote`. القيمة الافتراضية لـ `block_number` هي `None` (بدون قيمة). + +```python + if block_number is None: + block_number = w3.eth.block_number +``` + +إذا لم يتم تحديد رقم كتلة، فاستخدم `w3.eth.block_number`، وهو أحدث رقم كتلة. هذا هو بناء الجملة لـ[عبارة `if`](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement). + +قد يبدو أنه كان من الأفضل تعيين القيمة الافتراضية على `w3.eth.block_number`، ولكن هذا لا يعمل جيدًا لأنه سيكون رقم الكتلة في وقت تعريف الدالة. في وكيل يعمل لفترة طويلة، ستكون هذه مشكلة. + +```python + block = w3.eth.get_block(block_number) + price = pool.get_price(block_number) + return Quote( + timestamp=datetime.fromtimestamp(block.timestamp, timezone.utc).isoformat(), + price=price.quantize(Decimal("0.01")), + asset=pool.asset + ) +``` + +استخدم [مكتبة `datetime`](https://docs.python.org/3/library/datetime.html) لتنسيقها إلى تنسيق قابل للقراءة من قبل البشر ونماذج اللغة الكبيرة (LLMs). استخدم [`Decimal.quantize`](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) لتقريب القيمة إلى منزلتين عشريتين. + +```python +def get_quotes(pool: PoolInfo, start_block: int, end_block: int, step: int) -> list[Quote]: +``` + +في لغة Python، يمكنك تعريف [قائمة](https://docs.python.org/3/library/stdtypes.html#typesseq-list) لا يمكن أن تحتوي إلا على نوع معين باستخدام `list[]`. + +```python + quotes = [] + for block in range(start_block, end_block + 1, step): +``` + +في Python، تتكرر [حلقة `for`](https://docs.python.org/3/tutorial/controlflow.html#for-statements) عادةً على قائمة. تأتي قائمة أرقام الكتل التي يتم البحث عن عروض الأسعار فيها من [`range`](https://docs.python.org/3/library/stdtypes.html#range). + +```python + quote = get_quote(pool, block) + quotes.append(quote) + return quotes +``` + +لكل رقم كتلة، احصل على كائن `Quote` وأضفه إلى قائمة `quotes`. ثم قم بإرجاع تلك القائمة. + +```python +pool = read_pool(WETHUSDC_ADDRESS) +quotes = get_quotes( + pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) + +pprint(quotes) +``` + +هذا هو الكود الرئيسي للبرنامج النصي. اقرأ معلومات المجمع، واحصل على اثني عشر عرض سعر، وقم بطباعتها بشكل جميل [`pprint`](https://docs.python.org/3/library/pprint.html#pprint.pprint). + +### إنشاء موجه {#prompt} + +بعد ذلك، نحتاج إلى تحويل هذه القائمة من عروض الأسعار إلى موجه لـ LLM والحصول على قيمة مستقبلية متوقعة. + +```sh +git checkout 03-create-prompt +uv run agent.py +``` + +سيكون الإخراج الآن موجهًا إلى LLM، على غرار: + +``` +بالنظر إلى عروض الأسعار هذه: +الأصل: WETH/USDC + 2026-01-20T16:34 3016.21 + . + . + . + 2026-02-01T17:49 2299.10 + +الأصل: WBTC/WETH + 2026-01-20T16:34 29.84 + . + . + . + 2026-02-01T17:50 33.46 + + +ماذا تتوقع أن تكون قيمة WETH/USDC في الوقت 2026-02-02T17:56؟ + +قدم إجابتك كرقم واحد مقرب إلى منزلتين عشريتين، +بدون أي نص آخر. +``` + +لاحظ أن هناك عروض أسعار لأصلين هنا، `WETH/USDC` و`WBTC/WETH`. قد تؤدي إضافة عروض أسعار من أصل آخر إلى تحسين دقة التنبؤ. + +#### كيف يبدو الموجه {#prompt-explanation} + +يحتوي هذا الموجه على ثلاثة أقسام، وهي شائعة جدًا في موجهات LLM. + +1. المعلومات. تحتوي نماذج اللغة الكبيرة على الكثير من المعلومات من تدريبها، لكنها عادة لا تملك الأحدث. هذا هو سبب حاجتنا إلى استرداد أحدث عروض الأسعار هنا. تسمى إضافة المعلومات إلى موجه [التوليد المعزز بالاسترداد (RAG)](https://en.wikipedia.org/wiki/Retrieval-augmented_generation). + +2. السؤال الفعلي. هذا ما نريد أن نعرفه. + +3. تعليمات تنسيق الإخراج. عادة، سيعطينا نموذج اللغة الكبير تقديرًا مع شرح لكيفية وصوله إليه. هذا أفضل للبشر، لكن برنامج الكمبيوتر يحتاج فقط إلى الخلاصة. + +#### شرح الكود {#prompt-code} + +ها هو الكود الجديد. + +```python +from datetime import datetime, timezone, timedelta +``` + +نحتاج إلى تزويد LLM بالوقت الذي نريد تقديرًا له. للحصول على وقت "n دقيقة/ساعة/يوم" في المستقبل، نستخدم [فئة `timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta). + +```python +# عناوين المجمعات التي نقرأها +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +WETHWBTC_ADDRESS = Web3.to_checksum_address("0xCBCdF9626bC03E24f779434178A73a0B4bad62eD") +``` + +لدينا مجمعان نحتاج إلى قراءتهما. + +```python +@dataclass(frozen=True) +class PoolInfo: + . + . + . + reverse: bool = False + + def get_price(self, block: int) -> Decimal: + assert block <= w3.eth.block_number, "Block is in the future" + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 # (token1 per token0) + if self.reverse: + return 1/(raw_price * self.decimal_factor) + else: + return raw_price * self.decimal_factor +``` + +في مجمع WETH/USDC، نريد أن نعرف كم عدد `token0` (USDC) الذي نحتاجه لشراء واحد من `token1` (WETH). في مجمع WETH/WBTC، نريد أن نعرف كم عدد `token1` (WETH) الذي نحتاجه لشراء واحد `token0` (WBTC، وهو بيتكوين مغلف). نحتاج إلى تتبع ما إذا كانت نسبة المجمع بحاجة إلى عكسها. + +```python +def read_pool(address: str, reverse: bool = False) -> PoolInfo: + . + . + . + + return PoolInfo( + . + . + . + + asset= f"{token1.symbol}/{token0.symbol}" if reverse else f"{token0.symbol}/{token1.symbol}", + reverse=reverse + ) +``` + +لمعرفة ما إذا كان المجمع بحاجة إلى عكسه، نحصل على ذلك كمدخل إلى `read_pool`. أيضًا، يجب إعداد رمز الأصل بشكل صحيح. + +إن البناء ` if else ` هو المكافئ في لغة Python لـ[المشغل الشرطي الثلاثي](https://en.wikipedia.org/wiki/Ternary_conditional_operator)، والذي سيكون في لغة مشتقة من C ` ? : `. + +```python +def format_quotes(quotes: list[Quote]) -> str: + result = f"Asset: {quotes[0].asset}\n" + for quote in quotes: + result += f"\t{quote.timestamp[0:16]} {quote.price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)}\n" + return result +``` + +تبني هذه الدالة سلسلة نصية تنسق قائمة بكائنات `Quote`، بافتراض أنها تنطبق جميعها على نفس الأصل. + +```python +def make_prompt(quotes: list[list[Quote]], expected_time: str, asset: str) -> str: + return f""" +``` + +في Python، تُكتب [السلاسل النصية الحرفية متعددة الأسطر](https://www.w3schools.com/python/gloss_python_multi_line_strings.asp) على النحو التالي: `"""` .... `"""`. + +```python +Given these quotes: +{ + functools.reduce(lambda acc, q: acc + '\n' + q, + map(lambda q: format_quotes(q), quotes)) +} +``` + +هنا، نستخدم نمط [MapReduce](https://en.wikipedia.org/wiki/MapReduce) لإنشاء سلسلة نصية لكل قائمة عرض أسعار باستخدام `format_quotes`، ثم نختصرها إلى سلسلة نصية واحدة لاستخدامها في الموجه. + +```python +What would you expect the value for {asset} to be at time {expected_time}? + +Provide your answer as a single number rounded to two decimal places, +without any other text. + """ +``` + +بقية الموجه كما هو متوقع. + +```python +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +راجع المجمعين واحصل على عروض أسعار من كليهما. + +```python +future_time = (datetime.now(timezone.utc) + timedelta(days=1)).isoformat()[0:16] + +print(make_prompt(wethusdc_quotes + wethwbtc_quotes, future_time, wethusdc_pool.asset)) +``` + +حدد النقطة الزمنية المستقبلية التي نريد التقدير لها، وقم بإنشاء الموجه. + +### التفاعل مع LLM {#interface-llm} + +بعد ذلك، نقوم بتوجيه LLM فعلي ونحصل على قيمة مستقبلية متوقعة. لقد كتبت هذا البرنامج باستخدام OpenAI، لذا إذا كنت تريد استخدام مزود مختلف، فستحتاج إلى تعديله. + +1. احصل على [حساب OpenAI](https://auth.openai.com/create-account) + +2. [قم بتمويل الحساب](https://platform.openai.com/settings/organization/billing/overview)—الحد الأدنى للمبلغ في وقت كتابة هذا التقرير هو 5 دولارات + +3. [أنشئ مفتاح واجهة برمجة تطبيقات](https://platform.openai.com/settings/organization/api-keys) + +4. في سطر الأوامر، قم بتصدير مفتاح واجهة برمجة التطبيقات حتى يتمكن برنامجك من استخدامه + + ```sh + export OPENAI_API_KEY=sk-<بقية المفتاح هنا> + ``` + +5. سحب الوكيل وتشغيله + + ```sh + git checkout 04-interface-llm + uv run agent.py + ``` + +ها هو الكود الجديد. + +```python +from openai import OpenAI + +open_ai = OpenAI() # يقرأ العميل متغير البيئة OPENAI_API_KEY +``` + +قم باستيراد واجهة برمجة تطبيقات OpenAI وإنشاء مثيل لها. + +```python +response = open_ai.chat.completions.create( + model="gpt-4-turbo", + messages=[ + {"role": "user", "content": prompt} + ], + temperature=0.0, + max_tokens=16, +) +``` + +استدعاء واجهة برمجة تطبيقات OpenAI (`open_ai.chat.completions.create`) لإنشاء الاستجابة. + +```python +expected_price = Decimal(response.choices[0].message.content.strip()) +current_price = wethusdc_quotes[-1].price + +print ("Current price:", wethusdc_quotes[-1].price) +print(f"In {future_time}, expected price: {expected_price} USD") + +if (expected_price > current_price): + print(f"Buy, I expect the price to go up by {expected_price - current_price} USD") +else: + print(f"Sell, I expect the price to go down by {current_price - expected_price} USD") +``` + +إخراج السعر وتقديم توصية بالشراء أو البيع. + +#### اختبار التنبؤات {#testing-the-predictions} + +الآن بعد أن أصبح بإمكاننا إنشاء تنبؤات، يمكننا أيضًا استخدام البيانات التاريخية لتقييم ما إذا كنا ننتج تنبؤات مفيدة. + +```sh +uv run test-predictor.py +``` + +النتيجة المتوقعة مشابهة لـ: + +``` +التنبؤ لـ 2026-01-05T19:50: التنبؤ 3138.93 دولارًا أمريكيًا، الحقيقي 3218.92 دولارًا أمريكيًا، الخطأ 79.99 دولارًا أمريكيًا +التنبؤ لـ 2026-01-06T19:56: التنبؤ 3243.39 دولارًا أمريكيًا، الحقيقي 3221.08 دولارًا أمريكيًا، الخطأ 22.31 دولارًا أمريكيًا +التنبؤ لـ 2026-01-07T20:02: التنبؤ 3223.24 دولارًا أمريكيًا، الحقيقي 3146.89 دولارًا أمريكيًا، الخطأ 76.35 دولارًا أمريكيًا +التنبؤ لـ 2026-01-08T20:11: التنبؤ 3150.47 دولارًا أمريكيًا، الحقيقي 3092.04 دولارًا أمريكيًا، الخطأ 58.43 دولارًا أمريكيًا +. +. +. +التنبؤ لـ 2026-01-31T22:33: التنبؤ 2637.73 دولارًا أمريكيًا، الحقيقي 2417.77 دولارًا أمريكيًا، الخطأ 219.96 دولارًا أمريكيًا +التنبؤ لـ 2026-02-01T22:41: التنبؤ 2381.70 دولارًا أمريكيًا، الحقيقي 2318.84 دولارًا أمريكيًا، الخطأ 62.86 دولارًا أمريكيًا +التنبؤ لـ 2026-02-02T22:49: التنبؤ 2234.91 دولارًا أمريكيًا، الحقيقي 2349.28 دولارًا أمريكيًا، الخطأ 114.37 دولارًا أمريكيًا +متوسط خطأ التنبؤ على مدار 29 تنبؤًا: 83.87103448275862068965517241 دولارًا أمريكيًا +متوسط التغيير لكل توصية: 4.787931034482758620689655172 دولار أمريكي +التباين المعياري للتغيرات: 104.42 دولار أمريكي +أيام مربحة: 51.72% +أيام خاسرة: 48.28% +``` + +معظم المختبر مطابق للوكيل، ولكن إليك الأجزاء الجديدة أو المعدلة. + +```python +CYCLES_FOR_TEST = 40 # للاختبار الخلفي، كم عدد الدورات التي نختبرها + +# الحصول على الكثير من عروض الأسعار +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +نحن ننظر إلى `CYCLES_FOR_TEST` (المحدد هنا بـ 40) يومًا إلى الوراء. + +```python +# إنشاء تنبؤات والتحقق منها مقابل التاريخ الحقيقي + +total_error = Decimal(0) +changes = [] +``` + +هناك نوعان من الأخطاء التي نهتم بها. الأول، `total_error`، هو ببساطة مجموع الأخطاء التي ارتكبها المتنبئ. + +لفهم الثاني، `changes`، نحتاج إلى تذكر غرض الوكيل. ليس التنبؤ بنسبة WETH/USDC (سعر ETH). بل إصدار توصيات البيع والشراء. إذا كان السعر حاليًا 2000 دولار وتنبأ بـ 2010 دولارات غدًا، فإننا لا نمانع إذا كانت النتيجة الفعلية 2020 دولارًا وحققنا أموالًا إضافية. لكننا نمانع إذا تنبأ بـ 2010 دولارات، واشترى ETH بناءً على تلك التوصية، وانخفض السعر إلى 1990 دولارًا. + +```python +for index in range(0,len(wethusdc_quotes)-CYCLES_BACK): +``` + +لا يمكننا النظر إلا في الحالات التي يتوفر فيها السجل الكامل (القيم المستخدمة للتنبؤ والقيمة الحقيقية لمقارنتها بها). وهذا يعني أن أحدث حالة يجب أن تكون تلك التي بدأت قبل `CYCLES_BACK`. + +```python + wethusdc_slice = wethusdc_quotes[index:index+CYCLES_BACK] + wethwbtc_slice = wethwbtc_quotes[index:index+CYCLES_BACK] +``` + +استخدم [شرائح](https://www.w3schools.com/python/ref_func_slice.asp) للحصول على نفس عدد العينات التي يستخدمها الوكيل. الكود بين هنا والجزء التالي هو نفس كود الحصول على التنبؤ الموجود لدينا في الوكيل. + +```python + predicted_price = Decimal(response.choices[0].message.content.strip()) + real_price = wethusdc_quotes[index+CYCLES_BACK].price + prediction_time_price = wethusdc_quotes[index+CYCLES_BACK-1].price +``` + +احصل على السعر المتوقع والسعر الحقيقي والسعر وقت التنبؤ. نحتاج إلى السعر وقت التنبؤ لتحديد ما إذا كانت التوصية بالشراء أو البيع. + +```python + error = abs(predicted_price - real_price) + total_error += error + print (f"Prediction for {prediction_time}: predicted {predicted_price} USD, real {real_price} USD, error {error} USD") +``` + +احسب الخطأ، وأضفه إلى الإجمالي. + +```python + recomended_action = 'buy' if predicted_price > prediction_time_price else 'sell' + price_increase = real_price - prediction_time_price + changes.append(price_increase if recomended_action == 'buy' else -price_increase) +``` + +بالنسبة لـ `changes`، نريد التأثير النقدي لشراء أو بيع عملة ETH واحدة. لذا أولاً، نحتاج إلى تحديد التوصية، ثم تقييم كيفية تغير السعر الفعلي، وما إذا كانت التوصية قد حققت ربحًا (تغيير إيجابي) أو كلفت أموالًا (تغيير سلبي). + +```python +print (f"Mean prediction error over {len(wethusdc_quotes)-CYCLES_BACK} predictions: {total_error / Decimal(len(wethusdc_quotes)-CYCLES_BACK)} USD") + +length_changes = Decimal(len(changes)) +mean_change = sum(changes, Decimal(0)) / length_changes +print (f"Mean change per recommendation: {mean_change} USD") +var = sum((x - mean_change) ** 2 for x in changes) / length_changes +print (f"Standard variance of changes: {var.sqrt().quantize(Decimal("0.01"))} USD") +``` + +تقرير النتائج. + +```python +print (f"Profitable days: {len(list(filter(lambda x: x > 0, changes)))/length_changes:.2%}") +print (f"Losing days: {len(list(filter(lambda x: x < 0, changes)))/length_changes:.2%}") +``` + +استخدم [`filter`](https://www.w3schools.com/python/ref_func_filter.asp) لحساب عدد الأيام المربحة وعدد الأيام المكلفة. النتيجة هي كائن مرشح، والذي نحتاج إلى تحويله إلى قائمة للحصول على الطول. + +### إرسال المعاملات {#submit-txn} + +الآن نحن بحاجة إلى إرسال المعاملات بالفعل. ومع ذلك، لا أريد إنفاق أموال حقيقية في هذه المرحلة، قبل إثبات النظام. بدلاً من ذلك، سننشئ انقسام محلي للشبكة الرئيسية، و "نتداول" على تلك الشبكة. + +فيما يلي خطوات إنشاء انقسام محلي وتمكين التداول. + +1. قم بتثبيت [Foundry](https://getfoundry.sh/introduction/installation) + +2. ابدأ [`anvil`](https://getfoundry.sh/anvil/overview) + + ```sh + anvil --fork-url https://eth.drpc.org --block-time 12 + ``` + + يستمع `anvil` على عنوان URL الافتراضي لـ Foundry، http://localhost:8545، لذلك لا نحتاج إلى تحديد عنوان URL لأمر `cast` الذي نستخدمه لمعالجة سلسلة الكتل (blockchain). + +3. عند التشغيل في `anvil`، هناك عشرة حسابات اختبار تحتوي على ETH—قم بتعيين متغيرات البيئة للحساب الأول + + ```sh + PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ADDRESS=`cast wallet address $PRIVATE_KEY` + ``` + +4. هذه هي العقود التي نحتاج إلى استخدامها. [`SwapRouter`](https://github.com/Uniswap/v3-periphery/blob/main/contracts/SwapRouter.sol) هو عقد Uniswap v3 الذي نستخدمه للتداول الفعلي. يمكننا التداول مباشرة من خلال المجمع، ولكن هذا أسهل بكثير. + + المتغيران السفليان هما مسارات Uniswap v3 المطلوبة للتبديل بين WETH وUSDC. + + ```sh + WETH_ADDRESS=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + USDC_ADDRESS=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + POOL_ADDRESS=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 + SWAP_ROUTER=0xE592427A0AEce92De3Edee1F18E0157C05861564 + WETH_TO_USDC=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + USDC_TO_WETH=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + ``` + +5. يحتوي كل حساب من حسابات الاختبار على 10000 ETH. استخدم عقد WETH لتغليف 1000 ETH للحصول على 1000 WETH للتداول. + + ```sh + cast send $WETH_ADDRESS "deposit()" --value 1000ether --private-key $PRIVATE_KEY + ``` + +6. استخدم `SwapRouter` لتداول 500 WETH مقابل USDC. + + ```sh + cast send $WETH_ADDRESS "approve(address,uint256)" $SWAP_ROUTER 500ether --private-key $PRIVATE_KEY + MAXINT=`cast max-int uint256` + cast send $SWAP_ROUTER \ + "exactInput((bytes,address,uint256,uint256,uint256))" \ + "($WETH_TO_USDC,$ADDRESS,$MAXINT,500ether,1000000)" \ + --private-key $PRIVATE_KEY + ``` + + ينشئ استدعاء `approve` بدلًا يسمح لـ `SwapRouter` بإنفاق بعض رموزنا. لا يمكن للعقود مراقبة الأحداث، لذلك إذا قمنا بنقل الرموز المميزة مباشرة إلى عقد `SwapRouter`، فلن يعرف أنه تم الدفع له. بدلاً من ذلك، نسمح لعقد `SwapRouter` بإنفاق مبلغ معين، ثم يقوم `SwapRouter` بذلك. يتم ذلك من خلال دالة يستدعيها `SwapRouter`، لذلك يعرف ما إذا كانت ناجحة. + +7. تحقق من أن لديك ما يكفي من كلا الرمزين. + + ```sh + cast call $WETH_ADDRESS "balanceOf(address)" $ADDRESS | cast from-wei + echo `cast call $USDC_ADDRESS "balanceOf(address)" $ADDRESS | cast to-dec`/10^6 | bc + ``` + +الآن بعد أن أصبح لدينا WETH وUSDC، يمكننا تشغيل الوكيل بالفعل. + +```sh +git checkout 05-trade +uv run agent.py +``` + +سيبدو الإخراج مشابهًا لـ: + +``` +(ai-trading-agent) qbzzt@Ori-Cloudnomics:~/260215-ai-agent$ uv run agent.py +السعر الحالي: 1843.16 +في 2026-02-06T23:07، السعر المتوقع: 1724.41 دولار أمريكي +أرصدة الحسابات قبل التداول: +رصيد USDC: 927301.578272 +رصيد WETH: 500 +بيع، أتوقع أن ينخفض السعر بمقدار 118.75 دولارًا أمريكيًا +تم إرسال معاملة الموافقة: 74e367ddbb407c1aaf567d87aa5863049991b1d2aa092b6b85195d925e2bd41f +تم تعدين معاملة الموافقة. +تم إرسال معاملة البيع: fad1bcf938585c9e90364b26ac7a80eea9efd34c37e5db81e58d7655bcae28bf +تم تعدين معاملة البيع. +أرصدة الحسابات بعد التداول: +رصيد USDC: 929143.797116 +رصيد WETH: 499 +``` + +لاستخدامه بالفعل، تحتاج إلى بعض التغييرات الطفيفة. + +- في السطر 14، قم بتغيير `MAINNET_URL` إلى نقطة وصول حقيقية، مثل `https://eth.drpc.org` +- في السطر 28، قم بتغيير `PRIVATE_KEY` إلى مفتاحك الخاص +- ما لم تكن ثريًا جدًا ويمكنك شراء أو بيع 1 ETH كل يوم لوكيل غير مثبت، فقد ترغب في تغيير 29 لتقليل `WETH_TRADE_AMOUNT` + +#### شرح الكود {#trading-code} + +ها هو الكود الجديد. + +```python +SWAP_ROUTER_ADDRESS=Web3.to_checksum_address("0xE592427A0AEce92De3Edee1F18E0157C05861564") +WETH_TO_USDC=bytes.fromhex("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") +USDC_TO_WETH=bytes.fromhex("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +``` + +نفس المتغيرات التي استخدمناها في الخطوة 4. + +```python +WETH_TRADE_AMOUNT=1 +``` + +المبلغ المراد تداوله. + +```python +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... }, + { "name": "balanceOf", ...}, + { "name": "approve", ...} +] +``` + +للتداول فعليًا، نحتاج إلى وظيفة `approve`. نريد أيضًا إظهار الأرصدة قبل وبعد، لذلك نحتاج أيضًا إلى `balanceOf`. + +```python +SWAP_ROUTER_ABI = [ + { "name": "exactInput", ...}, +] +``` + +في واجهة التطبيق الثنائية `SwapRouter`، نحتاج فقط إلى `exactInput`. هناك وظيفة ذات صلة، `exactOutput`، يمكننا استخدامها لشراء WETH واحد بالضبط، ولكن من أجل البساطة نستخدم `exactInput` فقط في كلتا الحالتين. + +```python +account = w3.eth.account.from_key(PRIVATE_KEY) +swap_router = w3.eth.contract( + address=SWAP_ROUTER_ADDRESS, + abi=SWAP_ROUTER_ABI +) +``` + +تعريفات Web3 للحساب `account` ([https://web3py.readthedocs.io/en/stable/web3.eth.account.html](https://web3py.readthedocs.io/en/stable/web3.eth.account.html)) وعقد `SwapRouter`. + +```python +def txn_params() -> dict: + return { + "from": account.address, + "value": 0, + "gas": 300000, + "nonce": w3.eth.get_transaction_count(account.address), + } +``` + +معلمات المعاملة. نحتاج إلى وظيفة هنا لأن [النون](https://en.wikipedia.org/wiki/Cryptographic_nonce) يجب أن يتغير في كل مرة. + +```python +def approve_token(contract: Contract, amount: int): +``` + +الموافقة على بدل رمز مميز لـ `SwapRouter`. + +```python + txn = contract.functions.approve(SWAP_ROUTER_ADDRESS, amount).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) +``` + +هذه هي الطريقة التي نرسل بها معاملة في Web3. أولاً نستخدم كائن `Contract` ([https://web3py.readthedocs.io/en/stable/web3.contract.html](https://web3py.readthedocs.io/en/stable/web3.contract.html)) لبناء المعاملة. ثم نستخدم `web3.eth.account.sign_transaction` ([https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-contract-transaction](https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-contract-transaction)) لتوقيع المعاملة، باستخدام `PRIVATE_KEY`. أخيرًا، نستخدم `w3.eth.send_raw_transaction` ([https://web3py.readthedocs.io/en/stable/transactions.html#chapter-2-w3-eth-send-raw-transaction](https://web3py.readthedocs.io/en/stable/transactions.html#chapter-2-w3-eth-send-raw-transaction)) لإرسال المعاملة. + +```python + print(f"Approve transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Approve transaction mined.") +``` + +تنتظر `w3.eth.wait_for_transaction_receipt` ([https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.wait_for_transaction_receipt](https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.wait_for_transaction_receipt)) حتى يتم تعدين المعاملة. يعيد الإيصال إذا لزم الأمر. + +```python +SELL_PARAMS = { + "path": WETH_TO_USDC, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": WETH_TRADE_AMOUNT * 10 ** wethusdc_pool.token1.decimals, + "amountOutMinimum": 0, +} +``` + +هذه هي المعلمات عند بيع WETH. + +```python +def make_buy_params(quote: Quote) -> dict: + return { + "path": USDC_TO_WETH, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": int(quote.price*WETH_TRADE_AMOUNT) * 10**wethusdc_pool.token0.decimals, + "amountOutMinimum": 0, + } +``` + +على عكس `SELL_PARAMS`، يمكن أن تتغير معلمات الشراء. مبلغ الإدخال هو تكلفة 1 WETH، كما هو متاح في `quote`. + +```python +def buy(quote: Quote): + buy_params = make_buy_params(quote) + approve_token(wethusdc_pool.token0.contract, buy_params["amountIn"]) + txn = swap_router.functions.exactInput(buy_params).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Buy transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Buy transaction mined.") + + +def sell(): + approve_token(wethusdc_pool.token1.contract, + WETH_TRADE_AMOUNT * 10**wethusdc_pool.token1.decimals) + txn = swap_router.functions.exactInput(SELL_PARAMS).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Sell transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Sell transaction mined.") +``` + +وظائف `buy()` و `sell()` متطابقة تقريبًا. أولاً، نوافق على بدل كافٍ لـ `SwapRouter`، ثم نستدعيه بالمسار والمبلغ الصحيحين. + +```python +def balances(): + token0_balance = wethusdc_pool.token0.contract.functions.balanceOf(account.address).call() + token1_balance = wethusdc_pool.token1.contract.functions.balanceOf(account.address).call() + + print(f"{wethusdc_pool.token0.symbol} Balance: {Decimal(token0_balance) / Decimal(10 ** wethusdc_pool.token0.decimals)}") + print(f"{wethusdc_pool.token1.symbol} Balance: {Decimal(token1_balance) / Decimal(10 ** wethusdc_pool.token1.decimals)}") +``` + +تقرير أرصدة المستخدم بالعملتين. + +```python +print("أرصدة الحساب قبل التداول:") +balances() + +if (expected_price > current_price): + print(f"شراء، أتوقع أن يرتفع السعر بمقدار {expected_price - current_price} دولار أمريكي") + buy(wethusdc_quotes[-1]) +else: + print(f"بيع، أتوقع أن ينخفض السعر بمقدار {current_price - expected_price} دولار أمريكي") + sell() + +print("أرصدة الحساب بعد التداول:") +balances() +``` + +يعمل هذا الوكيل حاليًا مرة واحدة فقط. ومع ذلك، يمكنك تغييره للعمل بشكل مستمر إما عن طريق تشغيله من [`crontab`](https://man7.org/linux/man-pages/man1/crontab.1.html) أو عن طريق تغليف الأسطر 368-400 في حلقة واستخدام [`time.sleep`](https://docs.python.org/3/library/time.html#time.sleep) للانتظار حتى يحين وقت الدورة التالية. + +## التحسينات الممكنة {#improvements} + +هذه ليست نسخة إنتاج كاملة؛ إنها مجرد مثال لتعليم الأساسيات. فيما يلي بعض الأفكار للتحسينات. + +### تداول أذكى {#smart-trading} + +هناك حقيقتان مهمتان يتجاهلهما الوكيل عند تحديد ما يجب القيام به. + +- _حجم التغيير المتوقع_. يبيع الوكيل كمية ثابتة من `WETH` إذا كان من المتوقع أن ينخفض السعر، بغض النظر عن حجم الانخفاض. + يمكن القول إنه من الأفضل تجاهل التغييرات الطفيفة والبيع بناءً على مدى توقعنا لانخفاض السعر. +- _المحفظة الحالية_. إذا كانت 10% من محفظتك في WETH وتعتقد أن السعر سيرتفع، فمن المحتمل أن يكون من المنطقي شراء المزيد. ولكن إذا كانت 90% من محفظتك في WETH، فقد تكون معرضًا بشكل كافٍ، وليست هناك حاجة لشراء المزيد. والعكس صحيح إذا كنت تتوقع أن ينخفض السعر. + +### ماذا لو كنت تريد أن تبقي استراتيجية التداول الخاصة بك سرية؟ {#secret} + +يمكن لبائعي الذكاء الاصطناعي رؤية الاستعلامات التي ترسلها إلى نماذج اللغة الكبيرة الخاصة بهم، مما قد يكشف عن نظام التداول العبقري الذي طورته مع وكيلك. نظام التداول الذي يستخدمه عدد كبير جدًا من الأشخاص لا قيمة له لأن عددًا كبيرًا جدًا من الأشخاص يحاولون الشراء عندما تريد الشراء (ويرتفع السعر) ويحاولون البيع عندما تريد البيع (وينخفض السعر). + +يمكنك تشغيل LLM محليًا، على سبيل المثال، باستخدام [LM-Studio](https://lmstudio.ai/)، لتجنب هذه المشكلة. + +### من بوت الذكاء الاصطناعي إلى وكيل الذكاء الاصطناعي {#bot-to-agent} + +يمكنك تقديم حجة جيدة بأن هذا [بوت ذكاء اصطناعي، وليس وكيل ذكاء اصطناعي](/ai-agents/#ai-agents-vs-ai-bots). إنه يطبق استراتيجية بسيطة نسبيًا تعتمد على معلومات محددة مسبقًا. يمكننا تمكين التحسين الذاتي، على سبيل المثال، من خلال توفير قائمة بمجمعات Uniswap v3 وأحدث قيمها والسؤال عن المجموعة التي لديها أفضل قيمة تنبؤية. + +### الحماية من الانزلاق {#slippage-protection} + +حاليًا لا توجد [حماية من الانزلاق](https://uniswapv3book.com/milestone_3/slippage-protection.html). إذا كان السعر الحالي 2000 دولار، والسعر المتوقع 2100 دولار، فسيقوم الوكيل بالشراء. ومع ذلك، إذا ارتفعت التكلفة إلى 2200 دولار قبل أن يشتري الوكيل، فلن يكون هناك معنى للشراء بعد الآن. + +لتنفيذ الحماية من الانزلاق، حدد قيمة `amountOutMinimum` في السطرين 325 و 334 من [`agent.py`](https://github.com/qbzzt/260215-ai-agent/blob/05-trade/agent.py#L325). + +## الخلاصة {#conclusion} + +نأمل أن تعرف الآن ما يكفي للبدء في استخدام وكلاء الذكاء الاصطناعي. هذه ليست نظرة عامة شاملة على الموضوع؛ فهناك كتب كاملة مخصصة لذلك، لكن هذا يكفي لتبدأ. حظ سعيد! + +[انظر هنا لمزيد من أعمالي](https://cryptodocguy.pro/). diff --git a/public/content/translations/bn/community/support/faq/index.md b/public/content/translations/bn/community/support/faq/index.md new file mode 100644 index 00000000000..ba98f4926bc --- /dev/null +++ b/public/content/translations/bn/community/support/faq/index.md @@ -0,0 +1,77 @@ +--- +title: "সাধারণত জিজ্ঞাসিত প্রশ্নসমুহ" +description: "ওয়ালেট, লেনদেন, স্টেকিং এবং আরও অনেক কিছু সম্পর্কে সাধারণ ইথেরিয়াম প্রশ্ন।" +lang: bn +--- + +# সাধারণত জিজ্ঞাসিত প্রশ্নসমূহ {#faq} + +## আমি ভুল অ্যাড্রেসে ক্রিপ্টো পাঠিয়েছি {#wrong-wallet} + +ইথেরিয়ামে পাঠানো একটি লেনদেন অপরিবর্তনীয়। দুর্ভাগ্যবশত, আপনি যদি ভুল ওয়ালেটে ETH বা টোকেন পাঠিয়ে থাকেন, তাহলে লেনদেনটি ফিরিয়ে আনার কোনো উপায় নেই। + +**আপনি যা করতে পারেন:** + +- **আপনি যদি অ্যাড্রেসের মালিককে চেনেন**, তাহলে সরাসরি তাদের সাথে যোগাযোগ করুন এবং তাদের তহবিল ফেরত দিতে বলুন। +- **যদি অ্যাড্রেসটি কোনো এক্সচেঞ্জ বা পরিচিত পরিষেবার হয়**, তবে তাদের সহায়তা দলের সাথে যোগাযোগ করুন, কারণ তারা সাহায্য করতে পারে। +- **আপনি যদি কোনো কন্ট্রাক্ট অ্যাড্রেসে টোকেন পাঠিয়ে থাকেন**, তাহলে কন্ট্রাক্টটিতে কোনো উইথড্রয়াল বা রিকভারি ফাংশন আছে কিনা তা পরীক্ষা করুন (এটি বিরল)। + +বেশিরভাগ ক্ষেত্রে, তহবিল পুনরুদ্ধার করার কোনো উপায় নেই। কোনো কেন্দ্রীয় সংস্থা, সত্তা বা ব্যক্তি ইথেরিয়ামের মালিক নয়, যার মানে কেউ লেনদেন বিপরীত করতে পারে না। নিশ্চিত করার আগে সর্বদা প্রাপকের অ্যাড্রেস দুবার পরীক্ষা করুন। + +## আমি আমার ওয়ালেটের অ্যাক্সেস হারিয়ে ফেলেছি {#lost-wallet-access} + +আপনার পুনরুদ্ধারের বিকল্পগুলি আপনি যে ধরনের ওয়ালেট ব্যবহার করেন তার উপর নির্ভর করে। + +### আপনার যদি আপনার সীড ফ্রেজ (রিকভারি ফ্রেজ) থাকে + +আপনি আপনার সীড ফ্রেজ ব্যবহার করে যেকোনো সামঞ্জস্যপূর্ণ ওয়ালেট অ্যাপে আপনার ওয়ালেট পুনরুদ্ধার করতে পারেন। এই কারণেই আপনার সীড ফ্রেজ নিরাপদে অফলাইনে সংরক্ষণ করা অত্যন্ত গুরুত্বপূর্ণ। পুনরুদ্ধারের নির্দেশাবলীর জন্য আপনার ওয়ালেট প্রদানকারীর ডকুমেন্টেশন পরীক্ষা করুন। + +### আপনি যদি আপনার সীড ফ্রেজ হারিয়ে ফেলেন + +আপনার সীড ফ্রেজ বা প্রাইভেট কী ছাড়া, আপনার তহবিল পুনরুদ্ধার করা যাবে না। ethereum.org সহ কেউই আপনার পাসওয়ার্ড রিসেট করতে বা একটি সেলফ-কাস্টডি ওয়ালেটের অ্যাক্সেস পুনরুদ্ধার করতে পারে না। + +### আপনার অ্যাকাউন্ট যদি কোনো এক্সচেঞ্জে থাকে + +আপনার অ্যাকাউন্ট যদি Coinbase, Binance, বা Kraken-এর মতো একটি সেন্ট্রালাইডড এক্সচেঞ্জে থাকে, তাহলে সরাসরি এক্সচেঞ্জের সহায়তা দলের সাথে যোগাযোগ করুন। তারা তাদের প্ল্যাটফর্মে অ্যাকাউন্ট নিয়ন্ত্রণ করে এবং পাসওয়ার্ড রিসেট বা অ্যাকাউন্ট পুনরুদ্ধারে সাহায্য করতে পারে। + + + + + + +**আপনার ওয়ালেট পুনরুদ্ধার করতে সাহায্য করার দাবিদার কারো সাথে আপনার সীড ফ্রেজ শেয়ার করবেন না**। এটি সবচেয়ে সাধারণ স্ক্যাম কৌশলগুলির মধ্যে একটি। কোনো বৈধ পরিষেবা কখনোই আপনার সীড ফ্রেজ চাইবে না। + + + + + + কিভাবে একটি ওয়ালেট ব্যবহার করতে হয় + + +## আমার লেনদেন আটকে আছে বা মুলতুবি আছে {#stuck-transaction} + +ইথেরিয়ামে লেনদেন আটকে যেতে পারে যখন আপনার সেট করা গ্যাস ফি নেটওয়ার্কের বর্তমান প্রয়োজনের চেয়ে কম থাকে। বেশিরভাগ ওয়ালেট আপনাকে এটি ঠিক করতে দেয়: + +- **দ্রুত করুন:** উচ্চতর গ্যাস ফি সহ একই লেনদেন পুনরায় জমা দিন +- **বাতিল করুন:** মুলতুবি লেনদেনের মতো একই নন্স ব্যবহার করে আপনার নিজের অ্যাড্রেসে একটি 0 ETH লেনদেন পাঠান + +### সহায়ক নির্দেশিকা + +- [MetaMask-এ একটি মুলতুবি থাকা লেনদেন কীভাবে দ্রুত বা বাতিল করবেন](https://support.metamask.io/transactions-and-gas/transactions/how-to-speed-up-or-cancel-a-pending-transaction/) +- [অমীমাংসিত ইথেরিয়াম লেনদেন কীভাবে বাতিল করবেন](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) + +## আমি কীভাবে আমার ইথেরিয়াম গিভঅ্যাওয়ে দাবি করতে পারি? {#giveaway-scam} + +ইথেরিয়াম গিভঅ্যাওয়ে হল আপনার ETH চুরি করার জন্য ডিজাইন করা স্ক্যাম। যে অফারগুলো বিশ্বাসযোগ্য নয় সেগুলোর প্রতি প্রলুব্ধ হবেন না। আপনি যদি কোনো গিভঅ্যাওয়ে অ্যাড্রেসে ETH পাঠান, তাহলে আপনি কোনো গিভঅ্যাওয়ে পাবেন না, এবং আপনি আপনার তহবিল পুনরুদ্ধার করতে পারবেন না। + +[স্ক্যাম প্রতিরোধ সম্পর্কে আরও জানুন](/security/#common-scams) + +## আমি কীভাবে ETH স্টেক করব? {#how-to-stake} + +একজন ভ্যালিডেটর হতে, আপনাকে অবশ্যই ইথেরিয়াম ডিপোজিট কন্ট্রাক্টে 32 ETH স্টেক করতে হবে এবং একটি ভ্যালিডেটর নোড সেট আপ করতে হবে। আপনি স্টেকিং পুলের মাধ্যমে কম ETH দিয়েও অংশগ্রহণ করতে পারেন। + +আরও তথ্য আমাদের [স্টেকিং পৃষ্ঠাগুলিতে](/staking/) এবং [স্টেকিং লঞ্চপ্যাডে](https://launchpad.ethereum.org/) উপলব্ধ। + +## আমি কীভাবে ইথেরিয়াম মাইন করব? {#mining-ethereum} + +ইথেরিয়াম মাইনিং আর সম্ভব নয়। সেপ্টেম্বর ২০২২-এ [দ্য মার্জ](/roadmap/merge/)-এর সময় যখন ইথেরিয়াম [প্রুফ-অফ-ওয়ার্ক](/glossary/#pow) থেকে [প্রুফ-অফ-স্টেক](/glossary/#pos)-এ স্থানান্তরিত হয়েছিল তখন মাইনিং বন্ধ করে দেওয়া হয়েছিল। এখন, মাইনারদের পরিবর্তে, ইথেরিয়ামে ভ্যালিডেটর রয়েছে। নেটওয়ার্ক সুরক্ষিত করার জন্য যে কেউ ETH [স্টেক](/glossary/#staking) করতে পারেন এবং ভ্যালিডেটর সফ্টওয়্যার চালানোর জন্য স্টেকিং পুরস্কার পেতে পারেন। diff --git a/public/content/translations/bn/community/support/index.md b/public/content/translations/bn/community/support/index.md deleted file mode 100644 index 04bb167e3fb..00000000000 --- a/public/content/translations/bn/community/support/index.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: "ইথেরিয়াম সাপোর্ট" -description: "ইথেরিয়াম ইকোসিস্টেমে সহায়তা পান।" -lang: bn ---- - -# ইথেরিয়াম সহায়তা {#support} - -## অফিশিয়াল ইথেরিয়াম সহায়তা {#official-support} - -আপনি কি অফিশিয়াল ইথেরিয়াম সহায়তার জন্য খুঁজছেন? আপনার প্রথম যে জিনিসটি জানা উচিত তা হল ইথেরিয়াম বিকেন্দ্রীভূত। এর মানে হল কোনো কেন্দ্রীয় সংস্থা, সত্তা বা ব্যক্তি ইথেরিয়ামের মালিক নয়, এবং এই কারণে, কোনো অফিশিয়াল সহায়তা চ্যানেল বিদ্যমান নেই। - -ইথেরিয়ামের বিকেন্দ্রীভূত প্রকৃতি বোঝা অত্যাবশ্যক কারণ **যেই নিজেকে ইথেরিয়ামের অফিশিয়াল সহায়তা বলে দাবি করছে, সে সম্ভবত আপনার সাথে স্ক্যাম করার চেষ্টা করছে!** স্ক্যামারদের বিরুদ্ধে সেরা সুরক্ষা হল নিজেকে শিক্ষিত করা এবং নিরাপত্তাকে গুরুত্ব সহকারে নেওয়া। - - - ইথেরিয়াম সুরক্ষা এবং স্ক্যাম প্রতিরোধ - - - - ইথেরিয়ামের মূল বিষয়গুলো শিখুন - - -অফিশিয়াল সহায়তার অভাব সত্ত্বেও, ইথেরিয়াম ইকোসিস্টেম জুড়ে অনেক গোষ্ঠী, সম্প্রদায় এবং প্রকল্প সাহায্য করতে পেরে খুশি, এবং আপনি এই পৃষ্ঠায় অনেক দরকারী তথ্য এবং রিসোর্স খুঁজে পেতে পারেন। এখনও প্রশ্ন আছে? [ethereum.org ডিসকর্ড](https://discord.gg/ethereum-org)-এ যোগ দিন, এবং আমরা সাহায্য করার চেষ্টা করব। - -## সাধারণত জিজ্ঞাসিত প্রশ্নসমূহ {#faq} - -### আমি ভুল ওয়ালেটে ETH পাঠিয়েছি {#wrong-wallet} - -ইথেরিয়ামে পাঠানো একটি লেনদেন অপরিবর্তনীয়। দুর্ভাগ্যবশত, আপনি যদি ভুল ওয়ালেটে ETH পাঠিয়ে থাকেন, তবে এই তহবিল পুনরুদ্ধার করার কোনো উপায় নেই। কোনো একক কেন্দ্রীয় সংস্থা, সত্তা বা ব্যক্তি ইথেরিয়ামের মালিক নয়, যার মানে হল কেউ লেনদেন বিপরীত করতে পারে না। অতএব, পাঠানোর আগে আপনার লেনদেন সবসময় দুবার পরীক্ষা করা অত্যাবশ্যক। - -### আমি কীভাবে আমার ইথেরিয়াম গিভঅ্যাওয়ে দাবি করতে পারি? {#giveaway-scam} - -ইথেরিয়াম গিভঅ্যাওয়ে হল আপনার ETH চুরি করার জন্য ডিজাইন করা স্ক্যাম। যেসব অফার বিশ্বাস করার জন্য খুব ভালো মনে হয়, সেগুলোর দ্বারা প্রলুব্ধ হবেন না — আপনি যদি কোনো গিভঅ্যাওয়ে ঠিকানায় ETH পাঠান, তাহলে আপনি কোনো গিভঅ্যাওয়ে পাবেন না, এবং আপনি আপনার তহবিল পুনরুদ্ধার করতে পারবেন না। - -[স্ক্যাম প্রতিরোধ সম্পর্কে আরও জানুন](/security/#common-scams) - -### আমার লেনদেন আটকে গেছে {#stuck-transaction} - -নেটওয়ার্কের চাহিদার কারণে প্রয়োজনের চেয়ে কম লেনদেন ফি জমা দিলে ইথেরিয়ামে লেনদেন কখনও কখনও আটকে যেতে পারে। অনেক ওয়ালেট লেনদেন প্রক্রিয়াকরণের জন্য উচ্চতর লেনদেন ফি সহ একই লেনদেন পুনরায় জমা দেওয়ার একটি বিকল্প প্রদান করে। বিকল্পভাবে, আপনি আপনার নিজের ঠিকানায় একটি লেনদেন পাঠিয়ে এবং অমীমাংসিত লেনদেনের মতো একই ননস ব্যবহার করে একটি অমীমাংসিত লেনদেন বাতিল করতে পারেন। - -[MetaMask-এ একটি অমীমাংসিত লেনদেনের গতি বাড়ানো বা বাতিল করার উপায়](https://metamask.zendesk.com/hc/en-us/articles/360015489251-How-to-speed-up-or-cancel-a-pending-transaction) - -[অমীমাংসিত ইথেরিয়াম লেনদেন কীভাবে বাতিল করবেন](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) - -### আমি কীভাবে ইথেরিয়াম মাইন করব? {#mining-ethereum} - -ইথেরিয়াম মাইনিং আর সম্ভব নয়। ইথেরিয়াম যখন [প্রুফ-অফ-ওয়ার্ক](/glossary/#pow) থেকে [প্রুফ-অফ-স্টেক](/glossary/#pos)-এ স্থানান্তরিত হয়, তখন মাইনিং বন্ধ করে দেওয়া হয়। এখন, মাইনারদের পরিবর্তে, ইথেরিয়ামে ভ্যালিডেটর রয়েছে। নেটওয়ার্ক সুরক্ষিত করার জন্য যে কেউ ETH [স্টেক](/glossary/#staking) করতে পারেন এবং ভ্যালিডেটর সফ্টওয়্যার চালানোর জন্য স্টেকিং পুরস্কার পেতে পারেন। - -### আমি কীভাবে একজন স্টেকার / ভ্যালিডেটর চালাব? {#how-to-stake} - -একজন ভ্যালিডেটর হতে, আপনাকে অবশ্যই ইথেরিয়াম ডিপোজিট কন্ট্রাক্টে 32 ETH স্টেক করতে হবে এবং একটি ভ্যালিডেটর নোড সেট আপ করতে হবে। আমাদের [স্টেকিং পেজ](/staking)-এ এবং [স্টেকিং লঞ্চপ্যাড](https://launchpad.ethereum.org/)-এ আরও তথ্য পাওয়া যায়। - -## ডিএ্যাপস তৈরি করা {#building-support} - -তৈরি করা কঠিন হতে পারে। এখানে অভিজ্ঞ ইথেরিয়াম ডেভেলপারদের সাথে কিছু উন্নয়ন কেন্দ্রিক স্থান রয়েছে যারা সাহায্য করতে পেরে খুশি। - -- [Alchemy University](https://university.alchemy.com/#starter_code) -- [CryptoDevs discord](https://discord.com/invite/5W5tVb3) -- [Ethereum StackExchange](https://ethereum.stackexchange.com/) -- [Web3 University](https://www.web3.university/) -- [LearnWeb3](https://discord.com/invite/learnweb3) - -আপনি আমাদের [ইথেরিয়াম ডেভেলপার রিসোর্স](/developers/) বিভাগে ডকুমেন্টেশন এবং ডেভেলপমেন্ট গাইডও খুঁজে পেতে পারেন। - -### টুলিং {#dapp-tooling} - -আপনার প্রশ্ন কি কোনো নির্দিষ্ট টুল, প্রকল্প বা লাইব্রেরির সাথে সম্পর্কিত? বেশিরভাগ প্রকল্পের চ্যাট সার্ভার বা ফোরাম রয়েছে যা আপনাকে সহায়তা করার জন্য নিবেদিত। - -এখানে কিছু জনপ্রিয় উদাহরণ রয়েছে: - -- [Solidity](https://app.element.io/#/room/#solidity:matrix.org) -- [ethers.js](https://discord.gg/6jyGVDK6Jx) -- [web3.js](https://discord.gg/GsABYQu4sC) -- [Hardhat](https://discord.gg/xtrMGhmbfZ) -- [Alchemy](http://alchemy.com/discord) -- [Tenderly](https://discord.gg/fBvDJYR) - -## একটি নোড চালানো {#node-support} - -আপনি যদি একটি নোড বা ভ্যালিডেটর চালান, তবে এখানে কিছু সম্প্রদায় রয়েছে যা আপনাকে শুরু করতে সাহায্য করার জন্য নিবেদিত। - -- [EthStaker discord](https://discord.gg/ethstaker) -- [EthStaker reddit](https://www.reddit.com/r/ethstaker) - -ইথেরিয়াম ক্লায়েন্ট তৈরি করা বেশিরভাগ দলেরও নিবেদিত, সর্বজনীন-মুখী, স্থান রয়েছে যেখানে আপনি সহায়তা পেতে এবং প্রশ্ন জিজ্ঞাসা করতে পারেন। - -### এক্সিকিউশন ক্লায়েন্ট {#execution-clients} - -- [Geth](https://discord.gg/FqDzupGyYf) -- [Nethermind](https://discord.gg/YJx3pm8z5C) -- [Besu](https://discord.gg/p8djYngzKN) -- [Erigon](https://github.com/ledgerwatch/erigon/issues) -- [Reth](https://github.com/paradigmxyz/reth/discussions) - -### কনসেন্সাস ক্লায়েন্ট {#consensus-clients} - -- [Prysm](https://discord.gg/prysmaticlabs) -- [Nimbus](https://discord.gg/nSmEH3qgFv) -- [Lighthouse](https://discord.gg/cyAszAh) -- [Teku](https://discord.gg/7hPv2T6) -- [Lodestar](https://discord.gg/aMxzVcr) -- [Grandine](https://discord.gg/H9XCdUSyZd) - -আপনি এখানে [কিভাবে একটি নোড চালাতে হয় তা শিখতে পারেন](/developers/docs/nodes-and-clients/run-a-node/)। diff --git a/public/content/translations/bn/community/support/misconceptions/index.md b/public/content/translations/bn/community/support/misconceptions/index.md new file mode 100644 index 00000000000..55c92a2c0e6 --- /dev/null +++ b/public/content/translations/bn/community/support/misconceptions/index.md @@ -0,0 +1,73 @@ +--- +title: "ইথেরিয়াম সম্পর্কে সাধারণ ভুল ধারণা" +description: "ইথেরিয়াম কীভাবে কাজ করে সে সম্পর্কে সবচেয়ে সাধারণ ভুল ধারণাগুলো পরিষ্কার করা।" +lang: bn +--- + +# ইথেরিয়াম সম্পর্কে সাধারণ ভুল ধারণা {#misconceptions} + +## ইথেরিয়াম কি একটি কোম্পানি? {#not-a-company} + +ইথেরিয়াম একটি ওপেন-সোর্স, ডিসেন্ট্রালাইজড প্রযুক্তি যা বিশ্বজুড়ে হাজার হাজার অবদানকারী দ্বারা রক্ষণাবেক্ষণ করা হয়। "ইথেরিয়াম" নামক এমন কোনো কোম্পানি নেই যা অ্যাকাউন্ট পরিচালনা করে, তহবিল রাখে বা গ্রাহক সহায়তা প্রদান করে। + +[ইথেরিয়াম ফাউন্ডেশন](https://ethereum.foundation/) একটি অলাভজনক সংস্থা যা ইথেরিয়ামের উন্নয়নে সহায়তা করে, কিন্তু এটি নেটওয়ার্কের মালিকানা বা নিয়ন্ত্রণ করে না। কোনো একক সত্তা তা করে না। + +**[ethereum.org](/)** একটি কমিউনিটি-চালিত শিক্ষামূলক রিসোর্স। এটি কোনো এক্সচেঞ্জ, ওয়ালেট বা আর্থিক প্রতিষ্ঠান নয়। এটি কোনো ব্যবহারকারীর তহবিল রাখে না এবং কোনো অ্যাকাউন্টে অ্যাক্সেস করতে পারে না। + + + Ethereum কী? + + +## কেউ কি আমার তহবিল পুনরুদ্ধার বা ফ্রিজ করতে পারে? {#no-fund-access} + +ব্যাংকের মতো, ইথেরিয়ামে এমন কোনো কেন্দ্রীয় কর্তৃপক্ষ নেই যা তহবিল ফ্রিজ, বাজেয়াপ্ত বা পুনরুদ্ধার করতে পারে। যে ব্যক্তি প্রাইভেট কী (বা সিড ফ্রেজ) ধারণ করে, তার একটি ওয়ালেটের উপর সম্পূর্ণ এবং একক নিয়ন্ত্রণ থাকে। + +এর মানে হল: + +- **কেউ তহবিল পুনরুদ্ধার করতে পারে না** যা আপনি ভুল অ্যাড্রেসে পাঠিয়েছেন +- একটি লেনদেন নিশ্চিত হওয়ার পর **কেউ তা উল্টাতে পারে না** +- **কেউ আপনার ওয়ালেট ফ্রিজ করতে পারে না** বা আপনার লেনদেন ব্লক করতে পারে না +- আপনি যদি আপনার সিড ফ্রেজ হারিয়ে ফেলেন তবে **কেউ আপনার পাসওয়ার্ড রিসেট করতে পারে না** + +এই কারণেই আপনার সিড ফ্রেজ রক্ষা করা অত্যন্ত গুরুত্বপূর্ণ। আপনার ওয়ালেটে অ্যাক্সেস করার এটিই একমাত্র উপায়। যদি এটি হারিয়ে যায় বা চুরি হয়ে যায়, তবে কোনো পুনরুদ্ধারের বিকল্প নেই। + + + ইথেরিয়াম সুরক্ষা এবং স্ক্যাম প্রতিরোধ + + +## আমি কি এখনও ইথেরিয়াম মাইন করতে পারি? {#no-mining} + +ইথেরিয়াম ২০২২ সালের সেপ্টেম্বরে [দ্য মার্জ](/roadmap/merge/) এর সময় [প্রুফ-অফ-ওয়ার্ক](/glossary/#pow) থেকে [প্রুফ-অফ-স্টেক](/glossary/#pos)-এ স্যুইচ করেছে। ইথেরিয়ামে মাইনিং আর সম্ভব নয়। + +নেটওয়ার্কটি এখন ভ্যালিডেটরদের দ্বারা সুরক্ষিত যারা ETH [স্টেক](/glossary/#staking) করে। যে কেউ অংশগ্রহণ করতে পারে: + +- **সোলো স্টেকিং:** 32 ETH দিয়ে আপনার নিজস্ব ভ্যালিডেটর চালান—[আরও জানুন](/staking/solo/) +- **সার্ভিস হিসেবে স্টেকিং:** আপনার কী নিজের কাছে রেখে নোড অপারেশন অন্যকে অর্পণ করুন—[আরও জানুন](/staking/saas/) +- **পুলড স্টেকিং:** একটি পুলে যোগ দিয়ে 32 ETH-এর কম দিয়ে স্টেক করুন—[আরও জানুন](/staking/pools/) + + + স্টেকিং সম্পর্কে আরও জানুন + + +## কোনো ইথেরিয়াম সাপোর্ট টিম আছে কি? {#no-support-team} + +"অফিসিয়াল ইথেরিয়াম সাপোর্ট" খোঁজাটা "অফিসিয়াল ইন্টারনেট সাপোর্ট" খোঁজার মতোই। অবশ্যই এর কোনো অস্তিত্ব নেই, কিন্তু আপনার সমস্যার উপর নির্ভর করে আপনি আপনার ইন্টারনেট পরিষেবা প্রদানকারী, আপনার রাউটার হার্ডওয়্যার প্রস্তুতকারক, বা আপনি যে ডিভাইস, অ্যাপ বা ওয়েবসাইট ব্যবহার করছেন তার পেছনের কোনো কোম্পানির কাছ থেকে সহায়তা চাইতে পারেন। + +ইথেরিয়ামও অনুরূপ। সামগ্রিকভাবে ইথেরিয়ামের পিছনে কোনো কোম্পানি, সাপোর্ট টিম বা হেল্প ডেস্ক নেই, তবে সমস্যার উপর নির্ভর করে আপনি আপনার _ওয়ালেট প্রদানকারী_, _স্টেকিং পরিষেবা_, _এক্সচেঞ্জ_, _আর্থিক প্রতিষ্ঠান_ বা আপনি যে _অ্যাপটি ব্যবহার করছেন তার রক্ষণাবেক্ষণকারী টিমের_ সাথে যোগাযোগ করে সহায়তা পেতে পারেন। + +যেহেতু ইথেরিয়াম ডিফল্টরূপে সর্বজনীনভাবে স্বচ্ছ, তাই আপনি সরাসরি কোনো সমস্যা খতিয়ে দেখার জন্য [ব্লক এক্সপ্লোরার](/developers/docs/data-and-analytics/block-explorers/), [অ্যানালিটিক্স টুলস](/developers/tools/analytics/), এবং অন্যান্য [অনলাইন তদন্ত রিসোর্স](/community/support/scams/#analyze) উপকারী মনে করতে পারেন। + +তা সত্ত্বেও, ইথেরিয়াম বা ethereum.org থেকে কেউ কখনো: + +- সরাসরি বার্তার মাধ্যমে আপনার সাথে যোগাযোগ করবে না +- আপনার সিড ফ্রেজ বা প্রাইভেট কী চাইবে না +- আপনার ওয়ালেট যাচাই করার জন্য আপনাকে ETH পাঠাতে বলবে না +- একটি ফি-এর বিনিময়ে আপনাকে তহবিল পুনরুদ্ধার করতে সাহায্য করার প্রস্তাব দেবে না + +**উপরের যেকোনোটি যিনিই করছেন, তিনি আপনাকে স্ক্যাম করার চেষ্টা করছেন।** + +আপনার যদি সাহায্যের প্রয়োজন হয়, তাহলে যে প্রকৃত কমিউনিটিগুলো সহায়তা করতে পারে তাদের [সাপোর্ট পেজে](/community/support/) তালিকাভুক্ত করা হয়েছে। এগুলো স্বেচ্ছাসেবী-চালিত, উন্মুক্ত কমিউনিটি—কোনো অফিসিয়াল সাপোর্ট চ্যানেল নয়। + + + ইথেরিয়াম সুরক্ষা এবং স্ক্যাম প্রতিরোধ + diff --git a/public/content/translations/bn/community/support/scams/index.md b/public/content/translations/bn/community/support/scams/index.md new file mode 100644 index 00000000000..556acad826d --- /dev/null +++ b/public/content/translations/bn/community/support/scams/index.md @@ -0,0 +1,159 @@ +--- +title: "স্ক্যাম সহায়তা ও রিপোর্টিং" +description: "আপনি স্ক্যামের শিকার হলে কী করবেন, আপনার অবশিষ্ট সম্পদ কীভাবে সুরক্ষিত করবেন এবং কোথায় জালিয়াতির রিপোর্ট করবেন।" +lang: bn +--- + +# আমি স্ক্যামের শিকার হয়েছি বা তহবিল হারিয়েছি {#scam-help} + +ক্রিপটোকারেন্সি স্ক্যামগুলি ফিনান্স এবং প্রযুক্তির পেশাদারদের সহ সকল অভিজ্ঞতার স্তরের লোকেদেরকে টার্গেট করে। আপনি একা নন এবং এখানে আসাটা প্রথম সঠিক পদক্ষেপ। + + + + + + +**কেউ ব্লকচেইন লেনদেন উল্টাতে পারে না।** যদি কেউ আপনার সাথে যোগাযোগ করে দাবি করে যে তারা একটি ফি-এর বিনিময়ে আপনার তহবিল পুনরুদ্ধার করতে পারে, তবে তা প্রায় নিশ্চিতভাবেই একটি দ্বিতীয় স্ক্যাম। নীচে [পুনরুদ্ধার স্ক্যাম](#recovery-scams) দেখুন। + + + + +## আপনার অবশিষ্ট সম্পদ সুরক্ষিত করুন {#secure-assets} + +আপনি যদি কোনো স্ক্যামারের সাথে যোগাযোগ করে থাকেন বা সন্দেহ করেন যে আপনার ওয়ালেট আপোস করা হয়েছে, তাহলে অবিলম্বে এই পদক্ষেপগুলি নিন: + +1. **অবশিষ্ট তহবিল** একটি নতুন, সুরক্ষিত ওয়ালেটে **সরান** যেখানে স্ক্যামারের অ্যাক্সেস নেই +2. **টোকেন অনুমোদন বাতিল করুন।** স্ক্যামাররা প্রায়শই আপনাকে সীমাহীন টোকেন খরচের অনুমোদন দিতে প্রতারণা করে। এই অনুমতিগুলি বাতিল করলে আপনার ওয়ালেট থেকে আরও অর্থ বেরিয়ে যাওয়া আটকানো যায় +3. লিঙ্ক করা থাকতে পারে এমন যেকোনো এক্সচেঞ্জ অ্যাকাউন্টে **পাসওয়ার্ড পরিবর্তন করুন** +4. সমস্ত ক্রিপ্টো-সম্পর্কিত অ্যাকাউন্টে **টু-ফ্যাক্টর অথেনটিকেশন (2FA) চালু করুন** + +### টোকেন অনুমোদন কীভাবে বাতিল করবেন {#revoke-approvals} + +যখন আপনি একটি ডিএ্যাপ বা স্মার্ট কন্ট্র্যাক্টের সাথে ইন্টারঅ্যাক্ট করেন, তখন আপনি এটিকে আপনার টোকেনগুলি ব্যয় করার অনুমতি দিয়ে থাকতে পারেন। যদি কোনো স্ক্যামার আপনাকে একটি ক্ষতিকারক চুক্তি অনুমোদন করতে প্রতারিত করে, তবে তারা প্রাথমিক স্ক্যামের পরেও আপনার টোকেনগুলি বের করে নেওয়া চালিয়ে যেতে পারে। + +অনুমোদন পরীক্ষা এবং বাতিল করতে এই টুলগুলি ব্যবহার করুন: + +- [Revoke.cash](https://revoke.cash/): সমস্ত সক্রিয় অনুমোদন দেখতে এবং সেগুলি বাতিল করতে আপনার ওয়ালেট কানেক্ট করুন +- [Revokescout](https://revoke.blockscout.com/): Blockscout-এর মাধ্যমে অনুমোদনগুলি পরীক্ষা ও বাতিল করুন +- [Etherscan Token Approval Checker](https://etherscan.io/tokenapprovalchecker): Etherscan-এর মাধ্যমে অনুমোদনগুলি পরীক্ষা ও বাতিল করুন + + + ধাপে ধাপে নির্দেশিকা: টোকেন অ্যাক্সেস কীভাবে বাতিল করবেন + + +## স্ক্যাম ঠিকানা এবং ওয়েবসাইট রিপোর্ট করুন {#report} + +রিপোর্টিং অন্য ব্যবহারকারীদের সতর্ক করতে সাহায্য করে এবং আইন প্রয়োগকারী সংস্থার তদন্তে সহায়তা করতে পারে। সবকিছু নথিভুক্ত করুন: লেনদেনের হ্যাস, ওয়ালেট ঠিকানা, স্ক্রিনশট এবং স্ক্যামারের সাথে যেকোনো যোগাযোগ। + +### একটি স্ক্যাম ঠিকানা রিপোর্ট করুন {#report-address} + +- [Chainabuse](https://www.chainabuse.com/): কমিউনিটি-চালিত স্ক্যাম এবং জালিয়াতি রিপোর্টিং ডেটাবেস। রিপোর্ট জমা দিন এবং পরিচিত স্ক্যাম ঠিকানা অনুসন্ধান করুন +- [Etherscan report](https://info.etherscan.com/report-address/): সর্বাধিক ব্যবহৃত ইথেরিয়াম ব্লক এক্সপ্লোরারে একটি ঠিকানা ফ্ল্যাগ করুন +- [CryptoScamDB](https://cryptoscamdb.org/): ক্রিপটোকারেন্সি স্ক্যাম ট্র্যাকিং-এর জন্য ওপেন-সোর্স ডেটাবেস + +### একটি স্ক্যাম ওয়েবসাইট বা সোশ্যাল মিডিয়া অ্যাকাউন্ট রিপোর্ট করুন {#report-website} + +- [PhishTank](https://phishtank.org/): ফিশিং URL জমা দিন এবং যাচাই করুন +- [Google Safe Browsing](https://safebrowsing.google.com/safebrowsing/report_phish/): Google-কে ফিশিং সাইট সম্পর্কে রিপোর্ট করুন যাতে সেগুলি Chrome এবং অন্যান্য ব্রাউজারে ব্লক হয়ে যায় +- [Netcraft](https://report.netcraft.com/report/mistake): ক্ষতিকারক এবং প্রতারণামূলক ওয়েবসাইট রিপোর্ট করুন +- যে সোশ্যাল মিডিয়া প্ল্যাটফর্মে স্ক্যামটি ঘটেছে সেখানে সরাসরি রিপোর্ট করুন (Twitter/X, Discord, Telegram সবগুলিতেই রিপোর্টিং বৈশিষ্ট্য রয়েছে) + +### আইন প্রয়োগকারী সংস্থাকে রিপোর্ট করুন {#report-law-enforcement} + +- **মার্কিন যুক্তরাষ্ট্র:** [FBI Internet Crime Complaint Center (IC3)](https://www.ic3.gov/) +- **যুক্তরাজ্য:** [Action Fraud](https://www.actionfraud.police.uk/) +- **ইউরোপীয় ইউনিয়ন:** [Europol](https://www.europol.europa.eu/report-a-crime) +- **অন্যান্য দেশ:** আপনার স্থানীয় পুলিশের কাছে একটি রিপোর্ট ফাইল করুন। ক্রিপটোকারেন্সি জালিয়াতি বেশিরভাগ বিচারব্যবস্থায় একটি অপরাধ + +## কী ঘটেছে তা বিশ্লেষণ করুন {#analyze} + +আপনার তহবিল কোথায় গেছে তা বোঝা রিপোর্ট করতে সাহায্য করতে পারে এবং যদি তহবিল কোনো সেন্ট্রালাইডড এক্সচেঞ্জে জমা হয় তবে পুনরুদ্ধারের প্রচেষ্টাকে সমর্থন করতে পারে। + +- [Blockscout](https://eth.blockscout.com/): ওপেন-সোর্স ব্লক এক্সপ্লোরার, যা দিয়ে যেকোনো লেনদেনের হ্যাস বা ওয়ালেট ঠিকানা খুঁজে দেখা যায় যে তহবিল কোথায় পাঠানো হয়েছে +- [Etherscan](https://etherscan.io/): যেকোনো লেনদেনের হ্যাস বা ওয়ালেট ঠিকানা খুঁজে দেখুন তহবিল কোথায় পাঠানো হয়েছে +- [Chainabuse lookup](https://www.chainabuse.com/): কোনো ঠিকানা অন্যান্য ভুক্তভোগীদের দ্বারা ইতিমধ্যে রিপোর্ট করা হয়েছে কিনা তা পরীক্ষা করুন +- [MetaSleuth](https://metasleuth.io/) by BlockSec: ভিজ্যুয়াল লেনদেন ট্র্যাকিং টুল যা ফান্ডের প্রবাহকে ম্যাপ করে + +**যদি কোনো সেন্ট্রালাইডড এক্সচেঞ্জে (যেমন Coinbase, Binance, Kraken) তহবিল পাঠানো হয়**, তাহলে লেনদেনের বিবরণ সহ অবিলম্বে তাদের সহায়তা দলের সাথে যোগাযোগ করুন। এক্সচেঞ্জগুলি কখনও কখনও জালিয়াতির জন্য ফ্ল্যাগ করা অ্যাকাউন্টগুলি ফ্রিজ করতে পারে। + +## কঠিন সত্য {#hard-truth} + +যেহেতু ইথেরিয়াম ডিসেন্ট্রালাইজড, তাই কোনো কেন্দ্রীয় কর্তৃপক্ষ লেনদেন উল্টাতে বা চুরি হওয়া তহবিল পুনরুদ্ধার করতে পারে না। একবার ব্লকচেইনে একটি লেনদেন নিশ্চিত হয়ে গেলে, তা চূড়ান্ত। + +রিপোর্টিং করা এখনও মূল্যবান। রিপোর্টগুলি আইন প্রয়োগকারী সংস্থাকে সংগঠিত জালিয়াতির চক্র ট্র্যাক করতে সহায়তা করে এবং Chainabuse ও Etherscan-এ ঠিকানা ফ্ল্যাগ করা ভবিষ্যতের সম্ভাব্য ভুক্তভোগীদের সতর্ক করে। + +## যে ধরনের স্ক্যাম থেকে সতর্ক থাকবেন {#scam-types} + + + +স্ক্যামাররা আপনার ETH গুণ করে দেওয়ার বা আপনাকে বিনামূল্যে টোকেন দেওয়ার প্রতিশ্রুতি দিয়ে নকল গিভঅ্যাওয়ে তৈরি করে। তারা প্রায়ই ভিটালিক বুটেরিনের মতো সুপরিচিত ব্যক্তিদের ছদ্মবেশ ধারণ করে। আপনি যদি একটি "গিভঅ্যাওয়ে" ঠিকানায় ETH পাঠান, তবে আপনি বিনিময়ে কিছুই পাবেন না। + +**মনে রাখবেন:** ভিটালিক এবং অন্যান্য বিশিষ্ট ব্যক্তিরা কখনই আপনাকে তাদের কাছে ETH পাঠাতে বলবে না। + +[সাধারণ স্ক্যাম সম্পর্কে আরও জানুন](/security/#common-scams) + + + + +স্ক্যামাররা Discord, Telegram এবং সোশ্যাল মিডিয়াতে ইথেরিয়াম দলের সদস্য, মডারেটর বা সহায়তা এজেন্টদের ছদ্মবেশ ধারণ করে। তারা আপনাকে সরাসরি মেসেজ পাঠিয়ে সাহায্য করার অফার দিতে পারে অথবা আপনার অ্যাকাউন্টে সমস্যা আছে বলে দাবি করতে পারে। + +**মনে রাখবেন:** + +- "ইথেরিয়াম সহায়তা দল" বলে কিছু নেই +- আসল মডারেটররা কখনই আপনাকে প্রথমে ডিএম করবে না +- কখনোই আপনার সিড ফ্রেজ বা প্রাইভেট কী কারো সাথে, কোনো কারণে শেয়ার করবেন না +- অযাচিত মেসেজে পাঠানো লিঙ্কে কখনই ক্লিক করবেন না + + + + +পুনরুদ্ধার স্ক্যামগুলি বিশেষত সেই ব্যক্তিদের টার্গেট করে যারা ইতিমধ্যেই তহবিল হারিয়েছেন। স্ক্যামাররা সোশ্যাল মিডিয়াতে স্ক্যামের শিকার হওয়া নিয়ে কথা বলা লোকদের উপর নজর রাখে এবং তারপর "ব্লকচেইন তদন্তকারী" বা "ক্রিপ্টো পুনরুদ্ধার বিশেষজ্ঞ" হিসাবে নিজেদের জাহির করে যোগাযোগ করে। + +তারা একটি অগ্রিম ফি-এর বিনিময়ে আপনার চুরি যাওয়া ক্রিপ্টো ট্রেস করে পুনরুদ্ধার করার প্রতিশ্রুতি দেয়। আপনি অর্থ প্রদান করার পরে, তারা উধাও হয়ে যায়। + +**কোনো বৈধ পরিষেবা ব্লকচেইন লেনদেনকে উল্টাতে পারে না।** যে কেউ এই প্রতিশ্রুতি দেয় সে মিথ্যা বলছে। এটি সবচেয়ে সাধারণ ফলো-আপ স্ক্যামগুলির মধ্যে একটি। + + + + +ফিশিং সাইটগুলি আসল ওয়ালেট অ্যাপ, এক্সচেঞ্জ বা DeFi প্ল্যাটফর্মগুলির মতোই দেখতে হয়। তারা আপনাকে আপনার সিড ফ্রেজ প্রবেশ করাতে বা আপনার ওয়ালেট কানেক্ট করতে প্রতারণা করে, এবং তারপরে আপনার তহবিল খালি করে দেয়। + +**নিজেকে সুরক্ষিত রাখুন:** + +- আপনার ওয়ালেট কানেক্ট করার আগে সর্বদা URL যাচাই করুন +- আপনি যে অফিসিয়াল সাইটগুলি নিয়মিত ব্যবহার করেন সেগুলি বুকমার্ক করুন +- কোনো ওয়েবসাইটে আপনার সিড ফ্রেজ প্রবেশ করাবেন না। বৈধ অ্যাপগুলি কখনই এটি চায় না +- সন্দেহজনক URL পরীক্ষা করতে [PhishTank](https://phishtank.org/) ব্যবহার করুন + + + স্ক্যাম টোকেন কীভাবে শনাক্ত করবেন + + + + + ইথেরিয়াম সুরক্ষা এবং স্ক্যাম প্রতিরোধের সম্পূর্ণ নির্দেশিকা + diff --git a/public/content/translations/bn/developers/docs/networking-layer/index.md b/public/content/translations/bn/developers/docs/networking-layer/index.md index 2338f0fe250..157a2fb0e8e 100644 --- a/public/content/translations/bn/developers/docs/networking-layer/index.md +++ b/public/content/translations/bn/developers/docs/networking-layer/index.md @@ -146,8 +146,8 @@ SSZ মানে হল সিম্পল সিরিয়ালাইজেশ একবার ব্লকটি পর্যাপ্ত ভ্যালিডেটর দ্বারা অ্যাটেস্টেড হয়ে গেলে এটি চেইনের শীর্ষে যুক্ত হয়, ন্যায্য বলে বিবেচিত হয় এবং অবশেষে চূড়ান্ত হয়। -![](cons_client_net_layer.png) -![](exe_client_net_layer.png) +![Ethereum ঐক্যমত ক্লায়েন্ট নেটওয়ার্কিং স্তরের চিত্র](cons_client_net_layer.png) +![ইথেরিয়াম এক্সিকিউশন ক্লায়েন্ট নেটওয়ার্কিং স্তরের চিত্র](exe_client_net_layer.png) [ethresear.ch](https://ethresear.ch/t/eth1-eth2-client-relationship/7248) থেকে কনসেন্সাস এবং এক্সিকিউশন ক্লায়েন্টদের জন্য নেটওয়ার্ক লেয়ার স্কিম্যাটিক diff --git a/public/content/translations/bn/developers/docs/nodes-and-clients/node-architecture/index.md b/public/content/translations/bn/developers/docs/nodes-and-clients/node-architecture/index.md index 9f1d02079f6..79542f7bc9f 100644 --- a/public/content/translations/bn/developers/docs/nodes-and-clients/node-architecture/index.md +++ b/public/content/translations/bn/developers/docs/nodes-and-clients/node-architecture/index.md @@ -10,7 +10,7 @@ lang: bn নীচের ডায়াগ্রামটি দুটি ইথেরিয়াম ক্লায়েন্টের মধ্যে সম্পর্ক দেখায়। দুটি ক্লায়েন্ট তাদের নিজ নিজ পিয়ার-টু-পিয়ার (P2P) নেটওয়ার্কের সাথে সংযুক্ত হয়। আলাদা P2P নেটওয়ার্কের প্রয়োজন হয়, কারণ এক্সিকিউশন ক্লায়েন্টরা তাদের P2P নেটওয়ার্কের মাধ্যমে লেনদেন গসিপ করে, যা তাদের স্থানীয় লেনদেন পুল পরিচালনা করতে সক্ষম করে, অন্যদিকে কনসেন্সাস ক্লায়েন্টরা তাদের P2P নেটওয়ার্কের মাধ্যমে ব্লক গসিপ করে, যা কনসেন্সাস এবং চেইন বৃদ্ধি সক্ষম করে। -![](node-architecture-text-background.png) +![Ethereum নোড আর্কিটেকচারের ডায়াগ্রাম এক্সিকিউশন এবং কনসেনসাস লেয়ার দেখাচ্ছে](node-architecture-text-background.png) _এক্সিকিউশন ক্লায়েন্টের জন্য Erigon, Nethermind, এবং Besu সহ বেশ কয়েকটি বিকল্প রয়েছে।_ diff --git a/public/content/translations/bn/developers/tutorials/ai-trading-agent/index.md b/public/content/translations/bn/developers/tutorials/ai-trading-agent/index.md new file mode 100644 index 00000000000..27730f4807f --- /dev/null +++ b/public/content/translations/bn/developers/tutorials/ai-trading-agent/index.md @@ -0,0 +1,980 @@ +--- +title: "ইথেরিয়ামে আপনার নিজস্ব AI ট্রেডিং এজেন্ট তৈরি করুন" +description: "এই টিউটোরিয়ালে আপনি একটি সহজ AI ট্রেডিং এজেন্ট কীভাবে তৈরি করতে হয় তা শিখবেন। এই এজেন্টটি ব্লকচেইন থেকে তথ্য পড়ে, সেই তথ্যের উপর ভিত্তি করে একটি LLM-এর কাছে সুপারিশ চায়, LLM-এর সুপারিশকৃত ট্রেডটি সম্পাদন করে এবং তারপর অপেক্ষা করে ও পুনরাবৃত্তি করে।" +author: Ori Pomerantz +tags: [ "AI", "ট্রেডিং", "এজেন্ট", "python" ] +skill: intermediate +published: 2026-02-13 +lang: bn +sidebarDepth: 3 +--- + +এই টিউটোরিয়ালে আপনি একটি সহজ AI ট্রেডিং এজেন্ট কীভাবে তৈরি করতে হয় তা শিখবেন। এই এজেন্টটি এই ধাপগুলো ব্যবহার করে কাজ করে: + +1. একটি টোকেনের বর্তমান এবং অতীতের মূল্য, সেইসাথে অন্যান্য সম্ভাব্য প্রাসঙ্গিক তথ্য পড়ুন +2. এই তথ্যের সাথে একটি কোয়েরি তৈরি করুন, সাথে ব্যাকগ্রাউন্ড তথ্য যোগ করে ব্যাখ্যা করুন যে এটি কীভাবে প্রাসঙ্গিক হতে পারে +3. কোয়েরি জমা দিন এবং একটি অনুমানিত মূল্য ফেরত পান +4. সুপারিশের ভিত্তিতে ট্রেড করুন +5. অপেক্ষা করুন এবং পুনরাবৃত্তি করুন + +এই এজেন্টটি দেখায় কীভাবে তথ্য পড়তে হয়, এটিকে একটি কোয়েরিতে রূপান্তর করতে হয় যা একটি ব্যবহারযোগ্য উত্তর দেয় এবং সেই উত্তরটি ব্যবহার করতে হয়। এগুলো সবই একটি AI এজেন্টের জন্য প্রয়োজনীয় ধাপ। এই এজেন্টটি Python-এ প্রয়োগ করা হয়েছে কারণ এটি AI-তে ব্যবহৃত সবচেয়ে সাধারণ ভাষা। + +## এটা কেন করবেন? {#why-do-this} + +স্বয়ংক্রিয় ট্রেডিং এজেন্ট ডেভেলপারদের একটি ট্রেডিং কৌশল নির্বাচন এবং কার্যকর করার সুযোগ দেয়। [AI এজেন্ট](/ai-agents) আরও জটিল এবং গতিশীল ট্রেডিং কৌশলের সুযোগ দেয়, সম্ভাব্যভাবে এমন তথ্য এবং অ্যালগরিদম ব্যবহার করে যা ডেভেলপার ব্যবহার করার কথাও ভাবেনি। + +## টুলস {#tools} + +এই টিউটোরিয়ালটি কোট এবং ট্রেডিংয়ের জন্য [Python](https://www.python.org/), [Web3 লাইব্রেরি](https://web3py.readthedocs.io/en/stable/) এবং [Uniswap v3](https://github.com/Uniswap/v3-periphery) ব্যবহার করে। + +### কেন Python? {#python} + +AI-এর জন্য সবচেয়ে বেশি ব্যবহৃত ভাষা হল [Python](https://www.python.org/), তাই আমরা এখানে এটি ব্যবহার করেছি। আপনি Python না জানলেও চিন্তা করবেন না। ভাষাটি খুব স্পষ্ট, এবং আমি ব্যাখ্যা করব এটি ঠিক কী করে। + +[Web3 লাইব্রেরি](https://web3py.readthedocs.io/en/stable/) হল সবচেয়ে সাধারণ Python ইথেরিয়াম API। এটি ব্যবহার করা বেশ সহজ। + +### ব্লকচেইনে ট্রেডিং {#trading-on-blockchain} + +[অনেক ডিস্ট্রিবিউটেড এক্সচেঞ্জ (DEX)](/apps/categories/defi/) আছে যা আপনাকে ইথেরিয়ামে টোকেন ট্রেড করার সুযোগ দেয়। তবে, [আর্বিট্রেজ](/developers/docs/smart-contracts/composability/#better-user-experience)-এর কারণে তাদের এক্সচেঞ্জ রেট প্রায় একই রকম থাকে। + +[Uniswap](https://app.uniswap.org/) একটি বহুল ব্যবহৃত DEX যা আমরা কোট (টোকেনের আপেক্ষিক মান দেখতে) এবং ট্রেড উভয়ের জন্য ব্যবহার করতে পারি। + +### OpenAI {#openai} + +একটি বড় ল্যাঙ্গুয়েজ মডেলের জন্য, আমি [OpenAI](https://openai.com/) দিয়ে শুরু করতে চেয়েছি। এই টিউটোরিয়ালের অ্যাপ্লিকেশনটি চালানোর জন্য আপনাকে API অ্যাক্সেসের জন্য অর্থপ্রদান করতে হবে। $5-এর ন্যূনতম পেমেন্ট যথেষ্টর চেয়েও বেশি। + +## ডেভেলপমেন্ট, ধাপে ধাপে {#step-by-step} + +ডেভেলপমেন্টকে সহজ করার জন্য, আমরা ধাপে ধাপে এগোব। প্রতিটি ধাপ GitHub-এর একটি ব্রাঞ্চ। + +### শুরু করা যাক {#getting-started} + +UNIX বা Linux-এর অধীনে শুরু করার জন্য কিছু ধাপ রয়েছে (এর মধ্যে [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) অন্তর্ভুক্ত) + +1. আপনার কাছে যদি এটি আগে থেকে না থাকে, তাহলে [Python](https://www.python.org/downloads/) ডাউনলোড এবং ইনস্টল করুন। + +2. GitHub রিপোজিটরিটি ক্লোন করুন। + + ```sh + git clone https://github.com/qbzzt/260215-ai-agent.git -b 01-getting-started + cd 260215-ai-agent + ``` + +3. [`uv`](https://docs.astral.sh/uv/getting-started/installation/) ইনস্টল করুন। আপনার সিস্টেমে কমান্ডটি ভিন্ন হতে পারে। + + ```sh + pipx install uv + ``` + +4. লাইব্রেরিগুলো ডাউনলোড করুন। + + ```sh + uv sync + ``` + +5. ভার্চুয়াল এনভায়রনমেন্ট সক্রিয় করুন। + + ```sh + source .venv/bin/activate + ``` + +6. Python এবং Web3 সঠিকভাবে কাজ করছে কিনা তা যাচাই করতে, `python3` চালান এবং এটিকে এই প্রোগ্রামটি সরবরাহ করুন। আপনি এটি `>>>` প্রম্পটে প্রবেশ করতে পারেন; একটি ফাইল তৈরি করার প্রয়োজন নেই। + + ```python + from web3 import Web3 + MAINNET_URL = "https://eth.drpc.org" + w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) + w3.eth.block_number + quit() + ``` + +### ব্লকচেইন থেকে পড়া {#read-blockchain} + +পরবর্তী ধাপ হল ব্লকচেইন থেকে পড়া। এটি করার জন্য, আপনাকে `02-read-quote` ব্রাঞ্চে পরিবর্তন করতে হবে এবং তারপর প্রোগ্রামটি চালানোর জন্য `uv` ব্যবহার করতে হবে। + +```sh +git checkout 02-read-quote +uv run agent.py +``` + +আপনার একটি `Quote` অবজেক্টের তালিকা পাওয়া উচিত, প্রতিটিতে একটি টাইমস্ট্যাম্প, একটি মূল্য এবং অ্যাসেট (বর্তমানে সবসময় `WETH/USDC`) থাকবে। + +এখানে একটি লাইন-বাই-লাইন ব্যাখ্যা দেওয়া হলো। + +```python +from web3 import Web3 +from web3.contract import Contract +from decimal import Decimal, ROUND_HALF_UP +from dataclasses import dataclass +from datetime import datetime, timezone +from pprint import pprint +import time +import functools +import sys +``` + +আমাদের প্রয়োজনীয় লাইব্রেরিগুলি আমদানি করুন। এগুলি ব্যবহার করার সময় নীচে ব্যাখ্যা করা হয়েছে। + +```python +print = functools.partial(print, flush=True) +``` + +Python-এর `print`-কে এমন একটি সংস্করণ দিয়ে প্রতিস্থাপন করে যা সবসময় অবিলম্বে আউটপুট ফ্লাশ করে। এটি একটি দীর্ঘ-চলমান স্ক্রিপ্টে উপযোগী কারণ আমরা স্ট্যাটাস আপডেট বা ডিবাগিং আউটপুটের জন্য অপেক্ষা করতে চাই না। + +```python +MAINNET_URL = "https://eth.drpc.org" +``` + +মেইননেটে যাওয়ার জন্য একটি URL। আপনি [নোড অ্যাজ এ সার্ভিস](/developers/docs/nodes-and-clients/nodes-as-a-service/) থেকে একটি পেতে পারেন বা [Chainlist](https://chainlist.org/chain/1)-এ বিজ্ঞাপিত একটি ব্যবহার করতে পারেন। + +```python +BLOCK_TIME_SECONDS = 12 +MINUTE_BLOCKS = int(60 / BLOCK_TIME_SECONDS) +HOUR_BLOCKS = MINUTE_BLOCKS * 60 +DAY_BLOCKS = HOUR_BLOCKS * 24 +``` + +একটি ইথেরিয়াম মেইননেট ব্লক সাধারণত প্রতি বারো সেকেন্ডে ঘটে, তাই এগুলি হল ব্লকের সংখ্যা যা আমরা একটি সময়কালে ঘটার আশা করি। লক্ষ্য করুন যে এটি একটি সঠিক সংখ্যা নয়। যখন [ব্লক প্রস্তাবক](/developers/docs/consensus-mechanisms/pos/block-proposal/) ডাউন থাকে, তখন সেই ব্লকটি এড়িয়ে যাওয়া হয় এবং পরবর্তী ব্লকের জন্য সময় হল 24 সেকেন্ড। আমরা যদি একটি টাইমস্ট্যাম্পের জন্য সঠিক ব্লক পেতে চাই, তাহলে আমরা [বাইনারি সার্চ](https://en.wikipedia.org/wiki/Binary_search) ব্যবহার করব। তবে, এটি আমাদের উদ্দেশ্যের জন্য যথেষ্ট কাছাকাছি। ভবিষ্যদ্বাণী করা কোনো সঠিক বিজ্ঞান নয়। + +```python +CYCLE_BLOCKS = DAY_BLOCKS +``` + +চক্রের আকার। আমরা প্রতি চক্রে একবার কোট পর্যালোচনা করি এবং পরবর্তী চক্রের শেষে মান অনুমান করার চেষ্টা করি। + +```python +# আমরা যে পুলটি পড়ছি তার অ্যাড্রেস +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +``` + +কোট মানগুলি Uniswap 3 USDC/WETH পুল থেকে [`0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`](https://eth.blockscout.com/address/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640?tab=read_write_contract) অ্যাড্রেসে নেওয়া হয়েছে। এই অ্যাড্রেসটি ইতিমধ্যেই চেকসাম ফর্মে আছে, কিন্তু কোডটিকে পুনঃব্যবহারযোগ্য করতে [`Web3.to_checksum_address`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_checksum_address) ব্যবহার করা ভাল। + +```python +POOL_ABI = [ + { "name": "slot0", ... }, + { "name": "token0", ... }, + { "name": "token1", ... }, +] + +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... } +] +``` + +এগুলো হল দুটি কন্ট্র্যাক্টের [ABI](https://docs.soliditylang.org/en/latest/abi-spec.html) যার সাথে আমাদের যোগাযোগ করতে হবে। কোডটি সংক্ষিপ্ত রাখতে, আমরা শুধুমাত্র সেই ফাংশনগুলো অন্তর্ভুক্ত করি যা আমাদের কল করতে হবে। + +```python +w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) +``` + +[`Web3`](https://web3py.readthedocs.io/en/stable/quickstart.html#remote-providers) লাইব্রেরি শুরু করুন এবং একটি ইথেরিয়াম নোডের সাথে সংযোগ স্থাপন করুন। + +```python +@dataclass(frozen=True) +class ERC20Token: + address: str + symbol: str + decimals: int + contract: Contract +``` + +এটি Python-এ একটি ডেটা ক্লাস তৈরি করার একটি উপায়। কন্ট্র্যাক্টের সাথে সংযোগ স্থাপন করতে [`Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) ডেটা টাইপ ব্যবহার করা হয়। ` (frozen=True)` লক্ষ্য করুন। Python-এ [বুলিয়ান](https://en.wikipedia.org/wiki/Boolean_data_type)-কে `True` বা `False` হিসেবে সংজ্ঞায়িত করা হয়, যা ক্যাপিটালাইজড। এই ডেটা ক্লাসটি `frozen`, যার মানে ফিল্ডগুলি পরিবর্তন করা যাবে না। + +ইনডেনটেশন লক্ষ্য করুন। [C-থেকে উদ্ভূত ভাষা](https://en.wikipedia.org/wiki/List_of_C-family_programming_languages)-এর বিপরীতে, Python ব্লক বোঝাতে ইনডেনটেশন ব্যবহার করে। Python ইন্টারপ্রেটার জানে যে নিম্নলিখিত সংজ্ঞাটি এই ডেটা ক্লাসের অংশ নয় কারণ এটি ডেটা ক্লাসের ফিল্ডগুলির মতো একই ইনডেনটেশন থেকে শুরু হয় না। + +```python +@dataclass(frozen=True) +class PoolInfo: + address: str + token0: ERC20Token + token1: ERC20Token + contract: Contract + asset: str + decimal_factor: Decimal = 1 +``` + +দশমিক ভগ্নাংশ সঠিকভাবে পরিচালনা করার জন্য [`Decimal`](https://docs.python.org/3/library/decimal.html) টাইপ ব্যবহার করা হয়। + +```python + def get_price(self, block: int) -> Decimal: +``` + +এটি Python-এ একটি ফাংশন সংজ্ঞায়িত করার উপায়। সংজ্ঞাটি ইনডেন্ট করা হয়েছে এটি দেখানোর জন্য যে এটি এখনও `PoolInfo`-এর অংশ। + +একটি ডেটা ক্লাসের অংশ এমন একটি ফাংশনে প্রথম প্যারামিটারটি সর্বদা `self`, যা এখানে কল করা ডেটা ক্লাস ইনস্ট্যান্স। এখানে আরেকটি প্যারামিটার আছে, ব্লক নম্বর। + +```python + assert block <= w3.eth.block_number, "Block is in the future" +``` + +আমরা যদি ভবিষ্যৎ পড়তে পারতাম, তবে ট্রেডিংয়ের জন্য AI-এর প্রয়োজন হতো না। + +```python + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) +``` + +Web3 থেকে EVM-এ একটি ফাংশন কল করার সিনট্যাক্স হল: `.functions."().call()`। প্যারামিটারগুলো EVM ফাংশনের প্যারামিটার হতে পারে (যদি থাকে; এখানে নেই) অথবা ব্লকচেইন আচরণ পরিবর্তন করার জন্য [নামযুক্ত প্যারামিটার](https://en.wikipedia.org/wiki/Named_parameter) হতে পারে। এখানে আমরা `block_identifier` ব্যবহার করি, যা [ব্লক নম্বর](/developers/docs/apis/json-rpc/#default-block) নির্দিষ্ট করে যেখানে আমরা চালাতে চাই। + +ফলাফল হল [এই struct, অ্যারে ফর্মে](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol#L56-L72)। প্রথম মানটি দুটি টোকেনের মধ্যে এক্সচেঞ্জ রেটের একটি ফাংশন। + +```python + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 +``` + +অনচেইন গণনা কমাতে, Uniswap v3 আসল এক্সচেঞ্জ ফ্যাক্টর সংরক্ষণ করে না বরং এর বর্গমূল সংরক্ষণ করে। যেহেতু EVM ফ্লোটিং পয়েন্ট ম্যাথ বা ভগ্নাংশ সমর্থন করে না, তাই আসল মানের পরিবর্তে, প্রতিক্রিয়া হল price296 + +```python + # (টোকেন0 প্রতি টোকেন1) + return 1/(raw_price * self.decimal_factor) +``` + +আমরা যে কাঁচা মূল্য পাই তা হল `টোকেন1`-এর প্রতি আমরা কত `টোকেন0` পাব তার সংখ্যা। আমাদের পুলে `টোকেন0` হল USDC (মার্কিন ডলারের সমান মূল্যের স্টেবলকয়েন) এবং `টোকেন1` হল [WETH](https://opensea.io/learn/blockchain/what-is-weth)। আমরা আসলে যে মানটি চাই তা হল প্রতি WETH-এর জন্য ডলারের সংখ্যা, এর বিপরীত নয়। + +ডেসিমাল ফ্যাক্টর হলো দুটি টোকেনের [ডেসিমাল ফ্যাক্টর](https://docs.openzeppelin.com/contracts/4.x/erc20#a-note-on-decimals) এর মধ্যকার অনুপাত। + +```python +@dataclass(frozen=True) +class Quote: + timestamp: str + price: Decimal + asset: str +``` + +এই ডেটা ক্লাসটি একটি কোট উপস্থাপন করে: একটি নির্দিষ্ট সময়ে একটি নির্দিষ্ট অ্যাসেটের মূল্য। এই মুহূর্তে, `asset` ফিল্ডটি অপ্রাসঙ্গিক কারণ আমরা একটি একক পুল ব্যবহার করি এবং তাই একটি একক অ্যাসেট আছে। তবে, আমরা পরে আরও অ্যাসেট যোগ করব। + +```python +def read_token(address: str) -> ERC20Token: + token = w3.eth.contract(address=address, abi=ERC20_ABI) + symbol = token.functions.symbol().call() + decimals = token.functions.decimals().call() + + return ERC20Token( + address=address, + symbol=symbol, + decimals=decimals, + contract=token + ) +``` + +এই ফাংশনটি একটি অ্যাড্রেস নেয় এবং সেই অ্যাড্রেসে থাকা টোকেন কন্ট্র্যাক্ট সম্পর্কে তথ্য প্রদান করে। একটি নতুন [Web3 `Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) তৈরি করতে, আমরা `w3.eth.contract`-কে অ্যাড্রেস এবং ABI প্রদান করি। + +```python +def read_pool(address: str) -> PoolInfo: + pool_contract = w3.eth.contract(address=address, abi=POOL_ABI) + token0Address = pool_contract.functions.token0().call() + token1Address = pool_contract.functions.token1().call() + token0 = read_token(token0Address) + token1 = read_token(token1Address) + + return PoolInfo( + address=address, + asset=f"{token1.symbol}/{token0.symbol}", + token0=token0, + token1=token1, + contract=pool_contract, + decimal_factor=Decimal(10) ** Decimal(token0.decimals - token1.decimals) + ) +``` + +এই ফাংশনটি [একটি নির্দিষ্ট পুল](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol) সম্পর্কে আমাদের প্রয়োজনীয় সবকিছু প্রদান করে। সিনট্যাক্স `f""` একটি [ফরম্যাটেড স্ট্রিং](https://docs.python.org/3/reference/lexical_analysis.html#f-strings)। + +```python +def get_quote(pool: PoolInfo, block_number: int = None) -> Quote: +``` + +একটি `Quote` অবজেক্ট পান। `block_number`-এর ডিফল্ট মান হল `None` (কোনো মান নেই)। + +```python + if block_number is None: + block_number = w3.eth.block_number +``` + +যদি কোনো ব্লক নম্বর নির্দিষ্ট করা না হয়, তাহলে `w3.eth.block_number` ব্যবহার করুন, যা সর্বশেষ ব্লক নম্বর। এটি [একটি `if` স্টেটমেন্টের](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement) সিনট্যাক্স। + +এটা দেখে মনে হতে পারে যে ডিফল্ট হিসেবে `w3.eth.block_number` সেট করাই ভালো ছিল, কিন্তু সেটা ঠিকভাবে কাজ করে না কারণ এটা ফাংশনটি সংজ্ঞায়িত করার সময়ের ব্লক নম্বর হতো। একটি দীর্ঘ-চলমান এজেন্টে, এটি একটি সমস্যা হবে। + +```python + block = w3.eth.get_block(block_number) + price = pool.get_price(block_number) + return Quote( + timestamp=datetime.fromtimestamp(block.timestamp, timezone.utc).isoformat(), + price=price.quantize(Decimal("0.01")), + asset=pool.asset + ) +``` + +মানুষ এবং বড় ভাষার মডেলের (LLM) জন্য পঠনযোগ্য ফরম্যাটে ফরম্যাট করতে [`datetime` লাইব্রেরি](https://docs.python.org/3/library/datetime.html) ব্যবহার করুন। মানটিকে দুই দশমিক স্থানে রাউন্ড করতে [`Decimal.quantize`](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) ব্যবহার করুন। + +```python +def get_quotes(pool: PoolInfo, start_block: int, end_block: int, step: int) -> list[Quote]: +``` + +Python-এ আপনি `list[]` ব্যবহার করে একটি [তালিকা](https://docs.python.org/3/library/stdtypes.html#typesseq-list) সংজ্ঞায়িত করেন যা শুধুমাত্র একটি নির্দিষ্ট টাইপ ধারণ করতে পারে। + +```python + quotes = [] + for block in range(start_block, end_block + 1, step): +``` + +Python-এ একটি [`for` লুপ](https://docs.python.org/3/tutorial/controlflow.html#for-statements) সাধারণত একটি তালিকার উপর পুনরাবৃত্তি করে। কোট খুঁজে বের করার জন্য ব্লক নম্বরের তালিকাটি [`range`](https://docs.python.org/3/library/stdtypes.html#range) থেকে আসে। + +```python + quote = get_quote(pool, block) + quotes.append(quote) + return quotes +``` + +প্রতিটি ব্লক নম্বরের জন্য, একটি `Quote` অবজেক্ট পান এবং এটিকে `quotes` তালিকায় যোগ করুন। তারপর সেই তালিকাটি ফেরত দিন। + +```python +pool = read_pool(WETHUSDC_ADDRESS) +quotes = get_quotes( + pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) + +pprint(quotes) +``` + +এটি স্ক্রিপ্টের মূল কোড। পুল তথ্য পড়ুন, বারোটি কোট পান, এবং সেগুলোকে [`pprint`](https://docs.python.org/3/library/pprint.html#pprint.pprint) করুন। + +### একটি প্রম্পট তৈরি করা {#prompt} + +এরপরে, আমাদের এই কোটগুলোর তালিকাকে একটি LLM-এর জন্য প্রম্পটে রূপান্তর করতে হবে এবং একটি প্রত্যাশিত ভবিষ্যৎ মান পেতে হবে। + +```sh +git checkout 03-create-prompt +uv run agent.py +``` + +আউটপুট এখন একটি LLM-এর জন্য একটি প্রম্পট হবে, যা দেখতে অনেকটা এইরকম: + +``` +এই কোটগুলো দেওয়া আছে: +অ্যাসেট: WETH/USDC + 2026-01-20T16:34 3016.21 + . + . + . + 2026-02-01T17:49 2299.10 + +অ্যাসেট: WBTC/WETH + 2026-01-20T16:34 29.84 + . + . + . + 2026-02-01T17:50 33.46 + + +2026-02-02T17:56 সময়ে WETH/USDC-এর মান কী হতে পারে বলে আপনি আশা করেন? + +আপনার উত্তরটি দুটি দশমিক স্থানে রাউন্ড করা একটি একক সংখ্যা হিসেবে দিন, +অন্য কোনো লেখা ছাড়া। +``` + +লক্ষ্য করুন যে এখানে দুটি অ্যাসেটের জন্য কোট রয়েছে, `WETH/USDC` এবং `WBTC/WETH`। অন্য একটি অ্যাসেট থেকে কোট যোগ করলে ভবিষ্যদ্বাণীর নির্ভুলতা উন্নত হতে পারে। + +#### একটি প্রম্পট কেমন দেখতে হয় {#prompt-explanation} + +এই প্রম্পটটিতে তিনটি বিভাগ রয়েছে, যা LLM প্রম্পটে বেশ সাধারণ। + +1. তথ্য। LLM-গুলির প্রশিক্ষণের অনেক তথ্য থাকে, কিন্তু সাধারণত তাদের কাছে সর্বশেষ তথ্য থাকে না। এই কারণে আমাদের এখানে সর্বশেষ কোটগুলি পুনরুদ্ধার করতে হবে। একটি প্রম্পটে তথ্য যোগ করাকে [রিট্রিভাল অগমেন্টেড জেনারেশন (RAG)](https://en.wikipedia.org/wiki/Retrieval-augmented_generation) বলা হয়। + +2. আসল প্রশ্ন। এটাই আমরা জানতে চাই। + +3. আউটপুট ফরম্যাটিং নির্দেশাবলী। সাধারণত, একটি LLM আমাদের একটি অনুমান দেয় এবং এটি কীভাবে সেই অনুমানে পৌঁছেছে তার একটি ব্যাখ্যা দেয়। এটি মানুষের জন্য ভালো, কিন্তু একটি কম্পিউটার প্রোগ্রামের শুধু চূড়ান্ত ফলাফল প্রয়োজন। + +#### কোড ব্যাখ্যা {#prompt-code} + +এখানে নতুন কোডটি দেওয়া হলো। + +```python +from datetime import datetime, timezone, timedelta +``` + +আমাদের LLM-কে সেই সময়টি সরবরাহ করতে হবে যার জন্য আমরা একটি অনুমান চাই। ভবিষ্যতে "n মিনিট/ঘন্টা/দিন" সময় পেতে, আমরা [`timedelta` ক্লাস](https://docs.python.org/3/library/datetime.html#datetime.timedelta) ব্যবহার করি। + +```python +# আমরা যে পুলগুলো পড়ছি তার অ্যাড্রেস +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +WETHWBTC_ADDRESS = Web3.to_checksum_address("0xCBCdF9626bC03E24f779434178A73a0B4bad62eD") +``` + +আমাদের দুটি পুল পড়তে হবে। + +```python +@dataclass(frozen=True) +class PoolInfo: + . + . + . + reverse: bool = False + + def get_price(self, block: int) -> Decimal: + assert block <= w3.eth.block_number, "Block is in the future" + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 # (টোকেন0 প্রতি টোকেন1) + if self.reverse: + return 1/(raw_price * self.decimal_factor) + else: + return raw_price * self.decimal_factor +``` + +WETH/USDC পুলে, আমরা জানতে চাই একটি `টোকেন1` (WETH) কিনতে কতগুলো `টোকেন0` (USDC) প্রয়োজন। WETH/WBTC পুলে, আমরা জানতে চাই একটি `টোকেন0` (WBTC, যা র‍্যাপড বিটকয়েন) কিনতে কতগুলো `টোকেন1` (WETH) প্রয়োজন। আমাদের পুলের অনুপাত বিপরীত করা প্রয়োজন কিনা তা ট্র্যাক করতে হবে। + +```python +def read_pool(address: str, reverse: bool = False) -> PoolInfo: + . + . + . + + return PoolInfo( + . + . + . + + asset= f"{token1.symbol}/{token0.symbol}" if reverse else f"{token0.symbol}/{token1.symbol}", + reverse=reverse + ) +``` + +একটি পুলকে বিপরীত করতে হবে কিনা তা জানতে, আমরা `read_pool`-এ ইনপুট হিসেবে তা পাই। এছাড়াও, অ্যাসেট প্রতীকটি সঠিকভাবে সেট করতে হবে। + +` if else ` সিনট্যাক্সটি পাইথনে [টারনারি কন্ডিশনাল অপারেটর](https://en.wikipedia.org/wiki/Ternary_conditional_operator) এর সমতুল্য, যা একটি C-ডিরাইভড ভাষায় ` ? : ` হবে। + +```python +def format_quotes(quotes: list[Quote]) -> str: + result = f"Asset: {quotes[0].asset}\n" + for quote in quotes: + result += f"\t{quote.timestamp[0:16]} {quote.price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)}\n" + return result +``` + +এই ফাংশনটি `Quote` অবজেক্টের একটি তালিকা ফরম্যাট করে একটি স্ট্রিং তৈরি করে, ধরে নেওয়া হয় যে সবগুলো একই অ্যাসেটের জন্য প্রযোজ্য। + +```python +def make_prompt(quotes: list[list[Quote]], expected_time: str, asset: str) -> str: + return f""" +``` + +Python-এ [মাল্টি-লাইন স্ট্রিং লিটারাল](https://www.w3schools.com/python/gloss_python_multi_line_strings.asp) লেখা হয় `"""` .... হিসেবে। `"""`। + +```python +এই কোটগুলো দেওয়া আছে: +{ + functools.reduce(lambda acc, q: acc + '\n' + q, + map(lambda q: format_quotes(q), quotes)) +} +``` + +এখানে, আমরা প্রতিটি কোট তালিকার জন্য একটি স্ট্রিং তৈরি করতে [MapReduce](https://en.wikipedia.org/wiki/MapReduce) প্যাটার্ন ব্যবহার করি, `format_quotes` দিয়ে, তারপর প্রম্পটে ব্যবহারের জন্য সেগুলোকে একটি একক স্ট্রিং-এ পরিণত করি। + +```python +{expected_time} সময়ে {asset}-এর মান কী হবে বলে আপনি আশা করেন? + +আপনার উত্তরটি দুই দশমিক স্থান পর্যন্ত রাউন্ড করা একটি একক সংখ্যা হিসেবে দিন, +অন্য কোনো লেখা ছাড়া। + """ +``` + +প্রম্পটের বাকি অংশ প্রত্যাশিত। + +```python +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +দুটি পুল পর্যালোচনা করুন এবং উভয় থেকে কোট সংগ্রহ করুন। + +```python +future_time = (datetime.now(timezone.utc) + timedelta(days=1)).isoformat()[0:16] + +print(make_prompt(wethusdc_quotes + wethwbtc_quotes, future_time, wethusdc_pool.asset)) +``` + +ভবিষ্যতের যে সময়বিন্দুর জন্য আমরা অনুমান চাই তা নির্ধারণ করুন এবং প্রম্পটটি তৈরি করুন। + +### একটি LLM-এর সাথে ইন্টারফেসিং {#interface-llm} + +এরপরে, আমরা একটি আসল LLM-কে প্রম্পট করি এবং একটি প্রত্যাশিত ভবিষ্যৎ মান পাই। আমি এই প্রোগ্রামটি OpenAI ব্যবহার করে লিখেছি, তাই আপনি যদি অন্য কোনো প্রদানকারী ব্যবহার করতে চান, তাহলে আপনাকে এটি অ্যাডজাস্ট করতে হবে। + +1. একটি [OpenAI অ্যাকাউন্ট](https://auth.openai.com/create-account) পান + +2. [অ্যাকাউন্টে ফান্ড যোগ করুন](https://platform.openai.com/settings/organization/billing/overview)—লেখার সময় ন্যূনতম পরিমাণ হল $5 + +3. [একটি API কী তৈরি করুন](https://platform.openai.com/settings/organization/api-keys) + +4. কমান্ড লাইনে, API কী এক্সপোর্ট করুন যাতে আপনার প্রোগ্রাম এটি ব্যবহার করতে পারে + + ```sh + export OPENAI_API_KEY=sk-<কী-এর বাকি অংশ এখানে দিন> + ``` + +5. এজেন্টটি চেকআউট করুন এবং চালান + + ```sh + git checkout 04-interface-llm + uv run agent.py + ``` + +এখানে নতুন কোডটি দেওয়া হলো। + +```python +from openai import OpenAI + +open_ai = OpenAI() # ক্লায়েন্ট OPENAI_API_KEY এনভায়রনমেন্ট ভেরিয়েবল পড়ে +``` + +OpenAI API ইম্পোর্ট এবং ইনস্ট্যানশিয়েট করুন। + +```python +response = open_ai.chat.completions.create( + model="gpt-4-turbo", + messages=[ + {"role": "user", "content": prompt} + ], + temperature=0.0, + max_tokens=16, +) +``` + +প্রতিক্রিয়া তৈরি করতে OpenAI API (`open_ai.chat.completions.create`) কল করুন। + +```python +expected_price = Decimal(response.choices[0].message.content.strip()) +current_price = wethusdc_quotes[-1].price + +print ("বর্তমান মূল্য:", wethusdc_quotes[-1].price) +print(f"{future_time}-এ, প্রত্যাশিত মূল্য: {expected_price} USD") + +if (expected_price > current_price): + print(f"কিনুন, আমি আশা করি মূল্য {expected_price - current_price} USD বাড়বে") +else: + print(f"বিক্রি করুন, আমি আশা করি মূল্য {current_price - expected_price} USD কমবে") +``` + +মূল্যটি আউটপুট করুন এবং একটি কেনা বা বেচার সুপারিশ প্রদান করুন। + +#### ভবিষ্যদ্বাণী পরীক্ষা করা {#testing-the-predictions} + +এখন যেহেতু আমরা ভবিষ্যদ্বাণী তৈরি করতে পারি, আমরা ঐতিহাসিক ডেটা ব্যবহার করে মূল্যায়ন করতে পারি যে আমরা দরকারী ভবিষ্যদ্বাণী তৈরি করছি কিনা। + +```sh +uv run test-predictor.py +``` + +প্রত্যাশিত ফলাফলটি অনেকটা এইরকম: + +``` +2026-01-05T19:50-এর জন্য ভবিষ্যদ্বাণী: ভবিষ্যদ্বাণী 3138.93 USD, আসল 3218.92 USD, ত্রুটি 79.99 USD +2026-01-06T19:56-এর জন্য ভবিষ্যদ্বাণী: ভবিষ্যদ্বাণী 3243.39 USD, আসল 3221.08 USD, ত্রুটি 22.31 USD +2026-01-07T20:02-এর জন্য ভবিষ্যদ্বাণী: ভবিষ্যদ্বাণী 3223.24 USD, আসল 3146.89 USD, ত্রুটি 76.35 USD +2026-01-08T20:11-এর জন্য ভবিষ্যদ্বাণী: ভবিষ্যদ্বাণী 3150.47 USD, আসল 3092.04 USD, ত্রুটি 58.43 USD +. +. +. +2026-01-31T22:33-এর জন্য ভবিষ্যদ্বাণী: ভবিষ্যদ্বাণী 2637.73 USD, আসল 2417.77 USD, ত্রুটি 219.96 USD +2026-02-01T22:41-এর জন্য ভবিষ্যদ্বাণী: ভবিষ্যদ্বাণী 2381.70 USD, আসল 2318.84 USD, ত্রুটি 62.86 USD +2026-02-02T22:49-এর জন্য ভবিষ্যদ্বাণী: ভবিষ্যদ্বাণী 2234.91 USD, আসল 2349.28 USD, ত্রুটি 114.37 USD +29টি ভবিষ্যদ্বাণীর উপর গড় ভবিষ্যদ্বাণীর ত্রুটি: 83.87103448275862068965517241 USD +প্রতি সুপারিশে গড় পরিবর্তন: 4.787931034482758620689655172 USD +পরিবর্তনের স্ট্যান্ডার্ড ভ্যারিয়েন্স: 104.42 USD +লাভজনক দিন: 51.72% +লোকসানের দিন: 48.28% +``` + +পরীক্ষকের বেশিরভাগ অংশ এজেন্টের সাথে অভিন্ন, কিন্তু এখানে নতুন বা পরিবর্তিত অংশগুলি রয়েছে। + +```python +CYCLES_FOR_TEST = 40 # ব্যাকটেস্টের জন্য, আমরা কতগুলি চক্র পরীক্ষা করি + +# অনেক কোট পান +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +আমরা `CYCLES_FOR_TEST` (এখানে 40 হিসাবে নির্দিষ্ট) দিন পিছনে দেখি। + +```python +# ভবিষ্যদ্বাণী তৈরি করুন এবং বাস্তব ইতিহাসের সাথে তাদের পরীক্ষা করুন + +total_error = Decimal(0) +changes = [] +``` + +দুই ধরনের ত্রুটি আছে যা নিয়ে আমরা আগ্রহী। প্রথমটি, `total_error`, হল ভবিষ্যদ্বাণীকারীর করা ত্রুটিগুলির সমষ্টি। + +দ্বিতীয়টি, `changes`, বোঝার জন্য, আমাদের এজেন্টের উদ্দেশ্য মনে রাখতে হবে। এটি WETH/USDC অনুপাত (ETH মূল্য) ভবিষ্যদ্বাণী করার জন্য নয়। এটি বিক্রয় এবং কেনার সুপারিশ জারি করার জন্য। যদি বর্তমানে মূল্য $2000 হয় এবং এটি আগামীকাল $2010 ভবিষ্যদ্বাণী করে, তাহলে আসল ফলাফল যদি $2020 হয় এবং আমরা অতিরিক্ত অর্থ উপার্জন করি তবে আমরা কিছু মনে করি না। কিন্তু আমরা _অবশ্যই_ কিছু মনে করি যদি এটি $2010 ভবিষ্যদ্বাণী করে, এবং সেই সুপারিশের ভিত্তিতে ETH কিনে, এবং দাম $1990-এ নেমে যায়। + +```python +for index in range(0,len(wethusdc_quotes)-CYCLES_BACK): +``` + +আমরা কেবল সেইসব ক্ষেত্রে দেখতে পারি যেখানে সম্পূর্ণ ইতিহাস (ভবিষ্যদ্বাণীর জন্য ব্যবহৃত মান এবং এটির সাথে তুলনা করার জন্য বাস্তব-বিশ্বের মান) উপলব্ধ রয়েছে। এর মানে হল যে নতুনতম কেসটি অবশ্যই `CYCLES_BACK` আগে শুরু হয়েছে। + +```python + wethusdc_slice = wethusdc_quotes[index:index+CYCLES_BACK] + wethwbtc_slice = wethwbtc_quotes[index:index+CYCLES_BACK] +``` + +এজেন্ট যে সংখ্যক নমুনা ব্যবহার করে সেই একই সংখ্যক নমুনা পেতে [স্লাইস](https://www.w3schools.com/python/ref_func_slice.asp) ব্যবহার করুন। এখানে এবং পরবর্তী সেগমেন্টের মধ্যে কোডটি এজেন্টে আমাদের থাকা একই get-a-prediction কোড। + +```python + predicted_price = Decimal(response.choices[0].message.content.strip()) + real_price = wethusdc_quotes[index+CYCLES_BACK].price + prediction_time_price = wethusdc_quotes[index+CYCLES_BACK-1].price +``` + +ভবিষ্যদ্বাণী করা মূল্য, আসল মূল্য এবং ভবিষ্যদ্বাণীর সময়ের মূল্য পান। সুপারিশটি কেনার নাকি বেচার ছিল তা নির্ধারণ করার জন্য আমাদের ভবিষ্যদ্বাণীর সময়ের মূল্য প্রয়োজন। + +```python + error = abs(predicted_price - real_price) + total_error += error + print (f"{prediction_time}-এর জন্য ভবিষ্যদ্বাণী: ভবিষ্যদ্বাণী {predicted_price} USD, আসল {real_price} USD, ত্রুটি {error} USD") +``` + +ত্রুটি নির্ণয় করুন, এবং এটিকে মোটের সাথে যোগ করুন। + +```python + recomended_action = 'buy' if predicted_price > prediction_time_price else 'sell' + price_increase = real_price - prediction_time_price + changes.append(price_increase if recomended_action == 'buy' else -price_increase) +``` + +`changes`-এর জন্য, আমরা এক ETH কেনা বা বেচার আর্থিক প্রভাব চাই। তাই প্রথমে, আমাদের সুপারিশটি নির্ধারণ করতে হবে, তারপর আসল মূল্য কীভাবে পরিবর্তিত হয়েছে তা মূল্যায়ন করতে হবে এবং সুপারিশটি লাভজনক ছিল (ধনাত্মক পরিবর্তন) নাকি লোকসানের কারণ হয়েছিল (ঋণাত্মক পরিবর্তন)। + +```python +print (f"{len(wethusdc_quotes)-CYCLES_BACK}টি ভবিষ্যদ্বাণীর উপর গড় ভবিষ্যদ্বাণীর ত্রুটি: {total_error / Decimal(len(wethusdc_quotes)-CYCLES_BACK)} USD") + +length_changes = Decimal(len(changes)) +mean_change = sum(changes, Decimal(0)) / length_changes +print (f"প্রতি সুপারিশে গড় পরিবর্তন: {mean_change} USD") +var = sum((x - mean_change) ** 2 for x in changes) / length_changes +print (f"পরিবর্তনের স্ট্যান্ডার্ড ভ্যারিয়েন্স: {var.sqrt().quantize(Decimal("0.01"))} USD") +``` + +ফলাফলগুলি রিপোর্ট করুন। + +```python +print (f"লাভজনক দিন: {len(list(filter(lambda x: x > 0, changes)))/length_changes:.2%}") +print (f"লোকসানের দিন: {len(list(filter(lambda x: x < 0, changes)))/length_changes:.2%}") +``` + +লাভজনক দিন এবং লোকসানের দিনের সংখ্যা গণনা করতে [`filter`](https://www.w3schools.com/python/ref_func_filter.asp) ব্যবহার করুন। ফলাফল একটি ফিল্টার অবজেক্ট, যা আমাদের দৈর্ঘ্য পেতে একটি তালিকায় রূপান্তর করতে হবে। + +### লেনদেন জমা দেওয়া {#submit-txn} + +এখন আমাদের আসলে লেনদেন জমা দিতে হবে। তবে, সিস্টেমটি প্রমাণিত হওয়ার আগে আমি এই মুহূর্তে আসল টাকা খরচ করতে চাই না। পরিবর্তে, আমরা মেইননেটের একটি স্থানীয় ফর্ক তৈরি করব এবং সেই নেটওয়ার্কে "ট্রেড" করব। + +এখানে একটি স্থানীয় ফর্ক তৈরি এবং ট্রেডিং সক্ষম করার ধাপগুলি দেওয়া হল। + +1. [Foundry](https://getfoundry.sh/introduction/installation) ইনস্টল করুন + +2. [`anvil`](https://getfoundry.sh/anvil/overview) শুরু করুন + + ```sh + anvil --fork-url https://eth.drpc.org --block-time 12 + ``` + + `anvil` Foundry-এর ডিফল্ট URL, http://localhost:8545-এ লিসেন করছে, তাই ব্লকচেইন ম্যানিপুলেট করার জন্য আমরা যে [`cast` কমান্ড](https://getfoundry.sh/cast/overview) ব্যবহার করি তার জন্য URL নির্দিষ্ট করার প্রয়োজন নেই। + +3. `anvil`-এ চালানোর সময়, দশটি টেস্ট অ্যাকাউন্ট থাকে যেগুলোতে ETH আছে—প্রথমটির জন্য এনভায়রনমেন্ট ভেরিয়েবল সেট করুন + + ```sh + PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ADDRESS=`cast wallet address $PRIVATE_KEY` + ``` + +4. এগুলো হল কন্ট্র্যাক্ট যা আমাদের ব্যবহার করতে হবে। [`SwapRouter`](https://github.com/Uniswap/v3-periphery/blob/main/contracts/SwapRouter.sol) হল Uniswap v3 কন্ট্র্যাক্ট যা আমরা আসলে ট্রেড করতে ব্যবহার করি। আমরা সরাসরি পুলের মাধ্যমে ট্রেড করতে পারতাম, কিন্তু এটি অনেক সহজ। + + নীচের দুটি ভেরিয়েবল হল WETH এবং USDC-এর মধ্যে সোয়াপ করার জন্য প্রয়োজনীয় Uniswap v3 পাথ। + + ```sh + WETH_ADDRESS=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + USDC_ADDRESS=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + POOL_ADDRESS=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 + SWAP_ROUTER=0xE592427A0AEce92De3Edee1F18E0157C05861564 + WETH_TO_USDC=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + USDC_TO_WETH=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + ``` + +5. প্রতিটি টেস্ট অ্যাকাউন্টে 10,000 ETH আছে। ট্রেডিংয়ের জন্য 1000 WETH পেতে 1000 ETH র‍্যাপ করতে WETH কন্ট্র্যাক্ট ব্যবহার করুন। + + ```sh + cast send $WETH_ADDRESS "deposit()" --value 1000ether --private-key $PRIVATE_KEY + ``` + +6. `SwapRouter` ব্যবহার করে 500 WETH ট্রেড করে USDC নিন। + + ```sh + cast send $WETH_ADDRESS "approve(address,uint256)" $SWAP_ROUTER 500ether --private-key $PRIVATE_KEY + MAXINT=`cast max-int uint256` + cast send $SWAP_ROUTER \ + "exactInput((bytes,address,uint256,uint256,uint256))" \ + "($WETH_TO_USDC,$ADDRESS,$MAXINT,500ether,1000000)" \ + --private-key $PRIVATE_KEY + ``` + + `approve` কল একটি অ্যালাওয়েন্স তৈরি করে যা `SwapRouter`-কে আমাদের কিছু টোকেন খরচ করার অনুমতি দেয়। কন্ট্র্যাক্টগুলি ইভেন্টগুলি নিরীক্ষণ করতে পারে না, তাই যদি আমরা সরাসরি `SwapRouter` কন্ট্র্যাক্টে টোকেন স্থানান্তর করি, তবে এটি জানতে পারবে না যে এটি পরিশোধ করা হয়েছে। পরিবর্তে, আমরা `SwapRouter` কন্ট্র্যাক্টকে একটি নির্দিষ্ট পরিমাণ খরচ করার অনুমতি দিই, এবং তারপর `SwapRouter` এটি করে। এটি `SwapRouter` দ্বারা কল করা একটি ফাংশনের মাধ্যমে করা হয়, তাই এটি জানে যে এটি সফল হয়েছে কিনা। + +7. আপনার কাছে উভয় টোকেন পর্যাপ্ত পরিমাণে আছে কিনা তা যাচাই করুন। + + ```sh + cast call $WETH_ADDRESS "balanceOf(address)" $ADDRESS | cast from-wei + echo `cast call $USDC_ADDRESS "balanceOf(address)" $ADDRESS | cast to-dec`/10^6 | bc + ``` + +এখন যেহেতু আমাদের কাছে WETH এবং USDC আছে, আমরা আসলে এজেন্টটি চালাতে পারি। + +```sh +git checkout 05-trade +uv run agent.py +``` + +আউটপুটটি দেখতে অনেকটা এইরকম হবে: + +``` +(ai-trading-agent) qbzzt@Ori-Cloudnomics:~/260215-ai-agent$ uv run agent.py +বর্তমান মূল্য: 1843.16 +2026-02-06T23:07-এ, প্রত্যাশিত মূল্য: 1724.41 USD +ট্রেডের আগে অ্যাকাউন্টের ব্যালেন্স: +USDC ব্যালেন্স: 927301.578272 +WETH ব্যালেন্স: 500 +বিক্রি করুন, আমি আশা করি মূল্য 118.75 USD কমবে +অনুমোদন লেনদেন পাঠানো হয়েছে: 74e367ddbb407c1aaf567d87aa5863049991b1d2aa092b6b85195d925e2bd41f +অনুমোদন লেনদেন মাইনিং করা হয়েছে। +বিক্রয় লেনদেন পাঠানো হয়েছে: fad1bcf938585c9e90364b26ac7a80eea9efd34c37e5db81e58d7655bcae28bf +বিক্রয় লেনদেন মাইনিং করা হয়েছে। +ট্রেডের পরে অ্যাকাউন্টের ব্যালেন্স: +USDC ব্যালেন্স: 929143.797116 +WETH ব্যালেন্স: 499 +``` + +এটি আসলে ব্যবহার করার জন্য, আপনাকে কয়েকটি ছোট পরিবর্তন করতে হবে। + +- লাইন 14-এ, `MAINNET_URL` পরিবর্তন করে একটি বাস্তব অ্যাক্সেস পয়েন্ট, যেমন `https://eth.drpc.org`-এ দিন +- লাইন 28-এ, `PRIVATE_KEY` পরিবর্তন করে আপনার নিজের প্রাইভেট কী দিন +- যদি না আপনি খুব ধনী হন এবং একটি অপ্রমাণিত এজেন্টের জন্য প্রতিদিন 1 ETH কিনতে বা বিক্রি করতে পারেন, তাহলে আপনি `WETH_TRADE_AMOUNT` কমাতে 29 পরিবর্তন করতে চাইতে পারেন + +#### কোড ব্যাখ্যা {#trading-code} + +এখানে নতুন কোডটি দেওয়া হলো। + +```python +SWAP_ROUTER_ADDRESS=Web3.to_checksum_address("0xE592427A0AEce92De3Edee1F18E0157C05861564") +WETH_TO_USDC=bytes.fromhex("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") +USDC_TO_WETH=bytes.fromhex("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +``` + +ধাপ 4-এ আমরা যে একই ভেরিয়েবল ব্যবহার করেছি। + +```python +WETH_TRADE_AMOUNT=1 +``` + +ট্রেড করার পরিমাণ। + +```python +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... }, + { "name": "balanceOf", ...}, + { "name": "approve", ...} +] +``` + +আসলে ট্রেড করার জন্য, আমাদের `approve` ফাংশন প্রয়োজন। আমরা আগে এবং পরে ব্যালেন্সও দেখাতে চাই, তাই আমাদের `balanceOf` ও প্রয়োজন। + +```python +SWAP_ROUTER_ABI = [ + { "name": "exactInput", ...}, +] +``` + +`SwapRouter` ABI-তে আমাদের শুধু `exactInput` প্রয়োজন। একটি সম্পর্কিত ফাংশন আছে, `exactOutput`, যা আমরা ঠিক একটি WETH কেনার জন্য ব্যবহার করতে পারতাম, কিন্তু সরলতার জন্য আমরা উভয় ক্ষেত্রে `exactInput` ব্যবহার করি। + +```python +account = w3.eth.account.from_key(PRIVATE_KEY) +swap_router = w3.eth.contract( + address=SWAP_ROUTER_ADDRESS, + abi=SWAP_ROUTER_ABI +) +``` + +[`account`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html) এবং `SwapRouter` কন্ট্র্যাক্টের জন্য Web3 সংজ্ঞা। + +```python +def txn_params() -> dict: + return { + "from": account.address, + "value": 0, + "gas": 300000, + "nonce": w3.eth.get_transaction_count(account.address), + } +``` + +লেনদেনের প্যারামিটার। এখানে আমাদের একটি ফাংশন প্রয়োজন কারণ [নন্স](https://en.wikipedia.org/wiki/Cryptographic_nonce) প্রতিবার পরিবর্তন হতে হবে। + +```python +def approve_token(contract: Contract, amount: int): +``` + +`SwapRouter`-এর জন্য একটি টোকেন অ্যালাওয়েন্স অনুমোদন করুন। + +```python + txn = contract.functions.approve(SWAP_ROUTER_ADDRESS, amount).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) +``` + +এভাবে আমরা Web3-এ একটি লেনদেন পাঠাই। প্রথমে আমরা লেনদেন তৈরি করতে [`Contract` অবজেক্ট](https://web3py.readthedocs.io/en/stable/web3.contract.html) ব্যবহার করি। তারপর আমরা `PRIVATE_KEY` ব্যবহার করে লেনদেন সাইন করতে [`web3.eth.account.sign_transaction`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-contract-transaction) ব্যবহার করি। অবশেষে, আমরা লেনদেন পাঠাতে [`w3.eth.send_raw_transaction`](https://web3py.readthedocs.io/en/stable/transactions.html#chapter-2-w3-eth-send-raw-transaction) ব্যবহার করি। + +```python + print(f"অনুমোদন লেনদেন পাঠানো হয়েছে: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("অনুমোদন লেনদেন মাইনিং করা হয়েছে।") +``` + +[`w3.eth.wait_for_transaction_receipt`](https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.wait_for_transaction_receipt) লেনদেন মাইনিং না হওয়া পর্যন্ত অপেক্ষা করে। প্রয়োজন হলে এটি রসিদ প্রদান করে। + +```python +SELL_PARAMS = { + "path": WETH_TO_USDC, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": WETH_TRADE_AMOUNT * 10 ** wethusdc_pool.token1.decimals, + "amountOutMinimum": 0, +} +``` + +WETH বিক্রি করার সময় এইগুলি হল প্যারামিটার। + +```python +def make_buy_params(quote: Quote) -> dict: + return { + "path": USDC_TO_WETH, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": int(quote.price*WETH_TRADE_AMOUNT) * 10**wethusdc_pool.token0.decimals, + "amountOutMinimum": 0, + } +``` + +`SELL_PARAMS`-এর বিপরীতে, কেনার প্যারামিটারগুলি পরিবর্তন হতে পারে। ইনপুট পরিমাণ হল 1 WETH-এর খরচ, যা `quote`-এ উপলব্ধ। + +```python +def buy(quote: Quote): + buy_params = make_buy_params(quote) + approve_token(wethusdc_pool.token0.contract, buy_params["amountIn"]) + txn = swap_router.functions.exactInput(buy_params).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"কেনার লেনদেন পাঠানো হয়েছে: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("কেনার লেনদেন মাইনিং করা হয়েছে।") + + +def sell(): + approve_token(wethusdc_pool.token1.contract, + WETH_TRADE_AMOUNT * 10**wethusdc_pool.token1.decimals) + txn = swap_router.functions.exactInput(SELL_PARAMS).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"বিক্রয় লেনদেন পাঠানো হয়েছে: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("বিক্রয় লেনদেন মাইনিং করা হয়েছে।") +``` + +`buy()` এবং `sell()` ফাংশনগুলি প্রায় অভিন্ন। প্রথমে আমরা `SwapRouter`-এর জন্য একটি পর্যাপ্ত অ্যালাওয়েন্স অনুমোদন করি এবং তারপর আমরা সঠিক পাথ এবং পরিমাণ দিয়ে এটি কল করি। + +```python +def balances(): + token0_balance = wethusdc_pool.token0.contract.functions.balanceOf(account.address).call() + token1_balance = wethusdc_pool.token1.contract.functions.balanceOf(account.address).call() + + print(f"{wethusdc_pool.token0.symbol} ব্যালেন্স: {Decimal(token0_balance) / Decimal(10 ** wethusdc_pool.token0.decimals)}") + print(f"{wethusdc_pool.token1.symbol} ব্যালেন্স: {Decimal(token1_balance) / Decimal(10 ** wethusdc_pool.token1.decimals)}") +``` + +উভয় মুদ্রায় ব্যবহারকারীর ব্যালেন্স রিপোর্ট করুন। + +```python +print("ট্রেডের আগে অ্যাকাউন্টের ব্যালেন্স:") +balances() + +if (expected_price > current_price): + print(f"কিনুন, আমি আশা করি মূল্য {expected_price - current_price} USD বাড়বে") + buy(wethusdc_quotes[-1]) +else: + print(f"বিক্রি করুন, আমি আশা করি মূল্য {current_price - expected_price} USD কমবে") + sell() + +print("ট্রেডের পরে অ্যাকাউন্টের ব্যালেন্স:") +balances() +``` + +এই এজেন্ট বর্তমানে শুধুমাত্র একবার কাজ করে। তবে, আপনি এটিকে [`crontab`](https://man7.org/linux/man-pages/man1/crontab.1.html) থেকে চালিয়ে বা একটি লুপে 368-400 লাইনগুলি র‍্যাপ করে এবং পরবর্তী চক্রের জন্য অপেক্ষা করার জন্য [`time.sleep`](https://docs.python.org/3/library/time.html#time.sleep) ব্যবহার করে ক্রমাগত কাজ করার জন্য পরিবর্তন করতে পারেন। + +## সম্ভাব্য উন্নতি {#improvements} + +এটি একটি সম্পূর্ণ প্রোডাকশন সংস্করণ নয়; এটি শুধুমাত্র মূল বিষয়গুলি শেখানোর জন্য একটি উদাহরণ। এখানে উন্নতির জন্য কিছু ধারণা দেওয়া হল। + +### স্মার্ট ট্রেডিং {#smart-trading} + +দুটি গুরুত্বপূর্ণ তথ্য রয়েছে যা এজেন্ট কী করতে হবে তা সিদ্ধান্ত নেওয়ার সময় উপেক্ষা করে। + +- _প্রত্যাশিত পরিবর্তনের মাত্রা_। মূল্য হ্রাসের মাত্রা নির্বিশেষে, যদি মূল্য হ্রাসের প্রত্যাশা করা হয় তবে এজেন্ট একটি নির্দিষ্ট পরিমাণ `WETH` বিক্রি করে। + যুক্তিযুক্তভাবে, ছোটখাটো পরিবর্তন উপেক্ষা করা এবং আমরা কতটা মূল্য হ্রাসের প্রত্যাশা করি তার উপর ভিত্তি করে বিক্রি করা ভাল হবে। +- _বর্তমান পোর্টফোলিও_। যদি আপনার পোর্টফোলিওর 10% WETH-এ থাকে এবং আপনি মনে করেন দাম বাড়বে, তাহলে সম্ভবত আরও কেনা যুক্তিযুক্ত। কিন্তু যদি আপনার পোর্টফোলিওর 90% WETH-এ থাকে, তাহলে আপনি যথেষ্ট এক্সপোজড হতে পারেন, এবং আরও কেনার প্রয়োজন নেই। আপনি যদি দাম কমার আশা করেন তবে এর বিপরীতটি সত্য। + +### আপনি যদি আপনার ট্রেডিং কৌশল গোপন রাখতে চান তাহলে কী হবে? {#secret} + +AI বিক্রেতারা তাদের LLM-গুলিতে আপনার পাঠানো কোয়েরিগুলি দেখতে পারে, যা আপনার এজেন্টের সাথে আপনি যে জিনিয়াস ট্রেডিং সিস্টেম তৈরি করেছেন তা প্রকাশ করতে পারে। একটি ট্রেডিং সিস্টেম যা অনেক লোক ব্যবহার করে তা মূল্যহীন কারণ যখন আপনি কিনতে চান তখন অনেক লোক কেনার চেষ্টা করে (এবং দাম বেড়ে যায়) এবং যখন আপনি বিক্রি করতে চান তখন বিক্রি করার চেষ্টা করে (এবং দাম কমে যায়)। + +এই সমস্যা এড়াতে আপনি স্থানীয়ভাবে একটি LLM চালাতে পারেন, উদাহরণস্বরূপ, [LM-Studio](https://lmstudio.ai/) ব্যবহার করে। + +### AI বট থেকে AI এজেন্ট {#bot-to-agent} + +আপনি একটি ভাল যুক্তি দিতে পারেন যে এটি [একটি AI বট, AI এজেন্ট নয়](/ai-agents/#ai-agents-vs-ai-bots)। এটি একটি তুলনামূলকভাবে সহজ কৌশল বাস্তবায়ন করে যা পূর্বনির্ধারিত তথ্যের উপর নির্ভর করে। আমরা স্ব-উন্নতি সক্ষম করতে পারি, উদাহরণস্বরূপ, Uniswap v3 পুল এবং তাদের সর্বশেষ মানগুলির একটি তালিকা প্রদান করে এবং জিজ্ঞাসা করে কোন সংমিশ্রণের সেরা ভবিষ্যদ্বাণীমূলক মান রয়েছে। + +### স্লিপেজ সুরক্ষা {#slippage-protection} + +বর্তমানে কোনো [স্লিপেজ সুরক্ষা](https://uniswapv3book.com/milestone_3/slippage-protection.html) নেই। যদি বর্তমান কোট $2000 হয় এবং প্রত্যাশিত মূল্য $2100 হয়, এজেন্ট কিনবে। তবে, এজেন্ট কেনার আগে যদি খরচ $2200-এ বেড়ে যায়, তবে আর কেনার কোনো মানে হয় না। + +স্লিপেজ সুরক্ষা বাস্তবায়ন করতে, [`agent.py`](https://github.com/qbzzt/260215-ai-agent/blob/05-trade/agent.py#L325)-এর 325 এবং 334 লাইনে একটি `amountOutMinimum` মান নির্দিষ্ট করুন। + +## উপসংহার {#conclusion} + +আশা করি, এখন আপনি AI এজেন্টদের সাথে শুরু করার জন্য যথেষ্ট জানেন। এটি বিষয়টির একটি ব্যাপক ওভারভিউ নয়; এর জন্য পুরো বই উৎসর্গ করা হয়েছে, তবে এটি আপনাকে শুরু করার জন্য যথেষ্ট। শুভকামনা! + +[আমার আরও কাজের জন্য এখানে দেখুন](https://cryptodocguy.pro/)। diff --git a/public/content/translations/cs/community/support/faq/index.md b/public/content/translations/cs/community/support/faq/index.md new file mode 100644 index 00000000000..ca46bd90359 --- /dev/null +++ b/public/content/translations/cs/community/support/faq/index.md @@ -0,0 +1,77 @@ +--- +title: "Často kladené dotazy" +description: "Běžné dotazy o Ethereu týkající se peněženek, transakcí, uzamykání a dalších věcí." +lang: cs +--- + +# Často kladené dotazy {#faq} + +## Poslal jsem krypto na špatnou adresu {#wrong-wallet} + +Transakce odeslaná na Ethereu je nevratná. Pokud jste bohužel poslali ETH nebo tokeny na špatnou peněženku, neexistuje způsob, jak transakci vrátit. + +**Co můžete udělat:** + +- **Pokud znáte majitele adresy**, kontaktujte ho přímo a požádejte ho o vrácení prostředků +- **Pokud adresa patří burze nebo známé službě**, kontaktujte jejich tým podpory, protože by vám mohli pomoci +- **Pokud jste odeslali tokeny na adresu kontraktu**, zkontrolujte, zda má kontrakt funkci pro výběr nebo obnovení (to je vzácné) + +Ve většině případů neexistuje způsob, jak prostředky získat zpět. Ethereum nevlastní žádná centrální organizace, subjekt ani osoba, což znamená, že nikdo nemůže transakce vrátit. Před potvrzením si vždy dvakrát zkontrolujte adresu příjemce. + +## Ztratil jsem přístup ke své peněžence {#lost-wallet-access} + +Možnosti obnovení závisí na typu peněženky, kterou používáte. + +### Pokud máte svou bezpečnostní frázi (frázi pro obnovení) + +Pomocí bezpečnostní fráze můžete svou peněženku obnovit v jakékoli kompatibilní aplikaci peněženky. Proto je důležité, abyste svou bezpečnostní frázi uchovávali bezpečně v režimu offline. Pokyny k obnovení naleznete v dokumentaci poskytovatele vaší peněženky. + +### Pokud jste ztratili svou bezpečnostní frázi + +Bez vaší bezpečnostní fráze nebo privátních klíčů nelze vaše prostředky obnovit. Nikdo, včetně ethereum.org, vám nemůže obnovit heslo ani přístup k peněžence s vlastní správou. + +### Pokud je váš účet na burze + +Pokud je váš účet na centralizované burze, jako je Coinbase, Binance nebo Kraken, kontaktujte přímo tým podpory burzy. Oni spravují účty na své platformě a mohou vám pomoci s resetováním hesla nebo obnovením účtu. + + + + + + +**Nikdy nesdělujte svou bezpečnostní frázi nikomu**, kdo tvrdí, že vám pomáhá obnovit vaši peněženku. Jedná se o jednu z nejčastějších podvodných taktik. Žádná legitimní služba vás nikdy nepožádá o vaši bezpečnostní frázi. + + + + + + Jak používat peněženku + + +## Moje transakce je zaseknutá nebo čeká na vyřízení {#stuck-transaction} + +Transakce na Ethereu se mohou zaseknout, když je vámi nastavený poplatek za palivo nižší, než síť aktuálně vyžaduje. Většina peněženek vám to umožní opravit: + +- **Urychlit:** Odešlete stejnou transakci znovu s vyšším poplatkem za palivo +- **Zrušit:** Odešlete transakci 0 ETH na svou vlastní adresu se stejným nonce, jaké má čekající transakce + +### Užitečné příručky + +- [Jak urychlit nebo zrušit nevyřízenou transakci na MetaMask](https://support.metamask.io/transactions-and-gas/transactions/how-to-speed-up-or-cancel-a-pending-transaction/) +- [Jak zrušit nevyřízené transakce na Ethereu](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) + +## Jak mohu získat svou odměnu z Ethereum giveaway? {#giveaway-scam} + +Ethereum giveaway jsou podvody navržené k tomu, aby vám ukradly ETH. Nenechte se zlákat nabídkami, které se zdají být příliš dobré na to, aby byly pravdivé. Pokud pošlete ETH na adresu giveaway, žádnou odměnu nedostanete a nebudete moci své prostředky získat zpět. + +[Více o prevenci podvodů](/security/#common-scams) + +## Jak stakovat ETH? {#how-to-stake} + +Chcete-li se stát validátorem, musíte zastakovat 32 ETH v Ethereum deposit contractu a nastavit validační síťový uzel. S menším množstvím ETH se můžete také zúčastnit prostřednictvím stakingových poolů. + +Více informací je k dispozici na našich [stránkách o uzamykání](/staking/) a na [staking launchpadu](https://launchpad.ethereum.org/). + +## Jak mohu těžit Ethereum? Těžba Etherea {#mining-ethereum} + +Těžba Etherea už není možná. Těžba byla vypnuta, když Ethereum v září 2022 během [Sloučení (The Merge)](/roadmap/merge/) přešlo z [důkazu prací](/glossary/#pow) na [důkaz podílem](/glossary/#pos). Nyní má Ethereum místo těžařů validátory. Každý může [stakovat](/glossary/#staking) ETH a dostávat odměny za stakování za provozování validačního softwaru zabezpečujícího síť. diff --git a/public/content/translations/cs/community/support/index.md b/public/content/translations/cs/community/support/index.md deleted file mode 100644 index 742ddb1902f..00000000000 --- a/public/content/translations/cs/community/support/index.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Ethereum podpora -description: Získejte podporu v ekosystému Etherea. -lang: cs ---- - -# Ethereum podpora {#support} - -## Oficiální podpora pro Ethereum {#official-support} - -Hledáte oficiální podporu pro Ethereum? První věc, kterou byste měli vědět, je, že Ethereum je decentralizované. To znamená, že žádná centrální organizace, entita nebo osoba nevlastní Ethereum, a proto neexistují žádné oficiální kanály podpory. - -Pochopení decentralizované povahy Etherea je zásadní, protože **každý, kdo se vydává za oficiálního podporovatele Etherea, se vás pravděpodobně snaží podvést!** Nejlepší ochranou před podvodníky je vzdělávat se a brát bezpečnost vážně. - - - Bezpečnost a předcházení podvodům v Ethereu - - - - Osvojte si základy Etherea - - -Přestože neexistuje oficiální podpora, mnoho skupin, komunit a projektů v ekosystému Etherea je ochotných vám pomoci a na této stránce můžete najít mnoho užitečných informací a zdrojů. Stále máte dotazy? Připojte se na [Discordu ethereum.org](https://discord.gg/ethereum-org) a my se vám pokusíme pomoci. - -## Často kladené dotazy {#faq} - -### Poslal/a jsem ETH na špatnou peněženku {#wrong-wallet} - -Transakce odeslaná na Ethereu je nevratná. Bohužel, pokud jste poslali ETH na špatnou peněženku, není žádný způsob, jak tyto prostředky získat zpět. Žádná centrální organizace, entita ani osoba nevlastní Ethereum, což znamená, že nikdo nemůže transakce vrátit zpět. Proto je důležité vždy pečlivě zkontrolovat své transakce před jejich odesláním. - -### Jak mohu získat svou odměnu z Ethereum giveaway? {#giveaway-scam} - -Ethereum giveaway jsou podvody navržené k tomu, aby vám ukradly ETH. Nenechte se zlákat nabídkami, které vypadají až moc dobře na to, aby byly pravdivé — pokud pošlete ETH na adresu giveaway, nedostanete žádnou odměnu a nebudete moci své prostředky získat zpět. - -[Více o prevenci podvodů](/security/#common-scams) - -### Moje transakce se zasekla {#stuck-transaction} - -Transakce na Ethereu se mohou někdy zaseknout, a to v případě, že jste zadali nižší poplatek za transakci, než je požadováno vzhledem k zatížení sítě. Spousta peněženek poskytuje možnost znovu odeslat stejnou transakci s vyšším poplatkem, aby byla transakce zpracována. Alternativně můžete zrušit nevyřízenou transakci tím, že pošlete transakci na svou vlastní adresu a použijete stejné jedinečné číslo nonce jako u nevyřízené transakce. - -[Jak zrychlit nebo zrušit nevyřízenou transakci v MetaMasku](https://metamask.zendesk.com/hc/en-us/articles/360015489251-How-to-speed-up-or-cancel-a-pending-transaction) - -[Jak zrušit nevyřízené transakce na Ethereu](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) - -### Jak mohu těžit Ethereum? {#mining-ethereum} - -Těžba Etherea už není možná. Těžba byla ukončena, když Ethereum přešlo z [proof of work](/glossary/#pow) na [proof of stake](/glossary/#pos). Nyní má Ethereum místo těžařů validátory. Každý může [stakovat](/glossary/#staking) ETH a dostávat odměny za provozování validačního softwaru zabezpečujícího síť. - -### Jak se stát stakerem / provozovat validátor? {#how-to-stake} - -Chcete-li se stát validátorem, musíte zastakovat 32 ETH v Ethereum deposit contractu a nastavit validační síťový uzel. Další informace naleznete na našich [stránkách o stakování](/staking) a na [staking launchpadu](https://launchpad.ethereum.org/). - -## Vývoj dappek {#building-support} - -Vývoj může být obtížný. Zde najdete několik zdrojů zaměřených na vývoj, kde vám zkušení vývojáři Etherea rádi pomohou. - -- [Alchemy University](https://university.alchemy.com/#starter_code) -- [Discord CryptoDevs](https://discord.com/invite/5W5tVb3) -- [Ethereum StackExchange](https://ethereum.stackexchange.com/) -- [Web3 University](https://www.web3.university/) -- [LearnWeb3](https://discord.com/invite/learnweb3) - -V naší sekci [zdrojů pro vývojáře Etherea](/developers/) najdete dokumentaci a průvodce vývojem. - -### Nástroje {#dapp-tooling} - -Týká se vaše otázka konkrétního nástroje, projektu nebo knihovny? Většina projektů má chatovací servery nebo fóra věnovaná poskytování podpory. - -Zde jsou některé oblíbené příklady: - -- [Solidity](https://app.element.io/#/room/#solidity:matrix.org) -- [ethers.js](https://discord.gg/6jyGVDK6Jx) -- [web3.js](https://discord.gg/GsABYQu4sC) -- [Hardhat](https://discord.gg/xtrMGhmbfZ) -- [Alchemy](http://alchemy.com/discord) -- [Tenderly](https://discord.gg/fBvDJYR) - -## Provozování vlastního síťového uzlu {#node-support} - -Pokud provozujete uzel nebo validátora, tady najdete některé komunity, které vám pomohou začít. - -- [Discord EthStaker](https://discord.gg/ethstaker) -- [Reddit EthStaker](https://www.reddit.com/r/ethstaker) - -Většina týmů, které vytvářejí klienty na Ethereu, má také veřejně přístupné body, kde můžete získat podporu a ptát se na otázky. - -### Exekuční klienti {#execution-clients} - -- [Geth](https://discord.gg/FqDzupGyYf) -- [Nethermind](https://discord.gg/YJx3pm8z5C) -- [Besu](https://discord.gg/p8djYngzKN) -- [Erigon](https://github.com/ledgerwatch/erigon/issues) -- [Reth](https://github.com/paradigmxyz/reth/discussions) - -### Konsenzuální klienti {#consensus-clients} - -- [Prysm](https://discord.gg/prysmaticlabs) -- [Nimbus](https://discord.gg/nSmEH3qgFv) -- [Lighthouse](https://discord.gg/cyAszAh) -- [Teku](https://discord.gg/7hPv2T6) -- [Lodestar](https://discord.gg/aMxzVcr) -- [Grandine](https://discord.gg/H9XCdUSyZd) - -[Naučte se provozovat síťový uzel](/developers/docs/nodes-and-clients/run-a-node/). diff --git a/public/content/translations/cs/community/support/misconceptions/index.md b/public/content/translations/cs/community/support/misconceptions/index.md new file mode 100644 index 00000000000..0aa4c391f51 --- /dev/null +++ b/public/content/translations/cs/community/support/misconceptions/index.md @@ -0,0 +1,73 @@ +--- +title: "Běžné mylné představy o Ethereu" +description: "Vysvětlení nejčastějších nedorozumění o tom, jak Ethereum funguje." +lang: cs +--- + +# Běžné mylné představy o Ethereu {#misconceptions} + +## Je Ethereum společnost? {#not-a-company} + +Ethereum je open-source decentralizovaná technologie spravovaná tisíci přispěvateli z celého světa. Neexistuje žádná společnost s názvem "Ethereum", která by spravovala účty, držela prostředky nebo poskytovala zákaznickou podporu. + +[Nadace Ethereum](https://ethereum.foundation/) je nezisková organizace, která podporuje vývoj Etherea, ale nevlastní ani neovládá tuto síť. Žádná jediná entita ji neovládá. + +**[ethereum.org](/)** je komunitou spravovaný vzdělávací zdroj. Není to burza, peněženka ani finanční instituce. Nedrží žádné finanční prostředky uživatelů a nemůže přistupovat k žádným účtům. + + + Co je to Ethereum? + + +## Může někdo obnovit nebo zmrazit mé finanční prostředky? {#no-fund-access} + +Na rozdíl od banky na Ethereu neexistuje žádná centrální autorita, která by mohla zmrazit, zabavit nebo obnovit prostředky. Osoba, která drží soukromé klíče (nebo bezpečnostní frázi), má plnou a výhradní kontrolu nad peněženkou. + +To znamená: + +- **Nikdo nemůže obnovit prostředky**, které jste odeslali na špatnou adresu. +- **Nikdo nemůže zvrátit** transakci po jejím potvrzení. +- **Nikdo nemůže zmrazit** vaši peněženku ani blokovat vaše transakce. +- **Nikdo vám nemůže obnovit heslo**, pokud ztratíte svou bezpečnostní frázi. + +Proto je ochrana vaší bezpečnostní fráze klíčová. Je to jediný způsob, jak se dostat do vaší peněženky. Pokud ji ztratíte nebo vám bude odcizena, neexistuje žádná možnost obnovy. + + + Bezpečnost a předcházení podvodům v Ethereu + + +## Mohu stále těžit Ethereum? {#no-mining} + +Ethereum přešlo z [důkazu prací](/glossary/#pow) na [důkaz podílem](/glossary/#pos) během [Sloučení](/roadmap/merge/) v září 2022. Těžba na Ethereu již není možná. + +Síť je nyní zabezpečena validátory, kteří [uzamykají](/glossary/#staking) ETH. Zúčastnit se může kdokoli: + +- **Samostatné uzamčení:** Spusťte si vlastního validátora s 32 ETH – [dozvědět se více](/staking/solo/) +- **Uzamčení jako služba:** Delegujte provoz uzlu a ponechte si své klíče – [dozvědět se více](/staking/saas/) +- **Sdružené uzamčení:** Uzamkněte méně než 32 ETH tím, že se připojíte ke sdružení – [dozvědět se více](/staking/pools/) + + + Více o uzamčení + + +## Existuje tým podpory pro Ethereum? {#no-support-team} + +Hledat "oficiální podporu pro Ethereum" je podobné jako hledat "oficiální podporu pro internet". Ta samozřejmě neexistuje, ale v závislosti na vašem problému můžete vyhledat podporu u svého poskytovatele internetových služeb, výrobce hardwaru routeru nebo u jedné ze společností, které stojí za zařízením, aplikací nebo webovou stránkou, kterou používáte. + +S Ethereem je to podobné. Za Ethereem jako celkem nestojí žádná společnost, tým podpory ani helpdesk, ale v závislosti na problému můžete najít pomoc, když se obrátíte na svého _poskytovatele peněženky_, _službu pro uzamčení_, _burzu_, _finanční instituci_ nebo _tým, který spravuje aplikaci_, kterou používáte. + +Jelikož je Ethereum ve výchozím nastavení veřejně transparentní, mohou se vám hodit i [prohlížeče bloků](/developers/docs/data-and-analytics/block-explorers/), [analytické nástroje](/developers/tools/analytics/) a další [online zdroje pro vyšetřování](/community/support/scams/#analyze) k přímému prozkoumání problému. + +To znamená, že vás nikdy nikdo z Etherea ani z ethereum.org nebude: + +- Kontaktovat prostřednictvím přímé zprávy +- Žádat o vaši bezpečnostní frázi nebo soukromé klíče +- Žádat o zaslání ETH k ověření vaší peněženky +- Nabízet pomoc s obnovením prostředků za poplatek + +**Každý, kdo dělá cokoli z výše uvedeného, se vás snaží podvést.** + +Pokud potřebujete pomoc, skutečné komunity, které vám mohou pomoci, jsou uvedeny na [stránce podpory](/community/support/). Jedná se o otevřené komunity vedené dobrovolníky – nejedná se o oficiální kanály podpory. + + + Bezpečnost a předcházení podvodům v Ethereu + diff --git a/public/content/translations/cs/community/support/scams/index.md b/public/content/translations/cs/community/support/scams/index.md new file mode 100644 index 00000000000..ffdd6af6602 --- /dev/null +++ b/public/content/translations/cs/community/support/scams/index.md @@ -0,0 +1,159 @@ +--- +title: "Pomoc s podvody a jejich nahlášení" +description: "Co dělat, pokud jste se stali obětí podvodu, jak zabezpečit zbývající aktiva a kde podvod nahlásit." +lang: cs +--- + +# Někdo mě podvedl, nebo jsem přišel(a) o prostředky {#scam-help} + +Podvody s kryptoměnami se zaměřují na lidi všech úrovní zkušeností, včetně profesionálů v oblasti financí a technologií. Nejste v tom sami a to, že jste tady, je správný první krok. + + + + + + +**Nikdo nemůže zvrátit blockchainové transakce.** Pokud vás někdo kontaktuje s tvrzením, že vám za poplatek může obnovit vaše prostředky, jedná se téměř jistě o druhý podvod. Viz [podvody s obnovou](#recovery-scams) níže. + + + + +## Zabezpečte svá zbývající aktiva {#secure-assets} + +Pokud jste komunikovali s podvodníkem nebo máte podezření, že vaše peněženka byla kompromitována, okamžitě podnikněte následující kroky: + +1. **Přesuňte zbývající prostředky** do nové, bezpečné peněženky, ke které podvodník nemá přístup +2. **Zrušte schválení tokenů.** Podvodníci vás často přimějí schválit neomezené utrácení tokenů. Zrušení těchto oprávnění zabrání dalšímu odčerpávání prostředků z vaší peněženky +3. **Změňte hesla** na všech propojených účtech na burzách +4. **Povolte dvoufázové ověření (2FA)** na všech účtech souvisejících s kryptoměnami + +### Jak zrušit schválení tokenů {#revoke-approvals} + +Když komunikujete s dapp nebo chytrým kontraktem, možná jste mu udělili oprávnění utrácet vaše tokeny. Pokud vás podvodník přiměl schválit škodlivý kontrakt, může pokračovat v odčerpávání vašich tokenů i po původním podvodu. + +Použijte tyto nástroje ke kontrole a zrušení schválení: + +- [Revoke.cash](https://revoke.cash/): připojte svou peněženku, abyste viděli všechna aktivní schválení a zrušili je +- [Revokescout](https://revoke.blockscout.com/): zkontrolujte a zrušte schválení prostřednictvím Blockscout +- [Etherscan Token Approval Checker](https://etherscan.io/tokenapprovalchecker): zkontrolujte a zrušte schválení prostřednictvím Etherscanu + + + Podrobný průvodce: Jak zrušit přístup k tokenům + + +## Nahlaste podvodné adresy a webové stránky {#report} + +Nahlášení pomáhá varovat ostatní uživatele a může pomoci při vyšetřování orgánů činných v trestním řízení. Vše zdokumentujte: haše transakcí, adresy peněženek, snímky obrazovky a jakoukoli komunikaci s podvodníkem. + +### Nahlaste podvodnou adresu {#report-address} + +- [Chainabuse](https://www.chainabuse.com/): komunitní databáze pro hlášení podvodů. Odesílejte hlášení a vyhledávejte známé podvodné adresy +- [Etherscan report](https://info.etherscan.com/report-address/): označte adresu na nejpoužívanějším prohlížeči bloků Etherea +- [CryptoScamDB](https://cryptoscamdb.org/): open-source databáze sledující podvody s kryptoměnami + +### Nahlaste podvodný web nebo účet na sociálních sítích {#report-website} + +- [PhishTank](https://phishtank.org/): odešlete a ověřte phishingové adresy URL +- [Google Safe Browsing](https://safebrowsing.google.com/safebrowsing/report_phish/): nahlaste phishingové stránky společnosti Google, aby byly zablokovány v prohlížeči Chrome a dalších prohlížečích +- [Netcraft](https://report.netcraft.com/report/mistake): nahlaste škodlivé a podvodné webové stránky +- Nahlaste podvod přímo na platformě sociálních médií, kde k němu došlo (Twitter/X, Discord i Telegram mají funkce pro nahlašování) + +### Nahlaste to orgánům činným v trestním řízení {#report-law-enforcement} + +- **Spojené státy:** [FBI Internet Crime Complaint Center (IC3)](https://www.ic3.gov/) +- **Spojené království:** [Action Fraud](https://www.actionfraud.police.uk/) +- **Evropská unie:** [Europol](https://www.europol.europa.eu/report-a-crime) +- **Ostatní země:** podejte hlášení na místní policii. Podvody s kryptoměnami jsou ve většině jurisdikcí trestným činem + +## Analyzujte, co se stalo {#analyze} + +Pochopení toho, kam vaše prostředky šly, může pomoci s hlášeními a může podpořit snahy o obnovu, pokud prostředky skončí na centralizované burze. + +- [Blockscout](https://eth.blockscout.com/): open-source prohlížeč bloků pro vyhledání jakéhokoli haše transakce nebo adresy peněženky, abyste zjistili, kam byly prostředky odeslány +- [Etherscan](https://etherscan.io/): vyhledejte jakýkoli haš transakce nebo adresu peněženky, abyste viděli, kam byly prostředky odeslány +- [Vyhledávání na Chainabuse](https://www.chainabuse.com/): zkontrolujte, zda adresa již byla nahlášena jinými oběťmi +- [MetaSleuth](https://metasleuth.io/) od BlockSec: vizuální nástroj pro sledování transakcí, který mapuje toky prostředků + +**Pokud byly prostředky odeslány na centralizovanou burzu** (jako Coinbase, Binance, Kraken), okamžitě kontaktujte jejich tým podpory s podrobnostmi o transakci. Burzy mohou někdy zmrazit účty označené jako podvodné. + +## Krutá pravda {#hard-truth} + +Protože je Ethereum decentralizované, žádná centrální autorita nemůže zvrátit transakce ani obnovit ukradené prostředky. Jakmile je transakce potvrzena na blockchainu, je konečná. + +Nahlašování má stále smysl. Hlášení pomáhají orgánům činným v trestním řízení sledovat organizované podvodné skupiny a označování adres na Chainabuse a Etherscanu varuje budoucí potenciální oběti. + +## Typy podvodů, na které si dát pozor {#scam-types} + + + +Podvodníci vytvářejí falešné dárky slibující, že znásobí vaše ETH, nebo vám dají tokeny zdarma. Často se vydávají za známé osobnosti, jako je Vitalik Buterin. Pokud pošlete ETH na "dárkovou" adresu, nic nedostanete zpět. + +**Pamatujte:** Vitalik a další prominentní osobnosti vás nikdy nepožádají o zaslání ETH. + +[Více o běžných podvodech](/security/#common-scams) + + + + +Podvodníci se na Discordu, Telegramu a sociálních sítích vydávají za členy týmu Etherea, moderátory nebo agenty podpory. Mohou vám posílat přímé zprávy s nabídkou pomoci nebo tvrdit, že je problém s vaším účtem. + +**Pamatujte:** + +- Neexistuje žádný "tým podpory Etherea" +- Skuteční moderátoři vám nikdy nepošlou přímou zprávu jako první +- Nikdy s nikým a z žádného důvodu nesdílejte svou bezpečnostní frázi nebo soukromé klíče +- Nikdy neklikejte na odkazy zaslané v nevyžádaných zprávách + + + + +Podvody s obnovou se zaměřují konkrétně na lidi, kteří již o prostředky přišli. Podvodníci sledují na sociálních sítích lidi, kteří mluví o tom, že byli podvedeni, a pak se jim ozvou a vydávají se za "blockchainové vyšetřovatele" nebo "experty na obnovu kryptoměn". + +Slibují, že vystopují a obnoví vaše ukradené kryptoměny za poplatek předem. Poté, co zaplatíte, zmizí. + +**Žádná legitimní služba nemůže zvrátit blockchainové transakce.** Každý, kdo to slibuje, lže. Jedná se o jeden z nejčastějších následných podvodů. + + + + +Phishingové stránky vypadají identicky jako skutečné aplikace peněženek, burzy nebo platformy DeFi. Přimějí vás zadat vaši bezpečnostní frázi nebo připojit vaši peněženku a poté vám odčerpají prostředky. + +**Chraňte se:** + +- Před připojením peněženky si vždy ověřte adresu URL +- Uložte si do záložek oficiální stránky, které pravidelně používáte +- Nikdy nezadávejte svou bezpečnostní frázi na žádné webové stránce. Legitimní aplikace ji nikdy nevyžadují +- Použijte [PhishTank](https://phishtank.org/) ke kontrole podezřelých adres URL + + + Jak rozpoznat podvodné tokeny + + + + + Kompletní průvodce zabezpečením Etherea a prevencí podvodů + diff --git a/public/content/translations/cs/developers/docs/networking-layer/index.md b/public/content/translations/cs/developers/docs/networking-layer/index.md index ef5ac206c23..f72d749e8fe 100644 --- a/public/content/translations/cs/developers/docs/networking-layer/index.md +++ b/public/content/translations/cs/developers/docs/networking-layer/index.md @@ -146,7 +146,7 @@ Souhrn toku řízení je uveden níže, s relevantní síťovou vrstvou v závor Jakmile je blok potvrzen dostatečným počtem validátorů, je přidán na hlavu řetězce, ospravedlněn a nakonec finalizován. -![](cons_client_net_layer.png)\n![](exe_client_net_layer.png) +![Schéma síťové vrstvy klienta Ethereum consensus](cons_client_net_layer.png)\n![Schéma síťové vrstvy klienta pro provádění Etherea](exe_client_net_layer.png) Schéma síťové vrstvy pro konsensuální a exekuční klienty, z [ethresear.ch](https://ethresear.ch/t/eth1-eth2-client-relationship/7248) diff --git a/public/content/translations/cs/developers/docs/nodes-and-clients/node-architecture/index.md b/public/content/translations/cs/developers/docs/nodes-and-clients/node-architecture/index.md index 26199ed95d3..2e790d00727 100644 --- a/public/content/translations/cs/developers/docs/nodes-and-clients/node-architecture/index.md +++ b/public/content/translations/cs/developers/docs/nodes-and-clients/node-architecture/index.md @@ -10,7 +10,7 @@ Když Ethereum používalo [důkaz prací](/developers/docs/consensus-mechanisms Níže uvedený diagram znázorňuje vztah mezi dvěma klienty sítě Ethereum. Oba klienti se připojují ke svým vlastním sítím peer-to-peer (P2P). Jsou zapotřebí oddělené P2P sítě, protože exekuční klienti si přes svou P2P síť vyměňují transakce, což jim umožňuje spravovat jejich lokální transakční pool, zatímco konsensuální klienti si přes svou P2P síť vyměňují bloky, což umožňuje konsensus a růst řetězce. -![](node-architecture-text-background.png) +![Diagram architektury uzlu Ethereum zobrazující prováděcí a konsensuální vrstvy](node-architecture-text-background.png) _Pro exekučního klienta existuje několik možností, včetně Erigon, Nethermind a Besu_. diff --git a/public/content/translations/cs/developers/tutorials/ai-trading-agent/index.md b/public/content/translations/cs/developers/tutorials/ai-trading-agent/index.md new file mode 100644 index 00000000000..93cab455af5 --- /dev/null +++ b/public/content/translations/cs/developers/tutorials/ai-trading-agent/index.md @@ -0,0 +1,980 @@ +--- +title: "Vytvořte si vlastního AI obchodního agenta na Ethereu" +description: "V tomto tutoriálu se naučíte, jak vytvořit jednoduchého AI obchodního agenta. Tento agent čte informace z blockchainu, požádá LLM o doporučení na základě těchto informací, provádí obchod, který LLM doporučí, a pak čeká a opakuje." +author: Ori Pomerantz +tags: [ "AI", "obchodování", "agent", "python" ] +skill: intermediate +published: 2026-02-13 +lang: cs +sidebarDepth: 3 +--- + +V tomto tutoriálu se naučíte, jak sestavit jednoduchého AI obchodního agenta. Tento agent funguje pomocí těchto kroků: + +1. Přečtěte si aktuální a minulé ceny tokenu, stejně jako další potenciálně relevantní informace +2. Sestavte dotaz s těmito informacemi spolu s doplňujícími informacemi k vysvětlení, jak by to mohlo být relevantní +3. Odešlete dotaz a obdržíte zpět předpokládanou cenu +4. Obchodujte na základě doporučení +5. Počkejte a opakujte + +Tento agent demonstruje, jak číst informace, přeložit je do dotazu, který poskytne použitelnou odpověď, a použít tuto odpověď. Všechny tyto kroky jsou nutné pro agenta AI. Tento agent je implementován v Pythonu, protože je to nejběžnější jazyk používaný v AI. + +## Proč to dělat? {#why-do-this} + +Automatizovaní obchodní agenti umožňují vývojářům vybrat a provést obchodní strategii. [Agenti AI](/ai-agents) umožňují složitější a dynamičtější obchodní strategie, potenciálně s využitím informací a algoritmů, o jejichž použití vývojář ani neuvažoval. + +## Nástroje {#tools} + +Tento tutoriál používá [Python](https://www.python.org/), knihovnu [Web3](https://web3py.readthedocs.io/en/stable/) a [Uniswap v3](https://github.com/Uniswap/v3-periphery) pro nabídky a obchodování. + +### Proč Python? {#python} + +Nejrozšířenějším jazykem pro AI je [Python](https://www.python.org/), takže ho použijeme i tady. Nebojte se, pokud neznáte Python. Tento jazyk je velmi srozumitelný a já vám přesně vysvětlím, co dělá. + +[Knihovna Web3](https://web3py.readthedocs.io/en/stable/) je nejběžnější Python API pro Ethereum. Její použití je celkem snadné. + +### Obchodování na blockchainu {#trading-on-blockchain} + +Existuje [mnoho decentralizovaných burz (DEX)](/apps/categories/defi/), které vám umožní obchodovat s tokeny na Ethereu. Nicméně mívají podobné směnné kurzy kvůli [arbitráži](/developers/docs/smart-contracts/composability/#better-user-experience). + +[Uniswap](https://app.uniswap.org/) je široce používaná DEX, kterou můžeme použít jak pro nabídky (pro zobrazení relativních hodnot tokenů), tak pro obchody. + +### OpenAI {#openai} + +Pro velký jazykový model jsem se rozhodl začít s [OpenAI](https://openai.com/). Abyste mohli spustit aplikaci v tomto tutoriálu, budete muset zaplatit za přístup k API. Minimální platba 5 $ je více než dostačující. + +## Vývoj, krok za krokem {#step-by-step} + +Pro zjednodušení vývoje postupujeme po etapách. Každý krok je větev v GitHubu. + +### Začínáme {#getting-started} + +Zde jsou kroky, jak začít v systémech UNIX nebo Linux (včetně [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)) + +1. Pokud ho ještě nemáte, stáhněte a nainstalujte [Python](https://www.python.org/downloads/). + +2. Naklonujte repozitář na GitHubu. + + ```sh + git clone https://github.com/qbzzt/260215-ai-agent.git -b 01-getting-started + cd 260215-ai-agent + ``` + +3. Nainstalujte si [`uv`](https://docs.astral.sh/uv/getting-started/installation/). Příkaz na vašem systému se může lišit. + + ```sh + pipx install uv + ``` + +4. Stáhněte si knihovny. + + ```sh + uv sync + ``` + +5. Aktivujte virtuální prostředí. + + ```sh + source .venv/bin/activate + ``` + +6. Chcete-li ověřit, že Python a Web3 fungují správně, spusťte `python3` a zadejte do něj tento program. Můžete jej zadat na příkazový řádek `>>>`, není třeba vytvářet soubor. + + ```python + from web3 import Web3 + MAINNET_URL = "https://eth.drpc.org" + w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) + w3.eth.block_number + quit() + ``` + +### Čtení z blockchainu {#read-blockchain} + +Dalším krokem je čtení z blockchainu. K tomu se musíte přepnout na větev `02-read-quote` a poté pomocí `uv` spustit program. + +```sh +git checkout 02-read-quote +uv run agent.py +``` + +Měli byste obdržet seznam objektů `Quote`, každý s časovým razítkem, cenou a aktivem (v současnosti vždy `WETH/USDC`). + +Zde je vysvětlení řádek po řádku. + +```python +from web3 import Web3 +from web3.contract import Contract +from decimal import Decimal, ROUND_HALF_UP +from dataclasses import dataclass +from datetime import datetime, timezone +from pprint import pprint +import time +import functools +import sys +``` + +Importujte knihovny, které potřebujeme. Jsou vysvětleny níže, když jsou použity. + +```python +print = functools.partial(print, flush=True) +``` + +Nahrazuje pythonovský `print` verzí, která vždy okamžitě vyprázdní výstup. To je užitečné v dlouho běžícím skriptu, protože nechceme čekat na aktualizace stavu nebo na výstup pro ladění. + +```python +MAINNET_URL = "https://eth.drpc.org" +``` + +URL pro přístup na hlavní síť. Můžete si ji pořídit z [uzlu jako služby](/developers/docs/nodes-and-clients/nodes-as-a-service/) nebo použít jednu z těch, které jsou inzerovány na [Chainlistu](https://chainlist.org/chain/1). + +```python +BLOCK_TIME_SECONDS = 12 +MINUTE_BLOCKS = int(60 / BLOCK_TIME_SECONDS) +HOUR_BLOCKS = MINUTE_BLOCKS * 60 +DAY_BLOCKS = HOUR_BLOCKS * 24 +``` + +Blok na hlavní síti Etherea se obvykle objeví každých dvanáct sekund, takže toto jsou počty bloků, které bychom očekávali, že se objeví v daném časovém období. Upozorňujeme, že se nejedná o přesný údaj. Když je [navrhovatel bloku](/developers/docs/consensus-mechanisms/pos/block-proposal/) mimo provoz, tento blok je přeskočen a čas do dalšího bloku je 24 sekund. Kdybychom chtěli získat přesný blok pro časové razítko, použili bychom [binární vyhledávání](https://en.wikipedia.org/wiki/Binary_search). Pro naše účely je to však dostatečně blízko. Předpovídání budoucnosti není exaktní věda. + +```python +CYCLE_BLOCKS = DAY_BLOCKS +``` + +Velikost cyklu. Jednou za cyklus přezkoumáme nabídky a pokusíme se odhadnout hodnotu na konci dalšího cyklu. + +```python +# Adresa fondu, který čteme +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +``` + +Hodnoty nabídky jsou převzaty z fondu Uniswap 3 USDC/WETH na adrese [`0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`](https://eth.blockscout.com/address/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640?tab=read_write_contract). Tato adresa je již ve formě kontrolního součtu, ale je lepší použít [`Web3.to_checksum_address`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_checksum_address), aby byl kód znovu použitelný. + +```python +POOL_ABI = [ + { "name": "slot0", ... }, + { "name": "token0", ... }, + { "name": "token1", ... }, +] + +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... } +] +``` + +Toto jsou [ABI](https://docs.soliditylang.org/en/latest/abi-spec.html) pro dvě smlouvy, které potřebujeme kontaktovat. Aby byl kód stručný, zahrnuli jsme pouze funkce, které potřebujeme volat. + +```python +w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) +``` + +Inicializujte knihovnu [`Web3`](https://web3py.readthedocs.io/en/stable/quickstart.html#remote-providers) a připojte se k uzlu Ethereum. + +```python +@dataclass(frozen=True) +class ERC20Token: + address: str + symbol: str + decimals: int + contract: Contract +``` + +Toto je jeden ze způsobů, jak v Pythonu vytvořit datovou třídu. Datový typ [`Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) se používá pro připojení ke smlouvě. Všimněte si `(frozen=True)`. V Pythonu jsou [booleany](https://en.wikipedia.org/wiki/Boolean_data_type) definovány jako `True` nebo `False` s velkým písmenem. Tato datová třída je `frozen` (zmrazená), což znamená, že pole nelze upravovat. + +Všimněte si odsazení. Na rozdíl od [jazyků odvozených od C](https://en.wikipedia.org/wiki/List_of_C-family_programming_languages), Python používá k označení bloků odsazení. Interpret Pythonu ví, že následující definice není součástí této datové třídy, protože nezačíná na stejném odsazení jako pole datové třídy. + +```python +@dataclass(frozen=True) +class PoolInfo: + address: str + token0: ERC20Token + token1: ERC20Token + contract: Contract + asset: str + decimal_factor: Decimal = 1 +``` + +Typ [`Decimal`](https://docs.python.org/3/library/decimal.html) se používá pro přesnou práci s desetinnými zlomky. + +```python + def get_price(self, block: int) -> Decimal: +``` + +Takto se definuje funkce v Pythonu. Definice je odsazena, aby bylo vidět, že je stále součástí `PoolInfo`. + +Ve funkci, která je součástí datové třídy, je prvním parametrem vždy `self`, instance datové třídy, která zde volala. Zde je další parametr, číslo bloku. + +```python + assert block <= w3.eth.block_number, "Blok je v budoucnosti" +``` + +Kdybychom uměli číst budoucnost, nepotřebovali bychom AI pro obchodování. + +```python + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) +``` + +Syntaxe pro volání funkce na EVM z Web3 je tato: `.functions.().call()`. Parametry mohou být parametry funkce EVM (pokud nějaké jsou; zde nejsou) nebo [pojmenované parametry](https://en.wikipedia.org/wiki/Named_parameter) pro úpravu chování blockchainu. Zde používáme jeden, `block_identifier`, pro určení [čísla bloku](/developers/docs/apis/json-rpc/#default-block), ve kterém chceme pracovat. + +Výsledkem je [tato struktura ve formě pole](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol#L56-L72). První hodnota je funkcí směnného kurzu mezi dvěma tokeny. + +```python + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 +``` + +Pro snížení výpočtů na blockchainu Uniswap v3 neukládá skutečný směnný kurz, ale spíše jeho druhou odmocninu. Protože EVM nepodporuje matematiku s plovoucí desetinnou čárkou ani zlomky, místo skutečné hodnoty je odpověď price296 + +```python + # (token1 za token0) + return 1/(raw_price * self.decimal_factor) +``` + +Hrubá cena, kterou dostaneme, je počet `token0`, které získáme za každý `token1`. V našem fondu je `token0` USDC (stabilní kryptoměna se stejnou hodnotou jako americký dolar) a `token1` je [WETH](https://opensea.io/learn/blockchain/what-is-weth). Hodnota, kterou skutečně chceme, je počet dolarů za WETH, ne inverzní. + +Desetinný faktor je poměr mezi [desetinnými faktory](https://docs.openzeppelin.com/contracts/4.x/erc20#a-note-on-decimals) pro oba tokeny. + +```python +@dataclass(frozen=True) +class Quote: + timestamp: str + price: Decimal + asset: str +``` + +Tato datová třída představuje nabídku: cenu konkrétního aktiva v daném časovém okamžiku. V tomto okamžiku je pole `asset` irelevantní, protože používáme jeden fond, a proto máme jedno aktivum. Později však přidáme další aktiva. + +```python +def read_token(address: str) -> ERC20Token: + token = w3.eth.contract(address=address, abi=ERC20_ABI) + symbol = token.functions.symbol().call() + decimals = token.functions.decimals().call() + + return ERC20Token( + address=address, + symbol=symbol, + decimals=decimals, + contract=token + ) +``` + +Tato funkce přebírá adresu a vrací informace o tokenové smlouvě na této adrese. Pro vytvoření nové smlouvy [Web3 `Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) poskytneme adresu a ABI do `w3.eth.contract`. + +```python +def read_pool(address: str) -> PoolInfo: + pool_contract = w3.eth.contract(address=address, abi=POOL_ABI) + token0Address = pool_contract.functions.token0().call() + token1Address = pool_contract.functions.token1().call() + token0 = read_token(token0Address) + token1 = read_token(token1Address) + + return PoolInfo( + address=address, + asset=f"{token1.symbol}/{token0.symbol}", + token0=token0, + token1=token1, + contract=pool_contract, + decimal_factor=Decimal(10) ** Decimal(token0.decimals - token1.decimals) + ) +``` + +Tato funkce vrací vše, co potřebujeme o [konkrétním fondu](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol). Syntaxe `f""` je [formátovaný řetězec](https://docs.python.org/3/reference/lexical_analysis.html#f-strings). + +```python +def get_quote(pool: PoolInfo, block_number: int = None) -> Quote: +``` + +Získání objektu `Quote`. Výchozí hodnota pro `block_number` je `None` (žádná hodnota). + +```python + if block_number is None: + block_number = w3.eth.block_number +``` + +Pokud nebylo zadáno číslo bloku, použije se `w3.eth.block_number`, což je poslední číslo bloku. Toto je syntaxe pro [příkaz `if`](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement). + +Mohlo by se zdát, že by bylo lepší nastavit výchozí hodnotu na `w3.eth.block_number`, ale to nefunguje dobře, protože by to bylo číslo bloku v době definování funkce. V dlouhodobě běžícím agentovi by to byl problém. + +```python + block = w3.eth.get_block(block_number) + price = pool.get_price(block_number) + return Quote( + timestamp=datetime.fromtimestamp(block.timestamp, timezone.utc).isoformat(), + price=price.quantize(Decimal("0.01")), + asset=pool.asset + ) +``` + +Použijte [knihovnu `datetime`](https://docs.python.org/3/library/datetime.html) k formátování do formátu čitelného pro lidi a velké jazykové modely (LLM). Použijte [`Decimal.quantize`](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) k zaokrouhlení hodnoty na dvě desetinná místa. + +```python +def get_quotes(pool: PoolInfo, start_block: int, end_block: int, step: int) -> list[Quote]: +``` + +V Pythonu se definuje [seznam](https://docs.python.org/3/library/stdtypes.html#typesseq-list), který může obsahovat pouze určitý typ, pomocí `list[]`. + +```python + quotes = [] + for block in range(start_block, end_block + 1, step): +``` + +V Pythonu [`for` cyklus](https://docs.python.org/3/tutorial/controlflow.html#for-statements) obvykle prochází seznam. Seznam čísel bloků, ve kterých se mají hledat nabídky, pochází z [`range`](https://docs.python.org/3/library/stdtypes.html#range). + +```python + quote = get_quote(pool, block) + quotes.append(quote) + return quotes +``` + +Pro každé číslo bloku získá objekt `Quote` a přidá jej do seznamu `quotes`. Poté tento seznam vrátí. + +```python +pool = read_pool(WETHUSDC_ADDRESS) +quotes = get_quotes( + pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) + +pprint(quotes) +``` + +Toto je hlavní kód skriptu. Přečte informace o fondu, získá dvanáct nabídek a [`pprint`](https://docs.python.org/3/library/pprint.html#pprint.pprint) je vytiskne. + +### Vytvoření výzvy {#prompt} + +Dále musíme tento seznam nabídek převést na výzvu pro LLM a získat očekávanou budoucí hodnotu. + +```sh +git checkout 03-create-prompt +uv run agent.py +``` + +Výstupem nyní bude výzva pro LLM, podobná této: + +``` +Vzhledem k těmto nabídkám: +Aktivum: WETH/USDC + 2026-01-20T16:34 3016.21 + . + . + . + 2026-02-01T17:49 2299.10 + +Aktivum: WBTC/WETH + 2026-01-20T16:34 29.84 + . + . + . + 2026-02-01T17:50 33.46 + + +Jakou hodnotu byste očekávali pro WETH/USDC v čase 2026-02-02T17:56? + +Poskytněte odpověď jako jediné číslo zaokrouhlené na dvě desetinná místa, +bez jakéhokoli dalšího textu. +``` + +Všimněte si, že zde jsou nabídky pro dvě aktiva, `WETH/USDC` a `WBTC/WETH`. Přidání nabídek z jiného aktiva může zlepšit přesnost předpovědi. + +#### Jak vypadá výzva {#prompt-explanation} + +Tato výzva obsahuje tři sekce, které jsou v LLM výzvách poměrně běžné. + +1. Informace. LLM mají spoustu informací ze svého trénování, ale obvykle nemají nejnovější. To je důvod, proč zde musíme získat nejnovější nabídky. Přidávání informací do výzvy se nazývá [retrieval augmented generation (RAG)](https://en.wikipedia.org/wiki/Retrieval-augmented_generation). + +2. Skutečná otázka. To je to, co chceme vědět. + +3. Pokyny pro formátování výstupu. Normálně nám LLM dá odhad s vysvětlením, jak k němu dospěl. To je lepší pro lidi, ale počítačový program potřebuje pouze výsledek. + +#### Vysvětlení kódu {#prompt-code} + +Zde je nový kód. + +```python +from datetime import datetime, timezone, timedelta +``` + +Musíme poskytnout LLM čas, pro který chceme odhad. Pro získání času „n minut/hodin/dní“ v budoucnu používáme [třídu `timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta). + +```python +# Adresy fondů, které čteme +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +WETHWBTC_ADDRESS = Web3.to_checksum_address("0xCBCdF9626bC03E24f779434178A73a0B4bad62eD") +``` + +Máme dva fondy, které musíme přečíst. + +```python +@dataclass(frozen=True) +class PoolInfo: + . + . + . + reverse: bool = False + + def get_price(self, block: int) -> Decimal: + assert block <= w3.eth.block_number, "Blok je v budoucnosti" + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 # (token1 za token0) + if self.reverse: + return 1/(raw_price * self.decimal_factor) + else: + return raw_price * self.decimal_factor +``` + +Ve fondu WETH/USDC chceme vědět, kolik `token0` (USDC) potřebujeme k nákupu jednoho `token1` (WETH). Ve fondu WETH/WBTC chceme vědět, kolik `token1` (WETH) potřebujeme k nákupu jednoho `token0` (WBTC, což je wrapped Bitcoin). Musíme sledovat, zda je třeba poměr fondu obrátit. + +```python +def read_pool(address: str, reverse: bool = False) -> PoolInfo: + . + . + . + + return PoolInfo( + . + . + . + + asset= f"{token1.symbol}/{token0.symbol}" if reverse else f"{token0.symbol}/{token1.symbol}", + reverse=reverse + ) +``` + +Abychom věděli, zda je třeba fond obrátit, musíme to získat jako vstup do `read_pool`. Také je třeba správně nastavit symbol aktiva. + +Syntaxe ` if else ` je pythonovský ekvivalent [ternárního podmíněného operátoru](https://en.wikipedia.org/wiki/Ternary_conditional_operator), který by v jazyce odvozeném od C byl ` ? : `. + +```python +def format_quotes(quotes: list[Quote]) -> str: + result = f"Asset: {quotes[0].asset}\n" + for quote in quotes: + result += f"\t{quote.timestamp[0:16]} {quote.price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)}\n" + return result +``` + +Tato funkce sestaví řetězec, který formátuje seznam objektů `Quote`, za předpokladu, že se všechny vztahují ke stejnému aktivu. + +```python +def make_prompt(quotes: list[list[Quote]], expected_time: str, asset: str) -> str: + return f""" +``` + +V Pythonu se [víceřádkové řetězcové literály](https://www.w3schools.com/python/gloss_python_multi_line_strings.asp) zapisují jako `"""` .... `"""`. + +```python +Vzhledem k těmto nabídkám: +{ + functools.reduce(lambda acc, q: acc + '\n' + q, + map(lambda q: format_quotes(q), quotes)) +} +``` + +Zde používáme vzor [MapReduce](https://en.wikipedia.org/wiki/MapReduce) k vygenerování řetězce pro každý seznam nabídek pomocí `format_quotes`, a pak je zredukujeme do jediného řetězce pro použití ve výzvě. + +```python +Jakou hodnotu byste očekávali pro {asset} v čase {expected_time}? + +Poskytněte odpověď jako jediné číslo zaokrouhlené na dvě desetinná místa, +bez jakéhokoli dalšího textu. + """ +``` + +Zbytek výzvy je podle očekávání. + +```python +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +Přezkoumejte oba fondy a získejte nabídky z obou. + +```python +future_time = (datetime.now(timezone.utc) + timedelta(days=1)).isoformat()[0:16] + +print(make_prompt(wethusdc_quotes + wethwbtc_quotes, future_time, wethusdc_pool.asset)) +``` + +Určete budoucí časový bod, pro který chcete odhad, a vytvořte výzvu. + +### Propojení s LLM {#interface-llm} + +Dále vyzveme skutečný LLM a získáme očekávanou budoucí hodnotu. Tento program jsem napsal pomocí OpenAI, takže pokud chcete použít jiného poskytovatele, budete ho muset upravit. + +1. Získejte [účet OpenAI](https://auth.openai.com/create-account) + +2. [Vložte peníze na účet](https://platform.openai.com/settings/organization/billing/overview) — minimální částka v době psaní je 5 $ + +3. [Vytvořte API klíč](https://platform.openai.com/settings/organization/api-keys) + +4. V příkazovém řádku exportujte API klíč, aby ho váš program mohl použít + + ```sh + export OPENAI_API_KEY=sk- + ``` + +5. Checkout a spuštění agenta + + ```sh + git checkout 04-interface-llm + uv run agent.py + ``` + +Zde je nový kód. + +```python +from openai import OpenAI + +open_ai = OpenAI() # Klient čte proměnnou prostředí OPENAI_API_KEY +``` + +Import a instancování API OpenAI. + +```python +response = open_ai.chat.completions.create( + model="gpt-4-turbo", + messages=[ + {"role": "user", "content": prompt} + ], + temperature=0.0, + max_tokens=16, +) +``` + +Zavolejte API OpenAI (`open_ai.chat.completions.create`) pro vytvoření odpovědi. + +```python +expected_price = Decimal(response.choices[0].message.content.strip()) +current_price = wethusdc_quotes[-1].price + +print ("Aktuální cena:", wethusdc_quotes[-1].price) +print(f"V {future_time} je očekávaná cena: {expected_price} USD") + +if (expected_price > current_price): + print(f"Nákup, očekávám, že cena vzroste o {expected_price - current_price} USD") +else: + print(f"Prodej, očekávám, že cena klesne o {current_price - expected_price} USD") +``` + +Vypište cenu a poskytněte doporučení na nákup nebo prodej. + +#### Testování předpovědí {#testing-the-predictions} + +Nyní, když můžeme generovat předpovědi, můžeme také použít historická data k posouzení, zda produkujeme užitečné předpovědi. + +```sh +uv run test-predictor.py +``` + +Očekávaný výsledek je podobný: + +``` +Předpověď pro 2026-01-05T19:50: předpovězeno 3138,93 USD, reálná 3218,92 USD, chyba 79,99 USD +Předpověď pro 2026-01-06T19:56: předpovězeno 3243,39 USD, reálná 3221,08 USD, chyba 22,31 USD +Předpověď pro 2026-01-07T20:02: předpovězeno 3223,24 USD, reálná 3146,89 USD, chyba 76,35 USD +Předpověď pro 2026-01-08T20:11: předpovězeno 3150,47 USD, reálná 3092,04 USD, chyba 58,43 USD +. +. +. +Předpověď pro 2026-01-31T22:33: předpovězeno 2637,73 USD, reálná 2417,77 USD, chyba 219,96 USD +Předpověď pro 2026-02-01T22:41: předpovězeno 2381,70 USD, reálná 2318,84 USD, chyba 62,86 USD +Předpověď pro 2026-02-02T22:49: předpovězeno 2234,91 USD, reálná 2349,28 USD, chyba 114,37 USD +Průměrná chyba předpovědi u 29 předpovědí: 83,87103448275862068965517241 USD +Průměrná změna na doporučení: 4,787931034482758620689655172 USD +Standardní odchylka změn: 104,42 USD +Ziskové dny: 51,72% +Ztrátové dny: 48,28% +``` + +Většina testeru je identická s agentem, ale zde jsou části, které jsou nové nebo upravené. + +```python +CYCLES_FOR_TEST = 40 # Pro zpětné testování, kolik cyklů testujeme + +# Získání velkého množství nabídek +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +Díváme se na `CYCLES_FOR_TEST` (zde uvedeno jako 40) dní zpět. + +```python +# Vytvoření předpovědí a jejich kontrola vůči skutečné historii + +total_error = Decimal(0) +changes = [] +``` + +Zajímají nás dva typy chyb. První, `total_error`, je jednoduše součet chyb, které prediktor udělal. + +Pro pochopení druhé, `changes`, si musíme připomenout účel agenta. Není to předpovídání poměru WETH/USDC (cena ETH). Je to vydávání doporučení na prodej a nákup. Pokud je cena aktuálně 2000 $ a předpovídá 2010 $ zítra, nevadí nám, pokud bude skutečný výsledek 2020 $ a vyděláme více peněz. Ale _vadí_ nám, když předpověděl 2010 $, na základě tohoto doporučení koupil ETH a cena klesla na 1990 $. + +```python +for index in range(0,len(wethusdc_quotes)-CYCLES_BACK): +``` + +Můžeme se podívat pouze na případy, kdy je k dispozici kompletní historie (hodnoty použité pro predikci a reálná hodnota pro srovnání). To znamená, že nejnovější případ musí být ten, který začal před `CYCLES_BACK`. + +```python + wethusdc_slice = wethusdc_quotes[index:index+CYCLES_BACK] + wethwbtc_slice = wethwbtc_quotes[index:index+CYCLES_BACK] +``` + +Použijte [řezy](https://www.w3schools.com/python/ref_func_slice.asp) k získání stejného počtu vzorků, jaké používá agent. Kód mezi tímto a dalším segmentem je stejný kód pro získání predikce, který máme v agentu. + +```python + predicted_price = Decimal(response.choices[0].message.content.strip()) + real_price = wethusdc_quotes[index+CYCLES_BACK].price + prediction_time_price = wethusdc_quotes[index+CYCLES_BACK-1].price +``` + +Získejte předpokládanou cenu, skutečnou cenu a cenu v době předpovědi. Cenu v době předpovědi potřebujeme k určení, zda bylo doporučeno nakoupit nebo prodat. + +```python + error = abs(predicted_price - real_price) + total_error += error + print (f"Předpověď pro {prediction_time}: předpovězeno {predicted_price} USD, skutečná {real_price} USD, chyba {error} USD") +``` + +Zjistěte chybu a přičtěte ji k celkové. + +```python + recomended_action = 'buy' if predicted_price > prediction_time_price else 'sell' + price_increase = real_price - prediction_time_price + changes.append(price_increase if recomended_action == 'buy' else -price_increase) +``` + +Pro `changes` chceme peněžní dopad nákupu nebo prodeje jednoho ETH. Nejprve tedy musíme určit doporučení, poté posoudit, jak se skutečná cena změnila, a zda doporučení vydělalo peníze (pozitivní změna) nebo stálo peníze (negativní změna). + +```python +print (f"Průměrná chyba předpovědi pro {len(wethusdc_quotes)-CYCLES_BACK} předpovědí: {total_error / Decimal(len(wethusdc_quotes)-CYCLES_BACK)} USD") + +length_changes = Decimal(len(changes)) +mean_change = sum(changes, Decimal(0)) / length_changes +print (f"Průměrná změna na doporučení: {mean_change} USD") +var = sum((x - mean_change) ** 2 for x in changes) / length_changes +print (f"Standardní odchylka změn: {var.sqrt().quantize(Decimal("0.01"))} USD") +``` + +Vypište výsledky. + +```python +print (f"Ziskové dny: {len(list(filter(lambda x: x > 0, changes)))/length_changes:.2%}") +print (f"Ztrátové dny: {len(list(filter(lambda x: x < 0, changes)))/length_changes:.2%}") +``` + +Použijte [`filter`](https://www.w3schools.com/python/ref_func_filter.asp) k počítání počtu ziskových a ztrátových dnů. Výsledkem je objekt filtru, který je třeba převést na seznam, abychom získali jeho délku. + +### Odesílání transakcí {#submit-txn} + +Nyní musíme skutečně odesílat transakce. Nechci však v tomto okamžiku utrácet skutečné peníze, než se systém osvědčí. Místo toho vytvoříme lokální větev hlavní sítě a „obchodovat“ budeme v této síti. + +Zde jsou kroky k vytvoření lokální větve a povolení obchodování. + +1. Nainstalujte si [Foundry](https://getfoundry.sh/introduction/installation) + +2. Spusťte [`anvil`](https://getfoundry.sh/anvil/overview) + + ```sh + anvil --fork-url https://eth.drpc.org --block-time 12 + ``` + + `anvil` naslouchá na výchozí URL pro Foundry, http://localhost:8545, takže nemusíme specifikovat URL pro příkaz [`cast`](https://getfoundry.sh/cast/overview), který používáme k manipulaci s blockchainem. + +3. Při běhu v `anvil` je k dispozici deset testovacích účtů, které mají ETH — nastavte proměnné prostředí pro první z nich + + ```sh + PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ADDRESS=`cast wallet address $PRIVATE_KEY` + ``` + +4. Toto jsou smlouvy, které musíme použít. [`SwapRouter`](https://github.com/Uniswap/v3-periphery/blob/main/contracts/SwapRouter.sol) je smlouva Uniswap v3, kterou používáme k samotnému obchodování. Mohli bychom obchodovat přímo přes fond, ale toto je mnohem jednodušší. + + Spodní dvě proměnné jsou cesty Uniswap v3 potřebné pro směnu mezi WETH a USDC. + + ```sh + WETH_ADDRESS=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + USDC_ADDRESS=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + POOL_ADDRESS=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 + SWAP_ROUTER=0xE592427A0AEce92De3Edee1F18E0157C05861564 + WETH_TO_USDC=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + USDC_TO_WETH=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + ``` + +5. Každý z testovacích účtů má 10 000 ETH. Použijte smlouvu WETH k zabalení 1000 ETH a získejte 1000 WETH pro obchodování. + + ```sh + cast send $WETH_ADDRESS "deposit()" --value 1000ether --private-key $PRIVATE_KEY + ``` + +6. Použijte `SwapRouter` k obchodování 500 WETH za USDC. + + ```sh + cast send $WETH_ADDRESS "approve(address,uint256)" $SWAP_ROUTER 500ether --private-key $PRIVATE_KEY + MAXINT=`cast max-int uint256` + cast send $SWAP_ROUTER \ + "exactInput((bytes,address,uint256,uint256,uint256))" \ + "($WETH_TO_USDC,$ADDRESS,$MAXINT,500ether,1000000)" \ + --private-key $PRIVATE_KEY + ``` + + Volání `approve` vytvoří příspěvek, který umožní `SwapRouter` utratit některé z našich tokenů. Smlouvy nemohou sledovat události, takže pokud bychom převedli tokeny přímo na smlouvu `SwapRouter`, nevěděla by, že byla zaplacena. Místo toho povolíme smlouvě `SwapRouter` utratit určitou částku a poté to `SwapRouter` udělá. To se provádí pomocí funkce volané `SwapRouter`, takže ví, zda byla úspěšná. + +7. Ověřte si, že máte dostatek obou tokenů. + + ```sh + cast call $WETH_ADDRESS "balanceOf(address)" $ADDRESS | cast from-wei + echo `cast call $USDC_ADDRESS "balanceOf(address)" $ADDRESS | cast to-dec`/10^6 | bc + ``` + +Nyní, když máme WETH a USDC, můžeme skutečně spustit agenta. + +```sh +git checkout 05-trade +uv run agent.py +``` + +Výstup bude vypadat podobně jako: + +``` +(ai-trading-agent) qbzzt@Ori-Cloudnomics:~/260215-ai-agent$ uv run agent.py +Aktuální cena: 1843.16 +V 2026-02-06T23:07, očekávaná cena: 1724.41 USD +Stavy účtů před obchodem: +USDC Zůstatek: 927301.578272 +WETH Zůstatek: 500 +Prodej, očekávám, že cena klesne o 118.75 USD +Schvalovací transakce odeslána: 74e367ddbb407c1aaf567d87aa5863049991b1d2aa092b6b85195d925e2bd41f +Schvalovací transakce vytěžena. +Prodejní transakce odeslána: fad1bcf938585c9e90364b26ac7a80eea9efd34c37e5db81e58d7655bcae28bf +Prodejní transakce vytěžena. +Stavy účtů po obchodě: +USDC Zůstatek: 929143.797116 +WETH Zůstatek: 499 +``` + +Pro skutečné použití potřebujete několik drobných změn. + +- Na řádku 14 změňte `MAINNET_URL` na skutečný přístupový bod, například `https://eth.drpc.org` +- Na řádku 28 změňte `PRIVATE_KEY` na váš vlastní privátní klíč +- Pokud nejste velmi bohatí a nemůžete si dovolit kupovat nebo prodávat 1 ETH každý den pro neprověřeného agenta, možná budete chtít změnit řádek 29 a snížit `WETH_TRADE_AMOUNT` + +#### Vysvětlení kódu {#trading-code} + +Zde je nový kód. + +```python +SWAP_ROUTER_ADDRESS=Web3.to_checksum_address("0xE592427A0AEce92De3Edee1F18E0157C05861564") +WETH_TO_USDC=bytes.fromhex("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") +USDC_TO_WETH=bytes.fromhex("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +``` + +Stejné proměnné, které jsme použili v kroku 4. + +```python +WETH_TRADE_AMOUNT=1 +``` + +Částka k obchodování. + +```python +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... }, + { "name": "balanceOf", ...}, + { "name": "approve", ...} +] +``` + +K samotnému obchodování potřebujeme funkci `approve`. Chceme také zobrazit zůstatky před a po, takže potřebujeme také `balanceOf`. + +```python +SWAP_ROUTER_ABI = [ + { "name": "exactInput", ...}, +] +``` + +V ABI `SwapRouter` potřebujeme pouze `exactInput`. Existuje příbuzná funkce `exactOutput`, kterou bychom mohli použít k nákupu přesně jednoho WETH, ale pro jednoduchost používáme `exactInput` v obou případech. + +```python +account = w3.eth.account.from_key(PRIVATE_KEY) +swap_router = w3.eth.contract( + address=SWAP_ROUTER_ADDRESS, + abi=SWAP_ROUTER_ABI +) +``` + +Definice Web3 pro [`účet`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html) a smlouvu `SwapRouter`. + +```python +def txn_params() -> dict: + return { + "from": account.address, + "value": 0, + "gas": 300000, + "nonce": w3.eth.get_transaction_count(account.address), + } +``` + +Parametry transakce. Potřebujeme zde funkci, protože [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) se musí pokaždé měnit. + +```python +def approve_token(contract: Contract, amount: int): +``` + +Schvalte povolenku tokenu pro `SwapRouter`. + +```python + txn = contract.functions.approve(SWAP_ROUTER_ADDRESS, amount).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) +``` + +Takto posíláme transakci v Web3. Nejprve použijeme [objekt `Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) k vytvoření transakce. Poté použijeme [`web3.eth.account.sign_transaction`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-contract-transaction) k podepsání transakce pomocí `PRIVATE_KEY`. Nakonec použijeme [`w3.eth.send_raw_transaction`](https://web3py.readthedocs.io/en/stable/transactions.html#chapter-2-w3-eth-send-raw-transaction) k odeslání transakce. + +```python + print(f"Schvalovací transakce odeslána: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Schvalovací transakce vytěžena.") +``` + +[`w3.eth.wait_for_transaction_receipt`](https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.wait_for_transaction_receipt) čeká, dokud transakce není vytěžena. V případě potřeby vrátí potvrzení. + +```python +SELL_PARAMS = { + "path": WETH_TO_USDC, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": WETH_TRADE_AMOUNT * 10 ** wethusdc_pool.token1.decimals, + "amountOutMinimum": 0, +} +``` + +Toto jsou parametry pro prodej WETH. + +```python +def make_buy_params(quote: Quote) -> dict: + return { + "path": USDC_TO_WETH, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": int(quote.price*WETH_TRADE_AMOUNT) * 10**wethusdc_pool.token0.decimals, + "amountOutMinimum": 0, + } +``` + +Na rozdíl od `SELL_PARAMS`, parametry pro nákup se mohou měnit. Vstupní částka je cena 1 WETH, jak je uvedeno v `quote`. + +```python +def buy(quote: Quote): + buy_params = make_buy_params(quote) + approve_token(wethusdc_pool.token0.contract, buy_params["amountIn"]) + txn = swap_router.functions.exactInput(buy_params).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Nákupní transakce odeslána: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Nákupní transakce vytěžena.") + + +def sell(): + approve_token(wethusdc_pool.token1.contract, + WETH_TRADE_AMOUNT * 10**wethusdc_pool.token1.decimals) + txn = swap_router.functions.exactInput(SELL_PARAMS).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Prodejní transakce odeslána: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Prodejní transakce vytěžena.") +``` + +Funkce `buy()` a `sell()` jsou téměř identické. Nejprve schválíme dostatečnou povolenku pro `SwapRouter` a poté ho zavoláme se správnou cestou a částkou. + +```python +def balances(): + token0_balance = wethusdc_pool.token0.contract.functions.balanceOf(account.address).call() + token1_balance = wethusdc_pool.token1.contract.functions.balanceOf(account.address).call() + + print(f"{wethusdc_pool.token0.symbol} Zůstatek: {Decimal(token0_balance) / Decimal(10 ** wethusdc_pool.token0.decimals)}") + print(f"{wethusdc_pool.token1.symbol} Zůstatek: {Decimal(token1_balance) / Decimal(10 ** wethusdc_pool.token1.decimals)}") +``` + +Hlásit zůstatky uživatelů v obou měnách. + +```python +print("Stav účtu před obchodem:") +balances() + +if (expected_price > current_price): + print(f"Nákup, očekávám, že cena vzroste o {expected_price - current_price} USD") + buy(wethusdc_quotes[-1]) +else: + print(f"Prodej, očekávám, že cena klesne o {current_price - expected_price} USD") + sell() + +print("Stav účtu po obchodě:") +balances() +``` + +Tento agent v současné době funguje pouze jednou. Můžete ho však upravit tak, aby pracoval nepřetržitě, buď spuštěním z [`crontab`](https://man7.org/linux/man-pages/man1/crontab.1.html) nebo zabalením řádků 368–400 do smyčky a použitím [`time.sleep`](https://docs.python.org/3/library/time.html#time.sleep) k čekání, dokud nenastane čas na další cyklus. + +## Možná vylepšení {#improvements} + +Toto není plná produkční verze; je to pouze příklad pro naučení základů. Zde jsou některé nápady na vylepšení. + +### Chytřejší obchodování {#smart-trading} + +Existují dvě důležité skutečnosti, které agent ignoruje při rozhodování, co dělat. + +- _Velikost očekávané změny_. Agent prodává pevnou částku `WETH`, pokud se očekává pokles ceny, bez ohledu na velikost poklesu. + Dalo by se namítnout, že by bylo lepší ignorovat drobné změny a prodávat na základě toho, jak moc očekáváme pokles ceny. +- _Současné portfolio_. Pokud je 10 % vašeho portfolia v WETH a myslíte si, že cena poroste, pravděpodobně má smysl koupit více. Pokud je ale 90 % vašeho portfolia v WETH, můžete být dostatečně exponovaní a není třeba kupovat více. Opačně to platí, pokud očekáváte pokles ceny. + +### Co když chcete udržet svou obchodní strategii v tajnosti? {#secret} + +Prodejci AI mohou vidět dotazy, které posíláte jejich LLM, což by mohlo odhalit geniální obchodní systém, který jste vyvinuli se svým agentem. Obchodní systém, který používá příliš mnoho lidí, je bezcenný, protože příliš mnoho lidí se snaží nakupovat, když chcete nakupovat (a cena stoupá) a snaží se prodávat, když chcete prodávat (a cena klesá). + +Tomuto problému se můžete vyhnout spuštěním LLM lokálně, například pomocí [LM-Studio](https://lmstudio.ai/). + +### Od AI bota k AI agentovi {#bot-to-agent} + +Můžete dobře argumentovat, že se jedná o [AI bota, nikoli AI agenta](/ai-agents/#ai-agents-vs-ai-bots). Implementuje relativně jednoduchou strategii, která se opírá o předdefinované informace. Můžeme umožnit sebezdokonalování, například poskytnutím seznamu fondů Uniswap v3 a jejich nejnovějších hodnot a zeptat se, která kombinace má nejlepší prediktivní hodnotu. + +### Ochrana proti prokluzu {#slippage-protection} + +V současné době neexistuje žádná [ochrana proti prokluzu](https://uniswapv3book.com/milestone_3/slippage-protection.html). Pokud je aktuální nabídka 2000 $ a očekávaná cena je 2100 $, agent nakoupí. Pokud však předtím, než agent nakoupí, cena vzroste na 2200 $, už nemá smysl nakupovat. + +Pro implementaci ochrany proti prokluzu zadejte hodnotu `amountOutMinimum` na řádcích 325 a 334 v [`agent.py`](https://github.com/qbzzt/260215-ai-agent/blob/05-trade/agent.py#L325). + +## Závěr {#conclusion} + +Doufejme, že nyní víte dost na to, abyste mohli začít s agenty AI. Toto není komplexní přehled tématu; jsou o tom celé knihy, ale to stačí na to, abyste mohli začít. Hodně štěstí! + +[Více z mé práce najdete zde](https://cryptodocguy.pro/). diff --git a/public/content/translations/cs/developers/tutorials/hello-world-smart-contract-fullstack/index.md b/public/content/translations/cs/developers/tutorials/hello-world-smart-contract-fullstack/index.md index 0f37ba4dc20..19b519d6458 100644 --- a/public/content/translations/cs/developers/tutorials/hello-world-smart-contract-fullstack/index.md +++ b/public/content/translations/cs/developers/tutorials/hello-world-smart-contract-fullstack/index.md @@ -240,7 +240,7 @@ Nenazývejte jej `process.env` ani `.env-custom` ani nijak jinak. - Postupujte podle [těchto pokynů](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key) a exportujte svůj privátní klíč - Níže naleznete postup, jak získat URL pro HTTP API Alchemy -![](./get-alchemy-api-key.gif) +![Animovaný návod, jak získat klíč Alchemy API](./get-alchemy-api-key.gif) Váš soubor `.env` by měl vypadat takto: @@ -359,17 +359,17 @@ Kontrakt nasazen na adresu: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570 Pokud přejdeme na [Goerli Etherscan](https://goerli.etherscan.io) a vyhledáme adresu našeho kontraktu, měli bychom vidět, že byl úspěšně nasazen. Transakce bude vypadat nějak takto: -![](./etherscan-contract.png) +![Snímek obrazovky nasazené chytré smlouvy na Etherscan](./etherscan-contract.png) Adresa `From` by se měla shodovat s adresou vašeho účtu MetaMask a v adrese `To` bude uvedeno **Vytvoření kontraktu**. Pokud klikneme na transakci, uvidíme v poli `To` adresu našeho kontraktu. -![](./etherscan-transaction.png) +![Snímek obrazovky transakce na Etherscan](./etherscan-transaction.png) Výborně! Právě jste nasadili chytrý kontrakt do testovací sítě Ethereum. Abyste pochopili, co se děje pod pokličkou, přejděte na kartu Průzkumník v našem [řídicím panelu Alchemy](https://dashboard.alchemy.com/explorer). Pokud máte více aplikací Alchemy, nezapomeňte filtrovat podle aplikace a vybrat **Hello World**. -![](./hello-world-explorer.png) +![Snímek obrazovky chytré smlouvy Hello World v průzkumníku bloků](./hello-world-explorer.png) Zde uvidíte několik metod JSON-RPC, které pro nás Hardhat/Ethers vytvořil pod pokličkou, když jsme volali funkci `.deploy()`. Dvě důležité metody jsou zde [`eth_sendRawTransaction`](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_sendrawtransaction), což je požadavek na zapsání našeho kontraktu do chainu Goerli, a [`eth_getTransactionByHash`](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_gettransactionbyhash), což je požadavek na přečtení informací o naší transakci na základě daného haše. Chcete-li se dozvědět více o odesílání transakcí, podívejte se na [náš tutoriál o odesílání transakcí pomocí Web3](/developers/tutorials/sending-transactions-using-web3-and-alchemy/). diff --git a/public/content/translations/cs/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md b/public/content/translations/cs/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md index 11177bfe302..30c3d3c754e 100644 --- a/public/content/translations/cs/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md +++ b/public/content/translations/cs/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md @@ -62,13 +62,13 @@ Tím získáte stejné informace, jaké jsou uvedeny na stránce transakcí na E #### Etherscan {#etherscan} -![](./etherscan_view.png) +![Snímek obrazovky zobrazení průzkumníka transakcí Etherscan](./etherscan_view.png) [Stránka kontraktu EF na Blockscoutu.](https://eth.blockscout.com/address/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe) #### Dune Analytics {#dune-analytics} -![](./dune_view.png) +![Snímek obrazovky řídicího panelu dotazů Dune Analytics](./dune_view.png) Řídicí panel najdete [zde](https://dune.com/paulapivat/Learn-Ethereum). Kliknutím na tabulku zobrazíte dotaz (viz také výše). @@ -146,7 +146,7 @@ ORDER BY block_time DESC` Zde je výstup SQL na Dune: -![](./list_of_txn.png) +![Snímek obrazovky se seznamem transakcí Ethereum](./list_of_txn.png) Tento jediný blok přidaný do řetězce mění stav Ethereum Virtual Machine ([EVM](/developers/docs/evm/)). Najednou se ověřují desítky, někdy i stovky transakcí. V tomto konkrétním případě bylo zahrnuto 222 transakcí. @@ -165,7 +165,7 @@ FROM temp_table Pro blok 12396854 bylo z celkových 222 transakcí úspěšně ověřeno 204: -![](./successful_txn.png) +![Snímek obrazovky úspěšné transakce Ethereum](./successful_txn.png) Požadavky na transakce se objevují desítkykrát za sekundu, ale bloky jsou zapisovány přibližně jednou za 15 sekund ([zdroj](/developers/docs/blocks/)). @@ -173,11 +173,11 @@ Abychom viděli, že se jeden blok vyprodukuje přibližně každých 15 sekund, Graf pro vyprodukované bloky Etherea za den (2016 - současnost) je: -![](./daily_blocks.png) +![Graf zobrazující denní produkci bloku Ethereum](./daily_blocks.png) Průměrný počet denně vyprodukovaných bloků za toto období je ~5 874: -![](./avg_daily_blocks.png) +![Graf zobrazující denní produkci bloku Ethereum](./avg_daily_blocks.png) Dotazy jsou: @@ -214,7 +214,7 @@ Bloky mají omezenou velikost. Maximální velikost bloku je dynamická a liší Jeden ze způsobů, jak si představit palivový limit bloku, je vnímat ho jako **nabídku** dostupného prostoru v bloku, do kterého se dávkují transakce. Palivový limit bloku lze dotazovat a vizualizovat od roku 2016 do současnosti: -![](./avg_gas_limit.png) +![Graf zobrazující průměrný limit plynu Ethereum v průběhu času](./avg_gas_limit.png) ```sql SELECT @@ -227,7 +227,7 @@ OFFSET 1 Dále je tu skutečné množství paliva použitého denně k placení za výpočty prováděné v řetězci Ethereum (tj. odeslání transakce, volání chytrého kontraktu, ražba NFT). Toto je **poptávka** po dostupném prostoru v bloku Etherea: -![](./daily_gas_used.png) +![Graf zobrazující denní spotřebu plynu Ethereum](./daily_gas_used.png) ```sql SELECT @@ -246,7 +246,7 @@ Proto můžeme ceny paliva chápat jako funkci poptávky po prostoru v bloku Eth Nakonec bychom se mohli chtít dotázat na průměrné denní ceny paliva pro řetězec Ethereum, nicméně to by vedlo k obzvláště dlouhé době dotazu, takže náš dotaz omezíme na průměrné množství paliva zaplaceného za transakci Nadací Ethereum. -![](./ef_daily_gas.png) +![Graf ukazující denní spotřebu plynu nadace Ethereum](./ef_daily_gas.png) Můžeme vidět ceny paliva zaplacené za všechny transakce provedené na adresu Nadace Ethereum v průběhu let. Zde je dotaz: diff --git a/public/content/translations/cs/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md b/public/content/translations/cs/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md index 30e02f29886..4909db7d48c 100644 --- a/public/content/translations/cs/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md +++ b/public/content/translations/cs/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md @@ -117,35 +117,35 @@ sudo systemctl start grafana-server Když máte Grafanu spuštěnou, měla by být dostupná na `localhost:3000`. Použijte preferovaný prohlížeč pro přístup k této cestě, poté se přihlaste s výchozími přihlašovacími údaji (uživatel: `admin` a heslo: `admin`). Po zobrazení výzvy změňte výchozí heslo a uložte. -![](./grafana1.png) +![Snímek obrazovky řídicího panelu Grafana pro monitorování Geth (panel 1)](./grafana1.png) Budete přesměrováni na domovskou stránku Grafany. Nejprve nastavte svá zdrojová data. Klikněte na ikonu konfigurace v levém panelu a vyberte „Zdroje dat“. -![](./grafana2.png) +![Snímek obrazovky řídicího panelu Grafana pro monitorování Geth (panel 2)](./grafana2.png) Zatím nejsou vytvořeny žádné zdroje dat, klikněte na „Přidat zdroj dat“ pro definování jednoho. -![](./grafana3.png) +![Snímek obrazovky řídicího panelu Grafana pro monitorování Geth (panel 3)](./grafana3.png) Pro toto nastavení vyberte „InfluxDB“ a pokračujte. -![](./grafana4.png) +![Snímek obrazovky řídicího panelu Grafana pro monitorování Geth (panel 4)](./grafana4.png) Konfigurace zdroje dat je poměrně jednoduchá, pokud spouštíte nástroje na stejném stroji. Musíte nastavit adresu InfluxDB a podrobnosti pro přístup k databázi. Viz obrázek níže. -![](./grafana5.png) +![Snímek obrazovky řídicího panelu Grafana pro monitorování Geth (panel 5)](./grafana5.png) Pokud je vše kompletní a InfluxDB je dostupná, klikněte na „Uložit a testovat“ a počkejte, až se zobrazí potvrzení. -![](./grafana6.png) +![Snímek obrazovky řídicího panelu Grafana pro monitorování Geth (panel 6)](./grafana6.png) Grafana je nyní nastavena ke čtení dat z InfluxDB. Nyní musíte vytvořit panel, který je bude interpretovat a zobrazovat. Vlastnosti panelů jsou kódovány v souborech JSON, které může kdokoli vytvořit a snadno importovat. V levém panelu klikněte na „Vytvořit a importovat“. -![](./grafana7.png) +![Snímek obrazovky řídicího panelu Grafana pro monitorování Geth (panel 7)](./grafana7.png) Pro monitorovací panel Geth zkopírujte ID [tohoto panelu](https://grafana.com/grafana/dashboards/13877/) a vložte jej na stránku „Importovat“ v Grafaně. Po uložení panelu by měl vypadat takto: -![](./grafana8.png) +![Snímek obrazovky řídicího panelu Grafana pro monitorování Geth (panel 8)](./grafana8.png) Své panely můžete upravovat. Každý panel lze upravovat, přesouvat, odstraňovat nebo přidávat. Můžete měnit své konfigurace. Je to na vás! Chcete-li se dozvědět více o tom, jak panely fungují, podívejte se do [dokumentace Grafany](https://grafana.com/docs/grafana/latest/dashboards/). Mohlo by vás také zajímat [Upozorňování](https://grafana.com/docs/grafana/latest/alerting/). To vám umožní nastavit upozornění pro případy, kdy metriky dosáhnou určitých hodnot. Jsou podporovány různé komunikační kanály. diff --git a/public/content/translations/cs/developers/tutorials/the-graph-fixing-web3-data-querying/index.md b/public/content/translations/cs/developers/tutorials/the-graph-fixing-web3-data-querying/index.md index 8a6bd8bf5c2..9a9e4167561 100644 --- a/public/content/translations/cs/developers/tutorials/the-graph-fixing-web3-data-querying/index.md +++ b/public/content/translations/cs/developers/tutorials/the-graph-fixing-web3-data-querying/index.md @@ -90,7 +90,7 @@ Nejprve si povíme něco o GraphQL, původně navrženém a implementovaném spo ![GraphQL API vs. REST API](./graphql.jpg) -![](./graphql-query.gif) +![Animovaná ukázka dotazu GraphQL na hřišti The Graph](./graphql-query.gif) Tyto dva obrázky v podstatě vystihují podstatu GraphQL. S dotazem vpravo můžeme definovat přesně, jaká data chceme, takže získáme vše v jednom požadavku a nic víc, než přesně to, co potřebujeme. GraphQL server se stará o načítání všech požadovaných dat, takže je pro spotřebitelskou stranu frontendu neuvěřitelně snadno použitelný. [Zde je pěkné vysvětlení](https://www.apollographql.com/blog/graphql-explained), jak přesně server zpracovává dotaz, pokud vás to zajímá. diff --git a/public/content/translations/cs/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/cs/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 406a3bbaecc..00000000000 --- a/public/content/translations/cs/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -title: "Waffle: Dynamické mockování a testování volání kontraktů" -description: "Pokročilý tutoriál pro Waffle o použití dynamického mockování a testování volání kontraktů" -author: "Daniel Izdebski" -tags: - [ - "waffle", - "smart kontrakt účty", - "solidity", - "testování", - "mocking" - ] -skill: intermediate -lang: cs -published: 2020-11-14 ---- - -## O čem je tento tutoriál? {#what-is-this-tutorial-about} - -V tomto tutoriálu se dozvíte, jak: - -- používat dynamické mockování -- testovat interakce mezi chytrými kontrakty - -Předpoklady: - -- už umíte napsat jednoduchý chytrý kontrakt v `Solidity` -- orientujete se v `JavaScriptu` a `TypeScriptu` -- už jste absolvovali jiné tutoriály o `Waffle` nebo o něm už něco málo víte - -## Dynamické mockování {#dynamic-mocking} - -Proč je dynamické mockování užitečné? Umožňuje nám psát unit testy namísto integračních testů. Co to znamená? Znamená to, že se nemusíme starat o závislosti chytrých kontraktů, a tak je můžeme všechny testovat v naprosté izolaci. Dovolte mi, abych vám přesně ukázal, jak to můžete udělat. - -### **1.** Projekt\*\* {#1-project} - -Než začneme, musíme si připravit jednoduchý projekt node.js: - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# nebo pokud používáte npm -npm init -``` - -Začněme přidáním závislostí pro typescript a testování - mocha & chai: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# nebo pokud používáte npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Nyní přidejme `Waffle` a `ethers`: - -```bash -yarn add --dev ethereum-waffle ethers -# nebo pokud používáte npm -npm install ethereum-waffle ethers --save-dev -``` - -Struktura vašeho projektu by nyní měla vypadat takto: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2.** Chytrý kontrakt\*\* {#2-smart-contract} - -Abychom mohli začít s dynamickým mockováním, potřebujeme chytrý kontrakt se závislostmi. Nebojte se, mám to pro vás připravené! - -Zde je jednoduchý chytrý kontrakt napsaný v `Solidity`, jehož jediným účelem je zkontrolovat, zda jsme bohatí. Používá token ERC20 ke kontrole, zda máme dostatek tokenů. Vložte ho do `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Jelikož chceme použít dynamické mockování, nepotřebujeme celý ERC20, proto používáme rozhraní IERC20 s jedinou funkcí. - -Je čas tento kontrakt sestavit! K tomu použijeme `Waffle`. Nejprve vytvoříme jednoduchý konfigurační soubor `waffle.json`, který specifikuje možnosti kompilace. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Nyní jsme připraveni sestavit kontrakt s Waffle: - -```bash -npx waffle -``` - -Snadné, že? Ve složce `build/` se objevily dva soubory odpovídající kontraktu a rozhraní. Použijeme je později pro testování. - -### **3.** Testování\*\* {#3-testing} - -Vytvořme si soubor s názvem `AmIRichAlready.test.ts` pro samotné testování. Nejprve se musíme postarat o importy. Budeme je potřebovat později: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -Kromě závislostí JS musíme importovat náš sestavený kontrakt a rozhraní: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle používá pro testování `chai`. Než ho však budeme moci použít, musíme do samotného chai vložit matchery od Waffle: - -```typescript -use(solidity) -``` - -Musíme implementovat funkci `beforeEach()`, která obnoví stav kontraktu před každým testem. Nejdřív si rozmysleme, co tam budeme potřebovat. K nasazení kontraktu potřebujeme dvě věci: peněženku a nasazený kontrakt ERC20, který předáme jako argument kontraktu `AmIRichAlready`. - -Nejprve si vytvoříme peněženku: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Poté musíme nasadit kontrakt ERC20. Tady je ta záludná část – máme pouze rozhraní. Tohle je ta část, kde nás Waffle přichází zachránit. Waffle má kouzelnou funkci `deployMockContract()`, která vytváří kontrakt pouze pomocí _abi_ rozhraní: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Nyní s peněženkou i nasazeným ERC20 můžeme pokračovat a nasadit kontrakt `AmIRichAlready`: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -Tím je naše funkce `beforeEach()` hotová. Váš soubor `AmIRichAlready.test.ts` by zatím měl vypadat takto: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Napišme si první test pro kontrakt `AmIRichAlready`. Co myslíte, o čem by měl být náš test? Ano, máte pravdu! Měli bychom zkontrolovat, jestli už jsme bohatí :) - -Ale počkejte chvilku. Jak bude náš mockovaný kontrakt vědět, jaké hodnoty má vrátit? Neimplementovali jsme žádnou logiku pro funkci `balanceOf()`. I zde může Waffle pomoci. Náš mockovaný kontrakt má teď několik nových vychytávek: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -S touto znalostí můžeme konečně napsat náš první test: - -```typescript -it("vrátí false, pokud má peněženka méně než 1000000 tokenů", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Rozdělme si tento test na části: - -1. Nastavíme náš mock kontrakt ERC20, aby vždy vracel zůstatek 999999 tokenů. -2. Zkontrolujeme, zda metoda `contract.check()` vrací `false`. - -Jsme připraveni to spustit: - -![Jeden test prochází](./test-one.png) - -Takže test funguje, ale... stále je co zlepšovat. Funkce `balanceOf()` bude vždy vracet 999999. Můžeme to vylepšit tím, že určíme peněženku, pro kterou by funkce měla něco vrátit – stejně jako u skutečného kontraktu: - -```typescript -it("vrátí false, pokud má peněženka méně než 1000001 tokenů", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Zatím jsme testovali pouze případ, kdy nejsme dostatečně bohatí. Otestujme místo toho opak: - -```typescript -it("vrátí true, pokud má peněženka alespoň 1000001 tokenů", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Spustíte testy... - -![Dva testy procházejí](test-two.png) - -...a je to! Zdá se, že náš kontrakt funguje, jak má :) - -## Testování volání kontraktů {#testing-contract-calls} - -Pojďme si shrnout, co jsme dosud udělali. Otestovali jsme funkčnost našeho kontraktu `AmIRichAlready` a zdá se, že funguje správně. To znamená, že jsme hotovi, že? Ne tak docela! Waffle nám umožňuje testovat náš kontrakt ještě důkladněji. Ale jak přesně? V arzenálu Waffle jsou matchery `calledOnContract()` a `calledOnContractWith()`. Umožní nám zkontrolovat, zda náš kontrakt zavolal mock kontrakt ERC20. Zde je základní test s jedním z těchto matcherů: - -```typescript -it("kontroluje, zda kontrakt zavolal balanceOf na tokenu ERC20", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Můžeme jít ještě dál a vylepšit tento test s druhým matcherem, o kterém jsem vám říkal: - -```typescript -it("kontroluje, zda kontrakt zavolal balanceOf s určitou peněženkou na tokenu ERC20", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Zkontrolujme, zda jsou testy správné: - -![Tři testy procházejí](test-three.png) - -Skvělé, všechny testy jsou zelené. - -Testování volání kontraktů s Waffle je super snadné. A tady je ta nejlepší část. Tyto matchery fungují jak s normálními, tak s mockovanými kontrakty! Je to proto, že Waffle zaznamenává a filtruje volání EVM, místo aby vkládal kód, jak je tomu u populárních testovacích knihoven pro jiné technologie. - -## Cílová rovinka {#the-finish-line} - -Výborně! Nyní víte, jak používat Waffle k testování volání kontraktů a dynamickému mockování kontraktů. Existuje mnohem více zajímavých funkcí k objevení. Doporučuji ponořit se do dokumentace Waffle. - -Dokumentace Waffle je k dispozici [zde](https://ethereum-waffle.readthedocs.io/). - -Zdrojový kód pro tento tutoriál naleznete [zde](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Tutoriály, které by vás také mohly zajímat: - -- [Testování chytrých kontraktů s Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/cs/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/cs/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 844937f21cf..00000000000 --- a/public/content/translations/cs/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "Návod na ukázkový Hello World s Waffle, hardhat a ethers" -description: "Vytvořte svůj první Waffle projekt s hardhat a ethers.js" -author: "MiZiet" -tags: - [ - "waffle", - "smart kontrakt účty", - "solidity", - "testování", - "hardhat", - "ethers.js" - ] -skill: beginner -lang: cs -published: 2020-10-16 ---- - -V tomto [Waffle](https://ethereum-waffle.readthedocs.io) tutoriálu se naučíme, jak nastavit jednoduchý projekt s chytrým kontraktem "Hello world" s použitím [hardhat](https://hardhat.org/) a [ethers.js](https://docs.ethers.io/v5/). Poté se naučíme, jak do našeho chytrého kontraktu přidat novou funkcionalitu a jak ji otestovat pomocí Waffle. - -Začněme vytvořením nového projektu: - -```bash -yarn init -``` - -nebo - -```bash -npm init -``` - -a instalací požadovaných balíčků: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -nebo - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -Dalším krokem je vytvoření ukázkového projektu hardhat spuštěním `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Welcome to Hardhat v2.0.3 👷‍ - -? What do you want to do? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -Vyberte `Create a sample project` - -Struktura našeho projektu by měla vypadat takto: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Pojďme se nyní podívat na některé z těchto souborů: {#now-lets-talk} - -- Greeter.sol – náš chytrý kontrakt napsaný v Solidity; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Náš chytrý kontrakt lze rozdělit na tři části: - -1. konstruktor – kde deklarujeme proměnnou typu string s názvem `greeting`, -2. funkce greet – funkce, která po zavolání vrátí `greeting`, -3. funkce setGreeting – funkce, která nám umožňuje změnit hodnotu `greeting`. - -- sample-test.js – náš soubor s testy - -```js -describe("Greeter", function () { - it("Should return the new greeting once it's changed", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### Další krok spočívá v kompilaci našeho kontraktu a spuštění testů: {#compiling-and-testing} - -Waffle testy používají Mocha (testovací framework) s Chai (knihovna asercí). Vše, co musíte udělat, je spustit `npx hardhat test` a počkat, až se objeví následující zpráva. - -```bash -✓ Should return the new greeting once it's changed -``` - -### Zatím to vypadá skvěle, pojďme do projektu přidat trochu na složitosti {#adding-complexity} - -Představte si situaci, kde někdo vloží prázdný řetězec jako pozdrav. To by nebyl moc vřelý pozdrav, že? -Postarejme se, aby se to nestalo: - -Chceme použít funkci `revert` ze Solidity, když někdo předá prázdný řetězec. Dobrou zprávou je, že tuto funkcionalitu můžeme snadno otestovat pomocí Waffle chai matcheru `to.be.revertedWith()`. - -```js -it("Should revert when passing an empty string", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -Vypadá to, že náš nový test neprošel: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -Pojďme tuto funkcionalitu implementovat do našeho chytrého kontraktu: - -```solidity -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -``` - -Nyní naše funkce setGreeting vypadá takto: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Pojďme znovu spustit testy: - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -Výborně! Dali jste to! :) - -### Závěr {#conclusion} - -Vytvořili jsme jednoduchý projekt s Waffle, Hardhat a ethers.js. Naučili jsme se, jak nastavit projekt, přidat test a implementovat novou funkcionalitu. - -Pro více skvělých chai matcherů k testování vašich chytrých kontraktů se podívejte do [oficiální dokumentace Waffle](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/translations/cs/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/cs/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index c8379ef1b5b..00000000000 --- a/public/content/translations/cs/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: "Testování jednoduchého chytrého kontraktu s knihovnou Waffle" -description: "Návod pro začátečníky" -author: Ewa Kowalska -tags: - [ - "smart kontrakt účty", - "solidity", - "Waffle", - "testování" - ] -skill: beginner -lang: cs -published: 2021-02-26 ---- - -## V tomto návodu se naučíte, jak {#in-this-tutorial-youll-learn-how-to} - -- Testovat změny zůstatku peněženky -- Testovat emisi událostí se zadanými argumenty -- Ověřit, že byla transakce vrácena - -## Předpoklady {#assumptions} - -- Můžete vytvořit nový projekt v JavaScriptu nebo TypeScriptu -- Máte nějaké základní zkušenosti s testy v JavaScriptu -- Použili jste nějaké správce balíčků jako yarn nebo npm -- Máte velmi základní znalosti chytrých kontraktů a Solidity - -## Začínáme {#getting-started} - -Tento návod ukazuje nastavení a spuštění testu pomocí yarn, ale není problém, pokud dáváte přednost npm – poskytnu správné odkazy na oficiální [dokumentaci](https://ethereum-waffle.readthedocs.io/en/latest/index.html) Waffle. - -## Instalace závislostí {#install-dependencies} - -[Přidejte](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) závislosti ethereum-waffle a typescript do vývojářských závislostí vašeho projektu. - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## Příklad chytrého kontraktu {#example-smart-contract} - -Během tohoto návodu budeme pracovat na jednoduchém příkladu chytrého kontraktu – EtherSplitter. Nedělá toho moc kromě toho, že umožňuje komukoli poslat nějaké wei a rovnoměrně je rozdělit mezi dva předdefinované příjemce. -Funkce `split` vyžaduje, aby byl počet wei sudý, jinak se vrátí zpět. Pro oba příjemce provádí převod wei následovaný emisí události Transfer. - -Vložte úryvek kódu EtherSplitter do `src/EtherSplitter.sol`. - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Lichá částka wei není povolena'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## Kompilace kontraktu {#compile-the-contract} - -Pro [kompilaci](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) kontraktu přidejte následující položku do souboru package.json: - -```json -"scripts": { - "build": "waffle" - } -``` - -Dále vytvořte konfigurační soubor Waffle v kořenovém adresáři projektu – `waffle.json` – a poté tam vložte následující konfiguraci: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Spusťte `yarn build`. Výsledkem je, že se objeví adresář `build` s kompilovaným kontraktem EtherSplitter ve formátu JSON. - -## Nastavení testu {#test-setup} - -Testování pomocí Waffle vyžaduje použití Chai matchers a Mocha, takže je musíte [přidat](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) do svého projektu. Aktualizujte soubor package.json a přidejte položku `test` do části se skripty: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -Chcete-li [spustit](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) své testy, stačí spustit `yarn test` . - -## Testování {#testing} - -Nyní vytvořte adresář `test` a vytvořte nový soubor `test\EtherSplitter.test.ts`. -Zkopírujte úryvek níže a vložte jej do našeho testovacího souboru. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Rozdělovač etheru", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // sem přidejte testy -}) -``` - -Pár slov na úvod. -`MockProvider` poskytuje testovací verzi blockchainu. Poskytuje také testovací peněženky, které nám poslouží k testování kontraktu EtherSplitter. Můžeme získat až deset peněženek zavoláním metody `getWallets()` na providera. V příkladu získáme tři peněženky – pro odesílatele a pro dva příjemce. - -Dále deklarujeme proměnnou nazvanou „splitter“ – to je náš testovací kontrakt EtherSplitter. Vytváří se před každým spuštěním jednotlivého testu metodou `deployContract`. Tato metoda simuluje nasazení kontraktu z peněženky předané jako první parametr (v našem případě peněženky odesílatele). Druhým parametrem je ABI a bytecode testovaného kontraktu – předáme tam soubor json zkompilovaného kontraktu EtherSplitter z adresáře `build`. Třetím parametrem je pole s argumenty konstruktoru kontraktu, což jsou v našem případě dvě adresy příjemců. - -## changeBalances {#changebalances} - -Nejprve zkontrolujeme, zda metoda split skutečně změní zůstatky v peněženkách příjemců. Pokud rozdělíme 50 wei z účtu odesílatele, očekávali bychom, že zůstatky obou příjemců se zvýší o 25 wei. Použijeme matcher `changeBalances` od Waffle: - -```ts -it("Změní zůstatky účtů", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -Jako první parametr matcheru předáváme pole peněženek příjemců a jako druhý – pole očekávaných navýšení na odpovídajících účtech. -Pokud bychom chtěli zkontrolovat zůstatek jedné konkrétní peněženky, mohli bychom také použít matcher `changeBalance`, který nevyžaduje předávání polí, jako v příkladu níže: - -```ts -it("Změní zůstatek účtu", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -Všimněte si, že v obou případech `changeBalance` a `changeBalances` předáváme funkci split jako callback, protože matcher potřebuje přístup ke stavu zůstatků před a po volání. - -Dále otestujeme, zda byla po každém převodu wei emitována událost Transfer. Obrátíme se na další matcher od Waffle: - -## Emit {#emit} - -```ts -it("Emituje událost při převodu na prvního příjemce", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("Emituje událost při převodu na druhého příjemce", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -Matcher `emit` nám umožňuje zkontrolovat, zda kontrakt emitoval událost při volání metody. Jako parametry matcheru `emit` poskytneme testovací kontrakt, u kterého předpokládáme emisi události, spolu s názvem této události. V našem případě je testovacím kontraktem `splitter` a název události – `Transfer`. Můžeme také ověřit přesné hodnoty argumentů, se kterými byla událost emitována – do matcheru `withArgs` předáme tolik argumentů, kolik naše deklarace události očekává. V případě kontraktu EtherSplitter předáváme adresy odesílatele a příjemce spolu s převedenou částkou wei. - -## revertedWith {#revertedwith} - -Jako poslední příklad zkontrolujeme, zda byla transakce vrácena v případě lichého počtu wei. Použijeme matcher `revertedWith`: - -```ts -it("Vrátí zpět, když je částka wei lichá", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Lichá částka wei není povolena" - ) -}) -``` - -Test, pokud projde, nás ujistí, že transakce byla skutečně vrácena. Musí však také existovat přesná shoda mezi zprávami, které jsme předali v příkazu `require`, a zprávou, kterou očekáváme v `revertedWith`. Pokud se vrátíme ke kódu kontraktu EtherSplitter, v příkazu `require` pro částku wei poskytujeme zprávu: ‚Lichá částka wei není povolena‘. Ta se shoduje se zprávou, kterou očekáváme v našem testu. Pokud by se neshodovaly, test by selhal. - -## Gratulujeme! {#congratulations} - -Udělali jste první velký krok k testování chytrých kontraktů s Waffle! diff --git a/public/content/translations/de/community/support/faq/index.md b/public/content/translations/de/community/support/faq/index.md new file mode 100644 index 00000000000..6cdd27e1b78 --- /dev/null +++ b/public/content/translations/de/community/support/faq/index.md @@ -0,0 +1,77 @@ +--- +title: "Häufig gestellte Fragen" +description: "Häufige Fragen zu Ethereum rund um Wallets, Transaktionen, Staking und mehr." +lang: de +--- + +# Häufig gestellte Fragen {#faq} + +## Ich habe Krypto an die falsche Adresse gesendet {#wrong-wallet} + +Eine auf Ethereum gesendete Transaktion ist unumkehrbar. Wenn Sie ETH oder Token an die falsche Wallet gesendet haben, gibt es leider keine Möglichkeit, die Transaktion rückgängig zu machen. + +**Was Sie tun können:** + +- **Wenn Sie den Eigentümer der Adresse kennen**, kontaktieren Sie ihn direkt und bitten Sie ihn, die Gelder zurückzugeben +- **Wenn die Adresse zu einer Börse oder einem bekannten Dienst gehört**, kontaktieren Sie deren Support-Team, da es Ihnen möglicherweise helfen kann +- **Wenn Sie Token an eine Vertragsadresse gesendet haben**, prüfen Sie, ob der Vertrag über eine Auszahlungs- oder Wiederherstellungsfunktion verfügt (dies ist selten) + +In den meisten Fällen gibt es keine Möglichkeit, das Geld wiederzuerlangen. Keine zentrale Organisation, Entität oder Person ist Eigentümer von Ethereum. Das bedeutet, dass auch niemand Transaktionen rückgängig machen kann. Überprüfen Sie die Empfängeradresse immer doppelt, bevor Sie bestätigen. + +## Ich habe den Zugriff auf meine Wallet verloren {#lost-wallet-access} + +Ihre Wiederherstellungsoptionen hängen von der Art der von Ihnen verwendeten Wallet ab. + +### Wenn Sie Ihre Seed-Phrase (Wiederherstellungsphrase) haben + +Sie können Ihre Wallet in jeder kompatiblen Wallet-App mit Ihrer Seed-Phrase wiederherstellen. Deshalb ist es so wichtig, Ihre Seed-Phrase sicher offline aufzubewahren. Anweisungen zur Wiederherstellung finden Sie in der Dokumentation Ihres Wallet-Anbieters. + +### Wenn Sie Ihre Seed-Phrase verloren haben + +Ohne Ihre Seed-Phrase oder Ihre privaten Schlüssel können Ihre Gelder nicht wiederhergestellt werden. Niemand, auch nicht ethereum.org, kann Ihr Passwort zurücksetzen oder den Zugang zu einer selbstverwalteten Wallet wiederherstellen. + +### Wenn sich Ihr Konto bei einer Börse befindet + +Wenn sich Ihr Konto bei einer zentralisierten Börse wie Coinbase, Binance oder Kraken befindet, wenden Sie sich direkt an das Support-Team der Börse. Diese kontrollieren die Konten auf ihrer Plattform und können möglicherweise bei der Rücksetzung von Passwörtern oder der Wiederherstellung von Konten helfen. + + + + + + +**Teilen Sie Ihre Seed-Phrase niemals mit jemandem**, der behauptet, Ihnen bei der Wiederherstellung Ihrer Wallet zu helfen. Dies ist eine der häufigsten Betrugsmaschen. Kein seriöser Dienst wird Sie jemals nach Ihrer Seed-Phrase fragen. + + + + + + Wie Sie eine Wallet benutzen + + +## Meine Transaktion hängt fest oder ist ausstehend {#stuck-transaction} + +Transaktionen auf Ethereum können hängen bleiben, wenn die von Ihnen festgelegte Gasgebühr niedriger ist als die, die das Netzwerk derzeit erfordert. Die meisten Wallets ermöglichen es Ihnen, dies zu beheben: + +- **Beschleunigen:** Senden Sie die gleiche Transaktion mit einer höheren Gasgebühr erneut +- **Abbrechen:** Senden Sie eine 0-ETH-Transaktion an Ihre eigene Adresse und verwenden Sie dabei dieselbe Nonce wie bei der ausstehenden Transaktion + +### Hilfreiche Anleitungen + +- [Wie man eine ausstehende Transaktion auf MetaMask beschleunigt oder abbricht](https://support.metamask.io/transactions-and-gas/transactions/how-to-speed-up-or-cancel-a-pending-transaction/) +- [Wie man ausstehende Ethereum-Transaktionen abbricht](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) + +## Wie kann ich mein Ethereum-Giveaway erhalten? {#giveaway-scam} + +Ethereum-Giveaways sind Betrugsmaschen, die darauf abzielen, Ihr ETH zu stehlen. Lassen Sie sich nicht von Angeboten verleiten, die zu gut scheinen, um wahr zu sein. Wenn Sie ETH an eine Giveaway-Adresse senden, werden Sie kein Giveaway erhalten und Sie werden Ihre Gelder nicht wiedererlangen können. + +[Mehr zur Betrugsprävention](/security/#common-scams) + +## Wie stake ich ETH? {#how-to-stake} + +Um ein Validator zu werden, müssen Sie 32 ETH in den Einlagenvertrag von Ethereum einzahlen und einen Validator-Knoten aufbauen. Sie können auch mit weniger ETH über Staking-Pools teilnehmen. + +Weitere Informationen finden Sie auf unseren [Staking-Seiten](/staking/) und auf dem [Staking-Launchpad](https://launchpad.ethereum.org/). + +## Wie kann ich Ethereum minen? {#mining-ethereum} + +Ethereum-Mining ist nicht mehr möglich. Das Mining wurde abgeschaltet, als Ethereum im September 2022 während [The Merge](/roadmap/merge/) von [Proof-of-Work](/glossary/#pow) auf [Proof-of-Stake](/glossary/#pos) umgestellt wurde. Anstatt Miner hat Ethereum jetzt Validatoren. Jeder kann ETH [staken](/glossary/#staking) und Staking-Belohnungen für das Ausführen von Validator-Software zur Sicherung des Netzwerks erhalten. diff --git a/public/content/translations/de/community/support/index.md b/public/content/translations/de/community/support/index.md deleted file mode 100644 index c8f1281b63b..00000000000 --- a/public/content/translations/de/community/support/index.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: Ethereum-Support -description: Support im Ethereum-Ökosystem erhalten -lang: de ---- - -# Ethereum-Support {#support} - -## Offizieller Ethereum-Support {#official-support} - -Sind Sie auf der Suche nach dem offiziellen Ethereum-Support? Es ist wichtig, zu wissen, dass Ethereum dezentralisiert ist. Das bedeutet, dass Ethereum keiner zentralen Organisation, Entität oder Person gehört. Daher existieren auch keine offiziellen Supportkanäle. - -Es ist wichtig, die dezentrale Gestaltung von Ethereum zu verstehen, denn jeder, der behauptet, offizieller Support für Ethereum zu sein, versucht wahrscheinlich, Sie zu betrügen. Der beste Schutz vor Betrug ist, sich zu informieren und Sicherheit ernst zu nehmen. - - - Ethereum – Sicherheits- und Betrugsvorbeugung - - - - Mehr erfahren über die Grundlagen von Ethereum - - -Trotz des Mangels an offizieller Unterstützung sind viele Gruppen, Communitys und Projekte im gesamten Ethereum-Ökosystem gern bereit, zu helfen, und Sie können auf dieser Seite viele nützliche Informationen und Ressourcen finden. Haben Sie noch Fragen? Treten Sie dem [ethereum.org Discord](https://discord.gg/ethereum-org) bei und wir versuchen, Ihnen weiterzuhelfen. - -## Häufig gestellte Fragen {#faq} - -### Ich habe ETH an die falsche Wallet gesendet {#wrong-wallet} - -Eine auf Ethereum gesendete Transaktion ist unumkehrbar. Wenn Sie ETH an die falsche Wallet geschickt haben, gibt es leider keine Möglichkeit, diese Gelder zurückzuholen. Keine zentrale Organisation, Entität oder Person ist Eigentümer von Ethereum. Das bedeutet, dass auch niemand Transaktionen rückgängig machen kann. Deshalb ist es wichtig, dass Sie alle Transaktionen vor dem Versenden immer noch einmal überprüfen. - -### Wie kann ich mein Ethereum-Giveaway erhalten? {#giveaway-scam} - -Ethereum-Giveaways sind Betrugsmaschen, die darauf abzielen, Ihr ETH zu stehlen. Lassen Sie sich nicht von Angeboten verleiten, die zu schön sind, um wahr zu sein. Wenn Sie ETH an eine Giveaway-Adresse schicken, erhalten Sie kein Giveaway und Sie können Ihr Geld nicht zurückfordern. - -[Mehr zum Thema Betrugsprävention](/security/#common-scams) - -### Meine Transaktion steckt fest {#stuck-transaction} - -Transaktionen auf Ethereum können manchmal stecken bleiben, wenn Sie eine niedrigere Transaktionsgebühr eingereicht haben, als aufgrund der Netzwerknachfrage erforderlich ist. Viele Wallets bieten die Möglichkeit, dieselbe Transaktion mit einer höheren Transaktionsgebühr erneut zu übermitteln, damit die Transaktion bearbeitet werden kann. Alternativ können Sie eine ausstehende Transaktion abbrechen. Senden Sie dafür eine Transaktion an Ihre eigene Adresse und verwenden Sie dieselbe Nonce wie für die ausstehende Transaktion. - -[So beschleunigen Sie ausstehenden Transaktionen auf MetaMask oder brechen sie ab](https://metamask.zendesk.com/hc/en-us/articles/360015489251-How-to-speed-up-or-cancel-a-pending-transaction) - -[So stornieren Sie ausstehende Ethereum-Transaktionen](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) - -### Wie kann ich Ethereum minen? {#mining-ethereum} - -Ethereum-Mining ist nicht mehr möglich. Das Mining wurde abgeschaltet, als Ethereum von [Proof-of-Work](/glossary/#pow) auf [Proof-of-Stake](/glossary/#pos) umstieg. Anstatt Miner hat Ethereum jetzt Validatoren. Jeder kann ETH [staken](/glossary/#staking) und Staking-Belohnungen für das Ausführen einer Validator-Software zur Sicherung des Netzwerks erhalten. - -### Wie werde ich Staker bzw. wie betreibe ich einen Validator? {#how-to-stake} - -Um ein Validator zu werden, müssen Sie 32 ETH in den Einlagenvertrag von Ethereum einzahlen und einen Validator-Knoten aufbauen. Weitere Informationen dazu finden Sie auf den [Staking-Seiten](/staking) und [dem Staking-Launchpad](https://launchpad.ethereum.org/). - -## dApps erstellen {#building-support} - -Erstellen kann durchaus schwer sein. Hier finden Sie einige Breiche mit Schwerpunkt auf Entwicklung mit erfahrenen Ethereum-Entwicklern, die Ihnen gerne helfen. - -- [Alchemy University](https://university.alchemy.com/#starter_code) -- [CryptoDevs-Discord](https://discord.com/invite/5W5tVb3) -- [Ethereum StackExchange](https://ethereum.stackexchange.com/) -- [Web3 University](https://www.web3.university/) -- [LearnWeb3](https://discord.com/invite/learnweb3) - -In unserem Bereich mit [Ethereum-Entwicklerressourcen](/developers/) finden Sie auch Dokumentationen und Entwicklungsleitfäden. - -### Tools {#dapp-tooling} - -Bezieht sich Ihre Frage auf ein bestimmtes Tool, Projekt oder eine Bibliothek? Die meisten Projekte haben Chat-Server oder Foren, die Unterstützung bieten. - -Hier sind einige beliebte Beispiele: - -- [Solidity](https://app.element.io/#/room/#solidity:matrix.org) -- [ethers.js](https://discord.gg/6jyGVDK6Jx) -- [web3.js](https://discord.gg/GsABYQu4sC) -- [Hardhat](https://discord.gg/xtrMGhmbfZ) -- [Alchemy](http://alchemy.com/discord) -- [Tenderly](https://discord.gg/fBvDJYR) - -## Einen Knoten betreiben {#node-support} - -Wenn Sie einen Knoten oder Validator betreiben, finden Sie hier einige Communitys, die Ihnen den Einstieg erleichtern. - -- [EthStaker-Discord](https://discord.gg/ethstaker) -- [EthStaker-Reddit](https://www.reddit.com/r/ethstaker) - -Die meisten Teams, die Ethereum-Clients entwickeln, haben auch eigene, öffentlich zugängliche Bereiche, in denen Sie Unterstützung erhalten und Fragen stellen können. - -### Ausführende Clients {#execution-clients} - -- [Geth](https://discord.gg/FqDzupGyYf) -- [Nethermind](https://discord.gg/YJx3pm8z5C) -- [Besu](https://discord.gg/p8djYngzKN) -- [Erigon](https://github.com/ledgerwatch/erigon/issues) -- [Reth](https://github.com/paradigmxyz/reth/discussions) - -### Konsens-Clients {#consensus-clients} - -- [Prysm](https://discord.gg/prysmaticlabs) -- [Nimbus](https://discord.gg/nSmEH3qgFv) -- [Lighthouse](https://discord.gg/cyAszAh) -- [Teku](https://discord.gg/7hPv2T6) -- [Lodestar](https://discord.gg/aMxzVcr) - -Sie können hier auch [lernen, wie ein Knoten betrieben wird](/developers/docs/nodes-and-clients/run-a-node/). diff --git a/public/content/translations/de/community/support/misconceptions/index.md b/public/content/translations/de/community/support/misconceptions/index.md new file mode 100644 index 00000000000..d11783caacf --- /dev/null +++ b/public/content/translations/de/community/support/misconceptions/index.md @@ -0,0 +1,73 @@ +--- +title: "Häufige Missverständnisse über Ethereum" +description: "Aufklärung der häufigsten Missverständnisse über die Funktionsweise von Ethereum." +lang: de +--- + +# Häufige Missverständnisse über Ethereum {#misconceptions} + +## Ist Ethereum ein Unternehmen? {#not-a-company} + +Ethereum ist eine dezentralisierte Open-Source-Technologie, die von Tausenden von Mitwirkenden weltweit gepflegt wird. Es gibt kein Unternehmen namens "Ethereum", das Konten verwaltet, Gelder hält oder Kundensupport anbietet. + +Die [Ethereum Foundation](https://ethereum.foundation/) ist eine gemeinnützige Organisation, die die Entwicklung von Ethereum unterstützt, aber sie besitzt oder kontrolliert das Netzwerk nicht. Keine einzelne Entität tut dies. + +**[ethereum.org](/)** ist eine von der Community betriebene Bildungsressource. Es ist keine Börse, Wallet oder Finanzinstitut. Es hält keine Benutzergelder und kann nicht auf Konten zugreifen. + + + Was ist Ethereum? + + +## Kann jemand mein Geld wiederherstellen oder einfrieren? {#no-fund-access} + +Im Gegensatz zu einer Bank gibt es bei Ethereum keine zentrale Behörde, die Gelder einfrieren, beschlagnahmen oder wiederherstellen kann. Die Person, die die privaten Schlüssel (oder die Seed-Phrase) besitzt, hat die volle und alleinige Kontrolle über eine Wallet. + +Das bedeutet: + +- **Niemand kann Gelder wiederherstellen**, die Sie an die falsche Adresse gesendet haben +- **Niemand kann** eine Transaktion rückgängig machen, nachdem sie bestätigt wurde +- **Niemand kann** Ihre Wallet einfrieren oder Ihre Transaktionen blockieren +- **Niemand kann Ihr Passwort zurücksetzen**, wenn Sie Ihre Seed-Phrase verlieren + +Deshalb ist der Schutz Ihrer Seed-Phrase entscheidend. Es ist der einzige Weg, um auf Ihre Wallet zuzugreifen. Wenn sie verloren geht oder gestohlen wird, gibt es keine Wiederherstellungsoption. + + + Ethereum-Sicherheit und Betrugsprävention + + +## Kann ich noch Ethereum minen? {#no-mining} + +Ethereum ist im September 2022 während [The Merge](/roadmap/merge/) von [Proof-of-Work](/glossary/#pow) auf [Proof-of-Stake](/glossary/#pos) umgestiegen. Mining ist auf Ethereum nicht mehr möglich. + +Das Netzwerk wird jetzt von Validatoren gesichert, die ETH [staken](/glossary/#staking). Jeder kann teilnehmen: + +- **Solo-Staking:** Betreiben Sie Ihren eigenen Validator mit 32 ETH – [erfahren Sie mehr](/staking/solo/) +- **Staking as a Service:** Delegieren Sie den Betrieb des Nodes, während Sie Ihre Schlüssel behalten – [erfahren Sie mehr](/staking/saas/) +- **Gepooltes Staking:** Staken Sie mit weniger als 32 ETH, indem Sie einem Pool beitreten – [erfahren Sie mehr](/staking/pools/) + + + Mehr über Staking erfahren + + +## Gibt es ein Ethereum-Supportteam? {#no-support-team} + +Die Suche nach "offiziellem Ethereum-Support" ist ähnlich wie die Suche nach "offiziellem Internet-Support". Diesen gibt es natürlich nicht, aber je nach Problem können Sie möglicherweise Unterstützung von Ihrem Internetdienstanbieter, dem Hersteller Ihrer Router-Hardware oder einem der Unternehmen erhalten, die hinter dem von Ihnen verwendeten Gerät, der App oder der Website stehen. + +Bei Ethereum ist es ähnlich. Es gibt kein Unternehmen, kein Support-Team und keinen Helpdesk hinter Ethereum als Ganzes, aber je nach Problem können Sie Hilfe finden, indem Sie sich an Ihren _Wallet-Anbieter_, _Staking-Dienst_, Ihre _Börse_, Ihr _Finanzinstitut_ oder das _Team, das eine von Ihnen verwendete App pflegt_, wenden. + +Da Ethereum standardmäßig öffentlich transparent ist, können Sie auch [Block-Explorer](/developers/docs/data-and-analytics/block-explorers/), [Analyse-Tools](/developers/tools/analytics/) und andere [Online-Rechercheressourcen](/community/support/scams/#analyze) als nützlich empfinden, um ein Problem direkt zu untersuchen. + +Abgesehen davon wird Sie niemals jemand von Ethereum oder ethereum.org: + +- per Direktnachricht kontaktieren +- nach Ihrer Seed-Phrase oder Ihren privaten Schlüsseln fragen +- Sie bitten, ETH zu senden, um Ihre Wallet zu verifizieren +- anbieten, Ihnen gegen eine Gebühr bei der Wiederherstellung von Geldern zu helfen + +**Jeder, der etwas davon tut, versucht, Sie zu betrügen.** + +Wenn Sie Hilfe benötigen, sind die echten Communities, die Ihnen helfen können, auf der [Support-Seite](/community/support/) aufgeführt. Dies sind von Freiwilligen betriebene, offene Communities – keine offiziellen Support-Kanäle. + + + Ethereum-Sicherheit und Betrugsprävention + diff --git a/public/content/translations/de/community/support/scams/index.md b/public/content/translations/de/community/support/scams/index.md new file mode 100644 index 00000000000..3edab09e1a1 --- /dev/null +++ b/public/content/translations/de/community/support/scams/index.md @@ -0,0 +1,159 @@ +--- +title: Hilfe bei Betrug & Meldung +description: "Was Sie tun können, wenn Sie betrogen wurden, wie Sie Ihre verbleibenden Vermögenswerte sichern und wo Sie Betrug melden können." +lang: de +--- + +# Ich wurde betrogen oder habe Geld verloren {#scam-help} + +Betrügereien mit Kryptowährungen zielen auf Menschen aller Erfahrungsstufen ab, einschließlich Fachleuten aus dem Finanz- und Technologiebereich. Sie sind nicht allein, und hier zu sein ist der richtige erste Schritt. + + + + + + +**Niemand kann Blockchain-Transaktionen rückgängig machen.** Wenn Sie jemand kontaktiert und behauptet, er könne Ihr Geld gegen eine Gebühr wiederbeschaffen, handelt es sich mit ziemlicher Sicherheit um einen zweiten Betrug. Siehe [Wiederherstellungsbetrug](#recovery-scams) unten. + + + + +## Sichern Sie Ihre verbleibenden Vermögenswerte {#secure-assets} + +Wenn Sie mit einem Betrüger interagiert haben oder vermuten, dass Ihre Wallet kompromittiert ist, führen Sie sofort die folgenden Schritte aus: + +1. **Übertragen Sie verbleibende Gelder** in eine neue, sichere Wallet, auf die der Betrüger keinen Zugriff hat +2. **Widerrufen Sie Token-Genehmigungen.** Betrüger bringen Sie oft dazu, unbegrenzte Token-Ausgaben zu genehmigen. Der Widerruf dieser Berechtigungen verhindert, dass Ihre Wallet weiter leergeräumt wird +3. **Ändern Sie die Passwörter** für alle verknüpften Börsenkonten +4. **Aktivieren Sie die Zwei-Faktor-Authentifizierung (2FA)** für alle Konten, die mit Kryptowährungen zu tun haben + +### So widerrufen Sie Token-Genehmigungen {#revoke-approvals} + +Wenn Sie mit einer Dapp oder einem Smart Contract interagieren, haben Sie ihm möglicherweise die Erlaubnis erteilt, Ihre Token auszugeben. Wenn ein Betrüger Sie dazu gebracht hat, einen bösartigen Vertrag zu genehmigen, kann er auch nach dem ursprünglichen Betrug weiterhin Ihre Token abziehen. + +Verwenden Sie diese Tools, um Genehmigungen zu überprüfen und zu widerrufen: + +- [Revoke.cash](https://revoke.cash/): Verbinden Sie Ihre Wallet, um alle aktiven Genehmigungen zu sehen und sie zu widerrufen +- [Revokescout](https://revoke.blockscout.com/): Genehmigungen über Blockscout prüfen und widerrufen +- [Etherscan Token Approval Checker](https://etherscan.io/tokenapprovalchecker): Genehmigungen über Etherscan prüfen und widerrufen + + + Schritt-für-Schritt-Anleitung: So widerrufen Sie den Token-Zugriff + + +## Melden Sie Betrugsadressen und Websites {#report} + +Meldungen helfen, andere Benutzer zu warnen und können bei Ermittlungen der Strafverfolgungsbehörden helfen. Dokumentieren Sie alles: Transaktions-Hashes, Wallet-Adressen, Screenshots und jede Kommunikation mit dem Betrüger. + +### Eine Betrugsadresse melden {#report-address} + +- [Chainabuse](https://www.chainabuse.com/): Community-basierte Datenbank zur Meldung von Betrug und Schwindel. Senden Sie Berichte und suchen Sie nach bekannten Betrugsadressen +- [Etherscan-Bericht](https://info.etherscan.com/report-address/): eine Adresse auf dem meistgenutzten Ethereum-Block-Explorer markieren +- [CryptoScamDB](https://cryptoscamdb.org/): Open-Source-Datenbank zur Verfolgung von Betrügereien mit Kryptowährungen + +### Melden Sie eine betrügerische Website oder ein Social-Media-Konto {#report-website} + +- [PhishTank](https://phishtank.org/): Phishing-URLs einreichen und verifizieren +- [Google Safe Browsing](https://safebrowsing.google.com/safebrowsing/report_phish/): Melden Sie Phishing-Seiten an Google, damit diese in Chrome und anderen Browsern blockiert werden +- [Netcraft](https://report.netcraft.com/report/mistake): bösartige und betrügerische Websites melden +- Melden Sie es direkt auf der Social-Media-Plattform, auf der der Betrug stattgefunden hat (Twitter/X, Discord, Telegram haben alle Meldefunktionen) + +### Bei der Strafverfolgung melden {#report-law-enforcement} + +- **Vereinigte Staaten:** [FBI Internet Crime Complaint Center (IC3)](https://www.ic3.gov/) +- **Vereinigtes Königreich:** [Action Fraud](https://www.actionfraud.police.uk/) +- **Europäische Union:** [Europol](https://www.europol.europa.eu/report-a-crime) +- **Andere Länder:** erstatten Sie Anzeige bei Ihrer örtlichen Polizei. Betrug mit Kryptowährungen ist in den meisten Rechtsordnungen eine Straftat + +## Analysieren Sie, was passiert ist {#analyze} + +Zu verstehen, wohin Ihr Geld geflossen ist, kann bei Berichten helfen und Wiederherstellungsbemühungen unterstützen, wenn das Geld auf einer zentralisierten Börse landet. + +- [Blockscout](https://eth.blockscout.com/): Open-Source-Block-Explorer, um jeden Transaktions-Hash oder jede Wallet-Adresse nachzuschlagen und zu sehen, wohin Gelder gesendet wurden +- [Etherscan](https://etherscan.io/): Suchen Sie nach einem beliebigen Transaktions-Hash oder einer Wallet-Adresse, um zu sehen, wohin Gelder gesendet wurden +- [Chainabuse lookup](https://www.chainabuse.com/): prüfen, ob eine Adresse bereits von anderen Opfern gemeldet wurde +- [MetaSleuth](https://metasleuth.io/) von BlockSec: visuelles Transaktionsverfolgungstool, das Geldflüsse abbildet + +**Wenn Gelder an eine zentralisierte Börse** (wie Coinbase, Binance, Kraken) gesendet wurden, kontaktieren Sie sofort deren Support-Team mit den Transaktionsdetails. Börsen können manchmal Konten, die wegen Betrugs gemeldet wurden, einfrieren. + +## Die harte Wahrheit {#hard-truth} + +Da Ethereum dezentralisiert ist, kann keine zentrale Behörde Transaktionen rückgängig machen oder gestohlene Gelder wiederbeschaffen. Sobald eine Transaktion in der Blockchain bestätigt ist, ist sie endgültig. + +Eine Meldung ist dennoch wertvoll. Berichte helfen den Strafverfolgungsbehörden, organisierte Betrugsringe aufzuspüren, und das Markieren von Adressen auf Chainabuse und Etherscan warnt zukünftige potenzielle Opfer. + +## Arten von Betrug, auf die man achten sollte {#scam-types} + + + +Betrüger erstellen gefälschte Giveaways, die versprechen, Ihre ETH zu vervielfachen oder Ihnen kostenlose Token zu geben. Sie geben sich oft als bekannte Persönlichkeiten wie Vitalik Buterin aus. Wenn Sie ETH an eine "Giveaway"-Adresse senden, erhalten Sie nichts zurück. + +**Denken Sie daran:** Vitalik und andere prominente Persönlichkeiten werden Sie niemals bitten, ihnen ETH zu schicken. + +[Mehr zu gängigen Betrugsmaschen](/security/#common-scams) + + + + +Betrüger geben sich auf Discord, Telegram und in den sozialen Medien als Mitglieder des Ethereum-Teams, als Moderatoren oder als Support-Mitarbeiter aus. Sie können Ihnen Direktnachrichten schicken, in denen sie Hilfe anbieten oder behaupten, dass es ein Problem mit Ihrem Konto gibt. + +**Denken Sie daran:** + +- Es gibt kein "Ethereum-Support-Team" +- Echte Moderatoren werden Ihnen niemals zuerst eine Direktnachricht senden +- Geben Sie Ihre Seed-Phrase oder Ihre privaten Schlüssel niemals und aus keinem Grund an Dritte weiter +- Klicken Sie niemals auf Links, die in unaufgefordert zugesandten Nachrichten enthalten sind + + + + +Wiederherstellungsbetrügereien zielen speziell auf Personen ab, die bereits Geld verloren haben. Betrüger überwachen soziale Medien nach Personen, die darüber sprechen, betrogen worden zu sein, und geben sich dann als "Blockchain-Ermittler" oder "Krypto-Wiederherstellungsexperten" aus. + +Sie versprechen, Ihre gestohlene Kryptowährung gegen eine Vorauszahlung aufzuspüren und wiederzubeschaffen. Nachdem Sie bezahlt haben, verschwinden sie. + +**Kein seriöser Dienst kann Blockchain-Transaktionen rückgängig machen.** Jeder, der dies verspricht, lügt. Dies ist einer der häufigsten Folgebetrügereien. + + + + +Phishing-Websites sehen identisch aus wie echte Wallet-Apps, Börsen oder DeFi-Plattformen. Sie bringen Sie dazu, Ihre Seed-Phrase einzugeben oder Ihre Wallet zu verbinden, und ziehen dann Ihr Geld ab. + +**Schützen Sie sich:** + +- Überprüfen Sie immer die URL, bevor Sie Ihre Wallet verbinden +- Setzen Sie ein Lesezeichen für die offiziellen Websites, die Sie regelmäßig nutzen +- Geben Sie Ihre Seed-Phrase niemals auf einer Website ein. Legitime Apps fragen niemals danach +- Verwenden Sie [PhishTank](https://phishtank.org/), um verdächtige URLs zu überprüfen + + + So erkennen Sie betrügerische Token + + + + + Vollständiger Leitfaden zur Ethereum-Sicherheit und Betrugsprävention + diff --git a/public/content/translations/de/developers/docs/nodes-and-clients/node-architecture/index.md b/public/content/translations/de/developers/docs/nodes-and-clients/node-architecture/index.md index f23525ce622..ebb5978f1fd 100644 --- a/public/content/translations/de/developers/docs/nodes-and-clients/node-architecture/index.md +++ b/public/content/translations/de/developers/docs/nodes-and-clients/node-architecture/index.md @@ -10,7 +10,7 @@ Als Ethereum noch [Proof-of-Work](/developers/docs/consensus-mechanisms/pow/) ve Das folgende Diagramm zeigt die Verbindung zwischen zwei Ethereum-Clients. Die beiden Clients verbinden sich mit ihren eigenen Peer-to-Peer(P2P)-Netzwerken. Es werden separate P2P-Netzwerke benötigt, da der Ausführungsclient Transaktionen über ihr P2P Netzwerk kommuniziert, wodurch sie ihren lokalen Transaktionspool verwalten können. Konsensclients können dabei Blöcke über ihr eigenes P2P-Netzwerk kommunizieren, was Konsens und Wachstum der Blockchain ermöglicht. -![](node-architecture-text-background.png) +![Diagramm der Ethereum-Knotenarchitektur mit Darstellung der Ausführungs- und Konsensebenen](node-architecture-text-background.png) _Für den Execution Client stehen verschiedene Optionen zur Wahl, einschließlich Erigon, Nethermind und Besu_. diff --git a/public/content/translations/de/developers/tutorials/ai-trading-agent/index.md b/public/content/translations/de/developers/tutorials/ai-trading-agent/index.md new file mode 100644 index 00000000000..69180e6e974 --- /dev/null +++ b/public/content/translations/de/developers/tutorials/ai-trading-agent/index.md @@ -0,0 +1,980 @@ +--- +title: Make your own AI trading agent on Ethereum +description: In this tutorial you learn how to make a simple AI trading agent. This agent reads information from the blockchain, asks an LLM for a recommendation based on that information, performs the trade the LLM recommends, and then waits and repeats. +author: Ori Pomerantz +tags: [ "AI", "trading", "Agent", "Python" ] +skill: intermediate +published: 2026-02-13 +lang: de +sidebarDepth: 3 +--- + +In this tutorial you learn how to build a simple AI trading agent. This agent works using these steps: + +1. Read the current and past prices of a token, as well as other potentially relevant information +2. Build a query with this information, along with background information to explain how it might be relevant +3. Submit the query and receive back a projected price +4. Trade based on the recommendation +5. Wait and repeat + +This agent demonstrates how to read information, translate it into a query that yields a usable answer, and use that answer. All of these are steps required for an AI agent. This agent is implemented in Python because it is the most common language used in AI. + +## Why do this? {#why-do-this} + +Automated trading agents allow developers to select and execute a trading strategy. [AI agents](/ai-agents) allow for more complex and dynamic trading strategies, potentially using information and algorithms the developer has not even considered using. + +## The tools {#tools} + +This tutorial uses [Python](https://www.python.org/), the [Web3 library](https://web3py.readthedocs.io/en/stable/), and [Uniswap v3](https://github.com/Uniswap/v3-periphery) for quotes and trading. + +### Why Python? {#python} + +The most widely used language for AI is [Python](https://www.python.org/), so we use it here. Don't worry if you don't know Python. The language is very clear, and I will explain exactly what it does. + +The [Web3 library](https://web3py.readthedocs.io/en/stable/) is the most common Python Ethereum API. It is pretty easy to use. + +### Trading on the blockchain {#trading-on-blockchain} + +There are [many distributed exchanges (DEX)](/apps/categories/defi/) that let you trade tokens on Ethereum. However, they tend to have similar exchange rates due to [arbitrage](/developers/docs/smart-contracts/composability/#better-user-experience). + +[Uniswap](https://app.uniswap.org/) is a widely used DEX that we can use for both quotes (to see token relative values) and trades. + +### OpenAI {#openai} + +For a large language model, I chose to get started with [OpenAI](https://openai.com/). To run the application in this tutorial you'll need to pay for API access. The minimum payment of $5 is more than sufficient. + +## Development, step by step {#step-by-step} + +To simplify development, we proceed in stages. Each step is a branch in GitHub. + +### Erste Schritte {#getting-started} + +There are steps to get started under UNIX or Linux (including [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)) + +1. If you don't already have it, download and install [Python](https://www.python.org/downloads/). + +2. Klonen Sie das GitHub-Repository. + + ```sh + git clone https://github.com/qbzzt/260215-ai-agent.git -b 01-getting-started + cd 260215-ai-agent + ``` + +3. Install [`uv`](https://docs.astral.sh/uv/getting-started/installation/). The command on your system might be different. + + ```sh + pipx install uv + ``` + +4. Download the libraries. + + ```sh + uv sync + ``` + +5. Activate the virtual environment. + + ```sh + source .venv/bin/activate + ``` + +6. To verify Python and Web3 are working correctly, run `python3` and provide it with this program. You can enter it at the `>>>` prompt; there is no need to create a file. + + ```python + from web3 import Web3 + MAINNET_URL = "https://eth.drpc.org" + w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) + w3.eth.block_number + quit() + ``` + +### Reading from the blockchain {#read-blockchain} + +The next step is to read from the blockchain. To do that, you need to change to the `02-read-quote` branch and then use `uv` to run the program. + +```sh +git checkout 02-read-quote +uv run agent.py +``` + +You should receive a list of `Quote` objects, each with a timestamp, a price, and the asset (currently always `WETH/USDC`). + +Here is a line-by-line explanation. + +```python +from web3 import Web3 +from web3.contract import Contract +from decimal import Decimal, ROUND_HALF_UP +from dataclasses import dataclass +from datetime import datetime, timezone +from pprint import pprint +import time +import functools +import sys +``` + +Importieren Sie die Bibliotheken, die wir benötigen. They are explained below when used. + +```python +print = functools.partial(print, flush=True) +``` + +Replaces Python’s `print` with a version that always flushes output immediately. This is useful in a long-running script because we don't want to wait for status updates or debugging output. + +```python +MAINNET_URL = "https://eth.drpc.org" +``` + +A URL to get to mainnet. You can get one from [Node as a service](/developers/docs/nodes-and-clients/nodes-as-a-service/) or use one of those advertised in [Chainlist](https://chainlist.org/chain/1). + +```python +BLOCK_TIME_SECONDS = 12 +MINUTE_BLOCKS = int(60 / BLOCK_TIME_SECONDS) +HOUR_BLOCKS = MINUTE_BLOCKS * 60 +DAY_BLOCKS = HOUR_BLOCKS * 24 +``` + +An Ethereum mainnet block typically happens every twelve seconds, so these are the number of blocks we'd expect to happen in a time period. Note that this is not an exact figure. When the [block proposer](/developers/docs/consensus-mechanisms/pos/block-proposal/) is down, that block is skipped, and the time for the next block is 24 seconds. If we wanted to get the exact block for a timestamp, we'd use [binary search](https://en.wikipedia.org/wiki/Binary_search). However, this is close enough for our purposes. Predicting the future is not an exact science. + +```python +CYCLE_BLOCKS = DAY_BLOCKS +``` + +The size of the cycle. We review quotes once per cycle and try to estimate the value at the end of the next cycle. + +```python +# The address of the pool we're reading +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +``` + +The quote values are taken from the Uniswap 3 USDC/WETH pool at address [`0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`](https://eth.blockscout.com/address/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640?tab=read_write_contract). This address is already in checksum form, but it's better to use [`Web3.to_checksum_address`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_checksum_address) to make the code reusable. + +```python +POOL_ABI = [ + { "name": "slot0", ... }, + { "name": "token0", ... }, + { "name": "token1", ... }, +] + +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... } +] +``` + +These are the [ABIs](https://docs.soliditylang.org/en/latest/abi-spec.html) for the two contracts we need to contact. To keep the code concise, we include only the functions we need to call. + +```python +w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) +``` + +Initiate the [`Web3`](https://web3py.readthedocs.io/en/stable/quickstart.html#remote-providers) library and connect to an Ethereum node. + +```python +@dataclass(frozen=True) +class ERC20Token: + address: str + symbol: str + decimals: int + contract: Contract +``` + +This is one way to create a data class in Python. The [`Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) data type is used to connect to the contract. Note the `(frozen=True)`. In Python [booleans](https://en.wikipedia.org/wiki/Boolean_data_type) are defined as `True` or `False`, capitalized. This data class is `frozen`, meaning the fields cannot be modified. + +Note the indentation. In contrast to [C-derived languages](https://en.wikipedia.org/wiki/List_of_C-family_programming_languages), Python uses indentation to denote blocks. The Python interpreter knows that the following definition is not part of this data class because it doesn't start at the same indentation as the data class fields. + +```python +@dataclass(frozen=True) +class PoolInfo: + address: str + token0: ERC20Token + token1: ERC20Token + contract: Contract + asset: str + decimal_factor: Decimal = 1 +``` + +The [`Decimal`](https://docs.python.org/3/library/decimal.html) type is used for accurately handling decimal fractions. + +```python + def get_price(self, block: int) -> Decimal: +``` + +This is the way to define a function in Python. The definition is indented to show it is still part of `PoolInfo`. + +In a function that is part of a data class the first parameter is always `self`, the data class instance that called here. Here there is another parameter, the block number. + +```python + assert block <= w3.eth.block_number, "Block is in the future" +``` + +If we could read the future, we wouldn't need AI for trading. + +```python + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) +``` + +The syntax for calling a function on the EVM from Web3 is this: `.functions.().call()`. The parameters can be the EVM function's parameters (if any; here there aren't) or [named parameters](https://en.wikipedia.org/wiki/Named_parameter) for modifying blockchain behavior. Here we use one, `block_identifier`, to specify [the block number](/developers/docs/apis/json-rpc/#default-block) we wish to run in. + +The result is [this struct, in array form](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol#L56-L72). The first value is a function of the exchange rate between the two tokens. + +```python + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 +``` + +To reduce onchain calculations, Uniswap v3 does not store the actual exchange factor but rather its square root. Because the EVM does not support floating point math or fractions, instead of the actual value, the response is price296 + +```python + # (token1 per token0) + return 1/(raw_price * self.decimal_factor) +``` + +The raw price we get is the number of `token0` we get for each `token1`. In our pool `token0` is USDC (stablecoin with the same value as a US dollar) and `token1` is [WETH](https://opensea.io/learn/blockchain/what-is-weth). The value we really want is the number of dollars per WETH, not the inverse. + +The decimal factor is the ratio between the [decimal factors](https://docs.openzeppelin.com/contracts/4.x/erc20#a-note-on-decimals) for the two tokens. + +```python +@dataclass(frozen=True) +class Quote: + timestamp: str + price: Decimal + asset: str +``` + +This data class represents a quote: the price of a specific asset at a given point in time. At this point, the `asset` field is irrelevant because we use a single pool and therefore have a single asset. However, we will add more assets later. + +```python +def read_token(address: str) -> ERC20Token: + token = w3.eth.contract(address=address, abi=ERC20_ABI) + symbol = token.functions.symbol().call() + decimals = token.functions.decimals().call() + + return ERC20Token( + address=address, + symbol=symbol, + decimals=decimals, + contract=token + ) +``` + +This function takes an address and returns information about the token contract at that address. To create a new [Web3 `Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html), we provide the address and ABI to `w3.eth.contract`. + +```python +def read_pool(address: str) -> PoolInfo: + pool_contract = w3.eth.contract(address=address, abi=POOL_ABI) + token0Address = pool_contract.functions.token0().call() + token1Address = pool_contract.functions.token1().call() + token0 = read_token(token0Address) + token1 = read_token(token1Address) + + return PoolInfo( + address=address, + asset=f"{token1.symbol}/{token0.symbol}", + token0=token0, + token1=token1, + contract=pool_contract, + decimal_factor=Decimal(10) ** Decimal(token0.decimals - token1.decimals) + ) +``` + +This function returns everything we need about [a specific pool](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol). The syntax `f""` is a [formatted string](https://docs.python.org/3/reference/lexical_analysis.html#f-strings). + +```python +def get_quote(pool: PoolInfo, block_number: int = None) -> Quote: +``` + +Get a `Quote` object. The default value for `block_number` is `None` (no value). + +```python + if block_number is None: + block_number = w3.eth.block_number +``` + +If a block number was not specified, use `w3.eth.block_number`, which is the latest block number. This is the syntax for [an `if` statement](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement). + +It might look as if it would have been better to just set the default to `w3.eth.block_number`, but that doesn't work well because it would be the block number at the time the function is defined. In a long-running agent, this would be a problem. + +```python + block = w3.eth.get_block(block_number) + price = pool.get_price(block_number) + return Quote( + timestamp=datetime.fromtimestamp(block.timestamp, timezone.utc).isoformat(), + price=price.quantize(Decimal("0.01")), + asset=pool.asset + ) +``` + +Use [the `datetime` library](https://docs.python.org/3/library/datetime.html) to format it to a format readable for humans and large language models (LLMs). Use [`Decimal.quantize`](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) to round the value to two decimal places. + +```python +def get_quotes(pool: PoolInfo, start_block: int, end_block: int, step: int) -> list[Quote]: +``` + +In Python you define a [list](https://docs.python.org/3/library/stdtypes.html#typesseq-list) that can only contain a specific type using `list[]`. + +```python + quotes = [] + for block in range(start_block, end_block + 1, step): +``` + +In Python a [`for` loop](https://docs.python.org/3/tutorial/controlflow.html#for-statements) typically iterates over a list. The list of block numbers to find quotes in comes from [`range`](https://docs.python.org/3/library/stdtypes.html#range). + +```python + quote = get_quote(pool, block) + quotes.append(quote) + return quotes +``` + +For each block number, get a `Quote` object and append it to the `quotes` list. Then return that list. + +```python +pool = read_pool(WETHUSDC_ADDRESS) +quotes = get_quotes( + pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) + +pprint(quotes) +``` + +This is the main code of the script. Read the pool information, get twelve quotes, and [`pprint`](https://docs.python.org/3/library/pprint.html#pprint.pprint) them. + +### Creating a prompt {#prompt} + +Next, we need to convert this list of quotes into a prompt for an LLM and obtain an expected future value. + +```sh +git checkout 03-create-prompt +uv run agent.py +``` + +The output is now going to be a prompt to an LLM, similar to: + +``` +Given these quotes: +Asset: WETH/USDC + 2026-01-20T16:34 3016.21 + . + . + . + 2026-02-01T17:49 2299.10 + +Asset: WBTC/WETH + 2026-01-20T16:34 29.84 + . + . + . + 2026-02-01T17:50 33.46 + + +What would you expect the value for WETH/USDC to be at time 2026-02-02T17:56? + +Provide your answer as a single number rounded to two decimal places, +without any other text. +``` + +Notice that there are quotes for two assets here, `WETH/USDC` and `WBTC/WETH`. Adding quotes from another asset might improve the prediction accuracy. + +#### What a prompt looks like {#prompt-explanation} + +This prompt contains three sections, which are pretty common in LLM prompts. + +1. Information. LLMs have a lot of information from their training, but they usually don't have the latest. This is the reason we need to retrieve the latest quotes here. Adding information to a prompt is called [retrieval augmented generation (RAG)](https://en.wikipedia.org/wiki/Retrieval-augmented_generation). + +2. The actual question. This is what we want to know. + +3. Output formatting instructions. Normally, an LLM will give us an estimate with an explanation of how it arrived at it. This is better for humans, but a computer program just needs the bottom line. + +#### Code explanation {#prompt-code} + +Here is the new code. + +```python +from datetime import datetime, timezone, timedelta +``` + +We need to provide the LLM with the time for which we want an estimate. To get a time "n minutes/hours/days" in the future, we use [the `timedelta` class](https://docs.python.org/3/library/datetime.html#datetime.timedelta). + +```python +# The addresses of the pools we're reading +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +WETHWBTC_ADDRESS = Web3.to_checksum_address("0xCBCdF9626bC03E24f779434178A73a0B4bad62eD") +``` + +We have two pools we need to read. + +```python +@dataclass(frozen=True) +class PoolInfo: + . + . + . + reverse: bool = False + + def get_price(self, block: int) -> Decimal: + assert block <= w3.eth.block_number, "Block is in the future" + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 # (token1 per token0) + if self.reverse: + return 1/(raw_price * self.decimal_factor) + else: + return raw_price * self.decimal_factor +``` + +In the WETH/USDC pool, we want to know how many of `token0` (USDC) we need to buy one of `token1` (WETH). In the WETH/WBTC pool, we want to know how many `token1` (WETH) we need to buy one `token0` (WBTC, which is wrapped Bitcoin). We need to track whether the pool’s ratio needs to be reversed. + +```python +def read_pool(address: str, reverse: bool = False) -> PoolInfo: + . + . + . + + return PoolInfo( + . + . + . + + asset= f"{token1.symbol}/{token0.symbol}" if reverse else f"{token0.symbol}/{token1.symbol}", + reverse=reverse + ) +``` + +To know if a pool needs to be reversed, we get to get that as input to `read_pool`. Also, the asset symbol needs to be set up correctly. + +The syntax ` if else ` is the Python equivalent of the [ternary conditional operator](https://en.wikipedia.org/wiki/Ternary_conditional_operator), which in a C-derived language would be ` ? : `. + +```python +def format_quotes(quotes: list[Quote]) -> str: + result = f"Asset: {quotes[0].asset}\n" + for quote in quotes: + result += f"\t{quote.timestamp[0:16]} {quote.price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)}\n" + return result +``` + +This function builds a string that formats a list of `Quote` objects, assuming they all apply to the same asset. + +```python +def make_prompt(quotes: list[list[Quote]], expected_time: str, asset: str) -> str: + return f""" +``` + +In Python [multi-line string literals](https://www.w3schools.com/python/gloss_python_multi_line_strings.asp) are written as `"""` .... `"""`. + +```python +Given these quotes: +{ + functools.reduce(lambda acc, q: acc + '\n' + q, + map(lambda q: format_quotes(q), quotes)) +} +``` + +Here, we use the [MapReduce](https://en.wikipedia.org/wiki/MapReduce) pattern to generate a string for each quote list with `format_quotes`, then reduce them into a single string for use in the prompt. + +```python +What would you expect the value for {asset} to be at time {expected_time}? + +Provide your answer as a single number rounded to two decimal places, +without any other text. + """ +``` + +The rest of the prompt is as expected. + +```python +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +Review the two pools and obtain quotes from both. + +```python +future_time = (datetime.now(timezone.utc) + timedelta(days=1)).isoformat()[0:16] + +print(make_prompt(wethusdc_quotes + wethwbtc_quotes, future_time, wethusdc_pool.asset)) +``` + +Determine the future time point for which we want the estimate, and create the prompt. + +### Interfacing with an LLM {#interface-llm} + +Next, we prompt an actual LLM and receive an expected future value. I wrote this program using OpenAI, so if you want to use a different provider, you'll need to adjust it. + +1. Get an [OpenAI account](https://auth.openai.com/create-account) + +2. [Fund the account](https://platform.openai.com/settings/organization/billing/overview)—the minimum amount at the time of writing is $5 + +3. [Create an API key](https://platform.openai.com/settings/organization/api-keys) + +4. In the command line, export the API key so your program can use it + + ```sh + export OPENAI_API_KEY=sk- + ``` + +5. Checkout and run the agent + + ```sh + git checkout 04-interface-llm + uv run agent.py + ``` + +Here is the new code. + +```python +from openai import OpenAI + +open_ai = OpenAI() # The client reads the OPENAI_API_KEY environment variable +``` + +Import and instantiate the OpenAI API. + +```python +response = open_ai.chat.completions.create( + model="gpt-4-turbo", + messages=[ + {"role": "user", "content": prompt} + ], + temperature=0.0, + max_tokens=16, +) +``` + +Call the OpenAI API (`open_ai.chat.completions.create`) to create the response. + +```python +expected_price = Decimal(response.choices[0].message.content.strip()) +current_price = wethusdc_quotes[-1].price + +print ("Current price:", wethusdc_quotes[-1].price) +print(f"In {future_time}, expected price: {expected_price} USD") + +if (expected_price > current_price): + print(f"Buy, I expect the price to go up by {expected_price - current_price} USD") +else: + print(f"Sell, I expect the price to go down by {current_price - expected_price} USD") +``` + +Output the price and provide a buy or sell recommendation. + +#### Testing the predictions {#testing-the-predictions} + +Now that we can generate predictions, we can also use historical data to assess whether we produce useful predictions. + +```sh +uv run test-predictor.py +``` + +The expected result is similar to: + +``` +Prediction for 2026-01-05T19:50: predicted 3138.93 USD, real 3218.92 USD, error 79.99 USD +Prediction for 2026-01-06T19:56: predicted 3243.39 USD, real 3221.08 USD, error 22.31 USD +Prediction for 2026-01-07T20:02: predicted 3223.24 USD, real 3146.89 USD, error 76.35 USD +Prediction for 2026-01-08T20:11: predicted 3150.47 USD, real 3092.04 USD, error 58.43 USD +. +. +. +Prediction for 2026-01-31T22:33: predicted 2637.73 USD, real 2417.77 USD, error 219.96 USD +Prediction for 2026-02-01T22:41: predicted 2381.70 USD, real 2318.84 USD, error 62.86 USD +Prediction for 2026-02-02T22:49: predicted 2234.91 USD, real 2349.28 USD, error 114.37 USD +Mean prediction error over 29 predictions: 83.87103448275862068965517241 USD +Mean change per recommendation: 4.787931034482758620689655172 USD +Standard variance of changes: 104.42 USD +Profitable days: 51.72% +Losing days: 48.28% +``` + +Most of the tester is identical to the agent, but here are the parts that are new or modified. + +```python +CYCLES_FOR_TEST = 40 # For the backtest, how many cycles we test over + +# Get lots of quotes +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +We look at `CYCLES_FOR_TEST` (specified as 40 here) days back. + +```python +# Create predictions and check them against real history + +total_error = Decimal(0) +changes = [] +``` + +There are two types of errors we are interested in. The first, `total_error`, is simply the sum of errors the predictor made. + +To understand the second, `changes`, we need to remember the agent's purpose. It's not to predict the WETH/USDC ratio (ETH price). It's to issue sell and buy recommendations. If the price is currently $2000 and it predicts $2010 tomorrow, we don't mind if the actual result is $2020 and we earn extra money. But we _do_ mind if it predicted $2010, and bought ETH based on that recommendation, and the price drops to $1990. + +```python +for index in range(0,len(wethusdc_quotes)-CYCLES_BACK): +``` + +We can only look at cases where the complete history (the values used for the prediction and the real-world value to compare it to) is available. This means the newest case must be the one that started `CYCLES_BACK` ago. + +```python + wethusdc_slice = wethusdc_quotes[index:index+CYCLES_BACK] + wethwbtc_slice = wethwbtc_quotes[index:index+CYCLES_BACK] +``` + +Use [slices](https://www.w3schools.com/python/ref_func_slice.asp) to get the same number of samples as the number the agent uses. The code between here and the next segment is the same get-a-prediction code we have in the agent. + +```python + predicted_price = Decimal(response.choices[0].message.content.strip()) + real_price = wethusdc_quotes[index+CYCLES_BACK].price + prediction_time_price = wethusdc_quotes[index+CYCLES_BACK-1].price +``` + +Get the predicted price, the real price, and the price at the time of the prediction. We need the price at the time of the prediction to determine whether the recommendation was to buy or sell. + +```python + error = abs(predicted_price - real_price) + total_error += error + print (f"Prediction for {prediction_time}: predicted {predicted_price} USD, real {real_price} USD, error {error} USD") +``` + +Figure the error, and add it to the total. + +```python + recomended_action = 'buy' if predicted_price > prediction_time_price else 'sell' + price_increase = real_price - prediction_time_price + changes.append(price_increase if recomended_action == 'buy' else -price_increase) +``` + +For `changes`, we want the monetary impact of buying or selling one ETH. So first, we need to determine the recommendation, then assess how the actual price changed, and whether the recommendation made money (positive change) or cost money (negative change). + +```python +print (f"Mean prediction error over {len(wethusdc_quotes)-CYCLES_BACK} predictions: {total_error / Decimal(len(wethusdc_quotes)-CYCLES_BACK)} USD") + +length_changes = Decimal(len(changes)) +mean_change = sum(changes, Decimal(0)) / length_changes +print (f"Mean change per recommendation: {mean_change} USD") +var = sum((x - mean_change) ** 2 for x in changes) / length_changes +print (f"Standard variance of changes: {var.sqrt().quantize(Decimal("0.01"))} USD") +``` + +Report the results. + +```python +print (f"Profitable days: {len(list(filter(lambda x: x > 0, changes)))/length_changes:.2%}") +print (f"Losing days: {len(list(filter(lambda x: x < 0, changes)))/length_changes:.2%}") +``` + +Use [`filter`](https://www.w3schools.com/python/ref_func_filter.asp) to count the number of profitable days and the number of costly days. The result is a filter object, which we need to convert to a list to get the length. + +### Submitting transactions {#submit-txn} + +Now we need to actually submit transactions. However, I don't want to spend real money at this point, before the system is proven. Instead, we will create a local fork of mainnet, and "trade" on that network. + +Here are the steps to create a local fork and enable trading. + +1. Install [Foundry](https://getfoundry.sh/introduction/installation) + +2. Start [`anvil`](https://getfoundry.sh/anvil/overview) + + ```sh + anvil --fork-url https://eth.drpc.org --block-time 12 + ``` + + `anvil` is listening on the default URL for Foundry, http://localhost:8545, so we don't need to specify the URL for [the `cast` command](https://getfoundry.sh/cast/overview) we use to manipulate the blockchain. + +3. When running in `anvil`, there are ten test accounts that have ETH—set the environment variables for the first one + + ```sh + PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ADDRESS=`cast wallet address $PRIVATE_KEY` + ``` + +4. These are the contracts we need to use. [`SwapRouter`](https://github.com/Uniswap/v3-periphery/blob/main/contracts/SwapRouter.sol) is the Uniswap v3 contract we use to actually trade. We could trade directly through the pool, but this is much easier. + + The two bottom variables are the Uniswap v3 paths required to swap between WETH and USDC. + + ```sh + WETH_ADDRESS=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + USDC_ADDRESS=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + POOL_ADDRESS=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 + SWAP_ROUTER=0xE592427A0AEce92De3Edee1F18E0157C05861564 + WETH_TO_USDC=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + USDC_TO_WETH=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + ``` + +5. Each of the test accounts has 10,000 ETH. Use the WETH contract to wrap 1000 ETH to obtain 1000 WETH for trading. + + ```sh + cast send $WETH_ADDRESS "deposit()" --value 1000ether --private-key $PRIVATE_KEY + ``` + +6. Use `SwapRouter` to trade 500 WETH for USDC. + + ```sh + cast send $WETH_ADDRESS "approve(address,uint256)" $SWAP_ROUTER 500ether --private-key $PRIVATE_KEY + MAXINT=`cast max-int uint256` + cast send $SWAP_ROUTER \ + "exactInput((bytes,address,uint256,uint256,uint256))" \ + "($WETH_TO_USDC,$ADDRESS,$MAXINT,500ether,1000000)" \ + --private-key $PRIVATE_KEY + ``` + + The `approve` call creates an allowance that allows `SwapRouter` to spend some of our tokens. Contracts cannot monitor events, so if we transfer tokens directly to the `SwapRouter` contract, it wouldn't know it was paid. Instead, we permit the `SwapRouter` contract to spend a certain amount, and then `SwapRouter` does it. This is done through a function called by `SwapRouter`, so it knows if it was successful. + +7. Verify you have enough of both tokens. + + ```sh + cast call $WETH_ADDRESS "balanceOf(address)" $ADDRESS | cast from-wei + echo `cast call $USDC_ADDRESS "balanceOf(address)" $ADDRESS | cast to-dec`/10^6 | bc + ``` + +Now that we have WETH and USDC, we can actually run the agent. + +```sh +git checkout 05-trade +uv run agent.py +``` + +The output will look similar to: + +``` +(ai-trading-agent) qbzzt@Ori-Cloudnomics:~/260215-ai-agent$ uv run agent.py +Current price: 1843.16 +In 2026-02-06T23:07, expected price: 1724.41 USD +Account balances before trade: +USDC Balance: 927301.578272 +WETH Balance: 500 +Sell, I expect the price to go down by 118.75 USD +Approve transaction sent: 74e367ddbb407c1aaf567d87aa5863049991b1d2aa092b6b85195d925e2bd41f +Approve transaction mined. +Sell transaction sent: fad1bcf938585c9e90364b26ac7a80eea9efd34c37e5db81e58d7655bcae28bf +Sell transaction mined. +Account balances after trade: +USDC Balance: 929143.797116 +WETH Balance: 499 +``` + +To actually use it, you need a few minor changes. + +- In line 14, change `MAINNET_URL` to a real access point, such as `https://eth.drpc.org` +- In line 28, change `PRIVATE_KEY` to your own private key +- Unless you are very wealthy and can buy or sell 1 ETH each day for an unproven agent, you might want to change 29 to decrease `WETH_TRADE_AMOUNT` + +#### Code explanation {#trading-code} + +Here is the new code. + +```python +SWAP_ROUTER_ADDRESS=Web3.to_checksum_address("0xE592427A0AEce92De3Edee1F18E0157C05861564") +WETH_TO_USDC=bytes.fromhex("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") +USDC_TO_WETH=bytes.fromhex("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +``` + +The same variables we used in step 4. + +```python +WETH_TRADE_AMOUNT=1 +``` + +The amount to trade. + +```python +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... }, + { "name": "balanceOf", ...}, + { "name": "approve", ...} +] +``` + +To actually trade, we need the `approve` function. We also want to show balances before and after, so we also need `balanceOf`. + +```python +SWAP_ROUTER_ABI = [ + { "name": "exactInput", ...}, +] +``` + +In the `SwapRouter` ABI we just need `exactInput`. There is a related function, `exactOutput`, we could use to buy exactly one WETH, but for simplicity we just use `exactInput` in both cases. + +```python +account = w3.eth.account.from_key(PRIVATE_KEY) +swap_router = w3.eth.contract( + address=SWAP_ROUTER_ADDRESS, + abi=SWAP_ROUTER_ABI +) +``` + +The Web3 definitions for the [`account`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html) and the `SwapRouter` contract. + +```python +def txn_params() -> dict: + return { + "from": account.address, + "value": 0, + "gas": 300000, + "nonce": w3.eth.get_transaction_count(account.address), + } +``` + +The transaction parameters. We need a function here because [the nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) must change each time. + +```python +def approve_token(contract: Contract, amount: int): +``` + +Approve a token allowance for `SwapRouter`. + +```python + txn = contract.functions.approve(SWAP_ROUTER_ADDRESS, amount).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) +``` + +This is how we send a transaction in Web3. First we use [the `Contract` object](https://web3py.readthedocs.io/en/stable/web3.contract.html) to build the transaction. Then we use [`web3.eth.account.sign_transaction`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-contract-transaction) to sign the transaction, using `PRIVATE_KEY`. Finally, we use [`w3.eth.send_raw_transaction`](https://web3py.readthedocs.io/en/stable/transactions.html#chapter-2-w3-eth-send-raw-transaction) to send the transaction. + +```python + print(f"Approve transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Approve transaction mined.") +``` + +[`w3.eth.wait_for_transaction_receipt`](https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.wait_for_transaction_receipt) waits until the transaction is mined. It returns the receipt if needed. + +```python +SELL_PARAMS = { + "path": WETH_TO_USDC, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": WETH_TRADE_AMOUNT * 10 ** wethusdc_pool.token1.decimals, + "amountOutMinimum": 0, +} +``` + +These are the parameters when selling WETH. + +```python +def make_buy_params(quote: Quote) -> dict: + return { + "path": USDC_TO_WETH, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": int(quote.price*WETH_TRADE_AMOUNT) * 10**wethusdc_pool.token0.decimals, + "amountOutMinimum": 0, + } +``` + +In contrast to `SELL_PARAMS`, the buy parameters can change. The input amount is the cost of 1 WETH, as available in `quote`. + +```python +def buy(quote: Quote): + buy_params = make_buy_params(quote) + approve_token(wethusdc_pool.token0.contract, buy_params["amountIn"]) + txn = swap_router.functions.exactInput(buy_params).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Buy transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Buy transaction mined.") + + +def sell(): + approve_token(wethusdc_pool.token1.contract, + WETH_TRADE_AMOUNT * 10**wethusdc_pool.token1.decimals) + txn = swap_router.functions.exactInput(SELL_PARAMS).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Sell transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Sell transaction mined.") +``` + +The `buy()` and `sell()` functions are nearly identical. First we approve a sufficient allowance for `SwapRouter`, and then we call it with the correct path and amount. + +```python +def balances(): + token0_balance = wethusdc_pool.token0.contract.functions.balanceOf(account.address).call() + token1_balance = wethusdc_pool.token1.contract.functions.balanceOf(account.address).call() + + print(f"{wethusdc_pool.token0.symbol} Balance: {Decimal(token0_balance) / Decimal(10 ** wethusdc_pool.token0.decimals)}") + print(f"{wethusdc_pool.token1.symbol} Balance: {Decimal(token1_balance) / Decimal(10 ** wethusdc_pool.token1.decimals)}") +``` + +Report user balances in both currencies. + +```python +print("Account balances before trade:") +balances() + +if (expected_price > current_price): + print(f"Buy, I expect the price to go up by {expected_price - current_price} USD") + buy(wethusdc_quotes[-1]) +else: + print(f"Sell, I expect the price to go down by {current_price - expected_price} USD") + sell() + +print("Account balances after trade:") +balances() +``` + +This agent currently only works once. However, you can change it to work continuously either by running it from [`crontab`](https://man7.org/linux/man-pages/man1/crontab.1.html) or by wrapping lines 368-400 in a loop and using [`time.sleep`](https://docs.python.org/3/library/time.html#time.sleep) to wait until it is time for the next cycle. + +## Possible improvements {#improvements} + +This is not a full production version; it is merely an example to teach the basics. Here are some ideas for improvements. + +### Smarter trading {#smart-trading} + +There are two important facts the agent ignores when deciding what to do. + +- _The magnitude of anticipated change_. The agent sells a fixed amount of `WETH` if the price is expected to decline, regardless of the magnitude of the decline. + Arguably, it would be better to ignore minor changes and sell based on how much we expect the price to decline. +- _The current portfolio_. If 10% of your portfolio is in WETH and you think the price will go up, it probably makes sense to buy more. But if 90% of your portfolio is in WETH, you may be sufficiently exposed, and there is no need to buy more. The reverse is true if you expect the price to go down. + +### What if you want to keep your trading strategy a secret? {#secret} + +AI vendors can see the queries you send to their LLMs, which could expose the genius trading system you developed with your agent. A trading system that too many people use is worthless because too many people try to buy when you want to buy (and the price goes up) and try to sell when you want to sell (and the price goes down). + +You can run an LLM locally, for example, using [LM-Studio](https://lmstudio.ai/), to avoid this problem. + +### From AI bot to AI agent {#bot-to-agent} + +You can make a good case that this is [an AI bot, not an AI agent](/ai-agents/#ai-agents-vs-ai-bots). It implements a relatively simple strategy that relies on predefined information. We can enable self-improvement, for example, by providing a list of Uniswap v3 pools and their latest values and asking which combination has the best predictive value. + +### Slippage protection {#slippage-protection} + +Currently there is no [slippage protection](https://uniswapv3book.com/milestone_3/slippage-protection.html). If the current quote is $2000, and the expected price is $2100, the agent will buy. However, if before the agent buys the cost rises to $2200, it makes no sense to buy anymore. + +To implement slippage protection, specify an `amountOutMinimum` value in lines 325 and 334 of [`agent.py`](https://github.com/qbzzt/260215-ai-agent/blob/05-trade/agent.py#L325). + +## Fazit {#conclusion} + +Hopefully, now you know enough to get started with AI agents. This is not a comprehensive overview of the subject; there are whole books dedicated to that, but this is enough to get you started. Viel Erfolg! + +[Hier finden Sie mehr von meiner Arbeit](https://cryptodocguy.pro/). diff --git a/public/content/translations/de/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md b/public/content/translations/de/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md index f3ef6b9c6b3..9f61d452c14 100644 --- a/public/content/translations/de/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md +++ b/public/content/translations/de/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md @@ -62,13 +62,13 @@ Dies liefert die gleichen Informationen wie auf der Transaktionsseite von Ethers #### Etherscan {#etherscan} -![](./etherscan_view.png) +![Screenshot der Etherscan-Transaktions-Explorer-Ansicht](./etherscan_view.png) [Vertragsseite der EF auf Blockscout.](https://eth.blockscout.com/address/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe) #### Dune Analytics {#dune-analytics} -![](./dune_view.png) +![Screenshot eines Dune Analytics-Abfrage-Dashboards](./dune_view.png) Das Dashboard finden Sie [hier](https://dune.com/paulapivat/Learn-Ethereum). Klicken Sie auf die Tabelle, um die Abfrage zu sehen (siehe auch oben). @@ -146,7 +146,7 @@ ORDER BY block_time DESC` Hier ist die SQL-Ausgabe auf Dune: -![](./list_of_txn.png) +![Screenshot einer Liste von Ethereum-Transaktionen](./list_of_txn.png) Dieser einzelne Block, der der Chain hinzugefügt wird, ändert den Zustand der Ethereum Virtual Machine ([EVM](/developers/docs/evm/)). Dutzende, manchmal Hunderte von Transaktionen werden auf einmal verifiziert. In diesem speziellen Fall waren 222 Transaktionen enthalten. @@ -165,7 +165,7 @@ FROM temp_table Für Block 12396854 wurden von insgesamt 222 Transaktionen 204 erfolgreich verifiziert: -![](./successful_txn.png) +![Screenshot einer erfolgreichen Ethereum-Transaktion](./successful_txn.png) Transaktionsanfragen kommen Dutzende Male pro Sekunde vor, aber Blöcke werden etwa alle 15 Sekunden committet ([Quelle](/developers/docs/blocks/)). @@ -173,11 +173,11 @@ Um zu sehen, dass ungefähr alle 15 Sekunden ein Block produziert wird, können Das Diagramm der täglich erzeugten Ethereum-Blöcke (2016 – heute) ist: -![](./daily_blocks.png) +![Diagramm, das die tägliche Ethereum-Blockproduktion zeigt](./daily_blocks.png) Die durchschnittliche Anzahl der in diesem Zeitraum täglich produzierten Blöcke beträgt ~5.874: -![](./avg_daily_blocks.png) +![Diagramm, das die tägliche Ethereum-Blockproduktion zeigt](./avg_daily_blocks.png) Die Abfragen lauten: @@ -214,7 +214,7 @@ Blöcke sind in ihrer Größe begrenzt. Die maximale Blockgröße ist dynamisch Eine Möglichkeit, sich das Block-Gaslimit vorzustellen, ist, es als das **Angebot** an verfügbarem Blockspace zu betrachten, in dem Transaktionen gebündelt werden. Das Block-Gaslimit kann von 2016 bis heute abgefragt und visualisiert werden: -![](./avg_gas_limit.png) +![Diagramm, das das durchschnittliche Ethereum-Gaslimit im Zeitverlauf zeigt](./avg_gas_limit.png) ```sql SELECT @@ -227,7 +227,7 @@ OFFSET 1 Dann gibt es das tatsächlich täglich verwendete Gas, um für Berechnungen auf der Ethereum-Chain zu bezahlen (d. h. das Senden von Transaktionen, das Aufrufen eines Smart Contracts, das Prägen eines NFT). Dies ist die **Nachfrage** nach verfügbarem Ethereum-Blockspace: -![](./daily_gas_used.png) +![Diagramm, das den täglichen Ethereum-Gasverbrauch zeigt](./daily_gas_used.png) ```sql SELECT @@ -246,7 +246,7 @@ Daher können wir Gaspreise als eine Funktion der Nachfrage nach Ethereum-Blocks Schließlich möchten wir vielleicht die durchschnittlichen täglichen Gaspreise für die Ethereum-Chain abfragen. Dies würde jedoch zu einer besonders langen Abfragezeit führen, also filtern wir unsere Abfrage auf die durchschnittliche Gasmenge, die von der Ethereum Foundation pro Transaktion bezahlt wird. -![](./ef_daily_gas.png) +![Diagramm, das den täglichen Gasverbrauch der Ethereum Foundation zeigt](./ef_daily_gas.png) Wir können die Gaspreise sehen, die über die Jahre für alle an die Adresse der Ethereum Foundation getätigten Transaktionen gezahlt wurden. Hier ist die Abfrage: diff --git a/public/content/translations/de/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md b/public/content/translations/de/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md index 5d3ac6b05f7..5b671c6d3be 100644 --- a/public/content/translations/de/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md +++ b/public/content/translations/de/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md @@ -117,35 +117,35 @@ sudo systemctl start grafana-server Wenn Grafana läuft, sollte es unter `localhost:3000` erreichbar sein. Verwenden Sie Ihren bevorzugten Browser, um auf diesen Pfad zuzugreifen, und melden Sie sich dann mit den Standard-Anmeldeinformationen an (Benutzer: `admin` und Passwort: `admin`). Wenn Sie dazu aufgefordert werden, ändern Sie das Standardpasswort und speichern Sie es. -![](./grafana1.png) +![Screenshot des Grafana-Dashboards für die Geth-Überwachung (Panel 1)](./grafana1.png) Sie werden zur Grafana-Startseite weitergeleitet. Richten Sie zunächst Ihre Quelldaten ein. Klicken Sie auf das Konfigurationssymbol in der linken Leiste und wählen Sie "Datenquellen" aus. -![](./grafana2.png) +![Screenshot des Grafana-Dashboards für die Geth-Überwachung (Panel 2)](./grafana2.png) Es sind noch keine Datenquellen erstellt worden. Klicken Sie auf "Datenquelle hinzufügen", um eine zu definieren. -![](./grafana3.png) +![Screenshot des Grafana-Dashboards für die Geth-Überwachung (Panel 3)](./grafana3.png) Wählen Sie für dieses Setup "InfluxDB" aus und fahren Sie fort. -![](./grafana4.png) +![Screenshot des Grafana-Dashboards für die Geth-Überwachung (Panel 4)](./grafana4.png) Die Konfiguration der Datenquelle ist ziemlich einfach, wenn Sie die Tools auf demselben Rechner ausführen. Sie müssen die InfluxDB-Adresse und die Details für den Zugriff auf die Datenbank festlegen. Beachten Sie die Abbildung unten. -![](./grafana5.png) +![Screenshot des Grafana-Dashboards für die Geth-Überwachung (Panel 5)](./grafana5.png) Wenn alles vollständig ist und InfluxDB erreichbar ist, klicken Sie auf "Speichern und testen" und warten Sie, bis die Bestätigung erscheint. -![](./grafana6.png) +![Screenshot des Grafana-Dashboards für die Geth-Überwachung (Panel 6)](./grafana6.png) Grafana ist jetzt so eingerichtet, dass es Daten aus InfluxDB lesen kann. Jetzt müssen Sie ein Dashboard erstellen, das sie interpretiert und anzeigt. Dashboard-Eigenschaften sind in JSON-Dateien kodiert, die von jedermann erstellt und einfach importiert werden können. Klicken Sie in der linken Leiste auf "Erstellen und Importieren". -![](./grafana7.png) +![Screenshot des Grafana-Dashboards für die Geth-Überwachung (Panel 7)](./grafana7.png) Für ein Geth-Überwachungs-Dashboard kopieren Sie die ID von [diesem Dashboard](https://grafana.com/grafana/dashboards/13877/) und fügen Sie sie auf der "Importseite" in Grafana ein. Nach dem Speichern des Dashboards sollte es so aussehen: -![](./grafana8.png) +![Screenshot des Grafana-Dashboards für die Geth-Überwachung (Panel 8)](./grafana8.png) Sie können Ihre Dashboards ändern. Jedes Panel kann bearbeitet, verschoben, entfernt oder hinzugefügt werden. Sie können Ihre Konfigurationen ändern. Es liegt ganz bei Ihnen! Um mehr darüber zu erfahren, wie Dashboards funktionieren, lesen Sie die [Dokumentation von Grafana](https://grafana.com/docs/grafana/latest/dashboards/). Sie könnten auch an [Alerting](https://grafana.com/docs/grafana/latest/alerting/) interessiert sein. Damit können Sie Warnmeldungen für den Fall einrichten, dass Metriken bestimmte Werte erreichen. Verschiedene Kommunikationskanäle werden unterstützt. diff --git a/public/content/translations/es/community/support/faq/index.md b/public/content/translations/es/community/support/faq/index.md new file mode 100644 index 00000000000..d0d0a9585b6 --- /dev/null +++ b/public/content/translations/es/community/support/faq/index.md @@ -0,0 +1,77 @@ +--- +title: "Preguntas más frecuentes" +description: "Preguntas comunes sobre Ethereum acerca de billeteras, transacciones, staking y más." +lang: es +--- + +# Preguntas frecuentes {#faq} + +## Envié criptomonedas a la dirección equivocada {#wrong-wallet} + +Una transacción enviada en Ethereum es irreversible. Lamentablemente, si envió ETH o tokens a la billetera equivocada, no hay manera de revertir la transacción. + +**Qué puede hacer:** + +- **Si conoce al propietario de la dirección**, póngase en contacto con él directamente y pídale que le devuelva los fondos. +- **Si la dirección pertenece a un intercambio o a un servicio conocido**, póngase en contacto con su equipo de soporte, ya que es posible que puedan ayudarle. +- **Si envió tokens a la dirección de un contrato**, compruebe si el contrato tiene una función de retiro o recuperación (esto es poco frecuente). + +En la mayoría de los casos, no hay forma de recuperar los fondos. Ethereum no es propiedad de ninguna organización, entidad o persona central, lo que significa que nadie puede revertir las transacciones. Compruebe siempre dos veces la dirección del destinatario antes de confirmar. + +## Perdí el acceso a mi billetera {#lost-wallet-access} + +Sus opciones de recuperación dependen del tipo de billetera que utilice. + +### Si tiene su frase semilla (frase de recuperación) + +Puede restaurar su billetera en cualquier aplicación de billetera compatible usando su frase semilla. Por eso es fundamental que guarde su frase semilla de forma segura y sin conexión. Consulte la documentación de su proveedor de billetera para obtener instrucciones de restauración. + +### Si ha perdido su frase semilla + +Sin su frase semilla o claves privadas, no se pueden recuperar sus fondos. Nadie, incluido ethereum.org, puede restablecer su contraseña ni restaurar el acceso a una billetera de autocustodia. + +### Si su cuenta está en un intercambio + +Si su cuenta está en un intercambio centralizado como Coinbase, Binance o Kraken, póngase en contacto directamente con el equipo de soporte del intercambio. Ellos controlan las cuentas en su plataforma y es posible que puedan ayudarle con el restablecimiento de la contraseña o la recuperación de la cuenta. + + + + + + +**Nunca comparta su frase semilla con nadie** que afirme ayudarle a recuperar su billetera. Esta es una de las tácticas de estafa más comunes. Ningún servicio legítimo le pedirá nunca su frase semilla. + + + + + + Cómo usar una billetera + + +## Mi transacción está atascada o pendiente {#stuck-transaction} + +Las transacciones en Ethereum pueden atascarse cuando la tarifa de gas que estableció es más baja de lo que la red requiere actualmente. La mayoría de las billeteras le permiten solucionar este problema: + +- **Acelerar:** Vuelva a enviar la misma transacción con una tarifa de gas más alta +- **Cancelar:** Envíe una transacción de 0 ETH a su propia dirección utilizando el mismo nonce que la transacción pendiente + +### Guías útiles + +- [Cómo acelerar o cancelar una transacción pendiente en MetaMask](https://support.metamask.io/transactions-and-gas/transactions/how-to-speed-up-or-cancel-a-pending-transaction/) +- [Cómo cancelar transacciones pendientes de Ethereum](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) + +## ¿Cómo puedo reclamar mi regalo en Ethereum? {#giveaway-scam} + +Los regalos de Ethereum son estafas diseñadas para robarle ETH. No se deje tentar por ofertas que parezcan demasiado buenas para ser verdad. Si envía ETH a una dirección de regalo, no recibirá el regalo y no podrá recuperar sus fondos. + +[Más sobre prevención de estafas](/security/#common-scams) + +## ¿Cómo hago staking de ETH? {#how-to-stake} + +Para convertirse en validador, debe hacer staking de 32 ETH en el contrato de depósito de Ethereum y configurar un nodo de validación. También puede participar con menos ETH a través de pools de staking. + +Hay más información disponible en nuestras [páginas de staking](/staking/) y en [el launchpad de staking](https://launchpad.ethereum.org/). + +## ¿Cómo puedo minar Ethereum? {#mining-ethereum} + +Ya no se puede minar en Ethereum. La minería se desactivó cuando Ethereum pasó de [prueba de trabajo](/glossary/#pow) a [prueba de participación](/glossary/#pos) durante [la Fusión](/roadmap/merge/) en septiembre de 2022. Ahora, en lugar de mineros, Ethereum tiene validadores. Cualquier persona puede [hacer staking](/glossary/#staking) de ETH y recibir recompensas por staking al ejecutar software validador para asegurar la red. diff --git a/public/content/translations/es/community/support/index.md b/public/content/translations/es/community/support/index.md deleted file mode 100644 index bbfe77e5c18..00000000000 --- a/public/content/translations/es/community/support/index.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: "Soporte técnico de Ethereum" -description: "Explicación de cómo obtener soporte técnico en el ecosistema Ethereum." -lang: es ---- - -# Soporte de Ethereum {#support} - -## Soporte oficial de Ethereum {#official-support} - -¿Está buscando el soporte técnico oficial de Ethereum? Lo primero que debe saber es que Ethereum está descentralizado. Eso significa que carece de organización centra y que ninguna entidad ni persona es dueña de Ethereum. Por lo tanto, no existen canales de soporte oficiales. - -Comprender la naturaleza descentralizada de Ethereum es vital porque **¡cualquiera que afirme ser soporte oficial de Ethereum probablemente intenta estafarle!** La mejor protección contra estafadores es informarse y tomar la seguridad en serio. - - - Seguridad en Ethereum y prevención de estafas - - - - Aprenda los fundamentos de Ethereum - - -A pesar de la falta de apoyo oficial, muchos grupos, comunidades y proyectos en todo el ecosistema Ethereum están deseosos de ayudar, y puede encontrar mucha información y recursos útiles en esta página. ¿Todavía le surgen algunas preguntas? Únase al [Discord de ethereum.org](https://discord.gg/ethereum-org), e intentaremos ayudarle. - -## Preguntas frecuentes {#faq} - -### He enviado ETH a la billetera equivocada {#wrong-wallet} - -Una transacción enviada en Ethereum es irreversible. Desafortunadamente, si ha enviado ETH a la cartera equivocada, no hay forma de recuperar esos fondos. Debido a que no existe organización central, ni ninguna entidad ni persona al frente de Ethereum, nadie puede revertir las transacciones. Por lo tanto, es vital comprobar siempre sus transacciones antes de enviarlas. - -### ¿Cómo puedo reclamar mi regalo en Ethereum? {#giveaway-scam} - -Los regalos de Ethereum son estafas diseñadas para robarle ETH. No se deje tentar por ofertas que parezcan demasiado buenas para ser verdad, si envía ETH a una dirección de regalo, no recibirá ningún ningún regalo, ni tampoco podrá recuperar sus fondos. - -[Más sobre prevención de estafas](/security/#common-scams) - -### Mi transacción está atascada {#stuck-transaction} - -Debido a la demanda de la red, las transacciones en Ethereum pueden a veces estancarse si ha pagado una comisión de la transacción inferior a la requerida. Muchas carteras proporcionan una opción para volver a enviar la misma transacción con una comisión de transacción más elevada y así poder procesar la transacción. Otra alternativa es cancelar una transacción pendiente enviando una transacción a su propia dirección y utilizando el mismo nonce que la transacción pendiente. - -[Cómo acelerar o cancelar una transacción pendiente en MetaMask](https://metamask.zendesk.com/hc/en-us/articles/360015489251-How-to-speed-up-or-cancel-a-pending-transaction) - -[Cómo cancelar transacciones pendientes de Ethereum](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) - -### ¿Cómo puedo minar Ethereum? {#mining-ethereum} - -Ya no se puede minar en Ethereum. La minería se desactivó cuando Ethereum pasó de [proof-of-work](/glossary/#pow) a [proof-of-stake](/glossary/#pos). Ahora, en lugar de mineros, Ethereum tiene validadores. Cualquier persona puede [hacer staking](/glossary/#staking) de ETH y recibir recompensas por staking al ejecutar software validador para asegurar la red. - -### ¿Cómo me convierto en staker/ejecuto un validador? {#how-to-stake} - -Para convertirse en validador, debe apostar 32 ETH en el contrato de depósito de Ethereum y configurar un nodo de validación. Hay más información disponible en nuestras [páginas de staking](/staking) y en [el staking launchpad](https://launchpad.ethereum.org/). - -## Construyendo dapps {#building-support} - -Crear puede ser difícil. A continuación, le indicamos algunos espacios centrados en el desarrollo con experimentados desarrolladores de Ethereum que estarán dispuestos a ayudarle. - -- [Alchemy University](https://university.alchemy.com/#starter_code) -- [CryptoDevs discord](https://discord.com/invite/5W5tVb3) -- [Ethereum StackExchange](https://ethereum.stackexchange.com/) -- [Web3 University](https://www.web3.university/) -- [LearnWeb3](https://discord.com/invite/learnweb3) - -También puede encontrar documentación y guías de desarrollo en nuestra sección de [recursos para desarrolladores de Ethereum](/developers/). - -### Herramientas {#dapp-tooling} - -¿Su pregunta se refiere a una herramienta, proyecto o biblioteca en particular? La mayoría de los proyectos tienen servidores de chat o foros destinados a ayudarle. - -He aquí algunos ejemplos: - -- [Solidity](https://app.element.io/#/room/#solidity:matrix.org) -- [ethers.js](https://discord.gg/6jyGVDK6Jx) -- [web3.js](https://discord.gg/GsABYQu4sC) -- [Hardhat](https://discord.gg/xtrMGhmbfZ) -- [Alchemy](http://alchemy.com/discord) -- [Tenderly](https://discord.gg/fBvDJYR) - -## Ejecutar un nodo {#node-support} - -Si está ejecutando un nodo o validador, estas son algunas comunidades dedicadas a ayudar a los usuarios en sus comienzos. - -- [EthStaker discord](https://discord.gg/ethstaker) -- [EthStaker reddit](https://www.reddit.com/r/ethstaker) - -La mayoría de los equipos que se encargan de la creación de clientes de Ethereum también cuentan con espacios especializados, orientados al público, en los que se puede obtener ayuda y hacer preguntas. - -### Clientes de ejecución {#execution-clients} - -- [Geth](https://discord.gg/FqDzupGyYf) -- [Nethermind](https://discord.gg/YJx3pm8z5C) -- [Besu](https://discord.gg/p8djYngzKN) -- [Erigon](https://github.com/ledgerwatch/erigon/issues) -- [Reth](https://github.com/paradigmxyz/reth/discussions) - -### Clientes de consenso {#consensus-clients} - -- [Prysm](https://discord.gg/prysmaticlabs) -- [Nimbus](https://discord.gg/nSmEH3qgFv) -- [Lighthouse](https://discord.gg/cyAszAh) -- [Teku](https://discord.gg/7hPv2T6) -- [Lodestar](https://discord.gg/aMxzVcr) -- [Grandine](https://discord.gg/H9XCdUSyZd) - -También puede [aprender cómo ejecutar un nodo aquí](/developers/docs/nodes-and-clients/run-a-node/). diff --git a/public/content/translations/es/community/support/misconceptions/index.md b/public/content/translations/es/community/support/misconceptions/index.md new file mode 100644 index 00000000000..eca77334ae5 --- /dev/null +++ b/public/content/translations/es/community/support/misconceptions/index.md @@ -0,0 +1,73 @@ +--- +title: "Conceptos erróneos comunes sobre Ethereum" +description: "Aclarando los malentendidos más comunes sobre cómo funciona Ethereum." +lang: es +--- + +# Conceptos erróneos comunes sobre Ethereum {#misconceptions} + +## ¿Es Ethereum una empresa? {#not-a-company} + +Ethereum es una tecnología descentralizada de código abierto mantenida por miles de colaboradores en todo el mundo. No existe ninguna empresa llamada "Ethereum" que gestione cuentas, retenga fondos o preste atención al cliente. + +La [Fundación Ethereum](https://ethereum.foundation/) es una organización sin fines de lucro que apoya el desarrollo de Ethereum, pero no es propietaria ni controla la red. Ninguna entidad lo hace. + +**[ethereum.org](/)** es un recurso educativo gestionado por la comunidad. No es un exchange, una billetera o una institución financiera. No retiene fondos de los usuarios y no puede acceder a ninguna cuenta. + + + ¿Qué es Ethereum? + + +## ¿Puede alguien recuperar o congelar mis fondos? {#no-fund-access} + +A diferencia de un banco, no existe una autoridad central en Ethereum que pueda congelar, incautar o recuperar fondos. La persona que posee las claves privadas (o la frase semilla) tiene el control total y exclusivo sobre una billetera. + +Esto significa: + +- **Nadie puede recuperar los fondos** que haya enviado a la dirección equivocada +- **Nadie puede revertir** una transacción después de que se confirme +- **Nadie puede congelar** su billetera o bloquear sus transacciones +- **Nadie puede restablecer su contraseña** si pierde su frase semilla + +Por eso es fundamental proteger su frase semilla. Es la única forma de acceder a su billetera. Si se pierde o la roban, no hay opción de recuperación. + + + Seguridad en Ethereum y prevención de estafas + + +## ¿Todavía puedo minar Ethereum? {#no-mining} + +Ethereum cambió de [prueba de trabajo](/glossary/#pow) a [prueba de participación](/glossary/#pos) durante [La Fusión](/roadmap/merge/) en septiembre de 2022. La minería ya no es posible en Ethereum. + +La red ahora está protegida por validadores que hacen [staking](/glossary/#staking) de ETH. Cualquiera puede participar: + +- **Staking en solitario:** opere su propio validador con 32 ETH ([más información](/staking/solo/)) +- **Staking como servicio:** delegue la operación del nodo mientras conserva sus claves ([más información](/staking/saas/)) +- **Staking en grupo:** haga staking con menos de 32 ETH uniéndose a un grupo ([más información](/staking/pools/)) + + + Más información sobre el staking + + +## ¿Existe un equipo de soporte de Ethereum? {#no-support-team} + +Buscar "soporte oficial de Ethereum" es similar a buscar "soporte oficial de Internet". Esto, por supuesto, no existe, pero dependiendo de su problema puede buscar ayuda de su proveedor de servicios de internet, el fabricante del hardware de su rúter o una de las empresas detrás del dispositivo, la aplicación o el sitio web que está utilizando. + +Ethereum es similar. No hay ninguna empresa, equipo de soporte o servicio de ayuda detrás de Ethereum en su conjunto, pero dependiendo del problema puede encontrar ayuda contactando a su _proveedor de billetera_, _servicio de staking_, _exchange_, _institución financiera_ o el _equipo que mantiene la aplicación_ que está usando. + +Dado que Ethereum es públicamente transparente por defecto, también puede encontrar útiles los [exploradores de bloques](/developers/docs/data-and-analytics/block-explorers/), las [herramientas de análisis](/developers/tools/analytics/) y otros [recursos de investigación en línea](/community/support/scams/#analyze) para investigar un problema directamente. + +Dicho esto, nadie de Ethereum o de ethereum.org hará nunca lo siguiente: + +- Contactarle por mensaje directo +- Pedirle su frase semilla o claves privadas +- Pedirle que envíe ETH para verificar su billetera +- Ofrecerse a ayudarle a recuperar fondos a cambio de una tarifa + +**Cualquiera que haga algo de lo anterior está intentando estafarle.** + +Si necesita ayuda, las comunidades reales que pueden ayudarle se enumeran en la [página de soporte](/community/support/). Son comunidades abiertas, gestionadas por voluntarios, no canales de soporte oficiales. + + + Seguridad en Ethereum y prevención de estafas + diff --git a/public/content/translations/es/community/support/scams/index.md b/public/content/translations/es/community/support/scams/index.md new file mode 100644 index 00000000000..24459287dbc --- /dev/null +++ b/public/content/translations/es/community/support/scams/index.md @@ -0,0 +1,159 @@ +--- +title: Ayuda y denuncias de estafas +description: "Qué hacer si ha sido víctima de una estafa, cómo proteger sus activos restantes y dónde denunciar el fraude." +lang: es +--- + +# Fui estafado o perdí fondos {#scam-help} + +Las estafas de criptomonedas se dirigen a personas de todos los niveles de experiencia, incluidos profesionales de las finanzas y la tecnología. No está solo, y estar aquí es el primer paso correcto. + + + + + + +**Nadie puede revertir las transacciones de la cadena de bloques.** Si alguien se pone en contacto con usted afirmando que puede recuperar sus fondos a cambio de una comisión, es casi seguro que se trata de una segunda estafa. Vea [estafas de recuperación](#recovery-scams) a continuación. + + + + +## Proteja sus activos restantes {#secure-assets} + +Si ha interactuado con un estafador o sospecha que su billetera está comprometida, siga estos pasos inmediatamente: + +1. **Mueva los fondos restantes** a una nueva billetera segura a la que el estafador no tenga acceso. +2. **Revoque las aprobaciones de tókenes.** Los estafadores a menudo le engañan para que apruebe el gasto ilimitado de tókenes. Revocar estos permisos evita que se siga vaciando su billetera. +3. **Cambie las contraseñas** de cualquier cuenta de intercambio que pueda estar vinculada. +4. **Active la autenticación de dos factores (2FA)** en todas las cuentas relacionadas con criptomonedas. + +### Cómo revocar las aprobaciones de tókenes {#revoke-approvals} + +Cuando interactúa con una dapp o un contrato inteligente, es posible que le haya concedido permiso para gastar sus tókenes. Si un estafador le engañó para que aprobara un contrato malicioso, puede seguir sustrayendo sus tókenes incluso después de la estafa inicial. + +Utilice estas herramientas para comprobar y revocar las aprobaciones: + +- [Revoke.cash](https://revoke.cash/): conecte su billetera para ver todas las aprobaciones activas y revocarlas. +- [Revokescout](https://revoke.blockscout.com/): compruebe y revoque las aprobaciones a través de Blockscout. +- [Etherscan Token Approval Checker](https://etherscan.io/tokenapprovalchecker): compruebe y revoque aprobaciones a través de Etherscan. + + + Guía paso a paso: Cómo revocar el acceso a los tókenes + + +## Denunciar direcciones y sitios web de estafas {#report} + +Denunciar ayuda a advertir a otros usuarios y puede ayudar en las investigaciones policiales. Documente todo: hashes de transacciones, direcciones de billeteras, capturas de pantalla y cualquier comunicación con el estafador. + +### Denunciar una dirección de estafa {#report-address} + +- [Chainabuse](https://www.chainabuse.com/): base de datos de denuncias de estafas y fraudes impulsada por la comunidad. Envíe denuncias y busque direcciones de estafas conocidas. +- [Informe de Etherscan](https://info.etherscan.com/report-address/): marque una dirección en el explorador de bloques de Ethereum más utilizado. +- [CryptoScamDB](https://cryptoscamdb.org/): base de datos de código abierto que rastrea las estafas de criptomonedas. + +### Denunciar un sitio web o una cuenta de redes sociales de una estafa {#report-website} + +- [PhishTank](https://phishtank.org/): envíe y verifique las URL de phishing. +- [Navegación segura de Google](https://safebrowsing.google.com/safebrowsing/report_phish/): denuncie sitios de phishing a Google para que se bloqueen en Chrome y otros navegadores. +- [Netcraft](https://report.netcraft.com/report/mistake): denuncie sitios web maliciosos y fraudulentos. +- Denuncie directamente en la plataforma de redes sociales donde ocurrió la estafa (Twitter/X, Discord, Telegram, todas tienen funciones de denuncia). + +### Denunciar a las autoridades {#report-law-enforcement} + +- **Estados Unidos:** [Centro de Quejas de Delitos en Internet (IC3) del FBI](https://www.ic3.gov/) +- **Reino Unido:** [Action Fraud](https://www.actionfraud.police.uk/) +- **Unión Europea:** [Europol](https://www.europol.europa.eu/report-a-crime) +- **Otros países:** presente una denuncia a su policía local. El fraude con criptomonedas es un delito en la mayoría de las jurisdicciones. + +## Analice lo que sucedió {#analyze} + +Comprender a dónde fueron sus fondos puede ayudar con las denuncias y puede respaldar los esfuerzos de recuperación si los fondos llegan a un intercambio centralizado. + +- [Blockscout](https://eth.blockscout.com/): explorador de bloques de código abierto para buscar cualquier hash de transacción o dirección de billetera para ver a dónde se enviaron los fondos. +- [Etherscan](https://etherscan.io/): busque cualquier hash de transacción o dirección de billetera para ver a dónde se enviaron los fondos. +- [Búsqueda en Chainabuse](https://www.chainabuse.com/): compruebe si una dirección ya ha sido denunciada por otras víctimas. +- [MetaSleuth](https://metasleuth.io/) de BlockSec: herramienta de seguimiento visual de transacciones que mapea los flujos de fondos. + +**Si los fondos se enviaron a un intercambio centralizado** (como Coinbase, Binance, Kraken), comuníquese con su equipo de soporte de inmediato con los detalles de la transacción. Los intercambios a veces pueden congelar las cuentas marcadas por fraude. + +## La dura verdad {#hard-truth} + +Debido a que Ethereum es descentralizado, ninguna autoridad central puede revertir transacciones o recuperar fondos robados. Una vez que se confirma una transacción en la cadena de bloques, es definitiva. + +Denunciar sigue siendo valioso. Las denuncias ayudan a las autoridades a rastrear las redes de fraude organizado, y marcar las direcciones en Chainabuse y Etherscan advierte a las futuras víctimas potenciales. + +## Tipos de estafas a tener en cuenta {#scam-types} + + + +Los estafadores crean sorteos falsos que prometen multiplicar su ETH o darle tókenes gratis. A menudo se hacen pasar por figuras conocidas como Vitalik Buterin. Si envía ETH a una dirección de "sorteo", no recibirá nada a cambio. + +**Recuerde:** Vitalik y otras figuras prominentes nunca le pedirán que les envíe ETH. + +[Más sobre estafas comunes](/security/#common-scams) + + + + +Los estafadores se hacen pasar por miembros del equipo de Ethereum, moderadores o agentes de soporte en Discord, Telegram y las redes sociales. Pueden enviarle mensajes directos ofreciéndole ayuda o afirmando que hay un problema con su cuenta. + +**Recuerde:** + +- No existe un "equipo de soporte de Ethereum". +- Los moderadores reales nunca le enviarán un MD primero. +- Nunca comparta su frase semilla o claves privadas con nadie, por ningún motivo. +- Nunca haga clic en enlaces enviados en mensajes no solicitados. + + + + +Las estafas de recuperación se dirigen específicamente a personas que ya han perdido fondos. Los estafadores monitorean las redes sociales en busca de personas que hablan de haber sido estafadas, y luego se comunican haciéndose pasar por "investigadores de la cadena de bloques" o "expertos en recuperación de criptomonedas". + +Prometen rastrear y recuperar su criptomoneda robada a cambio de una tarifa inicial. Después de que paga, desaparecen. + +**Ningún servicio legítimo puede revertir las transacciones de la cadena de bloques.** Cualquiera que prometa esto está mintiendo. Esta es una de las estafas de seguimiento más comunes. + + + + +Los sitios de phishing tienen un aspecto idéntico al de las aplicaciones de billetera, los intercambios o las plataformas DeFi reales. Le engañan para que introduzca su frase semilla o conecte su billetera, y luego le vacían los fondos. + +**Protéjase:** + +- Verifique siempre la URL antes de conectar su billetera. +- Marque como favorito los sitios oficiales que utiliza con regularidad. +- Nunca introduzca su frase semilla en ningún sitio web. Las aplicaciones legítimas nunca la piden. +- Utilice [PhishTank](https://phishtank.org/) para comprobar las URL sospechosas. + + + Cómo detectar los tókenes de estafa + + + + + Guía completa de seguridad y prevención de estafas en Ethereum + diff --git a/public/content/translations/es/developers/docs/networking-layer/index.md b/public/content/translations/es/developers/docs/networking-layer/index.md index a9dfce92393..b096d0717c0 100644 --- a/public/content/translations/es/developers/docs/networking-layer/index.md +++ b/public/content/translations/es/developers/docs/networking-layer/index.md @@ -146,7 +146,7 @@ A continuación se muestra un resumen del flujo de control, con la pila de red r Una vez que el bloque ha sido certificado por suficientes validadores, se añade a la cabeza de la cadena, se justifica y finalmente se finaliza. -![](cons_client_net_layer.png)\n![](exe_client_net_layer.png) +![Diagrama de la capa de red del cliente de consenso de Ethereum](cons_client_net_layer.png)\n![Diagrama de la capa de red del cliente de ejecución de Ethereum](exe_client_net_layer.png) Esquema de la capa de red para los clientes de consenso y de ejecución, de [ethresear.ch](https://ethresear.ch/t/eth1-eth2-client-relationship/7248) diff --git a/public/content/translations/es/developers/docs/nodes-and-clients/node-architecture/index.md b/public/content/translations/es/developers/docs/nodes-and-clients/node-architecture/index.md index ca271a10e30..a5e3d2a277f 100644 --- a/public/content/translations/es/developers/docs/nodes-and-clients/node-architecture/index.md +++ b/public/content/translations/es/developers/docs/nodes-and-clients/node-architecture/index.md @@ -10,7 +10,7 @@ Cuando Ethereum utilizaba la [prueba de trabajo](/developers/docs/consensus-mech El siguiente diagrama muestra la relación entre los dos clientes Ethereum. Los dos clientes se conectan a sus respectivas redes entre pares (P2P). Se necesitan redes P2P separadas, ya que los clientes de ejecución envían transacciones con protocolo de intercambio de información (o Gossip) a través de su red P2P, lo que les permite administrar su reserva de transacciones local, mientras que los clientes de consenso envían por Gossip bloques de su red P2P, lo que permite el consenso y el crecimiento de la cadena. -![](node-architecture-text-background.png) +![Diagrama de la arquitectura del nodo Ethereum que muestra las capas de ejecución y consenso.](node-architecture-text-background.png) _Hay varias opciones para el cliente de ejecución, incluyendo Erigon, Nethermind y Besu_. diff --git a/public/content/translations/es/developers/tutorials/ai-trading-agent/index.md b/public/content/translations/es/developers/tutorials/ai-trading-agent/index.md new file mode 100644 index 00000000000..f1a2295f116 --- /dev/null +++ b/public/content/translations/es/developers/tutorials/ai-trading-agent/index.md @@ -0,0 +1,980 @@ +--- +title: "Crea tu propio agente de negociación con IA en Ethereum" +description: "En este tutorial, aprenderás a crear un agente de negociación con IA simple. Este agente lee información de la cadena de bloques, solicita a un LLM una recomendación basada en esa información, realiza la operación que el LLM recomienda, luego espera y repite el proceso." +author: Ori Pomerantz +tags: [ "IA", "negociación", "agente", "python" ] +skill: intermediate +published: 2026-02-13 +lang: es +sidebarDepth: 3 +--- + +En este tutorial, aprenderás a crear un agente de negociación con IA simple. Este agente funciona siguiendo estos pasos: + +1. Lee los precios actuales y pasados de un token, así como otra información potencialmente relevante +2. Crea una consulta con esta información, junto con información de fondo para explicar cómo podría ser relevante +3. Envía la consulta y recibe un precio proyectado +4. Opera en función de la recomendación +5. Espera y repite + +Este agente demuestra cómo leer información, traducirla en una consulta que produzca una respuesta útil y utilizar esa respuesta. Todos estos son pasos necesarios para un agente de IA. Este agente está implementado en Python porque es el lenguaje más común utilizado en IA. + +## ¿Por qué hacer esto? {#why-do-this} + +Los agentes de negociación automatizados permiten a los desarrolladores seleccionar y ejecutar una estrategia de negociación. [Agentes de IA](/ai-agents) permiten estrategias de negociación más complejas y dinámicas, utilizando potencialmente información y algoritmos que el desarrollador ni siquiera ha considerado usar. + +## Las herramientas {#tools} + +Este tutorial utiliza [Python](https://www.python.org/), la [biblioteca Web3](https://web3py.readthedocs.io/en/stable/) y [Uniswap v3](https://github.com/Uniswap/v3-periphery) para cotizaciones y negociación. + +### ¿Por qué Python? {#python} + +El lenguaje más utilizado para la IA es [Python](https://www.python.org/), por lo que lo usamos aquí. No te preocupes si no sabes Python. El lenguaje es muy claro y explicaré exactamente lo que hace. + +La [biblioteca Web3](https://web3py.readthedocs.io/en/stable/) es la API de Python para Ethereum más común. Es bastante fácil de usar. + +### Operar en la cadena de bloques {#trading-on-blockchain} + +Existen [muchos intercambios descentralizados (DEX)](/apps/categories/defi/) que te permiten operar con tokens en Ethereum. Sin embargo, tienden a tener tasas de cambio similares debido al [arbitraje](/developers/docs/smart-contracts/composability/#better-user-experience). + +[Uniswap](https://app.uniswap.org/) es un DEX muy utilizado que podemos usar tanto para cotizaciones (para ver los valores relativos de los tokens) como para operaciones. + +### OpenAI {#openai} + +Para un modelo de lenguaje grande, elegí empezar con [OpenAI](https://openai.com/). Para ejecutar la aplicación de este tutorial, necesitarás pagar por el acceso a la API. El pago mínimo de 5 $ es más que suficiente. + +## Desarrollo, paso a paso {#step-by-step} + +Para simplificar el desarrollo, procederemos por etapas. Cada paso es una rama en GitHub. + +### Primeros pasos {#getting-started} + +Estos son los pasos para empezar en UNIX o Linux (incluido [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)) + +1. Si aún no lo tienes, descarga e instala [Python](https://www.python.org/downloads/). + +2. Clone el repositorio de GitHub. + + ```sh + git clone https://github.com/qbzzt/260215-ai-agent.git -b 01-getting-started + cd 260215-ai-agent + ``` + +3. Instala [`uv`](https://docs.astral.sh/uv/getting-started/installation/). El comando en tu sistema podría ser diferente. + + ```sh + pipx install uv + ``` + +4. Descarga las bibliotecas. + + ```sh + uv sync + ``` + +5. Activa el entorno virtual. + + ```sh + source .venv/bin/activate + ``` + +6. Para verificar que Python y Web3 funcionan correctamente, ejecuta `python3` y proporciónale este programa. Puedes introducirlo en el indicador `>>>`; no es necesario crear un archivo. + + ```python + from web3 import Web3 + MAINNET_URL = "https://eth.drpc.org" + w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) + w3.eth.block_number + quit() + ``` + +### Lectura desde la cadena de bloques {#read-blockchain} + +El siguiente paso es leer desde la cadena de bloques. Para ello, debes cambiar a la rama `02-read-quote` y luego usar `uv` para ejecutar el programa. + +```sh +git checkout 02-read-quote +uv run agent.py +``` + +Deberías recibir una lista de objetos `Quote`, cada uno con una marca de tiempo, un precio y el activo (actualmente siempre `WETH/USDC`). + +Aquí tienes una explicación línea por línea. + +```python +from web3 import Web3 +from web3.contract import Contract +from decimal import Decimal, ROUND_HALF_UP +from dataclasses import dataclass +from datetime import datetime, timezone +from pprint import pprint +import time +import functools +import sys +``` + +Importe las librerías que necesitamos. Se explican a continuación cuando se utilizan. + +```python +print = functools.partial(print, flush=True) +``` + +Reemplaza el `print` de Python con una versión que siempre vacía la salida inmediatamente. Esto es útil en un script de larga duración porque no queremos esperar a las actualizaciones de estado ni a la salida de depuración. + +```python +MAINNET_URL = "https://eth.drpc.org" +``` + +Una URL para acceder a la red principal. Puedes obtener una de [Nodo como servicio](/developers/docs/nodes-and-clients/nodes-as-a-service/) o usar una de las anunciadas en [Chainlist](https://chainlist.org/chain/1). + +```python +BLOCK_TIME_SECONDS = 12 +MINUTE_BLOCKS = int(60 / BLOCK_TIME_SECONDS) +HOUR_BLOCKS = MINUTE_BLOCKS * 60 +DAY_BLOCKS = HOUR_BLOCKS * 24 +``` + +Un bloque de la red principal de Ethereum normalmente se produce cada doce segundos, así que este es el número de bloques que esperaríamos que se produjeran en un período de tiempo. Ten en cuenta que esta no es una cifra exacta. Cuando el [proponente de bloque](/developers/docs/consensus-mechanisms/pos/block-proposal/) está inactivo, ese bloque se salta y el tiempo para el siguiente bloque es de 24 segundos. Si quisiéramos obtener el bloque exacto para una marca de tiempo, usaríamos la [búsqueda binaria](https://en.wikipedia.org/wiki/Binary_search). Sin embargo, esto es lo suficientemente aproximado para nuestros propósitos. Predecir el futuro no es una ciencia exacta. + +```python +CYCLE_BLOCKS = DAY_BLOCKS +``` + +El tamaño del ciclo. Revisamos las cotizaciones una vez por ciclo e intentamos estimar el valor al final del siguiente ciclo. + +```python +# La dirección del fondo de liquidez que estamos leyendo +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +``` + +Los valores de cotización se toman del fondo de liquidez Uniswap 3 USDC/WETH en la dirección [`0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`](https://eth.blockscout.com/address/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640?tab=read_write_contract). Esta dirección ya está en formato de suma de verificación, pero es mejor usar [`Web3.to_checksum_address`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_checksum_address) para que el código sea reutilizable. + +```python +POOL_ABI = [ + { "name": "slot0", ... }, + { "name": "token0", ... }, + { "name": "token1", ... }, +] + +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... } +] +``` + +Estas son las [ABI](https://docs.soliditylang.org/en/latest/abi-spec.html) para los dos contratos que necesitamos contactar. Para mantener el código conciso, incluimos solo las funciones que necesitamos llamar. + +```python +w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) +``` + +Inicia la biblioteca [`Web3`](https://web3py.readthedocs.io/en/stable/quickstart.html#remote-providers) y conéctate a un nodo de Ethereum. + +```python +@dataclass(frozen=True) +class ERC20Token: + address: str + symbol: str + decimals: int + contract: Contract +``` + +Esta es una forma de crear una clase de datos en Python. El tipo de datos [`Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) se usa para conectarse al contrato. Observa el `(frozen=True)`. En Python, los [booleanos](https://en.wikipedia.org/wiki/Boolean_data_type) se definen como `True` o `False`, con mayúscula inicial. Esta clase de datos es `frozen` (congelada), lo que significa que los campos no se pueden modificar. + +Observa la sangría. A diferencia de los [lenguajes derivados de C](https://en.wikipedia.org/wiki/List_of_C-family_programming_languages), Python utiliza la sangría para denotar bloques. El intérprete de Python sabe que la siguiente definición no forma parte de esta clase de datos porque no comienza con la misma sangría que los campos de la clase de datos. + +```python +@dataclass(frozen=True) +class PoolInfo: + address: str + token0: ERC20Token + token1: ERC20Token + contract: Contract + asset: str + decimal_factor: Decimal = 1 +``` + +El tipo [`Decimal`](https://docs.python.org/3/library/decimal.html) se utiliza para manejar con precisión las fracciones decimales. + +```python + def get_price(self, block: int) -> Decimal: +``` + +Esta es la forma de definir una función en Python. La definición está sangrada para mostrar que todavía es parte de `PoolInfo`. + +En una función que forma parte de una clase de datos, el primer parámetro es siempre `self`, la instancia de la clase de datos que la llamó. Aquí hay otro parámetro, el número de bloque. + +```python + assert block <= w3.eth.block_number, "El bloque está en el futuro" +``` + +Si pudiéramos leer el futuro, no necesitaríamos IA para operar. + +```python + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) +``` + +La sintaxis para llamar a una función en la EVM desde Web3 es esta: `.functions."().call()`. Los parámetros pueden ser los parámetros de la función de la EVM (si los hay; aquí no hay) o [parámetros con nombre](https://en.wikipedia.org/wiki/Named_parameter) para modificar el comportamiento de la cadena de bloques. Aquí usamos uno, `block_identifier`, para especificar [el número de bloque](/developers/docs/apis/json-rpc/#default-block) en el que deseamos ejecutar. + +El resultado es [esta estructura, en forma de matriz](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol#L56-L72). El primer valor es una función de la tasa de cambio entre los dos tokens. + +```python + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 +``` + +Para reducir los cálculos en la cadena, Uniswap v3 no almacena el factor de cambio real, sino su raíz cuadrada. Debido a que la EVM no admite matemáticas de punto flotante ni fracciones, en lugar del valor real, la respuesta es price296 + +```python + # (token1 por token0) + return 1/(raw_price * self.decimal_factor) +``` + +El precio bruto que obtenemos es el número de `token0` que obtenemos por cada `token1`. En nuestro fondo de liquidez, `token0` es USDC (una moneda estable con el mismo valor que un dólar estadounidense) y `token1` es [WETH](https://opensea.io/learn/blockchain/what-is-weth). El valor que realmente queremos es el número de dólares por WETH, no el inverso. + +El factor decimal es la relación entre los [factores decimales](https://docs.openzeppelin.com/contracts/4.x/erc20#a-note-on-decimals) de los dos tokens. + +```python +@dataclass(frozen=True) +class Quote: + timestamp: str + price: Decimal + asset: str +``` + +Esta clase de datos representa una cotización: el precio de un activo específico en un momento dado. En este punto, el campo `asset` es irrelevante porque usamos un único fondo de liquidez y, por lo tanto, tenemos un único activo. Sin embargo, añadiremos más activos más adelante. + +```python +def read_token(address: str) -> ERC20Token: + token = w3.eth.contract(address=address, abi=ERC20_ABI) + symbol = token.functions.symbol().call() + decimals = token.functions.decimals().call() + + return ERC20Token( + address=address, + symbol=symbol, + decimals=decimals, + contract=token + ) +``` + +Esta función toma una dirección y devuelve información sobre el contrato del token en esa dirección. Para crear un nuevo [`Contrato` de Web3](https://web3py.readthedocs.io/en/stable/web3.contract.html), proporcionamos la dirección y la ABI a `w3.eth.contract`. + +```python +def read_pool(address: str) -> PoolInfo: + pool_contract = w3.eth.contract(address=address, abi=POOL_ABI) + token0Address = pool_contract.functions.token0().call() + token1Address = pool_contract.functions.token1().call() + token0 = read_token(token0Address) + token1 = read_token(token1Address) + + return PoolInfo( + address=address, + asset=f"{token1.symbol}/{token0.symbol}", + token0=token0, + token1=token1, + contract=pool_contract, + decimal_factor=Decimal(10) ** Decimal(token0.decimals - token1.decimals) + ) +``` + +Esta función devuelve todo lo que necesitamos sobre [un fondo de liquidez específico](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol). La sintaxis `f""` es una [cadena formateada](https://docs.python.org/3/reference/lexical_analysis.html#f-strings). + +```python +def get_quote(pool: PoolInfo, block_number: int = None) -> Quote: +``` + +Obtiene un objeto `Quote`. El valor predeterminado para `block_number` es `None` (sin valor). + +```python + if block_number is None: + block_number = w3.eth.block_number +``` + +Si no se especificó un número de bloque, usa `w3.eth.block_number`, que es el último número de bloque. Esta es la sintaxis para [una instrucción `if`](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement). + +Podría parecer que hubiera sido mejor simplemente establecer el valor predeterminado en `w3.eth.block_number`, pero eso no funciona bien porque sería el número de bloque en el momento en que se define la función. En un agente de larga duración, esto sería un problema. + +```python + block = w3.eth.get_block(block_number) + price = pool.get_price(block_number) + return Quote( + timestamp=datetime.fromtimestamp(block.timestamp, timezone.utc).isoformat(), + price=price.quantize(Decimal("0.01")), + asset=pool.asset + ) +``` + +Usa [la biblioteca `datetime`](https://docs.python.org/3/library/datetime.html) para darle un formato legible para humanos y modelos de lenguaje grandes (LLM). Usa [`Decimal.quantize`](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) para redondear el valor a dos decimales. + +```python +def get_quotes(pool: PoolInfo, start_block: int, end_block: int, step: int) -> list[Quote]: +``` + +En Python, se define una [lista](https://docs.python.org/3/library/stdtypes.html#typesseq-list) que solo puede contener un tipo específico usando `list[]`. + +```python + quotes = [] + for block in range(start_block, end_block + 1, step): +``` + +En Python, un [bucle `for`](https://docs.python.org/3/tutorial/controlflow.html#for-statements) normalmente itera sobre una lista. La lista de números de bloque en los que buscar cotizaciones proviene de [`range`](https://docs.python.org/3/library/stdtypes.html#range). + +```python + quote = get_quote(pool, block) + quotes.append(quote) + return quotes +``` + +Para cada número de bloque, obtén un objeto `Quote` y añádelo a la lista `quotes`. Luego, devuelve esa lista. + +```python +pool = read_pool(WETHUSDC_ADDRESS) +quotes = get_quotes( + pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) + +pprint(quotes) +``` + +Este es el código principal del script. Lee la información del fondo de liquidez, obtén doce cotizaciones y usa [`pprint`](https://docs.python.org/3/library/pprint.html#pprint.pprint) para imprimirlas. + +### Crear una indicación {#prompt} + +A continuación, necesitamos convertir esta lista de cotizaciones en una indicación para un LLM y obtener un valor futuro esperado. + +```sh +git checkout 03-create-prompt +uv run agent.py +``` + +La salida ahora será una indicación para un LLM, similar a: + +``` +Dadas estas cotizaciones: +Activo: WETH/USDC + 2026-01-20T16:34 3016.21 + . + . + . + 2026-02-01T17:49 2299.10 + +Activo: WBTC/WETH + 2026-01-20T16:34 29.84 + . + . + . + 2026-02-01T17:50 33.46 + + +¿Qué valor esperarías que tuviera WETH/USDC en la fecha 2026-02-02T17:56? + +Proporciona tu respuesta como un único número redondeado a dos decimales, +sin ningún otro texto. +``` + +Observa que aquí hay cotizaciones para dos activos, `WETH/USDC` y `WBTC/WETH`. Añadir cotizaciones de otro activo podría mejorar la precisión de la predicción. + +#### Cómo es una indicación {#prompt-explanation} + +Esta indicación contiene tres secciones, que son bastante comunes en las indicaciones para LLM. + +1. Información. Los LLM tienen mucha información de su entrenamiento, pero generalmente no tienen la más reciente. Esta es la razón por la que necesitamos recuperar las últimas cotizaciones aquí. Añadir información a una indicación se llama [generación aumentada por recuperación (RAG)](https://en.wikipedia.org/wiki/Retrieval-augmented_generation). + +2. La pregunta real. Esto es lo que queremos saber. + +3. Instrucciones de formato de salida. Normalmente, un LLM nos dará una estimación con una explicación de cómo llegó a ella. Esto es mejor para los humanos, pero un programa informático solo necesita el resultado final. + +#### Explicación del código {#prompt-code} + +Este es el nuevo código. + +```python +from datetime import datetime, timezone, timedelta +``` + +Necesitamos proporcionar al LLM la hora para la que queremos una estimación. Para obtener una hora "n minutos/horas/días" en el futuro, usamos [la clase `timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta). + +```python +# Las direcciones de los fondos de liquidez que estamos leyendo +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +WETHWBTC_ADDRESS = Web3.to_checksum_address("0xCBCdF9626bC03E24f779434178A73a0B4bad62eD") +``` + +Tenemos dos fondos de liquidez que necesitamos leer. + +```python +@dataclass(frozen=True) +class PoolInfo: + . + . + . + reverse: bool = False + + def get_price(self, block: int) -> Decimal: + assert block <= w3.eth.block_number, "El bloque está en el futuro" + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 # (token1 por token0) + if self.reverse: + return 1/(raw_price * self.decimal_factor) + else: + return raw_price * self.decimal_factor +``` + +En el fondo de liquidez WETH/USDC, queremos saber cuántos de `token0` (USDC) necesitamos para comprar uno de `token1` (WETH). En el fondo de liquidez WETH/WBTC, queremos saber cuántos `token1` (WETH) necesitamos para comprar un `token0` (WBTC, que es Bitcoin envuelto). Necesitamos hacer un seguimiento de si la proporción del fondo de liquidez debe invertirse. + +```python +def read_pool(address: str, reverse: bool = False) -> PoolInfo: + . + . + . + + return PoolInfo( + . + . + . + + asset= f"{token1.symbol}/{token0.symbol}" if reverse else f"{token0.symbol}/{token1.symbol}", + reverse=reverse + ) +``` + +Para saber si un fondo de liquidez debe invertirse, debemos obtener eso como entrada para `read_pool`. Además, el símbolo del activo debe configurarse correctamente. + +La sintaxis ` if else ` es el equivalente en Python del [operador condicional ternario](https://en.wikipedia.org/wiki/Ternary_conditional_operator), que en un lenguaje derivado de C sería ` ? : `. + +```python +def format_quotes(quotes: list[Quote]) -> str: + result = f"Asset: {quotes[0].asset}\n" + for quote in quotes: + result += f"\t{quote.timestamp[0:16]} {quote.price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)}\n" + return result +``` + +Esta función crea una cadena que formatea una lista de objetos `Quote`, asumiendo que todos se aplican al mismo activo. + +```python +def make_prompt(quotes: list[list[Quote]], expected_time: str, asset: str) -> str: + return f""" +``` + +En Python, los [literales de cadena multilínea](https://www.w3schools.com/python/gloss_python_multi_line_strings.asp) se escriben como `"""` .... `"""`. + +```python +Dadas estas cotizaciones: +{ + functools.reduce(lambda acc, q: acc + '\n' + q, + map(lambda q: format_quotes(q), quotes)) +} +``` + +Aquí, usamos el patrón [MapReduce](https://en.wikipedia.org/wiki/MapReduce) para generar una cadena para cada lista de cotizaciones con `format_quotes`, y luego las reducimos a una sola cadena para usarla en la indicación. + +```python +¿Qué valor esperarías que tuviera {asset} en la fecha {expected_time}? + +Proporciona tu respuesta como un único número redondeado a dos decimales, +sin ningún otro texto. + """ +``` + +El resto de la indicación es como se esperaba. + +```python +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +Revisa los dos fondos de liquidez y obtén cotizaciones de ambos. + +```python +future_time = (datetime.now(timezone.utc) + timedelta(days=1)).isoformat()[0:16] + +print(make_prompt(wethusdc_quotes + wethwbtc_quotes, future_time, wethusdc_pool.asset)) +``` + +Determina el punto de tiempo futuro para el que queremos la estimación y crea la indicación. + +### Interfaz con un LLM {#interface-llm} + +A continuación, le daremos una indicación a un LLM real y recibiremos un valor futuro esperado. Escribí este programa usando OpenAI, así que si quieres usar un proveedor diferente, tendrás que ajustarlo. + +1. Obtén una [cuenta de OpenAI](https://auth.openai.com/create-account) + +2. [Financia la cuenta](https://platform.openai.com/settings/organization/billing/overview): la cantidad mínima en el momento de escribir este artículo es de 5 $ + +3. [Crea una clave de API](https://platform.openai.com/settings/organization/api-keys) + +4. En la línea de comandos, exporta la clave de API para que tu programa pueda usarla + + ```sh + export OPENAI_API_KEY=sk- + ``` + +5. Haz un «checkout» y ejecuta el agente + + ```sh + git checkout 04-interface-llm + uv run agent.py + ``` + +Este es el nuevo código. + +```python +from openai import OpenAI + +open_ai = OpenAI() # El cliente lee la variable de entorno OPENAI_API_KEY +``` + +Importa e instancia la API de OpenAI. + +```python +response = open_ai.chat.completions.create( + model="gpt-4-turbo", + messages=[ + {"role": "user", "content": prompt} + ], + temperature=0.0, + max_tokens=16, +) +``` + +Llama a la API de OpenAI (`open_ai.chat.completions.create`) para crear la respuesta. + +```python +expected_price = Decimal(response.choices[0].message.content.strip()) +current_price = wethusdc_quotes[-1].price + +print ("Precio actual:", wethusdc_quotes[-1].price) +print(f"En {future_time}, precio esperado: {expected_price} USD") + +if (expected_price > current_price): + print(f"Comprar, espero que el precio suba en {expected_price - current_price} USD") +else: + print(f"Vender, espero que el precio baje en {current_price - expected_price} USD") +``` + +Muestra el precio y proporciona una recomendación de compra o venta. + +#### Prueba de las predicciones {#testing-the-predictions} + +Ahora que podemos generar predicciones, también podemos usar datos históricos para evaluar si producimos predicciones útiles. + +```sh +uv run test-predictor.py +``` + +El resultado esperado es similar a: + +``` +Predicción para 2026-01-05T19:50: predicho 3138.93 USD, real 3218.92 USD, error 79.99 USD +Predicción para 2026-01-06T19:56: predicho 3243.39 USD, real 3221.08 USD, error 22.31 USD +Predicción para 2026-01-07T20:02: predicho 3223.24 USD, real 3146.89 USD, error 76.35 USD +Predicción para 2026-01-08T20:11: predicho 3150.47 USD, real 3092.04 USD, error 58.43 USD +. +. +. +Predicción para 2026-01-31T22:33: predicho 2637.73 USD, real 2417.77 USD, error 219.96 USD +Predicción para 2026-02-01T22:41: predicho 2381.70 USD, real 2318.84 USD, error 62.86 USD +Predicción para 2026-02-02T22:49: predicho 2234.91 USD, real 2349.28 USD, error 114.37 USD +Error de predicción medio en 29 predicciones: 83.87103448275862068965517241 USD +Cambio medio por recomendación: 4.787931034482758620689655172 USD +Varianza estándar de los cambios: 104.42 USD +Días rentables: 51.72% +Días con pérdidas: 48.28% +``` + +La mayor parte del probador es idéntica al agente, pero aquí están las partes que son nuevas o modificadas. + +```python +CYCLES_FOR_TEST = 40 # Para la prueba retrospectiva, cuántos ciclos probamos + +# Obtener muchas cotizaciones +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +Miramos hacia atrás `CYCLES_FOR_TEST` (especificado como 40 aquí) días. + +```python +# Crear predicciones y verificarlas con el historial real + +total_error = Decimal(0) +changes = [] +``` + +Hay dos tipos de errores que nos interesan. El primero, `total_error`, es simplemente la suma de los errores que cometió el predictor. + +Para entender el segundo, `changes`, debemos recordar el propósito del agente. No es para predecir la relación WETH/USDC (precio de ETH). Es para emitir recomendaciones de compra y venta. Si el precio es actualmente de 2000 $ y predice 2010 $ para mañana, no nos importa si el resultado real es 2020 $ y ganamos dinero extra. Pero _sí_ nos importa si predijo 2010 $, y compramos ETH basándonos en esa recomendación, y el precio baja a 1990 $. + +```python +for index in range(0,len(wethusdc_quotes)-CYCLES_BACK): +``` + +Solo podemos ver los casos en los que el historial completo (los valores utilizados para la predicción y el valor del mundo real para compararlo) está disponible. Esto significa que el caso más reciente debe ser el que comenzó hace `CYCLES_BACK`. + +```python + wethusdc_slice = wethusdc_quotes[index:index+CYCLES_BACK] + wethwbtc_slice = wethwbtc_quotes[index:index+CYCLES_BACK] +``` + +Usa [divisiones](https://www.w3schools.com/python/ref_func_slice.asp) para obtener el mismo número de muestras que el número que usa el agente. El código entre aquí y el siguiente segmento es el mismo código para obtener una predicción que tenemos en el agente. + +```python + predicted_price = Decimal(response.choices[0].message.content.strip()) + real_price = wethusdc_quotes[index+CYCLES_BACK].price + prediction_time_price = wethusdc_quotes[index+CYCLES_BACK-1].price +``` + +Obtén el precio previsto, el precio real y el precio en el momento de la predicción. Necesitamos el precio en el momento de la predicción para determinar si la recomendación era comprar o vender. + +```python + error = abs(predicted_price - real_price) + total_error += error + print (f"Predicción para {prediction_time}: predicho {predicted_price} USD, real {real_price} USD, error {error} USD") +``` + +Calcula el error y súmalo al total. + +```python + recomended_action = 'buy' if predicted_price > prediction_time_price else 'sell' + price_increase = real_price - prediction_time_price + changes.append(price_increase if recomended_action == 'buy' else -price_increase) +``` + +Para `changes`, queremos el impacto monetario de comprar o vender un ETH. Así que primero, necesitamos determinar la recomendación, luego evaluar cómo cambió el precio real y si la recomendación generó ganancias (cambio positivo) o pérdidas (cambio negativo). + +```python +print (f"Error de predicción medio en {len(wethusdc_quotes)-CYCLES_BACK} predicciones: {total_error / Decimal(len(wethusdc_quotes)-CYCLES_BACK)} USD") + +length_changes = Decimal(len(changes)) +mean_change = sum(changes, Decimal(0)) / length_changes +print (f"Cambio medio por recomendación: {mean_change} USD") +var = sum((x - mean_change) ** 2 for x in changes) / length_changes +print (f"Varianza estándar de los cambios: {var.sqrt().quantize(Decimal("0.01"))} USD") +``` + +Informa de los resultados. + +```python +print (f"Días rentables: {len(list(filter(lambda x: x > 0, changes)))/length_changes:.2%}") +print (f"Días con pérdidas: {len(list(filter(lambda x: x < 0, changes)))/length_changes:.2%}") +``` + +Usa [`filter`](https://www.w3schools.com/python/ref_func_filter.asp) para contar el número de días rentables y el número de días con pérdidas. El resultado es un objeto de filtro, que debemos convertir en una lista para obtener la longitud. + +### Envío de transacciones {#submit-txn} + +Ahora necesitamos enviar transacciones reales. Sin embargo, no quiero gastar dinero real en este punto, antes de que el sistema esté probado. En su lugar, crearemos una bifurcación local de la red principal y «operaremos» en esa red. + +Aquí están los pasos para crear una bifurcación local y habilitar la negociación. + +1. Instala [Foundry](https://getfoundry.sh/introduction/installation) + +2. Inicia [`anvil`](https://getfoundry.sh/anvil/overview) + + ```sh + anvil --fork-url https://eth.drpc.org --block-time 12 + ``` + + `anvil` está escuchando en la URL predeterminada de Foundry, http://localhost:8545, por lo que no necesitamos especificar la URL para [el comando `cast`](https://getfoundry.sh/cast/overview) que usamos para manipular la cadena de bloques. + +3. Cuando se ejecuta en `anvil`, hay diez cuentas de prueba que tienen ETH: establece las variables de entorno para la primera + + ```sh + PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ADDRESS=`cast wallet address $PRIVATE_KEY` + ``` + +4. Estos son los contratos que necesitamos usar. [`SwapRouter`](https://github.com/Uniswap/v3-periphery/blob/main/contracts/SwapRouter.sol) es el contrato de Uniswap v3 que usamos para operar realmente. Podríamos operar directamente a través del fondo de liquidez, pero esto es mucho más fácil. + + Las dos variables inferiores son las rutas de Uniswap v3 necesarias para intercambiar entre WETH y USDC. + + ```sh + WETH_ADDRESS=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + USDC_ADDRESS=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + POOL_ADDRESS=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 + SWAP_ROUTER=0xE592427A0AEce92De3Edee1F18E0157C05861564 + WETH_TO_USDC=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + USDC_TO_WETH=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + ``` + +5. Cada una de las cuentas de prueba tiene 10.000 ETH. Usa el contrato WETH para envolver 1000 ETH y obtener 1000 WETH para operar. + + ```sh + cast send $WETH_ADDRESS "deposit()" --value 1000ether --private-key $PRIVATE_KEY + ``` + +6. Usa `SwapRouter` para intercambiar 500 WETH por USDC. + + ```sh + cast send $WETH_ADDRESS "approve(address,uint256)" $SWAP_ROUTER 500ether --private-key $PRIVATE_KEY + MAXINT=`cast max-int uint256` + cast send $SWAP_ROUTER \ + "exactInput((bytes,address,uint256,uint256,uint256))" \ + "($WETH_TO_USDC,$ADDRESS,$MAXINT,500ether,1000000)" \ + --private-key $PRIVATE_KEY + ``` + + La llamada `approve` crea una asignación que permite a `SwapRouter` gastar algunos de nuestros tokens. Los contratos no pueden supervisar eventos, por lo que si transferimos tokens directamente al contrato `SwapRouter`, no sabría que se le ha pagado. En cambio, permitimos que el contrato `SwapRouter` gaste una cierta cantidad, y luego `SwapRouter` lo hace. Esto se hace a través de una función llamada por `SwapRouter`, para que sepa si tuvo éxito. + +7. Verifica que tienes suficientes de ambos tokens. + + ```sh + cast call $WETH_ADDRESS "balanceOf(address)" $ADDRESS | cast from-wei + echo `cast call $USDC_ADDRESS "balanceOf(address)" $ADDRESS | cast to-dec`/10^6 | bc + ``` + +Ahora que tenemos WETH y USDC, podemos ejecutar el agente. + +```sh +git checkout 05-trade +uv run agent.py +``` + +La salida será similar a: + +``` +(ai-trading-agent) qbzzt@Ori-Cloudnomics:~/260215-ai-agent$ uv run agent.py +Precio actual: 1843.16 +En 2026-02-06T23:07, precio esperado: 1724.41 USD +Saldos de la cuenta antes de la operación: +Saldo de USDC: 927301.578272 +Saldo de WETH: 500 +Vender, espero que el precio baje en 118.75 USD +Transacción de aprobación enviada: 74e367ddbb407c1aaf567d87aa5863049991b1d2aa092b6b85195d925e2bd41f +Transacción de aprobación minada. +Transacción de venta enviada: fad1bcf938585c9e90364b26ac7a80eea9efd34c37e5db81e58d7655bcae28bf +Transacción de venta minada. +Saldos de la cuenta después de la operación: +Saldo de USDC: 929143.797116 +Saldo de WETH: 499 +``` + +Para usarlo realmente, necesitas algunos cambios menores. + +- En la línea 14, cambia `MAINNET_URL` a un punto de acceso real, como `https://eth.drpc.org` +- En la línea 28, cambia `PRIVATE_KEY` a tu propia clave privada +- A menos que seas muy rico y puedas comprar o vender 1 ETH cada día para un agente no probado, es posible que quieras cambiar la línea 29 para disminuir `WETH_TRADE_AMOUNT` + +#### Explicación del código {#trading-code} + +Este es el nuevo código. + +```python +SWAP_ROUTER_ADDRESS=Web3.to_checksum_address("0xE592427A0AEce92De3Edee1F18E0157C05861564") +WETH_TO_USDC=bytes.fromhex("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") +USDC_TO_WETH=bytes.fromhex("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +``` + +Las mismas variables que usamos en el paso 4. + +```python +WETH_TRADE_AMOUNT=1 +``` + +La cantidad a operar. + +```python +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... }, + { "name": "balanceOf", ...}, + { "name": "approve", ...} +] +``` + +Para operar realmente, necesitamos la función `approve`. También queremos mostrar los saldos antes y después, así que también necesitamos `balanceOf`. + +```python +SWAP_ROUTER_ABI = [ + { "name": "exactInput", ...}, +] +``` + +En la ABI `SwapRouter`, solo necesitamos `exactInput`. Hay una función relacionada, `exactOutput`, que podríamos usar para comprar exactamente un WETH, pero por simplicidad solo usamos `exactInput` en ambos casos. + +```python +account = w3.eth.account.from_key(PRIVATE_KEY) +swap_router = w3.eth.contract( + address=SWAP_ROUTER_ADDRESS, + abi=SWAP_ROUTER_ABI +) +``` + +Las definiciones de Web3 para la [`cuenta`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html) y el contrato `SwapRouter`. + +```python +def txn_params() -> dict: + return { + "from": account.address, + "value": 0, + "gas": 300000, + "nonce": w3.eth.get_transaction_count(account.address), + } +``` + +Los parámetros de la transacción. Necesitamos una función aquí porque [el nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) debe cambiar cada vez. + +```python +def approve_token(contract: Contract, amount: int): +``` + +Aprobar una asignación de token para `SwapRouter`. + +```python + txn = contract.functions.approve(SWAP_ROUTER_ADDRESS, amount).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) +``` + +Así es como enviamos una transacción en Web3. Primero usamos [el objeto `Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) para construir la transacción. Luego usamos [`web3.eth.account.sign_transaction`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-contract-transaction) para firmar la transacción, usando `PRIVATE_KEY`. Finalmente, usamos [`w3.eth.send_raw_transaction`](https://web3py.readthedocs.io/en/stable/transactions.html#chapter-2-w3-eth-send-raw-transaction) para enviar la transacción. + +```python + print(f"Transacción de aprobación enviada: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Transacción de aprobación minada.") +``` + +[`w3.eth.wait_for_transaction_receipt`](https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.wait_for_transaction_receipt) espera hasta que la transacción sea minada. Devuelve el recibo si es necesario. + +```python +SELL_PARAMS = { + "path": WETH_TO_USDC, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": WETH_TRADE_AMOUNT * 10 ** wethusdc_pool.token1.decimals, + "amountOutMinimum": 0, +} +``` + +Estos son los parámetros al vender WETH. + +```python +def make_buy_params(quote: Quote) -> dict: + return { + "path": USDC_TO_WETH, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": int(quote.price*WETH_TRADE_AMOUNT) * 10**wethusdc_pool.token0.decimals, + "amountOutMinimum": 0, + } +``` + +A diferencia de `SELL_PARAMS`, los parámetros de compra pueden cambiar. La cantidad de entrada es el costo de 1 WETH, como está disponible en `quote`. + +```python +def buy(quote: Quote): + buy_params = make_buy_params(quote) + approve_token(wethusdc_pool.token0.contract, buy_params["amountIn"]) + txn = swap_router.functions.exactInput(buy_params).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Transacción de compra enviada: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Transacción de compra minada.") + + +def sell(): + approve_token(wethusdc_pool.token1.contract, + WETH_TRADE_AMOUNT * 10**wethusdc_pool.token1.decimals) + txn = swap_router.functions.exactInput(SELL_PARAMS).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Transacción de venta enviada: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Transacción de venta minada.") +``` + +Las funciones `buy()` y `sell()` son casi idénticas. Primero aprobamos una asignación suficiente para `SwapRouter` y luego lo llamamos con la ruta y la cantidad correctas. + +```python +def balances(): + token0_balance = wethusdc_pool.token0.contract.functions.balanceOf(account.address).call() + token1_balance = wethusdc_pool.token1.contract.functions.balanceOf(account.address).call() + + print(f"{wethusdc_pool.token0.symbol} Saldo: {Decimal(token0_balance) / Decimal(10 ** wethusdc_pool.token0.decimals)}") + print(f"{wethusdc_pool.token1.symbol} Saldo: {Decimal(token1_balance) / Decimal(10 ** wethusdc_pool.token1.decimals)}") +``` + +Informa de los saldos de los usuarios en ambas monedas. + +```python +print("Saldos de la cuenta antes de la operación:") +balances() + +if (expected_price > current_price): + print(f"Comprar, espero que el precio suba en {expected_price - current_price} USD") + buy(wethusdc_quotes[-1]) +else: + print(f"Vender, espero que el precio baje en {current_price - expected_price} USD") + sell() + +print("Saldos de la cuenta después de la operación:") +balances() +``` + +Este agente actualmente solo funciona una vez. Sin embargo, puedes cambiarlo para que funcione continuamente, ya sea ejecutándolo desde [`crontab`](https://man7.org/linux/man-pages/man1/crontab.1.html) o envolviendo las líneas 368-400 en un bucle y usando [`time.sleep`](https://docs.python.org/3/library/time.html#time.sleep) para esperar hasta que sea el momento del siguiente ciclo. + +## Posibles mejoras {#improvements} + +Esta no es una versión de producción completa; es simplemente un ejemplo para enseñar los conceptos básicos. Aquí hay algunas ideas para mejoras. + +### Negociación más inteligente {#smart-trading} + +Hay dos hechos importantes que el agente ignora al decidir qué hacer. + +- _La magnitud del cambio anticipado_. El agente vende una cantidad fija de `WETH` si se espera que el precio baje, independientemente de la magnitud de la caída. + Podría decirse que sería mejor ignorar los cambios menores y vender en función de cuánto esperamos que baje el precio. +- _La cartera actual_. Si el 10 % de tu cartera está en WETH y crees que el precio subirá, probablemente tenga sentido comprar más. Pero si el 90 % de tu cartera está en WETH, es posible que ya estés suficientemente expuesto y no haya necesidad de comprar más. Lo contrario es cierto si esperas que el precio baje. + +### ¿Y si quieres mantener tu estrategia de negociación en secreto? {#secret} + +Los proveedores de IA pueden ver las consultas que envías a sus LLM, lo que podría exponer el genial sistema de negociación que desarrollaste con tu agente. Un sistema de negociación que demasiada gente usa no tiene valor porque demasiada gente intenta comprar cuando tú quieres comprar (y el precio sube) e intenta vender cuando tú quieres vender (y el precio baja). + +Puedes ejecutar un LLM localmente, por ejemplo, usando [LM-Studio](https://lmstudio.ai/), para evitar este problema. + +### De bot de IA a agente de IA {#bot-to-agent} + +Se puede argumentar que este es [un bot de IA, no un agente de IA](/ai-agents/#ai-agents-vs-ai-bots). Implementa una estrategia relativamente simple que se basa en información predefinida. Podemos habilitar la automejora, por ejemplo, proporcionando una lista de fondos de liquidez de Uniswap v3 y sus últimos valores y preguntando qué combinación tiene el mejor valor predictivo. + +### Protección contra el deslizamiento {#slippage-protection} + +Actualmente no hay [protección contra el deslizamiento](https://uniswapv3book.com/milestone_3/slippage-protection.html). Si la cotización actual es de 2000 $ y el precio esperado es de 2100 $, el agente comprará. Sin embargo, si antes de que el agente compre el costo sube a 2200 $, ya no tiene sentido comprar. + +Para implementar la protección contra el deslizamiento, especifica un valor de `amountOutMinimum` en las líneas 325 y 334 de [`agent.py`](https://github.com/qbzzt/260215-ai-agent/blob/05-trade/agent.py#L325). + +## Conclusión {#conclusion} + +Con suerte, ahora sabes lo suficiente para empezar con los agentes de IA. Esta no es una descripción exhaustiva del tema; hay libros enteros dedicados a eso, pero esto es suficiente para que empieces. ¡Buena suerte! + +[Vea aquí más de mi trabajo](https://cryptodocguy.pro/). diff --git a/public/content/translations/es/developers/tutorials/hello-world-smart-contract-fullstack/index.md b/public/content/translations/es/developers/tutorials/hello-world-smart-contract-fullstack/index.md index 72615e45bb9..ad60783c345 100644 --- a/public/content/translations/es/developers/tutorials/hello-world-smart-contract-fullstack/index.md +++ b/public/content/translations/es/developers/tutorials/hello-world-smart-contract-fullstack/index.md @@ -240,7 +240,7 @@ No lo nombre `process.env` o `.env-custom` ni de ninguna otra manera. - Siga [estas instrucciones](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key) para exportar su clave privada - Vea a continuación cómo obtener la URL de la API de HTTP de Alchemy. -![](./get-alchemy-api-key.gif) +![Tutorial animado para obtener una clave API de Alchemy](./get-alchemy-api-key.gif) Su `.env` debería verse así: diff --git a/public/content/translations/es/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md b/public/content/translations/es/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md index ea90b79663d..39379ea4463 100644 --- a/public/content/translations/es/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md +++ b/public/content/translations/es/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md @@ -62,13 +62,13 @@ Esto producirá la misma información que se proporciona en la página de transa #### Etherscan {#etherscan} -![](./etherscan_view.png) +![Captura de pantalla de la vista del explorador de transacciones de Etherscan](./etherscan_view.png) [Página del contrato de EF en Blockscout.](https://eth.blockscout.com/address/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe) #### Dune Analytics {#dune-analytics} -![](./dune_view.png) +![Captura de pantalla de un panel de consultas de Dune Analytics](./dune_view.png) Puede encontrar el panel de control [aquí](https://dune.com/paulapivat/Learn-Ethereum). Haga clic en la tabla para ver la consulta (véase también más arriba). @@ -146,7 +146,7 @@ ORDER BY block_time DESC` Este es el resultado de SQL en Dune: -![](./list_of_txn.png) +![Captura de pantalla de una lista de transacciones de Ethereum](./list_of_txn.png) La adición de este único bloque a la cadena cambia el estado de la máquina virtual de Ethereum ([EVM](/developers/docs/evm/)). Se verifican a la vez docenas, a veces cientos, de transacciones. En este caso concreto, se incluyeron 222 transacciones. @@ -165,7 +165,7 @@ FROM temp_table Para el bloque 12396854, de un total de 222 transacciones, 204 se verificaron con éxito: -![](./successful_txn.png) +![Captura de pantalla de una transacción exitosa de Ethereum](./successful_txn.png) Las solicitudes de transacciones se producen docenas de veces por segundo, pero los bloques se confirman aproximadamente una vez cada 15 segundos ([fuente](/developers/docs/blocks/)). @@ -173,11 +173,11 @@ Para ver que se produce un bloque aproximadamente cada 15 segundos, podríamos t El gráfico de bloques de Ethereum producidos por día (2016 - actualidad) es: -![](./daily_blocks.png) +![Gráfico que muestra la producción diaria de bloques Ethereum](./daily_blocks.png) El número promedio de bloques producidos diariamente durante este período de tiempo es de ~5874: -![](./avg_daily_blocks.png) +![Gráfico que muestra la producción diaria de bloques Ethereum](./avg_daily_blocks.png) Las consultas son: @@ -214,7 +214,7 @@ Los bloques tienen un tamaño limitado. El tamaño máximo de los bloques es din Una forma de conceptualizar el límite de gas de un bloque es pensar en él como la **oferta** de espacio de bloque disponible para agrupar las transacciones. El límite de gas de los bloques puede consultarse y visualizarse desde 2016 hasta la actualidad: -![](./avg_gas_limit.png) +![Gráfico que muestra el límite promedio de gas de Ethereum a lo largo del tiempo](./avg_gas_limit.png) ```sql SELECT @@ -227,7 +227,7 @@ OFFSET 1 Luego está el gas real que se utiliza diariamente para pagar la computación realizada en la cadena de Ethereum (es decir, enviar una transacción, llamar a un contrato inteligente, acuñar un NFT). Esta es la **demanda** de espacio de bloque disponible en Ethereum: -![](./daily_gas_used.png) +![Gráfico que muestra el gas Ethereum utilizado diariamente](./daily_gas_used.png) ```sql SELECT @@ -246,7 +246,7 @@ Por lo tanto, podemos entender los precios del gas como una función de la deman Por último, es posible que queramos consultar el precio promedio diario del gas para la cadena de Ethereum; sin embargo, si lo hacemos, el tiempo de consulta será especialmente largo, por lo que filtraremos nuestra consulta a la cantidad promedio de gas pagada por transacción por la Ethereum Foundation. -![](./ef_daily_gas.png) +![Gráfico que muestra el uso diario de gas de la Fundación Ethereum](./ef_daily_gas.png) Podemos ver los precios del gas pagados por todas las transacciones realizadas a la dirección de la Ethereum Foundation a lo largo de los años. Esta es la consulta: diff --git a/public/content/translations/es/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md b/public/content/translations/es/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md index d2b1fc7c7b6..7f07f24856a 100644 --- a/public/content/translations/es/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md +++ b/public/content/translations/es/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md @@ -117,23 +117,23 @@ sudo systemctl start grafana-server Cuando tenga Grafana en ejecución, se podrá acceder a él en `localhost:3000`. Use su navegador preferido para acceder a esta ruta, luego inicie sesión con las credenciales predeterminadas (usuario: `admin` y contraseña: `admin`). Cuando se le solicite, cambie la contraseña predeterminada y guárdela. -![](./grafana1.png) +![Captura de pantalla del panel de Grafana para el monitoreo de Geth (panel 1)](./grafana1.png) Será redirigido a la página de inicio de Grafana. Primero, configure sus datos de origen. Haga clic en el icono de configuración de la barra izquierda y seleccione "Fuentes de datos". -![](./grafana2.png) +![Captura de pantalla del panel de Grafana para el monitoreo de Geth (panel 2)](./grafana2.png) Aún no se ha creado ninguna fuente de datos; haga clic en "Añadir fuente de datos" para definir una. -![](./grafana3.png) +![Captura de pantalla del panel de Grafana para el monitoreo de Geth (panel 3)](./grafana3.png) Para esta configuración, seleccione "InfluxDB" y continúe. -![](./grafana4.png) +![Captura de pantalla del panel de Grafana para el monitoreo de Geth (panel 4)](./grafana4.png) La configuración de la fuente de datos es bastante sencilla si está ejecutando las herramientas en la misma máquina. Necesita establecer la dirección de InfluxDB y los detalles para acceder a la base de datos. Consulte la imagen de abajo. -![](./grafana5.png) +![Captura de pantalla del panel de Grafana para el monitoreo de Geth (panel 5)](./grafana5.png) Si todo está completo y se puede acceder a InfluxDB, haga clic en "Guardar y probar" y espere a que aparezca la confirmación. diff --git a/public/content/translations/es/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/translations/es/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index 2ef6b047122..00000000000 --- a/public/content/translations/es/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1146 +0,0 @@ ---- -title: Probar tokens ERC-20 con Waffle -description: "Aprende cómo probar smart contracts en Solidity y utiliza comparadores de smart contracts con Waffle." -author: Vladislav Starostenko -tags: - - "waffle" - - "contratos inteligentes" - - "solidity" - - "pruebas" - - "erc-20" -skill: intermediate -lang: es -published: 2020-10-16 ---- - -En este tutorial aprenderás como: - -- Escribir pruebas para smart contracts con Waffle -- Usar algunos de los matchers populares para probar smart contracts con Waffle - -Supuestos: - -- sabes cómo usar una terminal, -- puedes crear un proyecto nuevo en `JavaScript`, -- has escrito líneas de código en `Solidity`, -- has escrito pruebas en `JavaScript`, -- has usado `yarn` o `npm`, o el instalador de paquetes de JavaScript. - -Si una de las suposiciones previas no encajan, o no planeas reproducir el código en este artículo, puede ser que no tengas ningún inconveniente leyendo este articulo. - -## Un vistazo a Waffle {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io) es la biblioteca más avanzada para escribir y probar smart contracts. - -Funciona con ethers-js, un [API de JavaScript](/developers/docs/apis/javascript/). - -¡Puedes leer más detalles en la [documentación de Waffle](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation)! - -## Tutorial rápido {#the-quick-tutorial} - -Lo primero es lo primero, crea un nuevo proyecto `JavaScript` o `TypeScript` ( Utiliza `TS`, pero si utilizas `JS` no hay problema) : - -Algo como esto: - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## Paso #1: Instala Waffle en tu proyecto [Link](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) {#step-1-install-waffle-in-your-project} - -Para comenzar, instale `ethereum-waffle`. En este tutorial usaré `yarn`; para instalar `ethereum-waffle`, ejecute: - -```bash - yarn add --dev ethereum-waffle -``` - -## Paso #2: Escribe un contrato inteligente [Link](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract) {#step-2-write-a-smart-contract} - -En este tutorial, usaré el token [ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol) de [OpenZeppelin](https://openzeppelin.com). - -Por lo tanto, añade `OpenZeppelin` instalándolo con `yarn`: - -```bash - yarn add @openzeppelin/contracts -D -``` - -Luego cree el contrato `BasicToken.sol` en el directorio `src`: - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Example class - a mock class using delivering from ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## Paso #3: Compila tu contrato inteligente [Link](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) {#step-3-compile-your-smart-contract} - -Para compilar su contrato inteligente, agregue la siguiente entrada en el `package.json` de su proyecto: - -```json -{ - "scripts": { - "build": "waffle" - } -} -``` - -También, agregue el archivo `waffle.json` en el directorio principal de su proyecto. - -Un ejemplo de la configuración de `waffle.json`: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Puede leer más acerca de la configuración de Waffle [aquí](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration). - -Luego ejecute simplemente `yarn build` para compilar su contrato inteligente. - -Debería ver que Waffle ha compilado el contrato y ha ubicado la salida JSON resultante dentro del directorio `build`. - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 P -``` - -
- -## Paso #4: Compila tu contrato inteligente [Link](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-test-your-smart-contract} - -### Paso #4.1: Instala Waffle en tu proyecto [Link](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-1} - -Después de haber creado con éxito un Contrato Inteligente, podemos probarlo. Utilizaremos `Waffle` para hacerlo. - -Las pruebas en `Waffle` se escriben usando `Mocha` junto con `Chai`. Podemos usar un entorno de prueba diferente, pero los emparejadores `Waffle` solo funcionan con `Chai`. - -Por lo tanto, necesitamos añadir `Chai` a nuestras dependencias : - -```bash - yarn add --dev mocha chai -``` - -### Paso #4.2: Escribe un contrato inteligente de prueba [Link](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-2} - -Para escribir nuestra prueba necesitamos crear el archivo `BasicToken.test.ts` en nuestro directorio de pruebas. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -Por lo tanto, utilizamos el método `deployContract` de `Waffle`para desplegar nuestro token. Como argumentos, debemos pasar `wallet`, el archivo json compilado de nuestro contrato y el balance por defecto. - -`Waffle` también nos permite crear un `wallet`, lo que hace muy sencillo implementar un contrato. - -Puede leer más sobre `monedero` [aquí](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets) y puede leer más sobre la función de despliegue [aquí](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts). - -Vamos a escribir una prueba simple para comprobar el balance de nuestra cartera. Desde que enviamos el valor 1000 durante el despliegue de nuestro contrato, el saldo de nuestra cartera debe ser de 1000 tokens, que podemos comprobar en la primera prueba. - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -Para ejecutar la prueba usa `yarn test` - -### Paso #4.3 Emisión de eventos [Enlace al documento](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events) {#step-4-3} - -En este tutorial, quiero mostrarte los emparejadores más útiles de `Waffle`, así que comencemos con el primero. - -`Waffle` nos permite probar qué eventos se emiten. - -En este tutorial, probaré el método `transfer` de nuestro contrato. - -En esta prueba, haré una transferencia de una cartera a otra y comprobaré si el evento de `transfer` fue llamado. - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -Además, una gran ventaja de este emparejador es que podemos comprobar con qué argumentos se llamó este evento añadiendo `withArgs` a nuestra prueba. - -¡Esto nos permitirá estar seguros de que nuestra función se llama correctamente! - -### Paso #4.4 Revertir con mensaje [Enlace al documento](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message) {#step-4-4} - -`Waffle` nos permite probar qué eventos se emiten. - -Utilizaremos `revertedWith` matcher en nuestra prueba para comprobarlo. - -Podemos escribir una prueba en la que realizaremos una transferencia por una cantidad mayor que la que tenemos en nuestra cartera. Y luego comprobaremos si la transacción se ha revertido con el mensaje exacto! - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### Paso #4.5 Cambiar token-balance [Enlace al documento](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance) {#step-4-5} - -`¡Waffle` nos permite comprobar si hay cambios en los balances de las carteras! - -Podemos usar el comparador `changeTokenBalance` para verificar el cambio de balance o el `changeTokenBalances` para una cuenta múltiple. - -El emparejador puede aceptar `números`, `cadenas` y `números` como un cambio de balance. mientras que la dirección debe especificarse como una cartera o un contrato. - -Vamos a escribir la siguiente prueba: - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -Lo anterior es una prueba para una única cartera. - -Y el siguiente para múltiples carteras: - -```ts -it("Send transaction changes sender and receiver balances", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalances([wallet, walletTo], [-200, 200]) -}) -``` - -Se espera que la transacción se pase como callback (necesitamos comprobar el saldo antes de la llamada) o como una respuesta de la transacción. - -## Felicitaciones {#congratulations} - -**¡Felicitaciones! Lo has conseguido a través de mi tutorial. Has dado tu primer gran paso para probar contratos inteligentes con Waffle.** - -**Código de este tutorial que puedes encontrar [aquí](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website).** - -**Más documentación sobre `Waffle` disponible [aquí](https://getwaffle.io).** diff --git a/public/content/translations/es/developers/tutorials/the-graph-fixing-web3-data-querying/index.md b/public/content/translations/es/developers/tutorials/the-graph-fixing-web3-data-querying/index.md index 3a7ecf65fbb..526f75e3633 100644 --- a/public/content/translations/es/developers/tutorials/the-graph-fixing-web3-data-querying/index.md +++ b/public/content/translations/es/developers/tutorials/the-graph-fixing-web3-data-querying/index.md @@ -90,7 +90,7 @@ Primero, hablemos de GraphQL, diseñado e implementado originalmente por Faceboo ![API de GraphQL frente a API REST](./graphql.jpg) -![](./graphql-query.gif) +![Demostración animada de una consulta GraphQL en el patio de juegos Graph](./graphql-query.gif) Las dos imágenes capturan muy bien la esencia de GraphQL. Con la consulta de la derecha podemos definir exactamente qué datos queremos, así que ahí recibimos todo en una única solicitud y nada más que exactamente lo que necesitamos. Un servidor de GraphQL se encarga de obtener todos los datos necesarios, por lo que es increíblemente fácil de usar para el consumidor del frontend. [Esta es una buena explicación](https://www.apollographql.com/blog/graphql-explained) de cómo gestiona exactamente el servidor una consulta, por si le interesa. diff --git a/public/content/translations/es/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/es/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 7e04e787825..00000000000 --- a/public/content/translations/es/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -title: "Waffle: simulación dinámica y pruebas de llamadas a contratos" -description: "Tutorial avanzado de Waffle para el uso de simulaciones dinámicas y pruebas de llamadas a contratos" -author: "Daniel Izdebski" -tags: - [ - "waffle", - "contratos Inteligentes", - "Solidity", - "pruebas", - "simular" - ] -skill: intermediate -lang: es -published: 2020-11-14 ---- - -## ¿De qué trata este tutorial? {#what-is-this-tutorial-about} - -En este tutorial aprenderás cómo: - -- utilizar simulación dinámica -- comprobar las interacciones entre contratos inteligentes - -Suposiciones: - -- ya sabes cómo escribir un contrato inteligente simple en `Solidity` -- ya sabes utilizar `JavaScript` y `TypeScript` -- ya has hecho otros tutoriales de `Waffle` o sabes algunas cosas sobre él - -## Simulación dinámica {#dynamic-mocking} - -¿Por qué es útil la simulación dinámica? Bueno, nos permite escribir pruebas unitarias en lugar de pruebas de integración. ¿Y eso, qué significa? Significa que no tenemos que preocuparnos por las dependencias de los contratos inteligentes, por lo que podremos probarlos de forma aislada. Déjame mostrarte cómo puedes hacerlo. - -### **1. Proyecto** {#1-project} - -Antes de comenzar debemos preparar un proyecto simple node.js: - -```bash -mkdir simulacion-dinamica -cd simulacion-dinamica -mkdir contracts src - -yarn init -# o si estás usando npm -npm init -``` - -Comencemos agregando dependencias de typescript y prueba: mocha y chai: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# o si estás usando npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Ahora agreguemos `Waffle` y `ethers`: - -```bash -yarn add --dev ethereum-waffle ethers -# o si estás usando npm -npm install ethereum-waffle ethers --save-dev -``` - -La estructura de tu proyecto debería verse así: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Contrato inteligente** {#2-smart-contract} - -Para comenzar una simulación dinámica, necesitamos un contrato inteligente con dependencias. No te preocupes, ¡yo me encargo! - -Aquí hay un contrato inteligente simple escrito en `Solidity` cuyo único propósito es comprobar si somos ricos. Utiliza el token ERC20 para comprobar si tenemos suficientes tokens. Ponlo en `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Como queremos utilizar la simulación dinámica no necesitamos el ERC20 completo, por eso estamos utilizando la interfaz de IERC20 con sólo una función. - -¡Es hora de construir este contrato! Para ello utilizaremos `Waffle`. Primero, vamos a crear un archivo de configuración simple `waffle.json` que especifica las opciones de compilación. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Ahora estamos listos para crear el contrato con Waffle: - -```bash -npx waffle -``` - -Fácil, ¿verdad? En la carpeta `build/` aparecieron dos archivos correspondientes al contrato y la interfaz. Los utilizaremos luego para las pruebas. - -### **3. Pruebas** {#3-testing} - -Creemos un archivo llamado `AmIRichAlready.test.ts` para estas pruebas. Antes que nada, tenemos que gestionar las importaciones. Las necesitaremos luego: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -Aparte de las dependencias de JS, necesitamos importar nuestro contrato compilado y la interfaz: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle utiliza `chai` para las pruebas. Sin embargo, antes de utilizarlo, debemos insertar los emparejadores de Waffle en el propio chai: - -```typescript -use(solidity) -``` - -Necesitamos implementar una función `beforeEach()` que restablezca el estado del contrato antes de cada prueba. Pensemos primero en lo que necesitamos allí. Para desplegar un contrato, necesitamos dos cosas: una billetera y un contrato ERC20 desplegado para pasarlo como argumento del contrato `AmIRichAlready`. - -Primero, creamos la billetera: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Luego debemos desplegar un contrato ERC20. Aquí está la parte difícil: sólo tenemos una interfaz. Esta es la parte en que Waffle viene a salvarnos. Waffle tiene una función mágica `deployMockContract()` que crea un contrato usando únicamente el _abi_ de la interfaz: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Ahora con la billetera y el ERC20 desplegado, podemos continuar e implementar el contrato `AmIRichAlready`: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -Con todo eso, nuestra función `beforeEach()` está terminada. Hasta aquí, tu archivo `AmIRichAlready.test.ts` debería verse así: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Escribamos la primera prueba para el contrato `AmIRichAlready`. ¿De qué crees que debería ser nuestra prueba? ¡Sí, tienes razón! Deberíamos comprobar si ya somos ricos :) - -Pero espera un segundo. ¿Cómo sabrá nuestro contrato simulado qué valores devolver? No hemos implementado ninguna lógica para la función `balanceOf()`. Nuevamente, Waffle nos puede ayudar. Nuestro contrato simulado tiene algunas cosas nuevas: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -Con este conocimiento podemos, finalmente, escribir nuestra primera prueba: - -```typescript -it("devuelve «false» si la billetera tiene menos de 1000000 tokens", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Separemos esta prueba en partes: - -1. Establecimos nuestro contrato ERC20 simulado para devolver siempre un saldo de 999999 tokens. -2. Comprobar si el método `contract.check()` devuelve `false`. - -Estamos listos para liberar a la bestia: - -![Una prueba superada](./test-one.png) - -Así que la prueba funciona, pero... todavía hay margen de mejora. La función `balanceOf()` siempre devolverá 999999. Podemos mejorarla especificando una billetera para la que la función devolverá algo, como un contrato real: - -```typescript -it("devuelve «false» si la billetera tiene menos de 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Hasta el momento, sólo probamos el caso donde aún no somos suficientemente ricos. Probemos el opuesto esta vez: - -```typescript -it("devuelve «true» si la billetera tiene al menos 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Ejecutas las pruebas... - -![Dos pruebas superadas](./test-two.png) - -... ¡y aquí está! Nuestro contrato parece funcionar según lo previsto :) - -## Prueba de llamadas a contratos {#testing-contract-calls} - -Veamos lo que hicimos hasta ahora. Hemos probado la funcionalidad de nuestro contrato `AmIRichAlready` y parece que funciona correctamente. Esto significa que terminamos, ¿verdad? ¡No exactamente! Waffle nos permite probar nuestro contrato aún más. ¿Pero cómo? Bueno, en el arsenal de Waffle están los emparejadores `calledOnContract()` y `calledOnContractWith()`. Nos permitirán comprobar si nuestro contrato llamó al contrato simulado de ERC20. Aquí hay una prueba básica con uno de estos emparejadores: - -```typescript -it("comprueba si el contrato llamó a balanceOf en el token ERC20", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Podemos ir aún más lejos y mejorar esta prueba con el otro emparejador del que te hablé: - -```typescript -it("comprueba si el contrato llamó a balanceOf con una billetera determinada en el token ERC20", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Vamos a comprobar si las pruebas fueron correctas: - -![Tres pruebas superadas](./test-three.png) - -Genial, todas las pruebas están verdes. - -Probar las llamadas de contrato con Waffle es muy fácil. Y aquí está la mejor parte. ¡Estos emparejadores funcionan tanto con contratos normales como simulados! Esto se debe a que Waffle registra y filtra las llamadas de la EVM en lugar de inyectar código, como es el caso de las librerías de prueba populares para otras tecnologías. - -## La recta final {#the-finish-line} - -¡Enhorabuena! Ahora sabes cómo usar Waffle para probar las llamadas de contrato y contratos simulados de forma dinámica. Hay características mucho más interesantes que descubrir. Recomiendo revisar la documentación de Waffle. - -La documentación de Waffle está disponible [aquí](https://ethereum-waffle.readthedocs.io/). - -El código fuente de este tutorial se puede encontrar [aquí](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Otros tutoriales que podrían interesarte: - -- [Prueba de contratos inteligentes con Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/es/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/es/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 62d3105a3dc..00000000000 --- a/public/content/translations/es/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "Tutorial de Waffle «Hola, mundo» con Hardhat y ethers" -description: Cree su primer proyecto de Waffle con Hardhat y ethers.js -author: "MiZiet" -tags: - [ - "waffle", - "contratos Inteligentes", - "Solidity", - "pruebas", - "hardhat", - "ethers.js" - ] -skill: beginner -lang: es -published: 2020-10-16 ---- - -En este tutorial de [Waffle](https://ethereum-waffle.readthedocs.io), aprenderemos a configurar un proyecto simple de contrato inteligente «Hola, mundo», utilizando [hardhat](https://hardhat.org/) y [ethers.js](https://docs.ethers.io/v5/). Luego aprenderemos cómo añadir una nueva funcionalidad a nuestro contrato inteligente y cómo probarlo con Waffle. - -Empecemos creando un nuevo proyecto: - -```bash -yarn init -``` - -o - -```bash -npm init -``` - -y la instalación de los paquetes necesarios: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -o - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -El siguiente paso es crear un proyecto de muestra de Hardhat ejecutando `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Welcome to Hardhat v2.0.3 👷‍ - -? What do you want to do? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -Seleccione `Create a sample project` - -La estructura de nuestro proyecto debería verse así: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Ahora hablemos de algunos de estos archivos: {#now-lets-talk} - -- Greeter.sol: nuestro contrato inteligente escrito en Solidity; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Desplegando un Greeter con el saludo:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Cambiando el saludo de '%s' a '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Nuestro contrato inteligente se puede dividir en tres partes: - -1. constructor: donde declaramos una variable de tipo cadena llamada `greeting`, -2. función greet: una función que devolverá el `greeting` al ser invocada, -3. función setGreeting: una función que nos permite cambiar el valor de `greeting`. - -- sample-test.js: nuestro archivo de pruebas - -```js -describe("Greeter", function () { - it("Debería devolver el nuevo saludo una vez que se ha cambiado", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### El siguiente paso consiste en compilar nuestro contrato y ejecutar las pruebas: {#compiling-and-testing} - -Las pruebas de Waffle utilizan Mocha (un marco de pruebas) con Chai (una biblioteca de aserciones). Todo lo que tiene que hacer es ejecutar `npx hardhat test` y esperar a que aparezca el siguiente mensaje. - -```bash -✓ Should return the new greeting once it's changed -``` - -### Todo parece ir bien hasta ahora. Añadamos un poco más de complejidad a nuestro proyecto {#adding-complexity} - -Imagine una situación en la que alguien añade una cadena vacía como saludo. No sería un saludo muy cálido, ¿verdad? -Asegurémonos de que eso no ocurra: - -Queremos usar el `revert` de Solidity cuando alguien pase una cadena vacía. Lo bueno es que podemos probar fácilmente esta funcionalidad con el comparador de Chai de Waffle `to.be.revertedWith()`. - -```js -it("Debería revertir al pasar una cadena vacía", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "El saludo no debe estar vacío" - ) -}) -``` - -Parece que nuestra nueva prueba no ha pasado: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -Implementemos esta funcionalidad en nuestro contrato inteligente: - -```solidity -require(bytes(_greeting).length > 0, "El saludo no debe estar vacío"); -``` - -Ahora, nuestra función setGreeting se ve así: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "El saludo no debe estar vacío"); -console.log("Cambiando el saludo de '%s' a '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Ejecutemos las pruebas de nuevo: - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -¡Enhorabuena! ¡Lo ha conseguido! :) - -### Conclusión {#conclusion} - -Hemos creado un proyecto sencillo con Waffle, Hardhat y ethers.js. Hemos aprendido a configurar un proyecto, añadir una prueba e implementar una nueva funcionalidad. - -Para ver más comparadores de Chai excelentes con los que probar sus contratos inteligentes, consulte la [documentación oficial de Waffle](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/translations/es/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/es/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index 4bf3eb81b4c..00000000000 --- a/public/content/translations/es/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: Prueba de un contrato inteligente simple con la biblioteca Waffle -description: Tutorial para principiantes -author: Ewa Kowalska -tags: - [ - "contratos Inteligentes", - "Solidity", - "Waffle", - "pruebas" - ] -skill: beginner -lang: es -published: 2021-02-26 ---- - -## En este tutorial aprenderá a {#in-this-tutorial-youll-learn-how-to} - -- Probar los cambios en el saldo de la billetera -- Probar la emisión de eventos con argumentos específicos -- Afirmar que una transacción ha sido revertida - -## Supuestos {#assumptions} - -- Puede crear un nuevo proyecto de JavaScript o TypeScript -- Tiene algo de experiencia básica con pruebas en JavaScript -- Ha usado algunos administradores de paquetes como yarn o npm -- Posee conocimientos muy básicos sobre contratos inteligentes y Solidity - -## Primeros pasos {#getting-started} - -El tutorial demuestra la configuración y ejecución de la prueba usando yarn, pero no hay problema si prefiere npm. Proporcionaré las referencias adecuadas a la [documentación](https://ethereum-waffle.readthedocs.io/en/latest/index.html) oficial de Waffle. - -## Instalar dependencias {#install-dependencies} - -[Añada](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) las dependencias ethereum-waffle y typescript a las dependencias de desarrollo de su proyecto. - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## Ejemplo de contrato inteligente {#example-smart-contract} - -Durante el tutorial trabajaremos en un ejemplo de contrato inteligente simple: EtherSplitter. No hace mucho más que permitir que cualquiera envíe wei y los divida en partes iguales entre dos receptores predefinidos. -La función `split` requiere que la cantidad de wei sea par; de lo contrario, se revertirá. Para ambos receptores, realiza una transferencia de wei seguida de la emisión del evento `Transfer`. - -Coloque el fragmento de código de EtherSplitter en `src/EtherSplitter.sol`. - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'No se permite una cantidad impar de wei'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## Compilar el contrato {#compile-the-contract} - -Para [compilar](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) el contrato, añada la siguiente entrada al archivo package.json: - -```json -"scripts": { - "build": "waffle" - } -``` - -A continuación, cree el archivo de configuración de Waffle en el directorio raíz del proyecto, `waffle.json`, y pegue allí la siguiente configuración: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Ejecute `yarn build`. Como resultado, aparecerá el directorio `build` con el contrato EtherSplitter compilado en formato JSON. - -## Configuración de la prueba {#test-setup} - -Probar con Waffle requiere el uso de los matchers de Chai y Mocha, por lo que necesita [añadirlos](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) a su proyecto. Actualice su archivo package.json y añada la entrada `test` en la parte de scripts: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -Si desea [ejecutar](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) sus pruebas, simplemente ejecute `yarn test`. - -## Pruebas {#testing} - -Ahora cree el directorio `test` y el nuevo archivo `test\EtherSplitter.test.ts`. -Copie el siguiente fragmento y péguelo en nuestro archivo de prueba. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Ether Splitter", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // añada las pruebas aquí -}) -``` - -Unas palabras antes de empezar. -`MockProvider` viene con una versión de simulación de la cadena de bloques. También proporciona billeteras de simulación que nos servirán para probar el contrato EtherSplitter. Podemos obtener hasta diez billeteras llamando al método `getWallets()` en el proveedor. En el ejemplo, obtenemos tres billeteras: para el emisor y para dos receptores. - -A continuación, declaramos una variable llamada «splitter», que es nuestro contrato de simulación EtherSplitter. Se crea antes de cada ejecución de una única prueba mediante el método `deployContract`. Este método simula la implementación de un contrato desde la billetera pasada como primer parámetro (la billetera del emisor en nuestro caso). El segundo parámetro es la ABI y el bytecode del contrato probado. Allí pasamos el archivo json del contrato EtherSplitter compilado desde el directorio `build`. El tercer parámetro es un array con los argumentos del constructor del contrato, que en nuestro caso son las dos direcciones de los receptores. - -## changeBalances {#changebalances} - -Primero, comprobaremos si el método `split` cambia realmente los saldos de las billeteras de los receptores. Si dividimos 50 wei de la cuenta del emisor, esperaríamos que los saldos de ambos receptores aumentaran en 25 wei. Usaremos el matcher `changeBalances` de Waffle: - -```ts -it("Cambia los saldos de las cuentas", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -Como primer parámetro del matcher, pasamos un array de las billeteras de los receptores y, como segundo, un array de los aumentos esperados en las cuentas correspondientes. -Si quisiéramos comprobar el saldo de una billetera específica, también podríamos usar el matcher `changeBalance`, que no requiere pasar arrays, como en el siguiente ejemplo: - -```ts -it("Cambia el saldo de la cuenta", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -Tenga en cuenta que en ambos casos de `changeBalance` y `changeBalances` pasamos la función `split` como un callback porque el matcher necesita acceder al estado de los saldos antes y después de la llamada. - -A continuación, probaremos si el evento `Transfer` se emitió después de cada transferencia de wei. Pasaremos a otro matcher de Waffle: - -## Emit {#emit} - -```ts -it("Emite un evento en la transferencia al primer receptor", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("Emite un evento en la transferencia al segundo receptor", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -El matcher `emit` nos permite comprobar si un contrato emitió un evento al llamar a un método. Como parámetros para el matcher `emit`, proporcionamos el contrato de simulación que predecimos que emitirá el evento, junto con el nombre de ese evento. En nuestro caso, el contrato de simulación es `splitter` y el nombre del evento es `Transfer`. También podemos verificar los valores precisos de los argumentos con los que se emitió el evento: pasamos tantos argumentos al matcher `withArgs` como espera nuestra declaración de evento. En el caso del contrato EtherSplitter, pasamos las direcciones del emisor y del receptor junto con la cantidad de wei transferida. - -## revertedWith {#revertedwith} - -Como último ejemplo, comprobaremos si la transacción fue revertida en caso de una cantidad impar de wei. Usaremos el matcher `revertedWith`: - -```ts -it("Se revierte cuando la cantidad de wei es impar", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "No se permite una cantidad impar de wei" - ) -}) -``` - -La prueba, si se supera, nos asegurará que la transacción fue revertida. Sin embargo, también debe haber una coincidencia exacta entre los mensajes que pasamos en la declaración `require` y el mensaje que esperamos en `revertedWith`. Si volvemos al código del contrato EtherSplitter, en la declaración `require` para la cantidad de wei, proporcionamos el mensaje: «No se permite una cantidad impar de wei». Esto coincide con el mensaje que esperamos en nuestra prueba. Si no fueran iguales, la prueba fallaría. - -## ¡Felicitaciones! {#congratulations} - -¡Ha dado su primer gran paso hacia la prueba de contratos inteligentes con Waffle! diff --git a/public/content/translations/es/roadmap/verkle-trees/index.md b/public/content/translations/es/roadmap/verkle-trees/index.md index c9728a88109..7ab81785728 100644 --- a/public/content/translations/es/roadmap/verkle-trees/index.md +++ b/public/content/translations/es/roadmap/verkle-trees/index.md @@ -39,7 +39,7 @@ El tamaño del testigo varía dependiendo del número de hojas que incluya. Supo Los árboles de Verkle son pares `(clave,valor)` donde las claves son elementos de 32 bytes compuestos por un _tallo_ de 31 bytes y un _sufijo_ de un solo byte. Estas claves se organizan en nodos de _extensión_ y nodos _internos_. Los nodos de extensión representan una sola raíz para 256 hijos con diferentes sufijos. Los nodos internos también tienen 256 hijos, pero pueden ser otros nodos de extensión. La principal diferencia entre el árbol Verkle y la estructura del árbol Merkle es que el árbol Verkle es mucho más plano, lo que significa que hay menos nodos intermedios que conectan una hoja con la raíz y, por lo tanto, menos datos necesarios para generar una prueba. -![](./verkle.png) +![Diagrama de una estructura de datos de árbol de Verkle](./verkle.png) [Lea más sobre la estructura de los árboles de Verkle](https://blog.ethereum.org/2021/12/02/verkle-tree-structure) diff --git a/public/content/translations/es/what-are-apps/index.md b/public/content/translations/es/what-are-apps/index.md index fe0b479e976..0864ba8f144 100644 --- a/public/content/translations/es/what-are-apps/index.md +++ b/public/content/translations/es/what-are-apps/index.md @@ -50,7 +50,7 @@ Las aplicaciones funcionan mediante contratos inteligentes - bits de código que
-![](./developers-eth-blocks.png) +![Ilustración de la construcción del bloque desarrollador de Ethereum](./developers-eth-blocks.png)
## Las aplicaciones de Ethereum son como piezas de lego {#how-does-it-work} diff --git a/public/content/translations/fr/community/support/faq/index.md b/public/content/translations/fr/community/support/faq/index.md new file mode 100644 index 00000000000..d04fb416308 --- /dev/null +++ b/public/content/translations/fr/community/support/faq/index.md @@ -0,0 +1,77 @@ +--- +title: "Questions fréquemment posées" +description: "Questions fréquentes sur Ethereum concernant les portefeuilles, les transactions, la mise en jeu et plus encore." +lang: fr +--- + +# Foire aux questions {#faq} + +## J'ai envoyé de la crypto à la mauvaise adresse {#wrong-wallet} + +Les transactions effectuées sur Ethereum sont irréversibles. Malheureusement, si vous avez envoyé des ETH ou des jetons au mauvais portefeuille, il n'y a aucun moyen d'annuler la transaction. + +**Ce que vous pouvez faire :** + +- **Si vous connaissez le propriétaire de l'adresse**, contactez-le directement et demandez-lui de vous retourner les fonds +- **Si l'adresse appartient à un échange ou à un service connu**, contactez leur équipe d'assistance, car ils pourraient être en mesure de vous aider +- **Si vous avez envoyé des jetons à une adresse de contrat**, vérifiez si le contrat dispose d'une fonction de retrait ou de récupération (ce qui est rare) + +Dans la plupart des cas, il n'y a aucun moyen de récupérer les fonds. Aucune organisation centrale, entité ou personne n'est propriétaire d'Ethereum, ce qui signifie que personne ne peut annuler les transactions. Vérifiez toujours deux fois l'adresse du destinataire avant de confirmer. + +## J'ai perdu l'accès à mon portefeuille {#lost-wallet-access} + +Vos options de récupération dépendent du type de portefeuille que vous utilisez. + +### Si vous avez votre phrase de récupération + +Vous pouvez restaurer votre portefeuille dans n'importe quelle application de portefeuille compatible à l'aide de votre phrase de récupération. C'est pourquoi il est essentiel de conserver votre phrase de récupération en toute sécurité hors ligne. Consultez la documentation de votre fournisseur de portefeuille pour obtenir les instructions de restauration. + +### Si vous avez perdu votre phrase de récupération + +Sans votre phrase de récupération ou vos clés privées, vos fonds ne peuvent pas être récupérés. Personne, y compris ethereum.org, ne peut réinitialiser votre mot de passe ou restaurer l'accès à un portefeuille non-dépositaire. + +### Si votre compte se trouve sur un échange + +Si votre compte se trouve sur un échange centralisé comme Coinbase, Binance ou Kraken, contactez directement l'équipe d'assistance de l'échange. Ils contrôlent les comptes sur leur plateforme et peuvent être en mesure de vous aider à réinitialiser votre mot de passe ou à récupérer votre compte. + + + + + + +**Ne partagez jamais votre phrase de récupération avec quiconque** prétendant vous aider à récupérer votre portefeuille. C'est l'une des tactiques d'escroquerie les plus courantes. Aucun service légitime ne vous demandera jamais votre phrase de récupération. + + + + + + Comment utiliser un portefeuille + + +## Ma transaction est bloquée ou en attente {#stuck-transaction} + +Les transactions sur Ethereum peuvent être bloquées lorsque les frais de gaz que vous avez définis sont inférieurs à ce que le réseau exige actuellement. La plupart des portefeuilles vous permettent de résoudre ce problème : + +- **Accélérer :** Soumettre à nouveau la même transaction avec des frais de gaz plus élevés +- **Annuler :** Envoyer une transaction de 0 ETH à votre propre adresse en utilisant le même nonce que la transaction en attente + +### Guides utiles + +- [Comment accélérer ou annuler une transaction en attente sur MetaMask](https://support.metamask.io/transactions-and-gas/transactions/how-to-speed-up-or-cancel-a-pending-transaction/) +- [Comment annuler les transactions Ethereum en attente](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) + +## Comment puis-je réclamer mon cadeau Ethereum ? {#giveaway-scam} + +Les concours Ethereum sont des arnaques conçues pour récupérer vos ETH. Ne vous laissez pas tenter par des offres qui semblent trop belles pour être vraies. Si vous envoyez des ETH à une adresse de concours, vous ne recevrez pas de cadeau et vous ne pourrez pas récupérer vos fonds. + +[En savoir plus sur la prévention des arnaques](/security/#common-scams) + +## Comment puis-je mettre en jeu des ETH ? {#how-to-stake} + +Pour devenir un validateur, vous devez miser 32 ETH dans le contrat de dépôt Ethereum et mettre en place un nœud de validateur. Vous pouvez également participer avec moins d'ETH via des pools de staking. + +Plus d'informations sont disponibles sur nos [pages de staking](/staking/) et sur [la plateforme de lancement du staking](https://launchpad.ethereum.org/). + +## Comment miner de l'Ethereum ? {#mining-ethereum} + +Le minage d'Ethereum n'est plus possible. Le minage a été désactivé lorsque Ethereum est passé de la [preuve de travail](/glossary/#pow) à la [preuve d'enjeu](/glossary/#pos) lors de [La Fusion](/roadmap/merge/) en septembre 2022. Désormais, en place des mineurs, Ethereum dispose de validateurs. Tout le monde peut [mettre en jeu](/glossary/#staking) des ETH et recevoir des récompenses de mise en jeu en exécutant un logiciel de validateur pour sécuriser le réseau. diff --git a/public/content/translations/fr/community/support/index.md b/public/content/translations/fr/community/support/index.md deleted file mode 100644 index b4bfd3eb295..00000000000 --- a/public/content/translations/fr/community/support/index.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Assistance Ethereum -description: "Obtenez de l'aide sur l'écosystème Ethereum." -lang: fr ---- - -# Assistance Ethereum {#support} - -## Assistance Ethereum officielle {#official-support} - -Vous recherchez l'assistance officielle Ethereum ? La première chose que vous devez savoir est le fait qu'Ethereum est décentralisé. Cela signifie qu'aucune organisation, entité ou personne n'est propriétaire d'Ethereum et, de ce fait, il n'existe aucune assistance officielle. - -Comprendre la nature décentralisée d’Ethereum est essentiel car **toute personne prétendant être une assistance officielle pour Ethereum essaie probablement de vous arnaquer !** La meilleure protection contre les escrocs est de vous informer et de prendre la sécurité au sérieux. - - - Sécurité d'Ethereum et prévention des arnaques - - - - Apprendre les fondamentaux d'Ethereum - - -Malgré le manque d'assistance officielle, de nombreux groupes, communautés et projets à travers l'écosystème Ethereum sont heureux de vous aider. Vous pouvez trouver beaucoup d'informations et de ressources utiles sur cette page. Vous avez d'autres questions ? Rejoignez le [Discord ethereum.org](https://discord.gg/ethereum-org), et nous essaierons de vous aider. - -## Foire aux questions {#faq} - -### J'ai envoyé des ETH au mauvais portefeuille {#wrong-wallet} - -Les transactions effectuées sur Ethereum sont irréversibles. Malheureusement, si vous avez envoyé des ETH au mauvais portefeuille, il n'y a aucun moyen de récupérer ces fonds. Aucune organisation centrale, entité ou personne n'est propriétaire d'Ethereum, ce qui signifie que personne ne peut annuler les transactions. Pour cette raison, il est primordial de vérifier deux fois vos transactions avant de les effectuer. - -### Comment puis-je réclamer mon cadeau Ethereum ? {#giveaway-scam} - -Les concours Ethereum sont des arnaques conçues pour récupérer vos ETH. Ne vous laissez pas tenter par des offres qui semblent trop belles pour être vraies — si vous envoyez des ETH vers une adresse de « concours », vous ne recevrez pas de cadeau, et vous ne pourrez pas récupérer vos fonds. - -[En savoir plus sur la prévention des arnaques](/security/#common-scams) - -### Ma transaction est bloquée {#stuck-transaction} - -Les transactions sur Ethereum peuvent parfois se bloquer si vous avez soumis des frais de transactions inférieurs à ceux requis en raison de la demande du réseau. De nombreux portefeuilles offrent la possibilité de renvoyer la même transaction avec des frais de transaction plus élevés, afin de permettre à celle-ci d'être traitée. Vous pouvez aussi annuler une transaction en cours en envoyant une transaction vers votre propre adresse en utilisant le même nonce que la transaction en cours. - -[Comment accélérer ou annuler une transaction en attente sur MetaMask](https://metamask.zendesk.com/hc/en-us/articles/360015489251-How-to-speed-up-or-cancel-a-pending-transaction) - -[Comment annuler les transactions Ethereum en attente](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) - -### Comment miner de l'Ethereum ? {#mining-ethereum} - -Le minage d'Ethereum n'est plus possible. Le minage a été désactivé lorsqu'Ethereum est passé de la [preuve de travail](/glossary/#pow) à la [preuve d'enjeu](/glossary/#pos). Désormais, en place des mineurs, Ethereum dispose de validateurs. Tout le monde peut [mettre en jeu](/glossary/#staking) des ETH et recevoir des récompenses de mise en jeu en exécutant un logiciel de validateur pour sécuriser le réseau. - -### Comment devenir un validateur / faire fonctionner un validateur ? {#how-to-stake} - -Pour devenir un validateur, vous devez miser 32 ETH dans le contrat de dépôt Ethereum et mettre en place un nœud de validateur. Plus d'informations sont disponibles sur nos [pages de staking](/staking) et sur [le launchpad de staking](https://launchpad.ethereum.org/). - -## Créer des dapps {#building-support} - -Le développement d'une application décentralisée peut être difficile. Voici quelques espaces axés sur leur création, avec des développeurs Ethereum chevronnés qui seront heureux de vous faire part de leur expérience. - -- [Alchemy University](https://university.alchemy.com/#starter_code) -- [Discord CryptoDevs](https://discord.com/invite/5W5tVb3) -- [Ethereum StackExchange](https://ethereum.stackexchange.com/) -- [Web3 University](https://www.web3.university/) -- [LearnWeb3](https://discord.com/invite/learnweb3) - -Vous pouvez également trouver de la documentation et des guides de développement dans notre section [ressources pour les développeurs Ethereum](/developers/). - -### Outils {#dapp-tooling} - -Votre question concerne un outil, un projet ou une bibliothèque en particulier ? La plupart des projets disposent de serveurs de discussion ou des forums dédiés au soutien des membres. - -Voici quelques exemples connus : - -- [Solidity](https://app.element.io/#/room/#solidity:matrix.org) -- [ethers.js](https://discord.gg/6jyGVDK6Jx) -- [web3.js](https://discord.gg/GsABYQu4sC) -- [Hardhat](https://discord.gg/xtrMGhmbfZ) -- [Alchemy](http://alchemy.com/discord) -- [Tenderly](https://discord.gg/fBvDJYR) - -## Exécuter un nœud {#node-support} - -Si vous exécutez un nœud ou un validateur, voici quelques communautés qui sont consacrées à aider ceux qui débutent. - -- [Discord EthStaker](https://discord.gg/ethstaker) -- [Reddit EthStaker](https://www.reddit.com/r/ethstaker) - -La plupart des équipes qui créent des clients Ethereum disposent aussi d'espaces dédiés, ouverts au public, dans lesquels vous pouvez obtenir une aide et poser des questions. - -### Clients d'exécution {#execution-clients} - -- [Geth](https://discord.gg/FqDzupGyYf) -- [Nethermind](https://discord.gg/YJx3pm8z5C) -- [Besu](https://discord.gg/p8djYngzKN) -- [Erigon](https://github.com/ledgerwatch/erigon/issues) -- [Reth](https://github.com/paradigmxyz/reth/discussions) - -### Clients de consensus {#consensus-clients} - -- [Prysm](https://discord.gg/prysmaticlabs) -- [Nimbus](https://discord.gg/nSmEH3qgFv) -- [Lighthouse](https://discord.gg/cyAszAh) -- [Teku](https://discord.gg/7hPv2T6) -- [Lodestar](https://discord.gg/aMxzVcr) -- [Grandine](https://discord.gg/H9XCdUSyZd) - -Vous pouvez également [apprendre à exécuter un nœud ici](/developers/docs/nodes-and-clients/run-a-node/). diff --git a/public/content/translations/fr/community/support/misconceptions/index.md b/public/content/translations/fr/community/support/misconceptions/index.md new file mode 100644 index 00000000000..9f382b08983 --- /dev/null +++ b/public/content/translations/fr/community/support/misconceptions/index.md @@ -0,0 +1,73 @@ +--- +title: "Idées reçues sur Ethereum" +description: Clarification des malentendus les plus courants sur le fonctionnement d'Ethereum. +lang: fr +--- + +# Idées reçues sur Ethereum {#misconceptions} + +## Est-ce qu'Ethereum est une entreprise ? {#not-a-company} + +Ethereum est une technologie open-source et décentralisée, maintenue par des milliers de contributeurs dans le monde entier. Il n'existe aucune société appelée « Ethereum » qui gère des comptes, détient des fonds ou fournit un support client. + +La [Fondation Ethereum](https://ethereum.foundation/) est une organisation à but non lucratif qui soutient le développement d'Ethereum, mais elle ne possède ni ne contrôle le réseau. Aucune entité unique ne le fait. + +**[ethereum.org](/)** est une ressource éducative gérée par la communauté. Ce n'est pas une plateforme d'échange, un portefeuille ou une institution financière. Il ne détient aucun fonds d'utilisateur et ne peut accéder à aucun compte. + + + Qu'est-ce qu'Ethereum ? + + +## Quelqu'un peut-il récupérer ou geler mes fonds ? {#no-fund-access} + +Contrairement à une banque, il n'y a pas d'autorité centrale sur Ethereum qui puisse geler, saisir ou récupérer des fonds. La personne détenant les clés privées (ou la phrase de récupération) a un contrôle total et exclusif sur un portefeuille. + +Cela signifie que : + +- **Personne ne peut récupérer les fonds** que vous avez envoyés à la mauvaise adresse +- **Personne ne peut annuler** une transaction après sa confirmation +- **Personne ne peut geler** votre portefeuille ou bloquer vos transactions +- **Personne ne peut réinitialiser votre mot de passe** si vous perdez votre phrase de récupération + +C'est pourquoi il est essentiel de protéger votre phrase de récupération. C'est le seul moyen d'accéder à votre portefeuille. Si elle est perdue ou volée, il n'y a aucune option de récupération. + + + Sécurité d'Ethereum et prévention des arnaques + + +## Puis-je encore miner de l'Ethereum ? {#no-mining} + +Ethereum est passé de la [preuve de travail](/glossary/#pow) à la [preuve d'enjeu](/glossary/#pos) lors de [La Fusion](/roadmap/merge/) en septembre 2022. Le minage n'est plus possible sur Ethereum. + +Le réseau est maintenant sécurisé par des validateurs qui [mettent en jeu](/glossary/#staking) des ETH. Tout le monde peut participer : + +- **Mise en jeu en solo :** Exécutez votre propre validateur avec 32 ETH—[en savoir plus](/staking/solo/) +- **Mise en jeu en tant que service :** Déléguez le fonctionnement des nœuds tout en conservant vos clés—[en savoir plus](/staking/saas/) +- **Mise en jeu en pool :** Misez moins de 32 ETH en rejoignant un pool—[en savoir plus](/staking/pools/) + + + En savoir plus sur la mise en jeu + + +## Existe-t-il une équipe d'assistance Ethereum ? {#no-support-team} + +Rechercher un « support officiel d'Ethereum » est similaire à rechercher un « support officiel d'Internet ». Bien sûr, cela n'existe pas, mais en fonction de votre problème, vous pourrez peut-être obtenir de l'aide auprès de votre fournisseur d'accès à Internet, du fabricant de votre routeur, ou de l'une des entreprises derrière l'appareil, l'application ou le site Web que vous utilisez. + +Ethereum est similaire. Il n'y a pas d'entreprise, d'équipe de support ou de service d'assistance derrière Ethereum dans son ensemble, mais en fonction du problème, vous pouvez trouver de l'aide en contactant votre _fournisseur de portefeuille_, votre _service de mise en jeu_, votre _plateforme d'échange_, votre _institution financière_ ou l'_équipe qui maintient une application_ que vous utilisez. + +Puisqu'Ethereum est publiquement transparent par défaut, vous pouvez également trouver des [explorateurs de blocs](/developers/docs/data-and-analytics/block-explorers/), des [outils d'analyse](/developers/tools/analytics/), et d'autres [ressources d'enquête en ligne](/community/support/scams/#analyze) utiles pour examiner un problème directement. + +Ceci dit, personne d'Ethereum ou d'ethereum.org ne fera jamais ce qui suit : + +- Vous contacter par message direct +- Vous demander votre phrase de récupération ou vos clés privées +- Vous demander d'envoyer des ETH pour vérifier votre portefeuille +- Vous proposer de vous aider à récupérer des fonds contre des frais + +**Toute personne faisant l'une des actions ci-dessus essaie de vous arnaquer.** + +Si vous avez besoin d'aide, les véritables communautés qui peuvent vous aider sont répertoriées sur la [page de support](/community/support/). Ce sont des communautés ouvertes, gérées par des bénévoles, et non des canaux de support officiels. + + + Sécurité d'Ethereum et prévention des arnaques + diff --git a/public/content/translations/fr/community/support/scams/index.md b/public/content/translations/fr/community/support/scams/index.md new file mode 100644 index 00000000000..e816ed1c542 --- /dev/null +++ b/public/content/translations/fr/community/support/scams/index.md @@ -0,0 +1,159 @@ +--- +title: Aide et signalement des arnaques +description: "Que faire si vous avez été victime d'une arnaque, comment sécuriser vos actifs restants et où signaler la fraude." +lang: fr +--- + +# J'ai été victime d'une arnaque ou j'ai perdu des fonds {#scam-help} + +Les arnaques aux cryptomonnaies ciblent des personnes de tous niveaux d'expérience, y compris des professionnels de la finance et de la technologie. Vous n'êtes pas seul, et être ici est un premier pas dans la bonne direction. + + + + + + +**Personne ne peut annuler les transactions sur la blockchain.** Si quelqu'un vous contacte en prétendant pouvoir récupérer vos fonds moyennant des frais, il s'agit presque certainement d'une deuxième arnaque. Voir les [arnaques à la récupération](#recovery-scams) ci-dessous. + + + + +## Sécurisez vos actifs restants {#secure-assets} + +Si vous avez interagi avec un arnaqueur ou si vous soupçonnez que votre portefeuille est compromis, prenez immédiatement les mesures suivantes : + +1. **Transférez les fonds restants** vers un nouveau portefeuille sécurisé auquel l'arnaqueur n'a pas accès +2. **Révoquez les approbations de jetons.** Les arnaqueurs vous piègent souvent pour que vous approuviez des dépenses illimitées de jetons. La révocation de ces autorisations empêche que votre portefeuille ne soit vidé davantage +3. **Changez les mots de passe** de tous les comptes d'échange qui pourraient être liés +4. **Activez l'authentification à deux facteurs (2FA)** sur tous les comptes liés aux cryptomonnaies + +### Comment révoquer les approbations de jetons {#revoke-approvals} + +Lorsque vous interagissez avec une dapp ou un contrat intelligent, vous lui avez peut-être accordé la permission de dépenser vos jetons. Si un arnaqueur vous a piégé en vous faisant approuver un contrat malveillant, il peut continuer à vider vos jetons même après l'arnaque initiale. + +Utilisez ces outils pour vérifier et révoquer les approbations : + +- [Revoke.cash](https://revoke.cash/) : connectez votre portefeuille pour voir toutes les approbations actives et les révoquer +- [Revokescout](https://revoke.blockscout.com/) : vérifiez et révoquez les approbations via Blockscout +- [Etherscan Token Approval Checker](https://etherscan.io/tokenapprovalchecker) : vérifiez et révoquez les approbations via Etherscan + + + Guide étape par étape : Comment révoquer l'accès aux jetons + + +## Signaler les adresses et les sites Web frauduleux {#report} + +Le signalement permet d'avertir les autres utilisateurs et peut aider les forces de l'ordre dans leurs enquêtes. Documentez tout : les hachages de transaction, les adresses de portefeuille, les captures d'écran et toute communication avec l'arnaqueur. + +### Signaler une adresse frauduleuse {#report-address} + +- [Chainabuse](https://www.chainabuse.com/) : base de données communautaire de signalement des arnaques et des fraudes. Soumettez des rapports et recherchez des adresses frauduleuses connues +- [Rapport Etherscan](https://info.etherscan.com/report-address/) : signalez une adresse sur l'explorateur de blocs Ethereum le plus utilisé +- [CryptoScamDB](https://cryptoscamdb.org/) : base de données open-source qui suit les arnaques aux cryptomonnaies + +### Signaler un site Web ou un compte de réseau social frauduleux {#report-website} + +- [PhishTank](https://phishtank.org/) : soumettez et vérifiez les URL d'hameçonnage +- [Google Safe Browsing](https://safebrowsing.google.com/safebrowsing/report_phish/) : signalez les sites d'hameçonnage à Google afin qu'ils soient bloqués dans Chrome et d'autres navigateurs +- [Netcraft](https://report.netcraft.com/report/mistake) : signalez les sites Web malveillants et frauduleux +- Signalez directement sur la plateforme de réseau social où l'arnaque a eu lieu (Twitter/X, Discord, Telegram ont tous des fonctionnalités de signalement) + +### Signaler aux forces de l'ordre {#report-law-enforcement} + +- **États-Unis :** [FBI Internet Crime Complaint Center (IC3)](https://www.ic3.gov/) +- **Royaume-Uni :** [Action Fraud](https://www.actionfraud.police.uk/) +- **Union européenne :** [Europol](https://www.europol.europa.eu/report-a-crime) +- **Autres pays :** déposez une plainte auprès de votre police locale. La fraude à la cryptomonnaie est un crime dans la plupart des juridictions + +## Analysez ce qui s'est passé {#analyze} + +Comprendre où sont allés vos fonds peut aider à la rédaction des rapports et peut soutenir les efforts de récupération si les fonds atterrissent sur un échange centralisé. + +- [Blockscout](https://eth.blockscout.com/) : explorateur de blocs open-source pour rechercher n'importe quel hachage de transaction ou adresse de portefeuille pour voir où les fonds ont été envoyés +- [Etherscan](https://etherscan.io/) : recherchez n'importe quel hachage de transaction ou adresse de portefeuille pour voir où les fonds ont été envoyés +- [Recherche sur Chainabuse](https://www.chainabuse.com/) : vérifiez si une adresse a déjà été signalée par d'autres victimes +- [MetaSleuth](https://metasleuth.io/) par BlockSec : outil visuel de suivi des transactions qui cartographie les flux de fonds + +**Si des fonds ont été envoyés à un échange centralisé** (comme Coinbase, Binance, Kraken), contactez immédiatement leur équipe de support avec les détails de la transaction. Les échanges peuvent parfois geler les comptes signalés pour fraude. + +## La dure vérité {#hard-truth} + +Parce qu'Ethereum est décentralisé, aucune autorité centrale ne peut annuler des transactions ou récupérer des fonds volés. Une fois qu'une transaction est confirmée sur la blockchain, elle est définitive. + +Le signalement reste utile. Les rapports aident les forces de l'ordre à suivre les réseaux de fraude organisée, et le signalement d'adresses sur Chainabuse et Etherscan avertit les futures victimes potentielles. + +## Types d'arnaques à surveiller {#scam-types} + + + +Les arnaqueurs créent de faux cadeaux promettant de multiplier vos ETH ou de vous donner des jetons gratuits. Ils se font souvent passer pour des personnalités connues comme Vitalik Buterin. Si vous envoyez des ETH à une adresse de "cadeau", vous ne recevrez rien en retour. + +**Rappelez-vous :** Vitalik et d'autres personnalités ne vous demanderont jamais de leur envoyer des ETH. + +[En savoir plus sur les arnaques courantes](/security/#common-scams) + + + + +Les arnaqueurs se font passer pour des membres de l'équipe Ethereum, des modérateurs ou des agents de support sur Discord, Telegram et les réseaux sociaux. Ils peuvent vous envoyer des messages directs pour vous offrir de l'aide ou prétendre qu'il y a un problème avec votre compte. + +**Rappelez-vous :** + +- Il n'y a pas d'"équipe de support Ethereum" +- Les vrais modérateurs ne vous enverront jamais de message privé en premier +- Ne partagez jamais votre phrase de récupération ou vos clés privées avec qui que ce soit, pour quelque raison que ce soit. +- Ne cliquez jamais sur les liens envoyés dans des messages non sollicités. + + + + +Les arnaques à la récupération ciblent spécifiquement les personnes qui ont déjà perdu des fonds. Les arnaqueurs surveillent les réseaux sociaux à la recherche de personnes parlant d'avoir été arnaquées, puis les contactent en se faisant passer pour des "enquêteurs blockchain" ou des "experts en récupération de cryptomonnaies". + +Ils promettent de tracer et de récupérer vos cryptomonnaies volées contre des frais initiaux. Après que vous ayez payé, ils disparaissent. + +**Aucun service légitime ne peut annuler les transactions de la blockchain.** Quiconque promet cela ment. C'est l'une des arnaques de suivi les plus courantes. + + + + +Les sites d'hameçonnage ressemblent à de vraies applications de portefeuille, à des échanges ou à des plateformes DeFi. Ils vous piègent pour que vous saisissiez votre phrase de récupération ou que vous connectiez votre portefeuille, puis ils vident vos fonds. + +**Protégez-vous :** + +- Vérifiez toujours l'URL avant de connecter votre portefeuille +- Mettez en favoris les sites officiels que vous utilisez régulièrement +- Ne saisissez jamais votre phrase de récupération sur un site Web. Les applications légitimes ne la demandent jamais +- Utilisez [PhishTank](https://phishtank.org/) pour vérifier les URL suspectes + + + Comment identifier les jetons frauduleux + + + + + Guide complet sur la sécurité d'Ethereum et la prévention des arnaques + diff --git a/public/content/translations/fr/developers/docs/networking-layer/index.md b/public/content/translations/fr/developers/docs/networking-layer/index.md index cfc845e6e51..fc426974c65 100644 --- a/public/content/translations/fr/developers/docs/networking-layer/index.md +++ b/public/content/translations/fr/developers/docs/networking-layer/index.md @@ -146,7 +146,9 @@ Un résumé du flux de contrôle est affiché ci-dessous (la pile réseau pertin Une fois le bloc attesté par suffisamment de validateurs, il est ajouté en tête de la chaîne, justifié et finalisé. -![](cons_client_net_layer.png)\n![](exe_client_net_layer.png) +![Schéma de la couche réseau client consensus Ethereum](cons_client_net_layer.png) + +![Schéma de la couche réseau du client d'exécution Ethereum](exe_client_net_layer.png) Schéma de la couche réseau pour les clients de consensus et d'exécution, de [ethresear.ch](https://ethresear.ch/t/eth1-eth2-client-relationship/7248) diff --git a/public/content/translations/fr/developers/docs/nodes-and-clients/node-architecture/index.md b/public/content/translations/fr/developers/docs/nodes-and-clients/node-architecture/index.md index 7692ac8f322..c26abb21058 100644 --- a/public/content/translations/fr/developers/docs/nodes-and-clients/node-architecture/index.md +++ b/public/content/translations/fr/developers/docs/nodes-and-clients/node-architecture/index.md @@ -10,7 +10,7 @@ Lorsque Ethereum utilisait la [preuve de travail](/developers/docs/consensus-mec Le diagramme ci-dessous montre la relation entre les deux clients Ethereum. Les deux clients se connectent à leurs propres réseaux peer-to-peer (P2P) respectifs. Des réseaux P2P séparés sont nécessaires car les clients d'exécution propagent les transactions sur leur réseau P2P, leur permettant de gérer leur pool de transactions local, tandis que les clients de consensus propagent les blocs sur leur réseau P2P, permettant le consensus et l'accroissement de la chaîne. -![](node-architecture-text-background.png) +![Schéma de l'architecture des nœuds Ethereum montrant les couches d'exécution et de consensus](node-architecture-text-background.png) _Il existe plusieurs options pour le client d’exécution, notamment Erigon, Nethermind et Besu_. diff --git a/public/content/translations/fr/developers/tutorials/ai-trading-agent/index.md b/public/content/translations/fr/developers/tutorials/ai-trading-agent/index.md new file mode 100644 index 00000000000..2cfcd48f5a9 --- /dev/null +++ b/public/content/translations/fr/developers/tutorials/ai-trading-agent/index.md @@ -0,0 +1,980 @@ +--- +title: "Créez votre propre agent de trading IA sur Ethereum" +description: "Dans ce tutoriel, vous apprendrez comment créer un agent de trading IA simple. Cet agent lit les informations de la blockchain, demande une recommandation à un LLM sur la base de ces informations, effectue la transaction que le LLM recommande, puis attend et répète le processus." +author: Ori Pomerantz +tags: [ "IA", "trading", "agent", "python" ] +skill: intermediate +published: 2026-02-13 +lang: fr +sidebarDepth: 3 +--- + +Dans ce tutoriel, vous apprendrez comment créer un agent de trading IA simple. Cet agent fonctionne en suivant ces étapes : + +1. Lire les prix actuels et passés d'un jeton, ainsi que d'autres informations potentiellement pertinentes +2. Construire une requête avec ces informations, ainsi que des informations de base pour expliquer en quoi elles pourraient être pertinentes +3. Soumettre la requête et recevoir en retour un prix projeté +4. Trader en fonction de la recommandation +5. Attendre et répéter + +Cet agent montre comment lire des informations, les traduire en une requête qui produit une réponse utilisable, et utiliser cette réponse. Toutes ces étapes sont nécessaires pour un agent IA. Cet agent est implémenté en Python car c'est le langage le plus courant utilisé en IA. + +## Pourquoi faire cela ? {#why-do-this} + +Les agents de trading automatisés permettent aux développeurs de sélectionner et d'exécuter une stratégie de trading. [Les agents IA](/ai-agents) permettent des stratégies de trading plus complexes et dynamiques, en utilisant potentiellement des informations et des algorithmes que le développeur n'a même pas envisagé d'utiliser. + +## Les outils {#tools} + +Ce tutoriel utilise [Python](https://www.python.org/), la [bibliothèque Web3](https://web3py.readthedocs.io/en/stable/), et [Uniswap v3](https://github.com/Uniswap/v3-periphery) pour les cotations et le trading. + +### Pourquoi Python ? {#python} + +Le langage le plus utilisé pour l'IA est [Python](https://www.python.org/), c'est pourquoi nous l'utilisons ici. Ne vous inquiétez pas si vous ne connaissez pas Python. Le langage est très clair, et j'expliquerai exactement ce qu'il fait. + +La [bibliothèque Web3](https://web3py.readthedocs.io/en/stable/) est l'API Python pour Ethereum la plus courante. Elle est assez facile à utiliser. + +### Trader sur la blockchain {#trading-on-blockchain} + +Il existe [de nombreux échanges décentralisés (DEX)](/apps/categories/defi/) qui vous permettent de trader des jetons sur Ethereum. Cependant, ils ont tendance à avoir des taux de change similaires en raison de [l'arbitrage](/developers/docs/smart-contracts/composability/#better-user-experience). + +[Uniswap](https://app.uniswap.org/) est un DEX largement utilisé que nous pouvons utiliser à la fois pour les cotations (pour voir les valeurs relatives des jetons) et pour les transactions. + +### OpenAI {#openai} + +Pour un grand modèle de langage, j'ai choisi de commencer avec [OpenAI](https://openai.com/). Pour exécuter l'application de ce tutoriel, vous devrez payer pour l'accès à l'API. Le paiement minimum de 5 $ est plus que suffisant. + +## Développement, étape par étape {#step-by-step} + +Pour simplifier le développement, nous procédons par étapes. Chaque étape est une branche dans GitHub. + +### Mise en route {#getting-started} + +Voici les étapes pour commencer sous UNIX ou Linux (y compris [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)) + +1. Si vous ne l'avez pas déjà, téléchargez et installez [Python](https://www.python.org/downloads/). + +2. Clonez le dépôt GitHub. + + ```sh + git clone https://github.com/qbzzt/260215-ai-agent.git -b 01-getting-started + cd 260215-ai-agent + ``` + +3. Installez [`uv`](https://docs.astral.sh/uv/getting-started/installation/). La commande sur votre système pourrait être différente. + + ```sh + pipx install uv + ``` + +4. Téléchargez les bibliothèques. + + ```sh + uv sync + ``` + +5. Activez l'environnement virtuel. + + ```sh + source .venv/bin/activate + ``` + +6. Pour vérifier que Python et Web3 fonctionnent correctement, exécutez `python3` et fournissez-lui ce programme. Vous pouvez le saisir à l'invite `>>>` ; il n'est pas nécessaire de créer un fichier. + + ```python + from web3 import Web3 + MAINNET_URL = "https://eth.drpc.org" + w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) + w3.eth.block_number + quit() + ``` + +### Lecture depuis la blockchain {#read-blockchain} + +L'étape suivante consiste à lire les données de la blockchain. Pour ce faire, vous devez passer à la branche `02-read-quote`, puis utiliser `uv` pour exécuter le programme. + +```sh +git checkout 02-read-quote +uv run agent.py +``` + +Vous devriez recevoir une liste d'objets `Quote`, chacun avec un horodatage, un prix et l'actif (actuellement toujours `WETH/USDC`). + +Voici une explication ligne par ligne. + +```python +from web3 import Web3 +from web3.contract import Contract +from decimal import Decimal, ROUND_HALF_UP +from dataclasses import dataclass +from datetime import datetime, timezone +from pprint import pprint +import time +import functools +import sys +``` + +Importez les bibliothèques dont nous avons besoin. Ils sont expliqués ci-dessous lorsqu'ils sont utilisés. + +```python +print = functools.partial(print, flush=True) +``` + +Remplace le `print` de Python par une version qui vide toujours la sortie immédiatement. Ceci est utile dans un script de longue durée car nous ne voulons pas attendre les mises à jour de statut ou les sorties de débogage. + +```python +MAINNET_URL = "https://eth.drpc.org" +``` + +Une URL pour accéder au réseau principal. Vous pouvez en obtenir un auprès d'un [nœud en tant que service](/developers/docs/nodes-and-clients/nodes-as-a-service/) ou utiliser l'un de ceux annoncés dans [Chainlist](https://chainlist.org/chain/1). + +```python +BLOCK_TIME_SECONDS = 12 +MINUTE_BLOCKS = int(60 / BLOCK_TIME_SECONDS) +HOUR_BLOCKS = MINUTE_BLOCKS * 60 +DAY_BLOCKS = HOUR_BLOCKS * 24 +``` + +Un bloc du réseau principal Ethereum est généralement créé toutes les douze secondes, il s'agit donc du nombre de blocs que nous nous attendons à voir créés sur une période donnée. Notez que ce chiffre n'est pas exact. Lorsque le [proposeur de bloc](/developers/docs/consensus-mechanisms/pos/block-proposal/) est hors service, ce bloc est sauté, et le temps pour le bloc suivant est de 24 secondes. Si nous voulions obtenir le bloc exact pour un horodatage, nous utiliserions une [recherche binaire](https://en.wikipedia.org/wiki/Binary_search). Cependant, c'est assez proche pour nos besoins. Prédire l'avenir n'est pas une science exacte. + +```python +CYCLE_BLOCKS = DAY_BLOCKS +``` + +La taille du cycle. Nous examinons les cotations une fois par cycle et essayons d'estimer la valeur à la fin du cycle suivant. + +```python +# L'adresse du pool que nous lisons +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +``` + +Les valeurs de cotation sont extraites du pool Uniswap 3 USDC/WETH à l'adresse [`0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`](https://eth.blockscout.com/address/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640?tab=read_write_contract). Cette adresse est déjà au format checksum, mais il est préférable d'utiliser [`Web3.to_checksum_address`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_checksum_address) pour rendre le code réutilisable. + +```python +POOL_ABI = [ + { "name": "slot0", ... }, + { "name": "token0", ... }, + { "name": "token1", ... }, +] + +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... } +] +``` + +Ce sont les [ABI](https://docs.soliditylang.org/en/latest/abi-spec.html) pour les deux contrats que nous devons contacter. Pour que le code reste concis, nous n'incluons que les fonctions que nous devons appeler. + +```python +w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) +``` + +Initialisez la bibliothèque [`Web3`](https://web3py.readthedocs.io/en/stable/quickstart.html#remote-providers) et connectez-vous à un nœud Ethereum. + +```python +@dataclass(frozen=True) +class ERC20Token: + address: str + symbol: str + decimals: int + contract: Contract +``` + +C'est une façon de créer une classe de données en Python. Le type de données [`Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) est utilisé pour se connecter au contrat. Notez le `(frozen=True)`. En Python, les [booléens](https://en.wikipedia.org/wiki/Boolean_data_type) sont définis comme `True` ou `False`, avec une majuscule. Cette classe de données est `figée` (`frozen`), ce qui signifie que les champs ne peuvent pas être modifiés. + +Notez l'indentation. Contrairement aux [langages dérivés de C](https://en.wikipedia.org/wiki/List_of_C-family_programming_languages), Python utilise l'indentation pour délimiter les blocs. L'interpréteur Python sait que la définition suivante ne fait pas partie de cette classe de données car elle ne commence pas à la même indentation que les champs de la classe de données. + +```python +@dataclass(frozen=True) +class PoolInfo: + address: str + token0: ERC20Token + token1: ERC20Token + contract: Contract + asset: str + decimal_factor: Decimal = 1 +``` + +Le type [`Decimal`](https://docs.python.org/3/library/decimal.html) est utilisé pour gérer avec précision les fractions décimales. + +```python + def get_price(self, block: int) -> Decimal: +``` + +C'est ainsi que l'on définit une fonction en Python. La définition est indentée pour montrer qu'elle fait toujours partie de `PoolInfo`. + +Dans une fonction qui fait partie d'une classe de données, le premier paramètre est toujours `self`, l'instance de la classe de données qui a appelé ici. Ici, il y a un autre paramètre, le numéro de bloc. + +```python + assert block <= w3.eth.block_number, "Le bloc est dans le futur" +``` + +Si nous pouvions lire l'avenir, nous n'aurions pas besoin de l'IA pour le trading. + +```python + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) +``` + +La syntaxe pour appeler une fonction sur l'EVM depuis Web3 est la suivante : `.functions.().call()`. Les paramètres peuvent être les paramètres de la fonction EVM (s'il y en a ; ici, il n'y en a pas) ou des [paramètres nommés](https://en.wikipedia.org/wiki/Named_parameter) pour modifier le comportement de la blockchain. Ici, nous en utilisons un, `block_identifier`, pour spécifier [le numéro de bloc](/developers/docs/apis/json-rpc/#default-block) dans lequel nous souhaitons exécuter. + +Le résultat est [cette structure, sous forme de tableau](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol#L56-L72). La première valeur est une fonction du taux de change entre les deux jetons. + +```python + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 +``` + +Pour réduire les calculs en chaîne, Uniswap v3 ne stocke pas le facteur de change réel mais plutôt sa racine carrée. Comme l'EVM ne prend pas en charge les calculs à virgule flottante ou les fractions, au lieu de la valeur réelle, la réponse est prix296 + +```python + # (jeton1 par jeton0) + return 1/(raw_price * self.decimal_factor) +``` + +Le prix brut que nous obtenons est le nombre de `token0` que nous recevons pour chaque `token1`. Dans notre pool, `token0` est l'USDC (un stablecoin ayant la même valeur qu'un dollar américain) et `token1` est le [WETH](https://opensea.io/learn/blockchain/what-is-weth). La valeur que nous voulons vraiment est le nombre de dollars par WETH, et non l'inverse. + +Le facteur décimal est le rapport entre les [facteurs décimaux](https://docs.openzeppelin.com/contracts/4.x/erc20#a-note-on-decimals) pour les deux jetons. + +```python +@dataclass(frozen=True) +class Quote: + timestamp: str + price: Decimal + asset: str +``` + +Cette classe de données représente une cotation : le prix d'un actif spécifique à un moment donné. À ce stade, le champ `asset` n'est pas pertinent car nous utilisons un seul pool et nous n'avons donc qu'un seul actif. Cependant, nous ajouterons d'autres actifs plus tard. + +```python +def read_token(address: str) -> ERC20Token: + token = w3.eth.contract(address=address, abi=ERC20_ABI) + symbol = token.functions.symbol().call() + decimals = token.functions.decimals().call() + + return ERC20Token( + address=address, + symbol=symbol, + decimals=decimals, + contract=token + ) +``` + +Cette fonction prend une adresse et renvoie des informations sur le contrat de jeton à cette adresse. Pour créer un nouveau [`Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) Web3, nous fournissons l'adresse et l'ABI à `w3.eth.contract`. + +```python +def read_pool(address: str) -> PoolInfo: + pool_contract = w3.eth.contract(address=address, abi=POOL_ABI) + token0Address = pool_contract.functions.token0().call() + token1Address = pool_contract.functions.token1().call() + token0 = read_token(token0Address) + token1 = read_token(token1Address) + + return PoolInfo( + address=address, + asset=f"{token1.symbol}/{token0.symbol}", + token0=token0, + token1=token1, + contract=pool_contract, + decimal_factor=Decimal(10) ** Decimal(token0.decimals - token1.decimals) + ) +``` + +Cette fonction renvoie tout ce dont nous avons besoin à propos d'[un pool spécifique](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol). La syntaxe `f""` est une [chaîne de caractères formatée](https://docs.python.org/3/reference/lexical_analysis.html#f-strings). + +```python +def get_quote(pool: PoolInfo, block_number: int = None) -> Quote: +``` + +Obtenez un objet `Quote`. La valeur par défaut pour `block_number` est `None` (aucune valeur). + +```python + if block_number is None: + block_number = w3.eth.block_number +``` + +Si un numéro de bloc n'a pas été spécifié, utilisez `w3.eth.block_number`, qui est le dernier numéro de bloc. Voici la syntaxe d'[une instruction `if`](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement). + +On pourrait penser qu'il aurait été préférable de définir la valeur par défaut à `w3.eth.block_number`, mais cela ne fonctionne pas bien car ce serait le numéro de bloc au moment où la fonction est définie. Dans un agent fonctionnant en continu, cela poserait problème. + +```python + block = w3.eth.get_block(block_number) + price = pool.get_price(block_number) + return Quote( + timestamp=datetime.fromtimestamp(block.timestamp, timezone.utc).isoformat(), + price=price.quantize(Decimal("0.01")), + asset=pool.asset + ) +``` + +Utilisez [la bibliothèque `datetime`](https://docs.python.org/3/library/datetime.html) pour la formater dans un format lisible par les humains et les grands modèles de langage (LLM). Utilisez [`Decimal.quantize`](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) pour arrondir la valeur à deux décimales. + +```python +def get_quotes(pool: PoolInfo, start_block: int, end_block: int, step: int) -> list[Quote]: +``` + +En Python, vous définissez une [liste](https://docs.python.org/3/library/stdtypes.html#typesseq-list) qui ne peut contenir qu'un type spécifique en utilisant `list[]`. + +```python + quotes = [] + for block in range(start_block, end_block + 1, step): +``` + +En Python, une boucle [`for`](https://docs.python.org/3/tutorial/controlflow.html#for-statements) itère généralement sur une liste. La liste des numéros de bloc dans lesquels trouver des cotations provient de [`range`](https://docs.python.org/3/library/stdtypes.html#range). + +```python + quote = get_quote(pool, block) + quotes.append(quote) + return quotes +``` + +Pour chaque numéro de bloc, obtenez un objet `Quote` et ajoutez-le à la liste `quotes`. Retournez ensuite cette liste. + +```python +pool = read_pool(WETHUSDC_ADDRESS) +quotes = get_quotes( + pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) + +pprint(quotes) +``` + +Ceci est le code principal du script. Lisez les informations du pool, obtenez douze cotations et [`pprint`](https://docs.python.org/3/library/pprint.html#pprint.pprint)-les. + +### Créer une invite {#prompt} + +Ensuite, nous devons convertir cette liste de cotations en une invite pour un LLM et obtenir une valeur future attendue. + +```sh +git checkout 03-create-prompt +uv run agent.py +``` + +La sortie sera désormais une invite pour un LLM, similaire à : + +``` +Compte tenu de ces cotations : +Actif : WETH/USDC + 2026-01-20T16:34 3016.21 + . + . + . + 2026-02-01T17:49 2299.10 + +Actif : WBTC/WETH + 2026-01-20T16:34 29.84 + . + . + . + 2026-02-01T17:50 33.46 + + +Quelle serait, selon vous, la valeur de WETH/USDC à la date 2026-02-02T17:56 ? + +Fournissez votre réponse sous la forme d'un nombre unique arrondi à deux décimales, +sans aucun autre texte. +``` + +Notez qu'il y a ici des cotations pour deux actifs, `WETH/USDC` et `WBTC/WETH`. L'ajout de cotations d'un autre actif pourrait améliorer la précision de la prédiction. + +#### À quoi ressemble une invite {#prompt-explanation} + +Cette invite contient trois sections, qui sont assez courantes dans les invites de LLM. + +1. Informations. Les LLM disposent de beaucoup d'informations provenant de leur entraînement, mais ils n'ont généralement pas les plus récentes. C'est la raison pour laquelle nous devons récupérer les dernières cotations ici. L'ajout d'informations à une invite est appelé [génération augmentée par récupération (RAG)](https://en.wikipedia.org/wiki/Retrieval-augmented_generation). + +2. La question proprement dite. C'est ce que nous voulons savoir. + +3. Instructions de formatage de la sortie. Normalement, un LLM nous donnera une estimation avec une explication sur la façon dont il y est parvenu. C'est mieux pour les humains, mais un programme informatique n'a besoin que du résultat final. + +#### Explication du code {#prompt-code} + +Voici le nouveau code. + +```python +from datetime import datetime, timezone, timedelta +``` + +Nous devons fournir au LLM le moment pour lequel nous voulons une estimation. Pour obtenir un temps « n minutes/heures/jours » dans le futur, nous utilisons [la classe `timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta). + +```python +# Les adresses des pools que nous lisons +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +WETHWBTC_ADDRESS = Web3.to_checksum_address("0xCBCdF9626bC03E24f779434178A73a0B4bad62eD") +``` + +Nous avons deux pools à lire. + +```python +@dataclass(frozen=True) +class PoolInfo: + . + . + . + reverse: bool = False + + def get_price(self, block: int) -> Decimal: + assert block <= w3.eth.block_number, "Block is in the future" + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 # (token1 per token0) + if self.reverse: + return 1/(raw_price * self.decimal_factor) + else: + return raw_price * self.decimal_factor +``` + +Dans le pool WETH/USDC, nous voulons savoir combien de `token0` (USDC) nous avons besoin pour acheter un `token1` (WETH). Dans le pool WETH/WBTC, nous voulons savoir combien de `token1` (WETH) nous avons besoin pour acheter un `token0` (WBTC, qui est du Bitcoin encapsulé). Nous devons savoir si le ratio du pool doit être inversé. + +```python +def read_pool(address: str, reverse: bool = False) -> PoolInfo: + . + . + . + + return PoolInfo( + . + . + . + + asset= f"{token1.symbol}/{token0.symbol}" if reverse else f"{token0.symbol}/{token1.symbol}", + reverse=reverse + ) +``` + +Pour savoir si un pool doit être inversé, nous devons obtenir cela en entrée de `read_pool`. De plus, le symbole de l'actif doit être correctement configuré. + +La syntaxe `
if else ` est l'équivalent Python de l'[opérateur conditionnel ternaire](https://en.wikipedia.org/wiki/Ternary_conditional_operator), qui dans un langage dérivé de C serait ` ? : `. + +```python +def format_quotes(quotes: list[Quote]) -> str: + result = f"Asset: {quotes[0].asset}\n" + for quote in quotes: + result += f"\t{quote.timestamp[0:16]} {quote.price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)}\n" + return result +``` + +Cette fonction construit une chaîne de caractères qui formate une liste d'objets `Quote`, en supposant qu'ils s'appliquent tous au même actif. + +```python +def make_prompt(quotes: list[list[Quote]], expected_time: str, asset: str) -> str: + return f""" +``` + +En Python, les [littéraux de chaînes de caractères sur plusieurs lignes](https://www.w3schools.com/python/gloss_python_multi_line_strings.asp) s'écrivent comme `"""` .... `"""`. + +```python +Compte tenu de ces cotations : +{ + functools.reduce(lambda acc, q: acc + '\n' + q, + map(lambda q: format_quotes(q), quotes)) +} +``` + +Ici, nous utilisons le modèle [MapReduce](https://en.wikipedia.org/wiki/MapReduce) pour générer une chaîne de caractères pour chaque liste de cotations avec `format_quotes`, puis nous les réduisons en une seule chaîne de caractères à utiliser dans l'invite. + +```python +Quelle serait la valeur attendue pour {asset} au moment {expected_time} ? + +Fournissez votre réponse sous la forme d'un nombre unique arrondi à deux décimales, +sans aucun autre texte. + """ +``` + +Le reste de l'invite est conforme aux attentes. + +```python +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +Examinez les deux pools et obtenez des cotations de chacun. + +```python +future_time = (datetime.now(timezone.utc) + timedelta(days=1)).isoformat()[0:16] + +print(make_prompt(wethusdc_quotes + wethwbtc_quotes, future_time, wethusdc_pool.asset)) +``` + +Déterminez le moment futur pour lequel nous voulons l'estimation, et créez l'invite. + +### Interaction avec un LLM {#interface-llm} + +Ensuite, nous interrogeons un LLM réel et recevons une valeur future attendue. J'ai écrit ce programme en utilisant OpenAI, donc si vous voulez utiliser un autre fournisseur, vous devrez l'ajuster. + +1. Créez un [compte OpenAI](https://auth.openai.com/create-account) + +2. [Approvisionnez le compte](https://platform.openai.com/settings/organization/billing/overview)—le montant minimum au moment de la rédaction est de 5 $ + +3. [Créez une clé d'API](https://platform.openai.com/settings/organization/api-keys) + +4. Dans la ligne de commande, exportez la clé d'API pour que votre programme puisse l'utiliser + + ```sh + export OPENAI_API_KEY=sk- + ``` + +5. Récupérez et exécutez l'agent + + ```sh + git checkout 04-interface-llm + uv run agent.py + ``` + +Voici le nouveau code. + +```python +from openai import OpenAI + +open_ai = OpenAI() # Le client lit la variable d'environnement OPENAI_API_KEY +``` + +Importez et instanciez l'API OpenAI. + +```python +response = open_ai.chat.completions.create( + model="gpt-4-turbo", + messages=[ + {"role": "user", "content": prompt} + ], + temperature=0.0, + max_tokens=16, +) +``` + +Appelez l'API OpenAI (`open_ai.chat.completions.create`) pour créer la réponse. + +```python +expected_price = Decimal(response.choices[0].message.content.strip()) +current_price = wethusdc_quotes[-1].price + +print ("Current price:", wethusdc_quotes[-1].price) +print(f"In {future_time}, expected price: {expected_price} USD") + +if (expected_price > current_price): + print(f"Buy, I expect the price to go up by {expected_price - current_price} USD") +else: + print(f"Sell, I expect the price to go down by {current_price - expected_price} USD") +``` + +Affichez le prix et fournissez une recommandation d'achat ou de vente. + +#### Tester les prédictions {#testing-the-predictions} + +Maintenant que nous pouvons générer des prédictions, nous pouvons également utiliser des données historiques pour évaluer si nous produisons des prédictions utiles. + +```sh +uv run test-predictor.py +``` + +Le résultat attendu est similaire à : + +``` +Prédiction pour 2026-01-05T19:50 : prédit 3138.93 USD, réel 3218.92 USD, erreur 79.99 USD +Prédiction pour 2026-01-06T19:56 : prédit 3243.39 USD, réel 3221.08 USD, erreur 22.31 USD +Prédiction pour 2026-01-07T20:02 : prédit 3223.24 USD, réel 3146.89 USD, erreur 76.35 USD +Prédiction pour 2026-01-08T20:11 : prédit 3150.47 USD, réel 3092.04 USD, erreur 58.43 USD +. +. +. +Prédiction pour 2026-01-31T22:33 : prédit 2637.73 USD, réel 2417.77 USD, erreur 219.96 USD +Prédiction pour 2026-02-01T22:41 : prédit 2381.70 USD, réel 2318.84 USD, erreur 62.86 USD +Prédiction pour 2026-02-02T22:49 : prédit 2234.91 USD, réel 2349.28 USD, erreur 114.37 USD +Erreur moyenne de prédiction sur 29 prédictions : 83.87103448275862068965517241 USD +Variation moyenne par recommandation : 4.787931034482758620689655172 USD +Variance standard des variations : 104.42 USD +Jours rentables : 51,72% +Jours de perte : 48,28% +``` + +La majeure partie du testeur est identique à l'agent, mais voici les parties qui sont nouvelles ou modifiées. + +```python +CYCLES_FOR_TEST = 40 # Pour le backtest, combien de cycles nous testons + +# Obtenir beaucoup de cotations +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +Nous regardons en arrière sur `CYCLES_FOR_TEST` (spécifié à 40 ici) jours. + +```python +# Créer des prédictions et les vérifier par rapport à l'historique réel + +total_error = Decimal(0) +changes = [] +``` + +Il y a deux types d'erreurs qui nous intéressent. La première, `total_error`, est simplement la somme des erreurs commises par le prédicteur. + +Pour comprendre la seconde, `changes`, nous devons nous rappeler le but de l'agent. Il ne s'agit pas de prédire le ratio WETH/USDC (prix de l'ETH). Il s'agit d'émettre des recommandations de vente et d'achat. Si le prix est actuellement de 2000 $ et qu'il prédit 2010 $ demain, peu nous importe si le résultat réel est de 2020 $ et que nous gagnons de l'argent supplémentaire. Mais nous nous _soucions_ s'il a prédit 2010 $, et a acheté de l'ETH sur la base de cette recommandation, et que le prix chute à 1990 $. + +```python +for index in range(0,len(wethusdc_quotes)-CYCLES_BACK): +``` + +Nous ne pouvons examiner que les cas où l'historique complet (les valeurs utilisées pour la prédiction et la valeur réelle pour la comparer) est disponible. Cela signifie que le cas le plus récent doit être celui qui a commencé il y a `CYCLES_BACK`. + +```python + wethusdc_slice = wethusdc_quotes[index:index+CYCLES_BACK] + wethwbtc_slice = wethwbtc_quotes[index:index+CYCLES_BACK] +``` + +Utilisez des [tranches](https://www.w3schools.com/python/ref_func_slice.asp) pour obtenir le même nombre d'échantillons que celui utilisé par l'agent. Le code entre ici et le segment suivant est le même code d'obtention de prédiction que nous avons dans l'agent. + +```python + predicted_price = Decimal(response.choices[0].message.content.strip()) + real_price = wethusdc_quotes[index+CYCLES_BACK].price + prediction_time_price = wethusdc_quotes[index+CYCLES_BACK-1].price +``` + +Obtenez le prix prédit, le prix réel et le prix au moment de la prédiction. Nous avons besoin du prix au moment de la prédiction pour déterminer si la recommandation était d'acheter ou de vendre. + +```python + error = abs(predicted_price - real_price) + total_error += error + print (f"Prediction for {prediction_time}: predicted {predicted_price} USD, real {real_price} USD, error {error} USD") +``` + +Calculez l'erreur et ajoutez-la au total. + +```python + recomended_action = 'buy' if predicted_price > prediction_time_price else 'sell' + price_increase = real_price - prediction_time_price + changes.append(price_increase if recomended_action == 'buy' else -price_increase) +``` + +Pour les `changements`, nous voulons l'impact monétaire de l'achat ou de la vente d'un ETH. Donc, d'abord, nous devons déterminer la recommandation, puis évaluer comment le prix réel a changé, et si la recommandation a fait gagner de l'argent (changement positif) ou a coûté de l'argent (changement négatif). + +```python +print (f"Mean prediction error over {len(wethusdc_quotes)-CYCLES_BACK} predictions: {total_error / Decimal(len(wethusdc_quotes)-CYCLES_BACK)} USD") + +length_changes = Decimal(len(changes)) +mean_change = sum(changes, Decimal(0)) / length_changes +print (f"Mean change per recommendation: {mean_change} USD") +var = sum((x - mean_change) ** 2 for x in changes) / length_changes +print (f"Standard variance of changes: {var.sqrt().quantize(Decimal("0.01"))} USD") +``` + +Rapportez les résultats. + +```python +print (f"Profitable days: {len(list(filter(lambda x: x > 0, changes)))/length_changes:.2%}") +print (f"Losing days: {len(list(filter(lambda x: x < 0, changes)))/length_changes:.2%}") +``` + +Utilisez [`filter`](https://www.w3schools.com/python/ref_func_filter.asp) pour compter le nombre de jours rentables et le nombre de jours coûteux. Le résultat est un objet de filtre, que nous devons convertir en liste pour en obtenir la longueur. + +### Soumettre des transactions {#submit-txn} + +Maintenant, nous devons réellement soumettre des transactions. Cependant, je ne veux pas dépenser de l'argent réel à ce stade, avant que le système ne soit éprouvé. Au lieu de cela, nous allons créer une fourche locale du réseau principal, et « trader » sur ce réseau. + +Voici les étapes pour créer une fourche locale et permettre le trading. + +1. Installez [Foundry](https://getfoundry.sh/introduction/installation) + +2. Démarrez [`anvil`](https://getfoundry.sh/anvil/overview) + + ```sh + anvil --fork-url https://eth.drpc.org --block-time 12 + ``` + + `anvil` écoute sur l'URL par défaut de Foundry, http://localhost:8545, nous n'avons donc pas besoin de spécifier l'URL pour [la commande `cast`](https://getfoundry.sh/cast/overview) que nous utilisons pour manipuler la blockchain. + +3. Lors de l'exécution dans `anvil`, il y a dix comptes de test qui ont de l'ETH—définissez les variables d'environnement pour le premier + + ```sh + PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ADDRESS=`cast wallet address $PRIVATE_KEY` + ``` + +4. Ce sont les contrats que nous devons utiliser. [`SwapRouter`](https://github.com/Uniswap/v3-periphery/blob/main/contracts/SwapRouter.sol) est le contrat Uniswap v3 que nous utilisons pour réellement trader. Nous pourrions trader directement via le pool, mais c'est beaucoup plus facile. + + Les deux variables du bas sont les chemins Uniswap v3 requis pour échanger entre le WETH et l'USDC. + + ```sh + WETH_ADDRESS=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + USDC_ADDRESS=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + POOL_ADDRESS=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 + SWAP_ROUTER=0xE592427A0AEce92De3Edee1F18E0157C05861564 + WETH_TO_USDC=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + USDC_TO_WETH=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + ``` + +5. Chacun des comptes de test dispose de 10 000 ETH. Utilisez le contrat WETH pour envelopper 1000 ETH afin d'obtenir 1000 WETH pour le trading. + + ```sh + cast send $WETH_ADDRESS "deposit()" --value 1000ether --private-key $PRIVATE_KEY + ``` + +6. Utilisez `SwapRouter` pour échanger 500 WETH contre des USDC. + + ```sh + cast send $WETH_ADDRESS "approve(address,uint256)" $SWAP_ROUTER 500ether --private-key $PRIVATE_KEY + MAXINT=`cast max-int uint256` + cast send $SWAP_ROUTER \ + "exactInput((bytes,address,uint256,uint256,uint256))" \ + "($WETH_TO_USDC,$ADDRESS,$MAXINT,500ether,1000000)" \ + --private-key $PRIVATE_KEY + ``` + + L'appel `approve` crée une autorisation qui permet à `SwapRouter` de dépenser certains de nos jetons. Les contrats ne peuvent pas surveiller les événements, donc si nous transférons des jetons directement au contrat `SwapRouter`, il ne saurait pas qu'il a été payé. Au lieu de cela, nous autorisons le contrat `SwapRouter` à dépenser un certain montant, puis `SwapRouter` le fait. Cela se fait par une fonction appelée par `SwapRouter`, afin qu'il sache si cela a réussi. + +7. Vérifiez que vous avez assez des deux jetons. + + ```sh + cast call $WETH_ADDRESS "balanceOf(address)" $ADDRESS | cast from-wei + echo `cast call $USDC_ADDRESS "balanceOf(address)" $ADDRESS | cast to-dec`/10^6 | bc + ``` + +Maintenant que nous avons des WETH et des USDC, nous pouvons réellement exécuter l'agent. + +```sh +git checkout 05-trade +uv run agent.py +``` + +La sortie ressemblera à ceci : + +``` +(ai-trading-agent) qbzzt@Ori-Cloudnomics:~/260215-ai-agent$ uv run agent.py +Prix actuel : 1843.16 +En 2026-02-06T23:07, prix attendu : 1724.41 USD +Soldes du compte avant la transaction : +Solde USDC : 927301.578272 +Solde WETH : 500 +Vendre, je m'attends à ce que le prix baisse de 118.75 USD +Transaction d'approbation envoyée : 74e367ddbb407c1aaf567d87aa5863049991b1d2aa092b6b85195d925e2bd41f +Transaction d'approbation minée. +Transaction de vente envoyée : fad1bcf938585c9e90364b26ac7a80eea9efd34c37e5db81e58d7655bcae28bf +Transaction de vente minée. +Soldes du compte après la transaction : +Solde USDC : 929143.797116 +Solde WETH : 499 +``` + +Pour l'utiliser réellement, vous avez besoin de quelques modifications mineures. + +- À la ligne 14, changez `MAINNET_URL` en un point d'accès réel, comme `https://eth.drpc.org` +- À la ligne 28, changez `PRIVATE_KEY` par votre propre clé privée +- À moins que vous ne soyez très riche et que vous puissiez acheter ou vendre 1 ETH chaque jour pour un agent non éprouvé, vous voudrez peut-être modifier 29 pour diminuer `WETH_TRADE_AMOUNT` + +#### Explication du code {#trading-code} + +Voici le nouveau code. + +```python +SWAP_ROUTER_ADDRESS=Web3.to_checksum_address("0xE592427A0AEce92De3Edee1F18E0157C05861564") +WETH_TO_USDC=bytes.fromhex("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") +USDC_TO_WETH=bytes.fromhex("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +``` + +Les mêmes variables que nous avons utilisées à l'étape 4. + +```python +WETH_TRADE_AMOUNT=1 +``` + +Le montant à trader. + +```python +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... }, + { "name": "balanceOf", ...}, + { "name": "approve", ...} +] +``` + +Pour réellement trader, nous avons besoin de la fonction `approve`. Nous voulons également afficher les soldes avant et après, nous avons donc également besoin de `balanceOf`. + +```python +SWAP_ROUTER_ABI = [ + { "name": "exactInput", ...}, +] +``` + +Dans l'ABI `SwapRouter`, nous n'avons besoin que de `exactInput`. Il existe une fonction connexe, `exactOutput`, que nous pourrions utiliser pour acheter exactement un WETH, mais par souci de simplicité, nous utilisons simplement `exactInput` dans les deux cas. + +```python +account = w3.eth.account.from_key(PRIVATE_KEY) +swap_router = w3.eth.contract( + address=SWAP_ROUTER_ADDRESS, + abi=SWAP_ROUTER_ABI +) +``` + +Les définitions Web3 pour le [`compte`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html) et le contrat `SwapRouter`. + +```python +def txn_params() -> dict: + return { + "from": account.address, + "value": 0, + "gas": 300000, + "nonce": w3.eth.get_transaction_count(account.address), + } +``` + +Les paramètres de la transaction. Nous avons besoin d'une fonction ici car [le nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) doit changer à chaque fois. + +```python +def approve_token(contract: Contract, amount: int): +``` + +Approuvez une autorisation de jeton pour `SwapRouter`. + +```python + txn = contract.functions.approve(SWAP_ROUTER_ADDRESS, amount).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) +``` + +Voici comment nous envoyons une transaction dans Web3. D'abord, nous utilisons [l'objet `Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) pour construire la transaction. Ensuite, nous utilisons [`web3.eth.account.sign_transaction`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-contract-transaction) pour signer la transaction, en utilisant `PRIVATE_KEY`. Enfin, nous utilisons [`w3.eth.send_raw_transaction`](https://web3py.readthedocs.io/en/stable/transactions.html#chapter-2-w3-eth-send-raw-transaction) pour envoyer la transaction. + +```python + print(f"Approve transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Approve transaction mined.") +``` + +[`w3.eth.wait_for_transaction_receipt`](https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.wait_for_transaction_receipt) attend que la transaction soit minée. Il renvoie le reçu si nécessaire. + +```python +SELL_PARAMS = { + "path": WETH_TO_USDC, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": WETH_TRADE_AMOUNT * 10 ** wethusdc_pool.token1.decimals, + "amountOutMinimum": 0, +} +``` + +Ce sont les paramètres lors de la vente de WETH. + +```python +def make_buy_params(quote: Quote) -> dict: + return { + "path": USDC_TO_WETH, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": int(quote.price*WETH_TRADE_AMOUNT) * 10**wethusdc_pool.token0.decimals, + "amountOutMinimum": 0, + } +``` + +Contrairement à `SELL_PARAMS`, les paramètres d'achat peuvent changer. Le montant d'entrée est le coût de 1 WETH, tel qu'il est disponible dans la `cotation`. + +```python +def buy(quote: Quote): + buy_params = make_buy_params(quote) + approve_token(wethusdc_pool.token0.contract, buy_params["amountIn"]) + txn = swap_router.functions.exactInput(buy_params).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Buy transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Buy transaction mined.") + + +def sell(): + approve_token(wethusdc_pool.token1.contract, + WETH_TRADE_AMOUNT * 10**wethusdc_pool.token1.decimals) + txn = swap_router.functions.exactInput(SELL_PARAMS).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Sell transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Sell transaction mined.") +``` + +Les fonctions `buy()` et `sell()` sont presque identiques. D'abord, nous approuvons une autorisation suffisante pour `SwapRouter`, puis nous l'appelons avec le bon chemin et le bon montant. + +```python +def balances(): + token0_balance = wethusdc_pool.token0.contract.functions.balanceOf(account.address).call() + token1_balance = wethusdc_pool.token1.contract.functions.balanceOf(account.address).call() + + print(f"{wethusdc_pool.token0.symbol} Balance: {Decimal(token0_balance) / Decimal(10 ** wethusdc_pool.token0.decimals)}") + print(f"{wethusdc_pool.token1.symbol} Balance: {Decimal(token1_balance) / Decimal(10 ** wethusdc_pool.token1.decimals)}") +``` + +Rapportez les soldes des utilisateurs dans les deux devises. + +```python +print("Soldes du compte avant la transaction :") +balances() + +if (expected_price > current_price): + print(f"Acheter, je m'attends à ce que le prix augmente de {expected_price - current_price} USD") + buy(wethusdc_quotes[-1]) +else: + print(f"Vendre, je m'attends à ce que le prix baisse de {current_price - expected_price} USD") + sell() + +print("Soldes du compte après la transaction :") +balances() +``` + +Cet agent ne fonctionne actuellement qu'une seule fois. Cependant, vous pouvez le modifier pour qu'il fonctionne en continu, soit en l'exécutant à partir de [`crontab`](https://man7.org/linux/man-pages/man1/crontab.1.html), soit en encapsulant les lignes 368-400 dans une boucle et en utilisant [`time.sleep`](https://docs.python.org/3/library/time.html#time.sleep) pour attendre qu'il soit temps de passer au cycle suivant. + +## Améliorations possibles {#improvements} + +Ce n'est pas une version de production complète ; c'est simplement un exemple pour enseigner les bases. Voici quelques idées d'améliorations. + +### Trading plus intelligent {#smart-trading} + +Il y a deux faits importants que l'agent ignore lorsqu'il décide quoi faire. + +- _L'ampleur du changement anticipé_. L'agent vend un montant fixe de `WETH` si le prix est censé baisser, quelle que soit l'ampleur de la baisse. + On pourrait soutenir qu'il serait préférable d'ignorer les changements mineurs et de vendre en fonction de l'ampleur de la baisse attendue du prix. +- _Le portefeuille actuel_. Si 10 % de votre portefeuille est en WETH et que vous pensez que le prix va augmenter, il est probablement judicieux d'en acheter davantage. Mais si 90 % de votre portefeuille est en WETH, vous êtes peut-être suffisamment exposé, et il n'est pas nécessaire d'en acheter davantage. L'inverse est vrai si vous vous attendez à ce que le prix baisse. + +### Et si vous voulez garder votre stratégie de trading secrète ? {#secret} + +Les fournisseurs d'IA peuvent voir les requêtes que vous envoyez à leurs LLM, ce qui pourrait exposer le système de trading de génie que vous avez développé avec votre agent. Un système de trading que trop de gens utilisent est sans valeur car trop de gens essaient d'acheter quand vous voulez acheter (et le prix monte) et essaient de vendre quand vous voulez vendre (et le prix baisse). + +Vous pouvez exécuter un LLM localement, par exemple en utilisant [LM-Studio](https://lmstudio.ai/), pour éviter ce problème. + +### Du bot IA à l'agent IA {#bot-to-agent} + +On peut affirmer qu'il s'agit [d'un bot IA, et non d'un agent IA](/ai-agents/#ai-agents-vs-ai-bots). Il met en œuvre une stratégie relativement simple qui repose sur des informations prédéfinies. Nous pouvons permettre l'auto-amélioration, par exemple, en fournissant une liste de pools Uniswap v3 et leurs dernières valeurs et en demandant quelle combinaison a la meilleure valeur prédictive. + +### Protection contre le glissement de prix {#slippage-protection} + +Actuellement, il n'y a pas de [protection contre le glissement de prix](https://uniswapv3book.com/milestone_3/slippage-protection.html). Si la cotation actuelle est de 2 000 $ et que le prix attendu est de 2 100 $, l'agent achètera. Cependant, si avant que l'agent n'achète, le coût monte à 2 200 $, il n'est plus logique d'acheter. + +Pour mettre en œuvre une protection contre le glissement de prix, spécifiez une valeur `amountOutMinimum` aux lignes 325 et 334 de [`agent.py`](https://github.com/qbzzt/260215-ai-agent/blob/05-trade/agent.py#L325). + +## Conclusion {#conclusion} + +Espérons que vous en savez maintenant assez pour commencer avec les agents IA. Ce n'est pas un aperçu complet du sujet ; des livres entiers y sont consacrés, mais c'est suffisant pour vous lancer. Bonne chance ! + +[Voir ici pour plus de mon travail](https://cryptodocguy.pro/). diff --git a/public/content/translations/fr/developers/tutorials/hello-world-smart-contract-fullstack/index.md b/public/content/translations/fr/developers/tutorials/hello-world-smart-contract-fullstack/index.md index b9947928805..600ea17dd41 100644 --- a/public/content/translations/fr/developers/tutorials/hello-world-smart-contract-fullstack/index.md +++ b/public/content/translations/fr/developers/tutorials/hello-world-smart-contract-fullstack/index.md @@ -240,7 +240,7 @@ Ne le nommez pas `process.env` ou `.env-custom` ou quoi que ce soit d'autre. - Suivez [ces instructions](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key) pour exporter votre clé privée - Voir ci-dessous pour obtenir l'URL de l'API HTTP Alchemy -![](./get-alchemy-api-key.gif) +![Procédure pas à pas animée pour obtenir une clé API Alchemy](./get-alchemy-api-key.gif) Votre `.env` devrait ressembler à ceci : diff --git a/public/content/translations/fr/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md b/public/content/translations/fr/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md index 0518d560e8a..a4a90389737 100644 --- a/public/content/translations/fr/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md +++ b/public/content/translations/fr/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md @@ -62,13 +62,13 @@ Cela produira les mêmes informations que celles fournies sur la page des transa #### Etherscan {#etherscan} -![](./etherscan_view.png) +![Capture d'écran de la vue de l'explorateur de transactions Etherscan](./etherscan_view.png) [Page du contrat de l'EF sur Blockscout.](https://eth.blockscout.com/address/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe) #### Dune Analytics {#dune-analytics} -![](./dune_view.png) +![Capture d'écran d'un tableau de bord de requête Dune Analytics](./dune_view.png) Vous pouvez trouver le tableau de bord [ici](https://dune.com/paulapivat/Learn-Ethereum). Cliquez sur le tableau pour voir la requête (également visible ci-dessus). @@ -146,7 +146,7 @@ ORDER BY block_time DESC` Voici le résultat SQL sur Dune : -![](./list_of_txn.png) +![Capture d'écran d'une liste de transactions Ethereum](./list_of_txn.png) L'ajout de ce seul bloc à la chaîne modifie l'état de la machine virtuelle Ethereum ([EVM](/developers/docs/evm/)). Des dizaines, parfois des centaines de transactions sont vérifiées en une seule fois. Dans ce cas précis, 222 transactions ont été incluses. @@ -165,7 +165,7 @@ FROM temp_table Pour le bloc 12396854, sur un total de 222 transactions, 204 ont été vérifiées avec succès : -![](./successful_txn.png) +![Capture d'écran d'une transaction Ethereum réussie](./successful_txn.png) Les demandes de transaction se produisent des dizaines de fois par seconde, mais les blocs sont validés environ une fois toutes les 15 secondes ([source](/developers/docs/blocks/)). @@ -173,11 +173,11 @@ Pour voir qu'un bloc est produit environ toutes les 15 secondes, nous pourrions Le graphique des blocs Ethereum produits par jour (de 2016 à aujourd'hui) est le suivant : -![](./daily_blocks.png) +![Graphique montrant la production quotidienne de blocs Ethereum](./daily_blocks.png) Le nombre moyen de blocs produits quotidiennement au cours de cette période est d'environ 5 874 : -![](./avg_daily_blocks.png) +![Graphique montrant la production quotidienne de blocs Ethereum](./avg_daily_blocks.png) Les requêtes sont : @@ -214,7 +214,7 @@ La taille des blocs est limitée. La taille maximale d'un bloc est dynamique et Une façon de conceptualiser la limite de gaz par bloc est de la considérer comme l'**offre** d'espace de bloc disponible pour regrouper les transactions. La limite de gaz par bloc peut être interrogée et visualisée de 2016 à aujourd'hui : -![](./avg_gas_limit.png) +![Graphique montrant la limite moyenne de gaz Ethereum au fil du temps](./avg_gas_limit.png) ```sql SELECT @@ -227,7 +227,7 @@ OFFSET 1 Ensuite, il y a le gaz réellement utilisé quotidiennement pour payer les calculs effectués sur la chaîne Ethereum (par exemple, envoyer une transaction, appeler un contrat intelligent, frapper un NFT). C'est la **demande** pour l'espace de bloc Ethereum disponible : -![](./daily_gas_used.png) +![Graphique montrant le gaz Ethereum utilisé quotidiennement](./daily_gas_used.png) ```sql SELECT @@ -246,7 +246,7 @@ Par conséquent, nous pouvons comprendre les prix du gaz comme une fonction de l Enfin, nous pourrions vouloir interroger les prix moyens quotidiens du gaz pour la chaîne Ethereum. Cependant, cela entraînerait un temps de requête particulièrement long, nous allons donc filtrer notre requête sur le montant moyen de gaz payé par transaction par l'Ethereum Foundation. -![](./ef_daily_gas.png) +![Graphique montrant la consommation quotidienne de gaz de la Fondation Ethereum](./ef_daily_gas.png) Nous pouvons voir les prix du gaz payés pour toutes les transactions effectuées vers l'adresse de l'Ethereum Foundation au fil des ans. Voici la requête : diff --git a/public/content/translations/fr/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md b/public/content/translations/fr/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md index 23692a3aa82..4ffe030cf38 100644 --- a/public/content/translations/fr/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md +++ b/public/content/translations/fr/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md @@ -117,35 +117,35 @@ sudo systemctl start grafana-server Lorsque Grafana est en cours d'exécution, il devrait être accessible à l'adresse `localhost:3000`. Utilisez votre navigateur préféré pour accéder à ce chemin, puis connectez-vous avec les identifiants par défaut (utilisateur : `admin` et mot de passe : `admin`). Lorsque vous y êtes invité, changez le mot de passe par défaut et enregistrez. -![](./grafana1.png) +![Capture d'écran du tableau de bord Grafana pour la surveillance Geth (panneau 1)](./grafana1.png) Vous serez redirigé vers la page d'accueil de Grafana. Tout d'abord, configurez vos données sources. Cliquez sur l'icône de configuration dans la barre de gauche et sélectionnez "Sources de données". -![](./grafana2.png) +![Capture d'écran du tableau de bord Grafana pour la surveillance Geth (panneau 2)](./grafana2.png) Aucune source de données n'a encore été créée, cliquez sur "Ajouter une source de données" pour en définir une. -![](./grafana3.png) +![Capture d'écran du tableau de bord Grafana pour la surveillance Geth (panneau 3)](./grafana3.png) Pour cette configuration, sélectionnez "InfluxDB" et continuez. -![](./grafana4.png) +![Capture d'écran du tableau de bord Grafana pour la surveillance Geth (panneau 4)](./grafana4.png) La configuration de la source de données est assez simple si vous exécutez les outils sur la même machine. Vous devez définir l'adresse d'InfluxDB et les informations d'accès à la base de données. Reportez-vous à l'image ci-dessous. -![](./grafana5.png) +![Capture d'écran du tableau de bord Grafana pour la surveillance Geth (panneau 5)](./grafana5.png) Si tout est complet et qu'InfluxDB est accessible, cliquez sur "Enregistrer et tester" et attendez que la confirmation apparaisse. -![](./grafana6.png) +![Capture d'écran du tableau de bord Grafana pour la surveillance Geth (panneau 6)](./grafana6.png) Grafana est maintenant configuré pour lire les données depuis InfluxDB. Vous devez maintenant créer un tableau de bord qui interprétera et affichera ces données. Les propriétés des tableaux de bord sont encodées dans des fichiers JSON qui peuvent être créés par n'importe qui et importés facilement. Dans la barre de gauche, cliquez sur "Créer et Importer". -![](./grafana7.png) +![Capture d'écran du tableau de bord Grafana pour la surveillance Geth (panneau 7)](./grafana7.png) Pour un tableau de bord de surveillance Geth, copiez l'ID de [ce tableau de bord](https://grafana.com/grafana/dashboards/13877/) et collez-le dans la "Page d'importation" dans Grafana. Après avoir enregistré le tableau de bord, il devrait ressembler à ceci : -![](./grafana8.png) +![Capture d'écran du tableau de bord Grafana pour la surveillance Geth (panneau 8)](./grafana8.png) Vous pouvez modifier vos tableaux de bord. Chaque panneau peut être modifié, déplacé, supprimé ou ajouté. Vous pouvez modifier vos configurations. À vous de jouer ! Pour en savoir plus sur le fonctionnement des tableaux de bord, consultez la [documentation de Grafana](https://grafana.com/docs/grafana/latest/dashboards/). Les [alertes](https://grafana.com/docs/grafana/latest/alerting/) pourraient également vous intéresser. Cela vous permet de configurer des notifications d'alerte pour les cas où les métriques atteignent certaines valeurs. Divers canaux de communication sont pris en charge. diff --git a/public/content/translations/fr/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/translations/fr/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index 3e992f41c33..00000000000 --- a/public/content/translations/fr/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1147 +0,0 @@ ---- -title: Tester les jetons ERC-20 avec Waffle -description: "Découvrez comment tester les contrats intelligents Solidity et utiliser des correspondances de contrats intelligents avec Waffle." -author: Vladislav Starostenko -tags: - - "waffle" - - "contrats intelligents" - - "solidity" - - "test" - - "erc-20" -skill: intermediate -lang: fr -published: 2020-10-16 ---- - -Dans ce tutoriel, vous apprendrez comment : - -- Écrire des tests pour les contrats intelligents avec Waffle -- Utiliser des correspondances populaires pour tester des contrats intelligents avec Waffle - -Prérequis : - -- vous savez utiliser un terminal ou une invite de commandes, -- vous savez créer un nouveau projet `JavaScript`, -- Vous avez déjà écrit quelques lignes de code en `Solidity`, -- vous avez déjà écrit quelques tests en `JavaScript`, -- vous avez déjà utilisé `yarn` ou `npm`, un installateur de paquets JavaScript. - -Encore une fois, si l'un de ces éléments n'est pas correct ou si vous ne prévoyez pas de reproduire l'exact code de cet article, il vous sera possible de comprendre son contenu sans grande difficulté. - -## Quelques mots sur Waffle {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io) est la bibliothèque la plus avancée pour écrire et tester les contrats intelligents. - -Fonctionne avec l'[API JavaScript](/developers/docs/apis/javascript/) ethers-js. - -Vous pouvez trouver de plus amples détails dans la [documentation Waffle](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation) ! - -## Le tutoriel rapide {#the-quick-tutorial} - -Tout d'abord, créez un nouveau projet `JavaScript` ou `TypeScript` (Je vais utiliser `TS`, mais si vous utilisez `JS` ce n'est pas un problème) : - -Quelque chose comme ceci : - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## Étape #1 : Installez Waffle dans votre projet ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation)) {#step-1-install-waffle-in-your-project} - -Pour commencer, installez `ethereum-waffle`. Dans ce tutoriel, j'utiliserai `yarn`, donc pour installer `ethereum-waffle` exécutez : - -```bash - yarn add --dev ethereum-waffle -``` - -## Étape #2 : Écrire un contrat intelligent ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract)) {#step-2-write-a-smart-contract} - -Dans ce tutoriel, j'utiliserai le jeton [ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol) de [OpenZeppelin](https://openzeppelin.com). - -Il convient donc d'ajouter `OpenZeppelin` en l'installant avec `yarn` : - -```bash - yarn add @openzeppelin/contracts -D -``` - -Ensuite, créez le contrat `BasicToken.sol` dans le répertoire `src` : - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Exemple de classe - une classe fictive utilisant la livraison de ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## Étape #3 : Compilez votre contrat intelligent ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract)) {#step-3-compile-your-smart-contract} - -Pour compiler votre contrat intelligent, ajoutez l'entrée suivante dans le `package.json` de votre projet : - -```json -{ - "scripts": { - "build": "waffle" - } -} -``` - -Ajoutez également le fichier `waffle.json` dans le répertoire principal de votre projet. - -Un exemple de configuration `waffle.json` : - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Vous pouvez en apprendre plus sur la configuration de Waffle [ici](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration). - -Ensuite, exécutez `yarn build` pour compiler votre contrat intelligent. - -Vous devriez voir que Waffle a compilé votre contrat et placé la sortie JSON résultante dans le répertoire `build`. - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 P - -``` - -
- -## Étape #4 : Testez votre contrat intelligent ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)) {#step-4-test-your-smart-contract} - -### Étape #4.1 Installez les dépendances nécessaires ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)) {#step-4-1} - -Une fois que nous avons réussi à rédiger un Contrat Intelligent, nous pouvons le tester. Nous utiliserons `Waffle` pour le faire. - -Les tests dans `Waffle` sont écrits à l'aide de `Mocha` avec `Chai`. Nous pouvons utiliser un environnement de test différent, mais les correspondances `Waffle` ne fonctionnent qu'avec `Chai`. - -Nous devons donc ajouter `Chai` à nos dépendances : - -```bash - yarn add --dev mocha chai -``` - -### Étape #4.2 Créez un fichier de test ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)) {#step-4-2} - -Pour écrire notre test, nous devons créer le fichier `BasicToken.test.ts` dans notre répertoire de test. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -Nous utilisons alors la méthode `deployContract` de `Waffle` pour déployer notre jeton. En tant qu'arguments, nous devons passer `wallet`, le fichier json compilé de notre contrat et le solde par défaut. - -`Waffle` nous permet également de créer un `wallet`, ce qui le rend très facile à déployer un contrat. - -Vous pouvez en apprendre plus sur `wallet` [ici](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets) et vous pouvez en savoir plus sur la fonction de déploiement [ici](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts). - -Écrivons un simple test pour vérifier le solde de notre portefeuille. Depuis que nous avons soumis la valeur 1000 lors du déploiement de notre contrat, le solde de notre portefeuille doit être de 1000 jetons, ce que nous pouvons vérifier dans le premier test. - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -Pour exécuter le test, utilisez `yarn test` - -### Étape #4.3 Événement d'émission ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events)) {#step-4-3} - -Dans ce tutoriel, nous souhaitons montrer les correspondances les plus utiles de `Waffle`, alors commençons par la première. - -`Waffle` nous permet de tester quels événements ont été émis. - -Dans ce tutoriel, nous allons tester la méthode `transfer` de notre contrat. - -Dans ce test, nous allons réaliser un transfert d'un portefeuille à l'autre en vérifiant si l'événement `Transfer` a bien été appelé. - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -Un autre avantage de cette correspondance est que nous pouvons vérifier avec quels arguments cet événement a été appelé en ajoutant `withArgs` à notre test. - -Cela nous permettra d'être sûrs que notre fonction est appelée correctement ! - -### Étape #4.4 Annuler avec un message ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message)) {#step-4-4} - -`Waffle` nous permet de tester le message avec lequel il a été retourné. - -Nous utiliserons la correspondance `revertedWith` dans notre test pour vérifier. - -Nous pouvons écrire un test dans lequel nous effectuerons un transfert pour un montant supérieur à celui que nous avons dans notre portefeuille. Et puis nous vérifierons si la transaction a été annulée avec le message exact ! - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### Étape #4.5 Change-jeton-solde ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance)) {#step-4-5} - -`Waffle` nous permet de vérifier les changements dans les soldes des portefeuilles ! - -Nous pouvons utiliser la correspondance `changeTokenBalance` pour vérifier le changement de solde ou les `changeTokenBalances` pour un compte multiple. - -La correspondance peut accepter les `numbers`, `strings` et `BigNumbers` comme changement de solde, alors que l'adresse doit être spécifiée en tant que portefeuille ou contrat. - -Écrivons le prochain test : - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -Ce qui précède est un test pour un seul portefeuille. - -Et le prochain pour plusieurs portefeuilles : - -```ts -it("Send transaction changes sender and receiver balances", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalances([wallet, walletTo], [-200, 200]) -}) -``` - -La transaction devrait être passée en tant que rappel (callback) (nous devons vérifier le solde avant l'appel) ou en tant que réponse de transaction. - -## Félicitations {#congratulations} - -**Félicitations ! Vous avez réussi à le faire avec mon tutoriel. Vous avez fait votre premier grand pas vers les tests des contrats intelligents avec Waffle.** - -**Vous pouvez retrouver le code de ce tutoriel [ici](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website).** - -**Pour en apprendre plus sur Waffle, une `documentation` est disponible [ici](https://getwaffle.io).** diff --git a/public/content/translations/fr/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/fr/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 01b0105b5f6..00000000000 --- a/public/content/translations/fr/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -title: "Waffle : Bouchonnage dynamique et tests d'appels de contrat" -description: "Tutoriel Waffle avancé pour utiliser le bouchonnage dynamique et tester les appels de contrat" -author: "Daniel Izdebski" -tags: - [ - "Waffle", - "contrats intelligents", - "Solidity", - "test", - "simulation" - ] -skill: intermediate -lang: fr -published: 2020-11-14 ---- - -## À quoi sert ce tutoriel ? {#what-is-this-tutorial-about} - -Dans ce tutoriel, vous apprendrez comment : - -- utiliser le bouchonnage dynamique -- tester les interactions entre contrats intelligents - -Hypothèses : - -- vous savez déjà écrire un simple contrat intelligent en `Solidity` -- vous vous débrouillez en `JavaScript` et `TypeScript` -- vous avez suivi d'autres tutoriels `Waffle` ou vous en savez déjà un peu plus à ce sujet - -## Bouchonnage dynamique {#dynamic-mocking} - -Pourquoi le bouchonnage dynamique est-il utile ? Eh bien, il nous permet de rédiger des tests unitaires plutôt que des tests d'intégration. Qu'est-ce que cela signifie ? Cela signifie que nous n'avons pas à nous soucier des dépendances des contrats intelligents, nous pouvons donc tous les tester de manière complètement isolée. Laissez-moi vous montrer comment procéder. - -### **1. Projet** {#1-project} - -Avant de commencer, nous devons préparer un simple projet node.js : - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# ou si vous utilisez npm -npm init -``` - -Commençons par ajouter TypeScript et les dépendances de test, soit mocha et chai : - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# ou si vous utilisez npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Maintenant, ajoutons `Waffle` et `ethers` : - -```bash -yarn add --dev ethereum-waffle ethers -# ou si vous utilisez npm -npm install ethereum-waffle ethers --save-dev -``` - -La structure de votre projet devrait ressembler à ceci : - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Contrat intelligent** {#2-smart-contract} - -Pour commencer le bouchonnage dynamique, nous avons besoin d'un contrat intelligent avec des dépendances. Ne vous inquiétez pas, j'ai ce qu'il vous faut ! - -Voici un contrat intelligent simple écrit en `Solidity` dont le seul but est de vérifier si nous sommes riches. Il utilise un jeton ERC20 pour vérifier si nous avons suffisamment de jetons. Placez-le dans `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Comme nous voulons utiliser le bouchonnage dynamique, nous n'avons pas besoin de l'intégralité de l'ERC20. C'est pourquoi nous utilisons l'interface IERC20 avec une seule fonction. - -Il est temps de compiler ce contrat ! Pour cela, nous utiliserons `Waffle`. Tout d'abord, nous allons créer un simple fichier de configuration `waffle.json` qui spécifie les options de compilation. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Nous sommes désormais prêts à construire le contrat avec Waffle : - -```bash -npx waffle -``` - -Facile, n'est-ce pas ? Dans le dossier `build/`, deux fichiers correspondant au contrat et à l'interface sont apparus. Nous les utiliserons plus tard pour les tests. - -### **3. Tests** {#3-testing} - -Créons un fichier nommé `AmIRichAlready.test.ts` pour y mettre nos tests. Tout d'abord, nous devons gérer les importations. Nous en aurons besoin pour plus tard : - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -Outre les dépendances JS, nous devons importer notre contrat compilé et son interface : - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle utilise `chai` pour les tests. Cependant, avant de pouvoir l'utiliser, nous devons injecter les matchers de Waffle dans chai lui-même : - -```typescript -use(solidity) -``` - -Nous devons implémenter la fonction `beforeEach()` qui réinitialisera l'état du contrat avant chaque test. Réfléchissons d'abord à ce dont nous avons besoin. Pour déployer un contrat, nous avons besoin de deux choses : un portefeuille et un contrat ERC20 déployé pour le passer en argument au contrat `AmIRichAlready`. - -Premièrement, créons un portefeuille : - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Ensuite, nous devons déployer un contrat ERC20. Voici la partie délicate : nous n'avons qu'une interface. C'est là que Waffle vient à notre rescousse. Waffle dispose d'une fonction magique `deployMockContract()` qui crée un contrat en utilisant uniquement l'_abi_ de l'interface : - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Maintenant qu'on a le portefeuille et le contrat ERC20 déployé, nous pouvons déployer le contrat `AmIRichAlready` : - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -Avec tout cela, notre fonction `beforeEach()` est terminée. Pour l'instant, votre fichier `AmIRichAlready.test.ts` devrait ressembler à ceci : - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Écrivons le premier test pour le contrat `AmIRichAlready`. Selon vous, sur quoi notre test devrait-il porter ? Oui, vous avez raison ! Nous devrions vérifier si nous sommes déjà riches :) - -Mais attendez une seconde. Comment notre contrat bouchonné saura-t-il quelles valeurs retourner ? Nous n'avons implémenté aucune logique pour la fonction `balanceOf()`. Là encore, Waffle peut nous aider. Notre contrat bouchonné dispose maintenant de nouvelles fonctionnalités intéressantes : - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -Grâce à ces connaissances, nous pouvons enfin écrire notre premier test : - -```typescript -it("retourne « faux » si le portefeuille a moins de 1 000 000 de jetons", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Décomposons ce test en plusieurs parties : - -1. Nous configurons notre contrat ERC20 bouchonné pour qu'il retourne toujours un solde de 999 999 jetons. -2. Vérifier si la méthode `contract.check()` retourne `false`. - -Nous sommes prêts à lancer le test : - -![Un test réussi](./test-one.png) - -Le test fonctionne donc, mais... il y a encore une marge d'amélioration. La fonction `balanceOf()` retournera toujours 99999. Nous pouvons l'améliorer en spécifiant un portefeuille pour lequel la fonction doit retourner quelque chose, tout comme un vrai contrat : - -```typescript -it("retourne « faux » si le portefeuille a moins de 1 000 001 jetons", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Jusqu'à présent, nous n'avons testé que le cas où nous ne sommes pas assez riches. Testons le cas contraire : - -```typescript -it("retourne « vrai » si le portefeuille a au moins 1 000 001 jetons", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Vous lancez les tests... - -![Deux tests réussis](test-two.png) - -... et voilà ! Notre contrat semble fonctionner comme prévu :) - -## Test des appels de contrat {#testing-contract-calls} - -Résumons ce que nous avons fait jusqu'à présent. Nous avons testé la fonctionnalité de notre contrat `AmIRichAlready` et il semble fonctionner correctement. Cela signifie que nous avons terminé, n'est-ce pas ? Pas tout à fait ! Waffle nous permet de tester notre contrat de manière encore plus approfondie. Mais comment exactement ? Eh bien, dans l'arsenal de Waffle, il y a les matchers `calledOnContract()` et `calledOnContractWith()`. Ils nous permettront de vérifier si notre contrat a bien appelé le contrat ERC20 bouchonné. Voici un test de base avec l'un de ces matchers : - -```typescript -it("vérifie si le contrat a appelé balanceOf sur le jeton ERC20", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Nous pouvons aller encore plus loin et améliorer ce test avec l'autre matcher dont je vous ai parlé : - -```typescript -it("vérifie si le contrat a appelé balanceOf avec un certain portefeuille sur le jeton ERC20", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Vérifions si les tests sont corrects : - -![Trois tests réussis](test-three.png) - -Super, tous les tests sont au vert. - -Tester les appels de contrat avec Waffle est super facile. Et voici le meilleur. Ces matchers fonctionnent aussi bien avec des contrats normaux qu'avec des contrats bouchonnés ! C'est parce que Waffle enregistre et filtre les appels EVM plutôt que d'injecter du code, comme c'est le cas des bibliothèques de test populaires pour d'autres technologies. - -## La ligne d'arrivée {#the-finish-line} - -Félicitations ! Vous savez maintenant comment utiliser Waffle pour tester les appels de contrat et pour bouchonner dynamiquement les contrats. Il y a bien d'autres fonctionnalités intéressantes à découvrir. Je vous recommande de vous plonger dans la documentation de Waffle. - -La documentation de Waffle est disponible [ici](https://ethereum-waffle.readthedocs.io/). - -Le code source de ce tutoriel se trouve [ici](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Tutoriels qui pourraient également vous intéresser : - -- [Tester des contrats intelligents avec Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/fr/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/fr/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index b8a5363ac8d..00000000000 --- a/public/content/translations/fr/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "Tutoriel Waffle « Hello world » avec Hardhat et Ethers" -description: "Réalisez votre premier projet Waffle avec Hardhat et ethers.js" -author: "MiZiet" -tags: - [ - "Waffle", - "contrats intelligents", - "Solidity", - "test", - "Hardhat", - "ethers.js" - ] -skill: beginner -lang: fr -published: 2020-10-16 ---- - -Dans ce tutoriel [Waffle](https://ethereum-waffle.readthedocs.io), nous apprendrons à configurer un projet simple de contrat intelligent « Hello world », en utilisant [Hardhat](https://hardhat.org/) et [ethers.js](https://docs.ethers.io/v5/). Ensuite, nous apprendrons comment ajouter une nouvelle fonctionnalité à notre contrat intelligent et comment la tester avec Waffle. - -Commençons par créer un nouveau projet : - -```bash -yarn init -``` - -ou - -```bash -npm init -``` - -et installez les paquets requis : - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -ou - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -L'étape suivante consiste à créer un projet d'exemple Hardhat en exécutant `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Welcome to Hardhat v2.0.3 👷‍ - -? What do you want to do? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -Sélectionnez `Create a sample project` - -La structure de notre projet devrait ressembler à ceci : - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Parlons maintenant de certains de ces fichiers : {#now-lets-talk} - -- Greeter.sol - notre contrat intelligent écrit en Solidity ; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Notre contrat intelligent peut être divisé en trois parties : - -1. constructeur - où nous déclarons une variable de type `string` appelée `greeting`, -2. fonction `greet` - une fonction qui renverra la valeur `greeting` lorsqu'elle est appelée, -3. fonction `setGreeting` - une fonction qui nous permet de modifier la valeur de `greeting`. - -- sample-test.js - notre fichier de tests - -```js -describe("Greeter", function () { - it("Should return the new greeting once it's changed", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### L'étape suivante consiste à compiler notre contrat et à exécuter les tests : {#compiling-and-testing} - -Les tests Waffle utilisent Mocha (un framework de test) avec Chai (une bibliothèque d'assertions). Il vous suffit d'exécuter `npx hardhat test` et d'attendre que le message suivant s'affiche. - -```bash -✓ Should return the new greeting once it's changed -``` - -### Tout semble parfait jusqu'à présent. Ajoutons un peu de complexité à notre projet {#adding-complexity} - -Imaginez que quelqu'un ajoute une chaîne vide en guise de salut. Ce ne serait pas un salut très chaleureux, n'est-ce pas ? -Assurons-nous que cela ne se produise pas : - -Nous voulons utiliser la fonction `revert` de Solidity lorsque quelqu'un transmet une chaîne de caractères vide. Heureusement, nous pouvons facilement tester cette fonctionnalité avec le matcher Chai de Waffle `to.be.revertedWith()`. - -```js -it("Should revert when passing an empty string", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -Il semblerait que notre nouveau test n'ait pas réussi : - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -Implémentons cette fonctionnalité dans notre contrat intelligent : - -```solidity -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -``` - -Maintenant, notre fonction `setGreeting` ressemble à ceci : - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Exécutons les tests à nouveau : - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -Félicitations ! Vous y êtes arrivé :) - -### Conclusion {#conclusion} - -Nous avons réalisé un projet simple avec Waffle, Hardhat et ethers.js. Nous avons appris à configurer un projet, à ajouter un test et à implémenter de nouvelles fonctionnalités. - -Pour découvrir d'autres matchers Chai très utiles pour tester vos contrats intelligents, consultez la [documentation officielle de Waffle](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/translations/fr/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/fr/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index f4e47509d28..00000000000 --- a/public/content/translations/fr/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: "Test d'un contrat intelligent simple avec la bibliothèque Waffle" -description: "Tutoriel pour débutants" -author: Ewa Kowalska -tags: [ "contrats intelligents", "Solidity", "Waffle", "test" ] -skill: beginner -lang: fr -published: 2021-02-26 ---- - -## Dans ce tutoriel, vous apprendrez à {#in-this-tutorial-youll-learn-how-to} - -- Tester les modifications du solde du portefeuille -- Tester l'émission d'événements avec des arguments spécifiés -- Affirmer qu'une transaction a été annulée - -## Prérequis {#assumptions} - -- Vous pouvez créer un nouveau projet JavaScript ou TypeScript -- Vous avez une certaine expérience de base des tests en JavaScript -- Vous avez déjà utilisé des gestionnaires de paquets comme yarn ou npm -- Vous possédez des connaissances très élémentaires sur les contrats intelligents et Solidity - -## Mise en route {#getting-started} - -Le tutoriel présente la configuration et l'exécution du test à l'aide de yarn, mais il n'y a aucun problème si vous préférez utiliser npm. Je vous fournirai les références appropriées dans la [documentation](https://ethereum-waffle.readthedocs.io/en/latest/index.html) officielle de Waffle. - -## Installer les dépendances {#install-dependencies} - -[Ajoutez](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) les dépendances ethereum-waffle et typescript aux dépendances de développement de votre projet. - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## Exemple de contrat intelligent {#example-smart-contract} - -Pendant le tutoriel, nous travaillerons sur un exemple de contrat intelligent simple : EtherSplitter. Il ne fait pas grand-chose, à part permettre à n'importe qui d'envoyer des wei et de les répartir équitablement entre deux destinataires prédéfinis. -La fonction de répartition exige que le nombre de wei soit pair, sinon la transaction sera annulée. Pour les deux destinataires, il effectue un transfert de wei suivi de l'émission de l'événement Transfert. - -Placez l'extrait de code d'EtherSplitter dans `src/EtherSplitter.sol`. - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Montant de wei impair non autorisé'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## Compiler le contrat {#compile-the-contract} - -Pour [compiler](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) le contrat, ajoutez l'entrée suivante au fichier package.json : - -```json -"scripts": { - "build": "waffle" - } -``` - -Ensuite, créez le fichier de configuration Waffle dans le répertoire racine du projet, `waffle.json`, puis collez-y la configuration suivante : - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Exécutez `yarn build`. En conséquence, le répertoire `build` apparaîtra avec le contrat EtherSplitter compilé au format JSON. - -## Configuration du test {#test-setup} - -Les tests avec Waffle nécessitent l'utilisation des matchers Chai et de Mocha. Vous devez donc les [ajouter](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) à votre projet. Mettez à jour votre fichier package.json et ajoutez l'entrée `test` dans la partie scripts : - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -Si vous voulez [exécuter](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) vos tests, il suffit de lancer `yarn test`. - -## Tester {#testing} - -Créez maintenant le répertoire `test` et le nouveau fichier `test\EtherSplitter.test.ts`. -Copiez l'extrait de code ci-dessous et collez-le dans notre fichier de test. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Ether Splitter", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // ajoutez les tests ici -}) -``` - -Quelques mots avant de commencer. -Le `MockProvider` propose une version simulée de la blockchain. Il fournit également des portefeuilles simulés qui nous serviront pour tester le contrat EtherSplitter. Nous pouvons obtenir jusqu'à dix portefeuilles en appelant la méthode `getWallets()` sur le fournisseur. Dans l'exemple, nous obtenons trois portefeuilles : un pour l'expéditeur et deux pour les destinataires. - -Ensuite, nous déclarons une variable appelée « splitter ». C'est notre contrat EtherSplitter simulé. Il est créé avant chaque exécution d'un test unique par la méthode `deployContract`. Cette méthode simule le déploiement d'un contrat à partir du portefeuille passé comme premier paramètre (le portefeuille de l'expéditeur dans notre cas). Le deuxième paramètre est l'ABI et le bytecode du contrat testé. Nous y passons le fichier JSON du contrat EtherSplitter compilé à partir du répertoire `build`. Le troisième paramètre est un tableau avec les arguments du constructeur du contrat qui, dans notre cas, sont les deux adresses des destinataires. - -## changeBalances {#changebalances} - -Tout d'abord, nous vérifierons si la méthode de répartition modifie réellement les soldes des portefeuilles des destinataires. Si nous divisons 50 wei du compte de l'expéditeur, nous nous attendons à ce que les soldes des deux destinataires augmentent de 25 wei. Nous utiliserons le matcher `changeBalances` de Waffle : - -```ts -it("Changes accounts balances", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -Comme premier paramètre du matcher, nous passons un tableau des portefeuilles des destinataires, et comme second, un tableau des augmentations attendues sur les comptes correspondants. -Si nous voulions vérifier le solde d'un portefeuille spécifique, nous pourrions également utiliser le matcher `changeBalance`, qui ne nécessite pas de passer des tableaux, comme dans l'exemple ci-dessous : - -```ts -it("Changes account balance", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -Notez que dans les deux cas de `changeBalance` et `changeBalances`, nous passons la fonction de répartition en tant que rappel, car le matcher doit accéder à l'état des soldes avant et après l'appel. - -Ensuite, nous allons tester si l'événement Transfer a été émis après chaque transfert de wei. Nous allons nous tourner vers un autre matcher de Waffle : - -## Émission {#emit} - -```ts -it("Émet un événement lors du transfert vers le premier destinataire", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("Émet un événement lors du transfert vers le second destinataire", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -Le matcher `emit` nous permet de vérifier si un contrat a émis un événement en appelant une méthode. En tant que paramètres du matcher `emit`, nous fournissons le contrat simulé qui, selon nos prévisions, émettra l'événement, ainsi que le nom de cet événement. Dans notre cas, le contrat simulé est `splitter` et le nom de l'événement est `Transfer`. Nous pouvons également vérifier les valeurs précises des arguments avec lesquels l'événement a été émis. Nous passons autant d'arguments au matcher `withArgs` que notre déclaration d'événement en attend. Dans le cas du contrat EtherSplitter, nous passons les adresses de l'expéditeur et du destinataire ainsi que le montant en wei transféré. - -## revertedWith {#revertedwith} - -Comme dernier exemple, nous vérifierons si la transaction a été annulée en cas de nombre impair de wei. Nous utiliserons le matcher `revertedWith` : - -```ts -it("Reverts when Vei amount uneven", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Montant de wei impair non autorisé" - ) -}) -``` - -Le test, s'il est concluant, nous assurera que la transaction a bien été annulée. Cependant, il doit également y avoir une correspondance exacte entre les messages que nous avons passés dans l'instruction `require` et le message que nous attendons dans `revertedWith`. Si nous retournons au code du contrat EtherSplitter, dans l'instruction `require` pour le montant en wei, nous fournissons le message : « Montant de wei impair non autorisé ». Cela correspond au message que nous attendons dans notre test. S'ils n'étaient pas égaux, le test échouerait. - -## Félicitations ! {#congratulations} - -Vous avez fait votre premier grand pas vers le test de contrats intelligents avec Waffle ! diff --git a/public/content/translations/hi/community/support/faq/index.md b/public/content/translations/hi/community/support/faq/index.md new file mode 100644 index 00000000000..bd7a1aaf448 --- /dev/null +++ b/public/content/translations/hi/community/support/faq/index.md @@ -0,0 +1,77 @@ +--- +title: "अक्सर पूछे जाने वाले सवाल" +description: "वॉलेट, लेनदेन, स्टेकिंग और अन्य के बारे में एथेरियम से संबंधित सामान्य प्रश्न।" +lang: hi +--- + +# अक्सर पूछे जाने वाले सवाल {#faq} + +## मैंने गलत पते पर क्रिप्टो भेज दिया {#wrong-wallet} + +एथेरियम पर भेजा गया लेनदेन अपरिवर्तनीय है। दुर्भाग्य से, यदि आपने गलत वॉलेट में ETH या टोकन भेज दिए हैं, तो लेनदेन को उलटने का कोई तरीका नहीं है। + +**आप क्या कर सकते हैं:** + +- **यदि आप पते के मालिक को जानते हैं**, तो उनसे सीधे संपर्क करें और धनराशि वापस करने के लिए कहें +- **यदि पता किसी एक्सचेंज या ज्ञात सेवा का है**, तो उनकी सहायता टीम से संपर्क करें, क्योंकि वे मदद करने में सक्षम हो सकते हैं +- **यदि आपने किसी अनुबंध पते पर टोकन भेजे हैं**, तो जांचें कि क्या अनुबंध में निकासी या रिकवरी फ़ंक्शन है (यह दुर्लभ है) + +अधिकांश मामलों में, धनराशि की वसूली का कोई तरीका नहीं है। कोई भी केंद्रीय संगठन, इकाई या व्यक्ति एथेरियम का मालिक नहीं है, जिसका अर्थ है कि कोई भी लेनदेन को उलट नहीं सकता है। पुष्टि करने से पहले हमेशा प्राप्तकर्ता के पते की दोबारा जांच करें। + +## मैंने अपने वॉलेट तक पहुंच खो दी है {#lost-wallet-access} + +आपके रिकवरी विकल्प आपके द्वारा उपयोग किए जाने वाले वॉलेट के प्रकार पर निर्भर करते हैं। + +### यदि आपके पास आपका सीड वाक्यांश (रिकवरी वाक्यांश) है + +आप अपने सीड वाक्यांश का उपयोग करके किसी भी संगत वॉलेट ऐप में अपने वॉलेट को पुनर्स्थापित कर सकते हैं। यही कारण है कि अपने सीड वाक्यांश को सुरक्षित रूप से ऑफ़लाइन संग्रहीत रखना महत्वपूर्ण है। पुनर्स्थापना निर्देशों के लिए अपने वॉलेट प्रदाता के दस्तावेज़ देखें। + +### यदि आपने अपना सीड वाक्यांश खो दिया है + +आपके सीड वाक्यांश या निजी चाबियों के बिना, आपकी धनराशि की वसूली नहीं की जा सकती है। ethereum.org सहित कोई भी, आपका पासवर्ड रीसेट नहीं कर सकता या स्व-हिरासत वॉलेट तक पहुंच बहाल नहीं कर सकता। + +### यदि आपका खाता किसी एक्सचेंज पर है + +यदि आपका खाता Coinbase, Binance, या Kraken जैसे केंद्रीकृत एक्सचेंज पर है, तो सीधे एक्सचेंज की सहायता टीम से संपर्क करें। वे अपने प्लेटफ़ॉर्म पर खातों को नियंत्रित करते हैं और पासवर्ड रीसेट या खाता रिकवरी में मदद करने में सक्षम हो सकते हैं। + + + + + + +**अपना सीड वाक्यांश किसी के साथ भी साझा न करें** जो आपके वॉलेट को पुनर्प्राप्त करने में आपकी मदद करने का दावा करता हो। यह सबसे आम घोटाला युक्तियों में से एक है। कोई भी वैध सेवा आपसे कभी भी आपका सीड वाक्यांश नहीं मांगेगी। + + + + + + वॉलेट का उपयोग कैसे करें + + +## मेरा लेनदेन अटक गया है या लंबित है {#stuck-transaction} + +जब आपके द्वारा निर्धारित गैस शुल्क नेटवर्क द्वारा वर्तमान में आवश्यक शुल्क से कम हो, तो एथेरियम पर लेनदेन अटक सकते हैं। अधिकांश वॉलेट आपको इसे ठीक करने की सुविधा देते हैं: + +- **गति बढ़ाएँ:** उच्च गैस शुल्क के साथ वही लेनदेन फिर से सबमिट करें +- **रद्द करें:** लंबित लेनदेन के समान नॉन्स का उपयोग करके अपने पते पर 0 ETH लेनदेन भेजें + +### सहायक मार्गदर्शिकाएँ + +- [MetaMask पर लंबित लेनदेन को कैसे तेज करें या रद्द करें](https://support.metamask.io/transactions-and-gas/transactions/how-to-speed-up-or-cancel-a-pending-transaction/) +- [लंबित एथेरियम लेन-देन कैसे रद्द करें](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) + +## मैं अपने एथेरियम गिवअवे का दावा कैसे कर सकता हूं? {#giveaway-scam} + +एथेरियम गिवअवे आपके ETH को चुराने के लिए डिज़ाइन किए गए घोटाले हैं। ऐसे प्रस्तावों के लालच में न आएं जो सच होने के लिए बहुत अच्छे लगते हैं। यदि आप किसी गिवअवे पते पर ETH भेजते हैं, तो आपको कोई गिवअवे नहीं मिलेगा, और आप अपनी धनराशि की वसूली नहीं कर पाएंगे। + +[स्कैम से रोकथाम पर अधिक जानकारी](/security/#common-scams) + +## मैं ETH कैसे स्टेक करूं? {#how-to-stake} + +सत्यापनकर्ता बनने के लिए, आपको एथेरियम जमा अनुबंध में 32 ETH को दांव पर लगाना होगा और एक सत्यापनकर्ता नोड स्थापित करना होगा। आप स्टेकिंग पूल के माध्यम से कम ETH के साथ भी भाग ले सकते हैं। + +अधिक जानकारी हमारे [स्टेकिंग पृष्ठों](/staking/) पर और [स्टेकिंग लॉन्चपैड](https://launchpad.ethereum.org/) पर उपलब्ध है। + +## मैं एथेरियम कैसे माईन करूं? एथेरियम माइनिंग {#mining-ethereum} + +एथेरियम माईनिंग अब संभव नहीं है। सितंबर 2022 में [मर्ज](/roadmap/merge/) के दौरान जब एथेरियम [काम के सबूत](/glossary/#pow) से [हिस्सेदारी के सबूत](/glossary/#pos) में चला गया, तो माइनिंग बंद कर दी गई थी। अब माईनर के बजाय, एथेरियम के पास सत्यापनकर्ता हैं। कोई भी व्यक्ति ETH को [स्टेक](/glossary/#staking) कर सकता है और नेटवर्क को सुरक्षित करने के लिए सत्यापनकर्ता सॉफ्टवेयर चलाकर स्टेकिंग पुरस्कार प्राप्त कर सकता है। diff --git a/public/content/translations/hi/community/support/misconceptions/index.md b/public/content/translations/hi/community/support/misconceptions/index.md new file mode 100644 index 00000000000..f01464ceb17 --- /dev/null +++ b/public/content/translations/hi/community/support/misconceptions/index.md @@ -0,0 +1,73 @@ +--- +title: "एथेरियम के बारे में आम ग़लतफ़हमियाँ" +description: "एथेरियम कैसे काम करता है, इस बारे में सबसे आम ग़लतफ़हमियों को दूर करना।" +lang: hi +--- + +# एथेरियम के बारे में आम ग़लतफ़हमियाँ {#misconceptions} + +## क्या एथेरियम एक कंपनी है? {#not-a-company} + +एथेरियम ओपन-सोर्स, विकेंद्रीकृत तकनीक है जिसे दुनिया भर में हज़ारों योगदानकर्ताओं द्वारा बनाए रखा जाता है। "एथेरियम" नामक कोई कंपनी नहीं है जो खातों का प्रबंधन करती है, फंड रखती है, या ग्राहक सहायता प्रदान करती है। + +[Ethereum फाउंडेशन](https://ethereum.foundation/) एक गैर-लाभकारी संगठन है जो एथेरियम के विकास का समर्थन करता है, लेकिन यह नेटवर्क का मालिक नहीं है या इसे नियंत्रित नहीं करता है। कोई एक इकाई ऐसा नहीं करती है। + +**[ethereum.org](/)** एक समुदाय द्वारा संचालित शैक्षिक संसाधन है। यह कोई एक्सचेंज, वॉलेट या वित्तीय संस्थान नहीं है। यह किसी भी यूज़र के फंड को नहीं रखता है और किसी भी खाते तक नहीं पहुंच सकता है। + + + एथेरियम क्या है? + + +## क्या कोई मेरे फंड को रिकवर या फ्रीज कर सकता है? {#no-fund-access} + +बैंक के विपरीत, एथेरियम पर कोई केंद्रीय प्राधिकरण नहीं है जो फंड को फ्रीज, जब्त या पुनर्प्राप्त कर सकता है। निजी चाबियों (या बीज वाक्यांश) को रखने वाले व्यक्ति का वॉलेट पर पूर्ण और एकमात्र नियंत्रण होता है। + +इसका मतलब है: + +- **कोई भी आपके द्वारा गलत पते पर भेजे गए फंड को पुनर्प्राप्त नहीं कर सकता है** +- **पुष्टि होने के बाद कोई भी** लेन-देन को उलट नहीं सकता +- **कोई भी आपके वॉलेट को फ्रीज नहीं कर सकता** या आपके लेन-देन को ब्लोक नहीं कर सकता +- यदि आप अपना बीज वाक्यांश खो देते हैं तो **कोई भी आपका पासवर्ड रीसेट नहीं कर सकता है** + +इसलिए अपने बीज वाक्यांश की सुरक्षा करना महत्वपूर्ण है। यह आपके वॉलेट तक पहुँचने का एकमात्र तरीका है। यदि यह खो जाता है या चोरी हो जाता है, तो कोई रिकवरी विकल्प नहीं है। + + + एथेरियम सुरक्षा और स्कैम से रोकथाम + + +## क्या मैं अभी भी एथेरियम माइन कर सकता हूं? {#no-mining} + +सितंबर 2022 में [द मर्ज](/roadmap/merge/) के दौरान एथेरियम [काम के सबूत](/glossary/#pow) से [हिस्सेदारी के सबूत](/glossary/#pos) में बदल गया। एथेरियम पर अब माइनिंग संभव नहीं है। + +नेटवर्क अब सत्यापनकर्ताओं द्वारा सुरक्षित है जो ETH [स्टेक](/glossary/#staking) करते हैं। कोई भी भाग ले सकता है: + +- **सोलो स्टेकिंग:** 32 ETH के साथ अपना खुद का सत्यापनकर्ता चलाएं—[और जानें](/staking/solo/) +- **सेवा के रूप में स्टेकिंग:** अपनी चाबियों को रखते हुए नोड संचालन सौंपें—[और जानें](/staking/saas/) +- **पूल्ड स्टेकिंग:** एक पूल में शामिल होकर 32 ETH से कम के साथ स्टेक करें—[और जानें](/staking/pools/) + + + स्टेकिंग के बारे में और जानें + + +## क्या कोई एथेरियम सहायता टीम है? {#no-support-team} + +"आधिकारिक एथेरियम समर्थन" की तलाश करना "आधिकारिक इंटरनेट समर्थन" की तलाश करने के समान है। बेशक यह मौजूद नहीं है, लेकिन आपकी समस्या के आधार पर आप अपने इंटरनेट सेवा प्रदाता, अपने राउटर हार्डवेयर निर्माता, या आपके द्वारा उपयोग किए जा रहे डिवाइस, ऐप या वेबसाइट के पीछे की किसी एक कंपनी से सहायता प्राप्त कर सकते हैं। + +एथेरियम समान है। समग्र रूप से एथेरियम के पीछे कोई कंपनी, सहायता टीम या हेल्प डेस्क नहीं है, लेकिन समस्या के आधार पर आप अपने _वॉलेट प्रदाता_, _स्टेकिंग सेवा_, _एक्सचेंज_, _वित्तीय संस्थान_ या आपके द्वारा उपयोग किए जा रहे _ऐप को बनाए रखने वाली टीम_ से संपर्क करके मदद पा सकते हैं। + +चूंकि एथेरियम डिफ़ॉल्ट रूप से सार्वजनिक रूप से पारदर्शी है, इसलिए आप किसी समस्या की सीधे जांच करने में [ब्लॉक खोजकर्ता](/developers/docs/data-and-analytics/block-explorers/), [विश्लेषण उपकरण](/developers/tools/analytics/), और अन्य [ऑनलाइन जांच संसाधन](/community/support/scams/#analyze) भी उपयोगी पा सकते हैं। + +कहा जा रहा है, एथेरियम या ethereum.org से कोई भी कभी नहीं करेगा: + +- सीधे संदेश के माध्यम से आपसे संपर्क करें +- आपके बीज वाक्यांश या निजी चाबियों के लिए पूछें +- अपने वॉलेट को सत्यापित करने के लिए आपको ETH भेजने के लिए कहें +- शुल्क के लिए फंड की वसूली में आपकी मदद करने की पेशकश करें + +**उपरोक्त में से कोई भी कार्य करने वाला कोई भी व्यक्ति आपको धोखा देने की कोशिश कर रहा है।** + +यदि आपको मदद की ज़रूरत है, तो सहायता कर सकने वाले वास्तविक समुदाय [समर्थन पृष्ठ](/community/support/) पर सूचीबद्ध हैं। ये स्वयंसेवक द्वारा संचालित, खुले समुदाय हैं—आधिकारिक सहायता चैनल नहीं। + + + एथेरियम सुरक्षा और स्कैम से रोकथाम + diff --git a/public/content/translations/hi/community/support/scams/index.md b/public/content/translations/hi/community/support/scams/index.md new file mode 100644 index 00000000000..728416bdcda --- /dev/null +++ b/public/content/translations/hi/community/support/scams/index.md @@ -0,0 +1,159 @@ +--- +title: "घोटाले में मदद और रिपोर्टिंग" +description: "अगर आपके साथ घोटाला हुआ है तो क्या करें, अपनी बची हुई संपत्ति को कैसे सुरक्षित करें और धोखाधड़ी की रिपोर्ट कहां करें।" +lang: hi +--- + +# मेरे साथ घोटाला हुआ या मेरी धनराशि खो गई {#scam-help} + +क्रिप्टोकरेंसी घोटाले वित्त और प्रौद्योगिकी के पेशेवरों सहित सभी अनुभव स्तरों के लोगों को लक्षित करते हैं। आप अकेले नहीं हैं, और यहां होना पहला सही कदम है। + + + + + + +**कोई भी ब्लॉकचेन लेनदेन को उलट नहीं सकता है।** यदि कोई आपसे यह दावा करते हुए संपर्क करता है कि वे शुल्क के बदले आपकी धनराशि वापस पा सकते हैं, तो यह लगभग निश्चित रूप से एक दूसरा घोटाला है। नीचे [रिकवरी घोटाले](#recovery-scams) देखें। + + + + +## अपनी शेष संपत्ति सुरक्षित करें {#secure-assets} + +यदि आपने किसी घोटालेबाज के साथ बातचीत की है या आपको संदेह है कि आपका वॉलेट खतरे में है, तो तुरंत ये कदम उठाएं: + +1. **शेष धनराशि** को एक नए, सुरक्षित वॉलेट में ले जाएं, जिस तक घोटालेबाज की पहुंच न हो +2. **टोकन स्वीकृतियों को रद्द करें।** घोटालेबाज अक्सर आपको असीमित टोकन खर्च को मंजूरी देने के लिए बरगलाते हैं। इन अनुमतियों को रद्द करने से आपके वॉलेट से और धनराशि निकलने से रुक जाती है +3. **पासवर्ड बदलें** किसी भी लिंक किए गए एक्सचेंज खातों पर +4. सभी क्रिप्टो-संबंधित खातों पर **टू-फैक्टर ऑथेंटिकेशन (2FA) सक्षम करें** + +### टोकन स्वीकृतियों को कैसे रद्द करें {#revoke-approvals} + +जब आप किसी डैप या स्मार्ट अनुबंध के साथ इंटरैक्ट करते हैं, तो हो सकता है कि आपने इसे अपने टोकन खर्च करने की अनुमति दी हो। यदि किसी घोटालेबाज ने आपको किसी दुर्भावनापूर्ण अनुबंध को मंजूरी देने के लिए बरगलाया है, तो वे शुरुआती घोटाले के बाद भी आपके टोकन निकालना जारी रख सकते हैं। + +अनुमोदनों की जांच और उन्हें रद्द करने के लिए इन उपकरणों का उपयोग करें: + +- [Revoke.cash](https://revoke.cash/): सभी सक्रिय स्वीकृतियों को देखने और उन्हें रद्द करने के लिए अपना वॉलेट कनेक्ट करें +- [Revokescout](https://revoke.blockscout.com/): Blockscout के माध्यम से स्वीकृतियों की जांच करें और उन्हें रद्द करें +- [Etherscan Token Approval Checker](https://etherscan.io/tokenapprovalchecker): Etherscan के माध्यम से स्वीकृतियों की जांच करें और उन्हें रद्द करें + + + चरण-दर-चरण मार्गदर्शिका: टोकन एक्सेस कैसे रद्द करें + + +## घोटाले वाले पतों और वेबसाइटों की रिपोर्ट करें {#report} + +रिपोर्टिंग अन्य यूज़र को चेतावनी देने में मदद करती है और कानून प्रवर्तन जांच में सहायता कर सकती है। सब कुछ दस्तावेजीकृत करें: लेनदेन हैश, वॉलेट पते, स्क्रीनशॉट, और घोटालेबाज के साथ कोई भी संचार। + +### घोटाले वाले पते की रिपोर्ट करें {#report-address} + +- [Chainabuse](https://www.chainabuse.com/): समुदाय-संचालित घोटाला और धोखाधड़ी रिपोर्टिंग डेटाबेस। रिपोर्ट सबमिट करें और ज्ञात घोटाले वाले पतों की खोज करें +- [Etherscan रिपोर्ट](https://info.etherscan.com/report-address/): सबसे अधिक उपयोग किए जाने वाले Ethereum ब्लॉक खोजकर्ता पर एक पते को फ़्लैग करें +- [CryptoScamDB](https://cryptoscamdb.org/): क्रिप्टोकरेंसी घोटालों पर नज़र रखने वाला ओपन-सोर्स डेटाबेस + +### घोटाले वाली वेबसाइट या सोशल मीडिया खाते की रिपोर्ट करें {#report-website} + +- [PhishTank](https://phishtank.org/): फ़िशिंग यूआरएल सबमिट करें और सत्यापित करें +- [Google Safe Browsing](https://safebrowsing.google.com/safebrowsing/report_phish/): Google को फ़िशिंग साइटों की रिपोर्ट करें ताकि उन्हें Chrome और अन्य ब्राउज़रों में ब्लॉक कर दिया जाए +- [Netcraft](https://report.netcraft.com/report/mistake): दुर्भावनापूर्ण और धोखाधड़ी वाली वेबसाइटों की रिपोर्ट करें +- उस सोशल मीडिया प्लेटफॉर्म पर सीधे रिपोर्ट करें जहां घोटाला हुआ है (Twitter/X, Discord, Telegram सभी में रिपोर्टिंग सुविधाएं हैं) + +### कानून प्रवर्तन को रिपोर्ट करें {#report-law-enforcement} + +- **संयुक्त राज्य:** [FBI इंटरनेट अपराध शिकायत केंद्र (IC3)](https://www.ic3.gov/) +- **यूनाइटेड किंगडम:** [एक्शन फ्रॉड](https://www.actionfraud.police.uk/) +- **यूरोपीय संघ:** [Europol](https://www.europol.europa.eu/report-a-crime) +- **अन्य देश:** अपनी स्थानीय पुलिस में एक रिपोर्ट दर्ज करें। क्रिप्टोकरेंसी धोखाधड़ी अधिकांश न्यायालयों में एक अपराध है + +## विश्लेषण करें कि क्या हुआ {#analyze} + +यह समझने से कि आपकी धनराशि कहाँ गई, रिपोर्ट में मदद मिल सकती है और यदि धनराशि एक केंद्रीकृत एक्सचेंज पर पहुंचती है तो वसूली के प्रयासों में सहायता मिल सकती है। + +- [Blockscout](https://eth.blockscout.com/): किसी भी लेनदेन हैश या वॉलेट पते को खोजने के लिए ओपन-सोर्स ब्लॉक एक्सप्लोरर, यह देखने के लिए कि धनराशि कहां भेजी गई थी +- [Etherscan](https://etherscan.io/): यह देखने के लिए कि धनराशि कहाँ भेजी गई थी, किसी भी लेन-देन हैश या वॉलेट पते को खोजें +- [Chainabuse लुकअप](https://www.chainabuse.com/): जांचें कि क्या किसी पते की रिपोर्ट पहले ही अन्य पीड़ितों द्वारा की जा चुकी है +- BlockSec द्वारा [MetaSleuth](https://metasleuth.io/): विज़ुअल ट्रांज़ैक्शन ट्रेसिंग टूल जो फंड प्रवाह को मैप करता है + +**यदि धनराशि एक केंद्रीकृत एक्सचेंज** (जैसे Coinbase, Binance, Kraken) को भेजी गई थी, तो लेनदेन विवरण के साथ तुरंत उनकी सहायता टीम से संपर्क करें। एक्सचेंज कभी-कभी धोखाधड़ी के लिए फ़्लैग किए गए खातों को फ़्रीज़ कर सकते हैं। + +## कड़वी सच्चाई {#hard-truth} + +क्योंकि Ethereum विकेन्द्रीकृत है, कोई भी केंद्रीय प्राधिकरण लेनदेन को उलट नहीं सकता है या चोरी की गई धनराशि को पुनर्प्राप्त नहीं कर सकता है। एक बार जब ब्लॉकचेन पर एक लेनदेन की पुष्टि हो जाती है, तो यह अंतिम होता है। + +रिपोर्टिंग अभी भी मूल्यवान है। रिपोर्ट कानून प्रवर्तन को संगठित धोखाधड़ी गिरोहों को ट्रैक करने में मदद करती हैं, और Chainabuse और Etherscan पर पतों को फ़्लैग करना भविष्य के संभावित पीड़ितों को चेतावनी देता है। + +## जिन घोटालों से सावधान रहना है उनके प्रकार {#scam-types} + + + +घोटालेबाज आपके ETH को गुणा करने या आपको मुफ्त टोकन देने का वादा करते हुए नकली गिवअवे बनाते हैं। वे अक्सर Vitalik Buterin जैसी प्रसिद्ध हस्तियों का रूप धारण करते हैं। यदि आप "गिवअवे" पते पर ETH भेजते हैं, तो आपको कुछ भी वापस नहीं मिलेगा। + +**याद रखें:** Vitalik और अन्य प्रमुख हस्तियां आपको कभी भी उन्हें ETH भेजने के लिए नहीं कहेंगी। + +[आम घोटालों पर अधिक जानकारी](/security/#common-scams) + + + + +घोटालेबाज Discord, Telegram और सोशल मीडिया पर Ethereum टीम के सदस्यों, मॉडरेटरों या सहायता एजेंटों का रूप धारण करते हैं। वे आपको मदद की पेशकश करने वाले या यह दावा करने वाले सीधे संदेश भेज सकते हैं कि आपके खाते में कोई समस्या है। + +**याद रखें:** + +- कोई "Ethereum सहायता टीम" नहीं है +- वास्तविक मॉडरेटर आपको कभी भी पहले डीएम नहीं करेंगे +- अपना बीज वाक्यांश या निजी चाबी किसी के साथ, किसी भी कारण से साझा न करें +- अनचाहे संदेशों में भेजे गए लिंक पर कभी भी क्लिक न करें + + + + +रिकवरी घोटाले विशेष रूप से उन लोगों को लक्षित करते हैं जो पहले ही धनराशि खो चुके हैं। घोटालेबाज सोशल मीडिया पर उन लोगों पर नज़र रखते हैं जो घोटाले का शिकार होने के बारे में बात कर रहे हैं, फिर "ब्लॉकचेन जांचकर्ताओं" या "क्रिप्टो रिकवरी विशेषज्ञों" के रूप में सामने आते हैं। + +वे एक अग्रिम शुल्क के लिए आपके चोरी हुए क्रिप्टो का पता लगाने और उसे पुनर्प्राप्त करने का वादा करते हैं। आपके भुगतान करने के बाद, वे गायब हो जाते हैं। + +**कोई भी वैध सेवा ब्लॉकचेन लेनदेन को उलट नहीं सकती है।** जो कोई भी इसका वादा करता है वह झूठ बोल रहा है। यह सबसे आम फॉलो-अप घोटालों में से एक है। + + + + +फ़िशिंग साइटें असली वॉलेट ऐप, एक्सचेंज या DeFi प्लेटफॉर्म के समान दिखती हैं। वे आपको अपना बीज वाक्यांश दर्ज करने या अपना वॉलेट कनेक्ट करने के लिए बरगलाते हैं, फिर आपकी धनराशि निकाल लेते हैं। + +**अपनी सुरक्षा करें:** + +- अपना वॉलेट कनेक्ट करने से पहले हमेशा यूआरएल सत्यापित करें +- उन आधिकारिक साइटों को बुकमार्क करें जिनका आप नियमित रूप से उपयोग करते हैं +- किसी भी वेबसाइट पर अपना बीज वाक्यांश कभी भी दर्ज न करें। वैध ऐप कभी भी इसकी मांग नहीं करते हैं +- संदिग्ध यूआरएल की जांच के लिए [PhishTank](https://phishtank.org/) का उपयोग करें + + + घोटाले वाले टोकन की पहचान कैसे करें + + + + + Ethereum सुरक्षा और घोटाले की रोकथाम के लिए पूरी गाइड + diff --git a/public/content/translations/hi/developers/docs/nodes-and-clients/node-architecture/index.md b/public/content/translations/hi/developers/docs/nodes-and-clients/node-architecture/index.md index 4650a3ceba6..02be066c542 100644 --- a/public/content/translations/hi/developers/docs/nodes-and-clients/node-architecture/index.md +++ b/public/content/translations/hi/developers/docs/nodes-and-clients/node-architecture/index.md @@ -10,7 +10,7 @@ lang: hi नीचे दिया गया आरेख दो एथेरियम क्लाइंट के बीच संबंध दिखाता है। दो क्लाइंट अपने स्वयं के संबंधित पीयर-टू-पीयर (P2P) नेटवर्क से जुड़ते हैं। अलग-अलग P2P नेटवर्क की आवश्यकता होती है क्योंकि निष्पादन ग्राहक अपने P2P नेटवर्क पर गपशप लेनदेन करते हैं, जिससे उन्हें अपने स्थानीय लेनदेन पूल का प्रबंधन करने में सक्षम बनाया जाता है, जबकि सहमति ग्राहक अपने P2P नेटवर्क पर गपशप ब्लॉक करते हैं, जिससे आम सहमति और श्रृंखला विकास को सक्षम किया जाता है। -![](node-architecture-text-background.png) +![एथेरियम नोड आर्किटेक्चर का आरेख निष्पादन और सर्वसम्मति परतें दिखा रहा है](node-architecture-text-background.png) इस दो-क्लाइंट संरचना के काम करने के लिए, सहमति ग्राहक को निष्पादन ग्राहक को लेनदेन के बंडलों को पारित करने में सक्षम होना चाहिए। स्थानीय स्तर पर लेनदेन निष्पादित करने से क्लाइंट यह सत्यापित करता है कि लेनदेन किसी भी एथेरियम नियमों का उल्लंघन नहीं करता है और एथेरियम की स्थिति का प्रस्तावित अपडेट सही है। इसी तरह, जब नोड को ब्लॉक निर्माता के रूप में चुना जाता है, तो सहमति ग्राहक को नए ब्लॉक में शामिल करने के लिए Geth से लेनदेन के बंडलों का अनुरोध करने और वैश्विक स्थिति को अपडेट करने के लिए उन्हें निष्पादित करने में सक्षम होना चाहिए। यह अंतर-क्लाइंट संचार [इंजन API](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md) का उपयोग करके एक स्थानीय RPC कनेक्शन द्वारा नियंत्रित किया जाता है। diff --git a/public/content/translations/hi/developers/tutorials/ai-trading-agent/index.md b/public/content/translations/hi/developers/tutorials/ai-trading-agent/index.md new file mode 100644 index 00000000000..05d03d9e26f --- /dev/null +++ b/public/content/translations/hi/developers/tutorials/ai-trading-agent/index.md @@ -0,0 +1,980 @@ +--- +title: "एथेरियम पर अपना खुद का AI ट्रेडिंग एजेंट बनाएं" +description: "इस ट्यूटोरियल में आप सीखते हैं कि एक सरल AI ट्रेडिंग एजेंट कैसे बनाया जाए। यह एजेंट ब्लॉकचेन से जानकारी पढ़ता है, उस जानकारी के आधार पर LLM से सिफारिश मांगता है, LLM द्वारा अनुशंसित ट्रेड करता है, और फिर इंतजार करता है और दोहराता है।" +author: Ori Pomerantz +tags: [ "AI", "ट्रेडिंग", "एजेंट", "python" ] +skill: intermediate +published: 2026-02-13 +lang: hi +sidebarDepth: 3 +--- + +इस ट्यूटोरियल में आप सीखते हैं कि एक सरल AI ट्रेडिंग एजेंट कैसे बनाया जाए। यह एजेंट इन चरणों का उपयोग करके काम करता है: + +1. एक टोकन की वर्तमान और पिछली कीमतों को पढ़ें, साथ ही अन्य संभावित रूप से प्रासंगिक जानकारी +2. इस जानकारी के साथ एक क्वेरी बनाएं, साथ ही यह समझाने के लिए पृष्ठभूमि की जानकारी दें कि यह कैसे प्रासंगिक हो सकता है +3. क्वेरी सबमिट करें और एक अनुमानित मूल्य वापस प्राप्त करें +4. सिफारिश के आधार पर ट्रेड करें +5. प्रतीक्षा करें और दोहराएं + +यह एजेंट प्रदर्शित करता है कि जानकारी कैसे पढ़ें, इसे एक ऐसी क्वेरी में अनुवाद करें जो एक उपयोगी उत्तर देती है, और उस उत्तर का उपयोग करें। ये सभी एक AI एजेंट के लिए आवश्यक कदम हैं। यह एजेंट Python में लागू किया गया है क्योंकि यह AI में इस्तेमाल होने वाली सबसे आम भाषा है। + +## ऐसा क्यों करें? {#why-do-this} + +स्वचालित ट्रेडिंग एजेंट डेवलपर्स को एक ट्रेडिंग रणनीति चुनने और निष्पादित करने की अनुमति देते हैं। [AI एजेंट](/ai-agents) अधिक जटिल और गतिशील ट्रेडिंग रणनीतियों की अनुमति देते हैं, संभावित रूप से उन सूचनाओं और एल्गोरिदम का उपयोग करते हैं जिनका उपयोग करने पर डेवलपर ने विचार भी नहीं किया है। + +## उपकरण {#tools} + +यह ट्यूटोरियल कोट्स और ट्रेडिंग के लिए [Python](https://www.python.org/), [Web3 लाइब्रेरी](https://web3py.readthedocs.io/en/stable/), और [Uniswap v3](https://github.com/Uniswap/v3-periphery) का उपयोग करता है। + +### Python क्यों? {#python} + +AI के लिए सबसे व्यापक रूप से इस्तेमाल की जाने वाली भाषा [Python](https://www.python.org/) है, इसलिए हम इसे यहाँ इस्तेमाल करते हैं। अगर आप Python नहीं जानते हैं तो चिंता न करें। भाषा बहुत स्पष्ट है, और मैं ठीक से समझाऊंगा कि यह क्या करती है। + +[Web3 लाइब्रेरी](https://web3py.readthedocs.io/en/stable/) सबसे आम Python एथेरियम API है। इसका उपयोग करना बहुत आसान है। + +### ब्लॉकचेन पर ट्रेडिंग {#trading-on-blockchain} + +कई [वितरित एक्सचेंज (DEX)](/apps/categories/defi/) हैं जो आपको एथेरियम पर टोकन ट्रेड करने की सुविधा देते हैं। हालांकि, [आर्बिट्रेज](/developers/docs/smart-contracts/composability/#better-user-experience) के कारण उनकी विनिमय दरें समान होती हैं। + +[Uniswap](https://app.uniswap.org/) एक व्यापक रूप से उपयोग किया जाने वाला DEX है जिसका उपयोग हम कोट्स (टोकन के सापेक्ष मान देखने के लिए) और ट्रेड्स दोनों के लिए कर सकते हैं। + +### OpenAI {#openai} + +एक बड़े भाषा मॉडल के लिए, मैंने [OpenAI](https://openai.com/) के साथ शुरुआत करने का फैसला किया। इस ट्यूटोरियल में एप्लिकेशन को चलाने के लिए आपको API एक्सेस के लिए भुगतान करना होगा। $5 का न्यूनतम भुगतान पर्याप्त से अधिक है। + +## विकास, चरण-दर-चरण {#step-by-step} + +विकास को सरल बनाने के लिए, हम चरणों में आगे बढ़ते हैं। प्रत्येक चरण GitHub में एक शाखा है। + +### शुरुआत करना {#getting-started} + +UNIX या Linux (जिसमें [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) शामिल है) के तहत आरंभ करने के लिए कुछ चरण हैं + +1. यदि आपके पास यह पहले से नहीं है, तो [Python](https://www.python.org/downloads/) डाउनलोड और इंस्टॉल करें। + +2. GitHub रिपॉजिटरी को क्लोन करें। + + ```sh + git clone https://github.com/qbzzt/260215-ai-agent.git -b 01-getting-started + cd 260215-ai-agent + ``` + +3. [`uv`](https://docs.astral.sh/uv/getting-started/installation/) इंस्टॉल करें। आपके सिस्टम पर कमांड अलग हो सकता है। + + ```sh + pipx install uv + ``` + +4. लाइब्रेरी डाउनलोड करें। + + ```sh + uv sync + ``` + +5. वर्चुअल एनवायरनमेंट को सक्रिय करें। + + ```sh + source .venv/bin/activate + ``` + +6. यह सत्यापित करने के लिए कि Python और Web3 सही ढंग से काम कर रहे हैं, `python3` चलाएं और इसे यह प्रोग्राम प्रदान करें। आप इसे `>>>` प्रॉम्प्ट पर दर्ज कर सकते हैं; फ़ाइल बनाने की कोई आवश्यकता नहीं है। + + ```python + from web3 import Web3 + MAINNET_URL = "https://eth.drpc.org" + w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) + w3.eth.block_number + quit() + ``` + +### ब्लॉकचेन से पढ़ना {#read-blockchain} + +अगला कदम ब्लॉकचेन से पढ़ना है। ऐसा करने के लिए, आपको `02-read-quote` शाखा में बदलना होगा और फिर प्रोग्राम चलाने के लिए `uv` का उपयोग करना होगा। + +```sh +git checkout 02-read-quote +uv run agent.py +``` + +आपको `Quote` ऑब्जेक्ट की एक सूची मिलनी चाहिए, प्रत्येक में एक टाइमस्टैम्प, एक मूल्य और एसेट (वर्तमान में हमेशा `WETH/USDC`) होता है। + +यहाँ पंक्ति-दर-पंक्ति स्पष्टीकरण है। + +```python +from web3 import Web3 +from web3.contract import Contract +from decimal import Decimal, ROUND_HALF_UP +from dataclasses import dataclass +from datetime import datetime, timezone +from pprint import pprint +import time +import functools +import sys +``` + +हमें जिन पुस्तकालयों की आवश्यकता है, उन्हें आयात करें। उपयोग किए जाने पर उन्हें नीचे समझाया गया है। + +```python +print = functools.partial(print, flush=True) +``` + +Python के `print` को एक ऐसे संस्करण से बदल देता है जो हमेशा आउटपुट को तुरंत फ्लश करता है। यह एक लंबे समय तक चलने वाली स्क्रिप्ट में उपयोगी है क्योंकि हम स्थिति अपडेट या डिबगिंग आउटपुट के लिए इंतजार नहीं करना चाहते हैं। + +```python +MAINNET_URL = "https://eth.drpc.org" +``` + +मेननेट तक पहुंचने के लिए एक URL। आप [नोड एज़ ए सर्विस](/developers/docs/nodes-and-clients/nodes-as-a-service/) से एक प्राप्त कर सकते हैं या [चेनलिस्ट](https://chainlist.org/chain/1) में विज्ञापित लोगों में से एक का उपयोग कर सकते हैं। + +```python +BLOCK_TIME_SECONDS = 12 +MINUTE_BLOCKS = int(60 / BLOCK_TIME_SECONDS) +HOUR_BLOCKS = MINUTE_BLOCKS * 60 +DAY_BLOCKS = HOUR_BLOCKS * 24 +``` + +एथेरियम मेननेट ब्लॉक आमतौर पर हर बारह सेकंड में होता है, इसलिए यह उन ब्लॉकों की संख्या है जिनकी हम एक समय अवधि में होने की उम्मीद करते हैं। ध्यान दें कि यह एक सटीक आंकड़ा नहीं है। जब [ब्लॉक प्रस्तावक](/developers/docs/consensus-mechanisms/pos/block-proposal/) डाउन होता है, तो उस ब्लॉक को छोड़ दिया जाता है, और अगले ब्लॉक का समय 24 सेकंड होता है। यदि हम एक टाइमस्टैम्प के लिए सटीक ब्लॉक प्राप्त करना चाहते हैं, तो हम [बाइनरी सर्च](https://en.wikipedia.org/wiki/Binary_search) का उपयोग करेंगे। हालांकि, यह हमारे उद्देश्यों के लिए काफी करीब है। भविष्य की भविष्यवाणी करना कोई सटीक विज्ञान नहीं है। + +```python +CYCLE_BLOCKS = DAY_BLOCKS +``` + +चक्र का आकार। हम प्रति चक्र एक बार कोट्स की समीक्षा करते हैं और अगले चक्र के अंत में मूल्य का अनुमान लगाने का प्रयास करते हैं। + +```python +# उस पूल का पता जिसे हम पढ़ रहे हैं +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +``` + +कोट मूल्य Uniswap 3 USDC/WETH पूल से पते [`0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`](https://eth.blockscout.com/address/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640?tab=read_write_contract) पर लिए गए हैं। यह पता पहले से ही चेकसम प्रारूप में है, लेकिन कोड को पुन: प्रयोज्य बनाने के लिए [`Web3.to_checksum_address`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_checksum_address) का उपयोग करना बेहतर है। + +```python +POOL_ABI = [ + { "name": "slot0", ... }, + { "name": "token0", ... }, + { "name": "token1", ... }, +] + +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... } +] +``` + +ये उन दो कॉन्ट्रैक्ट के लिए [ABI](https://docs.soliditylang.org/en/latest/abi-spec.html) हैं जिनसे हमें संपर्क करने की आवश्यकता है। कोड को संक्षिप्त रखने के लिए, हम केवल उन कार्यों को शामिल करते हैं जिन्हें हमें कॉल करने की आवश्यकता है। + +```python +w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) +``` + +[`Web3`](https://web3py.readthedocs.io/en/stable/quickstart.html#remote-providers) लाइब्रेरी शुरू करें और एथेरियम नोड से कनेक्ट करें। + +```python +@dataclass(frozen=True) +class ERC20Token: + address: str + symbol: str + decimals: int + contract: Contract +``` + +यह Python में डेटा क्लास बनाने का एक तरीका है। [`Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) डेटा प्रकार का उपयोग कॉन्ट्रैक्ट से कनेक्ट करने के लिए किया जाता है। ` (frozen=True)` पर ध्यान दें। Python में [बूलियन](https://en.wikipedia.org/wiki/Boolean_data_type) को `True` या `False`, कैपिटलाइज़्ड के रूप में परिभाषित किया गया है। यह डेटा क्लास `frozen` है, जिसका अर्थ है कि फ़ील्ड को संशोधित नहीं किया जा सकता है। + +इंडेंटेशन पर ध्यान दें। [C-व्युत्पन्न भाषाओं](https://en.wikipedia.org/wiki/List_of_C-family_programming_languages) के विपरीत, Python ब्लॉक को दर्शाने के लिए इंडेंटेशन का उपयोग करता है। Python इंटरप्रेटर जानता है कि निम्नलिखित परिभाषा इस डेटा क्लास का हिस्सा नहीं है क्योंकि यह डेटा क्लास फ़ील्ड के समान इंडेंटेशन पर शुरू नहीं होती है। + +```python +@dataclass(frozen=True) +class PoolInfo: + address: str + token0: ERC20Token + token1: ERC20Token + contract: Contract + asset: str + decimal_factor: Decimal = 1 +``` + +[`Decimal`](https://docs.python.org/3/library/decimal.html) प्रकार का उपयोग दशमलव भिन्नों को सटीक रूप से संभालने के लिए किया जाता है। + +```python + def get_price(self, block: int) -> Decimal: +``` + +यह Python में फ़ंक्शन को परिभाषित करने का तरीका है। परिभाषा यह दिखाने के लिए इंडेंट की गई है कि यह अभी भी `PoolInfo` का हिस्सा है। + +डेटा क्लास का हिस्सा होने वाले फ़ंक्शन में पहला पैरामीटर हमेशा `self` होता है, जो डेटा क्लास इंस्टेंस है जिसे यहाँ कॉल किया गया है। यहाँ एक और पैरामीटर है, ब्लॉक नंबर। + +```python + assert block <= w3.eth.block_number, "Block is in the future" +``` + +अगर हम भविष्य पढ़ सकते, तो हमें ट्रेडिंग के लिए AI की ज़रूरत नहीं होती। + +```python + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) +``` + +Web3 से EVM पर किसी फ़ंक्शन को कॉल करने का सिंटैक्स यह है: `.functions."().call()`। पैरामीटर EVM फ़ंक्शन के पैरामीटर हो सकते हैं (यदि कोई हो; यहाँ नहीं हैं) या ब्लॉकचेन व्यवहार को संशोधित करने के लिए [नामित पैरामीटर](https://en.wikipedia.org/wiki/Named_parameter) हो सकते हैं। यहाँ हम एक, `block_identifier`, का उपयोग [ब्लॉक नंबर](/developers/docs/apis/json-rpc/#default-block) को निर्दिष्ट करने के लिए करते हैं जिसमें हम चलाना चाहते हैं। + +परिणाम [यह स्ट्रक्ट, ऐरे रूप में](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol#L56-L72) है। पहला मान दो टोकन के बीच विनिमय दर का एक कार्य है। + +```python + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 +``` + +ऑन-चेन गणनाओं को कम करने के लिए, Uniswap v3 वास्तविक विनिमय कारक को संग्रहीत नहीं करता है, बल्कि इसके वर्गमूल को संग्रहीत करता है। क्योंकि EVM फ्लोटिंग पॉइंट गणित या भिन्नों का समर्थन नहीं करता है, वास्तविक मान के बजाय, प्रतिक्रिया price296 है + +```python + # (टोकन1 प्रति टोकन0) + return 1/(raw_price * self.decimal_factor) +``` + +जो कच्चा मूल्य हमें मिलता है, वह प्रत्येक `token1` के लिए मिलने वाले `token0` की संख्या है। हमारे पूल में `token0` USDC (एक अमेरिकी डॉलर के समान मूल्य वाला स्थिर मुद्रा) है और `token1` [WETH](https://opensea.io/learn/blockchain/what-is-weth) है। जो मूल्य हम वास्तव में चाहते हैं वह प्रति WETH डॉलर की संख्या है, न कि इसका व्युत्क्रम। + +दशमलव कारक दो टोकन के [दशमलव कारकों](https://docs.openzeppelin.com/contracts/4.x/erc20#a-note-on-decimals) के बीच का अनुपात है। + +```python +@dataclass(frozen=True) +class Quote: + timestamp: str + price: Decimal + asset: str +``` + +यह डेटा क्लास एक उद्धरण का प्रतिनिधित्व करता है: किसी दिए गए समय पर किसी विशिष्ट संपत्ति की कीमत। इस बिंदु पर, `एसेट` फ़ील्ड अप्रासंगिक है क्योंकि हम एक ही पूल का उपयोग करते हैं और इसलिए हमारे पास एक ही एसेट है। हालांकि, हम बाद में और एसेट्स जोड़ेंगे। + +```python +def read_token(address: str) -> ERC20Token: + token = w3.eth.contract(address=address, abi=ERC20_ABI) + symbol = token.functions.symbol().call() + decimals = token.functions.decimals().call() + + return ERC20Token( + address=address, + symbol=symbol, + decimals=decimals, + contract=token + ) +``` + +यह फ़ंक्शन एक पता लेता है और उस पते पर टोकन अनुबंध के बारे में जानकारी देता है। एक नया [Web3 `Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) बनाने के लिए, हम `w3.eth.contract` को पता और ABI प्रदान करते हैं। + +```python +def read_pool(address: str) -> PoolInfo: + pool_contract = w3.eth.contract(address=address, abi=POOL_ABI) + token0Address = pool_contract.functions.token0().call() + token1Address = pool_contract.functions.token1().call() + token0 = read_token(token0Address) + token1 = read_token(token1Address) + + return PoolInfo( + address=address, + asset=f"{token1.symbol}/{token0.symbol}", + token0=token0, + token1=token1, + contract=pool_contract, + decimal_factor=Decimal(10) ** Decimal(token0.decimals - token1.decimals) + ) +``` + +यह फ़ंक्शन [एक विशिष्ट पूल](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol) के बारे में हमें जो कुछ भी चाहिए वह सब कुछ देता है। सिंटैक्स `f""` एक [फ़ॉर्मेटेड स्ट्रिंग](https://docs.python.org/3/reference/lexical_analysis.html#f-strings) है। + +```python +def get_quote(pool: PoolInfo, block_number: int = None) -> Quote: +``` + +`Quote` ऑब्जेक्ट प्राप्त करें। `block_number` का डिफ़ॉल्ट मान `None` (कोई मान नहीं) है। + +```python + if block_number is None: + block_number = w3.eth.block_number +``` + +यदि कोई ब्लॉक नंबर निर्दिष्ट नहीं किया गया था, तो `w3.eth.block_number` का उपयोग करें, जो नवीनतम ब्लॉक नंबर है। यह [एक `if` स्टेटमेंट](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement) का सिंटैक्स है। + +ऐसा लग सकता है कि डिफ़ॉल्ट को `w3.eth.block_number` पर सेट करना बेहतर होता, लेकिन यह अच्छी तरह से काम नहीं करता क्योंकि यह फ़ंक्शन को परिभाषित करते समय ब्लॉक नंबर होगा। एक लंबे समय तक चलने वाले एजेंट में, यह एक समस्या होगी। + +```python + block = w3.eth.get_block(block_number) + price = pool.get_price(block_number) + return Quote( + timestamp=datetime.fromtimestamp(block.timestamp, timezone.utc).isoformat(), + price=price.quantize(Decimal("0.01")), + asset=pool.asset + ) +``` + +इसे मनुष्यों और बड़े भाषा मॉडल (LLM) के लिए पठनीय प्रारूप में प्रारूपित करने के लिए [`datetime` लाइब्रेरी](https://docs.python.org/3/library/datetime.html) का उपयोग करें। मान को दो दशमलव स्थानों तक गोल करने के लिए [`Decimal.quantize`](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) का उपयोग करें। + +```python +def get_quotes(pool: PoolInfo, start_block: int, end_block: int, step: int) -> list[Quote]: +``` + +Python में आप एक [सूची](https://docs.python.org/3/library/stdtypes.html#typesseq-list) परिभाषित करते हैं जिसमें `list[]` का उपयोग करके केवल एक विशिष्ट प्रकार हो सकता है। + +```python + quotes = [] + for block in range(start_block, end_block + 1, step): +``` + +Python में एक [`for` लूप](https://docs.python.org/3/tutorial/controlflow.html#for-statements) आमतौर पर एक सूची पर पुनरावृति करता है। उद्धरणों को खोजने के लिए ब्लॉक नंबरों की सूची [`रेंज`](https://docs.python.org/3/library/stdtypes.html#range) से आती है। + +```python + quote = get_quote(pool, block) + quotes.append(quote) + return quotes +``` + +प्रत्येक ब्लॉक नंबर के लिए, एक `Quote` ऑब्जेक्ट प्राप्त करें और इसे `quotes` सूची में जोड़ें। फिर उस सूची को वापस करें। + +```python +pool = read_pool(WETHUSDC_ADDRESS) +quotes = get_quotes( + pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) + +pprint(quotes) +``` + +यह स्क्रिप्ट का मुख्य कोड है। पूल की जानकारी पढ़ें, बारह उद्धरण प्राप्त करें, और उन्हें [`pprint`](https://docs.python.org/3/library/pprint.html#pprint.pprint) करें। + +### एक प्रॉम्प्ट बनाना {#prompt} + +अगला, हमें उद्धरणों की इस सूची को एक एलएलएम के लिए एक संकेत में बदलने और भविष्य के अपेक्षित मूल्य प्राप्त करने की आवश्यकता है। + +```sh +git checkout 03-create-prompt +uv run agent.py +``` + +आउटपुट अब LLM के लिए एक संकेत होने जा रहा है, इसके समान: + +``` +इन उद्धरणों को देखते हुए: +एसेट: WETH/USDC + 2026-01-20T16:34 3016.21 + . + . + . + 2026-02-01T17:49 2299.10 + +एसेट: WBTC/WETH + 2026-01-20T16:34 29.84 + . + . + . + 2026-02-01T17:50 33.46 + + +समय 2026-02-02T17:56 पर WETH/USDC का मूल्य क्या होने की उम्मीद करेंगे? + +अपना उत्तर दो दशमलव स्थानों पर गोल की गई एक ही संख्या के रूप में प्रदान करें, +बिना किसी अन्य पाठ के। +``` + +ध्यान दें कि यहां दो संपत्तियों, `WETH/USDC` और `WBTC/WETH` के लिए उद्धरण हैं। किसी अन्य संपत्ति से उद्धरण जोड़ने से भविष्यवाणी की सटीकता में सुधार हो सकता है। + +#### प्रॉम्प्ट कैसा दिखता है {#prompt-explanation} + +इस प्रॉम्प्ट में तीन खंड हैं, जो एलएलएम प्रॉम्प्ट में बहुत आम हैं। + +1. जानकारी। LLMs के पास अपने प्रशिक्षण से बहुत सारी जानकारी होती है, लेकिन उनके पास आमतौर पर नवीनतम जानकारी नहीं होती है। यही कारण है कि हमें यहां नवीनतम उद्धरण प्राप्त करने की आवश्यकता है। प्रॉम्प्ट में जानकारी जोड़ने को [पुनर्प्राप्ति संवर्धित पीढ़ी (RAG)](https://en.wikipedia.org/wiki/Retrieval-augmented_generation) कहा जाता है। + +2. वास्तविक प्रश्न। यही हम जानना चाहते हैं। + +3. आउटपुट स्वरूपण निर्देश। आम तौर पर, एक LLM हमें इस बात के स्पष्टीकरण के साथ एक अनुमान देगा कि यह इस पर कैसे पहुंचा। यह मनुष्यों के लिए बेहतर है, लेकिन एक कंप्यूटर प्रोग्राम को केवल बॉटम लाइन की आवश्यकता होती है। + +#### कोड स्पष्टीकरण {#prompt-code} + +यहाँ नया कोड है। + +```python +from datetime import datetime, timezone, timedelta +``` + +हमें LLM को उस समय के बारे में बताने की आवश्यकता है जिसके लिए हम एक अनुमान चाहते हैं। भविष्य में "n मिनट/घंटे/दिन" का समय प्राप्त करने के लिए, हम [`timedelta` वर्ग](https://docs.python.org/3/library/datetime.html#datetime.timedelta) का उपयोग करते हैं। + +```python +# उन पूलों के पते जिन्हें हम पढ़ रहे हैं +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +WETHWBTC_ADDRESS = Web3.to_checksum_address("0xCBCdF9626bC03E24f779434178A73a0B4bad62eD") +``` + +हमें दो पूल पढ़ने हैं। + +```python +@dataclass(frozen=True) +class PoolInfo: + . + . + . + reverse: bool = False + + def get_price(self, block: int) -> Decimal: + assert block <= w3.eth.block_number, "Block is in the future" + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 # (token1 per token0) + if self.reverse: + return 1/(raw_price * self.decimal_factor) + else: + return raw_price * self.decimal_factor +``` + +WETH/USDC पूल में, हम जानना चाहते हैं कि `token1` (WETH) में से एक को खरीदने के लिए हमें कितने `token0` (USDC) की आवश्यकता है। WETH/WBTC पूल में, हम जानना चाहते हैं कि एक `token0` (WBTC, जो रैप्ड बिटकॉइन है) खरीदने के लिए हमें कितने `token1` (WETH) की आवश्यकता है। हमें यह ट्रैक करने की आवश्यकता है कि क्या पूल के अनुपात को उलटने की आवश्यकता है। + +```python +def read_pool(address: str, reverse: bool = False) -> PoolInfo: + . + . + . + + return PoolInfo( + . + . + . + + asset= f"{token1.symbol}/{token0.symbol}" if reverse else f"{token0.symbol}/{token1.symbol}", + reverse=reverse + ) +``` + +यह जानने के लिए कि क्या किसी पूल को उलटने की आवश्यकता है, हम इसे `read_pool` में इनपुट के रूप में प्राप्त करते हैं। इसके अलावा, संपत्ति प्रतीक को सही ढंग से स्थापित करने की आवश्यकता है। + +वाक्यविन्यास `
if else ` [टर्नेरी कंडीशनल ऑपरेटर](https://en.wikipedia.org/wiki/Ternary_conditional_operator) के पायथन समकक्ष है, जो सी-व्युत्पन्न भाषा में ` ? : ` होगा। + +```python +def format_quotes(quotes: list[Quote]) -> str: + result = f"Asset: {quotes[0].asset}\n" + for quote in quotes: + result += f"\t{quote.timestamp[0:16]} {quote.price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)}\n" + return result +``` + +यह फ़ंक्शन एक स्ट्रिंग बनाता है जो `Quote` ऑब्जेक्ट की एक सूची को प्रारूपित करता है, यह मानते हुए कि वे सभी एक ही संपत्ति पर लागू होते हैं। + +```python +def make_prompt(quotes: list[list[Quote]], expected_time: str, asset: str) -> str: + return f""" +``` + +Python में [मल्टी-लाइन स्ट्रिंग लिटरल](https://www.w3schools.com/python/gloss_python_multi_line_strings.asp) `"""` के रूप में लिखे जाते हैं .... `"""`. + +```python +इन उद्धरणों को देखते हुए: +{ + functools.reduce(lambda acc, q: acc + '\n' + q, + map(lambda q: format_quotes(q), quotes)) +} +``` + +यहां, हम प्रत्येक उद्धरण सूची के लिए `format_quotes` के साथ एक स्ट्रिंग उत्पन्न करने के लिए [MapReduce](https://en.wikipedia.org/wiki/MapReduce) पैटर्न का उपयोग करते हैं, फिर उन्हें प्रॉम्प्ट में उपयोग के लिए एक एकल स्ट्रिंग में कम करते हैं। + +```python +{asset} का मान समय {expected_time} पर क्या होने की उम्मीद करेंगे? + +अपना उत्तर दो दशमलव स्थानों पर गोल की गई एक ही संख्या के रूप में प्रदान करें, +बिना किसी अन्य पाठ के। + """ +``` + +प्रॉम्प्ट का बाकी हिस्सा अपेक्षित है। + +```python +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +दो पूलों की समीक्षा करें और दोनों से उद्धरण प्राप्त करें। + +```python +future_time = (datetime.now(timezone.utc) + timedelta(days=1)).isoformat()[0:16] + +print(make_prompt(wethusdc_quotes + wethwbtc_quotes, future_time, wethusdc_pool.asset)) +``` + +भविष्य का समय बिंदु निर्धारित करें जिसके लिए हम अनुमान चाहते हैं, और प्रॉम्प्ट बनाएं। + +### एक LLM के साथ इंटरफेसिंग {#interface-llm} + +अगला, हम एक वास्तविक एलएलएम को संकेत देते हैं और एक अपेक्षित भविष्य मूल्य प्राप्त करते हैं। मैंने यह प्रोग्राम OpenAI का उपयोग करके लिखा है, इसलिए यदि आप किसी भिन्न प्रदाता का उपयोग करना चाहते हैं, तो आपको इसे समायोजित करने की आवश्यकता होगी। + +1. [OpenAI खाता](https://auth.openai.com/create-account) प्राप्त करें + +2. [खाता फंड करें](https://platform.openai.com/settings/organization/billing/overview)—लिखने के समय न्यूनतम राशि $5 है + +3. [API कुंजी बनाएँ](https://platform.openai.com/settings/organization/api-keys) + +4. कमांड लाइन में, एपीआई कुंजी को निर्यात करें ताकि आपका प्रोग्राम इसका उपयोग कर सके + + ```sh + export OPENAI_API_KEY=sk-<बाकी कुंजी यहाँ जाती है> + ``` + +5. एजेंट को चेकआउट करें और चलाएं + + ```sh + git checkout 04-interface-llm + uv run agent.py + ``` + +यहाँ नया कोड है। + +```python +from openai import OpenAI + +open_ai = OpenAI() # क्लाइंट OPENAI_API_KEY पर्यावरण चर पढ़ता है +``` + +OpenAI API को आयात करें और इंस्टैंशिएट करें। + +```python +response = open_ai.chat.completions.create( + model="gpt-4-turbo", + messages=[ + {"role": "user", "content": prompt} + ], + temperature=0.0, + max_tokens=16, +) +``` + +प्रतिक्रिया बनाने के लिए OpenAI API (`open_ai.chat.completions.create`) को कॉल करें। + +```python +expected_price = Decimal(response.choices[0].message.content.strip()) +current_price = wethusdc_quotes[-1].price + +print ("वर्तमान मूल्य:", wethusdc_quotes[-1].price) +print(f"भविष्य में {future_time}, अपेक्षित मूल्य: {expected_price} USD") + +if (expected_price > current_price): + print(f"खरीदें, मुझे उम्मीद है कि कीमत {expected_price - current_price} USD तक बढ़ जाएगी") +else: + print(f"बेचें, मुझे उम्मीद है कि कीमत {current_price - expected_price} USD तक गिर जाएगी") +``` + +कीमत का आउटपुट दें और खरीदें या बेचें की सिफारिश करें। + +#### भविष्यवाणियों का परीक्षण {#testing-the-predictions} + +अब जब हम भविष्यवाणियां उत्पन्न कर सकते हैं, तो हम यह आकलन करने के लिए ऐतिहासिक डेटा का भी उपयोग कर सकते हैं कि क्या हम उपयोगी भविष्यवाणियां उत्पन्न करते हैं। + +```sh +uv run test-predictor.py +``` + +अपेक्षित परिणाम इसके समान है: + +``` +2026-01-05T19:50 के लिए भविष्यवाणी: भविष्यवाणी 3138.93 USD, वास्तविक 3218.92 USD, त्रुटि 79.99 USD +2026-01-06T19:56 के लिए भविष्यवाणी: भविष्यवाणी 3243.39 USD, वास्तविक 3221.08 USD, त्रुटि 22.31 USD +2026-01-07T20:02 के लिए भविष्यवाणी: भविष्यवाणी 3223.24 USD, वास्तविक 3146.89 USD, त्रुटि 76.35 USD +2026-01-08T20:11 के लिए भविष्यवाणी: भविष्यवाणी 3150.47 USD, वास्तविक 3092.04 USD, त्रुटि 58.43 USD +. +. +. +2026-01-31T22:33 के लिए भविष्यवाणी: भविष्यवाणी 2637.73 USD, वास्तविक 2417.77 USD, त्रुटि 219.96 USD +2026-02-01T22:41 के लिए भविष्यवाणी: भविष्यवाणी 2381.70 USD, वास्तविक 2318.84 USD, त्रुटि 62.86 USD +2026-02-02T22:49 के लिए भविष्यवाणी: भविष्यवाणी 2234.91 USD, वास्तविक 2349.28 USD, त्रुटि 114.37 USD +29 भविष्यवाणियों पर औसत भविष्यवाणी त्रुटि: 83.87103448275862068965517241 USD +प्रति अनुशंसा औसत परिवर्तन: 4.787931034482758620689655172 USD +परिवर्तनों का मानक विचरण: 104.42 USD +लाभदायक दिन: 51.72% +नुकसान वाले दिन: 48.28% +``` + +परीक्षक का अधिकांश भाग एजेंट के समान है, लेकिन यहां वे हिस्से हैं जो नए या संशोधित हैं। + +```python +CYCLES_FOR_TEST = 40 # बैकटेस्ट के लिए, हम कितने चक्रों का परीक्षण करते हैं + +# बहुत सारे उद्धरण प्राप्त करें +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +हम `CYCLES_FOR_TEST` (यहाँ 40 के रूप में निर्दिष्ट) दिन पीछे देखते हैं। + +```python +# भविष्यवाणियां बनाएं और उन्हें वास्तविक इतिहास के विरुद्ध जांचें + +total_error = Decimal(0) +changes = [] +``` + +दो प्रकार की त्रुटियां हैं जिनमें हम रुचि रखते हैं। पहला, `टोटल_एरर`, भविष्यवक्ता द्वारा की गई त्रुटियों का योग है। + +दूसरा, `परिवर्तन` को समझने के लिए, हमें एजेंट के उद्देश्य को याद रखने की आवश्यकता है। यह WETH/USDC अनुपात (ETH मूल्य) की भविष्यवाणी करने के लिए नहीं है। यह बेचने और खरीदने की सिफारिशें जारी करने के लिए है। यदि कीमत वर्तमान में $2000 है और यह कल $2010 की भविष्यवाणी करता है, तो हमें कोई आपत्ति नहीं है यदि वास्तविक परिणाम $2020 है और हम अतिरिक्त पैसा कमाते हैं। लेकिन हमें _ आपत्ति है _ यदि इसने $2010 की भविष्यवाणी की, और उस सिफारिश के आधार पर ETH खरीदा, और कीमत $1990 तक गिर जाती है। + +```python +for index in range(0,len(wethusdc_quotes)-CYCLES_BACK): +``` + +हम केवल उन मामलों को देख सकते हैं जहां पूरा इतिहास (भविष्यवाणी के लिए उपयोग किए गए मान और वास्तविक-विश्व मान जिसके साथ इसकी तुलना की जानी है) उपलब्ध है। इसका मतलब है कि सबसे नया मामला वह होना चाहिए जो `CYCLES_BACK` पहले शुरू हुआ था। + +```python + wethusdc_slice = wethusdc_quotes[index:index+CYCLES_BACK] + wethwbtc_slice = wethwbtc_quotes[index:index+CYCLES_BACK] +``` + +एजेंट द्वारा उपयोग किए जाने वाले नमूनों की संख्या के समान संख्या प्राप्त करने के लिए [स्लाइस](https://www.w3schools.com/python/ref_func_slice.asp) का उपयोग करें। यहां और अगले खंड के बीच का कोड वही गेट-ए-प्रेडिक्शन कोड है जो हमारे पास एजेंट में है। + +```python + predicted_price = Decimal(response.choices[0].message.content.strip()) + real_price = wethusdc_quotes[index+CYCLES_BACK].price + prediction_time_price = wethusdc_quotes[index+CYCLES_BACK-1].price +``` + +अनुमानित मूल्य, वास्तविक मूल्य और भविष्यवाणी के समय मूल्य प्राप्त करें। यह निर्धारित करने के लिए कि क्या सिफारिश खरीदने या बेचने की थी, हमें भविष्यवाणी के समय मूल्य की आवश्यकता है। + +```python + error = abs(predicted_price - real_price) + total_error += error + print (f"भविष्यवाणी के लिए {prediction_time}: भविष्यवाणी की गई {predicted_price} USD, वास्तविक {real_price} USD, त्रुटि {error} USD") +``` + +त्रुटि का पता लगाएं, और इसे कुल में जोड़ें। + +```python + recomended_action = 'buy' if predicted_price > prediction_time_price else 'sell' + price_increase = real_price - prediction_time_price + changes.append(price_increase if recomended_action == 'buy' else -price_increase) +``` + +`बदलाव` के लिए, हम एक ETH खरीदने या बेचने के मौद्रिक प्रभाव चाहते हैं। इसलिए सबसे पहले, हमें सिफारिश निर्धारित करने की आवश्यकता है, फिर यह आकलन करें कि वास्तविक मूल्य कैसे बदला, और क्या सिफारिश ने पैसा बनाया (सकारात्मक परिवर्तन) या पैसे की लागत (नकारात्मक परिवर्तन)। + +```python +print (f"Mean prediction error over {len(wethusdc_quotes)-CYCLES_BACK} predictions: {total_error / Decimal(len(wethusdc_quotes)-CYCLES_BACK)} USD") + +length_changes = Decimal(len(changes)) +mean_change = sum(changes, Decimal(0)) / length_changes +print (f"Mean change per recommendation: {mean_change} USD") +var = sum((x - mean_change) ** 2 for x in changes) / length_changes +print (f"Standard variance of changes: {var.sqrt().quantize(Decimal("0.01"))} USD") +``` + +परिणामों की रिपोर्ट करें। + +```python +print (f"लाभदायक दिन: {len(list(filter(lambda x: x > 0, changes)))/length_changes:.2%}") +print (f"नुकसान वाले दिन: {len(list(filter(lambda x: x < 0, changes)))/length_changes:.2%}") +``` + +लाभदायक दिनों की संख्या और महंगे दिनों की संख्या की गणना करने के लिए [`filter`](https://www.w3schools.com/python/ref_func_filter.asp) का उपयोग करें। परिणाम एक फ़िल्टर ऑब्जेक्ट है, जिसे लंबाई प्राप्त करने के लिए हमें एक सूची में बदलने की आवश्यकता है। + +### लेन-देन जमा करना {#submit-txn} + +अब हमें वास्तव में लेन-देन जमा करने की आवश्यकता है। हालांकि, मैं इस समय असली पैसा खर्च नहीं करना चाहता, जब तक कि सिस्टम साबित न हो जाए। इसके बजाय, हम मेननेट का एक स्थानीय फोर्क बनाएंगे, और उस नेटवर्क पर "ट्रेड" करेंगे। + +यहां एक स्थानीय फोर्क बनाने और ट्रेडिंग को सक्षम करने के चरण दिए गए हैं। + +1. [फाउंड्री](https://getfoundry.sh/introduction/installation) इंस्टॉल करें + +2. [`अनविल`](https://getfoundry.sh/anvil/overview) शुरू करें + + ```sh + anvil --fork-url https://eth.drpc.org --block-time 12 + ``` + + `अनविल` फाउंड्री के लिए डिफ़ॉल्ट URL, http://localhost:8545 पर सुन रहा है, इसलिए हमें [ `कास्ट` कमांड](https://getfoundry.sh/cast/overview) के लिए URL निर्दिष्ट करने की आवश्यकता नहीं है जिसका उपयोग हम ब्लॉकचेन में हेरफेर करने के लिए करते हैं। + +3. `अनविल` में चलने पर, दस परीक्षण खाते होते हैं जिनमें ETH होता है - पहले वाले के लिए पर्यावरण चर सेट करें + + ```sh + PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ADDRESS=`cast wallet address $PRIVATE_KEY` + ``` + +4. ये वे अनुबंध हैं जिनका हमें उपयोग करने की आवश्यकता है। [`SwapRouter`](https://github.com/Uniswap/v3-periphery/blob/main/contracts/SwapRouter.sol) Uniswap v3 कॉन्ट्रैक्ट है जिसका उपयोग हम वास्तव में व्यापार करने के लिए करते हैं। हम सीधे पूल के माध्यम से व्यापार कर सकते हैं, लेकिन यह बहुत आसान है। + + दो नीचे के चर WETH और USDC के बीच स्वैप करने के लिए आवश्यक Uniswap v3 पथ हैं। + + ```sh + WETH_ADDRESS=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + USDC_ADDRESS=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + POOL_ADDRESS=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 + SWAP_ROUTER=0xE592427A0AEce92De3Edee1F18E0157C05861564 + WETH_TO_USDC=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + USDC_TO_WETH=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + ``` + +5. प्रत्येक परीक्षण खाते में 10,000 ETH हैं। ट्रेडिंग के लिए 1000 WETH प्राप्त करने के लिए WETH अनुबंध का उपयोग करके 1000 ETH को रैप करें। + + ```sh + cast send $WETH_ADDRESS "deposit()" --value 1000ether --private-key $PRIVATE_KEY + ``` + +6. USDC के लिए 500 WETH का व्यापार करने के लिए `SwapRouter` का उपयोग करें। + + ```sh + cast send $WETH_ADDRESS "approve(address,uint256)" $SWAP_ROUTER 500ether --private-key $PRIVATE_KEY + MAXINT=`cast max-int uint256` + cast send $SWAP_ROUTER \ + "exactInput((bytes,address,uint256,uint256,uint256))" \ + "($WETH_TO_USDC,$ADDRESS,$MAXINT,500ether,1000000)" \ + --private-key $PRIVATE_KEY + ``` + + `अनुमोदन` कॉल एक भत्ता बनाता है जो `SwapRouter` को हमारे कुछ टोकन खर्च करने की अनुमति देता है। कॉन्ट्रैक्ट्स इवेंट्स की निगरानी नहीं कर सकते हैं, इसलिए यदि हम सीधे `SwapRouter` कॉन्ट्रैक्ट में टोकन स्थानांतरित करते हैं, तो उसे पता नहीं चलेगा कि उसे भुगतान किया गया है। इसके बजाय, हम `SwapRouter` कॉन्ट्रैक्ट को एक निश्चित राशि खर्च करने की अनुमति देते हैं, और फिर `SwapRouter` ऐसा करता है। यह `SwapRouter` द्वारा बुलाए गए फ़ंक्शन के माध्यम से किया जाता है, इसलिए यह जानता है कि यह सफल रहा या नहीं। + +7. सत्यापित करें कि आपके पास दोनों टोकन पर्याप्त हैं। + + ```sh + cast call $WETH_ADDRESS "balanceOf(address)" $ADDRESS | cast from-wei + echo `cast call $USDC_ADDRESS "balanceOf(address)" $ADDRESS | cast to-dec`/10^6 | bc + ``` + +अब जब हमारे पास WETH और USDC हैं, तो हम वास्तव में एजेंट चला सकते हैं। + +```sh +git checkout 05-trade +uv run agent.py +``` + +आउटपुट इसके समान दिखेगा: + +``` +(ai-trading-agent) qbzzt@Ori-Cloudnomics:~/260215-ai-agent$ uv run agent.py +वर्तमान मूल्य: 1843.16 +2026-02-06T23:07 में, अपेक्षित मूल्य: 1724.41 USD +ट्रेड से पहले खाते की शेष राशि: +USDC शेष: 927301.578272 +WETH शेष: 500 +बेचें, मुझे उम्मीद है कि कीमत 118.75 USD तक गिर जाएगी +अनुमोदन लेनदेन भेजा गया: 74e367ddbb407c1aaf567d87aa5863049991b1d2aa092b6b85195d925e2bd41f +अनुमोदन लेनदेन खनन किया गया। +विक्रय लेनदेन भेजा गया: fad1bcf938585c9e90364b26ac7a80eea9efd34c37e5db81e58d7655bcae28bf +विक्रय लेनदेन खनन किया गया। +व्यापार के बाद खाता शेष: +USDC शेष: 929143.797116 +WETH शेष: 499 +``` + +वास्तव में इसका उपयोग करने के लिए, आपको कुछ छोटे बदलावों की आवश्यकता है। + +- लाइन 14 में, `MAINNET_URL` को वास्तविक एक्सेस प्वाइंट में बदलें, जैसे `https://eth.drpc.org` +- लाइन 28 में, `PRIVATE_KEY` को अपनी निजी चाबी में बदलें +- जब तक आप बहुत अमीर नहीं हैं और एक अप्रमाणित एजेंट के लिए हर दिन 1 ETH खरीद या बेच सकते हैं, तब तक आप `WETH_TRADE_AMOUNT` को कम करने के लिए 29 को बदलना चाह सकते हैं। + +#### कोड स्पष्टीकरण {#trading-code} + +यहाँ नया कोड है। + +```python +SWAP_ROUTER_ADDRESS=Web3.to_checksum_address("0xE592427A0AEce92De3Edee1F18E0157C05861564") +WETH_TO_USDC=bytes.fromhex("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") +USDC_TO_WETH=bytes.fromhex("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +``` + +वही चर जो हमने चरण 4 में उपयोग किए थे। + +```python +WETH_TRADE_AMOUNT=1 +``` + +ट्रेड करने की राशि। + +```python +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... }, + { "name": "balanceOf", ...}, + { "name": "approve", ...} +] +``` + +वास्तव में व्यापार करने के लिए, हमें `अनुमोदन` फ़ंक्शन की आवश्यकता है। हम पहले और बाद में शेष राशि भी दिखाना चाहते हैं, इसलिए हमें `बैलेंसऑफ़` की भी आवश्यकता है। + +```python +SWAP_ROUTER_ABI = [ + { "name": "exactInput", ...}, +] +``` + +`SwapRouter` ABI में हमें बस `exactInput` की आवश्यकता है। एक संबंधित फ़ंक्शन है, `exactOutput`, जिसका उपयोग हम ठीक एक WETH खरीदने के लिए कर सकते हैं, लेकिन सरलता के लिए हम दोनों मामलों में `exactInput` का उपयोग करते हैं। + +```python +account = w3.eth.account.from_key(PRIVATE_KEY) +swap_router = w3.eth.contract( + address=SWAP_ROUTER_ADDRESS, + abi=SWAP_ROUTER_ABI +) +``` + +[`खाता`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html) और `SwapRouter` अनुबंध के लिए Web3 परिभाषाएँ। + +```python +def txn_params() -> dict: + return { + "from": account.address, + "value": 0, + "gas": 300000, + "nonce": w3.eth.get_transaction_count(account.address), + } +``` + +लेन-देन के पैरामीटर। हमें यहां एक फ़ंक्शन की आवश्यकता है क्योंकि [नोंस](https://en.wikipedia.org/wiki/Cryptographic_nonce) हर बार बदलना चाहिए। + +```python +def approve_token(contract: Contract, amount: int): +``` + +`SwapRouter` के लिए एक टोकन भत्ते को मंजूरी दें। + +```python + txn = contract.functions.approve(SWAP_ROUTER_ADDRESS, amount).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) +``` + +यह है कि हम Web3 में एक लेनदेन कैसे भेजते हैं। सबसे पहले हम लेन-देन बनाने के लिए [`कॉन्ट्रैक्ट` ऑब्जेक्ट](https://web3py.readthedocs.io/en/stable/web3.contract.html) का उपयोग करते हैं। फिर हम लेन-देन पर हस्ताक्षर करने के लिए [`web3.eth.account.sign_transaction`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-contract-transaction) का उपयोग करते हैं, `PRIVATE_KEY` का उपयोग करके। अंत में, हम लेन-देन भेजने के लिए [`w3.eth.send_raw_transaction`](https://web3py.readthedocs.io/en/stable/transactions.html#chapter-2-w3-eth-send-raw-transaction) का उपयोग करते हैं। + +```python + print(f"अनुमोदन लेनदेन भेजा गया: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("अनुमोदन लेनदेन खनन किया गया।") +``` + +[`w3.eth.wait_for_transaction_receipt`](https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.wait_for_transaction_receipt) तब तक प्रतीक्षा करता है जब तक कि लेनदेन खनन न हो जाए। यदि आवश्यक हो तो यह रसीद लौटाता है। + +```python +SELL_PARAMS = { + "path": WETH_TO_USDC, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": WETH_TRADE_AMOUNT * 10 ** wethusdc_pool.token1.decimals, + "amountOutMinimum": 0, +} +``` + +ये WETH बेचते समय के पैरामीटर हैं। + +```python +def make_buy_params(quote: Quote) -> dict: + return { + "path": USDC_TO_WETH, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": int(quote.price*WETH_TRADE_AMOUNT) * 10**wethusdc_pool.token0.decimals, + "amountOutMinimum": 0, + } +``` + +`SELL_PARAMS` के विपरीत, खरीद पैरामीटर बदल सकते हैं। इनपुट राशि 1 WETH की लागत है, जैसा कि `उद्धरण` में उपलब्ध है। + +```python +def buy(quote: Quote): + buy_params = make_buy_params(quote) + approve_token(wethusdc_pool.token0.contract, buy_params["amountIn"]) + txn = swap_router.functions.exactInput(buy_params).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Buy transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Buy transaction mined.") + + +def sell(): + approve_token(wethusdc_pool.token1.contract, + WETH_TRADE_AMOUNT * 10**wethusdc_pool.token1.decimals) + txn = swap_router.functions.exactInput(SELL_PARAMS).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Sell transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Sell transaction mined.") +``` + +`buy()` और `sell()` फ़ंक्शन लगभग समान हैं। पहले हम `SwapRouter` के लिए पर्याप्त भत्ते को मंजूरी देते हैं, और फिर हम इसे सही पथ और राशि के साथ बुलाते हैं। + +```python +def balances(): + token0_balance = wethusdc_pool.token0.contract.functions.balanceOf(account.address).call() + token1_balance = wethusdc_pool.token1.contract.functions.balanceOf(account.address).call() + + print(f"{wethusdc_pool.token0.symbol} Balance: {Decimal(token0_balance) / Decimal(10 ** wethusdc_pool.token0.decimals)}") + print(f"{wethusdc_pool.token1.symbol} Balance: {Decimal(token1_balance) / Decimal(10 ** wethusdc_pool.token1.decimals)}") +``` + +दोनों मुद्राओं में यूज़र शेष राशि की रिपोर्ट करें। + +```python +print("ट्रेड से पहले खाते की शेष राशि:") +शेष राशि() + +if (expected_price > current_price): + print(f"खरीदें, मुझे उम्मीद है कि कीमत {expected_price - current_price} USD तक बढ़ जाएगी") + buy(wethusdc_quotes[-1]) +else: + print(f"बेचें, मुझे उम्मीद है कि कीमत {current_price - expected_price} USD तक गिर जाएगी") + sell() + +print("ट्रेड के बाद खाते की शेष राशि:") +balances() +``` + +यह एजेंट वर्तमान में केवल एक बार काम करता है। हालांकि, आप इसे [`क्रॉन्टैब`](https://man7.org/linux/man-pages/man1/crontab.1.html) से चलाकर या लूप में 368-400 लाइनों को लपेटकर और अगले चक्र के लिए समय होने तक प्रतीक्षा करने के लिए [`टाइम.स्लीप`](https://docs.python.org/3/library/time.html#time.sleep) का उपयोग करके इसे लगातार काम करने के लिए बदल सकते हैं। + +## संभावित सुधार {#improvements} + +यह एक पूर्ण उत्पादन संस्करण नहीं है; यह केवल मूल बातें सिखाने के लिए एक उदाहरण है। यहां सुधार के लिए कुछ विचार दिए गए हैं। + +### स्मार्ट ट्रेडिंग {#smart-trading} + +दो महत्वपूर्ण तथ्य हैं जिन्हें एजेंट क्या करना है यह तय करते समय अनदेखा करता है। + +- _प्रत्याशित परिवर्तन की भयावहता_। एजेंट `WETH` की एक निश्चित राशि बेचता है यदि कीमत में गिरावट की उम्मीद है, गिरावट की भयावहता की परवाह किए बिना। + तर्कसंगत रूप से, मामूली बदलावों को अनदेखा करना और कीमत में गिरावट की उम्मीद के आधार पर बेचना बेहतर होगा। +- _वर्तमान पोर्टफोलियो_। यदि आपके पोर्टफोलियो का 10% WETH में है और आपको लगता है कि कीमत बढ़ेगी, तो शायद अधिक खरीदना समझ में आता है। लेकिन अगर आपके पोर्टफोलियो का 90% WETH में है, तो आप पर्याप्त रूप से उजागर हो सकते हैं, और अधिक खरीदने की कोई आवश्यकता नहीं है। यदि आप कीमत में गिरावट की उम्मीद करते हैं तो विपरीत सच है। + +### क्या होगा यदि आप अपनी ट्रेडिंग रणनीति को गुप्त रखना चाहते हैं? {#secret} + +AI विक्रेता आपके द्वारा उनके LLMs को भेजी गई क्वेरी देख सकते हैं, जो आपके एजेंट के साथ विकसित की गई जीनियस ट्रेडिंग प्रणाली को उजागर कर सकती है। एक ट्रेडिंग सिस्टम जिसका बहुत से लोग उपयोग करते हैं वह बेकार है क्योंकि बहुत से लोग तब खरीदने की कोशिश करते हैं जब आप खरीदना चाहते हैं (और कीमत बढ़ जाती है) और तब बेचने की कोशिश करते हैं जब आप बेचना चाहते हैं (और कीमत गिर जाती है)। + +आप इस समस्या से बचने के लिए स्थानीय रूप से एक LLM चला सकते हैं, उदाहरण के लिए, [LM-Studio](https://lmstudio.ai/) का उपयोग करके। + +### AI बॉट से AI एजेंट तक {#bot-to-agent} + +आप एक अच्छा मामला बना सकते हैं कि यह [एक AI बॉट है, AI एजेंट नहीं](/ai-agents/#ai-agents-vs-ai-bots)। यह एक अपेक्षाकृत सरल रणनीति लागू करता है जो पूर्वनिर्धारित जानकारी पर निर्भर करती है। हम स्व-सुधार को सक्षम कर सकते हैं, उदाहरण के लिए, Uniswap v3 पूलों की एक सूची और उनके नवीनतम मूल्यों को प्रदान करके और यह पूछकर कि किस संयोजन का सबसे अच्छा पूर्वानुमान मूल्य है। + +### स्लिपेज सुरक्षा {#slippage-protection} + +वर्तमान में कोई [स्लिपेज सुरक्षा](https://uniswapv3book.com/milestone_3/slippage-protection.html) नहीं है। यदि वर्तमान उद्धरण $2000 है, और अपेक्षित मूल्य $2100 है, तो एजेंट खरीदेगा। हालांकि, यदि एजेंट खरीदने से पहले लागत $2200 तक बढ़ जाती है, तो अब और खरीदने का कोई मतलब नहीं है। + +स्लिपेज सुरक्षा को लागू करने के लिए, [`agent.py`](https://github.com/qbzzt/260215-ai-agent/blob/05-trade/agent.py#L325) की पंक्तियों 325 और 334 में `amountOutMinimum` मान निर्दिष्ट करें। + +## निष्कर्ष {#conclusion} + +उम्मीद है, अब आप AI एजेंटों के साथ शुरुआत करने के लिए पर्याप्त जानते हैं। यह विषय का एक व्यापक अवलोकन नहीं है; इसके लिए पूरी किताबें समर्पित हैं, लेकिन यह आपको शुरू करने के लिए पर्याप्त है। शुभकामनाएँ! + +[मेरे और काम के लिए यहाँ देखें](https://cryptodocguy.pro/)। diff --git a/public/content/translations/id/community/support/faq/index.md b/public/content/translations/id/community/support/faq/index.md new file mode 100644 index 00000000000..2640927f102 --- /dev/null +++ b/public/content/translations/id/community/support/faq/index.md @@ -0,0 +1,77 @@ +--- +title: Pertanyaan yang sering diajukan +description: Pertanyaan umum Ethereum tentang dompet, transaksi, penaruhan, dan lainnya. +lang: id +--- + +# Pertanyaan yang sering diajukan {#faq} + +## Saya mengirim kripto ke alamat yang salah {#wrong-wallet} + +Transaksi yang dikirimkan di Ethereum tidak dapat dibalikkan. Sayangnya, jika Anda mengirim ETH atau token ke dompet yang salah, tidak ada cara untuk membalikkan transaksi tersebut. + +**Apa yang dapat Anda lakukan:** + +- **Jika Anda mengetahui pemilik alamat tersebut**, hubungi mereka secara langsung dan minta mereka untuk mengembalikan dananya +- **Jika alamat tersebut milik bursa atau layanan yang dikenal**, hubungi tim dukungan mereka, karena mereka mungkin dapat membantu +- **Jika Anda mengirim token ke akun kontrak**, periksa apakah kontrak tersebut memiliki fungsi penarikan atau pemulihan (ini jarang terjadi) + +Dalam sebagian besar kasus, tidak ada cara untuk memulihkan dana tersebut. Tidak ada organisasi, entitas, atau orang pusat yang memiliki Ethereum, yang berarti tidak ada yang bisa membalikkan transaksi. Selalu periksa kembali alamat penerima sebelum mengonfirmasi. + +## Saya kehilangan akses ke dompet saya {#lost-wallet-access} + +Opsi pemulihan Anda bergantung pada jenis dompet yang Anda gunakan. + +### Jika Anda memiliki frase benih (frasa pemulihan) Anda + +Anda dapat memulihkan dompet Anda di aplikasi dompet apa pun yang kompatibel menggunakan frase benih Anda. Inilah sebabnya sangat penting untuk menyimpan frase benih Anda dengan aman secara luring. Periksa dokumentasi penyedia dompet Anda untuk instruksi pemulihan. + +### Jika Anda kehilangan frase benih Anda + +Tanpa frase benih atau kunci pribadi Anda, dana Anda tidak dapat dipulihkan. Tidak seorang pun, termasuk ethereum.org, dapat mengatur ulang kata sandi Anda atau memulihkan akses ke dompet kustodi mandiri. + +### Jika akun Anda ada di bursa + +Jika akun Anda ada di bursa terpusat seperti Coinbase, Binance, atau Kraken, hubungi tim dukungan bursa secara langsung. Mereka mengontrol akun di platform mereka dan mungkin dapat membantu mengatur ulang kata sandi atau pemulihan akun. + + + + + + +**Jangan pernah membagikan frase benih Anda kepada siapa pun** yang mengaku membantu Anda memulihkan dompet Anda. Ini adalah salah satu taktik penipuan yang paling umum. Tidak ada layanan sah yang akan pernah meminta frase benih Anda. + + + + + + Cara menggunakan dompet + + +## Transaksi saya macet atau tertunda {#stuck-transaction} + +Transaksi di Ethereum bisa macet ketika biaya gas yang Anda tetapkan lebih rendah dari yang dibutuhkan jaringan saat ini. Sebagian besar dompet memungkinkan Anda memperbaikinya: + +- **Percepat:** Kirim ulang transaksi yang sama dengan biaya gas yang lebih tinggi +- **Batalkan:** Kirim transaksi 0 ETH ke alamat Anda sendiri menggunakan nonce yang sama dengan transaksi yang tertunda + +### Panduan bermanfaat + +- [Cara mempercepat atau membatalkan transaksi yang tertunda di MetaMask](https://support.metamask.io/transactions-and-gas/transactions/how-to-speed-up-or-cancel-a-pending-transaction/) +- [Cara membatalkan transaksi Ethereum yang tertunda](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) + +## Bagaimana saya dapat mengklaim hadiah Ethereum? {#giveaway-scam} + +Hadiah Ethereum adalah penipuan yang dirancang untuk mencuri ETH Anda. Jangan tergoda oleh penawaran yang tampaknya terlalu bagus untuk menjadi kenyataan. Jika Anda mengirim ETH ke alamat giveaway, Anda tidak akan menerima giveaway, dan Anda tidak akan dapat memulihkan dana Anda. + +[Selengkapnya tentang pencegahan penipuan](/security/#common-scams) + +## Bagaimana cara saya melakukan penaruhan ETH? {#how-to-stake} + +Untuk menjadi seorang validator, Anda harus memasang taruhan 32 ETH di kontrak deposit Ethereum dan mengatur simpul validator. Anda juga dapat berpartisipasi dengan lebih sedikit ETH melalui pool penaruhan. + +Informasi lebih lanjut tersedia di [halaman penaruhan](/staking/) kami dan di [landasan peluncuran penaruhan](https://launchpad.ethereum.org/) + +## Bagaimana cara menambang Ethereum? {#mining-ethereum} + +Penambangan Ethereum tidak lagi memungkinkan. Penambangan dinonaktifkan ketika Ethereum beralih dari [bukti kerja](/glossary/#pow) ke [bukti taruhan](/glossary/#pos) selama [Penggabungan](/roadmap/merge/) pada bulan September 2022. Sekarang, Ethereum memiliki validator, bukan penambang. Siapa pun dapat [melakukan penaruhan](/glossary/#staking) ETH dan menerima imbalan penaruhan dengan menjalankan perangkat lunak validator untuk mengamankan jaringan. diff --git a/public/content/translations/id/community/support/index.md b/public/content/translations/id/community/support/index.md deleted file mode 100644 index 93d7ba70bb2..00000000000 --- a/public/content/translations/id/community/support/index.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: Dukungan Ethereum -description: Mendapatkan dukungan di ekosistem Ethereum. -lang: id ---- - -# Dukungan Ethereum {#support} - -## Dukungan resmi Ethereum {#official-support} - -Apakah Anda sedang mencari dukungan resmi Ethereum? Hal pertama yang harus Anda ketahui adalah bahwa Ethereum bersifat terdesentralisasi. Ini berarti tidak ada organisasi, entitas, atau orang sentral yang memiliki Ethereum, dan karena ini, tidak ada kanal dukungan resmi. - -Memahami sifat terdesentralisasi Ethereum sangat penting karena siapa pun yang mengklaim sebagai pemberi dukungan resmi Ethereum mungkin sedang mencoba menipu Anda! Perlindungan terbaik terhadap para penipu adalah mengedukasi diri Anda sendiri dan memperhatikan aspek keamanan dengan serius. - - - Keamanan dan pencegahan penipuan Ethereum - - - - Pelajari tentang fundamental Ethereum - - -Sekalipun kurang adanya dukungan resmi, banyak kelompok, komunitas, dan proyek di keseluruhan ekosistem Ethereum senang memberikan bantuan. - -## Dukungan dompet {#wallet-support} - -Mengalami masalah dengan dompet Anda? Kebanyakan dompet telah mendedikasikan tim dukungan yang dapat menolong: - -- [MetaMask](https://metamask.zendesk.com/hc/) -- [Argent](https://support.argent.xyz/hc/) -- [MyEtherWallet](https://help.myetherwallet.com/) - -_Ini bukanlah daftar yang lengkap. Perlu bantuan menemukan bantuan untuk dompet yang khusus? Bergabunglah dengan [discord ethereum.org](https://discord.gg/ethereum-org) dan kami akan mencoba menolong Anda._ - -Sedang mencari dompet Ethereum? [Jelajahi daftar lengkap dompet Ethereum kami](/wallets/find-wallet/). - -## Membangun dapps {#building-support} - -Membangun dapat bisa saja sulit. Berikut adalah beberapa lingkungan yang berfokus pengembangan dengan para pengembang Ethereum berpengalaman yang senang memberikan bantuan. - -- [Discord CryptoDevs](https://discord.gg/Z9TA39m8Yu) -- [StackExchange Ethereum](https://ethereum.stackexchange.com/) -- [Universitas Web3](https://www.web3.university/) - -Anda juga dapat menemukan dokumentasi dan panduan pengembangan di bagian [Sumber pengembang Ethereum](/developers/) kami. - -### Perangkat {#dapp-tooling} - -Apakah pertanyaan Anda terkait dengan peralatan, proyek, atau pustaka tertentu? Kebanyakan proyek memiliki peladen atau forum obrolan yang dikhususkan untuk mendukung Anda. - -Berikut adalah beberapa contoh populer: - -- [Solidity](https://app.element.io/#/room/#solidity:matrix.org) -- [ethers.js](https://discord.gg/6jyGVDK6Jx) -- [web3.js](https://discord.gg/GsABYQu4sC) -- [Hardhat](https://discord.gg/xtrMGhmbfZ) -- [Alchemy](http://alchemy.com/discord) - -## Menjalankan node {#node-support} - -Jika Anda menjalankan node atau validator, berikut adalah beberapa komunitas yang dikhususkan untuk menolong Anda memulai. - -- [Discord EthStaker](https://discord.gg/ethstaker) -- [Reddit EthStaker](https://www.reddit.com/r/ethstaker) - -Kebanyakan tim yang membangun klien Ethereum juga telah mendedikasikan lingkungan untuk publik di mana Anda dapat mendapatkan dukungan dan mengajukan pertanyaan. - -### Klien eksekusi {#execution-clients} - -- [Geth](https://discord.gg/FqDzupGyYf) -- [Nethermind](https://discord.gg/YJx3pm8z5C) -- [Besu](https://discord.gg/p8djYngzKN) -- [Erigon](https://github.com/ledgerwatch/erigon/issues) - -### Klien konsensus {#consensus-clients} - -- [Prysm](https://discord.gg/prysmaticlabs) -- [Nimbus](https://discord.gg/nSmEH3qgFv) -- [Lighthouse](https://discord.gg/cyAszAh) -- [Teku](https://discord.gg/7hPv2T6) -- [Lodestar](https://discord.gg/aMxzVcr) - -Anda juga dapat [mempelajari cara menjalankan node di sini](/developers/docs/nodes-and-clients/run-a-node/). - -## Pertanyaan yang sering diajukan {#faq} - -### Saya telah mengirim ETH ke dompet yang salah {#wrong-wallet} - -Transaksi yang dikirimkan di Ethereum tidak dapat dibalikkan. Sayangnya, jika Anda telah mengirim ETH ke dompet yang salah, tidak ada cara untuk mendapatkan kembali dana ini. Tidak ada satu organisasi, entitas, atau orang sentral yang memiliki Ethereum, yang berarti tidak ada satu pun yang dapat membalikkan transaksi. Oleh karena itu, sangat penting untuk selalu memeriksa ulang transaksi Anda sebelum mengirimkannya. - -### Bagaimana saya dapat mengklaim hadiah Ethereum? {#giveaway-scam} - -Hadiah Ethereum adalah penipuan yang dirancang untuk mencuri ETH Anda. Jangan tergoda dengan penawaran yang tampak terlalu menggiurkan — jika Anda mengirim ETH ke suatu alamat hadiah, Anda tidak akan menerima hadiah, dan Anda tidak akan dapat mendapatkan dana Anda kembali. - -[Lebih lanjut tentang pencegahan penipuan](/security/#common-scams) - -### Transaksi saya macet {#stuck-transaction} - -Transaksi di Ethereum dapat terkadang mengalami kemacetan jika Anda telah mengirimkan biaya transaksi yang lebih rendah dari yang diharuskan karena permintaan jaringan. Banyak dompet menyediakan opsi untuk mengirimkan kembali transaksi yang sama dengan biaya transaksi yang lebih tinggi untuk memungkinkan transaksi diproses. Sebagai alternatif, Anda dapat membatalkan transaksi berstatus tunggu dengan mengirimkan transaksi ke alamat Anda sendiri dan menggunakan nonce yang sama sebagai transaksi berstatus tunggu. - -[Cara mempercepat atau membatalkan transaksi berstatus tunggu di MetaMask](https://metamask.zendesk.com/hc/en-us/articles/360015489251-How-to-speed-up-or-cancel-a-pending-transaction) - -[Cara membatalkan transaksi Ethereum berstatus tunggu](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) - -### Bagaimana cara menambang Ethereum? {#mining-ethereum} - -Kami tidak menyarankan membeli peralatan menambang jika Anda belum menambang Ethereum. Di ~Q3/Q4 2022, [penggabungan](/roadmap/merge/) akan terjadi, yang mengalihkan Ethereum dari bukti kerja ke bukti taruhan. Perubahan ini berarti menambang Ethereum tidak akan mungkin lagi. diff --git a/public/content/translations/id/community/support/misconceptions/index.md b/public/content/translations/id/community/support/misconceptions/index.md new file mode 100644 index 00000000000..2b745aa96fb --- /dev/null +++ b/public/content/translations/id/community/support/misconceptions/index.md @@ -0,0 +1,73 @@ +--- +title: Kekeliruan umum tentang Ethereum +description: Menjelaskan kesalahpahaman paling umum tentang cara kerja Ethereum. +lang: id +--- + +# Kekeliruan umum tentang Ethereum {#misconceptions} + +## Apakah Ethereum adalah perusahaan? {#not-a-company} + +Ethereum adalah teknologi sumber terbuka dan terdesentralisasi yang dikelola oleh ribuan kontributor di seluruh dunia. Tidak ada perusahaan bernama "Ethereum" yang mengelola akun, menyimpan dana, atau menyediakan dukungan pelanggan. + +[Ethereum Foundation](https://ethereum.foundation/) adalah organisasi nirlaba yang mendukung pengembangan Ethereum, tetapi tidak memiliki atau mengendalikan jaringan tersebut. Tidak ada satu entitas pun yang melakukannya. + +**[ethereum.org](/)** adalah sumber daya edukasi yang dijalankan oleh komunitas. Ini bukanlah bursa, dompet, atau lembaga keuangan. Situs ini tidak menyimpan dana pengguna mana pun dan tidak dapat mengakses akun mana pun. + + + Apa itu Ethereum? + + +## Bisakah seseorang memulihkan atau membekukan dana saya? {#no-fund-access} + +Tidak seperti bank, tidak ada otoritas pusat di Ethereum yang dapat membekukan, menyita, atau memulihkan dana. Orang yang memegang kunci pribadi (atau frase benih) memiliki kendali penuh dan satu-satunya atas dompet. + +Ini berarti: + +- **Tidak ada yang dapat memulihkan dana** yang Anda kirim ke alamat yang salah +- **Tidak ada yang dapat membatalkan** transaksi setelah dikonfirmasi +- **Tidak ada yang dapat membekukan** dompet Anda atau memblokir transaksi Anda +- **Tidak ada yang dapat mengatur ulang kata sandi Anda** jika Anda kehilangan frase benih Anda + +Inilah mengapa melindungi frase benih Anda sangat penting. Itu adalah satu-satunya cara untuk mengakses dompet Anda. Jika hilang atau dicuri, tidak ada pilihan pemulihan. + + + Keamanan Ethereum dan pencegahan penipuan + + +## Apakah saya masih bisa menambang Ethereum? {#no-mining} + +Ethereum beralih dari [bukti kerja](/glossary/#pow) ke [bukti taruhan](/glossary/#pos) selama [Penggabungan](/roadmap/merge/) pada bulan September 2022. Menambang tidak lagi memungkinkan di Ethereum. + +Jaringan ini sekarang diamankan oleh validator yang [menaruhkan](/glossary/#staking) ETH. Siapa pun dapat berpartisipasi: + +- **Penaruhan solo:** Jalankan validator Anda sendiri dengan 32 ETH—[pelajari selengkapnya](/staking/solo/) +- **Penaruhan sebagai layanan:** Delegasikan operasi simpul sambil tetap menyimpan kunci Anda—[pelajari selengkapnya](/staking/saas/) +- **Penaruhan terkumpul:** Taruhkan dengan kurang dari 32 ETH dengan bergabung dalam sebuah pool—[pelajari selengkapnya](/staking/pools/) + + + Pelajari selengkapnya tentang penaruhan + + +## Apakah ada tim dukungan Ethereum? {#no-support-team} + +Mencari "dukungan resmi Ethereum" mirip dengan mencari "dukungan resmi internet." Tentu saja ini tidak ada, tetapi tergantung pada masalah Anda, Anda mungkin dapat mencari dukungan dari penyedia layanan internet Anda, produsen perangkat keras router Anda, atau salah satu perusahaan di balik perangkat, aplikasi, atau situs web yang Anda gunakan. + +Ethereum juga serupa. Tidak ada perusahaan, tim dukungan, atau meja bantuan di balik Ethereum secara keseluruhan, tetapi tergantung pada masalahnya, Anda mungkin menemukan bantuan dengan menghubungi _penyedia dompet_ Anda, _layanan penaruhan_, _bursa_, _lembaga keuangan_, atau _tim yang mengelola aplikasi_ yang Anda gunakan. + +Karena Ethereum secara default transparan untuk publik, Anda mungkin juga menemukan [penjelajah blok](/developers/docs/data-and-analytics/block-explorers/), [perangkat analisis](/developers/tools/analytics/), dan [sumber daya investigasi daring](/community/support/scams/#analyze) lainnya yang berguna untuk menyelidiki masalah secara langsung. + +Meskipun begitu, tidak seorang pun dari Ethereum atau ethereum.org yang akan pernah: + +- Menghubungi Anda melalui pesan langsung +- Meminta frase benih atau kunci pribadi Anda +- Meminta Anda mengirim ETH untuk memverifikasi dompet Anda +- Menawarkan untuk membantu Anda memulihkan dana dengan biaya tertentu + +**Siapa pun yang melakukan salah satu hal di atas sedang mencoba menipu Anda.** + +Jika Anda membutuhkan bantuan, komunitas nyata yang dapat membantu tercantum di [halaman dukungan](/community/support/). Ini adalah komunitas terbuka yang dijalankan oleh sukarelawan—bukan saluran dukungan resmi. + + + Keamanan Ethereum dan pencegahan penipuan + diff --git a/public/content/translations/id/community/support/scams/index.md b/public/content/translations/id/community/support/scams/index.md new file mode 100644 index 00000000000..d0a5d2668ca --- /dev/null +++ b/public/content/translations/id/community/support/scams/index.md @@ -0,0 +1,159 @@ +--- +title: Bantuan & pelaporan penipuan +description: Apa yang harus dilakukan jika Anda telah ditipu, cara mengamankan sisa aset Anda, dan di mana harus melaporkan penipuan. +lang: id +--- + +# Saya ditipu atau kehilangan dana {#scam-help} + +Penipuan mata uang kripto menargetkan orang-orang dari semua tingkat pengalaman, termasuk para profesional di bidang keuangan dan teknologi. Anda tidak sendirian, dan berada di sini adalah langkah pertama yang tepat. + + + + + + +**Tidak ada yang bisa membalikkan transaksi blockchain.** Jika seseorang menghubungi Anda dan mengklaim bahwa mereka dapat memulihkan dana Anda dengan biaya tertentu, itu hampir pasti merupakan penipuan kedua. Lihat [penipuan pemulihan](#recovery-scams) di bawah. + + + + +## Amankan sisa aset Anda {#secure-assets} + +Jika Anda berinteraksi dengan penipu atau mencurigai dompet Anda disusupi, segera ambil langkah-langkah berikut: + +1. **Pindahkan dana yang tersisa** ke dompet baru yang aman yang tidak dapat diakses oleh penipu +2. **Cabut persetujuan token.** Penipu sering kali menipu Anda untuk menyetujui pembelanjaan token tanpa batas. Mencabut izin ini mencegah pengurasan lebih lanjut dari dompet Anda +3. **Ubah kata sandi** pada akun bursa apa pun yang mungkin tertaut +4. **Aktifkan autentikasi dua faktor (2FA)** di semua akun yang terkait dengan kripto + +### Cara mencabut persetujuan token {#revoke-approvals} + +Saat Anda berinteraksi dengan dapp atau kontrak pintar, Anda mungkin telah memberinya izin untuk membelanjakan token Anda. Jika seorang penipu menipu Anda untuk menyetujui kontrak jahat, mereka dapat terus menguras token Anda bahkan setelah penipuan awal. + +Gunakan alat ini untuk memeriksa dan mencabut persetujuan: + +- [Revoke.cash](https://revoke.cash/): hubungkan dompet Anda untuk melihat semua persetujuan aktif dan mencabutnya +- [Revokescout](https://revoke.blockscout.com/): periksa dan cabut persetujuan melalui Blockscout +- [Pemeriksa Persetujuan Token Etherscan](https://etherscan.io/tokenapprovalchecker): periksa dan cabut persetujuan melalui Etherscan + + + Panduan langkah demi langkah: Cara mencabut akses token + + +## Laporkan alamat dan situs web penipuan {#report} + +Melaporkan membantu memperingatkan pengguna lain dan dapat membantu penyelidikan penegakan hukum. Dokumentasikan semuanya: hash transaksi, alamat dompet, tangkapan layar, dan komunikasi apa pun dengan penipu. + +### Laporkan alamat penipuan {#report-address} + +- [Chainabuse](https://www.chainabuse.com/): basis data pelaporan penipuan dan kejahatan yang didorong oleh komunitas. Kirim laporan dan cari alamat penipuan yang diketahui +- [Laporan Etherscan](https://info.etherscan.com/report-address/): tandai alamat di penjelajah blok Ethereum yang paling banyak digunakan +- [CryptoScamDB](https://cryptoscamdb.org/): basis data sumber terbuka yang melacak penipuan mata uang kripto + +### Laporkan situs web penipuan atau akun media sosial {#report-website} + +- [PhishTank](https://phishtank.org/): kirim dan verifikasi URL phishing +- [Penjelajahan Aman Google](https://safebrowsing.google.com/safebrowsing/report_phish/): laporkan situs phishing ke Google agar diblokir di Chrome dan peramban lainnya +- [Netcraft](https://report.netcraft.com/report/mistake): melaporkan situs web jahat dan penipuan +- Laporkan langsung di platform media sosial tempat penipuan terjadi (Twitter/X, Discord, Telegram semuanya memiliki fitur pelaporan) + +### Laporkan ke penegak hukum {#report-law-enforcement} + +- **Amerika Serikat:** [Pusat Pengaduan Kejahatan Internet FBI (IC3)](https://www.ic3.gov/) +- **Britania Raya:** [Action Fraud](https://www.actionfraud.police.uk/) +- **Uni Eropa:** [Europol](https://www.europol.europa.eu/report-a-crime) +- **Negara lain:** ajukan laporan ke polisi setempat. Penipuan mata uang kripto adalah kejahatan di sebagian besar yurisdiksi + +## Analisis apa yang terjadi {#analyze} + +Memahami ke mana dana Anda pergi dapat membantu laporan dan dapat mendukung upaya pemulihan jika dana tersebut mendarat di bursa terpusat. + +- [Blockscout](https://eth.blockscout.com/): penjelajah blok sumber terbuka untuk mencari hash transaksi atau alamat dompet apa pun untuk melihat ke mana dana dikirim +- [Etherscan](https://etherscan.io/): cari hash transaksi atau alamat dompet apa pun untuk melihat ke mana dana dikirim +- [Pencarian Chainabuse](https://www.chainabuse.com/): periksa apakah suatu alamat telah dilaporkan oleh korban lain +- [MetaSleuth](https://metasleuth.io/) oleh BlockSec: alat pelacakan transaksi visual yang memetakan alur dana + +**Jika dana dikirim ke bursa terpusat** (seperti Coinbase, Binance, Kraken), segera hubungi tim dukungan mereka dengan detail transaksi. Bursa terkadang dapat membekukan akun yang ditandai karena penipuan. + +## Kenyataan pahit {#hard-truth} + +Karena Ethereum terdesentralisasi, tidak ada otoritas pusat yang dapat membalikkan transaksi atau memulihkan dana yang dicuri. Setelah transaksi dikonfirmasi di blockchain, transaksi tersebut bersifat final. + +Melaporkan tetap berharga. Laporan membantu penegak hukum melacak jaringan penipuan yang terorganisir, dan menandai alamat di Chainabuse dan Etherscan akan memperingatkan calon korban di masa depan. + +## Jenis-jenis penipuan yang harus diwaspadai {#scam-types} + + + +Penipu membuat giveaway palsu yang menjanjikan untuk melipatgandakan ETH Anda atau memberi Anda token gratis. Mereka sering menyamar sebagai tokoh terkenal seperti Vitalik Buterin. Jika Anda mengirim ETH ke alamat "giveaway", Anda tidak akan menerima apa pun kembali. + +**Ingat:** Vitalik dan tokoh terkemuka lainnya tidak akan pernah meminta Anda untuk mengirimkan ETH kepada mereka. + +[Lebih lanjut tentang penipuan umum](/security/#common-scams) + + + + +Penipu menyamar sebagai anggota tim Ethereum, moderator, atau agen dukungan di Discord, Telegram, dan media sosial. Mereka mungkin mengirimi Anda pesan langsung yang menawarkan bantuan atau mengklaim ada masalah dengan akun Anda. + +**Ingat:** + +- Tidak ada "tim dukungan Ethereum" +- Moderator sungguhan tidak akan pernah mengirimi Anda DM terlebih dahulu +- Jangan pernah membagikan frase benih atau kunci pribadi Anda kepada siapa pun, dengan alasan apa pun +- Jangan pernah mengeklik tautan yang dikirim dalam pesan yang tidak diminta + + + + +Penipuan pemulihan secara khusus menargetkan orang-orang yang telah kehilangan dana. Penipu memantau media sosial untuk mencari orang-orang yang membicarakan tentang ditipu, lalu menghubungi mereka dengan menyamar sebagai "penyelidik blockchain" atau "ahli pemulihan kripto." + +Mereka berjanji untuk melacak dan memulihkan kripto Anda yang dicuri dengan biaya di muka. Setelah Anda membayar, mereka menghilang. + +**Tidak ada layanan sah yang dapat membalikkan transaksi blockchain.** Siapa pun yang menjanjikan hal ini berarti berbohong. Ini adalah salah satu penipuan tindak lanjut yang paling umum. + + + + +Situs phishing terlihat identik dengan aplikasi dompet, bursa, atau platform DeFi asli. Mereka menipu Anda untuk memasukkan frase benih Anda atau menghubungkan dompet Anda, lalu menguras dana Anda. + +**Lindungi diri Anda:** + +- Selalu verifikasi URL sebelum menghubungkan dompet Anda +- Tandai situs resmi yang sering Anda gunakan +- Jangan pernah memasukkan frase benih Anda di situs web mana pun. Aplikasi yang sah tidak pernah memintanya +- Gunakan [PhishTank](https://phishtank.org/) untuk memeriksa URL yang mencurigakan + + + Cara mengidentifikasi token penipuan + + + + + Panduan lengkap untuk keamanan Ethereum dan pencegahan penipuan + diff --git a/public/content/translations/id/developers/tutorials/ai-trading-agent/index.md b/public/content/translations/id/developers/tutorials/ai-trading-agent/index.md new file mode 100644 index 00000000000..a1cc717596f --- /dev/null +++ b/public/content/translations/id/developers/tutorials/ai-trading-agent/index.md @@ -0,0 +1,980 @@ +--- +title: Buat agen perdagangan AI Anda sendiri di Ethereum +description: Dalam tutorial ini Anda akan belajar cara membuat agen perdagangan AI sederhana. Agen ini membaca informasi dari rantai blok, meminta rekomendasi dari LLM berdasarkan informasi tersebut, melakukan perdagangan yang direkomendasikan LLM, lalu menunggu dan mengulangi. +author: Ori Pomerantz +tags: [ "AI", "perdagangan", "agen", "python" ] +skill: intermediate +published: 2026-02-13 +lang: id +sidebarDepth: 3 +--- + +Dalam tutorial ini Anda akan belajar cara membangun agen perdagangan AI sederhana. Agen ini bekerja menggunakan langkah-langkah berikut: + +1. Baca harga token saat ini dan yang lalu, serta informasi lain yang berpotensi relevan +2. Buat kueri dengan informasi ini, beserta informasi latar belakang untuk menjelaskan bagaimana informasi tersebut mungkin relevan +3. Kirimkan kueri dan terima kembali harga yang diproyeksikan +4. Perdagangkan berdasarkan rekomendasi +5. Tunggu dan ulangi + +Agen ini menunjukkan cara membaca informasi, menerjemahkannya ke dalam kueri yang menghasilkan jawaban yang dapat digunakan, dan menggunakan jawaban tersebut. Semua ini adalah langkah-langkah yang diperlukan untuk agen AI. Agen ini diimplementasikan dalam Python karena ini adalah bahasa yang paling umum digunakan dalam AI. + +## Mengapa melakukan ini? {#why-do-this} + +Agen perdagangan otomatis memungkinkan pengembang untuk memilih dan menjalankan strategi perdagangan. [Agen AI](/ai-agents) memungkinkan strategi perdagangan yang lebih kompleks dan dinamis, berpotensi menggunakan informasi dan algoritma yang bahkan belum dipertimbangkan oleh pengembang untuk digunakan. + +## Perangkat {#tools} + +Tutorial ini menggunakan [Python](https://www.python.org/), [pustaka Web3](https://web3py.readthedocs.io/en/stable/), dan [Uniswap v3](https://github.com/Uniswap/v3-periphery) untuk kuotasi dan perdagangan. + +### Mengapa Python? {#python} + +Bahasa yang paling banyak digunakan untuk AI adalah [Python](https://www.python.org/), jadi kami menggunakannya di sini. Jangan khawatir jika Anda tidak tahu Python. Bahasa ini sangat jelas, dan saya akan menjelaskan dengan tepat apa yang dilakukannya. + +[Pustaka Web3](https://web3py.readthedocs.io/en/stable/) adalah API Python Ethereum yang paling umum. Cukup mudah digunakan. + +### Berdagang di rantai blok {#trading-on-blockchain} + +Ada [banyak bursa terdesentralisasi (DEX)](/apps/categories/defi/) yang memungkinkan Anda memperdagangkan token di Ethereum. Namun, mereka cenderung memiliki nilai tukar yang serupa karena [arbitrase](/developers/docs/smart-contracts/composability/#better-user-experience). + +[Uniswap](https://app.uniswap.org/) adalah DEX yang banyak digunakan yang dapat kita gunakan untuk kuotasi (untuk melihat nilai relatif token) dan perdagangan. + +### OpenAI {#openai} + +Untuk model bahasa besar, saya memilih untuk memulai dengan [OpenAI](https://openai.com/). Untuk menjalankan aplikasi dalam tutorial ini, Anda harus membayar untuk akses API. Pembayaran minimum sebesar $5 sudah lebih dari cukup. + +## Pengembangan, langkah demi langkah {#step-by-step} + +Untuk menyederhanakan pengembangan, kita akan melanjutkannya secara bertahap. Setiap langkah adalah sebuah cabang di GitHub. + +### Memulai {#getting-started} + +Ada langkah-langkah untuk memulai di bawah UNIX atau Linux (termasuk [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)) + +1. Jika Anda belum memilikinya, unduh dan instal [Python](https://www.python.org/downloads/). + +2. Kloning repositori GitHub. + + ```sh + git clone https://github.com/qbzzt/260215-ai-agent.git -b 01-getting-started + cd 260215-ai-agent + ``` + +3. Instal [`uv`](https://docs.astral.sh/uv/getting-started/installation/). Perintah di sistem Anda mungkin berbeda. + + ```sh + pipx install uv + ``` + +4. Unduh pustaka. + + ```sh + uv sync + ``` + +5. Aktifkan lingkungan virtual. + + ```sh + source .venv/bin/activate + ``` + +6. Untuk memverifikasi Python dan Web3 berfungsi dengan benar, jalankan `python3` dan berikan program ini. Anda dapat memasukkannya di prompt `>>>`; tidak perlu membuat file. + + ```python + from web3 import Web3 + MAINNET_URL = "https://eth.drpc.org" + w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) + w3.eth.block_number + quit() + ``` + +### Membaca dari rantai blok {#read-blockchain} + +Langkah selanjutnya adalah membaca dari rantai blok. Untuk melakukannya, Anda perlu beralih ke cabang `02-read-quote` lalu menggunakan `uv` untuk menjalankan program. + +```sh +git checkout 02-read-quote +uv run agent.py +``` + +Anda akan menerima daftar objek `Quote`, masing-masing dengan stempel waktu, harga, dan aset (saat ini selalu `WETH/USDC`). + +Berikut adalah penjelasan baris demi baris. + +```python +from web3 import Web3 +from web3.contract import Contract +from decimal import Decimal, ROUND_HALF_UP +from dataclasses import dataclass +from datetime import datetime, timezone +from pprint import pprint +import time +import functools +import sys +``` + +Impor pustaka yang kita butuhkan. Mereka dijelaskan di bawah ini saat digunakan. + +```python +print = functools.partial(print, flush=True) +``` + +Mengganti `print` Python dengan versi yang selalu membersihkan keluaran dengan segera. Ini berguna dalam skrip yang berjalan lama karena kita tidak ingin menunggu pembaruan status atau keluaran debugging. + +```python +MAINNET_URL = "https://eth.drpc.org" +``` + +Sebuah URL untuk menuju ke Jaringan Utama. Anda bisa mendapatkan satu dari [Simpul sebagai layanan](/developers/docs/nodes-and-clients/nodes-as-a-service/) atau menggunakan salah satu yang diiklankan di [Chainlist](https://chainlist.org/chain/1). + +```python +BLOCK_TIME_SECONDS = 12 +MINUTE_BLOCKS = int(60 / BLOCK_TIME_SECONDS) +HOUR_BLOCKS = MINUTE_BLOCKS * 60 +DAY_BLOCKS = HOUR_BLOCKS * 24 +``` + +Sebuah blok Jaringan Utama Ethereum biasanya terjadi setiap dua belas detik, jadi ini adalah jumlah blok yang kita harapkan terjadi dalam suatu periode waktu. Perhatikan bahwa ini bukan angka yang pasti. Ketika [pengusul blok](/developers/docs/consensus-mechanisms/pos/block-proposal/) tidak berfungsi, blok tersebut dilewati, dan waktu untuk blok berikutnya adalah 24 detik. Jika kita ingin mendapatkan blok yang tepat untuk stempel waktu, kita akan menggunakan [pencarian biner](https://en.wikipedia.org/wiki/Binary_search). Namun, ini sudah cukup dekat untuk tujuan kita. Memprediksi masa depan bukanlah ilmu pasti. + +```python +CYCLE_BLOCKS = DAY_BLOCKS +``` + +Ukuran siklus. Kami meninjau kuotasi sekali per siklus dan mencoba memperkirakan nilai di akhir siklus berikutnya. + +```python +# Alamat pool yang kita baca +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +``` + +Nilai kuotasi diambil dari pool Uniswap 3 USDC/WETH di alamat [`0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`](https://eth.blockscout.com/address/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640?tab=read_write_contract). Alamat ini sudah dalam bentuk checksum, tetapi lebih baik menggunakan [`Web3.to_checksum_address`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_checksum_address) untuk membuat kode dapat digunakan kembali. + +```python +POOL_ABI = [ + { "name": "slot0", ... }, + { "name": "token0", ... }, + { "name": "token1", ... }, +] + +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... } +] +``` + +Ini adalah [ABI](https://docs.soliditylang.org/en/latest/abi-spec.html) untuk dua kontrak yang perlu kita hubungi. Untuk menjaga agar kode tetap ringkas, kami hanya menyertakan fungsi yang perlu kami panggil. + +```python +w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) +``` + +Mulai pustaka [`Web3`](https://web3py.readthedocs.io/en/stable/quickstart.html#remote-providers) dan sambungkan ke simpul Ethereum. + +```python +@dataclass(frozen=True) +class ERC20Token: + address: str + symbol: str + decimals: int + contract: Contract +``` + +Ini adalah salah satu cara untuk membuat kelas data di Python. Tipe data [`Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) digunakan untuk terhubung ke kontrak. Perhatikan `(frozen=True)`. Dalam Python, [boolean](https://en.wikipedia.org/wiki/Boolean_data_type) didefinisikan sebagai `True` atau `False`, dengan huruf besar. Kelas data ini `beku` (frozen), artinya bidang-bidangnya tidak dapat dimodifikasi. + +Perhatikan indentasi. Berbeda dengan [bahasa turunan C](https://en.wikipedia.org/wiki/List_of_C-family_programming_languages), Python menggunakan indentasi untuk menunjukkan blok. Interpreter Python tahu bahwa definisi berikut bukan bagian dari kelas data ini karena tidak dimulai pada indentasi yang sama dengan bidang kelas data. + +```python +@dataclass(frozen=True) +class PoolInfo: + address: str + token0: ERC20Token + token1: ERC20Token + contract: Contract + asset: str + decimal_factor: Decimal = 1 +``` + +Tipe [`Decimal`](https://docs.python.org/3/library/decimal.html) digunakan untuk menangani pecahan desimal secara akurat. + +```python + def get_price(self, block: int) -> Decimal: +``` + +Ini adalah cara untuk mendefinisikan sebuah fungsi di Python. Definisi tersebut diberi indentasi untuk menunjukkan bahwa ia masih merupakan bagian dari `PoolInfo`. + +Dalam sebuah fungsi yang merupakan bagian dari kelas data, parameter pertama selalu `self`, yaitu instance kelas data yang memanggilnya. Di sini ada parameter lain, yaitu nomor blok. + +```python + assert block <= w3.eth.block_number, "Blok ada di masa depan" +``` + +Jika kita bisa membaca masa depan, kita tidak akan memerlukan AI untuk berdagang. + +```python + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) +``` + +Sintaks untuk memanggil fungsi di EVM dari Web3 adalah ini: `.functions.().call(). Parameter dapat berupa parameter fungsi EVM (jika ada; di sini tidak ada) atau [parameter bernama](https://en.wikipedia.org/wiki/Named_parameter) untuk mengubah perilaku rantai blok. Di sini kita menggunakan satu, `block_identifier`, untuk menentukan [nomor blok](/developers/docs/apis/json-rpc/#default-block) yang ingin kita jalankan. + +Hasilnya adalah [struct ini, dalam bentuk array](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol#L56-L72). Nilai pertama adalah fungsi dari nilai tukar antara dua token. + +```python + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 +``` + +Untuk mengurangi kalkulasi di dalam rantai, Uniswap v3 tidak menyimpan faktor pertukaran aktual tetapi akar kuadratnya. Karena EVM tidak mendukung matematika titik mengambang atau pecahan, alih-alih nilai aktual, responsnya adalah harga296 + +```python + # (token1 per token0) + return 1/(raw_price * self.decimal_factor) +``` + +Harga mentah yang kita dapatkan adalah jumlah `token0` yang kita peroleh untuk setiap `token1`. Di pool kami, `token0` adalah USDC (Koin Stabil dengan nilai yang sama dengan dolar AS) dan `token1` adalah [WETH](https://opensea.io/learn/blockchain/what-is-weth). Nilai yang sebenarnya kita inginkan adalah jumlah dolar per WETH, bukan kebalikannya. + +Faktor desimal adalah rasio antara [faktor desimal](https://docs.openzeppelin.com/contracts/4.x/erc20#a-note-on-decimals) untuk kedua token tersebut. + +```python +@dataclass(frozen=True) +class Quote: + timestamp: str + price: Decimal + asset: str +``` + +Kelas data ini mewakili sebuah kuotasi: harga aset tertentu pada titik waktu tertentu. Pada titik ini, bidang `asset` tidak relevan karena kita menggunakan satu pool dan oleh karena itu hanya memiliki satu aset. Namun, kami akan menambahkan lebih banyak aset nanti. + +```python +def read_token(address: str) -> ERC20Token: + token = w3.eth.contract(address=address, abi=ERC20_ABI) + symbol = token.functions.symbol().call() + decimals = token.functions.decimals().call() + + return ERC20Token( + address=address, + symbol=symbol, + decimals=decimals, + contract=token + ) +``` + +Fungsi ini mengambil sebuah alamat dan mengembalikan informasi tentang kontrak token di alamat tersebut. Untuk membuat [Kontrak Web3](https://web3py.readthedocs.io/en/stable/web3.contract.html) yang baru, kita memberikan alamat dan ABI ke `w3.eth.contract`. + +```python +def read_pool(address: str) -> PoolInfo: + pool_contract = w3.eth.contract(address=address, abi=POOL_ABI) + token0Address = pool_contract.functions.token0().call() + token1Address = pool_contract.functions.token1().call() + token0 = read_token(token0Address) + token1 = read_token(token1Address) + + return PoolInfo( + address=address, + asset=f"{token1.symbol}/{token0.symbol}", + token0=token0, + token1=token1, + contract=pool_contract, + decimal_factor=Decimal(10) ** Decimal(token0.decimals - token1.decimals) + ) +``` + +Fungsi ini mengembalikan semua yang kita butuhkan tentang [pool tertentu](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol). Sintaks `f""` adalah [string yang diformat](https://docs.python.org/3/reference/lexical_analysis.html#f-strings). + +```python +def get_quote(pool: PoolInfo, block_number: int = None) -> Quote: +``` + +Dapatkan objek `Quote`. Nilai default untuk `block_number` adalah `None` (tidak ada nilai). + +```python + if block_number is None: + block_number = w3.eth.block_number +``` + +Jika nomor blok tidak ditentukan, gunakan `w3.eth.block_number`, yang merupakan nomor blok terbaru. Ini adalah sintaks untuk [pernyataan `if`](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement). + +Mungkin terlihat seolah-olah akan lebih baik jika hanya mengatur default ke `w3.eth.block_number`, tetapi itu tidak bekerja dengan baik karena itu akan menjadi nomor blok pada saat fungsi didefinisikan. Dalam agen yang berjalan lama, ini akan menjadi masalah. + +```python + block = w3.eth.get_block(block_number) + price = pool.get_price(block_number) + return Quote( + timestamp=datetime.fromtimestamp(block.timestamp, timezone.utc).isoformat(), + price=price.quantize(Decimal("0.01")), + asset=pool.asset + ) +``` + +Gunakan [pustaka `datetime`](https://docs.python.org/3/library/datetime.html) untuk memformatnya ke format yang dapat dibaca oleh manusia dan model bahasa besar (LLM). Gunakan [`Decimal.quantize`](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) untuk membulatkan nilai ke dua tempat desimal. + +```python +def get_quotes(pool: PoolInfo, start_block: int, end_block: int, step: int) -> list[Quote]: +``` + +Di Python Anda mendefinisikan sebuah [daftar](https://docs.python.org/3/library/stdtypes.html#typesseq-list) yang hanya dapat berisi tipe tertentu menggunakan `list[]`. + +```python + quotes = [] + for block in range(start_block, end_block + 1, step): +``` + +Di Python sebuah [`for` loop](https://docs.python.org/3/tutorial/controlflow.html#for-statements) biasanya melakukan iterasi pada sebuah daftar. Daftar nomor blok untuk menemukan kutipan berasal dari [`range`](https://docs.python.org/3/library/stdtypes.html#range). + +```python + quote = get_quote(pool, block) + quotes.append(quote) + return quotes +``` + +Untuk setiap nomor blok, dapatkan objek `Quote` dan tambahkan ke daftar `quotes`. Kemudian kembalikan daftar itu. + +```python +pool = read_pool(WETHUSDC_ADDRESS) +quotes = get_quotes( + pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) + +pprint(quotes) +``` + +Ini adalah kode utama dari skrip. Baca informasi pool, dapatkan dua belas kutipan, dan [`pprint`](https://docs.python.org/3/library/pprint.html#pprint.pprint) mereka. + +### Membuat prompt {#prompt} + +Selanjutnya, kita perlu mengubah daftar kutipan ini menjadi sebuah prompt untuk LLM dan mendapatkan nilai masa depan yang diharapkan. + +```sh +git checkout 03-create-prompt +uv run agent.py +``` + +Outputnya sekarang akan menjadi prompt untuk LLM, mirip dengan: + +``` +Mengingat kutipan ini: +Aset: WETH/USDC + 2026-01-20T16:34 3016.21 + . + . + . + 2026-02-01T17:49 2299.10 + +Aset: WBTC/WETH + 2026-01-20T16:34 29.84 + . + . + . + 2026-02-01T17:50 33.46 + + +Berapa nilai yang Anda harapkan untuk WETH/USDC pada waktu 2026-02-02T17:56? + +Berikan jawaban Anda sebagai satu angka yang dibulatkan ke dua tempat desimal, +tanpa teks lain. +``` + +Perhatikan bahwa ada kutipan untuk dua aset di sini, `WETH/USDC` dan `WBTC/WETH`. Menambahkan kutipan dari aset lain mungkin meningkatkan akurasi prediksi. + +#### Seperti apa bentuk sebuah prompt {#prompt-explanation} + +Prompt ini berisi tiga bagian, yang cukup umum dalam prompt LLM. + +1. Informasi. LLM memiliki banyak informasi dari pelatihan mereka, tetapi biasanya mereka tidak memiliki yang terbaru. Inilah alasan kita perlu mengambil kutipan terbaru di sini. Menambahkan informasi ke prompt disebut [retrieval augmented generation (RAG)](https://en.wikipedia.org/wiki/Retrieval-augmented_generation). + +2. Pertanyaan sebenarnya. Inilah yang ingin kita ketahui. + +3. Instruksi pemformatan output. Biasanya, LLM akan memberi kita perkiraan dengan penjelasan tentang bagaimana ia sampai pada perkiraan tersebut. Ini lebih baik untuk manusia, tetapi program komputer hanya membutuhkan hasil akhirnya. + +#### Penjelasan kode {#prompt-code} + +Berikut adalah kode barunya. + +```python +from datetime import datetime, timezone, timedelta +``` + +Kita perlu memberikan LLM waktu yang kita inginkan untuk perkiraan. Untuk mendapatkan waktu "n menit/jam/hari" di masa depan, kita menggunakan [kelas `timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta). + +```python +# Alamat pool yang kita baca +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +WETHWBTC_ADDRESS = Web3.to_checksum_address("0xCBCdF9626bC03E24f779434178A73a0B4bad62eD") +``` + +Kita memiliki dua pool yang perlu dibaca. + +```python +@dataclass(frozen=True) +class PoolInfo: + . + . + . + reverse: bool = False + + def get_price(self, block: int) -> Decimal: + assert block <= w3.eth.block_number, "Blok ada di masa depan" + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 # (token1 per token0) + if self.reverse: + return 1/(raw_price * self.decimal_factor) + else: + return raw_price * self.decimal_factor +``` + +Di pool WETH/USDC, kami ingin tahu berapa banyak `token0` (USDC) yang kami butuhkan untuk membeli satu `token1` (WETH). Di pool WETH/WBTC, kami ingin tahu berapa banyak `token1` (WETH) yang kami butuhkan untuk membeli satu `token0` (WBTC, yaitu Bitcoin terbungkus). Kita perlu melacak apakah rasio pool perlu dibalik. + +```python +def read_pool(address: str, reverse: bool = False) -> PoolInfo: + . + . + . + + return PoolInfo( + . + . + . + + asset= f"{token1.symbol}/{token0.symbol}" if reverse else f"{token0.symbol}/{token1.symbol}", + reverse=reverse + ) +``` + +Untuk mengetahui apakah sebuah pool perlu dibalik, kita harus mendapatkannya sebagai input untuk `read_pool`. Selain itu, simbol aset perlu diatur dengan benar. + +Sintaks ` if else ` adalah padanan Python dari [operator kondisional terner](https://en.wikipedia.org/wiki/Ternary_conditional_operator), yang dalam bahasa turunan C adalah ` ? : `. + +```python +def format_quotes(quotes: list[Quote]) -> str: + result = f"Asset: {quotes[0].asset}\n" + for quote in quotes: + result += f"\t{quote.timestamp[0:16]} {quote.price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)}\n" + return result +``` + +Fungsi ini membangun sebuah string yang memformat daftar objek `Quote`, dengan asumsi semuanya berlaku untuk aset yang sama. + +```python +def make_prompt(quotes: list[list[Quote]], expected_time: str, asset: str) -> str: + return f""" +``` + +Di Python, [literal string multibaris](https://www.w3schools.com/python/gloss_python_multi_line_strings.asp) ditulis sebagai `"""` .... `"""`. + +```python +Mengingat kutipan ini: +{ + functools.reduce(lambda acc, q: acc + '\n' + q, + map(lambda q: format_quotes(q), quotes)) +} +``` + +Di sini, kami menggunakan pola [MapReduce](https://en.wikipedia.org/wiki/MapReduce) untuk menghasilkan string untuk setiap daftar kutipan dengan `format_quotes`, lalu mereduksinya menjadi satu string untuk digunakan dalam prompt. + +```python +Berapa nilai yang Anda harapkan untuk {asset} pada waktu {expected_time}? + +Berikan jawaban Anda sebagai satu angka yang dibulatkan ke dua tempat desimal, +tanpa teks lain. + """ +``` + +Sisa dari prompt adalah seperti yang diharapkan. + +```python +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +Tinjau kedua pool dan dapatkan kuotasi dari keduanya. + +```python +future_time = (datetime.now(timezone.utc) + timedelta(days=1)).isoformat()[0:16] + +print(make_prompt(wethusdc_quotes + wethwbtc_quotes, future_time, wethusdc_pool.asset)) +``` + +Tentukan titik waktu masa depan yang kita inginkan estimasinya, dan buat prompt. + +### Berinteraksi dengan LLM {#interface-llm} + +Selanjutnya, kita akan meminta LLM yang sebenarnya dan menerima nilai masa depan yang diharapkan. Saya menulis program ini menggunakan OpenAI, jadi jika Anda ingin menggunakan penyedia yang berbeda, Anda harus menyesuaikannya. + +1. Dapatkan [akun OpenAI](https://auth.openai.com/create-account) + +2. [Danai akun](https://platform.openai.com/settings/organization/billing/overview)—jumlah minimum pada saat penulisan adalah $5 + +3. [Buat kunci API](https://platform.openai.com/settings/organization/api-keys) + +4. Di baris perintah, ekspor kunci API agar program Anda dapat menggunakannya + + ```sh + export OPENAI_API_KEY=sk- + ``` + +5. Checkout dan jalankan agen + + ```sh + git checkout 04-interface-llm + uv run agent.py + ``` + +Berikut adalah kode barunya. + +```python +from openai import OpenAI + +open_ai = OpenAI() # Klien membaca variabel lingkungan OPENAI_API_KEY +``` + +Impor dan buat instance API OpenAI. + +```python +response = open_ai.chat.completions.create( + model="gpt-4-turbo", + messages=[ + {"role": "user", "content": prompt} + ], + temperature=0.0, + max_tokens=16, +) +``` + +Panggil API OpenAI (`open_ai.chat.completions.create`) untuk membuat respons. + +```python +expected_price = Decimal(response.choices[0].message.content.strip()) +current_price = wethusdc_quotes[-1].price + +print ("Harga saat ini:", wethusdc_quotes[-1].price) +print(f"Pada {future_time}, harga yang diharapkan: {expected_price} USD") + +if (expected_price > current_price): + print(f"Beli, saya perkirakan harga akan naik sebesar {expected_price - current_price} USD") +else: + print(f"Jual, saya perkirakan harga akan turun sebesar {current_price - expected_price} USD") +``` + +Keluarkan harga dan berikan rekomendasi beli atau jual. + +#### Menguji prediksi {#testing-the-predictions} + +Sekarang setelah kita dapat menghasilkan prediksi, kita juga dapat menggunakan data historis untuk menilai apakah kita menghasilkan prediksi yang berguna. + +```sh +uv run test-predictor.py +``` + +Hasil yang diharapkan serupa dengan: + +``` +Prediksi untuk 2026-01-05T19:50: diprediksi 3138.93 USD, riil 3218.92 USD, kesalahan 79.99 USD +Prediksi untuk 2026-01-06T19:56: diprediksi 3243.39 USD, riil 3221.08 USD, kesalahan 22.31 USD +Prediksi untuk 2026-01-07T20:02: diprediksi 3223.24 USD, riil 3146.89 USD, kesalahan 76.35 USD +Prediksi untuk 2026-01-08T20:11: diprediksi 3150.47 USD, riil 3092.04 USD, kesalahan 58.43 USD +. +. +. +Prediksi untuk 2026-01-31T22:33: diprediksi 2637.73 USD, riil 2417.77 USD, kesalahan 219.96 USD +Prediksi untuk 2026-02-01T22:41: diprediksi 2381.70 USD, riil 2318.84 USD, kesalahan 62.86 USD +Prediksi untuk 2026-02-02T22:49: diprediksi 2234.91 USD, riil 2349.28 USD, kesalahan 114.37 USD +Kesalahan prediksi rata-rata selama 29 prediksi: 83.87103448275862068965517241 USD +Perubahan rata-rata per rekomendasi: 4.787931034482758620689655172 USD +Varians standar perubahan: 104.42 USD +Hari menguntungkan: 51.72% +Hari merugi: 48.28% +``` + +Sebagian besar penguji identik dengan agen, tetapi berikut adalah bagian-bagian yang baru atau dimodifikasi. + +```python +CYCLES_FOR_TEST = 40 # Untuk backtest, berapa banyak siklus yang kita uji + +# Dapatkan banyak kutipan +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +Kami melihat ke belakang sebanyak `CYCLES_FOR_TEST` (ditentukan sebagai 40 di sini) hari. + +```python +# Buat prediksi dan periksa terhadap riwayat nyata + +total_error = Decimal(0) +changes = [] +``` + +Ada dua jenis kesalahan yang kami minati. Yang pertama, `total_error`, hanyalah jumlah kesalahan yang dibuat oleh prediktor. + +Untuk memahami yang kedua, `changes`, kita perlu mengingat tujuan agen. Tujuannya bukan untuk memprediksi rasio WETH/USDC (harga ETH). Ini untuk mengeluarkan rekomendasi jual dan beli. Jika harga saat ini adalah $2000 dan memprediksi $2010 besok, kami tidak keberatan jika hasil sebenarnya adalah $2020 dan kami mendapatkan uang tambahan. Namun, kita _keberatan_ jika diprediksi $2010, dan membeli ETH berdasarkan rekomendasi tersebut, dan harganya turun menjadi $1990. + +```python +for index in range(0,len(wethusdc_quotes)-CYCLES_BACK): +``` + +Kami hanya dapat melihat kasus di mana riwayat lengkap (nilai yang digunakan untuk prediksi dan nilai dunia nyata untuk membandingkannya) tersedia. Ini berarti kasus terbaru haruslah yang dimulai `CYCLES_BACK` yang lalu. + +```python + wethusdc_slice = wethusdc_quotes[index:index+CYCLES_BACK] + wethwbtc_slice = wethwbtc_quotes[index:index+CYCLES_BACK] +``` + +Gunakan [irisan](https://www.w3schools.com/python/ref_func_slice.asp) untuk mendapatkan jumlah sampel yang sama dengan jumlah yang digunakan agen. Kode antara di sini dan segmen berikutnya adalah kode get-a-prediction yang sama yang kami miliki di agen. + +```python + predicted_price = Decimal(response.choices[0].message.content.strip()) + real_price = wethusdc_quotes[index+CYCLES_BACK].price + prediction_time_price = wethusdc_quotes[index+CYCLES_BACK-1].price +``` + +Dapatkan harga yang diprediksi, harga riil, dan harga pada saat prediksi. Kita memerlukan harga pada saat prediksi untuk menentukan apakah rekomendasi tersebut untuk membeli atau menjual. + +```python + error = abs(predicted_price - real_price) + total_error += error + print (f"Prediksi untuk {prediction_time}: diprediksi {predicted_price} USD, riil {real_price} USD, kesalahan {error} USD") +``` + +Hitung kesalahannya, dan tambahkan ke total. + +```python + recomended_action = 'buy' if predicted_price > prediction_time_price else 'sell' + price_increase = real_price - prediction_time_price + changes.append(price_increase if recomended_action == 'buy' else -price_increase) +``` + +Untuk `changes`, kami menginginkan dampak moneter dari membeli atau menjual satu ETH. Jadi pertama, kita perlu menentukan rekomendasi, kemudian menilai bagaimana harga sebenarnya berubah, dan apakah rekomendasi tersebut menghasilkan uang (perubahan positif) atau merugikan uang (perubahan negatif). + +```python +print (f"Kesalahan prediksi rata-rata selama {len(wethusdc_quotes)-CYCLES_BACK} prediksi: {total_error / Decimal(len(wethusdc_quotes)-CYCLES_BACK)} USD") + +length_changes = Decimal(len(changes)) +mean_change = sum(changes, Decimal(0)) / length_changes +print (f"Perubahan rata-rata per rekomendasi: {mean_change} USD") +var = sum((x - mean_change) ** 2 for x in changes) / length_changes +print (f"Varians standar perubahan: {var.sqrt().quantize(Decimal("0.01"))} USD") +``` + +Laporkan hasilnya. + +```python +print (f"Hari menguntungkan: {len(list(filter(lambda x: x > 0, changes)))/length_changes:.2%}") +print (f"Hari merugi: {len(list(filter(lambda x: x < 0, changes)))/length_changes:.2%}") +``` + +Gunakan [`filter`](https://www.w3schools.com/python/ref_func_filter.asp) untuk menghitung jumlah hari yang menguntungkan dan jumlah hari yang merugikan. Hasilnya adalah objek filter, yang perlu kita ubah menjadi daftar untuk mendapatkan panjangnya. + +### Mengirimkan transaksi {#submit-txn} + +Sekarang kita perlu benar-benar mengirimkan transaksi. Namun, saya tidak ingin menghabiskan uang sungguhan pada saat ini, sebelum sistem terbukti. Sebaliknya, kita akan membuat fork lokal dari Jaringan Utama, dan "berdagang" di jaringan itu. + +Berikut adalah langkah-langkah untuk membuat fork lokal dan mengaktifkan perdagangan. + +1. Instal [Foundry](https://getfoundry.sh/introduction/installation) + +2. Mulai [`anvil`](https://getfoundry.sh/anvil/overview) + + ```sh + anvil --fork-url https://eth.drpc.org --block-time 12 + ``` + + `anvil` mendengarkan di URL default untuk Foundry, http://localhost:8545, jadi kita tidak perlu menentukan URL untuk [perintah `cast`](https://getfoundry.sh/cast/overview) yang kita gunakan untuk memanipulasi rantai blok. + +3. Saat berjalan di `anvil`, ada sepuluh akun uji yang memiliki ETH—atur variabel lingkungan untuk yang pertama + + ```sh + PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ADDRESS=`cast wallet address $PRIVATE_KEY` + ``` + +4. Ini adalah kontrak yang perlu kita gunakan. [`SwapRouter`](https://github.com/Uniswap/v3-periphery/blob/main/contracts/SwapRouter.sol) adalah kontrak Uniswap v3 yang kami gunakan untuk benar-benar berdagang. Kita bisa berdagang langsung melalui pool, tetapi ini jauh lebih mudah. + + Dua variabel terbawah adalah jalur Uniswap v3 yang diperlukan untuk menukar antara WETH dan USDC. + + ```sh + WETH_ADDRESS=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + USDC_ADDRESS=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + POOL_ADDRESS=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 + SWAP_ROUTER=0xE592427A0AEce92De3Edee1F18E0157C05861564 + WETH_TO_USDC=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + USDC_TO_WETH=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + ``` + +5. Setiap akun uji memiliki 10.000 ETH. Gunakan kontrak WETH untuk membungkus 1000 ETH untuk mendapatkan 1000 WETH untuk perdagangan. + + ```sh + cast send $WETH_ADDRESS "deposit()" --value 1000ether --private-key $PRIVATE_KEY + ``` + +6. Gunakan `SwapRouter` untuk memperdagangkan 500 WETH untuk USDC. + + ```sh + cast send $WETH_ADDRESS "approve(address,uint256)" $SWAP_ROUTER 500ether --private-key $PRIVATE_KEY + MAXINT=`cast max-int uint256` + cast send $SWAP_ROUTER \ + "exactInput((bytes,address,uint256,uint256,uint256))" \ + "($WETH_TO_USDC,$ADDRESS,$MAXINT,500ether,1000000)" \ + --private-key $PRIVATE_KEY + ``` + + Panggilan `approve` membuat tunjangan yang memungkinkan `SwapRouter` untuk membelanjakan sebagian token kita. Kontrak tidak dapat memantau aksi, jadi jika kita mentransfer token langsung ke kontrak `SwapRouter`, kontrak tersebut tidak akan tahu bahwa ia telah dibayar. Sebaliknya, kami mengizinkan kontrak `SwapRouter` untuk membelanjakan sejumlah tertentu, dan kemudian `SwapRouter` melakukannya. Ini dilakukan melalui fungsi yang dipanggil oleh `SwapRouter`, sehingga ia tahu jika berhasil. + +7. Verifikasi Anda memiliki cukup kedua token. + + ```sh + cast call $WETH_ADDRESS "balanceOf(address)" $ADDRESS | cast from-wei + echo `cast call $USDC_ADDRESS "balanceOf(address)" $ADDRESS | cast to-dec`/10^6 | bc + ``` + +Sekarang setelah kita memiliki WETH dan USDC, kita dapat benar-benar menjalankan agen. + +```sh +git checkout 05-trade +uv run agent.py +``` + +Outputnya akan terlihat mirip dengan: + +``` +(ai-trading-agent) qbzzt@Ori-Cloudnomics:~/260215-ai-agent$ uv run agent.py +Harga saat ini: 1843.16 +Pada 2026-02-06T23:07, harga yang diharapkan: 1724.41 USD +Saldo akun sebelum perdagangan: +Saldo USDC: 927301.578272 +Saldo WETH: 500 +Jual, saya perkirakan harga akan turun sebesar 118.75 USD +Transaksi approve terkirim: 74e367ddbb407c1aaf567d87aa5863049991b1d2aa092b6b85195d925e2bd41f +Transaksi approve ditambang. +Transaksi jual terkirim: fad1bcf938585c9e90364b26ac7a80eea9efd34c37e5db81e58d7655bcae28bf +Transaksi jual ditambang. +Saldo akun setelah perdagangan: +Saldo USDC: 929143.797116 +Saldo WETH: 499 +``` + +Untuk benar-benar menggunakannya, Anda memerlukan beberapa perubahan kecil. + +- Di baris 14, ubah `MAINNET_URL` ke titik akses nyata, seperti `https://eth.drpc.org` +- Pada baris 28, ubah `PRIVATE_KEY` ke kunci pribadi Anda sendiri +- Kecuali Anda sangat kaya dan dapat membeli atau menjual 1 ETH setiap hari untuk agen yang belum terbukti, Anda mungkin ingin mengubah 29 untuk mengurangi `WETH_TRADE_AMOUNT` + +#### Penjelasan kode {#trading-code} + +Berikut adalah kode barunya. + +```python +SWAP_ROUTER_ADDRESS=Web3.to_checksum_address("0xE592427A0AEce92De3Edee1F18E0157C05861564") +WETH_TO_USDC=bytes.fromhex("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") +USDC_TO_WETH=bytes.fromhex("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +``` + +Variabel yang sama yang kita gunakan di langkah 4. + +```python +WETH_TRADE_AMOUNT=1 +``` + +Jumlah yang akan diperdagangkan. + +```python +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... }, + { "name": "balanceOf", ...}, + { "name": "approve", ...} +] +``` + +Untuk benar-benar berdagang, kita memerlukan fungsi `approve`. Kami juga ingin menampilkan saldo sebelum dan sesudah, jadi kami juga memerlukan `balanceOf`. + +```python +SWAP_ROUTER_ABI = [ + { "name": "exactInput", ...}, +] +``` + +Di `SwapRouter` ABI, kita hanya perlu `exactInput`. Ada fungsi terkait, `exactOutput`, yang bisa kita gunakan untuk membeli tepat satu WETH, tetapi untuk kesederhanaan kita hanya menggunakan `exactInput` dalam kedua kasus. + +```python +account = w3.eth.account.from_key(PRIVATE_KEY) +swap_router = w3.eth.contract( + address=SWAP_ROUTER_ADDRESS, + abi=SWAP_ROUTER_ABI +) +``` + +Definisi Web3 untuk [`akun`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html) dan kontrak `SwapRouter`. + +```python +def txn_params() -> dict: + return { + "from": account.address, + "value": 0, + "gas": 300000, + "nonce": w3.eth.get_transaction_count(account.address), + } +``` + +Parameter transaksi. Kita memerlukan fungsi di sini karena [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) harus berubah setiap saat. + +```python +def approve_token(contract: Contract, amount: int): +``` + +Setujui alokasi token untuk `SwapRouter`. + +```python + txn = contract.functions.approve(SWAP_ROUTER_ADDRESS, amount).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) +``` + +Beginilah cara kami mengirim transaksi di Web3. Pertama kita menggunakan [objek `Kontrak`](https://web3py.readthedocs.io/en/stable/web3.contract.html) untuk membangun transaksi. Kemudian kita menggunakan [`web3.eth.account.sign_transaction`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-contract-transaction) untuk menandatangani transaksi, menggunakan `PRIVATE_KEY`. Terakhir, kami menggunakan [`w3.eth.send_raw_transaction`](https://web3py.readthedocs.io/en/stable/transactions.html#chapter-2-w3-eth-send-raw-transaction) untuk mengirim transaksi. + +```python + print(f"Transaksi approve terkirim: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Transaksi approve ditambang.") +``` + +[`w3.eth.wait_for_transaction_receipt`](https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.wait_for_transaction_receipt) menunggu hingga transaksi ditambang. Ini mengembalikan tanda terima jika diperlukan. + +```python +SELL_PARAMS = { + "path": WETH_TO_USDC, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": WETH_TRADE_AMOUNT * 10 ** wethusdc_pool.token1.decimals, + "amountOutMinimum": 0, +} +``` + +Ini adalah parameter saat menjual WETH. + +```python +def make_buy_params(quote: Quote) -> dict: + return { + "path": USDC_TO_WETH, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": int(quote.price*WETH_TRADE_AMOUNT) * 10**wethusdc_pool.token0.decimals, + "amountOutMinimum": 0, + } +``` + +Berbeda dengan `SELL_PARAMS`, parameter pembelian bisa berubah. Jumlah masukan adalah biaya 1 WETH, seperti yang tersedia di `quote`. + +```python +def buy(quote: Quote): + buy_params = make_buy_params(quote) + approve_token(wethusdc_pool.token0.contract, buy_params["amountIn"]) + txn = swap_router.functions.exactInput(buy_params).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Transaksi beli terkirim: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Transaksi beli ditambang.") + + +def sell(): + approve_token(wethusdc_pool.token1.contract, + WETH_TRADE_AMOUNT * 10**wethusdc_pool.token1.decimals) + txn = swap_router.functions.exactInput(SELL_PARAMS).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Transaksi jual terkirim: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Transaksi jual ditambang.") +``` + +Fungsi `buy()` dan `sell()` hampir identik. Pertama kita menyetujui alokasi yang cukup untuk `SwapRouter`, dan kemudian kita memanggilnya dengan jalur dan jumlah yang benar. + +```python +def balances(): + token0_balance = wethusdc_pool.token0.contract.functions.balanceOf(account.address).call() + token1_balance = wethusdc_pool.token1.contract.functions.balanceOf(account.address).call() + + print(f"{wethusdc_pool.token0.symbol} Balance: {Decimal(token0_balance) / Decimal(10 ** wethusdc_pool.token0.decimals)}") + print(f"{wethusdc_pool.token1.symbol} Balance: {Decimal(token1_balance) / Decimal(10 ** wethusdc_pool.token1.decimals)}") +``` + +Laporkan saldo pengguna dalam kedua mata uang. + +```python +print("Saldo akun sebelum perdagangan:") +balances() + +if (expected_price > current_price): + print(f"Beli, saya perkirakan harga akan naik sebesar {expected_price - current_price} USD") + buy(wethusdc_quotes[-1]) +else: + print(f"Jual, saya perkirakan harga akan turun sebesar {current_price - expected_price} USD") + sell() + +print("Saldo akun setelah perdagangan:") +balances() +``` + +Agen ini saat ini hanya bekerja sekali. Namun, Anda dapat mengubahnya agar berfungsi secara terus-menerus baik dengan menjalankannya dari [`crontab`](https://man7.org/linux/man-pages/man1/crontab.1.html) atau dengan membungkus baris 368-400 dalam sebuah loop dan menggunakan [`time.sleep`](https://docs.python.org/3/library/time.html#time.sleep) untuk menunggu hingga tiba waktunya untuk siklus berikutnya. + +## Kemungkinan perbaikan {#improvements} + +Ini bukan versi produksi penuh; ini hanyalah contoh untuk mengajarkan dasar-dasarnya. Berikut adalah beberapa ide untuk perbaikan. + +### Perdagangan yang lebih cerdas {#smart-trading} + +Ada dua fakta penting yang diabaikan agen saat memutuskan apa yang harus dilakukan. + +- _Besarnya perubahan yang diantisipasi_. Agen menjual sejumlah `WETH` yang tetap jika harga diperkirakan akan menurun, terlepas dari besarnya penurunan. + Boleh dibilang, akan lebih baik untuk mengabaikan perubahan kecil dan menjual berdasarkan seberapa besar kita mengharapkan harga akan turun. +- _Portofolio saat ini_. Jika 10% dari portofolio Anda ada di WETH dan Anda pikir harganya akan naik, mungkin masuk akal untuk membeli lebih banyak. Tetapi jika 90% dari portofolio Anda ada di WETH, Anda mungkin sudah cukup terekspos, dan tidak perlu membeli lebih banyak. Kebalikannya benar jika Anda mengharapkan harga akan turun. + +### Bagaimana jika Anda ingin merahasiakan strategi perdagangan Anda? {#secret} + +Vendor AI dapat melihat kueri yang Anda kirim ke LLM mereka, yang dapat mengekspos sistem perdagangan jenius yang Anda kembangkan dengan agen Anda. Sistem perdagangan yang digunakan terlalu banyak orang tidak ada gunanya karena terlalu banyak orang mencoba membeli saat Anda ingin membeli (dan harga naik) dan mencoba menjual saat Anda ingin menjual (dan harga turun). + +Anda dapat menjalankan LLM secara lokal, misalnya, menggunakan [LM-Studio](https://lmstudio.ai/), untuk menghindari masalah ini. + +### Dari bot AI ke agen AI {#bot-to-agent} + +Anda dapat membuat argumen yang baik bahwa ini adalah [bot AI, bukan agen AI](/ai-agents/#ai-agents-vs-ai-bots). Ini mengimplementasikan strategi yang relatif sederhana yang mengandalkan informasi yang telah ditentukan sebelumnya. Kita dapat mengaktifkan perbaikan diri, misalnya, dengan menyediakan daftar pool Uniswap v3 dan nilai terbarunya dan menanyakan kombinasi mana yang memiliki nilai prediktif terbaik. + +### Perlindungan slippage {#slippage-protection} + +Saat ini tidak ada [perlindungan slippage](https://uniswapv3book.com/milestone_3/slippage-protection.html). Jika kutipan saat ini adalah $2000, dan harga yang diharapkan adalah $2100, agen akan membeli. Namun, jika sebelum agen membeli biayanya naik menjadi $2200, tidak masuk akal lagi untuk membeli. + +Untuk menerapkan perlindungan slippage, tentukan nilai `amountOutMinimum` di baris 325 dan 334 dari [`agent.py`](https://github.com/qbzzt/260215-ai-agent/blob/05-trade/agent.py#L325). + +## Kesimpulan {#conclusion} + +Semoga, sekarang Anda cukup tahu untuk memulai dengan agen AI. Ini bukan gambaran umum yang komprehensif tentang subjek ini; ada seluruh buku yang didedikasikan untuk itu, tetapi ini cukup untuk membuat Anda memulai. Semoga beruntung! + +[Lihat di sini untuk lebih banyak pekerjaan saya](https://cryptodocguy.pro/). diff --git a/public/content/translations/id/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md b/public/content/translations/id/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md index 1520a37b3dd..e3c2feab844 100644 --- a/public/content/translations/id/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md +++ b/public/content/translations/id/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md @@ -114,23 +114,23 @@ sudo systemctl start grafana-server Ketika Anda telah membuat Grafana beroperasi, ia seharusnya dapat dicapai di `localhost:3000`. Gunakan peramban yang Anda inginkan untuk mengakses jalur ini, lalu masuk dengan kredensial default (pengguna: `admin` dan kata sandi: `admin`). Ketika diminta, ubah kata sandi defaultnya dan simpan. -![](./grafana1.png) +![Tangkapan layar dasbor Grafana untuk pemantauan Geth (panel 1)](./grafana1.png) Anda akan diarahkan kembali ke halaman beranda Grafana. Pertama - tama, siapkan data sumber Anda. Klik pada ikon konfigurasi di bar kiri dan pilih "Sumber data". -![](./grafana2.png) +![Tangkapan layar dasbor Grafana untuk pemantauan Geth (panel 2)](./grafana2.png) Tidak ada sumber data mana pun yang dibuat, klik pada "Tambahkan sumber data" untuk menentukan satu sumber. -![](./grafana3.png) +![Tangkapan layar dasbor Grafana untuk pemantauan Geth (panel 3)](./grafana3.png) Untuk penyiapan ini, pilih "InfluxDB" dan lanjutkan. -![](./grafana4.png) +![Tangkapan layar dasbor Grafana untuk pemantauan Geth (panel 4)](./grafana4.png) Konfigurasi sumber data cukup mudah jika Anda menjalankan perangkat pada mesin yang sama. Anda perlu menyiapkan alamat dan detail InfluxDB untuk mengakses basis data. Lihat gambar di bawah. -![](./grafana5.png) +![Tangkapan layar dasbor Grafana untuk pemantauan Geth (panel 5)](./grafana5.png) Jika semuanya lengkap dan InfluxDB dapat dicapai, klik pada "Simpan dan uji" dan tunggu hingga konfirmasinya muncul. diff --git a/public/content/translations/id/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/translations/id/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index 55441fcb3ce..00000000000 --- a/public/content/translations/id/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1145 +0,0 @@ ---- -title: Menguji token ERC-20 dengan Waffle -description: Pelajari cara menguji kontrak pintar Solidity dan menggunakan matcher kontrak pintar dengan Waffle. -author: Vladislav Starostenko -tags: - - "waffle" - - "kontrak pintar" - - "solidity" - - "pengujian" - - "erc-20" -skill: intermediate -lang: id -published: 2020-10-16 ---- - -Pada tutorial ini, Anda akan belajar cara: - -- Menulis tes untuk kontrak pintar dengan Waffle -- Menggunakan beberapa matcher populer untuk menguji kontrak pintar dengan Waffle - -Asumsi: - -- Anda dapat menguasai penggunaan terminal, -- Anda dapat membuat proyek `JavaScript` baru, -- Anda telah menulis beberapa baris kode `Solidity`, -- Anda telah menulis beberapa tes dalam `JavaScript`, -- Anda telah menggunakan `yarn` atau `npm`, penginstal paket JavaScript. - -Sekali lagi, jika salah satu dari asumsi ini tidak benar, atau Anda tidak berencana untuk membuat kembali kode dalam artikel ini, Anda kemungkinan masih dapat mengikuti penjelasannya dengan baik. - -## Beberapa kata tentang Waffle {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io) adalah pustaka yang paling canggih untuk penulisan dan pengujian kontrak pintar. - -Berfungsi dengan [API JavaScript](/developers/docs/apis/javascript/) ethers-js. - -Anda dapat membaca detail selengkapnya di [dokumentasi Waffle](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation)! - -## Tutorial cepat {#the-quick-tutorial} - -Pertama-tama, buat proyek `JavaScript` atau `TypeScript` baru ( Saya akan menggunakan `TS`, tetapi jika Anda menggunakan `JS` itu tidak jadi masalah ) : - -Itu akan tampak seperti ini: - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## Langkah #1: Instal waffle dalam proyek Anda [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) {#step-1-install-waffle-in-your-project} - -Untuk memulai, instal `ethereum-waffle`. Dalam tutorial ini, saya akan menggunakan `yarn`, sehingga untuk menginstal `ethereum-waffle` jalankan: - -```bash - yarn add --dev ethereum-waffle -``` - -## Langkah #2: Tulis kontrak pintar [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract) {#step-2-write-a-smart-contract} - -Dalam tutorial ini, saya akan menggunakan token [ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol) dari [OpenZeppelin](https://openzeppelin.com). - -Jadi, tambahkan `OpenZeppelin` dengan menginstalnya dengan menggunakan `yarn`: - -```bash - yarn add @openzeppelin/contracts -D -``` - -Lalu buat kontrak `BasicToken.sol` di direktori `src`: - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Kelas percontohan - sebuah kelas tiruan yang menggunakan pengantaran dari ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## Langkah #3: Kompilasikan kontrak pintar Anda [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) {#step-3-compile-your-smart-contract} - -Untuk mengompilasi kontrak pintar Anda, tambahkan entri berikut ke dalam `package.json` proyek Anda: - -```json -{ - "scripts": { - "build": "waffle" - } -} -``` - -Selain itu, tambahkan file `waffle.json` dalam direktori utama proyek Anda. - -Contoh konfigurasi `waffle.json`: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Anda dapat membaca lebih banyak tentang konfigurasi Waffle [di sini](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration). - -Lalu cukup jalankan `yarn build` untuk mengompilasi kontrak pintar Anda. - -Anda akan melihat bahwa Waffle mengompilasi kontrak Anda dan menempatkan output JSON yang dihasilkan di dalam directori `build`. - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 P -``` -
- -## Langkah #4: Uji kontrak pintar Anda [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-test-your-smart-contract} - -### Langkah #4.1 Instal dependensi yang diperlukan [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-1} - -Setelah kita telah berhasil menulis sebuah Kontrak Pintar, kita dapat mengujinya. Kita akan menggunakan `Waffle` untuk melakukannya. - -Tes dalam `Waffle` ditulis dengan menggunakan `Mocha` bersama dengan `Chai`. Kita dapat menggunakan lingkungan pengujian berbeda, tetapi matcher `Waffle` hanya berfungsi dengan `Chai`. - -Jadi, kita perlu menambahkan `Chai` ke dependensi kita: - -```bash - yarn add --dev mocha chai -``` - -### Langkah #4.2 Buat file uji [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-2} - -Untuk menulis tes, kita perlu membuat file `BasicToken.test.ts` dalam direktori tes kita. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -Jadi, kita menggunakan metode `deployContract` dari `Waffle` untuk menyebarkan token kita. Sebagai argumen, kita harus meneruskan `dompet`, file json terkompilasi dari kontrak kita, dan saldo default. - -`Waffle` juga memungkinkan kita membuat `dompet`, yang sangat memudahkan dalam menyebarkan kontrak. - -Anda dapat membaca selengkapnya tentang `dompet` [di sini](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets) dan Anda dapat membaca selengkapnya tentang fungsi penggunaan [di sini](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts). - -Mari menulis sebuah tes sederhana untuk memeriksa saldo dompet kita. Karena kita mengirimkan senilai 1000 pada saat penggunaan kontrak, saldo dompet kita harus bernilai 1000 token, yang dapat kita periksa pada tes pertama. - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -Untuk menjalankan tes gunakan `yarn test` - -### Langkah #4.3 Memancarkan aksi [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events) {#step-4-3} - -Dalam tutorial ini, saya ingin menunjukkan kepada Anda matcher yang paling berguna dari `Waffle`, jadi mari kita mulai dengan yang pertama. - -`Waffle` memungkinkan Anda menguji aksi mana yang dipancarkan. - -Dalam tutorial ini, saya akan menguji metode `transfer` kontrak kita. - -Dalam tes ini, saya akan membuat sebuah transfer dari satu dompet ke dompet lainnya dan memeriksa apakah aksi `Transfer` dipanggil. - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -Selain itu, keunggulan besar dari matcher ini adalah kita dapat memeriksa di argumen mana aksi ini dipanggil dengan menambahkan `withArgs` ke dalam tes kita. - -Ini akan memungkinkan kita memastikan bahwa fungsi kita dipanggil dengan benar! - -### Langkah #4.4 Balikkan dengan message [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message) {#step-4-4} - -`Waffle` memungkinkan kita menguji dengan message mana itu dibalikkan. - -Kita akan menggunakan matcher `revertedWith` dalam tes kita untuk mengujinya. - -Kita dapat menulis sebuah tes yang dalamnya kita akan melakukan transfer dengan jumlah lebih besar dari yang kita miliki dalam dompet kita. Dan kemudian kita akan memeriksa apakah transaksinya dibalikkan dengan message yang tepat! - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### Langkah #4.5 Ubah saldo token [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance) {#step-4-5} - -`Waffle` memungkinkan kita memeriksa perubahan dalam saldo dompet! - -Kita dapat menggunakan matcher `changeTokenBalance` untuk memeriksa perubahan saldo atau `changeTokenBalances` untuk beberapa akun. - -Matcher dapat menerima `numbers`, `strings` dan `BigNumbers` sebagai perubahan saldo, sedangkan alamatnya akan ditentukan sebagai dompet atau kontrak. - -Mari menulis tes berikutnya: - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -Tes di atas merupakan tes untuk sebuah dompet tunggal. - -Dan yang berikut ini untuk beberapa dompet: - -```ts -it("Send transaction changes sender and receiver balances", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalances([wallet, walletTo], [-200, 200]) -}) -``` - -Transaksinya diharapkan untuk diteruskan sebagai callback (kita perlu memeriksa saldo sebeleum pemanggilan ini) atau sebagai respon transaksi. - -## Selamat {#congratulations} - -**Selamat! Anda telah menyelesaikan tutorial saya. Anda telah mengambil langkah besar pertama Anda dalam menguji kontrak pintar dengan Waffle.** - -**Kode dari tutorial ini dapat Anda temukan [di sini](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website).** - -**Lebih banyak dokumentasi tentang `Waffle` tersedia [di sini](https://getwaffle.io).** diff --git a/public/content/translations/id/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/id/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 653f0ca5d46..00000000000 --- a/public/content/translations/id/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,298 +0,0 @@ ---- -title: "Waffle: Mocking dinamis dan percobaan memanggil kontrak pintar" -description: Tutorial tingkat lanjut Waffle untuk menggunakan mocking dinamis dan percobaan memanggil kontrak -author: "Daniel Izdebski" -tags: - - "waffle" - - "kontrak pintar" - - "solidity" - - "pengujian" - - "mocking" -skill: intermediate -lang: id -published: 2020-11-14 ---- - -## Apa yang akan di pelajari pada tutorial ini? {#what-is-this-tutorial-about} - -Pada tutorial ini, Anda akan belajar cara: - -- menggunakan mocking dinamis -- menguji interaksi antara kontrak pintar - -Asumsi: - -- Anda telah mengetahui bagaimana cara menulis kontrak pintar sederhana dalam `Solidity` -- Anda terbiasa dengan `JavaScript` dan `TypeScript` -- Anda telah menyelesaikan tutorial `Waffle` lainnya atau mengetahui beberapa hal tentangnya - -## Mocking dinamis {#dynamic-mocking} - -Mengapa mocking dinamis sangat berguna? Baiklah, hal ini mengizinkan kita menulis tes unit ketimbang tes yang terintegrasi. Apa maksudnya? Hal ini berarti bahwa kita tidak perlu khawatir tentang dependensi kontrak pintar, sehingga kita bisa menguji semuanya secara terisolasi. Saya akan menunjukan bagaimana cara Anda melakukannya. - -### **1. Proyek** {#1-project} - -Sebelum memulai, kita perlu menyiapkan proyek node.js sederhana: - -```bash -$ mkdir dynamic-mocking -$ cd dynamic-mocking -$ mkdir contracts src - -$ yarn init -# or if you're using npm -$ npm init -``` - -Mari kita mulai dengan menambah typescript dan menguji dependensi - mocha dan chai: - -```bash -$ yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# atau jika anda menggunakan npm -$ npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Sekarang mari tambahkan `Waffle` dan `ether`: - -```bash -$ yarn add --dev ethereum-waffle ethers -# atau jika anda menggunakan npm -$ npm install ethereum-waffle ethers --save-dev -``` - -Struktur proyek Anda seharusnya terlihat seperti ini: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Kontrak pintar** {#2-smart-contract} - -Untuk memulai mocking dinamis, kita membutuhkan kontrak pintar dengan dependensi. Tenang, saya akan membantu! - -Berikut adalah kontrak pintar sederhana yang ditulis dalam `Solidity` yang tujuannya hanya memeriksa apakah kita kaya. Kontrak pintar ini menggunakan token ERC20 untuk memeriksa apakah kita memiliki token yang cukup. Letakan pada `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Karena kita mau menggunakan mocking dinamis, kita tidak memerlukan seluruh ERC20, itulah mengapa kita menggunakan antarmuka IERC20 dengan hanya satu fungsi. - -Saatnya membuat kontrak ini! Untuk itu, kita akan menggunakan `Waffle`. Pertama, kita akan membuat file konfigurasi `waffle.json` sederhana yang menentukan pilihan kompilasi. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Sekarang, kita sudah siap untuk membuat kontrak menggunakan Waffle: - -```bash -$ npx waffle -``` - -Mudah, bukan? Dalam folder `build/`, dua file sesuai dengan kontrak dan antar mukanya muncul. Kita akan menggunakannya nanti untuk percobaan. - -### **3. Pengujian** {#3-testing} - -Mari kita buat file bernama `AmIRichAlready.test.ts` untuk tes yang sebenarnya. Pertama, kita harus menangani hasil impor. Kita akan membutuhkannya nanti: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -Kecuali untuk dependensi JS, kita harus mengimpor kontrak dan antar muka yang kita bangun: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle menggunakan `chai` untuk pengujian. Namun, sebelum kita menggunakannya, kita harus menginjeksi matcher Waffle kedalam chai: - -```typescript -use(solidity) -``` - -Kita harus mengimplementasikan fungsi `beforeEach()` yang akan mengatur ulang state kontrak sebelum setiap tes dimulai. Pertama-tama mari kita pikirkan apa yang kita butuhkan untuk itu. Untuk menggunakan kontrak, kita membutuhkan dua hal: dompet dan kontrak ERC20 yang digunakan untuk meneruskannya sebagai argumen kontrak `AmIRichAlready`. - -Pertama, kita buat dompetnya: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Selanjutnya, kita harus menggunakan kontrak ERC20. Ini bagian sulitnya - kita hanya memiliki satu antarmuka. Di sinilah peran di mana Waffle datang menyelamatkan kita. Waffle memiliki fungsi `deployMockContract()` ajaib yang membuat kontrak dengan hanya menggunakan _abi_ dari antarmuka: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Sekarang dengan dompet maupun ERC20 yang digunakan, kita akan lanjutkan dan menggunakan kontrak `AmIRichAlready`: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -Secara keseluruhan, fungsi `beforeEach()` kita telah selesai. Sejauh ini file `AmIRichAlready.test.ts` Anda seharusnya telihat seperti ini: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Mari kita tulis tes pertama ke kontrak `AmIRichAlready`. Menurut Anda, tentang apa seharusnya tes kita? Ya, Anda benar! Kita harus memeriksa apakah kita sudah kaya :) - -Tapi tunggu dulu. Bagaimana kontrak mocked kita tahu nilai apa yang dikembalikan? Kita belum mengimplementasikan logika apa pun untuk fungsi `balanceOf()`. Sekali lagi, Waffle bisa membantu kita di sini. Kontrak mocked kita memiliki hal baru yang menarik sekarang: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -Dengan pengetahuan ini, akhirnya kita bisa menulis tes pertama kita: - -```typescript -it("returns false if the wallet has less than 1000000 tokens", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Mari kita pecahkan tes ini ke dalam bagian-bagian: - -1. Kita atur kontrak mock ERC20 kita untuk selalu mengembalikan saldo 999999 token. -2. Periksa apakah metode `contract.check()` mengembalikan nilai `false`. - -Kita siap untuk menyalakannya: - -![Satu ujian lulus](./test-one.png) - -Jadi testnya bekerja, namun... masih ada sedikit ruang untuk peningkatan. Fungsi `balanceOf()` akan selalu mengembalikan 99999. Kita bisa meningkatkannya dengan menentukan dompet yang ke mana fungsinya harus mengembalikan sesuatu - sama seperti kontrak sungguhan: - -```typescript -it("returns false if the wallet has less than 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Sejauh ini, kita hanya mencoba kasus di mana kita tidak cukup kaya. Mari kita coba kebalikannya: - -```typescript -it("returns true if the wallet has at least 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Anda jalankan tesnya... - -![Dua ujian lulus](test-two.png) - -....dan ini dia! Kontrak kita tampak berjalan sebagaimana mestinya :) - -## Menguji pemanggilan kontrak {#testing-contract-calls} - -Mari kita ringkas apa yang telah kita lakukan sejauh ini. Kita telah menguji fungsionalitas kontrak `AmIRichAlready` kita dan tampaknya bekerja dengan benar. Artinya, kita telah selesai, bukan? Belum selesai! Waffle memungkinkan kita menguji kontrak bahkan lebih jauh lagi. Tapi, bagaimana persisnya? Dalam gudang senjata Waffle, ada matcher `calledOnContract()` dan `calledOnContractWith()`. Mereka akan memungkinkan kita memeriksa apakah kontrak kita memanggil kontrak mock ERC20. Berikut adalah tes dasarnya dengan salah satu matcher ini: - -```typescript -it("checks if contract called balanceOf on the ERC20 token", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Kita bahkan bisa melangkah lebih jauh dan meningkatkan tes ini dengan matcher lain yang saya sebutkan sebelumnya: - -```typescript -it("checks if contract called balanceOf with certain wallet on the ERC20 token", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Mari kita periksa apakah tesnya benar: - -![Tiga ujian lulus](test-three.png) - -Hebat, semua test berwarna hijau. - -Menguji pemanggilan kontrak dengan Waffle sangatlah mudah. Dan inilah bagian terbaiknya. Matcher ini bekerja baik dalam kontrak normal dan mocked! Itu karena Waffle mencatat dan menyaring pemanggilan EVM ketimbang menginjeksi kode, seperti dalam kasus pustaka pengujian populer untuk teknologi lainnya. - -## Garis Akhir {#the-finish-line} - -Selamat! Sekarang Anda tahu cara menggunakan Waffle untuk menguji pemanggilan kontrak dan kontrak mock secara dinamis. Ada fitur yang jauh lebih menarik untuk ditemukan. Saya menyarankan menyelam ke dalam dokumentasi Waffle. - -Dokumentasi Waffle tersedia [di sini](https://ethereum-waffle.readthedocs.io/). - -Sumber kode untuk tutorial ini bisa ditemukan [di sini](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Tutorial yang mungkin juga Anda minati: - -- [Menguji kontrak pintar dengan Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/id/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/id/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 803f0a465a0..00000000000 --- a/public/content/translations/id/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: "Tutorial Waffle hello world menggunakan hardhat dan ether" -description: Buat proyek Waffle pertama Anda dengan hardhat dan ethers.js -author: "MiZiet" -tags: - - "waffle" - - "kontrak pintar" - - "solidity" - - "pengujian" - - "hardhat" - - "ethers.js" -skill: beginner -lang: id -published: 2020-10-16 ---- - -Dalam tutorial [Waffle](https://ethereum-waffle.readthedocs.io) ini, kita akan belajar cara menyiapkan proyek kontrak pintar "Hello world" yang sederhana, menggunakan [hardhat](https://hardhat.org/) dan [ethers.js](https://docs.ethers.io/v5/). Kemudian kita akan belajar cara menambahkan fungsionalitas baru ke kontrak pintar kita dan cara mengujinya dengan Waffle. - -Mari kita mulai dengan membuat proyek baru: - -```bash -yarn init -``` - -atau - -```bash -npm init -``` - -dan menginstal paket yang diperlukan: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -atau - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -Langkah selanjutnya adalah membuat proyek hardhat percontohan dengan menjalankan `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Selamat datang di HardHat v2.0.3 👷‍ - -? What do you want to do? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -Pilih `Buat proyek sampel` - -Struktur proyek kita seharusnya terlihat seperti ini: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributs -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Sekarang mari kita bicara tentang beberapa file ini: {#now-lets-talk} - -- Greeter.sol - kontrak pintar kita yang ditulis dalam solidity; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Kontrak pintar kita dapat dibagi menjadi tiga bagian: - -1. constructor - tempat kami mendeklarasikan variabel tipe string yang disebut `greeting`, -2. function greet - sebuah fungsi yang akan mengembalikan `greeting` saat dipanggil, -3. function setGreeting - fungsi yang memungkinkan kita mengubah nilai `greeting`. - -- sample-test.js - file tes kita - -```js -describe("Greeter", function () { - it("Should return the new greeting once it's changed", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### Langkah selanjutnya terdiri dari mengompilasi kontrak kita dan menjalankan pengujian: {#compiling-and-testing} - -Pengujian wafel menggunakan Mocha (kerangka pengujian) dengan Chai (pustaka assertion). Yang harus Anda lakukan adalah menjalankan `npx hardhat test` dan menunggu pesan berikut muncul. - -```bash -✓ Should return the new greeting once it's changed -``` - -### Semuanya terlihat bagus sejauh ini, mari tambahkan lebih banyak kerumitan pada proyek kita {#adding-complexity} - -Bayangkan suatu situasi ketika seseorang menambahkan string kosong sebagai salam. Ini bukan sapaan yang hangat, bukan? -Mari kita pastikan itu tidak terjadi: - -Kita ingin menggunakan `revert` solidity ketika seseorang melewati string kosong. Hal baiknya adalah kita bisa dengan mudah menguji fungsionalitas ini dengan `to.be.revertedWith ()` matcher chai Waffle. - -```js -it("Should revert when passing an empty string", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -Sepertinya tes baru kita tidak lulus: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -Mari kita terapkan fungsi ini ke dalam kontrak pintar kita: - -```solidity -require(bytes(_greeting).length > 0, "Salam tidak boleh kosong"); -``` - -Sekarang, fungsi setGreeting kita terlihat seperti ini: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Mari kita jalankan tes lagi: - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -Selamat! Anda berhasil :) - -### Kesimpulan {#conclusion} - -Kita membuat proyek sederhana dengan Waffle, Hardhat, dan eters.js. Kita mempelajari cara menyiapkan proyek, menambahkan pengujian, dan mengimplementasikan fungsionalitas baru. - -Untuk chai matcher yang lebih hebat untuk menguji kontrak pintar Anda, lihat [dokumen resmi Waffle](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/translations/it/community/support/faq/index.md b/public/content/translations/it/community/support/faq/index.md new file mode 100644 index 00000000000..aa2dab8d497 --- /dev/null +++ b/public/content/translations/it/community/support/faq/index.md @@ -0,0 +1,77 @@ +--- +title: Domande frequenti +description: Domande frequenti su Ethereum riguardo a portafogli, transazioni, staking e altro. +lang: it +--- + +# Domande frequenti {#faq} + +## Ho inviato criptovalute all'indirizzo sbagliato {#wrong-wallet} + +Una transazione inviata in Ethereum è irreversibile. Sfortunatamente, se hai inviato ETH o token al portafoglio sbagliato, non c'è modo di annullare la transazione. + +**Cosa puoi fare:** + +- **Se conosci il proprietario dell'indirizzo**, contattalo direttamente e chiedigli di restituirti i fondi +- **Se l'indirizzo appartiene a un exchange o a un servizio noto**, contatta il loro team di assistenza, poiché potrebbero essere in grado di aiutarti +- **Se hai inviato token a un indirizzo di contratto**, controlla se il contratto ha una funzione di prelievo o di recupero (è raro) + +Nella maggior parte dei casi, non c'è modo di recuperare i fondi. Nessuna organizzazione centrale, entità o persona possiede Ethereum, il che significa che nessuno può annullare le transazioni. Ricontrolla sempre l'indirizzo del destinatario prima di confermare. + +## Ho perso l'accesso al mio portafoglio {#lost-wallet-access} + +Le opzioni di recupero dipendono dal tipo di portafoglio che usi. + +### Se hai la tua frase seed (frase di recupero) + +Puoi ripristinare il tuo portafoglio in qualsiasi app portafoglio compatibile usando la tua frase seed. Per questo è fondamentale conservare la frase seed in un posto sicuro e offline. Consulta la documentazione del fornitore del tuo portafoglio per le istruzioni di ripristino. + +### Se hai perso la tua frase seed + +Senza la tua frase seed o le chiavi private, non è possibile recuperare i tuoi fondi. Nessuno, incluso ethereum.org, può reimpostare la tua password o ripristinare l'accesso a un portafoglio a custodia autonoma. + +### Se il tuo account si trova su un exchange + +Se il tuo account si trova su un exchange centralizzato come Coinbase, Binance o Kraken, contatta direttamente il team di assistenza dell'exchange. Essi controllano gli account sulla loro piattaforma e potrebbero essere in grado di aiutarti con la reimpostazione della password o il recupero dell'account. + + + + + + +**Non condividere mai la tua frase seed con nessuno** che affermi di aiutarti a recuperare il tuo portafoglio. Questa è una delle tattiche di truffa più comuni. Nessun servizio legittimo ti chiederà mai la tua frase seed. + + + + + + Come utilizzare un portafoglio + + +## La mia transazione è bloccata o in sospeso {#stuck-transaction} + +Le transazioni su Ethereum possono bloccarsi quando la commissione sul gas che hai impostato è inferiore a quella attualmente richiesta dalla rete. La maggior parte dei portafogli ti permette di risolvere il problema: + +- **Velocizza:** Invia di nuovo la stessa transazione con una commissione sul gas più alta +- **Annulla:** Invia una transazione da 0 ETH al tuo stesso indirizzo usando lo stesso nonce della transazione in sospeso + +### Guide utili + +- [Come velocizzare o annullare una transazione in sospeso su MetaMask](https://support.metamask.io/transactions-and-gas/transactions/how-to-speed-up-or-cancel-a-pending-transaction/) +- [Come annullare le transazioni Ethereum in sospeso](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) + +## Come posso rivendicare la mia ricompensa di Ethereum? {#giveaway-scam} + +I giveaway Ethereum sono truffe progettate per rubare il vostro ETH. Non lasciarti tentare da offerte che sembrano troppo belle per essere vere. Se invii ETH a un indirizzo per un giveaway, non riceverai alcun giveaway e non potrai recuperare i tuoi fondi. + +[Maggiori informazioni sulla prevenzione delle truffe](/security/#common-scams) + +## Come posso mettere in staking ETH? {#how-to-stake} + +Per diventare un validatore, devi mettere in staking 32 ETH nel contratto di deposito di Ethereum e configurare un nodo del validatore. Puoi anche partecipare con meno ETH tramite i pool di staking. + +Maggiori informazioni sono disponibili sulle nostre [pagine sullo staking](/staking/) e sul [launchpad per lo staking](https://launchpad.ethereum.org/). + +## Come posso fare mining su Ethereum? {#mining-ethereum} + +Il mining su Ethereum non è più possibile. Il mining è stato disattivato quando Ethereum è passata da [proof-of-work](/glossary/#pow) a [proof-of-stake](/glossary/#pos) durante [La Fusione](/roadmap/merge/) a settembre 2022. Ora, invece dei miner, Ethereum ha i validatori. Chiunque può mettere ETH in [staking](/glossary/#staking) e ricevere ricompense per l'esecuzione del software del validatore per proteggere la rete. diff --git a/public/content/translations/it/community/support/index.md b/public/content/translations/it/community/support/index.md deleted file mode 100644 index 4b99eccc80d..00000000000 --- a/public/content/translations/it/community/support/index.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Supporto Ethereum -description: Ottenere supporto nell'ecosistema Ethereum. -lang: it ---- - -# Supporto Ethereum {#support} - -## Supporto ufficiale di Ethereum {#official-support} - -Stai cercando il supporto ufficiale di Ethereum? La prima cosa che dovresti sapere è che Ethereum è decentralizzato. Questo significa che nessuna organizzazione centrale, entità o persona possiede Ethereum, e per questo non esistono canali di supporto ufficiali. - -Comprendere la natura decentralizzata di Ethereum è fondamentale perché **chiunque sostenga di essere il supporto ufficiale per Ethereum sta probabilmente provando a truffarti!** La migliore protezione contro i truffatori è informarsi e prendere sul serio la sicurezza. - - - Sicurezza di Ethereum e prevenzione delle truffe - - - - Impara i fondamenti di Ethereum - - -Nonostante la mancanza di supporto ufficiale, molti gruppi, community e progetti nell'intero ecosistema di Ethereum sono lieti di aiutare e puoi trovare molte informazioni e risorse utili su questa pagina. Hai altre domande? Unisciti al [Discord di ethereum.org](https://discord.gg/ethereum-org) e faremo il possibile per aiutarti. - -## Domande frequenti {#faq} - -### Ho inviato degli ETH al portafoglio sbagliato {#wrong-wallet} - -Una transazione inviata in Ethereum è irreversibile. Sfortunatamente, se hai inviato ETH al portafoglio sbagliato, non c'è modo di recuperare questi fondi. Nessuna organizzazione centrale, entità o persona possiede Ethereum, il che significa che nessuno può annullare le transazioni. Pertanto, è fondamentale ricontrollare sempre le tue transazioni prima di inviarle. - -### Come posso rivendicare la mia ricompensa di Ethereum? {#giveaway-scam} - -I giveaway Ethereum sono truffe progettate per rubare il vostro ETH. Non farti tentare da offerte che sembrano troppo belle per essere vere - se invii ETH a un indirizzo giveaway, non riceverai un giveaway e non potrai recuperare i tuoi fondi. - -[Maggiori informazioni sulla prevenzione delle truffe](/security/#common-scams) - -### La mia transazione è bloccata {#stuck-transaction} - -Le transazioni su Ethereum a volte possono bloccarsi se hai inviato una commissione sulle transazioni inferiore a quella richiesta per la domanda di rete. Molti portafogli prevedono un'opzione per reinviare la stessa transazione con una commissione sulle transazioni più elevata per consentire l'elaborazione. In alternativa, è possibile annullare una transazione in sospeso inviando una transazione al proprio indirizzo e utilizzando lo stesso nonce della transazione in sospeso. - -[Come velocizzare o annullare una transazione in sospeso su MetaMask](https://metamask.zendesk.com/hc/en-us/articles/360015489251-How-to-speed-up-or-cancel-a-pending-transaction) - -[Come annullare le transazioni Ethereum in sospeso](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) - -### Come posso fare mining su Ethereum? {#mining-ethereum} - -Il mining su Ethereum non è più possibile. Il mining è stato disattivato quando Ethereum è passato dal [proof-of-work](/glossary/#pow) al [proof-of-stake](/glossary/#pos). Ora, invece dei miner, Ethereum ha i validatori. Chiunque può mettere degli ETH in [staking](/glossary/#staking) e ricevere delle ricompense per l'esecuzione del software del validatore per proteggere la rete. - -### Come divento uno staker / eseguo un validatore? {#how-to-stake} - -Per diventare un validatore, devi mettere in staking 32 ETH nel contratto di deposito di Ethereum e configurare un nodo del validatore. Ulteriori informazioni sono disponibili sulle nostre [pagine di staking](/staking) e al [launchpad di staking](https://launchpad.ethereum.org/). - -## Costruire dapps {#building-support} - -La costruzione può essere difficile. Ecco alcuni spazi focalizzati sullo sviluppo, con sviluppatori Ethereum esperti che sono felici di aiutarti. - -- [Alchemy University](https://university.alchemy.com/#starter_code) -- [CryptoDevs discord](https://discord.com/invite/5W5tVb3) -- [StackExchange Ethereum](https://ethereum.stackexchange.com/) -- [Web3 University](https://www.web3.university/) -- [LearnWeb3](https://discord.com/invite/learnweb3) - -Puoi anche trovare la documentazione e le guide di sviluppo nella nostra sezione [risorse per sviluppatore Ethereum](/developers/). - -### Strumenti {#dapp-tooling} - -La tua domanda riguarda un particolare strumento, progetto o libreria? La maggior parte dei progetti hanno server di chat o forum dedicati al supporto. - -Ecco alcuni esempi più diffusi: - -- [Solidity](https://app.element.io/#/room/#solidity:matrix.org) -- [ethers.js](https://discord.gg/6jyGVDK6Jx) -- [web3.js](https://discord.gg/GsABYQu4sC) -- [Hardhat](https://discord.gg/xtrMGhmbfZ) -- [Alchemy](http://alchemy.com/discord) -- [Tenderly](https://discord.gg/fBvDJYR) - -## Eseguire un nodo {#node-support} - -Se stai eseguendo un nodo o un validatore, ecco alcune community che sono dedicate ad aiutarti ad iniziare. - -- [EthStaker discord](https://discord.gg/ethstaker) -- [EthStaker reddit](https://www.reddit.com/r/ethstaker) - -La maggior parte dei team che costruiscono client di Ethereum hanno anche spazi dedicati, rivolti al pubblico, dove è possibile ottenere supporto e fare domande. - -### Client di esecuzione {#execution-clients} - -- [Geth](https://discord.gg/FqDzupGyYf) -- [Nethermind](https://discord.gg/YJx3pm8z5C) -- [Besu](https://discord.gg/p8djYngzKN) -- [Erigon](https://github.com/ledgerwatch/erigon/issues) -- [Reth](https://github.com/paradigmxyz/reth/discussions) - -### Client di consenso {#consensus-clients} - -- [Prysm](https://discord.gg/prysmaticlabs) -- [Nimbus](https://discord.gg/nSmEH3qgFv) -- [Lighthouse](https://discord.gg/cyAszAh) -- [Teku](https://discord.gg/7hPv2T6) -- [Lodestar](https://discord.gg/aMxzVcr) -- [Grandine](https://discord.gg/H9XCdUSyZd) - -Puoi anche [imparare ad eseguire un nodo qui](/developers/docs/nodes-and-clients/run-a-node/). diff --git a/public/content/translations/it/community/support/misconceptions/index.md b/public/content/translations/it/community/support/misconceptions/index.md new file mode 100644 index 00000000000..6e3db16b267 --- /dev/null +++ b/public/content/translations/it/community/support/misconceptions/index.md @@ -0,0 +1,73 @@ +--- +title: Idee sbagliate comuni su Ethereum +description: "Chiarire le incomprensioni più comuni su come funziona Ethereum." +lang: it +--- + +# Idee sbagliate comuni su Ethereum {#misconceptions} + +## Ethereum è un'azienda? {#not-a-company} + +Ethereum è una tecnologia open-source e decentralizzata gestita da migliaia di collaboratori in tutto il mondo. Non esiste un'azienda chiamata "Ethereum" che gestisce i conti, detiene fondi o fornisce assistenza ai clienti. + +La [Ethereum Foundation](https://ethereum.foundation/) è un'organizzazione no-profit che supporta lo sviluppo di Ethereum, ma non possiede né controlla la rete. Nessuna singola entità lo fa. + +**[ethereum.org](/)** è una risorsa educativa gestita dalla comunità. Non è una piattaforma di scambio, un portafoglio o un'istituzione finanziaria. Non detiene fondi degli utenti e non può accedere ad alcun conto. + + + Cos'è Ethereum? + + +## Qualcuno può recuperare o congelare i miei fondi? {#no-fund-access} + +A differenza di una banca, non esiste un'autorità centrale su Ethereum che possa congelare, sequestrare o recuperare fondi. La persona che detiene le chiavi private (o la frase seed) ha il controllo pieno ed esclusivo su un portafoglio. + +Ciò significa che: + +- **Nessuno può recuperare i fondi** inviati all'indirizzo sbagliato +- **Nessuno può annullare** una transazione dopo che è stata confermata +- **Nessuno può congelare** il tuo portafoglio o bloccare le tue transazioni +- **Nessuno può reimpostare la tua password** se perdi la tua frase seed + +Ecco perché proteggere la tua frase seed è fondamentale. È l'unico modo per accedere al tuo portafoglio. Se viene persa o rubata, non c'è alcuna opzione di recupero. + + + Sicurezza di Ethereum e prevenzione delle truffe + + +## Posso ancora fare mining di Ethereum? {#no-mining} + +Ethereum è passato da [proof-of-work](/glossary/#pow) a [proof-of-stake](/glossary/#pos) durante [La Fusione](/roadmap/merge/) a settembre 2022. Il mining non è più possibile su Ethereum. + +La rete è ora messa in sicurezza dai validatori che mettono in [staking](/glossary/#staking) ETH. Chiunque può partecipare: + +- **Staking in solitaria:** Gestisci il tuo validatore con 32 ETH—[scopri di più](/staking/solo/) +- **Staking come servizio:** delega il funzionamento del nodo mantenendo le tue chiavi—[scopri di più](/staking/saas/) +- **Staking in pool:** metti in staking con meno di 32 ETH unendoti a un pool—[scopri di più](/staking/pools/) + + + Maggiori informazioni sullo staking + + +## Esiste un team di supporto di Ethereum? {#no-support-team} + +Cercare il "supporto ufficiale di Ethereum" è simile a cercare il "supporto ufficiale di internet". Questo, ovviamente, non esiste, ma a seconda del tuo problema potresti riuscire a cercare supporto dal tuo fornitore di servizi internet, dal produttore del tuo router o da una delle aziende dietro il dispositivo, l'app o il sito web che stai utilizzando. + +Ethereum è simile. Non esiste un'azienda, un team di supporto o un help desk dietro a Ethereum nel suo complesso, ma, a seconda del problema, potresti trovare aiuto contattando il tuo _fornitore del portafoglio_, _servizio di staking_, _piattaforma di scambio_, _istituto finanziario_ o il _team che gestisce un'app_ che stai utilizzando. + +Poiché Ethereum è pubblicamente trasparente per impostazione predefinita, potresti anche trovare [esploratori di blocchi](/developers/docs/data-and-analytics/block-explorers/), [strumenti di analisi](/developers/tools/analytics/) e altre [risorse di indagine online](/community/support/scams/#analyze) utili per esaminare direttamente un problema. + +Detto questo, nessuno di Ethereum o di ethereum.org potrà mai: + +- Contattarti tramite messaggio diretto +- Chiederti la tua frase seed o le tue chiavi private +- Chiederti di inviare ETH per verificare il tuo portafoglio +- Offrirti di aiutarti a recuperare fondi a pagamento + +**Chiunque faccia una di queste cose sta cercando di truffarti.** + +Se hai bisogno di aiuto, le vere comunità che possono assisterti sono elencate nella [pagina di supporto](/community/support/). Si tratta di comunità aperte e gestite da volontari—non di canali di supporto ufficiali. + + + Sicurezza di Ethereum e prevenzione delle truffe + diff --git a/public/content/translations/it/community/support/scams/index.md b/public/content/translations/it/community/support/scams/index.md new file mode 100644 index 00000000000..cd39ca851ec --- /dev/null +++ b/public/content/translations/it/community/support/scams/index.md @@ -0,0 +1,159 @@ +--- +title: Aiuto e segnalazione truffe +description: Cosa fare se sei stato truffato, come proteggere i tuoi beni rimanenti e dove segnalare la frode. +lang: it +--- + +# Sono stato truffato o ho perso fondi {#scam-help} + +Le truffe di criptovaluta prendono di mira persone di ogni livello di esperienza, inclusi i professionisti della finanza e della tecnologia. Non sei solo, ed essere qui è il primo passo giusto. + + + + + + +**Nessuno può annullare le transazioni blockchain.** Se qualcuno ti contatta sostenendo di poter recuperare i tuoi fondi a pagamento, è quasi certamente una seconda truffa. Vedi le [truffe di recupero](#recovery-scams) qui sotto. + + + + +## Proteggi i tuoi beni rimanenti {#secure-assets} + +Se hai interagito con un truffatore o sospetti che il tuo portafoglio sia compromesso, segui immediatamente questi passaggi: + +1. **Sposta i fondi rimanenti** in un nuovo portafoglio sicuro a cui il truffatore non ha accesso +2. **Revoca le approvazioni dei token.** I truffatori spesso ti inducono con l'inganno ad approvare una spesa illimitata di token. Revocare queste autorizzazioni impedisce un ulteriore svuotamento del tuo portafoglio +3. **Cambia le password** di tutti gli account di exchange che potrebbero essere collegati +4. **Abilita l'autenticazione a due fattori (2FA)** su tutti gli account relativi alle criptovalute + +### Come revocare le approvazioni dei token {#revoke-approvals} + +Quando interagisci con una dApp o un contratto intelligente, potresti avergli concesso il permesso di spendere i tuoi token. Se un truffatore ti ha ingannato per farti approvare un contratto dannoso, può continuare a sottrarre i tuoi token anche dopo la truffa iniziale. + +Usa questi strumenti per controllare e revocare le approvazioni: + +- [Revoke.cash](https://revoke.cash/): collega il tuo portafoglio per vedere tutte le approvazioni attive e revocarle +- [Revokescout](https://revoke.blockscout.com/): controlla e revoca le approvazioni tramite Blockscout +- [Verifica approvazione token di Etherscan](https://etherscan.io/tokenapprovalchecker): controlla e revoca le approvazioni tramite Etherscan + + + Guida dettagliata: come revocare l'accesso ai token + + +## Segnala indirizzi e siti web di truffe {#report} + +La segnalazione aiuta ad avvertire altri utenti e può assistere le indagini delle forze dell'ordine. Documenta tutto: hash delle transazioni, indirizzi dei portafogli, screenshot e qualsiasi comunicazione con il truffatore. + +### Segnala un indirizzo di truffa {#report-address} + +- [Chainabuse](https://www.chainabuse.com/): database di segnalazione di truffe e frodi gestito dalla comunità. Invia segnalazioni e cerca indirizzi di truffa noti +- [Segnalazione su Etherscan](https://info.etherscan.com/report-address/): segnala un indirizzo sull'esploratore di blocchi di Ethereum più utilizzato +- [CryptoScamDB](https://cryptoscamdb.org/): database open source che traccia le truffe di criptovaluta + +### Segnala un sito web o un account di social media fraudolento {#report-website} + +- [PhishTank](https://phishtank.org/): invia e verifica URL di phishing +- [Navigazione sicura di Google](https://safebrowsing.google.com/safebrowsing/report_phish/): segnala siti di phishing a Google in modo che vengano bloccati in Chrome e altri browser +- [Netcraft](https://report.netcraft.com/report/mistake): segnala siti web dannosi e fraudolenti +- Segnala direttamente sulla piattaforma di social media in cui è avvenuta la truffa (Twitter/X, Discord, Telegram hanno tutti funzioni di segnalazione) + +### Segnala alle forze dell'ordine {#report-law-enforcement} + +- **Stati Uniti:** [Centro reclami per crimini su Internet dell'FBI (IC3)](https://www.ic3.gov/) +- **Regno Unito:** [Action Fraud](https://www.actionfraud.police.uk/) +- **Unione Europea:** [Europol](https://www.europol.europa.eu/report-a-crime) +- **Altri paesi:** sporgi denuncia alla tua polizia locale. La frode di criptovaluta è un crimine nella maggior parte delle giurisdizioni + +## Analizza cosa è successo {#analyze} + +Capire dove sono finiti i tuoi fondi può aiutare con le segnalazioni e può supportare gli sforzi di recupero se i fondi arrivano su un exchange centralizzato. + +- [Blockscout](https://eth.blockscout.com/): esploratore di blocchi open source per cercare qualsiasi hash di transazione o indirizzo di portafoglio per vedere dove sono stati inviati i fondi +- [Etherscan](https://etherscan.io/): cerca qualsiasi hash di transazione o indirizzo di portafoglio per vedere dove sono stati inviati i fondi +- [Ricerca su Chainabuse](https://www.chainabuse.com/): controlla se un indirizzo è già stato segnalato da altre vittime +- [MetaSleuth](https://metasleuth.io/) di BlockSec: strumento di tracciamento visivo delle transazioni che mappa i flussi di fondi + +**Se i fondi sono stati inviati a un exchange centralizzato** (come Coinbase, Binance, Kraken), contatta immediatamente il loro team di supporto con i dettagli della transazione. Gli exchange a volte possono congelare gli account segnalati per frode. + +## La dura verità {#hard-truth} + +Poiché Ethereum è decentralizzato, nessuna autorità centrale può annullare le transazioni o recuperare i fondi rubati. Una volta che una transazione è confermata sulla blockchain, è definitiva. + +Segnalare è comunque utile. Le segnalazioni aiutano le forze dell'ordine a rintracciare le organizzazioni fraudolente e la segnalazione degli indirizzi su Chainabuse ed Etherscan avverte le future potenziali vittime. + +## Tipi di truffe a cui prestare attenzione {#scam-types} + + + +I truffatori creano falsi giveaway promettendo di moltiplicare i tuoi ETH o di darti token gratuiti. Spesso si spacciano per personaggi noti come Vitalik Buterin. Se invii ETH a un indirizzo "giveaway", non riceverai nulla in cambio. + +**Ricorda:** Vitalik e altre figure di spicco non ti chiederanno mai di inviare loro ETH. + +[Altre informazioni sulle truffe comuni](/security/#common-scams) + + + + +I truffatori si spacciano per membri del team di Ethereum, moderatori o agenti di supporto su Discord, Telegram e social media. Potrebbero inviarti messaggi diretti offrendo aiuto o sostenendo che c'è un problema con il tuo account. + +**Ricorda:** + +- Non esiste un "team di supporto di Ethereum" +- I veri moderatori non ti invieranno mai per primi un messaggio diretto +- Non condividere mai la tua frase seed o le tue chiavi private con nessuno, per nessun motivo +- Non fare mai clic sui link inviati in messaggi non richiesti + + + + +Le truffe di recupero si rivolgono specificamente a persone che hanno già perso fondi. I truffatori monitorano i social media alla ricerca di persone che parlano di essere state truffate, quindi le contattano spacciandosi per "investigatori blockchain" o "esperti di recupero di criptovalute". + +Promettono di rintracciare e recuperare le tue criptovalute rubate in cambio di una commissione anticipata. Dopo che paghi, scompaiono. + +**Nessun servizio legittimo può annullare le transazioni blockchain.** Chiunque lo prometta sta mentendo. Questa è una delle truffe successive più comuni. + + + + +I siti di phishing sembrano identici alle app di portafoglio, agli exchange o alle piattaforme DeFi reali. Ti ingannano per farti inserire la tua frase seed o collegare il tuo portafoglio, per poi prosciugare i tuoi fondi. + +**Proteggiti:** + +- Verifica sempre l'URL prima di collegare il tuo portafoglio +- Aggiungi ai preferiti i siti ufficiali che usi regolarmente +- Non inserire mai la tua frase seed su nessun sito web. Le app legittime non la chiedono mai +- Usa [PhishTank](https://phishtank.org/) per controllare gli URL sospetti + + + Come identificare i token truffa + + + + + Guida completa alla sicurezza di Ethereum e alla prevenzione delle truffe + diff --git a/public/content/translations/it/developers/docs/networking-layer/index.md b/public/content/translations/it/developers/docs/networking-layer/index.md index 96e1663933c..95bf3c901df 100644 --- a/public/content/translations/it/developers/docs/networking-layer/index.md +++ b/public/content/translations/it/developers/docs/networking-layer/index.md @@ -146,7 +146,7 @@ Un sommario del flusso di controllo è mostrato di seguito, con indicazione tra Una volta che il blocco è stato attestato da sufficienti validatori, è aggiunto alla testa della catena, giustificato e, infine, finalizzato. -![](cons_client_net_layer.png) ![](exe_client_net_layer.png) +![Diagramma del livello di rete del client di consenso di Ethereum](cons_client_net_layer.png) ![Diagramma del livello di rete del client di esecuzione di Ethereum](exe_client_net_layer.png) Schematica del livello di rete per i client del consenso e d'esecuzione, da [ethresear.ch](https://ethresear.ch/t/eth1-eth2-client-relationship/7248) diff --git a/public/content/translations/it/developers/docs/nodes-and-clients/node-architecture/index.md b/public/content/translations/it/developers/docs/nodes-and-clients/node-architecture/index.md index ea5ea28c192..e96348e52f7 100644 --- a/public/content/translations/it/developers/docs/nodes-and-clients/node-architecture/index.md +++ b/public/content/translations/it/developers/docs/nodes-and-clients/node-architecture/index.md @@ -10,7 +10,7 @@ Quando Ethereum utilizzava il [proof-of-work](/developers/docs/consensus-mechani Il diagramma seguente mostra la relazione tra i due client di Ethereum. I due client si connettono alle rispettive reti peer-to-peer (P2P). Sono necessarie reti P2P separate poiché i client di esecuzione eseguono il gossip delle transazioni sulla propria rete P2P, consentendo loro di gestire il proprio pool locale di transazione, mentre i client di consenso eseguono il gossip dei blocchi sulla propria rete P2P, consentendo la crescita del consenso e della catena. -![](node-architecture-text-background.png) +![Diagramma dell'architettura del nodo Ethereum che mostra i livelli di esecuzione e consenso](node-architecture-text-background.png) Perché questa struttura a due client funzioni, i client di consenso devono poter passare i pacchetti di transazioni al client di esecuzione. Eseguire le transazioni localmente è la modalità in cui il client convalida che le transazioni non violano alcuna regola di Ethereum e che l'aggiornamento proposto allo stato di Ethereum sia corretto. Similmente, quando il nodo è selezionato come produttore di un blocco, il client di consenso deve poter richiedere i pacchetti di transazioni da Geth da includere nel nuovo blocco ed eseguirli per aggiornare lo stato globale. Questa comunicazione tra client è gestita da una connessione RPC locale utilizzando l'[API del motore](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md). diff --git a/public/content/translations/it/developers/tutorials/ai-trading-agent/index.md b/public/content/translations/it/developers/tutorials/ai-trading-agent/index.md new file mode 100644 index 00000000000..44283b84a24 --- /dev/null +++ b/public/content/translations/it/developers/tutorials/ai-trading-agent/index.md @@ -0,0 +1,980 @@ +--- +title: Crea il tuo agente di trading IA su Ethereum +description: In questa guida imparerai a creare un semplice agente di trading IA. Questo agente legge le informazioni dalla blockchain, chiede una raccomandazione a un LLM in base a tali informazioni, esegue lo scambio consigliato dall'LLM, quindi attende e ripete. +author: Ori Pomerantz +tags: [ "IA", "trading", "agente", "python" ] +skill: intermediate +published: 2026-02-13 +lang: it +sidebarDepth: 3 +--- + +In questa guida imparerai a creare un semplice agente di trading IA. Questo agente funziona seguendo questi passaggi: + +1. Leggere i prezzi attuali e passati di un token, nonché altre informazioni potenzialmente pertinenti +2. Costruire una query con queste informazioni, insieme a informazioni di base per spiegare come potrebbero essere pertinenti +3. Inviare la query e ricevere in risposta un prezzo previsto +4. Effettuare uno scambio in base alla raccomandazione +5. Attendere e ripetere + +Questo agente dimostra come leggere le informazioni, tradurle in una query che fornisce una risposta utilizzabile e utilizzare tale risposta. Tutti questi sono passaggi richiesti per un agente IA. Questo agente è implementato in Python perché è il linguaggio più comune utilizzato nell'IA. + +## Perché farlo? {#why-do-this} + +Gli agenti di trading automatizzati consentono agli sviluppatori di selezionare ed eseguire una strategia di trading. Gli [agenti IA](/ai-agents) consentono strategie di trading più complesse e dinamiche, utilizzando potenzialmente informazioni e algoritmi che lo sviluppatore non ha nemmeno considerato di usare. + +## Gli strumenti {#tools} + +Questa guida utilizza [Python](https://www.python.org/), la [libreria Web3](https://web3py.readthedocs.io/en/stable/) e [Uniswap v3](https://github.com/Uniswap/v3-periphery) per quotazioni e trading. + +### Perché Python? {#python} + +Il linguaggio più utilizzato per l'IA è [Python](https://www.python.org/), quindi lo usiamo qui. Non ti preoccupare se non conosci Python. Il linguaggio è molto chiaro e spiegherò esattamente cosa fa. + +La [libreria Web3](https://web3py.readthedocs.io/en/stable/) è l'API Python di Ethereum più comune. È abbastanza facile da usare. + +### Trading sulla blockchain {#trading-on-blockchain} + +Ci sono [molti exchange decentralizzati (DEX)](/apps/categories/defi/) che ti permettono di scambiare token su Ethereum. Tuttavia, tendono ad avere tassi di cambio simili a causa dell'[arbitraggio](/developers/docs/smart-contracts/composability/#better-user-experience). + +[Uniswap](https://app.uniswap.org/) è un DEX ampiamente utilizzato che possiamo usare sia per le quotazioni (per vedere i valori relativi dei token) sia per gli scambi. + +### OpenAI {#openai} + +Per un modello linguistico di grandi dimensioni, ho scelto di iniziare con [OpenAI](https://openai.com/). Per eseguire l'applicazione in questa guida dovrai pagare per l'accesso all'API. Il pagamento minimo di 5$ è più che sufficiente. + +## Sviluppo, passo dopo passo {#step-by-step} + +Per semplificare lo sviluppo, procediamo per fasi. Ogni passaggio è un branch in GitHub. + +### Per iniziare {#getting-started} + +Ci sono passaggi per iniziare con UNIX o Linux (incluso [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)) + +1. Se non lo hai già, scarica e installa [Python](https://www.python.org/downloads/). + +2. Clona la repository di GitHub. + + ```sh + git clone https://github.com/qbzzt/260215-ai-agent.git -b 01-getting-started + cd 260215-ai-agent + ``` + +3. Installa [`uv`](https://docs.astral.sh/uv/getting-started/installation/). Il comando sul tuo sistema potrebbe essere diverso. + + ```sh + pipx install uv + ``` + +4. Scarica le librerie. + + ```sh + uv sync + ``` + +5. Attiva l'ambiente virtuale. + + ```sh + source .venv/bin/activate + ``` + +6. Per verificare che Python e Web3 funzionino correttamente, esegui `python3` e forniscigli questo programma. Puoi inserirlo al prompt `>>>`; non è necessario creare un file. + + ```python + from web3 import Web3 + MAINNET_URL = "https://eth.drpc.org" + w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) + w3.eth.block_number + quit() + ``` + +### Lettura dalla blockchain {#read-blockchain} + +Il passo successivo è leggere dalla blockchain. Per farlo, devi passare al branch `02-read-quote` e quindi usare `uv` per eseguire il programma. + +```sh +git checkout 02-read-quote +uv run agent.py +``` + +Dovresti ricevere un elenco di oggetti `Quote`, ognuno con un indicatore ora, un prezzo e l'asset (attualmente sempre `WETH/USDC`). + +Ecco una spiegazione riga per riga. + +```python +from web3 import Web3 +from web3.contract import Contract +from decimal import Decimal, ROUND_HALF_UP +from dataclasses import dataclass +from datetime import datetime, timezone +from pprint import pprint +import time +import functools +import sys +``` + +Importa le librerie di cui abbiamo bisogno. Sono spiegati di seguito quando vengono utilizzati. + +```python +print = functools.partial(print, flush=True) +``` + +Sostituisce il `print` di Python con una versione che svuota sempre l'output immediatamente. Questo è utile in uno script a lunga esecuzione perché non vogliamo attendere aggiornamenti di stato o output di debug. + +```python +MAINNET_URL = "https://eth.drpc.org" +``` + +Un URL per accedere alla Rete Principale. Puoi ottenerne uno da [Nodo come servizio](/developers/docs/nodes-and-clients/nodes-as-a-service/) o usare uno di quelli pubblicizzati in [Chainlist](https://chainlist.org/chain/1). + +```python +BLOCK_TIME_SECONDS = 12 +MINUTE_BLOCKS = int(60 / BLOCK_TIME_SECONDS) +HOUR_BLOCKS = MINUTE_BLOCKS * 60 +DAY_BLOCKS = HOUR_BLOCKS * 24 +``` + +Un blocco della Rete Principale di Ethereum si verifica in genere ogni dodici secondi, quindi questo è il numero di blocchi che ci aspetteremmo si verifichino in un periodo di tempo. Nota che questa non è una cifra esatta. Quando il [proponente del blocco](/developers/docs/consensus-mechanisms/pos/block-proposal/) non è attivo, quel blocco viene saltato e il tempo per il blocco successivo è di 24 secondi. Se volessimo ottenere il blocco esatto per un indicatore ora, useremmo la [ricerca binaria](https://en.wikipedia.org/wiki/Binary_search). Tuttavia, questo è sufficientemente vicino per i nostri scopi. Prevedere il futuro non è una scienza esatta. + +```python +CYCLE_BLOCKS = DAY_BLOCKS +``` + +La dimensione del ciclo. Esaminiamo le quotazioni una volta per ciclo e proviamo a stimare il valore alla fine del ciclo successivo. + +```python +# L'indirizzo del gruppo che stiamo leggendo +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +``` + +I valori delle quotazioni sono presi dal gruppo USDC/WETH di Uniswap 3 all'indirizzo [`0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`](https://eth.blockscout.com/address/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640?tab=read_write_contract). Questo indirizzo è già in formato checksum, ma è meglio usare [`Web3.to_checksum_address`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_checksum_address) per rendere il codice riutilizzabile. + +```python +POOL_ABI = [ + { "name": "slot0", ... }, + { "name": "token0", ... }, + { "name": "token1", ... }, +] + +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... } +] +``` + +Queste sono le [ABI](https://docs.soliditylang.org/en/latest/abi-spec.html) per i due contratti che dobbiamo contattare. Per mantenere il codice conciso, includiamo solo le funzioni che dobbiamo chiamare. + +```python +w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) +``` + +Inizializza la libreria [`Web3`](https://web3py.readthedocs.io/en/stable/quickstart.html#remote-providers) e connettiti a un nodo Ethereum. + +```python +@dataclass(frozen=True) +class ERC20Token: + address: str + symbol: str + decimals: int + contract: Contract +``` + +Questo è un modo per creare una classe di dati in Python. Il tipo di dati [`Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) viene utilizzato per connettersi al contratto. Nota il `(frozen=True)`. In Python i [booleani](https://en.wikipedia.org/wiki/Boolean_data_type) sono definiti come `True` o `False`, con la lettera maiuscola. Questa classe di dati è `frozen`, il che significa che i campi non possono essere modificati. + +Nota l'indentazione. A differenza dei [linguaggi derivati dal C](https://en.wikipedia.org/wiki/List_of_C-family_programming_languages), Python usa l'indentazione per denotare i blocchi. L'interprete Python sa che la seguente definizione non fa parte di questa classe di dati perché non inizia con la stessa indentazione dei campi della classe di dati. + +```python +@dataclass(frozen=True) +class PoolInfo: + address: str + token0: ERC20Token + token1: ERC20Token + contract: Contract + asset: str + decimal_factor: Decimal = 1 +``` + +Il tipo [`Decimal`](https://docs.python.org/3/library/decimal.html) viene utilizzato per gestire accuratamente le frazioni decimali. + +```python + def get_price(self, block: int) -> Decimal: +``` + +Questo è il modo per definire una funzione in Python. La definizione è indentata per mostrare che fa ancora parte di `PoolInfo`. + +In una funzione che fa parte di una classe di dati il primo parametro è sempre `self`, l'istanza della classe di dati che ha chiamato qui. Qui c'è un altro parametro, il numero del blocco. + +```python + assert block <= w3.eth.block_number, "Il blocco è nel futuro" +``` + +Se potessimo leggere il futuro, non avremmo bisogno dell'IA per il trading. + +```python + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) +``` + +La sintassi per chiamare una funzione sulla EVM da Web3 è questa: `.functions.().call()`. I parametri possono essere i parametri della funzione EVM (se presenti; qui non ce ne sono) o [parametri nominativi](https://en.wikipedia.org/wiki/Named_parameter) per modificare il comportamento della blockchain. Qui ne usiamo uno, `block_identifier`, per specificare [il numero del blocco](/developers/docs/apis/json-rpc/#default-block) in cui desideriamo eseguire. + +Il risultato è [questa struct, in forma di array](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol#L56-L72). Il primo valore è una funzione del tasso di cambio tra i due token. + +```python + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 +``` + +Per ridurre i calcoli sulla catena, Uniswap v3 non memorizza il fattore di cambio effettivo ma la sua radice quadrata. Poiché l'EVM non supporta la matematica in virgola mobile o le frazioni, invece del valore effettivo, la risposta è price296 + +```python + # (token1 per token0) + return 1/(raw_price * self.decimal_factor) +``` + +Il prezzo grezzo che otteniamo è il numero di `token0` che otteniamo per ogni `token1`. Nel nostro gruppo `token0` è USDC (stablecoin con lo stesso valore di un dollaro USA) e `token1` è [WETH](https://opensea.io/learn/blockchain/what-is-weth). Il valore che vogliamo veramente è il numero di dollari per WETH, non l'inverso. + +Il fattore decimale è il rapporto tra i [fattori decimali](https://docs.openzeppelin.com/contracts/4.x/erc20#a-note-on-decimals) per i due token. + +```python +@dataclass(frozen=True) +class Quote: + timestamp: str + price: Decimal + asset: str +``` + +Questa classe di dati rappresenta una quotazione: il prezzo di un asset specifico in un dato momento. A questo punto, il campo `asset` è irrilevante perché usiamo un singolo gruppo e quindi abbiamo un singolo asset. Tuttavia, aggiungeremo altri asset in seguito. + +```python +def read_token(address: str) -> ERC20Token: + token = w3.eth.contract(address=address, abi=ERC20_ABI) + symbol = token.functions.symbol().call() + decimals = token.functions.decimals().call() + + return ERC20Token( + address=address, + symbol=symbol, + decimals=decimals, + contract=token + ) +``` + +Questa funzione accetta un indirizzo e restituisce informazioni sul contratto del token a quell'indirizzo. Per creare un nuovo [`Contract` Web3](https://web3py.readthedocs.io/en/stable/web3.contract.html), forniamo l'indirizzo e l'ABI a `w3.eth.contract`. + +```python +def read_pool(address: str) -> PoolInfo: + pool_contract = w3.eth.contract(address=address, abi=POOL_ABI) + token0Address = pool_contract.functions.token0().call() + token1Address = pool_contract.functions.token1().call() + token0 = read_token(token0Address) + token1 = read_token(token1Address) + + return PoolInfo( + address=address, + asset=f"{token1.symbol}/{token0.symbol}", + token0=token0, + token1=token1, + contract=pool_contract, + decimal_factor=Decimal(10) ** Decimal(token0.decimals - token1.decimals) + ) +``` + +Questa funzione restituisce tutto ciò di cui abbiamo bisogno su [un gruppo specifico](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol). La sintassi `f""` è una [stringa formattata](https://docs.python.org/3/reference/lexical_analysis.html#f-strings). + +```python +def get_quote(pool: PoolInfo, block_number: int = None) -> Quote: +``` + +Ottieni un oggetto `Quote`. Il valore predefinito per `block_number` è `None` (nessun valore). + +```python + if block_number is None: + block_number = w3.eth.block_number +``` + +Se non è stato specificato un numero di blocco, usa `w3.eth.block_number`, che è l'ultimo numero di blocco. Questa è la sintassi per [un'istruzione `if`](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement). + +Potrebbe sembrare che sarebbe stato meglio impostare semplicemente il valore predefinito su `w3.eth.block_number`, ma non funziona bene perché sarebbe il numero di blocco al momento della definizione della funzione. In un agente a lunga esecuzione, questo sarebbe un problema. + +```python + block = w3.eth.get_block(block_number) + price = pool.get_price(block_number) + return Quote( + timestamp=datetime.fromtimestamp(block.timestamp, timezone.utc).isoformat(), + price=price.quantize(Decimal("0.01")), + asset=pool.asset + ) +``` + +Usa [la libreria `datetime`](https://docs.python.org/3/library/datetime.html) per formattarlo in un formato leggibile per gli esseri umani e per i modelli linguistici di grandi dimensioni (LLM). Usa [`Decimal.quantize`](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) per arrotondare il valore a due cifre decimali. + +```python +def get_quotes(pool: PoolInfo, start_block: int, end_block: int, step: int) -> list[Quote]: +``` + +In Python si definisce un [elenco](https://docs.python.org/3/library/stdtypes.html#typesseq-list) che può contenere solo un tipo specifico usando `list[]`. + +```python + quotes = [] + for block in range(start_block, end_block + 1, step): +``` + +In Python un [`ciclo `for``](https://docs.python.org/3/tutorial/controlflow.html#for-statements) di solito itera su un elenco. L'elenco di numeri di blocco in cui trovare le quotazioni proviene da [`range`](https://docs.python.org/3/library/stdtypes.html#range). + +```python + quote = get_quote(pool, block) + quotes.append(quote) + return quotes +``` + +Per ogni numero di blocco, ottieni un oggetto `Quote` e aggiungilo all'elenco `quotes`. Quindi restituisci quell'elenco. + +```python +pool = read_pool(WETHUSDC_ADDRESS) +quotes = get_quotes( + pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) + +pprint(quotes) +``` + +Questo è il codice principale dello script. Leggi le informazioni del gruppo, ottieni dodici quotazioni e visualizzale con [`pprint`](https://docs.python.org/3/library/pprint.html#pprint.pprint). + +### Creazione di un prompt {#prompt} + +Successivamente, dobbiamo convertire questo elenco di quotazioni in un prompt per un LLM e ottenere un valore futuro atteso. + +```sh +git checkout 03-create-prompt +uv run agent.py +``` + +L'output ora sarà un prompt per un LLM, simile a: + +``` +Date queste quotazioni: +Asset: WETH/USDC + 2026-01-20T16:34 3016.21 + . + . + . + 2026-02-01T17:49 2299.10 + +Asset: WBTC/WETH + 2026-01-20T16:34 29.84 + . + . + . + 2026-02-01T17:50 33.46 + + +Quale valore ti aspetteresti per WETH/USDC all'ora 2026-02-02T17:56? + +Fornisci la tua risposta come un singolo numero arrotondato a due cifre decimali, +senza alcun altro testo. +``` + +Nota che qui ci sono quotazioni per due asset, `WETH/USDC` e `WBTC/WETH`. L'aggiunta di quotazioni da un altro asset potrebbe migliorare l'accuratezza della previsione. + +#### Come appare un prompt {#prompt-explanation} + +Questo prompt contiene tre sezioni, che sono abbastanza comuni nei prompt LLM. + +1. Informazioni. Gli LLM hanno molte informazioni dal loro addestramento, ma di solito non hanno le più recenti. Questo è il motivo per cui dobbiamo recuperare le ultime quotazioni qui. L'aggiunta di informazioni a un prompt è chiamata [generazione aumentata dal recupero (RAG)](https://en.wikipedia.org/wiki/Retrieval-augmented_generation). + +2. La domanda vera e propria. Questo è ciò che vogliamo sapere. + +3. Istruzioni per la formattazione dell'output. Normalmente, un LLM ci darà una stima con una spiegazione di come ci è arrivato. Questo è meglio per gli esseri umani, ma un programma per computer ha solo bisogno del risultato finale. + +#### Spiegazione del codice {#prompt-code} + +Ecco il nuovo codice. + +```python +from datetime import datetime, timezone, timedelta +``` + +Dobbiamo fornire all'LLM l'ora per la quale vogliamo una stima. Per ottenere un'ora "n minuti/ore/giorni" nel futuro, usiamo [la classe `timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta). + +```python +# Gli indirizzi dei gruppi che stiamo leggendo +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +WETHWBTC_ADDRESS = Web3.to_checksum_address("0xCBCdF9626bC03E24f779434178A73a0B4bad62eD") +``` + +Abbiamo due gruppi che dobbiamo leggere. + +```python +@dataclass(frozen=True) +class PoolInfo: + . + . + . + reverse: bool = False + + def get_price(self, block: int) -> Decimal: + assert block <= w3.eth.block_number, "Il blocco è nel futuro" + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 # (token1 per token0) + if self.reverse: + return 1/(raw_price * self.decimal_factor) + else: + return raw_price * self.decimal_factor +``` + +Nel gruppo WETH/USDC, vogliamo sapere quanti `token0` (USDC) ci servono per acquistare un `token1` (WETH). Nel gruppo WETH/WBTC, vogliamo sapere quanti `token1` (WETH) ci servono per acquistare un `token0` (WBTC, che è Bitcoin wrappato). Dobbiamo tenere traccia se il rapporto del gruppo deve essere invertito. + +```python +def read_pool(address: str, reverse: bool = False) -> PoolInfo: + . + . + . + + return PoolInfo( + . + . + . + + asset= f"{token1.symbol}/{token0.symbol}" if reverse else f"{token0.symbol}/{token1.symbol}", + reverse=reverse + ) +``` + +Per sapere se un gruppo deve essere invertito, dobbiamo ottenerlo come input per `read_pool`. Inoltre, il simbolo dell'asset deve essere impostato correttamente. + +La sintassi `
if else ` è l'equivalente Python dell'[operatore condizionale ternario](https://en.wikipedia.org/wiki/Ternary_conditional_operator), che in un linguaggio derivato dal C sarebbe ` ? : `. + +```python +def format_quotes(quotes: list[Quote]) -> str: + result = f"Asset: {quotes[0].asset}\n" + for quote in quotes: + result += f"\t{quote.timestamp[0:16]} {quote.price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)}\n" + return result +``` + +Questa funzione costruisce una stringa che formatta un elenco di oggetti `Quote`, assumendo che si applichino tutti allo stesso asset. + +```python +def make_prompt(quotes: list[list[Quote]], expected_time: str, asset: str) -> str: + return f""" +``` + +In Python le [stringhe letterali multiriga](https://www.w3schools.com/python/gloss_python_multi_line_strings.asp) sono scritte come `"""` .... `"""`. + +```python +Date queste quotazioni: +{ + functools.reduce(lambda acc, q: acc + '\n' + q, + map(lambda q: format_quotes(q), quotes)) +} +``` + +Qui usiamo il modello [MapReduce](https://en.wikipedia.org/wiki/MapReduce) per generare una stringa per ogni elenco di quotazioni con `format_quotes`, quindi li riduciamo in una singola stringa da usare nel prompt. + +```python +Quale valore ti aspetteresti per {asset} all'ora {expected_time}? + +Fornisci la tua risposta come un singolo numero arrotondato a due cifre decimali, +senza alcun altro testo. + """ +``` + +Il resto del prompt è come previsto. + +```python +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +Esamina i due gruppi e ottieni quotazioni da entrambi. + +```python +future_time = (datetime.now(timezone.utc) + timedelta(days=1)).isoformat()[0:16] + +print(make_prompt(wethusdc_quotes + wethwbtc_quotes, future_time, wethusdc_pool.asset)) +``` + +Determina il momento futuro per il quale vogliamo la stima e crea il prompt. + +### Interfacciarsi con un LLM {#interface-llm} + +Successivamente, inviamo un prompt a un LLM effettivo e riceviamo un valore futuro atteso. Ho scritto questo programma usando OpenAI, quindi se vuoi usare un fornitore diverso, dovrai adattarlo. + +1. Ottieni un [conto OpenAI](https://auth.openai.com/create-account) + +2. [Ricarica il conto](https://platform.openai.com/settings/organization/billing/overview)—l'importo minimo al momento della scrittura è di 5$ + +3. [Crea una chiave API](https://platform.openai.com/settings/organization/api-keys) + +4. Nella riga di comando, esporta la chiave API in modo che il tuo programma possa usarla + + ```sh + export OPENAI_API_KEY=sk- + ``` + +5. Fai il checkout ed esegui l'agente + + ```sh + git checkout 04-interface-llm + uv run agent.py + ``` + +Ecco il nuovo codice. + +```python +from openai import OpenAI + +open_ai = OpenAI() # Il client legge la variabile d'ambiente OPENAI_API_KEY +``` + +Importa e istanzia l'API di OpenAI. + +```python +response = open_ai.chat.completions.create( + model="gpt-4-turbo", + messages=[ + {"role": "user", "content": prompt} + ], + temperature=0.0, + max_tokens=16, +) +``` + +Chiama l'API di OpenAI (`open_ai.chat.completions.create`) per creare la risposta. + +```python +expected_price = Decimal(response.choices[0].message.content.strip()) +current_price = wethusdc_quotes[-1].price + +print ("Prezzo attuale:", wethusdc_quotes[-1].price) +print(f"In {future_time}, prezzo previsto: {expected_price} USD") + +if (expected_price > current_price): + print(f"Compra, mi aspetto che il prezzo salga di {expected_price - current_price} USD") +else: + print(f"Vendi, mi aspetto che il prezzo scenda di {current_price - expected_price} USD") +``` + +Mostra il prezzo e fornisci una raccomandazione di acquisto o vendita. + +#### Testare le previsioni {#testing-the-predictions} + +Ora che possiamo generare previsioni, possiamo anche utilizzare dati storici per valutare se produciamo previsioni utili. + +```sh +uv run test-predictor.py +``` + +Il risultato atteso è simile a: + +``` +Previsione per 2026-01-05T19:50: previsto 3138.93 USD, reale 3218.92 USD, errore 79.99 USD +Previsione per 2026-01-06T19:56: previsto 3243.39 USD, reale 3221.08 USD, errore 22.31 USD +Previsione per 2026-01-07T20:02: previsto 3223.24 USD, reale 3146.89 USD, errore 76.35 USD +Previsione per 2026-01-08T20:11: previsto 3150.47 USD, reale 3092.04 USD, errore 58.43 USD +. +. +. +Previsione per 2026-01-31T22:33: previsto 2637.73 USD, reale 2417.77 USD, errore 219.96 USD +Previsione per 2026-02-01T22:41: previsto 2381.70 USD, reale 2318.84 USD, errore 62.86 USD +Previsione per 2026-02-02T22:49: previsto 2234.91 USD, reale 2349.28 USD, errore 114.37 USD +Errore medio di previsione su 29 previsioni: 83.87103448275862068965517241 USD +Variazione media per raccomandazione: 4.787931034482758620689655172 USD +Varianza standard delle variazioni: 104.42 USD +Giorni redditizi: 51.72% +Giorni in perdita: 48.28% +``` + +La maggior parte del tester è identica all'agente, ma ecco le parti nuove o modificate. + +```python +CYCLES_FOR_TEST = 40 # Per il backtest, quanti cicli testiamo + +# Ottieni molte quotazioni +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +Guardiamo indietro di `CYCLES_FOR_TEST` (specificato come 40 qui) giorni. + +```python +# Crea previsioni e confrontale con la cronologia reale + +total_error = Decimal(0) +changes = [] +``` + +Ci sono due tipi di errori che ci interessano. Il primo, `total_error`, è semplicemente la somma degli errori commessi dal predittore. + +Per capire il secondo, `changes`, dobbiamo ricordare lo scopo dell'agente. Non è prevedere il rapporto WETH/USDC (prezzo di ETH). È emettere raccomandazioni di vendita e acquisto. Se il prezzo è attualmente di 2000 $ e prevede 2010 $ domani, non ci importa se il risultato effettivo è 2020 $ e guadagniamo soldi extra. Ma ci importa se ha previsto 2010 $, e ha comprato ETH sulla base di quella raccomandazione, e il prezzo scende a 1990 $. + +```python +for index in range(0,len(wethusdc_quotes)-CYCLES_BACK): +``` + +Possiamo esaminare solo i casi in cui la cronologia completa (i valori utilizzati per la previsione e il valore del mondo reale con cui confrontarla) è disponibile. Ciò significa che il caso più recente deve essere quello iniziato `CYCLES_BACK` fa. + +```python + wethusdc_slice = wethusdc_quotes[index:index+CYCLES_BACK] + wethwbtc_slice = wethwbtc_quotes[index:index+CYCLES_BACK] +``` + +Usa le [slice](https://www.w3schools.com/python/ref_func_slice.asp) per ottenere lo stesso numero di campioni utilizzato dall'agente. Il codice tra qui e il segmento successivo è lo stesso codice per ottenere una previsione che abbiamo nell'agente. + +```python + predicted_price = Decimal(response.choices[0].message.content.strip()) + real_price = wethusdc_quotes[index+CYCLES_BACK].price + prediction_time_price = wethusdc_quotes[index+CYCLES_BACK-1].price +``` + +Ottieni il prezzo previsto, il prezzo reale e il prezzo al momento della previsione. Abbiamo bisogno del prezzo al momento della previsione per determinare se la raccomandazione era di comprare o vendere. + +```python + error = abs(predicted_price - real_price) + total_error += error + print (f"Previsione per {prediction_time}: previsto {predicted_price} USD, reale {real_price} USD, errore {error} USD") +``` + +Calcola l'errore e aggiungilo al totale. + +```python + recomended_action = 'buy' if predicted_price > prediction_time_price else 'sell' + price_increase = real_price - prediction_time_price + changes.append(price_increase if recomended_action == 'buy' else -price_increase) +``` + +Per `changes`, vogliamo l'impatto monetario dell'acquisto o della vendita di un ETH. Quindi, prima dobbiamo determinare la raccomandazione, poi valutare come è cambiato il prezzo effettivo e se la raccomandazione ha prodotto un guadagno (variazione positiva) o una perdita (variazione negativa). + +```python +print (f"Errore medio di previsione su {len(wethusdc_quotes)-CYCLES_BACK} previsioni: {total_error / Decimal(len(wethusdc_quotes)-CYCLES_BACK)} USD") + +length_changes = Decimal(len(changes)) +mean_change = sum(changes, Decimal(0)) / length_changes +print (f"Variazione media per raccomandazione: {mean_change} USD") +var = sum((x - mean_change) ** 2 for x in changes) / length_changes +print (f"Varianza standard delle variazioni: {var.sqrt().quantize(Decimal("0.01"))} USD") +``` + +Riporta i risultati. + +```python +print (f"Giorni redditizi: {len(list(filter(lambda x: x > 0, changes)))/length_changes:.2%}") +print (f"Giorni in perdita: {len(list(filter(lambda x: x < 0, changes)))/length_changes:.2%}") +``` + +Usa [`filter`](https://www.w3schools.com/python/ref_func_filter.asp) per contare il numero di giorni redditizi e il numero di giorni costosi. Il risultato è un oggetto filtro, che dobbiamo convertire in un elenco per ottenerne la lunghezza. + +### Invio di transazioni {#submit-txn} + +Ora dobbiamo effettivamente inviare le transazioni. Tuttavia, non voglio spendere soldi veri a questo punto, prima che il sistema sia collaudato. Invece, creeremo una biforcazione locale della Rete Principale e faremo "trading" su quella rete. + +Ecco i passaggi per creare una biforcazione locale e abilitare il trading. + +1. Installa [Foundry](https://getfoundry.sh/introduction/installation) + +2. Avvia [`anvil`](https://getfoundry.sh/anvil/overview) + + ```sh + anvil --fork-url https://eth.drpc.org --block-time 12 + ``` + + `anvil` è in ascolto sull'URL predefinito per Foundry, http://localhost:8545, quindi non è necessario specificare l'URL per [il comando `cast`](https://getfoundry.sh/cast/overview) che usiamo per manipolare la blockchain. + +3. Quando si esegue in `anvil`, ci sono dieci conti di prova che hanno ETH: imposta le variabili d'ambiente per il primo + + ```sh + PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ADDRESS=`cast wallet address $PRIVATE_KEY` + ``` + +4. Questi sono i contratti che dobbiamo usare. [`SwapRouter`](https://github.com/Uniswap/v3-periphery/blob/main/contracts/SwapRouter.sol) è il contratto di Uniswap v3 che usiamo per fare trading. Potremmo fare trading direttamente attraverso il gruppo, ma questo è molto più facile. + + Le due variabili in basso sono i percorsi di Uniswap v3 necessari per scambiare tra WETH e USDC. + + ```sh + WETH_ADDRESS=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + USDC_ADDRESS=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + POOL_ADDRESS=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 + SWAP_ROUTER=0xE592427A0AEce92De3Edee1F18E0157C05861564 + WETH_TO_USDC=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + USDC_TO_WETH=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + ``` + +5. Ognuno dei conti di prova ha 10.000 ETH. Usa il contratto WETH per wrappare 1000 ETH per ottenere 1000 WETH per il trading. + + ```sh + cast send $WETH_ADDRESS "deposit()" --value 1000ether --private-key $PRIVATE_KEY + ``` + +6. Usa `SwapRouter` per scambiare 500 WETH con USDC. + + ```sh + cast send $WETH_ADDRESS "approve(address,uint256)" $SWAP_ROUTER 500ether --private-key $PRIVATE_KEY + MAXINT=`cast max-int uint256` + cast send $SWAP_ROUTER \ + "exactInput((bytes,address,uint256,uint256,uint256))" \ + "($WETH_TO_USDC,$ADDRESS,$MAXINT,500ether,1000000)" \ + --private-key $PRIVATE_KEY + ``` + + La chiamata `approve` crea un'autorizzazione che consente a `SwapRouter` di spendere alcuni dei nostri token. I contratti non possono monitorare gli eventi, quindi se trasferiamo i token direttamente al contratto `SwapRouter`, questo non saprebbe di essere stato pagato. Invece, permettiamo al contratto `SwapRouter` di spendere un certo importo, e poi `SwapRouter` lo fa. Questo viene fatto tramite una funzione chiamata da `SwapRouter`, quindi sa se ha avuto successo. + +7. Verifica di avere abbastanza di entrambi i token. + + ```sh + cast call $WETH_ADDRESS "balanceOf(address)" $ADDRESS | cast from-wei + echo `cast call $USDC_ADDRESS "balanceOf(address)" $ADDRESS | cast to-dec`/10^6 | bc + ``` + +Ora che abbiamo WETH e USDC, possiamo effettivamente eseguire l'agente. + +```sh +git checkout 05-trade +uv run agent.py +``` + +L'output sarà simile a: + +``` +(ai-trading-agent) qbzzt@Ori-Cloudnomics:~/260215-ai-agent$ uv run agent.py +Prezzo attuale: 1843.16 +In 2026-02-06T23:07, prezzo previsto: 1724.41 USD +Saldi del conto prima dello scambio: +Saldo USDC: 927301.578272 +Saldo WETH: 500 +Vendi, mi aspetto che il prezzo scenda di 118.75 USD +Transazione di approvazione inviata: 74e367ddbb407c1aaf567d87aa5863049991b1d2aa092b6b85195d925e2bd41f +Transazione di approvazione minata. +Transazione di vendita inviata: fad1bcf938585c9e90364b26ac7a80eea9efd34c37e5db81e58d7655bcae28bf +Transazione di vendita minata. +Saldi del conto dopo lo scambio: +Saldo USDC: 929143.797116 +Saldo WETH: 499 +``` + +Per usarlo effettivamente, hai bisogno di alcune piccole modifiche. + +- Nella riga 14, cambia `MAINNET_URL` in un punto di accesso reale, come `https://eth.drpc.org` +- Nella riga 28, cambia `PRIVATE_KEY` con la tua chiave privata +- A meno che tu non sia molto ricco e possa comprare o vendere 1 ETH ogni giorno per un agente non provato, potresti voler cambiare la riga 29 per diminuire `WETH_TRADE_AMOUNT` + +#### Spiegazione del codice {#trading-code} + +Ecco il nuovo codice. + +```python +SWAP_ROUTER_ADDRESS=Web3.to_checksum_address("0xE592427A0AEce92De3Edee1F18E0157C05861564") +WETH_TO_USDC=bytes.fromhex("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") +USDC_TO_WETH=bytes.fromhex("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +``` + +Le stesse variabili che abbiamo usato nel passaggio 4. + +```python +WETH_TRADE_AMOUNT=1 +``` + +L'importo da scambiare. + +```python +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... }, + { "name": "balanceOf", ...}, + { "name": "approve", ...} +] +``` + +Per fare effettivamente trading, abbiamo bisogno della funzione `approve`. Vogliamo anche mostrare i saldi prima e dopo, quindi abbiamo bisogno anche di `balanceOf`. + +```python +SWAP_ROUTER_ABI = [ + { "name": "exactInput", ...}, +] +``` + +Nell'ABI di `SwapRouter` abbiamo solo bisogno di `exactInput`. Esiste una funzione correlata, `exactOutput`, che potremmo usare per comprare esattamente un WETH, ma per semplicità usiamo solo `exactInput` in entrambi i casi. + +```python +account = w3.eth.account.from_key(PRIVATE_KEY) +swap_router = w3.eth.contract( + address=SWAP_ROUTER_ADDRESS, + abi=SWAP_ROUTER_ABI +) +``` + +Le definizioni Web3 per il [`conto`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html) e il contratto `SwapRouter`. + +```python +def txn_params() -> dict: + return { + "from": account.address, + "value": 0, + "gas": 300000, + "nonce": w3.eth.get_transaction_count(account.address), + } +``` + +I parametri della transazione. Abbiamo bisogno di una funzione qui perché [il nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) deve cambiare ogni volta. + +```python +def approve_token(contract: Contract, amount: int): +``` + +Approva un'autorizzazione di token per `SwapRouter`. + +```python + txn = contract.functions.approve(SWAP_ROUTER_ADDRESS, amount).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) +``` + +Questo è il modo in cui inviamo una transazione in Web3. Per prima cosa usiamo [l'oggetto `Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) per costruire la transazione. Poi usiamo [`web3.eth.account.sign_transaction`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-contract-transaction) per firmare la transazione, usando `PRIVATE_KEY`. Infine, usiamo [`w3.eth.send_raw_transaction`](https://web3py.readthedocs.io/en/stable/transactions.html#chapter-2-w3-eth-send-raw-transaction) per inviare la transazione. + +```python + print(f"Transazione di approvazione inviata: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Transazione di approvazione minata.") +``` + +[`w3.eth.wait_for_transaction_receipt`](https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.wait_for_transaction_receipt) attende che la transazione venga minata. Restituisce la ricevuta, se necessario. + +```python +SELL_PARAMS = { + "path": WETH_TO_USDC, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": WETH_TRADE_AMOUNT * 10 ** wethusdc_pool.token1.decimals, + "amountOutMinimum": 0, +} +``` + +Questi sono i parametri per la vendita di WETH. + +```python +def make_buy_params(quote: Quote) -> dict: + return { + "path": USDC_TO_WETH, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": int(quote.price*WETH_TRADE_AMOUNT) * 10**wethusdc_pool.token0.decimals, + "amountOutMinimum": 0, + } +``` + +A differenza di `SELL_PARAMS`, i parametri di acquisto possono cambiare. L'importo in entrata è il costo di 1 WETH, come disponibile in `quote`. + +```python +def buy(quote: Quote): + buy_params = make_buy_params(quote) + approve_token(wethusdc_pool.token0.contract, buy_params["amountIn"]) + txn = swap_router.functions.exactInput(buy_params).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Transazione di acquisto inviata: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Transazione di acquisto minata.") + + +def sell(): + approve_token(wethusdc_pool.token1.contract, + WETH_TRADE_AMOUNT * 10**wethusdc_pool.token1.decimals) + txn = swap_router.functions.exactInput(SELL_PARAMS).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Transazione di vendita inviata: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Transazione di vendita minata.") +``` + +Le funzioni `buy()` e `sell()` sono quasi identiche. Per prima cosa approviamo un'autorizzazione sufficiente per `SwapRouter`, e poi lo chiamiamo con il percorso e l'importo corretti. + +```python +def balances(): + token0_balance = wethusdc_pool.token0.contract.functions.balanceOf(account.address).call() + token1_balance = wethusdc_pool.token1.contract.functions.balanceOf(account.address).call() + + print(f"{wethusdc_pool.token0.symbol} Saldo: {Decimal(token0_balance) / Decimal(10 ** wethusdc_pool.token0.decimals)}") + print(f"{wethusdc_pool.token1.symbol} Saldo: {Decimal(token1_balance) / Decimal(10 ** wethusdc_pool.token1.decimals)}") +``` + +Riporta i saldi dell'utente in entrambe le valute. + +```python +print("Saldi del conto prima dello scambio:") +balances() + +if (expected_price > current_price): + print(f"Compra, mi aspetto che il prezzo salga di {expected_price - current_price} USD") + buy(wethusdc_quotes[-1]) +else: + print(f"Vendi, mi aspetto che il prezzo scenda di {current_price - expected_price} USD") + sell() + +print("Saldi del conto dopo lo scambio:") +balances() +``` + +Questo agente attualmente funziona solo una volta. Tuttavia, puoi modificarlo per farlo funzionare continuamente eseguendolo da [`crontab`](https://man7.org/linux/man-pages/man1/crontab.1.html) o racchiudendo le righe 368-400 in un ciclo e usando [`time.sleep`](https://docs.python.org/3/library/time.html#time.sleep) per attendere fino al momento del ciclo successivo. + +## Possibili miglioramenti {#improvements} + +Questa non è una versione di produzione completa; è semplicemente un esempio per insegnare le basi. Ecco alcune idee per miglioramenti. + +### Trading più intelligente {#smart-trading} + +Ci sono due fatti importanti che l'agente ignora quando decide cosa fare. + +- _L'entità del cambiamento previsto_. L'agente vende una quantità fissa di `WETH` se si prevede che il prezzo diminuisca, indipendentemente dall'entità del calo. + Probabilmente, sarebbe meglio ignorare le piccole variazioni e vendere in base a quanto ci aspettiamo che il prezzo diminuisca. +- _Il portafoglio attuale_. Se il 10% del tuo portafoglio è in WETH e pensi che il prezzo salirà, probabilmente ha senso acquistarne di più. Ma se il 90% del tuo portafoglio è in WETH, potresti essere sufficientemente esposto e non c'è bisogno di acquistarne di più. Il contrario è vero se ti aspetti che il prezzo scenda. + +### E se volessi mantenere segreta la tua strategia di trading? {#secret} + +I fornitori di IA possono vedere le query che invii ai loro LLM, il che potrebbe esporre il geniale sistema di trading che hai sviluppato con il tuo agente. Un sistema di trading che troppe persone usano è inutile perché troppe persone cercano di comprare quando vuoi comprare tu (e il prezzo sale) e cercano di vendere quando vuoi vendere tu (e il prezzo scende). + +Puoi eseguire un LLM localmente, ad esempio, utilizzando [LM-Studio](https://lmstudio.ai/), per evitare questo problema. + +### Da bot IA ad agente IA {#bot-to-agent} + +Si può sostenere validamente che questo è [un bot IA, non un agente IA](/ai-agents/#ai-agents-vs-ai-bots). Implementa una strategia relativamente semplice che si basa su informazioni predefinite. Possiamo abilitare l'auto-miglioramento, ad esempio, fornendo un elenco di gruppi di Uniswap v3 e i loro ultimi valori e chiedendo quale combinazione ha il miglior valore predittivo. + +### Protezione dallo slippage {#slippage-protection} + +Attualmente non c'è [protezione dallo slippage](https://uniswapv3book.com/milestone_3/slippage-protection.html). Se la quotazione attuale è di 2000 $ e il prezzo previsto è di 2100 $, l'agente comprerà. Tuttavia, se prima che l'agente acquisti il costo sale a 2200 $, non ha più senso comprare. + +Per implementare la protezione dallo slippage, specifica un valore `amountOutMinimum` nelle righe 325 e 334 di [`agent.py`](https://github.com/qbzzt/260215-ai-agent/blob/05-trade/agent.py#L325). + +## Conclusione {#conclusion} + +Speriamo che ora tu sappia abbastanza per iniziare con gli agenti IA. Questa non è una panoramica completa dell'argomento; ci sono interi libri dedicati a questo, ma questo è sufficiente per iniziare. Buona fortuna! + +[Vedi qui per altri miei lavori](https://cryptodocguy.pro/). diff --git a/public/content/translations/it/developers/tutorials/hello-world-smart-contract-fullstack/index.md b/public/content/translations/it/developers/tutorials/hello-world-smart-contract-fullstack/index.md index 0a417e53d75..27dfe2417ec 100644 --- a/public/content/translations/it/developers/tutorials/hello-world-smart-contract-fullstack/index.md +++ b/public/content/translations/it/developers/tutorials/hello-world-smart-contract-fullstack/index.md @@ -237,7 +237,7 @@ Non nominarlo `process.env` o `.env-custom` o in altro modo. - Segui [queste istruzioni](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key) per esportare la tua chiave privata - Vedi sotto per ottenere l'URL dell'API di Alchemy HTTP -![](./get-alchemy-api-key.gif) +![Procedura dettagliata animata per ottenere una chiave API Alchemy](./get-alchemy-api-key.gif) Il tuo `.env` dovrebbe somigliare a questo: diff --git a/public/content/translations/it/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md b/public/content/translations/it/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md index bfa2f23fd63..c5050a30969 100644 --- a/public/content/translations/it/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md +++ b/public/content/translations/it/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md @@ -65,13 +65,13 @@ Questo produrrà le stesse informazioni fornite sulla pagina della transazione d #### Etherscan {#etherscan} -![](./etherscan_view.png) +![Screenshot della visualizzazione dell'Explorer delle transazioni Etherscan](./etherscan_view.png) [Pagina del contratto dell'EF su Etherscan.](https://etherscan.io/address/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe) #### Dune Analytics {#dune-analytics} -![](./dune_view.png) +![Screenshot di un dashboard delle query di Dune Analytics](./dune_view.png) Puoi trovare la dashboard [qui](https://duneanalytics.com/paulapivat/Learn-Ethereum). Clicca sulla tabella per vedere l'interrogazione (vedi anche sopra). @@ -149,7 +149,7 @@ ORDER BY block_time DESC` Ecco l'output in SQL su Dune: -![](./list_of_txn.png) +![Screenshot di un elenco di transazioni Ethereum](./list_of_txn.png) Questo singolo blocco aggiunto alla catena cambia lo stato della macchina virtuale di Ethereum ([EVM](/developers/docs/evm/)). Dozzine, a volte, centinaia di transazioni vengono verificate in un solo colpo. In questo caso specifico, sono state incluse 222 transazioni. @@ -168,7 +168,7 @@ FROM temp_table Per il blocco 12396854, di 222 transazioni totali, 204 sono state verificate correttamente: -![](./successful_txn.png) +![Screenshot di una transazione Ethereum riuscita](./successful_txn.png) Le richieste di transazioni si verificano dozzine di volte al secondo, ma i blocchi sono impegnati approssimativamente ogni 15 secondi ([sorgente](/developers/docs/blocks/)). @@ -176,11 +176,11 @@ Per vedere che un blocco è prodotto approssimativamente ogni 15 secondi, potrem Il grafico per i blocchi di Ethereum prodotti al giorno (2016 - presente) è: -![](./daily_blocks.png) +![Grafico che mostra la produzione giornaliera di blocchi Ethereum](./daily_blocks.png) Il numero medio di blocchi prodotti giornalmente in questo periodo di tempo è di ~5.874: -![](./avg_daily_blocks.png) +![Grafico che mostra la produzione giornaliera di blocchi Ethereum](./avg_daily_blocks.png) Le interrogazioni sono: @@ -217,7 +217,7 @@ I blocchi hanno dimensioni limitate. La dimensione massima del blocco è dinamic Un modo per concettualizzare il limite di gas del blocco è immaginarlo come l'**offerta** di spazio del blocco disponibile, in cui raggruppare le transazioni. Il limite di gas del blocco è interrogabile e visualizzabile dal 2016 a oggi: -![](./avg_gas_limit.png) +![Grafico che mostra il limite medio di gas di Ethereum nel tempo](./avg_gas_limit.png) ```sql SELECT @@ -230,7 +230,7 @@ OFFSET 1 Poi, c'è il gas effettivo, usato quotidianamente per pagare i calcoli effettuati sulla catena di Ethereum (cioè, l'invio della transazione, la chiamata di un contratto intelligente, il conio di un NFT). Questa è la **domanda** di spazio per i blocchi disponibile di Ethereum: -![](./daily_gas_used.png) +![Grafico che mostra il gas Ethereum utilizzato quotidianamente](./daily_gas_used.png) ```sql SELECT @@ -249,7 +249,7 @@ Dunque, possiamo comprendere i prezzi del gas come una funzione di domanda per l Infine, potremmo voler interrogare i prezzi del gas quotidiani medi per la catena di Ethereum, tuttavia, farlo risulterà in un tempo di richiesta particolarmente lungo, quindi filtreremo la nostra richiesta all'importo medio di gas pagato per transazione dall'Ethereum Foundation. -![](./ef_daily_gas.png) +![Grafico che mostra l'utilizzo giornaliero del gas della Ethereum Foundation](./ef_daily_gas.png) Possiamo vedere i prezzi del gas pagati per tutte le transazioni effettuate all'indirizzo dell'Ethereum Foundation negli anni. Ecco l'interrogazione: diff --git a/public/content/translations/it/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md b/public/content/translations/it/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md index f88aaf9ee3a..29c3ce60257 100644 --- a/public/content/translations/it/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md +++ b/public/content/translations/it/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md @@ -114,34 +114,34 @@ sudo systemctl start grafana-server Quando Grafana è in esecuzione, dovrebbe esser raggiungibile a `localhost:3000`. Usa il tuo browser preferito per accedere a questo percorso, poi accedi con le credenziali predefinite (utente: `admin` e password: `admin`). Quando richiesto, modifica la password predefinita e salva. -![](./grafana1.png) +![Screenshot della dashboard di Grafana per il monitoraggio dei Geth (pannello 1)](./grafana1.png) Sarai reindirizzato alla pagina home di Grafana. Per prima cosa, configura i tuoi dati sorgente. Clicca sull'icona di configurazione nella barra a sinistra e seleziona "Sorgenti dati". -![](./grafana2.png) +![Screenshot della dashboard di Grafana per il monitoraggio dei Geth (pannello 2)](./grafana2.png) Se non sono ancora state create sorgenti di dati, clicca su "Aggiungi sorgente di dati" per definirne una. -![](./grafana3.png) +![Screenshot della dashboard di Grafana per il monitoraggio dei Geth (pannello 3)](./grafana3.png) Per questa configurazione, seleziona "InfluxDB" e procedi. -![](./grafana4.png) +![Screenshot della dashboard di Grafana per il monitoraggio dei Geth (pannello 4)](./grafana4.png) La configurazione della sorgente di dati è abbastanza semplice se esegui gli strumenti sulla stessa macchina. Devi impostare l'indirizzo di InfluxDB e i dettagli per accedere al database. Fai riferimento alla seguente immagine. -![](./grafana5.png) +![Screenshot della dashboard di Grafana per il monitoraggio dei Geth (pannello 5)](./grafana5.png) Se tutto è completo e InfluxDB è raggiungibile, clicca su "Salva e prova" e attendi che compaia la conferma. -![](./grafana6.png) +![Screenshot della dashboard di Grafana per il monitoraggio dei Geth (pannello 6)](./grafana6.png) Grafana è ora configurato per leggere i dati da InfluxDB. Ora devi creare una dashboard che li interpreterà e mostrerà. Le proprietà dei pannelli di controllo sono codificate nei file JSON, che possono essere creati da chiunque e sono facilmente importabili. Sulla barra sinistra, clicca su "Crea e Importa". -![](./grafana7.png) +![Screenshot della dashboard di Grafana per il monitoraggio dei Geth (pannello 7)](./grafana7.png) Per una dashboard di monitoraggio di Geth, copia l'ID di [questa dashboard](https://grafana.com/grafana/dashboards/13877/) e incollalo nella "Pagina d'importazione" su Grafana. Dopo aver salvato la dashboard, dovrebbe somigliare a questo: -![](./grafana8.png) +![Screenshot della dashboard di Grafana per il monitoraggio dei Geth (pannello 8)](./grafana8.png) Puoi modificare i tuoi pannelli di controllo. Ogni pannello può essere modificato, spostato, rimosso o aggiunto. Puoi modificare le tue configurazioni. Sta a te! Per saperne di più su come funzionano i pannelli di controllo, fai riferimento alla [documentazione di Grafana](https://grafana.com/docs/grafana/latest/dashboards/). Potresti esser anche interessato agli [avvisi](https://grafana.com/docs/grafana/latest/alerting/), che ti consentono di configurare delle notifiche di avviso per quando le metriche raggiungono certi valori. Sono supportati diversi canali di comunicazione. diff --git a/public/content/translations/it/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/translations/it/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index 8ccacffadef..00000000000 --- a/public/content/translations/it/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1145 +0,0 @@ ---- -title: Testare i token ERC-20 con Waffle -description: Scopri come testare i contratti intelligenti di Solidity e usa gli abbinatori di contratti intelligenti con Waffle. -author: Vladislav Starostenko -tags: - - "waffle" - - "Smart Contract" - - "Solidity" - - "test" - - "erc-20" -skill: intermediate -lang: it -published: 2020-10-16 ---- - -In questo tutorial imparerai come: - -- Scrivere test per i contratti intelligenti con Waffle -- Usare alcuni abbinatori popolari per testare i contratti intelligenti con Waffle - -Premesse: - -- sai muoverti in un terminale, -- sai creare un nuovo progetto `JavaScript`, -- hai scritto alcune righe di codice in `Solidity`, -- hai scritto qualche test in `JavaScript`, -- hai usato `yarn` o `npm`, installatore di pacchetti di JavaScript. - -Ancora, se alcune di queste premesse sono false o non desideri riprodurre il codice in questo articolo, puoi probabilmente seguirlo ancora e senza problemi. - -## Qualche parola su Waffle {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io) è la libreria più avanzata per scrivere e testare i contratti intelligenti. - -Opera con ethers-js dell'[API di JavaScript](/developers/docs/apis/javascript/). - -Puoi leggere maggiori dettagli nella [documentazione di Waffle](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation)! - -## Tutorial rapido {#the-quick-tutorial} - -Per prima cosa, crea un nuovo progetto `JavaScript` o `TypeScript` (Userò `TS`, ma se usi `JS` non è un problema ): - -Qualcosa del genere: - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## Fase #1: Installa waffle nel tuo progetto [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) {#step-1-install-waffle-in-your-project} - -Per iniziare, installa `ethereum-waffle`. In questo tutorial userò `yarn`, quindi per installare `ethereum-waffle`, esegui: - -```bash - yarn add --dev ethereum-waffle -``` - -## Fase #2: Scrivere un contratto intelligente [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract) {#step-2-write-a-smart-contract} - -In questo tutorial, userò un token [ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol) da [OpenZeppelin](https://openzeppelin.com). - -Quindi, aggiungi `OpenZeppelin` installandolo con `yarn`: - -```bash - yarn add @openzeppelin/contracts -D -``` - -Poi, crea il contratto `BasicToken.sol` nella cartella `src`: - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Example class - a mock class using delivering from ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## Fase #3: Compila il tuo contratto intelligente [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) {#step-3-compile-your-smart-contract} - -Per compilare il tuo contratto intelligente, aggiungi la seguente voce nel `package.json` del tuo progetto: - -```json -{ - "scripts": { - "build": "waffle" - } -} -``` - -Inoltre, aggiungi il file `waffle.json` nella cartella principale del tuo progetto. - -Un esempio della configurazione di `waffle.json`: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Puoi leggere di più sulla configurazione di Waffle [qui](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration). - -Poi basta eseguire `yarn build` per compilare il tuo contratto intelligente. - -Dovresti vedere che Waffle ha compilato il tuo contratto e posizionato l'output JSON risultante nella cartella `build`. - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 P -``` -
- -## Fase #4: Testa il tuo contratto intelligente [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-test-your-smart-contract} - -### Fase #4.1 Installa le dipendenze necessaria [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-1} - -Dopo aver autorizzato con successo un contratto intelligente, possiamo testarlo. Useremo `Waffle` per farlo. - -I test con `Waffle` sono scritti usando `Mocha` insieme a `Chai`. Possiamo usare un ambiente di test diverso, ma gli abbinatori di `Waffle` funzionano solo con `Chai`. - -Quindi, dobbiamo aggiungere `Chai` alle nostre dipendenze: - -```bash - yarn add --dev mocha chai -``` - -### Fase #4.2 Crea il file di test [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-2} - -Per scrivere il nostro test dobbiamo creare il file `BasicToken.test.ts` nella nostra cartella di prova. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -Quindi, usiamo il metodo `deployContract` di `Waffle` per distribuire il nostro token. Come argomenti dovremmo passare `wallet`, il file json compilato del nostro contratto e il saldo predefinito. - -`Waffle` ci consente inoltre di creare un `wallet`, il che rende davvero semplice la distribuzione di un contratto. - -Puoi leggere di più sul `wallet` [qui](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets) e puoi leggere di più sulla funzione di distribuzione [qui](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts). - -Scriviamo un test semplice per controllare il saldo del nostro portafoglio. Poiché abbiamo inviato il valore 1000 durante la distribuzione del nostro contratto, il saldo del nostro portafoglio dev'essere 1000 token, che possiamo verificare nel primo test. - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -Per eseguire il test, usa `yarn test` - -### Fase #4.3 Emettere eventi [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events) {#step-4-3} - -In questo tutorial, voglio mostrarti gli abbinatori di `Waffle` più utili, iniziamo con il primo. - -`Waffle` ci consente di testare che eventi sono emessi. - -In questo tutorial, testerò il metodo `transfer` del nostro contratto. - -In questo test, effettuerò un trasferimento da un portafoglio a un altro e controllerò se l'evento `Transfer` è stato chiamato. - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -Inoltre, un grande vantaggio di questo abbinatore è che possiamo controllare quali argomenti sono stati chiamati da quest'evento aggiungendo `withArgs` al nostro test. - -Questo ci consentirà di esser sicuri che la nostra funzione stia venendo chiamata correttamente! - -### Fase #4.4 Ripristino con il messaggio [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message) {#step-4-4} - -`Waffle` ci consente di testare con che messaggio è stato ripristinato. - -Useremo l'abbinatore `revertedWith` nel nostro test per controllarlo. - -Possiamo scrivere un test in cui eseguiremo un trasferimento per un importo maggiore di quanto abbiamo nel nostro portafoglio. E poi controlleremo se la transazione è tornata con il messaggio esatto! - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### Fase #4.5 Cambiamento del saldo dei token [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance) {#step-4-5} - -`Waffle` ci consente di verificare le modifiche ai saldi dei portafogli! - -Possiamo usare l'abbinatore `changeTokenBalance` per controllare il cambiamento del saldo o `changeTokenBalances` per un conto multiplo. - -L'abbinatore può accettare `numbers`, `strings` e `BigNumbers` come cambiamento di un saldo, mentre l'indirizzo dovrebbe esser specificato come un portafoglio o un contratto. - -Scriviamo il prossimo test: - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -Quanto sopra è un test per un singolo portafoglio. - -E il successivo per più portafogli: - -```ts -it("Send transaction changes sender and receiver balances", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalances([wallet, walletTo], [-200, 200]) -}) -``` - -La transazione dovrebbe passare come callback (dobbiamo controllare il saldo prima della chiamata) o come una risposta della transazione. - -## Congratulazioni {#congratulations} - -**Congratulazioni! Hai concluso il mio tutorial. Hai fatto il tuo primo grande passo verso i contratti intelligenti con Waffle.** - -**Il codice da questo tutorial si può trovare [qui](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website).** - -**Altra documentazione su `Waffle` è disponibile [qui](https://getwaffle.io).** diff --git a/public/content/translations/it/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/it/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 676f647e349..00000000000 --- a/public/content/translations/it/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,298 +0,0 @@ ---- -title: "Waffle: simulazioni dinamiche e test delle chiamate del contratto" -description: Tutorial avanzato su Waffle per usare la simulazione dinamica e testare le chiamate di contratto -author: "Daniel Izdebski" -tags: - - "waffle" - - "smart contract" - - "Solidity" - - "test" - - "simulazione" -skill: intermediate -lang: it -published: 2020-11-14 ---- - -## A cosa serve questo tutorial? {#what-is-this-tutorial-about} - -In questo tutorial imparerai come: - -- usare la simulazione dinamica -- testare interazioni tra Smart Contract - -Premesse: - -- sai già come scrivere un semplice Smart Contract in `Solidity` -- sai utilizzare `JavaScript` e `TypeScript` -- hai seguito altri tutorial di `Waffle<` o ne sai già qualcosa - -## Simulazione dinamica {#dynamic-mocking} - -Perché la simulazione dinamica è utile? Ci consente di scrivere unit test anziché test di integrazione. Cosa significa? Che non dobbiamo preoccuparci delle dipendenze tra gli Smart Contract, dunque possiamo testarli tutti in completo isolamento. Vediamo come. - -### **1. Progetto** {#1-project} - -Prima di iniziare dobbiamo preparare un semplice progetto node.js: - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# or if you're using npm -npm init -``` - -Iniziamo aggiungendo dipendenze typescript e di test: mocha e chai: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# or if you're using npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Ora aggiungiamo `Waffle` e `ethers`: - -```bash -yarn add --dev ethereum-waffle ethers -# or if you're using npm -npm install ethereum-waffle ethers --save-dev -``` - -La struttura del progetto sarà ora simile a: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Smart Contract** {#2-smart-contract} - -Per avviare la simulazione dinamica, serve uno Smart Contract con dipendenze. Nessun problema. - -Ecco un semplice Smart Contract scritto in `Solidity` con il solo scopo di controllare se siamo ricchi. Usa il token ERC20 per verificare se abbiamo abbastanza token. Inseriscilo in `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Poiché vogliamo usare la simulazione dinamica, non ci serve tutto ERC20, quindi usiamo l'interfaccia IERC20 con una sola funzione. - -È ora di creare questo contratto. Per questo useremo `Waffle`. Prima, creeremo un semplice file di configurazione `waffle.json` che specifichi le opzioni di compilazione. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Ora siamo pronti a creare il contratto con Waffle: - -```bash -npx waffle -``` - -Facile, vero? Nella cartella `build/` sono comparsi due file corrispondenti al contratto e all'interfaccia. Li useremo dopo per i test. - -### **3. Test** {#3-testing} - -Creiamo un file chiamato `AmIRichAlready.test.ts` per il test reale. Prima di tutto, dobbiamo gestire le importazioni. Ci serviranno dopo: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -A parte le dipendenze JS, dobbiamo importare il contratto e l'interfaccia creati: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle usa `chai` per il test. Tuttavia, prima di poterlo usare, dobbiamo inserire i matcher di Waffle in chai: - -```typescript -use(solidity) -``` - -Dobbiamo implementare la funzione `beforeEach()` che ripristinerà lo stato del contratto prima di ogni test. Prima pensiamo a cosa ci serve. Per distribuire un contratto servono due cose: un portafoglio e un contratto ERC20 distribuito da passare come argomento per il contratto `AmIRichAlready`. - -Prima creiamo un portafoglio: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Poi dobbiamo distribuire un contratto ERC20. Ecco la parte complicata: abbiamo solo un'interfaccia. Questa è la parte in cui Waffle ci viene in aiuto. Waffle ha la funzione magica `deployMockContract()` che crea un contratto usando solo l'_abi_ dell'interfaccia: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Ora con il portafoglio e l'ERC20 distribuito, possiamo continuare e distribuire il contratto `AmIRichAlready`: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -A questo punto, la funzione `beforeEach()` è finita. Il file `AmIRichAlready.test.ts` avrà il seguente aspetto: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Scriviamo il primo test per il contratto `AmIRichAlready`. Cosa pensi dovrebbe fare il test? Esatto! Dobbiamo controllare se siamo già ricchi :) - -Ma aspetta un attimo. Come farà il nostro contratto simulato a sapere che valori restituire? Non abbiamo implementato alcuna logica per la funzione `balanceOf()`. Di nuovo, Waffle ci viene in aiuto. Il nostro contratto simulato ha contenuto interessante: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -Con queste informazioni possiamo finalmente scrivere il primo test: - -```typescript -it("returns false if the wallet has less than 1000000 tokens", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Suddividiamo questo test in più parti: - -1. Impostiamo il contratto ERC20 simulato per restituire il saldo di 999999 token. -2. Controlliamo se il metodo `contract.check()` restituisce `false`. - -Siamo pronti a scatenare la bestia: - -![Un test superato](./test-one.png) - -Quindi il test funziona, ma... si può ancora migliorare. La funzione `balanceOf()` restituirà sempre 99999. Possiamo migliorarla specificando un portafoglio per cui la funzione deve restituire qualcosa, proprio come un vero contratto: - -```typescript -it("returns false if the wallet has less than 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Finora, abbiamo testato solo il caso in cui non siamo abbastanza ricchi. Testiamo invece l'opposto: - -```typescript -it("returns true if the wallet has at least 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Esegui i test... - -![Due test superati](test-two.png) - -...ed ecco qui! Il nostro contratto sembra funzionare come previsto :) - -## Test delle chiamate del contratto {#testing-contract-calls} - -Ricapitoliamo cosa abbiamo fatto finora. Abbiamo testato la funzionalità del contratto `AmIRichAlready` che sembra funzionare correttamente. Quindi abbiamo finito, giusto? Non proprio. Waffle ci consente di testare il nostro contratto ancora più a fondo. Ma come esattamente? Beh, nell'arsenale di Waffle ci sono i matcher `calledOnContract()` e `calledOnContractWith()`. Ci consentiranno di verificare se il contratto ha chiamato il contratto simulato ERC20. Ecco un test di base con uno di questi matcher: - -```typescript -it("checks if contract called balanceOf on the ERC20 token", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Possiamo andare persino oltre e migliorare questo test con l'altro matcher che ho indicato: - -```typescript -it("checks if contract called balanceOf with certain wallet on the ERC20 token", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Controlliamo se i test sono corretti: - -![Tre test superati](test-three.png) - -Ottimo, tutti i test danno luce verde. - -Testare le chiamate di contratto con Waffle è facilissimo. Ma ecco la parte migliore. Questi matcher funzionano sia con contratti normali che simulati! Questo perché Waffle registra e filtra le chiamate all'EVM piuttosto che inserire il codice, come invece fanno librerie di testing popolari di altre tecnologie. - -## Il traguardo {#the-finish-line} - -Congratulazioni! Ora sai come usare Waffle per testare le chiamate di contratto e i contratti simulati dinamicamente. Ci sono funzionalità ben più interessanti da scoprire. Ti consiglio di tuffarti nella documentazione di Waffle. - -La documentazione di Waffle è disponibile [qui](https://ethereum-waffle.readthedocs.io/). - -Il codice sorgente di questo tutorial si può trovare [qui](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Altri tutorial che potrebbero interessarti: - -- [Test di Smart Contract con Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/it/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/it/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 4de539e1148..00000000000 --- a/public/content/translations/it/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: "Tutorial Waffle Hello world con hardhat ed ethers" -description: Crea il tuo primo progetto Waffle con hardhat ed ethers.js -author: "MiZiet" -tags: - - "waffle" - - "smart contract" - - "Solidity" - - "test" - - "hardhat" - - "ethers.js" -skill: beginner -lang: it -published: 2020-10-16 ---- - -In questo tutorial di [Waffle](https://ethereum-waffle.readthedocs.io), impareremo come configurare un semplice progetto di smart contract "Hello World" usando [hardhat](https://hardhat.org/) e [ethers.js](https://docs.ethers.io/v5/). Quindi impareremo come aggiungere una nuova funzionalità allo smart contract e come testarla con Waffle. - -Iniziamo creando un nuovo progetto: - -```bash -yarn init -``` - -o - -```bash -npm init -``` - -e installando i pacchetti necessari: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -o - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -Il prossimo passaggio consiste nel creare un progetto hardhat di esempio eseguendo `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Welcome to Hardhat v2.0.3 👷‍ - -? What do you want to do? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -Seleziona `Create a sample project` - -La struttura del nostro progetto sarà simile a: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Ora parliamo di alcuni di questi file: {#now-lets-talk} - -- Greeter.sol - il nostro Smart Contract scritto in Solidity; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Il nostro smart contract è divisibile in tre parti: - -1. costruttore - posizione in cui dichiariamo una variabile di tipo di stringa chiamata `greeting`, -2. funzione greet - funzione che restituirà `greeting` quando chiamata, -3. funzione setGreeting - funzione che ci consente di cambiare il valore di `greeting`. - -- sample-test.js - file per il test - -```js -describe("Greeter", function () { - it("Should return the new greeting once it's changed", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### Il prossimo passaggio consiste nel compilare il contratto ed eseguire test: {#compiling-and-testing} - -I test di Waffle usano Mocha (un framework di test) con Chai (una libreria di asserzione). È sufficiente eseguire `npx hardhat test` e attendere che compaia il messaggio seguente. - -```bash -✓ Should return the new greeting once it's changed -``` - -### Finora tutto bene, adesso aggiungiamo un po' di complessità al nostro progetto {#adding-complexity} - -Immagina una situazione in cui qualcuno aggiunge una stringa vuota come formula di saluto. Non sarebbe un bel saluto, vero? -Assicuriamoci che non succeda: - -Vogliamo usare `revert` di Solidity quando qualcuno passa una stringa vuota. Un aspetto positivo è che possiamo facilmente testare questa funzionalità con il matcher chai di Waffle `to.be.revertedWith()`. - -```js -it("Should revert when passing an empty string", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -Sembra che il nostro nuovo test non sia riuscito: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -Implementiamo questa funzionalità nel nostro smart contract: - -```solidity -require(bytes(_greeting).length > 0, "Il saluto non dovrebbe esser vuoto"); -``` - -Ora, la nostra funzione setGreeting somiglia a: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Eseguiamo di nuovo i test: - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -Congratulazioni! Ce l'hai fatta :) - -### Conclusioni {#conclusion} - -Abbiamo realizzato un semplice progetto con Waffle, Hardhat ed ethers.js. Abbiamo imparato come configurare un progetto, aggiungere un test e implementare nuove funzionalità. - -Per informazioni su altri utili matcher chai per testare gli smart contract, consulta la [documentazione ufficiale di Waffle](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/translations/it/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/it/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index d440693878a..00000000000 --- a/public/content/translations/it/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Testare semplici contratti intelligenti con la libreria Waffle -description: Tutorial per principianti -author: Ewa Kowalska -tags: - - "contratti intelligenti" - - "solidity" - - "Waffle" - - "test" -skill: beginner -lang: it -published: 2021-02-26 ---- - -## In questo tutorial imparerai come {#in-this-tutorial-youll-learn-how-to} - -- Testare le modifiche del saldo del portafoglio -- Testare l'emissione di eventi con gli argomenti specificati -- Imporre il ripristino di una transazione - -## Premesse {#assumptions} - -- Sei in grado di creare un nuovo progetto JavaScript o TypeScript -- Hai delle esperienze di base con i test in JavaScript -- Hai utilizzato dei gestori di pacchetti come yarn o npm -- Possiedi conoscenze molto essenziali dei contratti intelligenti e di Solidity - -## Primi passi {#getting-started} - -Il tutorial dimostra la configurazione di prova e opera utilizzando yarn, ma non ci sono problemi se preferisci npm: fornirò gli adeguati riferimenti alla [documentazione](https://ethereum-waffle.readthedocs.io/en/latest/index.html) ufficiale di Waffle. - -### Installa dipendenze {#install-dependencies} - -[Aggiungi](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) ethereum-waffle e le dipendenze di TypeScript alle dipendenze di sviluppo del tuo progetto. - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -### Esempio di contratto intelligente {#example-smart-contract} - -Durante il tutorial lavoreremo a un esempio di contratto intelligente semplice: EtherSplitter. Non fa molto, tranne che consentire a chiunque di inviare wei e dividerli uniformemente tra due destinatari predefiniti. La funzione di divisione richiede che il numero di wei sia pari, altrimenti si ripristinerà. Per entrambi i destinatari esegue un trasferimento di wei, seguito dall'emissione dell'evento Trasferimento. - -Posiziona il frammento del codice di EtherSplitter in `src/EtherSplitter.sol`. - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Uneven wei amount not allowed'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -### Compila il contratto {#compile-the-contract} - -Per [compilare](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) il contratto, aggiungi il seguente elemento al file package.json: - -```json -"scripts": { - "build": "waffle" - } -``` - -Poi, crea un file di configurazione di Waffle nella cartella di root del progetto, `waffle.json`, e incolla qui la seguente configurazione: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Esegui `yarn build`. Di conseguenza, la cartella `build` apparirà con il contratto compilato di EtherSplitter nel formato JSON. - -### Testare la configurazione {#test-setup} - -Testare con Waffle richiede l'utilizzo di abbinatori Chai e Mocha, quindi, devi [aggiungerli](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) al tuo progetto. Aggiorna il tuo file package.json e aggiungi l'elemento `test` nella parte degli script: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -Se desideri [eseguire](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) i tuoi test, basta eseguire `yarn test`. - -## Test {#testing} - -Ora, crea la cartella `test` e crea il nuovo file `test\EtherSplitter.test.ts`. Copia il seguente frammento e incollalo sul nostro file di test. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Ether Splitter", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // add the tests here -}) -``` - -Solo due parole prima di iniziare. `MockProvider` offre una versione fittizia della blockchain. Inoltre, fornisce portafogli fittizi che ci serviranno per testare il contratto di EtherSplitter. Possiamo ottenere fino a dieci portafogli chiamando il metodo `getWallets()` sul fornitore. Nell'esempio, otteniamo tre portafogli: per il mittente e per i due destinatari. - -Quindi, dichiariamo una variabile detta "splitter" (divisore), che è il nostro contratto fittizio EtherSplitter. È creato prima di ogni esecuzione di un singolo test dal metodo `deployContract`. Questo metodo simula la distribuzione di un contratto dal portafoglio passato come primo parametro (nel nostro caso, il portafoglio del mittente). Il secondo parametro è l'ABI e il bytecode del contratto testato; qui, passiamo il file json del contratto compilato EtherSplitter dalla cartella `build`. Il terzo parametro è un insieme con gli argomenti del costruttore del contratto che, nel nostro caso, sono gli indirizzi dei due destinatari. - -### changeBalances {#changebalances} - -Prima controlleremo se il metodo di divisione modifica effettivamente i saldi dei portafogli dei destinatari. Se dividiamo 50 wei dall'account del mittente, i saldi di entrambi i destinatari dovrebbero aumentare di 25 wei. Utilizzeremo l'abbinatore di Waffle "`changeBalances`: - -```ts -it("Changes accounts balances", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -Come primo parametro dell'abbinatore, passiamo un insieme di portafogli dei destinatari e, come secondo, un insieme degli aumenti previsti sugli account corrispondenti. Se desiderassimo verificare il saldo di un portafoglio specifico, potremmo anche utilizzare l'abbinatore `changeBalance`, che non richiede di passare insiemi, come nel seguente esempio: - -```ts -it("Changes account balance", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -Nota che in entrambi i casi di `changeBalance` e `changeBalances`, passiamo la funzione di divisione come richiamata, poiché l'abbinatore deve accedere allo stato dei saldi prima e dopo la chiamata. - -Poi, testeremo se l'evento Trasferimento è stato emesso dopo ogni trasferimento di wei. Ci rivolgeremo a un altro abbinatore da Waffle: - -### Emetti {#emit} - -```ts -it("Emits event on the transfer to the first receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("Emits event on the transfer to the second receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -L'abbinatore `emit` ci consente di verificare se un contratto ha emesso un evento alla chiamata di un metodo. Come parametri all'abbinatore `emit`, forniamo il contratto fittizio che prevediamo emetterà l'evento, insieme al nome di tale evento. Nel nostro caso, il contratto fittizio è `splitter` e il nome dell'evento è `Trasferimento`. Inoltre, possiamo verificare i valori precisi degli argomenti con cui è stato emesso l'evento; passiamo altrettanti argomenti all'abbinatore `withArgs`, come previsto dalla dichiarazione del nostro evento. Nel caso del contratto EtherSplitter, passiamo gli indirizzi del mittente e del destinatario insieme all'importo trasferito di wei. - -### revertedWith {#revertedwith} - -Come ultimo esempio verificheremo se la transazione è stata ripristinata, nel caso di un numero dispari di wei. Utilizzeremo l'abbinatore `revertedWith`: - -```ts -it("Reverts when Vei amount uneven", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Uneven wei amount not allowed" - ) -}) -``` - -Il test, se superato, ci assicurerà che la transazione è stata effettivamente ripristinata. Tuttavia, deve anche verificarsi una corrispondenza esatta tra i messaggi passati nella dichiarazione `require` e il messaggio previsto in `revertedWith`. Se torniamo al codice del contratto EtherSplitter, nella dichiarazione `require` per l'importo di wei, forniamo il messaggio: "Importo di wei dispari non consentito". Questo corrisponde al messaggio che ci aspettiamo nel nostro test. Se non fossero stati uguali, il test sarebbe fallito. - -## Congratulazioni! {#congratulations} - -Hai compiuto il tuo primo grande passo verso il test dei contratti intelligenti con Waffle! diff --git a/public/content/translations/ja/community/support/faq/index.md b/public/content/translations/ja/community/support/faq/index.md new file mode 100644 index 00000000000..626e9f4b481 --- /dev/null +++ b/public/content/translations/ja/community/support/faq/index.md @@ -0,0 +1,77 @@ +--- +title: "よくある質問" +description: "ウォレット、トランザクション、ステーキングなどに関するイーサリアムのよくある質問。" +lang: ja +--- + +# よくある質問 {#faq} + +## 間違ったアドレスに暗号通貨を送ってしまった {#wrong-wallet} + +イーサリアムで送信されたトランザクションはもとに戻すことはできません。 残念ながら、間違ったウォレットにETHやトークンを送ってしまった場合、そのトランザクションを取り消す方法はありません。 + +**対処法:** + +- アドレスの所有者を知っている場合は、直接連絡して資金の返還を依頼してください。 +- アドレスが取引所や既知のサービスのものである場合は、そのサポートチームに連絡してください。助けてくれる可能性があります。 +- トークンをコントラクトアドレスに送った場合は、そのコントラクトに出金またはリカバリー機能があるかどうかを確認してください (まれなケースですが)。 + +ほとんどの場合、資金を回収する方法はありません。 イーサリアムは、中央集権的な組織、団体、個人によって所有されていないため、誰もトランザクションを取り消すことができません。 確定する前に、必ず受取人のアドレスを再確認してください。 + +## ウォレットにアクセスできなくなった {#lost-wallet-access} + +リカバリーの選択肢は、使用しているウォレットの種類によって異なります。 + +### シードフレーズ (リカバリーフレーズ) をお持ちの場合 + +シードフレーズを使えば、互換性のあるどのウォレットアプリでもウォレットを復元できます。 このため、シードフレーズをオフラインで安全に保管することが非常に重要です。 復元手順については、お使いのウォレットプロバイダーのドキュメントを確認してください。 + +### シードフレーズを紛失した場合 + +シードフレーズや秘密鍵がなければ、資金を回収することはできません。 ethereum.orgを含め、誰もあなたのパスワードをリセットしたり、セルフカストディウォレットへのアクセスを復元したりすることはできません。 + +### アカウントが取引所にある場合 + +Coinbase、Binance、Krakenなどの中央集権型取引所にお持ちのアカウントの場合は、取引所のサポートチームに直接お問い合わせください。 取引所はプラットフォーム上のアカウントを管理しており、パスワードのリセットやアカウントのリカバリーを手伝ってくれる可能性があります。 + + + + + + +ウォレットのリカバリーを手伝うと称する**いかなる人物ともシードフレーズを共有しないでください**。 これは最も一般的な詐欺の手口の一つです。 正規のサービスがシードフレーズを尋ねることは決してありません。 + + + + + + ウォレットの使用方法 + + +## トランザクションが詰まっている、または保留中のままになっている {#stuck-transaction} + +設定したガス代がネットワークで現在要求されている額よりも低い場合、イーサリアム上のトランザクションが詰まることがあります。 ほとんどのウォレットでは、この問題を解決できます。 + +- **スピードアップ:** より高いガス代で同じトランザクションを再送信します。 +- **キャンセル:** 保留中のトランザクションと同じノンスを使用して、自分のアドレスに0 ETHのトランザクションを送信します。 + +### 役立つガイド + +- [MetaMaskで保留中のトランザクションをスピードアップまたはキャンセルする方法](https://support.metamask.io/transactions-and-gas/transactions/how-to-speed-up-or-cancel-a-pending-transaction/) +- [保留中のイーサリアムのトランザクションをキャンセルする方法](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) + +## イーサリアムのプレゼントはどのように請求すれば良いですか? {#giveaway-scam} + +イーサリアムをプレゼントするというものは、ETHを盗もうと企てる詐欺です。 うますぎる話に騙されないでください。 景品配布のアドレスにETHを送金しても、景品は受け取れず、資金を回収することもできなくなります。 + +[詐欺対策の詳細](/security/#common-scams) + +## ETHをステーキングするにはどうすればよいですか? {#how-to-stake} + +バリデータになるには、イーサリアムのデポジットコントラクトに32ETHをステーキングし、バリデータノードを設定する必要があります。 ステーキングプールを通じて、より少ないETHで参加することもできます。 + +詳細については、[ステーキングのページ](/staking/)および[ステーキング・ローンチパッド](https://launchpad.ethereum.org/)をご覧ください。 + +## イーサリアムのマイニング方法を教えてください {#mining-ethereum} + +イーサリアムのマイニングはできなくなりました。 2022年9月の[マージ](/roadmap/merge/)でイーサリアムが[プルーフ・オブ・ワーク](/glossary/#pow)から[プルーフ・オブ・ステーク](/glossary/#pos)に移行した際、マイニングは停止されました。 現在は、マイナーの代わりとなるバリデータが活躍しており、 誰でもETHを[ステーク](/glossary/#staking)して、バリデータソフトウェアを実行しネットワークの安全を確保することで、ステーキング報酬を受け取ることができます。 diff --git a/public/content/translations/ja/community/support/index.md b/public/content/translations/ja/community/support/index.md deleted file mode 100644 index 72f2969317a..00000000000 --- a/public/content/translations/ja/community/support/index.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: "イーサリアムサポート" -description: "イーサリアムエコシステムにおけるサポート" -lang: ja ---- - -# イーサリアムのサポート {#support} - -## イーサリアムの公式サポート {#official-support} - -イーサリアムの公式サポートをお探しの場合は、まず始めに、 イーサリアムは非集中的な分散型であるということをご理解ください。 イーサリアムは、中央組織、団体、または個人により所有されていないため、公式のサポートチャンネルはありません。 - -イーサリアムの分散型の性質を理解することは極めて重要です。なぜなら、**イーサリアムの公式サポートを名乗る人は、おそらくあなたを騙そうとしているからです!**詐欺師に対する最良の防御は、自分自身を教育し、セキュリティを真剣に考えることです。 - - - イーサリアムのセキュリティと詐欺対策 - - - - イーサリアムの基礎を学ぶ - - -公式サポートはありませんが、イーサリアムエコシステム全体で多くのグループ、コミュニティ、およびプロジェクトからサポートを受けることができます。このページに有用な情報やリソースを記載していますので、ご確認ください。 ご質問やご不明点がある場合は、 [ethereum.org Discord](https://discord.gg/ethereum-org)にご参加ください。私たちがサポートします。 - -## よくある質問 {#faq} - -### 間違ったウォレットにETHを送ってしまいました {#wrong-wallet} - -イーサリアムで送信されたトランザクションはもとに戻すことはできません。 間違ったウォレットにETHを送信してしまった場合、残念ながら、これらの資金を回収する方法はありません。 イーサリアムは、中央組織、団体、個人により所有されていないため、誰もトランザクションを取り消すことができません。 そのため、必ず送信前に細心の注意を払って、ダブルチェックを行ってください。 - -### イーサリアムのプレゼントはどのように請求すれば良いですか? {#giveaway-scam} - -イーサリアムをプレゼントするというものは、ETHを盗もうと企てる詐欺です。 うま過ぎる話しには騙されないでください。プレゼントを受け取ろうと、相手先のアドレスにETHを送金してしまった場合、プレゼントはもらえず、自分の資金を回収することもできません。 - -[詐欺対策の詳細](/security/#common-scams) - -### トランザクションが保留中のままです {#stuck-transaction} - -イーサリアムのトランザクションは、必要とされるよりも低いトランザクションフィーを提示した場合、ネットワークの需要により、トランザクションが保留になってしまうことがあります。 多くのウォレットは、トランザクションが処理されるよう、トランザクションフィーの金額を上げて、同一トランザクションを再送信するオプションがあります。 もしくは、自分のアドレスにトランザクションを送信し、保留中のトランザクションと同じノンス (nonce)を使用することで、保留中のトランザクションをキャンセルすることができます。 - -[MetaMaskで保留中のトランザクションを高速化またはキャンセルする方法](https://metamask.zendesk.com/hc/en-us/articles/360015489251-How-to-speed-up-or-cancel-a-pending-transaction) - -[保留中のイーサリアムのトランザクションをキャンセルする方法](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) - -### イーサリアムのマイニング方法を教えてください {#mining-ethereum} - -イーサリアムのマイニングはできなくなりました。 イーサリアムが[プルーフ・オブ・ワーク](/glossary/#pow)から[プルーフ・オブ・ステーク](/glossary/#pos)に移行した際、マイニングは停止されました。 現在は、マイナーの代わりとなるバリデータが活躍しており、 誰でもETHを[ステーク](/glossary/#staking)して、バリデータソフトウェアを実行しネットワークの安全を確保することで、ステーキング報酬を受け取ることができます。 - -### ステーカーになる/バリデータを立ち上げる方法は? {#how-to-stake} - -バリデータになるには、イーサリアムのデポジットコントラクトに32ETHをステーキングし、バリデータノードを設定する必要があります。 詳細は、[ステーキングのページ](/staking)および[ステーキング・ローンチパッド](https://launchpad.ethereum.org/)でご覧いただけます。 - -## dappsの構築 {#building-support} - -開発では問題にぶち当たることもあります。 下記は、経験豊富なイーサリアムデベロッパーがいる、開発に特化したスペースです。 - -- [Alchemyユニバーシティ](https://university.alchemy.com/#starter_code) -- [CryptoDevs discord](https://discord.com/invite/5W5tVb3) -- [Ethereum StackExchange](https://ethereum.stackexchange.com/) -- [Web3ユニバーシティ](https://www.web3.university/) -- [LearnWeb3](https://discord.com/invite/learnweb3) - -私たちの[イーサリアムデベロッパー向けリソース](/developers/)セクションでも、ドキュメントや開発ガイドを見つけることができます。 - -### ツール {#dapp-tooling} - -ご質問が特定のツール、プロジェクト、ライブラリに関するものの場合は、 ほとんどのプロジェクトで、サポート専用のチャットサーバやフォーラムが用意されています。 - -下記は人気があるものの例です。 - -- [Solidity](https://app.element.io/#/room/#solidity:matrix.org) -- [ethers.js](https://discord.gg/6jyGVDK6Jx) -- [web3.js](https://discord.gg/GsABYQu4sC) -- [Hardhat](https://discord.gg/xtrMGhmbfZ) -- [Alchemy](http://alchemy.com/discord) -- [Tenderly](https://discord.gg/fBvDJYR) - -## ノードの実行 {#node-support} - -ノードを実行している場合やバリデータの方は、下記のコミュニティでサポートを受けることができます。 - -- [EthStaker discord](https://discord.gg/ethstaker) -- [EthStaker reddit](https://www.reddit.com/r/ethstaker) - -イーサリアムクライアントを構築しているチームの大半は、サポートを受けたり質問したりできる専用のパブリックスペースを持っています。 - -### 実行クライアント {#execution-clients} - -- [Geth](https://discord.gg/FqDzupGyYf) -- [Nethermind](https://discord.gg/YJx3pm8z5C) -- [Besu](https://discord.gg/p8djYngzKN) -- [Erigon](https://github.com/ledgerwatch/erigon/issues) -- [Reth](https://github.com/paradigmxyz/reth/discussions) - -### コンセンサスクライアント {#consensus-clients} - -- [Prysm](https://discord.gg/prysmaticlabs) -- [Nimbus](https://discord.gg/nSmEH3qgFv) -- [Lighthouse](https://discord.gg/cyAszAh) -- [Teku](https://discord.gg/7hPv2T6) -- [Lodestar](https://discord.gg/aMxzVcr) -- [Grandine](https://discord.gg/H9XCdUSyZd) - -また、[こちらでノードの実行方法を学ぶ](/developers/docs/nodes-and-clients/run-a-node/)こともできます。 diff --git a/public/content/translations/ja/community/support/misconceptions/index.md b/public/content/translations/ja/community/support/misconceptions/index.md new file mode 100644 index 00000000000..d521e004124 --- /dev/null +++ b/public/content/translations/ja/community/support/misconceptions/index.md @@ -0,0 +1,73 @@ +--- +title: "イーサリアムに関するよくある誤解" +description: "イーサリアムの仕組みに関する最も一般的な誤解を解消します。" +lang: ja +--- + +# イーサリアムに関するよくある誤解 {#misconceptions} + +## イーサリアムは企業ですか? {#not-a-company} + +イーサリアムは、世界中の何千人ものコントリビューターによって維持されている、オープンソースの分散型テクノロジーです。 アカウントを管理したり、資金を保有したり、カスタマーサポートを提供したりする「イーサリアム」という会社は存在しません。 + +[イーサリアム・ファウンデーション](https://ethereum.foundation/)はイーサリアムの開発を支援する非営利団体ですが、ネットワークを所有または管理しているわけではありません。 単一の主体は存在しません。 + +**[ethereum.org](/)** は、コミュニティが運営する教育用リソースです。 それは、取引所、ウォレット、金融機関ではありません。 ユーザーの資金を保有することはなく、どのアカウントにもアクセスできません。 + + + イーサリアムとは + + +## 誰かが私の資金を回収または凍結できますか? {#no-fund-access} + +銀行とは異なり、イーサリアムには資金を凍結、差し押さえ、または回収できる中央機関はありません。 秘密鍵(またはシードフレーズ)を保持している人が、ウォレットを完全かつ単独で管理しています。 + +これは、次のことを意味します: + +- 間違ったアドレスに送金した資金を**誰も回収することはできません** +- トランザクションが確定した後に**誰もそれを元に戻すことはできません** +- あなたのウォレットを**誰も凍結**したり、トランザクションをブロックしたりすることはできません +- シードフレーズを紛失した場合に**誰もパスワードをリセットすることはできません** + +このため、シードフレーズを保護することが重要です。 それがウォレットにアクセスする唯一の方法です。 紛失または盗難にあった場合、回復する手段はありません。 + + + イーサリアムのセキュリティと詐欺対策 + + +## 今でもイーサリアムをマイニングできますか? {#no-mining} + +2022年9月の[マージ](/roadmap/merge/)で、イーサリアムは[プルーフ・オブ・ワーク](/glossary/#pow)から[プルーフ・オブ・ステーク](/glossary/#pos)に切り替わりました。 イーサリアムではマイニングはもはや不可能です。 + +現在、ネットワークはETHを[ステーク](/glossary/#staking)するバリデータによって保護されています。 誰でも参加できます: + +- **ソロステーキング:** 32 ETHで自分のバリデータを運用する — [詳細はこちら](/staking/solo/) +- **サービスとしてのステーキング:** 鍵を自分で保持したままノードの運用を委任する — [詳細はこちら](/staking/saas/) +- **プールステーキング:** プールに参加して32 ETH未満でステークする — [詳細はこちら](/staking/pools/) + + + ステーキングについてもっと知る + + +## イーサリアムのサポートチームはありますか? {#no-support-team} + +「公式イーサリアムサポート」を探すのは、「公式インターネットサポート」を探すのと似ています。 もちろん、そのようなものは存在しませんが、問題によっては、インターネットサービスプロバイダー、ルーターのハードウェアメーカー、または使用しているデバイス、アプリ、ウェブサイトの背後にある企業のいずれかからサポートを求めることができる場合があります。 + +イーサリアムも同様です。 イーサリアム全体には、会社、サポートチーム、ヘルプデスクはありませんが、問題によっては、使用している_ウォレットプロバイダー_、_ステーキングサービス_、_取引所_、_金融機関_、または_アプリを維持しているチーム_に連絡することで、ヘルプを得られる場合があります。 + +イーサリアムはデフォルトで公開され透明性が高いため、[ブロックエクスプローラー](/developers/docs/data-and-analytics/block-explorers/)、[分析ツール](/developers/tools/analytics/)、その他の[オンライン調査リソース](/community/support/scams/#analyze)が、問題を直接調べるのに役立つ場合があります。 + +とは言え、イーサリアムやethereum.orgの関係者が以下のようなことをすることはありません。 + +- ダイレクトメッセージであなたに連絡する +- シードフレーズや秘密鍵を尋ねる +- ウォレットの確認のためにETHを送るように要求する +- 手数料と引き換えに資金を回収する手助けを申し出る + +**上記のいずれかを行う人は、あなたを詐欺にかけようとしています。** + +ヘルプが必要な場合、支援を提供できる実際のコミュニティが[サポートページ](/community/support/)にリストされています。 これらはボランティアが運営するオープンなコミュニティであり、公式のサポートチャネルではありません。 + + + イーサリアムのセキュリティと詐欺対策 + diff --git a/public/content/translations/ja/community/support/scams/index.md b/public/content/translations/ja/community/support/scams/index.md new file mode 100644 index 00000000000..309234e9561 --- /dev/null +++ b/public/content/translations/ja/community/support/scams/index.md @@ -0,0 +1,159 @@ +--- +title: "詐欺に関するヘルプと報告" +description: "詐欺にあった場合の対処法、残りの資産を保護する方法、詐欺の報告先について説明します。" +lang: ja +--- + +# 詐欺に遭った、または資金を失った場合 {#scam-help} + +暗号通貨詐欺は、金融やテクノロジーの専門家を含め、経験レベルを問わずあらゆる人々をターゲットにしています。 あなたは一人ではありません。このページを見ていることは、正しい第一歩です。 + + + + + + +**ブロックチェーンのトランザクションを元に戻すことは誰にもできません。** 手数料を支払えば資金を回収できると主張してあなたに連絡してくる人がいれば、それはほぼ間違いなく二次的な詐欺です。 以下の[リカバリー詐欺](#recovery-scams)をご覧ください。 + + + + +## 残りの資産を保護する {#secure-assets} + +詐欺師とやり取りした場合や、ウォレットが不正使用された疑いがある場合は、直ちに以下の手順を実行してください。 + +1. **残りの資金を移動する:** 詐欺師がアクセスできない新しい安全なウォレットに移動します。 +2. **トークンの承認を取り消す。** 詐欺師は、無制限のトークン消費を承認させようとすることがよくあります。 これらの権限を取り消すことで、ウォレットからのさらなる資金流出を防ぎます。 +3. **パスワードを変更する:** リンクされている可能性のある取引所アカウントのパスワードを変更します。 +4. **2要素認証(2FA)を有効にする:** すべての暗号通貨関連のアカウントで有効にします。 + +### トークンの承認を取り消す方法 {#revoke-approvals} + +dappやスマートコントラクトとやり取りする際、トークンを使用する権限を与えている場合があります。 詐欺師に騙されて悪意のある契約を承認してしまった場合、最初の詐欺の後もトークンを流出させ続ける可能性があります。 + +以下のツールを使用して承認を確認し、取り消してください。 + +- [Revoke.cash](https://revoke.cash/): ウォレットを接続して、すべてのアクティブな承認を確認し、取り消します。 +- [Revokescout](https://revoke.blockscout.com/): Blockscoutを介して承認を確認し、取り消します。 +- [Etherscan Token Approval Checker](https://etherscan.io/tokenapprovalchecker): Etherscanを介してトークンの承認を確認し、取り消します。 + + + ステップバイステップガイド: トークンアクセスを取り消す方法 + + +## 詐欺アドレスとウェブサイトを報告する {#report} + +報告は他のユーザーへの警告となり、法執行機関の調査に役立つ場合があります。 トランザクションハッシュ、ウォレットアドレス、スクリーンショット、詐欺師とのあらゆるコミュニケーションなど、すべてを記録してください。 + +### 詐欺アドレスを報告する {#report-address} + +- [Chainabuse](https://www.chainabuse.com/): コミュニティ主導の詐欺および不正行為報告データベースです。 報告を提出し、既知の詐欺アドレスを検索します。 +- [Etherscanレポート](https://info.etherscan.com/report-address/): 最も使用されているイーサリアムブロックエクスプローラーでアドレスにフラグを立てます。 +- [CryptoScamDB](https://cryptoscamdb.org/): 暗号通貨詐欺を追跡するオープンソースデータベースです。 + +### 詐欺ウェブサイトまたはソーシャルメディアアカウントを報告する {#report-website} + +- [PhishTank](https://phishtank.org/): フィッシングURLを提出して検証します。 +- [Googleセーフブラウジング](https://safebrowsing.google.com/safebrowsing/report_phish/): フィッシングサイトをGoogleに報告して、Chromeやその他のブラウザでブロックされるようにします。 +- [Netcraft](https://report.netcraft.com/report/mistake): 悪意のある不正なウェブサイトを報告します。 +- 詐欺が発生したソーシャルメディアプラットフォームで直接報告します(Twitter/X、Discord、Telegramにはすべて報告機能があります)。 + +### 法執行機関に報告する {#report-law-enforcement} + +- **米国:** [FBIインターネット犯罪苦情センター(IC3)](https://www.ic3.gov/) +- **英国:** [Action Fraud](https://www.actionfraud.police.uk/) +- **欧州連合:** [ユーロポール](https://www.europol.europa.eu/report-a-crime) +- **その他の国:** 現地の警察に報告書を提出してください。 暗号通貨詐欺は、ほとんどの法域で犯罪とされています。 + +## 何が起こったかを分析する {#analyze} + +資金がどこに送金されたかを理解することは、報告に役立ち、資金が中央集権型取引所に送金された場合には、回収活動を支援する可能性があります。 + +- [Blockscout](https://eth.blockscout.com/): トランザクションハッシュやウォレットアドレスを検索して資金の送金先を確認できる、オープンソースのブロックエクスプローラーです。 +- [Etherscan](https://etherscan.io/): トランザクションハッシュやウォレットアドレスを検索して、資金の送金先を確認できます。 +- [Chainabuseルックアップ](https://www.chainabuse.com/): アドレスが他の被害者によってすでに報告されているかどうかを確認します。 +- BlockSecによる[MetaSleuth](https://metasleuth.io/): 資金の流れをマッピングする視覚的なトランザクション追跡ツールです。 + +**資金が中央集権型取引所**(Coinbase、Binance、Krakenなど)に送金された場合は、直ちにサポートチームに連絡し、取引の詳細を伝えてください。 取引所は、詐欺のフラグが立てられたアカウントを凍結することがあります。 + +## 厳しい現実 {#hard-truth} + +イーサリアムは分散型であるため、中央集権的な機関がトランザクションを元に戻したり、盗まれた資金を回収したりすることはできません。 トランザクションがブロックチェーン上で確認されると、それは確定となります。 + +それでも報告することには価値があります。 報告は、法執行機関が組織的な詐欺グループを追跡するのに役立ち、ChainabuseやEtherscanでアドレスにフラグを立てることで、将来の潜在的な被害者に警告することができます。 + +## 注意すべき詐欺の種類 {#scam-types} + + + +詐欺師は、あなたのETHを増やすとか、無料のトークンをあげると約束して、偽の景品企画を作成します。 彼らはしばしばヴィタリック・ブテリンのような有名人になりすまします。 「景品企画」のアドレスにETHを送っても、何も返ってきません。 + +**覚えておいてください:** ヴィタリックやその他の著名人が、あなたにETHを送るように頼むことは決してありません。 + +[よくある詐欺の詳細](/security/#common-scams) + + + + +詐欺師は、Discord、Telegram、ソーシャルメディア上でイーサリアムのチームメンバー、モデレーター、またはサポート担当者になりすまします。 彼らは、ヘルプを提供したり、アカウントに問題があると主張したりするダイレクトメッセージを送ってくることがあります。 + +**覚えておいてください:** + +- 「イーサリアムサポートチーム」というものは存在しません。 +- 本物のモデレーターが最初にDMを送ってくることはありません。 +- いかなる理由があっても、シードフレーズや秘密鍵を誰とも共有しないでください。 +- 未承諾のメッセージで送られてきたリンクは絶対にクリックしないでください。 + + + + +リカバリー詐欺は、すでに資金を失った人々を特にターゲットにしています。 詐欺師は、ソーシャルメディアで詐欺に遭ったと話している人々を監視し、「ブロックチェーン調査員」や「暗号通貨回収の専門家」を装って接触してきます。 + +彼らは、前払いの手数料で盗まれた暗号通貨を追跡・回収すると約束します。 あなたが支払った後、彼らは姿を消します。 + +**正当なサービスでブロックチェーンのトランザクションを元に戻すことはできません。** これを約束する者は誰であれ、嘘をついています。 これは最も一般的な二次被害詐欺の一つです。 + + + + +フィッシングサイトは、本物のウォレットアプリ、取引所、またはDeFiプラットフォームとそっくりに見えます。 彼らはあなたを騙してシードフレーズを入力させたり、ウォレットを接続させたりして、資金を抜き取ります。 + +**自分を守るために:** + +- ウォレットを接続する前に、必ずURLを確認してください。 +- 定期的に使用する公式サイトをブックマークしてください。 +- どのウェブサイトにもシードフレーズを入力しないでください。 正当なアプリがそれを要求することはありません。 +- [PhishTank](https://phishtank.org/)を使用して、疑わしいURLを確認してください。 + + + 詐欺トークンの見分け方 + + + + + イーサリアムのセキュリティと詐欺対策の完全ガイド + diff --git a/public/content/translations/ja/developers/docs/networking-layer/index.md b/public/content/translations/ja/developers/docs/networking-layer/index.md index 15bed25b5e2..eadc168a827 100644 --- a/public/content/translations/ja/developers/docs/networking-layer/index.md +++ b/public/content/translations/ja/developers/docs/networking-layer/index.md @@ -146,8 +146,8 @@ SSZは、シンプル・シリアライゼーションの略です。 SSZは、 十分な数のバリデータによってブロックが認証されると、チェーンの先頭に追加され、正当性が確認された後、最終的に確定(ファイナライズ)される。 -![](cons_client_net_layer.png) -![](exe_client_net_layer.png) +![Ethereum コンセンサス クライアント ネットワーキング層の図](cons_client_net_layer.png) +![Ethereum 実行クライアント ネットワーキング層の図](exe_client_net_layer.png) [ethresear.ch](https://ethresear.ch/t/eth1-eth2-client-relationship/7248)より、コンセンサスクライアントと実行クライアントのネットワークレイヤー概略図 diff --git a/public/content/translations/ja/developers/docs/nodes-and-clients/node-architecture/index.md b/public/content/translations/ja/developers/docs/nodes-and-clients/node-architecture/index.md index 85f7640d357..07d1670f67a 100644 --- a/public/content/translations/ja/developers/docs/nodes-and-clients/node-architecture/index.md +++ b/public/content/translations/ja/developers/docs/nodes-and-clients/node-architecture/index.md @@ -10,7 +10,7 @@ lang: ja 以下の図は、2つのイーサリアムクライアント間の関係を示しています。 それぞれのクライアントは、独自のピアツーピア(P2P)・ネットワークに接続しています。 実行クライアントは、ピアツーピア・ネットワークでトランザクションをゴシップし、ローカルのトランザクションプールを管理することができます。一方、コンセンサスクライアントは、ピアツーピア・ネットワークでブロックをゴシップし、コンセンサスを確立し、チェーンの成長を促進します。そのため、別々のピアツーピア・ネットワークが必要になります。 -![](node-architecture-text-background.png) +![実行層とコンセンサス層を示すイーサリアム ノード アーキテクチャの図](node-architecture-text-background.png) _実行クライアントには、Erigon、Nethermind、Besuなど、いくつかの選択肢があります_。 diff --git a/public/content/translations/ja/developers/tutorials/ai-trading-agent/index.md b/public/content/translations/ja/developers/tutorials/ai-trading-agent/index.md new file mode 100644 index 00000000000..711b4e44af2 --- /dev/null +++ b/public/content/translations/ja/developers/tutorials/ai-trading-agent/index.md @@ -0,0 +1,979 @@ +--- +title: "イーサリアムで独自のAI取引エージェントを作成する" +description: "このチュートリアルでは、簡単なAI取引エージェントの作成方法を学びます。 このエージェントは、ブロックチェーンから情報を読み取り、その情報に基づいてLLMに推奨を求め、LLMが推奨する取引を実行し、その後待機して繰り返します。" +author: Ori Pomerantz +tags: [ "AI", "取引", "エージェント", "python" ] +skill: intermediate +published: 2026-02-13 +lang: ja +sidebarDepth: 3 +--- + +このチュートリアルでは、簡単なAI取引エージェントの構築方法を学びます。 このエージェントは次の手順で動作します。 + +1. トークンの現在および過去の価格、および関連する可能性のあるその他の情報を読み取ります +2. この情報と、その関連性を説明する背景情報を使用してクエリを構築します +3. クエリを送信し、予測価格を受け取ります +4. 推奨に基づいて取引します +5. 待機して繰り返します + +このエージェントは、情報を読み取り、それを使用可能な回答をもたらすクエリに変換し、その回答を使用する方法を示します。 これらはすべてAIエージェントに必要な手順です。 このエージェントは、AIで最も一般的に使用される言語であるため、Pythonで実装されています。 + +## なぜこれを行うのか? {#why-do-this} + +自動取引エージェントを使用すると、デベロッパーは取引戦略を選択して実行できます。 [AIエージェント](/ai-agents)は、デベロッパーが使用を考えもしなかった情報やアルゴリズムを使用して、より複雑で動的な取引戦略を可能にします。 + +## ツール {#tools} + +このチュートリアルでは、見積もりと取引に[Python](https://www.python.org/)、[Web3ライブラリ](https://web3py.readthedocs.io/en/stable/)、[Uniswap v3](https://github.com/Uniswap/v3-periphery)を使用します。 + +### なぜPythonなのか? {#python} + +AIで最も広く使用されている言語は[Python](https://www.python.org/)なので、ここではそれを使用します。 Pythonを知らなくても心配いりません。 この言語は非常に分かりやすく、何をするのかを正確に説明します。 + +[Web3ライブラリ](https://web3py.readthedocs.io/en/stable/)は、最も一般的なPythonのイーサリアムAPIです。 非常に使いやすいです。 + +### ブロックチェーンでの取引 {#trading-on-blockchain} + +イーサリアムでトークンを取引できる[多くの分散型取引所(DEX)](/apps/categories/defi/)があります。 しかし、[裁定取引](/developers/docs/smart-contracts/composability/#better-user-experience)により、それらの為替レートは類似する傾向にあります。 + +[Uniswap](https://app.uniswap.org/)は広く使用されているDEXで、見積もり(トークンの相対的な価値を確認するため)と取引の両方に使用できます。 + +### OpenAI {#openai} + +大規模言語モデルには、[OpenAI](https://openai.com/)から始めることにしました。 このチュートリアルのアプリケーションを実行するには、APIアクセスに料金を支払う必要があります。 最低支払額の5ドルで十分すぎるほどです。 + +## 開発、ステップバイステップ {#step-by-step} + +開発を簡素化するため、段階的に進めます。 各ステップはGitHubのブランチです。 + +### はじめに {#getting-started} + +UNIXまたはLinux([WSL](https://learn.microsoft.com/en-us/windows/wsl/install)を含む)で開始するための手順があります + +1. まだお持ちでない場合は、[Python](https://www.python.org/downloads/)をダウンロードしてインストールしてください。 + +2. GitHubリポジトリをクローンします。 + + ```sh + git clone https://github.com/qbzzt/260215-ai-agent.git -b 01-getting-started + cd 260215-ai-agent + ``` + +3. [`uv`](https://docs.astral.sh/uv/getting-started/installation/)をインストールします。 お使いのシステムではコマンドが異なる場合があります。 + + ```sh + pipx install uv + ``` + +4. ライブラリをダウンロードします。 + + ```sh + uv sync + ``` + +5. 仮想環境を有効にします。 + + ```sh + source .venv/bin/activate + ``` + +6. PythonとWeb3が正しく動作していることを確認するには、`python3`を実行し、このプログラムを提供します。 `>>>`プロンプトで入力できます。ファイルを作成する必要はありません。 + + ```python + from web3 import Web3 + MAINNET_URL = "https://eth.drpc.org" + w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) + w3.eth.block_number + quit() + ``` + +### ブロックチェーンからの読み取り {#read-blockchain} + +次のステップは、ブロックチェーンから読み取ることです。 そのためには、`02-read-quote`ブランチに切り替えてから、`uv`を使用してプログラムを実行する必要があります。 + +```sh +git checkout 02-read-quote +uv run agent.py +``` + +タイムスタンプ、価格、資産(現在は常に`WETH/USDC`)を持つ`Quote`オブジェクトのリストを受け取るはずです。 + +以下に一行ごとの説明を示します。 + +```python +from web3 import Web3 +from web3.contract import Contract +from decimal import Decimal, ROUND_HALF_UP +from dataclasses import dataclass +from datetime import datetime, timezone +from pprint import pprint +import time +import functools +import sys +``` + +必要なライブラリをインポートします。 これらは使用されるときに以下で説明されます。 + +```python +print = functools.partial(print, flush=True) +``` + +Pythonの`print`を、常に出力を即座にフラッシュするバージョンに置き換えます。 これは、ステータスのアップデートやデバッグ出力を待ちたくない長時間実行されるスクリプトで役立ちます。 + +```python +MAINNET_URL = "https://eth.drpc.org" +``` + +メインネットにアクセスするためのURLです。 [Node as a Service](/developers/docs/nodes-and-clients/nodes-as-a-service/)から取得するか、[Chainlist](https://chainlist.org/chain/1)で宣伝されているものを使用できます。 + +```python +BLOCK_TIME_SECONDS = 12 +MINUTE_BLOCKS = int(60 / BLOCK_TIME_SECONDS) +HOUR_BLOCKS = MINUTE_BLOCKS * 60 +DAY_BLOCKS = HOUR_BLOCKS * 24 +``` + +イーサリアムメインネットのブロックは通常12秒ごとに発生するため、これらは一定期間内に発生すると予想されるブロックの数です。 これは正確な数値ではないことに注意してください。 [ブロック提案者](/developers/docs/consensus-mechanisms/pos/block-proposal/)がダウンしている場合、そのブロックはスキップされ、次のブロックまでの時間は24秒になります。 タイムスタンプの正確なブロックを取得したい場合は、[バイナリ検索](https://en.wikipedia.org/wiki/Binary_search)を使用します。 しかし、これは我々の目的には十分近いです。 未来を予測することは、厳密な科学ではありません。 + +```python +CYCLE_BLOCKS = DAY_BLOCKS +``` + +サイクルのサイズ。 サイクルごとに1回見積もりを確認し、次のサイクルの終わりの値を推定しようとします。 + +```python +# 読み取っているプールのアドレス +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +``` + +見積もり値は、アドレス[`0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`](https://eth.blockscout.com/address/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640?tab=read_write_contract)のUniswap 3 USDC/WETHプールから取得されます。 このアドレスは既にチェックサム形式ですが、コードを再利用可能にするために[`Web3.to_checksum_address`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_checksum_address)を使用する方が良いです。 + +```python +POOL_ABI = [ + { "name": "slot0", ... }, + { "name": "token0", ... }, + { "name": "token1", ... }, +] + +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... } +] +``` + +これらは、私たちが連絡する必要のある2つのコントラクトの[ABI](https://docs.soliditylang.org/en/latest/abi-spec.html)です。 コードを簡潔に保つため、呼び出す必要のある関数のみを含めます。 + +```python +w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) +``` + +[`Web3`](https://web3py.readthedocs.io/en/stable/quickstart.html#remote-providers)ライブラリを初期化し、イーサリアムノードに接続します。 + +```python +@dataclass(frozen=True) +class ERC20Token: + address: str + symbol: str + decimals: int + contract: Contract +``` + +これはPythonでデータクラスを作成する方法の一つです。 [`Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html)データ型は、コントラクトへの接続に使用されます。 `(frozen=True)`に注意してください。 Pythonでは、[ブール値](https://en.wikipedia.org/wiki/Boolean_data_type)は`True`または`False`として定義され、大文字で始まります。 このデータクラスは`frozen`(フリーズ)されており、フィールドを変更できないことを意味します。 + +インデントに注意してください。 [C派生言語](https://en.wikipedia.org/wiki/List_of_C-family_programming_languages)とは対照的に、Pythonはインデントを使用してブロックを示します。 Pythonインタープリタは、次の定義がデータクラスのフィールドと同じインデントで始まっていないため、このデータクラスの一部ではないことを認識します。 + +```python +@dataclass(frozen=True) +class PoolInfo: + address: str + token0: ERC20Token + token1: ERC20Token + contract: Contract + asset: str + decimal_factor: Decimal = 1 +``` + +[`Decimal`](https://docs.python.org/3/library/decimal.html)型は、小数を正確に扱うために使用されます。 + +```python + def get_price(self, block: int) -> Decimal: +``` + +これはPythonで関数を定義する方法です。 定義はインデントされており、まだ`PoolInfo`の一部であることを示しています。 + +データクラスの一部である関数では、最初のパラメータは常に`self`であり、ここで呼び出されたデータクラスのインスタンスです。 ここにはもう1つのパラメータ、ブロック番号があります。 + +```python + assert block <= w3.eth.block_number, "ブロックは未来にあります" +``` + +もし未来を読むことができれば、取引にAIは必要ありません。 + +```python + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) +``` + +Web3からEVM上の関数を呼び出す構文は、`.functions.().call()`です。 パラメータは、EVM関数のパラメータ(もしあればですが、ここにはありません)、またはブロックチェーンの動作を変更するための[名前付きパラメータ](https://en.wikipedia.org/wiki/Named_parameter)にすることができます。 ここでは、`block_identifier`を使用して、実行したい[ブロック番号](/developers/docs/apis/json-rpc/#default-block)を指定します。 + +結果は[この構造体で、配列形式](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol#L56-L72)です。 最初の値は、2つのトークン間の為替レートの関数です。 + +```python + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 +``` + +オンチェーンでの計算を減らすため、Uniswap v3は実際の為替係数ではなく、その平方根を保存します。 EVMは浮動小数点演算や分数をサポートしていないため、実際の値の代わりに、応答はprice296となります + +```python + # (token0あたりのtoken1) + return 1/(raw_price * self.decimal_factor) +``` + +取得する生の価格は、`token1`ごとに取得できる`token0`の数です。 我々のプールでは、`token0`はUSDC(米ドルと同じ価値を持つステーブルコイン)であり、`token1`は[WETH](https://opensea.io/learn/blockchain/what-is-weth)です。 私たちが本当に欲しい値は、WETHあたりのドル数であり、その逆数ではありません。 + +小数係数は、2つのトークンの[小数係数](https://docs.openzeppelin.com/contracts/4.x/erc20#a-note-on-decimals)間の比率です。 + +```python +@dataclass(frozen=True) +class Quote: + timestamp: str + price: Decimal + asset: str +``` + +このデータクラスは、特定の時点での特定の資産の価格である見積もりを表します。 この時点では、単一のプールを使用しているため資産も単一であり、`asset`フィールドは無関係です。 しかし、後でさらに資産を追加します。 + +```python +def read_token(address: str) -> ERC20Token: + token = w3.eth.contract(address=address, abi=ERC20_ABI) + symbol = token.functions.symbol().call() + decimals = token.functions.decimals().call() + + return ERC20Token( + address=address, + symbol=symbol, + decimals=decimals, + contract=token + ) +``` + +この関数はアドレスを受け取り、そのアドレスにあるトークンコントラクトに関する情報を返します。 新しい[Web3 `Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html)を作成するには、アドレスとABIを`w3.eth.contract`に提供します。 + +```python +def read_pool(address: str) -> PoolInfo: + pool_contract = w3.eth.contract(address=address, abi=POOL_ABI) + token0Address = pool_contract.functions.token0().call() + token1Address = pool_contract.functions.token1().call() + token0 = read_token(token0Address) + token1 = read_token(token1Address) + + return PoolInfo( + address=address, + asset=f"{token1.symbol}/{token0.symbol}", + token0=token0, + token1=token1, + contract=pool_contract, + decimal_factor=Decimal(10) ** Decimal(token0.decimals - token1.decimals) + ) +``` + +この関数は、[特定のプール](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol)について必要なすべてを返します。 `f""`という構文は[フォーマット済み文字列](https://docs.python.org/3/reference/lexical_analysis.html#f-strings)です。 + +```python +def get_quote(pool: PoolInfo, block_number: int = None) -> Quote: +``` + +`Quote`オブジェクトを取得します。 `block_number`のデフォルト値は`None`(値なし)です。 + +```python + if block_number is None: + block_number = w3.eth.block_number +``` + +ブロック番号が指定されなかった場合、最新のブロック番号である`w3.eth.block_number`を使用します。 これは[`if`ステートメント](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement)の構文です。 + +デフォルトを単に`w3.eth.block_number`に設定する方が良いように見えるかもしれませんが、それは関数が定義された時点のブロック番号になってしまうため、うまく機能しません。 長時間実行されるエージェントでは、これが問題になります。 + +```python + block = w3.eth.get_block(block_number) + price = pool.get_price(block_number) + return Quote( + timestamp=datetime.fromtimestamp(block.timestamp, timezone.utc).isoformat(), + price=price.quantize(Decimal("0.01")), + asset=pool.asset + ) +``` + +[`datetime`ライブラリ](https://docs.python.org/3/library/datetime.html)を使用して、人間や大規模言語モデル(LLM)が読み取れる形式にフォーマットします。 [`Decimal.quantize`](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize)を使用して、値を小数点以下2桁に丸めます。 + +```python +def get_quotes(pool: PoolInfo, start_block: int, end_block: int, step: int) -> list[Quote]: +``` + +Pythonでは、`list[]`を使用して、特定の型のみを含むことができる[リスト](https://docs.python.org/3/library/stdtypes.html#typesseq-list)を定義します。 + +```python + quotes = [] + for block in range(start_block, end_block + 1, step): +``` + +Pythonでは、[`for`ループ](https://docs.python.org/3/tutorial/controlflow.html#for-statements)は通常、リストを反復処理します。 見積もりを検索するブロック番号のリストは、[`range`](https://docs.python.org/3/library/stdtypes.html#range)から取得します。 + +```python + quote = get_quote(pool, block) + quotes.append(quote) + return quotes +``` + +各ブロック番号について、`Quote`オブジェクトを取得し、それを`quotes`リストに追加します。 その後、そのリストを返します。 + +```python +pool = read_pool(WETHUSDC_ADDRESS) +quotes = get_quotes( + pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) + +pprint(quotes) +``` + +これはスクリプトのメインコードです。 プール情報を読み取り、12の見積もりを取得し、[`pprint`](https://docs.python.org/3/library/pprint.html#pprint.pprint)でそれらを表示します。 + +### プロンプトの作成 {#prompt} + +次に、この見積もりリストをLLMのプロンプトに変換し、予想される将来価値を取得する必要があります。 + +```sh +git checkout 03-create-prompt +uv run agent.py +``` + +出力は、次のようなLLMへのプロンプトになります。 + +``` +以下の見積もりを前提として: +Asset: WETH/USDC + 2026-01-20T16:34 3016.21 + . + . + . + 2026-02-01T17:49 2299.10 + +Asset: WBTC/WETH + 2026-01-20T16:34 29.84 + . + . + . + 2026-02-01T17:50 33.46 + + +2026-02-02T17:56の時点でWETH/USDCの値はいくらになると予想しますか? + +回答は、他のテキストを含まず、小数点以下2桁に丸めた単一の数値として提供してください。 +``` + +ここには、`WETH/USDC`と`WBTC/WETH`の2つの資産の見積もりがあることに注意してください。 別の資産からの見積もりを追加すると、予測精度が向上する可能性があります。 + +#### プロンプトの構成 {#prompt-explanation} + +このプロンプトには、LLMプロンプトで非常に一般的な3つのセクションが含まれています。 + +1. 情報。 LLMはトレーニングから多くの情報を持っていますが、通常は最新の情報を持っていません。 これが、ここで最新の見積もりを取得する必要がある理由です。 プロンプトに情報を追加することは、[検索拡張生成(RAG)](https://en.wikipedia.org/wiki/Retrieval-augmented_generation)と呼ばれます。 + +2. 実際の質問。 これが私たちが知りたいことです。 + +3. 出力フォーマットの指示。 通常、LLMは、どのようにしてその見積もりに至ったかの説明とともに、見積もりを提供します。 これは人間にとっては良いことですが、コンピュータプログラムには最終的な結果だけが必要です。 + +#### コードの説明 {#prompt-code} + +これが新しいコードです。 + +```python +from datetime import datetime, timezone, timedelta +``` + +LLMに見積もりを依頼したい時間を提供する必要があります。 将来の「n分/時間/日」後の時間を取得するには、[`timedelta`クラス](https://docs.python.org/3/library/datetime.html#datetime.timedelta)を使用します。 + +```python +# 読み取っているプールのアドレス +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +WETHWBTC_ADDRESS = Web3.to_checksum_address("0xCBCdF9626bC03E24f779434178A73a0B4bad62eD") +``` + +読み取る必要のある2つのプールがあります。 + +```python +@dataclass(frozen=True) +class PoolInfo: + . + . + . + reverse: bool = False + + def get_price(self, block: int) -> Decimal: + assert block <= w3.eth.block_number, "Block is in the future" + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 # (token1 per token0) + if self.reverse: + return 1/(raw_price * self.decimal_factor) + else: + return raw_price * self.decimal_factor +``` + +WETH/USDCプールでは、`token1`(WETH)を1つ購入するために必要な`token0`(USDC)の数を知りたいです。 WETH/WBTCプールでは、`token0`(WBTC、ラップされたビットコイン)を1つ購入するために必要な`token1`(WETH)の数を知りたいです。 プールの比率を逆にする必要があるかどうかを追跡する必要があります。 + +```python +def read_pool(address: str, reverse: bool = False) -> PoolInfo: + . + . + . + + return PoolInfo( + . + . + . + + asset= f"{token1.symbol}/{token0.symbol}" if reverse else f"{token0.symbol}/{token1.symbol}", + reverse=reverse + ) +``` + +プールを逆にする必要があるかどうかを知るには、それを`read_pool`への入力として取得します。 また、資産シンボルも正しく設定する必要があります。 + +`
if else `という構文は、Pythonにおける[三項条件演算子](https://en.wikipedia.org/wiki/Ternary_conditional_operator)に相当し、C派生言語では ` ? : `となります。 + +```python +def format_quotes(quotes: list[Quote]) -> str: + result = f"Asset: {quotes[0].asset}\n" + for quote in quotes: + result += f"\t{quote.timestamp[0:16]} {quote.price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)}\n" + return result +``` + +この関数は、`Quote`オブジェクトのリストをフォーマットする文字列を構築します。それらがすべて同じ資産に適用されることを前提としています。 + +```python +def make_prompt(quotes: list[list[Quote]], expected_time: str, asset: str) -> str: + return f""" +``` + +Pythonでは、[複数行の文字列リテラル](https://www.w3schools.com/python/gloss_python_multi_line_strings.asp)は`"""` ....と書かれます。 `"""`。 + +```python +Given these quotes: +{ + functools.reduce(lambda acc, q: acc + '\n' + q, + map(lambda q: format_quotes(q), quotes)) +} +``` + +ここでは、[MapReduce](https://en.wikipedia.org/wiki/MapReduce)パターンを使用して、各見積もりリストに対して`format_quotes`で文字列を生成し、それらをプロンプトで使用する単一の文字列に縮小します。 + +```python +What would you expect the value for {asset} to be at time {expected_time}? + +Provide your answer as a single number rounded to two decimal places, +without any other text. + """ +``` + +プロンプトの残りの部分は期待通りです。 + +```python +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +2つのプールを確認し、両方から見積もりを取得します。 + +```python +future_time = (datetime.now(timezone.utc) + timedelta(days=1)).isoformat()[0:16] + +print(make_prompt(wethusdc_quotes + wethwbtc_quotes, future_time, wethusdc_pool.asset)) +``` + +見積もりを依頼したい将来の時点を決定し、プロンプトを作成します。 + +### LLMとのインターフェース {#interface-llm} + +次に、実際のLLMにプロンプトを出し、予想される将来価値を受け取ります。 このプログラムはOpenAIを使用して作成したため、異なるプロバイダを使用する場合は調整する必要があります。 + +1. [OpenAIアカウント](https://auth.openai.com/create-account)を取得する + +2. [アカウントに資金を供給する](https://platform.openai.com/settings/organization/billing/overview)—執筆時点での最低額は5ドルです + +3. [APIキーを作成する](https://platform.openai.com/settings/organization/api-keys) + +4. コマンドラインで、プログラムが使用できるようにAPIキーをエクスポートします + + ```sh + export OPENAI_API_KEY=sk- + ``` + +5. エージェントをチェックアウトして実行する + + ```sh + git checkout 04-interface-llm + uv run agent.py + ``` + +これが新しいコードです。 + +```python +from openai import OpenAI + +open_ai = OpenAI() # クライアントはOPENAI_API_KEY環境変数を読み取ります +``` + +OpenAI APIをインポートしてインスタンス化します。 + +```python +response = open_ai.chat.completions.create( + model="gpt-4-turbo", + messages=[ + {"role": "user", "content": prompt} + ], + temperature=0.0, + max_tokens=16, +) +``` + +OpenAI API (`open_ai.chat.completions.create`)を呼び出して応答を作成します。 + +```python +expected_price = Decimal(response.choices[0].message.content.strip()) +current_price = wethusdc_quotes[-1].price + +print ("Current price:", wethusdc_quotes[-1].price) +print(f"In {future_time}, expected price: {expected_price} USD") + +if (expected_price > current_price): + print(f"Buy, I expect the price to go up by {expected_price - current_price} USD") +else: + print(f"Sell, I expect the price to go down by {current_price - expected_price} USD") +``` + +価格を出力し、買いまたは売りの推奨を提供します。 + +#### 予測のテスト {#testing-the-predictions} + +予測を生成できるようになったので、履歴データを使用して、有用な予測を生成できるかどうかを評価することもできます。 + +```sh +uv run test-predictor.py +``` + +期待される結果は次のようになります。 + +``` +2026-01-05T19:50の予測: 予測値 3138.93 USD、実績値 3218.92 USD、誤差 79.99 USD +2026-01-06T19:56の予測: 予測値 3243.39 USD、実績値 3221.08 USD、誤差 22.31 USD +2026-01-07T20:02の予測: 予測値 3223.24 USD、実績値 3146.89 USD、誤差 76.35 USD +2026-01-08T20:11の予測: 予測値 3150.47 USD、実績値 3092.04 USD、誤差 58.43 USD +. +. +. +2026-01-31T22:33の予測: 予測値 2637.73 USD、実績値 2417.77 USD、誤差 219.96 USD +2026-02-01T22:41の予測: 予測値 2381.70 USD、実績値 2318.84 USD、誤差 62.86 USD +2026-02-02T22:49の予測: 予測値 2234.91 USD、実績値 2349.28 USD、誤差 114.37 USD +29回の予測における平均予測誤差: 83.87103448275862068965517241 USD +推奨あたりの平均変化: 4.787931034482758620689655172 USD +変化の標準分散: 104.42 USD +利益が出た日数: 51.72% +損失が出た日数: 48.28% +``` + +テスターのほとんどはエージェントと同じですが、ここでは新規または変更された部分を示します。 + +```python +CYCLES_FOR_TEST = 40 # バックテストでは、テストするサイクル数 + +# 大量の見積もりを取得 +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +`CYCLES_FOR_TEST`(ここでは40として指定)日分遡ります。 + +```python +# 予測を作成し、実際の履歴と照合する + +total_error = Decimal(0) +changes = [] +``` + +私たちが関心を持つ誤差には2つのタイプがあります。 1つ目の`total_error`は、予測子が犯した誤差の単純な合計です。 + +2つ目の`changes`を理解するためには、エージェントの目的を思い出す必要があります。 それはWETH/USDC比率(ETH価格)を予測することではありません。 それは売りと買いの推奨を出すことです。 現在の価格が2000ドルで、明日2010ドルと予測した場合、実際の結果が2020ドルで追加の利益を得ても気にしません。 しかし、2010ドルと予測し、その推奨に基づいてETHを購入したのに、価格が1990ドルに下落した場合は気にします。 + +```python +for index in range(0,len(wethusdc_quotes)-CYCLES_BACK): +``` + +完全な履歴(予測に使用された値と、比較対象の実世界の価値)が利用可能なケースのみを見ることができます。 これは、最新のケースが`CYCLES_BACK`前に始まったものでなければならないことを意味します。 + +```python + wethusdc_slice = wethusdc_quotes[index:index+CYCLES_BACK] + wethwbtc_slice = wethwbtc_quotes[index:index+CYCLES_BACK] +``` + +[スライス](https://www.w3schools.com/python/ref_func_slice.asp)を使用して、エージェントが使用するサンプル数と同じ数を取得します。 ここから次のセグメントまでのコードは、エージェントにある予測取得コードと同じです。 + +```python + predicted_price = Decimal(response.choices[0].message.content.strip()) + real_price = wethusdc_quotes[index+CYCLES_BACK].price + prediction_time_price = wethusdc_quotes[index+CYCLES_BACK-1].price +``` + +予測価格、実価格、予測時点の価格を取得します。 推奨が買いか売りかを判断するために、予測時点の価格が必要です。 + +```python + error = abs(predicted_price - real_price) + total_error += error + print (f"Prediction for {prediction_time}: predicted {predicted_price} USD, real {real_price} USD, error {error} USD") +``` + +誤差を計算し、合計に加えます。 + +```python + recomended_action = 'buy' if predicted_price > prediction_time_price else 'sell' + price_increase = real_price - prediction_time_price + changes.append(price_increase if recomended_action == 'buy' else -price_increase) +``` + +`changes`については、1 ETHの売買による金銭的影響を知りたいです。 したがって、まず推奨を決定し、次に実際の価格がどのように変化したか、そして推奨が利益をもたらしたか(正の変化)、または損失をもたらしたか(負の変化)を評価する必要があります。 + +```python +print (f"Mean prediction error over {len(wethusdc_quotes)-CYCLES_BACK} predictions: {total_error / Decimal(len(wethusdc_quotes)-CYCLES_BACK)} USD") + +length_changes = Decimal(len(changes)) +mean_change = sum(changes, Decimal(0)) / length_changes +print (f"Mean change per recommendation: {mean_change} USD") +var = sum((x - mean_change) ** 2 for x in changes) / length_changes +print (f"Standard variance of changes: {var.sqrt().quantize(Decimal("0.01"))} USD") +``` + +結果を報告します。 + +```python +print (f"Profitable days: {len(list(filter(lambda x: x > 0, changes)))/length_changes:.2%}") +print (f"Losing days: {len(list(filter(lambda x: x < 0, changes)))/length_changes:.2%}") +``` + +[`filter`](https://www.w3schools.com/python/ref_func_filter.asp)を使用して、利益が出た日数と損失が出た日数を数えます。 結果はフィルターオブジェクトであり、長さを取得するにはリストに変換する必要があります。 + +### トランザクションの送信 {#submit-txn} + +次に、実際にトランザクションを送信する必要があります。 しかし、システムが証明される前のこの時点では、実際のお金を使いたくありません。 代わりに、メインネットのローカルフォークを作成し、そのネットワークで「取引」します。 + +ローカルフォークを作成し、取引を有効にする手順は次のとおりです。 + +1. [Foundry](https://getfoundry.sh/introduction/installation)をインストールする + +2. [`anvil`](https://getfoundry.sh/anvil/overview)を起動する + + ```sh + anvil --fork-url https://eth.drpc.org --block-time 12 + ``` + + `anvil`はFoundryのデフォルトURLであるhttp://localhost:8545でリッスンしているため、ブロックチェーンを操作するために使用する[`cast`コマンド](https://getfoundry.sh/cast/overview)のURLを指定する必要はありません。 + +3. `anvil`で実行すると、ETHを持つ10個のテストアカウントがあります—最初の1つの環境変数を設定します + + ```sh + PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ADDRESS=`cast wallet address $PRIVATE_KEY` + ``` + +4. これらは使用する必要のあるコントラクトです。 [`SwapRouter`](https://github.com/Uniswap/v3-periphery/blob/main/contracts/SwapRouter.sol)は、実際に取引に使用するUniswap v3コントラクトです。 プールを通じて直接取引することもできますが、こちらの方がはるかに簡単です。 + + 下の2つの変数は、WETHとUSDCの間でスワップするために必要なUniswap v3のパスです。 + + ```sh + WETH_ADDRESS=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + USDC_ADDRESS=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + POOL_ADDRESS=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 + SWAP_ROUTER=0xE592427A0AEce92De3Edee1F18E0157C05861564 + WETH_TO_USDC=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + USDC_TO_WETH=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + ``` + +5. 各テストアカウントには10,000 ETHがあります。 WETHコントラクトを使用して1000 ETHをラップし、取引のために1000 WETHを取得します。 + + ```sh + cast send $WETH_ADDRESS "deposit()" --value 1000ether --private-key $PRIVATE_KEY + ``` + +6. `SwapRouter`を使用して500 WETHをUSDCに取引します。 + + ```sh + cast send $WETH_ADDRESS "approve(address,uint256)" $SWAP_ROUTER 500ether --private-key $PRIVATE_KEY + MAXINT=`cast max-int uint256` + cast send $SWAP_ROUTER \ + "exactInput((bytes,address,uint256,uint256,uint256))" \ + "($WETH_TO_USDC,$ADDRESS,$MAXINT,500ether,1000000)" \ + --private-key $PRIVATE_KEY + ``` + + `approve`呼び出しは、`SwapRouter`が私たちのトークンの一部を使うことを許可するアローワンスを作成します。 コントラクトはイベントを監視できないため、トークンを`SwapRouter`コントラクトに直接転送しても、支払われたことを認識しません。 代わりに、`SwapRouter`コントラクトが一定額を使用することを許可し、その後`SwapRouter`がそれを行います。 これは`SwapRouter`によって呼び出される関数を介して行われるため、成功したかどうかを知ることができます。 + +7. 両方のトークンが十分にあることを確認します。 + + ```sh + cast call $WETH_ADDRESS "balanceOf(address)" $ADDRESS | cast from-wei + echo `cast call $USDC_ADDRESS "balanceOf(address)" $ADDRESS | cast to-dec`/10^6 | bc + ``` + +WETHとUSDCが手に入ったので、実際にエージェントを実行できます。 + +```sh +git checkout 05-trade +uv run agent.py +``` + +出力は次のようになります。 + +``` +(ai-trading-agent) qbzzt@Ori-Cloudnomics:~/260215-ai-agent$ uv run agent.py +現在価格: 1843.16 +2026-02-06T23:07時点での予測価格: 1724.41 USD +取引前の勘定残高: +USDC残高: 927301.578272 +WETH残高: 500 +売り、価格が118.75 USD下落すると予想します +承認トランザクション送信済み: 74e367ddbb407c1aaf567d87aa5863049991b1d2aa092b6b85195d925e2bd41f +承認トランザクションがマイニングされました。 +売りトランザクション送信済み: fad1bcf938585c9e90364b26ac7a80eea9efd34c37e5db81e58d7655bcae28bf +売りトランザクションがマイニングされました。 +取引後の勘定残高: +USDC残高: 929143.797116 +WETH残高: 499 +``` + +実際に使用するには、いくつかの小さな変更が必要です。 + +- 14行目で、`MAINNET_URL`を`https://eth.drpc.org`などの実際のアクセスポイントに変更します +- 28行目で、`PRIVATE_KEY`を自分の秘密鍵に変更します +- 非常に裕福で、未証明のエージェントのために毎日1 ETHを売買できる場合を除き、29行目を変更して`WETH_TRADE_AMOUNT`を減らすことをお勧めします + +#### コードの説明 {#trading-code} + +これが新しいコードです。 + +```python +SWAP_ROUTER_ADDRESS=Web3.to_checksum_address("0xE592427A0AEce92De3Edee1F18E0157C05861564") +WETH_TO_USDC=bytes.fromhex("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") +USDC_TO_WETH=bytes.fromhex("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +``` + +ステップ4で使用したのと同じ変数です。 + +```python +WETH_TRADE_AMOUNT=1 +``` + +取引する量。 + +```python +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... }, + { "name": "balanceOf", ...}, + { "name": "approve", ...} +] +``` + +実際に取引するには、`approve`関数が必要です。 また、前後の残高を表示したいため、`balanceOf`も必要です。 + +```python +SWAP_ROUTER_ABI = [ + { "name": "exactInput", ...}, +] +``` + +`SwapRouter` ABIでは、`exactInput`だけが必要です。 関連する関数として`exactOutput`があり、これを使用して正確に1 WETHを購入できますが、簡単にするために両方のケースで`exactInput`のみを使用します。 + +```python +account = w3.eth.account.from_key(PRIVATE_KEY) +swap_router = w3.eth.contract( + address=SWAP_ROUTER_ADDRESS, + abi=SWAP_ROUTER_ABI +) +``` + +[`account`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html)と`SwapRouter`コントラクトのWeb3定義です。 + +```python +def txn_params() -> dict: + return { + "from": account.address, + "value": 0, + "gas": 300000, + "nonce": w3.eth.get_transaction_count(account.address), + } +``` + +トランザクションパラメータ。 [ノンス](https://en.wikipedia.org/wiki/Cryptographic_nonce)は毎回変更する必要があるため、ここでは関数が必要です。 + +```python +def approve_token(contract: Contract, amount: int): +``` + +`SwapRouter`のトークンアローワンスを承認します。 + +```python + txn = contract.functions.approve(SWAP_ROUTER_ADDRESS, amount).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) +``` + +これがWeb3でトランザクションを送信する方法です。 まず、[`Contract`オブジェクト](https://web3py.readthedocs.io/en/stable/web3.contract.html)を使用してトランザクションを構築します。 次に、[`web3.eth.account.sign_transaction`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-contract-transaction)を使用して、`PRIVATE_KEY`でトランザクションに署名します。 最後に、[`w3.eth.send_raw_transaction`](https://web3py.readthedocs.io/en/stable/transactions.html#chapter-2-w3-eth-send-raw-transaction)を使用してトランザクションを送信します。 + +```python + print(f"Approve transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Approve transaction mined.") +``` + +[`w3.eth.wait_for_transaction_receipt`](https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.wait_for_transaction_receipt)は、トランザクションがマイニングされるまで待機します。 必要に応じてレシートを返します。 + +```python +SELL_PARAMS = { + "path": WETH_TO_USDC, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": WETH_TRADE_AMOUNT * 10 ** wethusdc_pool.token1.decimals, + "amountOutMinimum": 0, +} +``` + +これらはWETHを売るときのパラメータです。 + +```python +def make_buy_params(quote: Quote) -> dict: + return { + "path": USDC_TO_WETH, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": int(quote.price*WETH_TRADE_AMOUNT) * 10**wethusdc_pool.token0.decimals, + "amountOutMinimum": 0, + } +``` + +`SELL_PARAMS`とは対照的に、購入パラメータは変更される可能性があります。 入力額は、`quote`で利用可能な1 WETHのコストです。 + +```python +def buy(quote: Quote): + buy_params = make_buy_params(quote) + approve_token(wethusdc_pool.token0.contract, buy_params["amountIn"]) + txn = swap_router.functions.exactInput(buy_params).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Buy transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Buy transaction mined.") + + +def sell(): + approve_token(wethusdc_pool.token1.contract, + WETH_TRADE_AMOUNT * 10**wethusdc_pool.token1.decimals) + txn = swap_router.functions.exactInput(SELL_PARAMS).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Sell transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Sell transaction mined.") +``` + +`buy()`関数と`sell()`関数はほぼ同じです。 まず`SwapRouter`に十分なアローワンスを承認し、次に正しいパスと金額でそれを呼び出します。 + +```python +def balances(): + token0_balance = wethusdc_pool.token0.contract.functions.balanceOf(account.address).call() + token1_balance = wethusdc_pool.token1.contract.functions.balanceOf(account.address).call() + + print(f"{wethusdc_pool.token0.symbol} Balance: {Decimal(token0_balance) / Decimal(10 ** wethusdc_pool.token0.decimals)}") + print(f"{wethusdc_pool.token1.symbol} Balance: {Decimal(token1_balance) / Decimal(10 ** wethusdc_pool.token1.decimals)}") +``` + +両方の通貨でのユーザー残高を報告します。 + +```python +print("取引前の勘定残高:") +balances() + +if (expected_price > current_price): + print(f"買い、価格が{expected_price - current_price} USD上昇すると予想します") + buy(wethusdc_quotes[-1]) +else: + print(f"売り、価格が{current_price - expected_price} USD下落すると予想します") + sell() + +print("取引後の勘定残高:") +balances() +``` + +このエージェントは現在一度しか動作しません。 ただし、[`crontab`](https://man7.org/linux/man-pages/man1/crontab.1.html)から実行するか、368〜400行をループでラップし、[`time.sleep`](https://docs.python.org/3/library/time.html#time.sleep)を使用して次のサイクルまで待機することで、継続的に動作するように変更できます。 + +## 改善の可能性 {#improvements} + +これは完全な製品版ではありません。基本を教えるための単なる例です。 改善のためのいくつかのアイデアを以下に示します。 + +### よりスマートな取引 {#smart-trading} + +エージェントが何をするかを決定する際に無視している2つの重要な事実があります。 + +- _予想される変化の大きさ_。 エージェントは、下落の大きさに関係なく、価格が下落すると予想される場合に固定量の`WETH`を売却します。 + おそらく、軽微な変化は無視し、価格がどれだけ下落すると予想されるかに基づいて売却する方が良いでしょう。 +- _現在のポートフォリオ_。 ポートフォリオの10%がWETHで、価格が上がると考えている場合、さらに購入するのは理にかなっています。 しかし、ポートフォリオの90%がWETHである場合、十分にエクスポージャーがあり、さらに購入する必要はありません。 価格が下がると予想される場合は、その逆が当てはまります。 + +### 取引戦略を秘密にしたい場合はどうしますか? {#secret} + +AIベンダーは、あなたが彼らのLLMに送信するクエリを見ることができ、これによりあなたがエージェントで開発した天才的な取引システムが公開される可能性があります。 あまりにも多くの人が使用する取引システムは、あなたが買いたいときに多くの人が買おうとし(価格が上がる)、売りたいときに多くの人が売ろうとする(価格が下がる)ため、価値がありません。 + +この問題を回避するために、例えば[LM-Studio](https://lmstudio.ai/)を使用して、LLMをローカルで実行できます。 + +### AIボットからAIエージェントへ {#bot-to-agent} + +これが[AIエージェントではなくAIボットである](/ai-agents/#ai-agents-vs-ai-bots)という正当な主張ができます。 事前定義された情報に依存する、比較的単純な戦略を実装しています。 例えば、Uniswap v3プールのリストとその最新の値を提供し、どの組み合わせが最も予測価値が高いかを尋ねることで、自己改善を可能にすることができます。 + +### スリッページ保護 {#slippage-protection} + +現在、[スリッページ保護](https://uniswapv3book.com/milestone_3/slippage-protection.html)はありません。 現在の見積もりが2000ドルで、予想価格が2100ドルの場合、エージェントは購入します。 しかし、エージェントが購入する前にコストが2200ドルに上昇した場合、もはや購入する意味はありません。 + +スリッページ保護を実装するには、[`agent.py`](https://github.com/qbzzt/260215-ai-agent/blob/05-trade/agent.py#L325)の325行目と334行目で`amountOutMinimum`値を指定します。 + +## 結論 {#conclusion} + +うまくいけば、これでAIエージェントを始めるのに十分な知識が得られたはずです。 これはこの主題の包括的な概要ではありません。それには全書が捧げられていますが、これは始めるのに十分です。 健闘を祈ります! + +[私の他の作品はこちらでご覧いただけます](https://cryptodocguy.pro/). diff --git a/public/content/translations/ja/developers/tutorials/hello-world-smart-contract-fullstack/index.md b/public/content/translations/ja/developers/tutorials/hello-world-smart-contract-fullstack/index.md index af8028cd846..bfefde2c09d 100644 --- a/public/content/translations/ja/developers/tutorials/hello-world-smart-contract-fullstack/index.md +++ b/public/content/translations/ja/developers/tutorials/hello-world-smart-contract-fullstack/index.md @@ -240,7 +240,7 @@ npm install dotenv --save - 秘密鍵をエクスポートするための[これらの手順](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key)に従ってください - HTTP Alchemy API URLを取得するには、以下を参照してください -![](./get-alchemy-api-key.gif) +![Alchemy API キーを取得するためのアニメーション ウォークスルー](./get-alchemy-api-key.gif) `.env`は次のようになります: diff --git a/public/content/translations/ja/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md b/public/content/translations/ja/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md index bbb909695df..c0d2b583b31 100644 --- a/public/content/translations/ja/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md +++ b/public/content/translations/ja/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md @@ -62,13 +62,13 @@ FROM temp_table #### Etherscan {#etherscan} -![](./etherscan_view.png) +![Etherscan トランザクション エクスプローラー ビューのスクリーンショット](./etherscan_view.png) [Blockscout上のEFのコントラクトページ。](https://eth.blockscout.com/address/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe) #### Dune Analytics {#dune-analytics} -![](./dune_view.png) +![Dune Analytics クエリ ダッシュボードのスクリーンショット](./dune_view.png) ダッシュボードは[こちら](https://dune.com/paulapivat/Learn-Ethereum)にあります。 テーブルをクリックすると、クエリを確認できます(上記も参照してください)。 @@ -146,7 +146,7 @@ ORDER BY block_time DESC` DuneでのSQL出力はこちらです: -![](./list_of_txn.png) +![Ethereum トランザクションのリストのスクリーンショット](./list_of_txn.png) この1つのブロックがチェーンに追加されると、イーサリアム仮想マシン([EVM](/developers/docs/evm/))の状態が変化します。 一度に数十、時には数百ものトランザクションが検証されます。 このブロックの場合、222件のトランザクションが含まれていました。 @@ -165,7 +165,7 @@ FROM temp_table ブロック12396854では、計222件のトランザクションのうち、204件が正常に検証されました: -![](./successful_txn.png) +![成功したイーサリアムトランザクションのスクリーンショット](./successful_txn.png) トランザクションリクエストは毎秒数十回発生しますが、ブロックがコミットされるのはおよそ15秒に1回です([ソース](/developers/docs/blocks/))。 @@ -173,11 +173,11 @@ FROM temp_table イーサリアムで1日あたりに生成されたブロック数(2016年〜現在)のグラフはこちらです: -![](./daily_blocks.png) +![毎日のイーサリアムブロック生成を示すグラフ](./daily_blocks.png) この期間に毎日生成されたブロックの平均数は約5,874です: -![](./avg_daily_blocks.png) +![毎日のイーサリアムブロック生成を示すグラフ](./avg_daily_blocks.png) クエリは、次のように行います。 @@ -214,7 +214,7 @@ FROM temp_table ブロックのガスリミットを理解する一つの方法として、トランザクションをバッチ処理するために利用できるブロックスペースの**供給**量と考えることができます。 ブロックのガスリミットは、クエリを実行して2016年から現在までを可視化できます: -![](./avg_gas_limit.png) +![時間の経過に伴うイーサリアムの平均ガス制限を示すグラフ](./avg_gas_limit.png) ```sql SELECT @@ -227,7 +227,7 @@ OFFSET 1 そして、イーサリアムチェーン上での計算(トランザクションの送信、スマートコントラクトの呼び出し、NFTのミントなど)の支払いに毎日使用される実際のガスがあります。 これは、利用可能なイーサリアムのブロックスペースに対する**需要**です: -![](./daily_gas_used.png) +![毎日使用されるイーサリアムガスを示すグラフ](./daily_gas_used.png) ```sql SELECT @@ -246,7 +246,7 @@ OFFSET 1 最後に、イーサリアムチェーンの1日あたりの平均ガス価格をクエリすることもできますが、クエリ時間が非常に長くなるため、イーサリアム財団によってトランザクションごとに支払われた平均ガス量にクエリを絞り込みます。 -![](./ef_daily_gas.png) +![イーサリアム財団の毎日のガス使用量を示すグラフ](./ef_daily_gas.png) 長年にわたるイーサリアム財団のアドレスへのすべてのトランザクションで支払われたガス価格を見ることができます。 クエリは、次のとおりです。 diff --git a/public/content/translations/ja/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md b/public/content/translations/ja/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md index 3e1a62a595b..30b03fa4400 100644 --- a/public/content/translations/ja/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md +++ b/public/content/translations/ja/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md @@ -117,19 +117,19 @@ sudo systemctl start grafana-server Grafanaが実行されたら、`localhost:3000`でアクセスできるはずです。 お好みのブラウザでこのパスにアクセスし、デフォルトの認証情報(ユーザー: `admin`、パスワード: `admin`)でログインしてください。 プロンプトが表示されたら、デフォルトのパスワードを変更して保存してください。 -![](./grafana1.png) +![Geth モニタリング用の Grafana ダッシュボードのスクリーンショット (パネル 1)](./grafana1.png) Grafanaのホームページに転送されます。 まず、ソースデータを設定します。 左のバーにある設定アイコンをクリックし、「Data sources」を選択します。 -![](./grafana2.png) +![Geth モニタリング用の Grafana ダッシュボードのスクリーンショット (パネル 2)](./grafana2.png) まだデータソースは作成されていません。「Add data source」をクリックして定義します。 -![](./grafana3.png) +![Geth モニタリング用の Grafana ダッシュボードのスクリーンショット (パネル 3)](./grafana3.png) この設定では、「InfluxDB」を選択して続行します。 -![](./grafana4.png) +![Geth モニタリング用の Grafana ダッシュボードのスクリーンショット (パネル 4)](./grafana4.png) 同じマシンでツールを実行している場合、データソースの設定は非常に簡単です。 データベースにアクセスするには、InfluxDBのアドレスと詳細を設定する必要があります。 以下の画像を参照してください。 diff --git a/public/content/translations/ja/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/translations/ja/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index be94fd1c2f8..00000000000 --- a/public/content/translations/ja/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1145 +0,0 @@ ---- -title: "Waffleを使って、ERC-20トークンをテストする" -description: "Waffleを使用して、Solidityで書かれたスマートコントラクトをテストしたり、スマートコントラクトのマッチャーを使用する方法について学ぶ。" -author: Vladislav Starostenko -tags: - - "Waffle" - - "スマートコントラクト" - - "Solidity" - - "テスト" - - "ERC-20" -skill: intermediate -lang: ja -published: 2020-10-16 ---- - -このチュートリアルでは、以下について学びます: - -- Waffleを使って、スマートコントラクトをテストする方法 -- Waffle上で、一般的なマッチャーを使ってスマートコントラクトをテストする方法 - -前提知識: - -- ターミナルを操作できる。 -- 新規の`JavaScript`プロジェクトを作成できる。 -- 数行の`Solidity`コードを書いたことがある。 -- いくつかのテストを`JavaScript`で作成したことがある。 -- `yarn`あるいは、JavaScriptsのパッケージインストーラである`npm`を使用したことがある。 - -上記に該当しない場合や、以下のコードを実際に作成するつもりがない方でも、容易に理解できる内容です。 - -## Waffleの簡単な紹介 {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io)は、スマートコントラクトの作成とテストのための最も先進的なライブラリです。 - -[JavaScript API](/developers/docs/apis/javascript/)であるethers-jsと連携して動作します。 - -詳細については、[Waffleのドキュメンテーション](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation)をご覧ください! - -## クイックチュートリアル {#the-quick-tutorial} - -最初に、新規の`JavaScript`または`TypeScript`プロジェクトを作成します(ここでは`TS`を使用しますが、`JS`を使用しても問題ありません)。 - -以下のような構成になります: - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## ステップ1:あなたのプロジェクトに、Waffleをインストールする([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation))。 {#step-1-install-waffle-in-your-project} - -まずはじめに、`ethereum-waffle`をインストールします。 このチュートリアルでは、次のように `yarn`を使用しますので、以下を実行すると`ethereum-waffle`がインストールされます: - -```bash - yarn add --dev ethereum-waffle -``` - -## ステップ2:スマートコントラクトを作成する([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract)) {#step-2-write-a-smart-contract} - -このチュートリアルでは、[OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol)の[ERC-20](https://openzeppelin.com)トークンを使用します。 - -`yarn`で以下を実行すると、`OpenZeppelin`がインストールされます。 - -```bash - yarn add @openzeppelin/contracts -D -``` - -次に、 `src`ディレクトリに`BasicToken.sol`コントラクトを作成します。 - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Example class - a mock class using delivering from ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## ステップ3:スマートコントラクトをコンパイルします([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract)) {#step-3-compile-your-smart-contract} - -スマートコントラクトをコンパイルするには、プロジェクトの`package.json`に以下のエントリを追加します: - -```json -{ - "scripts": { - "build": "waffle" - } -} -``` - -また、プロジェクトのメイン ディレクトリに`waffle.json`ファイルを追加します。 - -以下は、`waffle.json`の設定例です: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Waffleの設定については、[こちら](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration)をご覧ください。 - -次に、`yarn build`を実行してスマートコントラクトをコンパイルします。 - -Waffleがコントラクトをコンパイルし、JSONの出力結果を`build`ディレクトリ内に配置したことがわかります。 - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 P -``` -
- -## ステップ4:スマートコントラクトをテストする([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)) {#step-4-test-your-smart-contract} - -### ステップ 4.1:必要な依存関係をインストールします([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)) {#step-4-1} - -スマートコントラクトを作成したら、さっそくテストしましょう。 テストには、`Waffle`を使用します。 - -`Waffle`のテストは、`Mocha`と`Chai`を使用して作成します。 他のテスト環境も使用できますが、`Waffle`マッチャーは `Chai`でのみ動作します。 - -そのため、`Chai`に依存関係を追加する必要があります: - -```bash - yarn add --dev mocha chai -``` - -### ステップ4.2:テストファイルを作成する([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)) {#step-4-2} - -テストを作成するには、テストディレクトリに`BasicToken.test.ts`ファイルを作成する必要があります。 - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -トークンのデプロイには、`Waffle`の`deployContract`メソッドを使用します。 引数としては、作成したコントラクトとデフォルト残高をコンパイルしたjsonファイルである`wallet`を引き渡す必要があります。 - -`Waffle`では`wallet`を作成することもできるため、コントラクトをとても簡単にデプロイできます。 - -`wallet`の詳細については、 [こちら](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets)をご覧ください。デプロイ機能に関しては、[こちら](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts)をご覧ください。 - -それでは、ウォレット残高を確認する簡単なテストを作成してみましょう。 コントラクトのデプロイ時に1000の値を送信したため、ウォレット残高が1000トークンになっているはずですが、最初のテストではこれを確認します。 - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -テストを実行するには、 `yarn test`を使用します。 - -### ステップ4.3:イベントを出力する([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events)) {#step-4-3} - -このチュートリアルでは、`Waffle`の中で最も便利なマッチャーを紹介したいと思いますので、一番便利なものから始めましょう。 - -`Waffle`は、どのイベントが発行されたのかをテストできます。 - -このチュートリアルでは、コントラクトの`送信`メソッドをテストします。 - -このテストでは、あるウォレットから別のウォレットへの送金を行い、 `送信`イベントの呼び出しが発生したかを確認します。 - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -このマッチャーの大きな利点のひとつは、`withArgs`をテストに追加することで、どの引数がこのイベントを呼び出したのかを確認できる点です。 - -これにより、関数が正しく呼び出されたことを確認できます! - -### ステップ4.4:メッセージと共に元に戻す([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message)) {#step-4-4} - -`Waffle`では、トランザクションを元に戻す際に添付されたメッセージもテストできます。 - -ここでは、`revertedWith`マッチャーを使って確認します。 - -ウォレット残高を上回る額の送金を実行するテストを作成することができます。 その上で、同一のメッセージと共にトランザクションが元に戻されたかどうかを確認できます。 - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### ステップ4.5:トークン残高を変更する([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance)) {#step-4-5} - -`Waffle`では、ウォレット残高の変化も確認できます! - -`changeTokenBalance`マッチャーを使用して残高の変化を確認することができ、複数のアカウントを対象とする場合は`changeTokenBalances`で確認できます。 - -このマッチャーでは、`numbers`、`strings`、`BigNumbers`を残高の変更として受け取ることができますが、アドレスはウォレットまたはコントラクトとして指定する必要があります。 - -次のテストを作成してみましょう: - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -これは、1つのウォレットを対象とするテストです。 - -以下は、複数のウォレットを対象とする場合です: - -```ts -it("Send transaction changes sender and receiver balances", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalances([wallet, walletTo], [-200, 200]) -}) -``` - -このトランザクションは、コールバックとして(呼び出しの前に残高を確認する必要があります)、あるいは他のトンラザクションへの応答として受け渡すことが想定されています。 - -## お疲れ様でした! {#congratulations} - -**おめでとうございます! チュートリアルは、これで終了です。 Waffleでスマートコントラクトをテストするための最初の大きな一歩を踏み出すことができました。** - -**このチュートリアルのコードについては、[こちら](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website)でアクセスできます。** - -**`Waffle`についての詳細なドキュメンテーションは、[こちら](https://getwaffle.io)からアクセスできます。** diff --git a/public/content/translations/ja/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/ja/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 899c71a6173..00000000000 --- a/public/content/translations/ja/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,293 +0,0 @@ ---- -title: "Waffle: 動的モッキングとコントラクト呼び出しのテスト" -description: "動的モッキングとコントラクト呼び出しのテストのためのWaffle上級チュートリアル" -author: "Daniel Izdebski" -tags: [ "Waffle", "スマートコントラクト", "Solidity", "テスト", "モックアップ作成" ] -skill: intermediate -lang: ja -published: 2020-11-14 ---- - -## このチュートリアルについて {#what-is-this-tutorial-about} - -このチュートリアルでは、以下の方法を学びます: - -- 動的モッキングの使用 -- スマートコントラクト間のインタラクションをテストする - -前提知識: - -- `Solidity`で簡単なスマートコントラクトを記述する方法をすでに知っている -- `JavaScript`と`TypeScript`に精通している -- 他の`Waffle`チュートリアルを完了したか、`Waffle`についてある程度の知識がある - -## 動的モッキング {#dynamic-mocking} - -動的モッキングはなぜ便利なのでしょうか? これにより、統合テストの代わりに単体テストを作成できます。 これは何を意味するのでしょうか。 つまり、スマートコントラクトの依存関係を気にする必要がなく、完全に分離してすべてのテストを行えるということです。 その具体的な方法をご紹介します。 - -### **1. プロジェクト** {#1-project} - -始める前に、簡単なnode.jsプロジェクトを準備する必要があります。 - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# またはnpmを使用している場合 -npm init -``` - -まず、TypeScriptとテストの依存関係であるmochaとchaiを追加しましょう。 - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# またはnpmを使用している場合 -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -では、`Waffle`と`ethers`を追加しましょう: - -```bash -yarn add --dev ethereum-waffle ethers -# またはnpmを使用している場合 -npm install ethereum-waffle ethers --save-dev -``` - -これで、プロジェクトの構成は以下のようになります: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. スマートコントラクト** {#2-smart-contract} - -動的モッキングを開始するには、依存関係のあるスマートコントラクトが必要です。 ご心配なく。こちらで用意してあります。 - -これは`Solidity`で書かれた簡単なスマートコントラクトで、唯一の目的は私たちがお金持ちかどうかをチェックすることです。 ERC20トークンを使って、十分なトークンを保有しているかチェックします。 これを`./contracts/AmIRichAlready.sol`に配置してください。 - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -動的モッキングを使いたいので、ERC20全体は必要ありません。そのため、関数が1つだけのIERC20インターフェースを使用しています。 - -では、このコントラクトをビルドしましょう。 そのために`Waffle`を使用します。 まず、コンパイルオプションを指定する簡単な`waffle.json`設定ファイルを作成します。 - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -これでWaffleでコントラクトをビルドする準備ができました: - -```bash -npx waffle -``` - -簡単でしょう? `build/`フォルダに、コントラクトとインターフェースに対応する2つのファイルが作成されました。 これらは後でテストに使用します。 - -### **3. テスト** {#3-testing} - -実際のテストのために、`AmIRichAlready.test.ts`というファイルを作成しましょう。 まず、インポートを記述します。 これらは後で必要になります: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -JSの依存関係とは別に、ビルドしたコントラクトとインターフェースをインポートする必要があります: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffleはテストに`chai`を使用します。 ただし、使用する前にWaffleのマッチャーをchai自体に注入する必要があります: - -```typescript -use(solidity) -``` - -各テストの前にコントラクトの状態をリセットする`beforeEach()`関数を実装する必要があります。 まず、そこで何が必要になるかを考えてみましょう。 コントラクトをデプロイするには、ウォレットと、`AmIRichAlready`コントラクトの引数として渡すためのデプロイ済みERC20コントラクトの2つが必要です。 - -まず、ウォレットを作成します: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -次に、ERC20コントラクトをデプロイする必要があります。 ここが難しいところです。インターフェースしかありません。 ここでWaffleが助けになります。 Waffleには、インターフェースのABIのみを使用してコントラクトを作成する、魔法のような`deployMockContract()`関数があります: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -ウォレットとデプロイ済みのERC20の両方を使用して、`AmIRichAlready`コントラクトをデプロイできます: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -以上で、`beforeEach()`関数は完成です。 ここまでの`AmIRichAlready.test.ts`ファイルは以下のようになります: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -`AmIRichAlready`コントラクトの最初のテストを書きましょう。 テストでは何をすべきだと思いますか? ええ、その通りです! 私たちがお金持ちかどうかをチェックすべきですね :) - -しかし、少し待ってください。 モックコントラクトは、どの値を返すかどうやって知るのでしょうか? `balanceOf()`関数のロジックを実装していません。 ここでもWaffleが役立ちます。 モックコントラクトには、このような新しい気の利いた機能が追加されました: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -この知識をもとに、ようやく最初のテストを書くことができます: - -```typescript -it("ウォレットの保有するトークンが1,000,000未満の場合にfalseを返す", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -このテストを分解してみましょう: - -1. モックERC20コントラクトが常に999,999トークンの残高を返すように設定します。 -2. `contract.check()`メソッドが`false`を返すかどうかを確認します。 - -準備ができたので、実行してみましょう。 - -![1つのテストが合格](./test-one.png) - -テストは動作しますが、しかし... まだ改善の余地があります。 `balanceOf()`関数は常に99999を返します。 実際のコントラクトのように、関数が値を返すウォレットを指定することで改善できます: - -```typescript -it("ウォレットの保有するトークンが1,000,001未満の場合にfalseを返す", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -ここまでは、十分にお金持ちでない場合のみをテストしました。 代わりに、その逆をテストしてみましょう: - -```typescript -it("ウォレットが少なくとも1,000,001トークンを保有している場合にtrueを返す", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -テストを実行すると... - -![2つのテストが合格](test-two.png) - -...これで完了です! コントラクトは意図通りに動作しているようです :) - -## コントラクト呼び出しのテスト {#testing-contract-calls} - -これまでの作業をまとめましょう。 `AmIRichAlready`コントラクトの機能をテストし、正しく動作しているようです。 これで完了ということですよね? 必ずしもそうではありません。 Waffleを使えば、コントラクトをさらにテストすることができます。 しかし、具体的にはどうやって? Waffleには、`calledOnContract()`と`calledOnContractWith()`というマッチャーが用意されています。 これらにより、コントラクトがERC20モックコントラクトを呼び出したかどうかをチェックできます。 これらのマッチャーの1つを使用した基本的なテストは次のとおりです: - -```typescript -it("コントラクトがERC20トークンでbalanceOfを呼び出したかチェックする", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -先ほどお話ししたもう一方のマッチャーで、このテストをさらに改善することができます: - -```typescript -it("コントラクトがERC20トークンで特定のウォレットに対してbalanceOfを呼び出したかチェックする", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -テストが正しいかチェックしましょう: - -![3つのテストが合格](test-three.png) - -素晴らしい、すべてのテストに合格しました。 - -Waffleを使ったコントラクト呼び出しのテストは非常に簡単です。 そして、ここからが一番すごいところです。 これらのマッチャーは、通常のコントラクトとモックコントラクトの両方で動作します! これは、他の技術で一般的なテストライブラリのようにコードを注入するのではなく、WaffleがEVM呼び出しを記録・フィルタリングするためです。 - -## ゴール {#the-finish-line} - -おめでとうございます! これで、Waffleを使ってコントラクト呼び出しをテストし、コントラクトを動的にモックする方法がわかりました。 他にも発見すべき興味深い機能がたくさんあります。 Waffleのドキュメンテーションを深く読んでみることをお勧めします。 - -Waffleのドキュメンテーションは[こちら](https://ethereum-waffle.readthedocs.io/)でご覧いただけます。 - -このチュートリアルのソースコードは[こちら](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls)にあります。 - -こちらもおすすめのチュートリアルです: - -- [Waffleでスマートコントラクトをテストする](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/ja/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/ja/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 05fdd1a50aa..00000000000 --- a/public/content/translations/ja/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "WaffleでHardhatとethersを使って「Hello world!」と出力するチュートリアル" -description: "Hardhatとethers.jsを使って、はじめてのWaffleプロジェクトを作成する" -author: "MiZiet" -tags: - [ - "Waffle", - "スマートコントラクト", - "Solidity", - "テスト", - "Hardhat", - "ethers.js" - ] -skill: beginner -lang: ja -published: 2020-10-16 ---- - -この[Waffle](https://ethereum-waffle.readthedocs.io)チュートリアルでは、[hardhat](https://hardhat.org/)と[ethers.js](https://docs.ethers.io/v5/)を使い、シンプルな「Hello world」スマートコントラクトプロジェクトをセットアップする方法を学びます。 次に、スマートコントラクトに新しい機能を追加する方法と、Waffleでそれをテストする方法を学びます。 - -まず、新しいプロジェクトを作成することから始めましょう: - -```bash -yarn init -``` - -または - -```bash -npm init -``` - -そして、必要なパッケージをインストールします: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -または - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -次のステップでは、`npx hardhat`を実行して、Hardhatのサンプルプロジェクトを作成します。 - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Hardhat v2.0.3へようこそ 👷‍ - -? 何をしますか? … -❯ サンプルプロジェクトを作成する -空のhardhat.config.jsを作成する -終了 -``` - -「Create a sample project」を選択します - -プロジェクトの構成は次のようになります: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### では、これらのファイルについて見ていきましょう: {#now-lets-talk} - -- Greeter.sol - Solidityで書かれたスマートコントラクトです。 - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -このスマートコントラクトは、3つの部分に分けられます: - -1. constructor - `greeting`という名前のstring型変数を宣言します。 -2. function greet - 呼び出されたときに`greeting`を返す関数です。 -3. function setGreeting - `greeting`の値を変更できるようにする関数です。 - -- sample-test.js - テストファイルです - -```js -describe("Greeter", function () { - it("変更されると新しい挨拶を返すはず", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### 次のステップでは、コントラクトのコンパイルとテストの実行を行います: {#compiling-and-testing} - -Waffleのテストでは、Mocha (テストフレームワーク) とChai (アサーションライブラリ) を使用します。 `npx hardhat test`を実行し、次のメッセージが表示されるのを待つだけです。 - -```bash -✓ 変更されると新しい挨拶を返すはず -``` - -### ここまでは順調です。プロジェクトにもう少し複雑な機能を追加してみましょう {#adding-complexity} - -誰かが挨拶として空の文字列を追加する状況を想像してみてください。 それでは心のこもった挨拶にはなりませんよね? -そうならないようにしてみましょう: - -誰かが空の文字列を渡した場合に、Solidityの`revert`を使いたいと思います。 幸いなことに、WaffleのChaiマッチャー`to.be.revertedWith()`を使えば、この機能を簡単にテストできます。 - -```js -it("空の文字列を渡したときにリバートするはず", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -新しいテストはパスしなかったようです: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ 変更されると新しい挨拶を返すはず (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) 空の文字列を渡したときにリバートするはず - - - 1件成功 (2s) - 1件失敗 -``` - -この機能をスマートコントラクトに実装しましょう: - -```solidity -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -``` - -これで、setGreeting関数は次のようになります: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -もう一度テストを実行してみましょう: - -```bash -✓ 変更されると新しい挨拶を返すはず (1467ms) -✓ 空の文字列を渡したときにリバートするはず (276ms) - -2件成功 (2s) -``` - -おめでとうございます! やり遂げましたね :) - -### 結論 {#conclusion} - -Waffle、Hardhat、ethers.jsを使ってシンプルなプロジェクトを作成しました。 プロジェクトのセットアップ、テストの追加、新機能の実装方法を学びました。 - -スマートコントラクトをテストするための、さらに優れたChaiマッチャーについては、[Waffleの公式ドキュメント](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html)を確認してください。 diff --git a/public/content/translations/ja/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/ja/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index 01ca363fab1..00000000000 --- a/public/content/translations/ja/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: "Waffleライブラリを使用したシンプルなスマートコントラクトのテスト" -description: "初心者用チュートリアル" -author: Ewa Kowalska -tags: [ "スマートコントラクト", "Solidity", "Waffle", "テスト" ] -skill: beginner -lang: ja -published: 2021-02-26 ---- - -## このチュートリアルでは、次の方法を学びます {#in-this-tutorial-youll-learn-how-to} - -- ウォレット残高の変更をテストする -- 指定された引数を持つイベントの発行をテストする -- トランザクションがrevertされたことをアサートする - -## 前提条件 {#assumptions} - -- 新規のJavaScriptまたはTypeScriptのプロジェクトを作成できる -- JavaScriptのテストの基本的な経験がある -- yarnやnpmなどのパッケージマネージャーを使用したことがある -- スマートコントラクトおよびSolidityのごく基本的な知識を持っている - -## はじめに {#getting-started} - -このチュートリアルでは、yarnを使ったテストのセットアップと実行を実演しますが、npmがお好みであれば問題ありません。公式Waffleの[ドキュメント](https://ethereum-waffle.readthedocs.io/en/latest/index.html)への適切なリファレンスを記載します。 - -## 依存関係をインストール {#install-dependencies} - -ethereum-waffleとtypescriptの依存関係をプロジェクトの開発依存関係に[追加](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation)します。 - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## スマートコントラクトの例 {#example-smart-contract} - -このチュートリアルでは、EtherSplitterというシンプルなスマートコントラクトの例に取り組みます。 誰かがweiを送金し、それを2つの事前定義された受信者の間で均等に分割できるようにする以外に、特別な機能はありません。 -split関数ではweiの数が偶数でなければなりません。さもないと処理は取り消されます。 両方の受信者に対して、weiの送金を実行し、続いてTransferイベントを発行します。 - -`src/EtherSplitter.sol`に、EtherSplitterコードのスニペットを配置します。 - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Uneven wei amount not allowed'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## コントラクトをコンパイルする {#compile-the-contract} - -コントラクトを[コンパイル](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract)するには、package.jsonファイルに次のエントリを追加します。 - -```json -"scripts": { - "build": "waffle" - } -``` - -次に、プロジェクトのルートディレクトリにWaffleの設定ファイル (`waffle.json`) を作成し、次の設定をそこに貼り付けます。 - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -`yarn build` を実行します。 結果として、`build`ディレクトリに、コンパイルされたEtherSplitterコントラクトがJSON形式で現れます。 - -## テストのセットアップ {#test-setup} - -Waffleを使ったテストにはChaiマッチャーとMochaが必要なので、それらをプロジェクトに[追加](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)する必要があります。 package.jsonファイルを更新し、scriptsの部分に`test`エントリを追加してください。 - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -テストを[実行](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests)したい場合は、`yarn test`を実行するだけです。 - -## テスト {#testing} - -それでは、`test`ディレクトリを作成し、新しいファイル `test\EtherSplitter.test.ts`を作成してください。 -以下のスニペットをコピーして、テストファイルに貼り付けてください。 - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("イーサスプリッター", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // ここにテストを追加 -}) -``` - -始める前に、少し解説をします。 -`MockProvider`は、ブロックチェーンのモックバージョンを作成します。 また、EtherSplitterコントラクトのテストで役立つモックウォレットも提供します。 このプロバイダーで、`getWallets()`メソッドを呼び出すと最大10個までウォレットを取得することができます。 この例では、送信者用と2人の受信者用の3つのウォレットを取得します。 - -次に、「splitter」という変数を宣言します。これは、EtherSplitterコントラクトのモックです。 このモックは、単一のテストを実行する前に`deployContract`メソッドによって作成されます。 当該のメソッドは、最初のパラメータとして渡されたウォレット (この場合は送信者のウォレット) からコントラクトのデプロイメントをシミュレートします。 2番目のパラメータは、テストされるコントラクトのABIとバイトコードです。コンパイルされたEtherSplitterコントラクトのjsonファイルを`build`ディレクトリから渡します。 3番目のパラメータは、コントラクトのコンストラクタ引数を持つ配列です。この場合、2人の受信者のアドレスです。 - -## changeBalances {#changebalances} - -まず、splitメソッドによって実際に受取人のウォレットの残高が変わるかどうかを確認します。 送信者のアカウントから50 weiを分割すると、両方の受信者の残高が25 wei増えることが期待されます。 ここで、Waffleの`changeBalances`マッチャーを使います。 - -```ts -it("アカウントの残高を変更する", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -マッチャーの最初のパラメータとして、受信者のウォレットの配列を渡し、2番目のパラメータとして、対応するアカウントで予想される増加分を配列で渡します。 -特定のウォレットの残高を確認したい場合は、以下の例のように、配列を渡さなくても`changeBalance`マッチャーを使えます。 - -```ts -it("アカウントの残高を変更する", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -`changeBalance`と`changeBalances`のどちらの場合も、マッチャーが呼び出しの前後に残高の状態にアクセスする必要があるため、split関数をコールバックとして渡すことに注意してください。 - -次に、weiの各転送後にTransferイベントが発行されたかどうかをテストします。 それでは、Waffleの別のマッチャーに移ります。 - -## Emit {#emit} - -```ts -it("最初の受信者への転送時にイベントを発行する", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("2番目の受信者への転送時にイベントを発行する", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -`emit`マッチャーを使うと、メソッドの呼び出し時にコントラクトがイベントを発行したかどうかを確認できます。 `emit`マッチャーへのパラメータとして、イベントを発行することが予期されるモックコントラクトとそのイベントの名前を渡します。 この場合、モックコントラクトは`splitter`で、イベント名は`Transfer`です。 また、イベントの発行で引数の正確な値を検証することもできます。その場合、イベントの宣言で期待される数の引数を`withArgs`マッチャーに渡します。 EtherSplitterコントラクトの場合では、送金されるwei単位の金額とともに送信者と受信者のアドレスを渡します。 - -## revertedWith {#revertedwith} - -最後の例として、weiの数が奇数の場合にトランザクションが取り消されるかどうかを確認します。 ここでは、`revertedWith`マッチャーを使います。 - -```ts -it("weiの量が奇数の場合にrevertする", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Uneven wei amount not allowed" - ) -}) -``` - -このテストをパスすれば、トランザクションが実際に取り消されたことが保証されます。 ただし、`require`ステートメントで渡したメッセージと、`revertedWith`で期待しているメッセージとが完全に一致している必要があります。 EtherSplitterコントラクトのコードに戻ると、weiの量に対する`require`ステートメントで、「Uneven wei amount not allowed」というメッセージが表示されます。 これは、テストで予期されるメッセージと一致します。 それらが等しくなければ、テストは失敗します。 - -## おめでとうございます! {#congratulations} - -Waffleでスマートコントラクトをテストするための最初の大きな一歩を踏み出すことができました。 diff --git a/public/content/translations/ko/about/index.md b/public/content/translations/ko/about/index.md new file mode 100644 index 00000000000..5723d7784bf --- /dev/null +++ b/public/content/translations/ko/about/index.md @@ -0,0 +1,134 @@ +--- +title: "우리 커뮤니티에 관하여" +description: "ethereum.org의 팀, 커뮤니티와 사명에 관하여" +lang: ko +--- + +# ethereum.org 소개 {#about-ethereumorg} + +ethereum.org는 누구나 참여할 수 있는 이더리움 커뮤니티의 공개 오픈소스 리소스입니다. 저희는 사이트를 유지하고 개발하는 데 전념하는 소규모 핵심 팀으로, 전 세계 수천 명의 커뮤니티 구성원들의 기여로 운영됩니다. + +**ethereum.orgethereum.org의 누구도 당신에게 연락하지는 않을 것입니다. 답변하지 말아 주세요.** + +## 이름에 대한 참고 사항 {#a-note-on-names} + +이더리움 생태계 내에서 이름을 혼동하는 경우가 흔하며, 이로 인해 이더리움 작동 방식에 대한 잘못된 정신 모델이 생길 수 있습니다. 명확한 이해를 위한 간단한 설명은 다음과 같습니다. + +### 이더리움 {#ethereum} + +이더리움은 공개 네트워크, 블록체인, 오픈 소스 프로토콜이며, 전 세계 수만 명의 개발자, 노드 운영자, ETH 보유자 및 사용자로 구성된 글로벌 커뮤니티가 운영, 관리, 거버넌스 및 소유를 담당합니다. + +[이더리움에 대해 더 알아보기](/what-is-ethereum/) + +[이더리움 거버넌스에 대해 더 알아보기](/governance/) + +### 이더(ETH) {#ether-or-eth} + +이더(티커 심볼 ETH로도 알려져 있음)는 이더리움에서 거래되는 네이티브 통화입니다. ETH는 이더리움 네트워크 사용 비용(거래 수수료 형태)을 지불하는 데 필요합니다. ETH는 스테이킹을 통해 네트워크를 보호하는 데에도 사용됩니다. 사람들이 이더리움 가격에 대해 이야기할 때, 그들은 자산으로서의 ETH를 의미합니다. + +[ETH에 대해 더 알아보기](/what-is-ether/) + +[ETH 스테이킹에 대해 더 알아보기](/staking/) + +### 이더리움 재단 {#ethereum-foundation} + +ETH의 크라우드세일로 초기 자금을 조달한 비영리 단체로, 이더리움 네트워크와 생태계를 지원하는 데 전념합니다. + +[이더리움 재단에 대해 더 알아보기](/foundation/) + +### ethereum.org {#ethereum-org} + +이더리움 커뮤니티를 위한 공개 오픈소스 웹사이트 및 교육 참고 자료입니다. ethereum.org는 이더리움 재단의 자금 지원을 받는 소규모 핵심 팀이 이끌고 있으며, 전 세계 수천 명의 커뮤니티 구성원이 기여하고 있습니다. + +이 페이지에서는 ethereum.org에 대한 자세한 정보를 다룹니다. + +## 우리의 임무 {#our-mission} + +**ethereum.org의 임무는 성장하는 이더리움 커뮤니티를 위한 최고의 포털이 되는 것입니다** + +우리는 새로운 사용자가 이더리움과 그 핵심 개념에 익숙해지도록 돕기 위해 설계된, 이더리움과 관련된 모든 주제에 대해 이해하기 쉬운 교육 참고 자료를 구축하기 위해 노력합니다. 우리는 다음을 원합니다. + +- 이더리움을 이 기술을 새로 접한 모두에게 설명하는 것 +- 새로운 사용자들이 ETH와 이더리움을 시작하는데 도움을 주는 것 +- 새로운 개발자들의 개발 시작을 돕는 것 +- 이더리움 세계 내의 업데이트 소식 전달 +- 커뮤니티에서 만든 예제 자료 +- 이더리움 교육 자료들을 최대한 많은 언어로 공급하는 것 + +이 임무를 달성하기 위해 우리 팀은 ethereum.org에서 두 가지 주요 목표에 집중합니다: + +### 1. ethereum.org 방문자의 사용자 경험 개선 {#visitors} + +- 콘텐츠 확장, 개선 및 최신 상태 유지 +- 현지화 및 웹 개발 모범 사례를 통한 사용성 및 접근성 개선 +- 설문조사, 퀴즈, 웹3 통합과 같은 기능을 통해 사용자 참여도 증대 +- 웹사이트를 가볍고 성능이 좋게 유지 + +### 2. 기여자 커뮤니티 성장, 강화 및 역량 강화 {#community} + +- 웹사이트 전체 기여자 수 증대 +- 참여, 인정, 보상을 통한 기여자 유지율 개선 +- 커뮤니티 구성원이 점점 더 중요한 기여를 할 수 있도록 역량 강화 +- 코드, 콘텐츠, 디자인, 번역, 중재 등 기여의 다양성 증진 +- 코드베이스를 현대적이고 깨끗하며 잘 문서화되도록 유지 + +## 핵심 원칙 {#core-principles} + +우리의 임무를 달성하는 데 도움이 되는 몇 가지 핵심 원칙이 있습니다. + +### 1. ethereum.org는 이더리움으로 가는 포털입니다 🌏 {#core-principles-1} + +우리는 사용자가 관심을 갖고 그들의 질문이 답변되기를 바랍니다. 따라서 우리 포털은 정보, "마법의 순간" 및 외부에 있는 훌륭한 커뮤니티 리소스에 대한 링크를 조합해야 합니다. 우리 콘텐츠의 목적은 이미 존재하는 광범위한 리소스를 대체하는 것이 아니라 "빠른 조직 문화 적응 포털"이 되는 것입니다. 우리는 커뮤니티 구축 리소스를 지원하고 통합하여 더 많은 가시성을 제공하고 더 쉽게 검색할 수 있도록 하고자 합니다. +[이더리움의 커뮤니티](/community/)가 이 모든 것의 중심에 있습니다. 우리는 커뮤니티를 지원할 뿐만 아니라 그들과 협력하고 그들의 피드백을 통합해야 합니다. 웹사이트는 현재 우리가 가진 커뮤니티를 위한 것이 아니라 우리가 성장하기를 바라는 커뮤니티를 위한 것입니다. 우리는 다양한 언어, 지역 및 문화의 사람들이 포함된 글로벌 커뮤니티임을 기억해야 합니다. + +### 2. ethereum.org는 항상 진화하고 있습니다 🛠 {#core-principles-2} + +이더리움과 그 커뮤니티는 항상 진화 중이며, ethereum.org도 그럴 겁니다. 그래서 사이트는 간단한 디자인 시스템과 모듈식 구조를 가지고 있습니다. 우리는 사람들이 사이트를 사용하는 방법과 커뮤니티가 사이트에서 원하는 것에 대해 더 많이 알게 될 수록 점진적으로 변경합니다. +우리는 기여자 커뮤니티가 있는 오픈 소스이므로 여러분은 변경 사항을 제안하거나 우리를 도울 수도 있습니다. +[기여에 대해 알아보기](/contributing/) + +### 3. ethereum.org는 일반적인 제품 웹사이트가 아닙니다 🦄 {#core-principles-3} + +이더리움은 단순한 웹사이트보다 더 큰 가치를 추구합니다. 이는 커뮤니티, 기술, 일련의 아이디어와 이데올로기, 그리고 그 이상을 포함합니다. +이는 웹사이트가 “특정 도구를 원하는 개발자”부터 “ETH를 막 구매했지만 지갑이 무엇인지 모르는 초보자”에 이르기까지 다양한 사용자 여정을 처리해야 함을 의미합니다. +"블록체인 플랫폼을 위한 최고의 웹사이트는 무엇인가?"는 열린 질문으로 남아 있습니다. - 우리는 개척자들입니다. 이를 만드는 것은 실험을 필요로 합니다. + +## 제품 로드맵 {#roadmap} + +우리의 작업을 더 쉽게 접근할 수 있도록 하고 더 많은 커뮤니티 협업을 촉진하기 위해 ethereum.org 핵심 팀은 [shape up cycle](https://www.productplan.com/glossary/shape-up-method/) 로드맵 목표에 대한 개요를 게시합니다. + +[2025년 1주기 제품 로드맵 보기](https://github.com/ethereum/ethereum-org-website/issues/14726) + +**어떻게 생각하세요?** 저희는 항상 로드맵에 대한 피드백을 환영합니다. 저희가 작업해야 한다고 생각하는 것이 있다면 알려주세요! 우리는 커뮤니티 + +**참여하고 싶으신가요?** [기여에 대해 더 알아보기](/contributing/), [Twitter에서 저희에게 연락 주세요](https://x.com/ethdotorg), 또는 [Discord 서버](https://discord.gg/ethereum-org)에서 커뮤니티 토론에 참여하세요. + +## 디자인 원칙 {#design-principles} + +우리는 사이트의 콘텐츠 및 디자인 결정을 안내하기 위해 [디자인 원칙](/contributing/design-principles/)을 사용합니다. + +## 디자인 시스템 {#design-system} + +우리는 기능을 더 빨리 출시하고 커뮤니티 구성원이 ethereum.org의 공개 디자인에 참여할 수 있도록 [디자인 시스템](https://www.figma.com/file/NrNxGjBL0Yl1PrNrOT8G2B/ethereum.org-Design-System?node-id=0%3A1&t=QBt9RkhpPqzE3Aa6-1)을 구축하고 출시했습니다. + +참여하고 싶으신가요?[Figma에서 따라가기](https://www.figma.com/file/NrNxGjBL0Yl1PrNrOT8G2B/ethereum.org-Design-System), [GitHub 이슈](https://github.com/ethereum/ethereum-org-website/issues/6284)를 확인하고 [#design Discord 채널](https://discord.gg/ethereum-org)에서 대화에 참여하세요. + +## 스타일 가이드 {#style-guide} + +기여 과정을 더 원활하게 만들기 위해 콘텐츠 작성의 특정 측면을 표준화하는 [스타일 가이드](/contributing/style-guide/)가 있습니다. + +사이트에 [기여](/contributing/)하고 싶다면 [우리의 원칙](/contributing/design-principles/)과 [스타일 가이드](/contributing/style-guide/)를 반드시 읽어보세요. + +우리는 우리의 디자인 원칙, 디자인 시스템 및 스타일 가이드 등에 대한 피드백을 환영합니다. 기억해라, ethereum.org는 커뮤니티를 위한, 커뮤니티에 의한 커뮤니티이다. + +## 라이선스 {#license} + +ethereum.org 웹사이트는 오픈 소스이며, 별도로 명시되지 않는 한 [MIT 라이선스](https://github.com/ethereum/ethereum-org-website/blob/dev/LICENSE)에 따라 구축되었습니다. ethereum.org의 [이용 약관](/terms-of-use/)에 대해 더 알아보기. + +## 채용 공고 {#open-jobs} + +이 웹사이트는 오픈 소스이고 누구나 작업할 수 있지만 ethereum.org 및 기타 이더리움 재단 웹 프로젝트를 전담하는 팀이 있습니다. + +우리는 모든 취업 공고를 여기에 올릴 겁니다. 여기에 본인에게 맞는 역할이 보이지 않는다면 [Discord 서버](https://discord.gg/ethereum-org)로 이동하여 어떻게 함께 일하고 싶은지 알려주세요! + +ethereum.org 팀 너머를 찾고 계세요? [기타 이더리움 관련 채용 공고 확인하기](/community/get-involved/#ethereum-jobs/) diff --git a/public/content/translations/ko/ai-agents/index.md b/public/content/translations/ko/ai-agents/index.md new file mode 100644 index 00000000000..f01b021f61b --- /dev/null +++ b/public/content/translations/ko/ai-agents/index.md @@ -0,0 +1,144 @@ +--- +title: "AI 에이전트" +metaTitle: "AI 에이전트 | 이더리움의 AI 에이전트" +description: "이더리움의 AI 에이전트 개요" +lang: ko +template: use-cases +emoji: ":robot:" +sidebarDepth: 2 +image: /images/ai-agents/hero-image.png +alt: People gathered at terminal table +summaryPoint1: "블록체인과 상호작용하며 독립적으로 거래하는 AI" +summaryPoint2: "온체인 지갑과 자금을 관리" +summaryPoint3: "사람이나 다른 에이전트를 고용하여 작업을 수행" +buttons: + - content: AI 에이전트란 무엇일까요? + toId: what-are-ai-agents + - content: 에이전트 살펴보기 + toId: ai-agents-on-ethereum + isSecondary: false +--- + +AI 비서와 함께 이더리움을 탐색한다고 상상해보세요. 그 비서는 24시간 일주일 내내 온체인 시장 동향을 분석하고, 질문에 답해주고, 심지어 당신을 대신해서 거래까지 실행해줍니다. 디지털 라이프를 더 간편하게 만들어주는 지능형 시스템, AI 에이전트의 세계에 오신 것을 환영합니다. + +이더리움에는 버추얼 인플루언서, 자율 콘텐츠 제작자부터 실시간 시장 분석 플랫폼에 이르기까지 다양한 AI 에이전트 혁신 사례를 볼 수 있으며, 사용자에게 통찰력, 즐거움, 운영 효율성을 제공하여 역량을 강화합니다. + +## AI 에이전트란 무엇일까요? {#what-are-ai-agents} + +AI 에이전트는 인공지능을 사용하여 작업을 수행하거나 스스로 결정을 내리는 소프트웨어 프로그램입니다. Ai 에이전트는 데이터를 학습하고, 변화에 적응하며, 복잡한 작업을 처리합니다. Ai 에이전트는 쉬지 않고 작동하며, 기회를 즉시 감지할 수 있습니다. + +### AI 에이전트가 블록체인과 협력하는 방식 {#how-ai-agents-work-with-blockchains} + +기존 금융에서 AI 에이전트는 중앙화된 환경 위에 제한된 데이터만을 가지고 운영되는 경우가 많습니다. 이로 인해 Ai 에이전트의 학습 능력이나 자율적인 자산 관리 능력이 저하됩니다. + +반면, 이더리움의 탈중앙화된 생태계는 다음과 같은 주요 이점을 제공합니다: + +- 투명한 데이터: 블록체인 정보에 대한 실시간 접근성. +- 진정한 자산 소유권: 디지털 자산을 AI 에이전트가 완전히 소유. +- 강력한 온체인 기능: AI 에이전트가 거래를 실행하고, 스마트 계약과 상호작용하며, 유동성을 제공하고, 다양한 프로토콜 간 협업을 가능하게 함. + +이러한 요소들은 AI 에이전트를 단순한 봇에서 다양한 분야에 걸쳐 큰 가치를 제공하는 역동적이고 자기 개선이 가능한 시스템으로 탈바꿈시킵니다: + + + + + + + +## 검증 가능한 AI {#verifiable-ai} + +오프체인에서 실행되는 AI 에이전트는 종종 '블랙박스'처럼 작동하며, 이들의 추론, 입력, 출력은 독립적으로 검증될 수 없습니다. 이더리움은 이를 바꿉니다. 개발자는 에이전트의 행동을 온체인에 고정함으로써 _신뢰가 필요 없고_, _투명하며_, _경제적으로 자율적인_ 에이전트를 구축할 수 있습니다. 이러한 에이전트의 행동은 감사, 제한, 증명이 가능합니다. + +### 검증 가능한 추론 {#verifiable-inference} + +AI 추론은 전통적으로 오프체인에서 발생하며, 실행 비용은 저렴하지만 모델 실행은 불투명합니다. 이더리움에서 개발자는 여러 기술을 사용하여 에이전트를 검증 가능한 계산과 결합할 수 있습니다. + +- [**zkML(영지식 머신러닝)**](https://opengradient.medium.com/a-gentle-introduction-to-zkml-8049a0e10a04)은 에이전트가 모델이나 입력을 공개하지 않고도 모델이 올바르게 실행되었음을 증명할 수 있게 합니다. +- [**TEE(신뢰할 수 있는 실행 환경) 인증**](https://en.wikipedia.org/wiki/Trusted_execution_environment)을 통해 에이전트가 특정 모델 또는 코드 경로를 실행했다는 하드웨어 기반 증명을 할 수 있습니다. +- 온체인 불변성은 이러한 증명과 인증을 모든 계약이나 에이전트가 참조하고, 재생하며, 신뢰할 수 있도록 보장합니다. + +## x402를 사용한 결제 및 상거래 {#x402} + +이더리움 및 L2에 배포된 [x402 프로토콜](https://www.x402.org/)은 에이전트가 사람의 개입 없이 자원에 대한 비용을 지불하고 경제적으로 상호 작용할 수 있는 네이티브 방법을 제공합니다. 에이전트는 다음을 수행할 수 있습니다. + +- 스테이블코인을 사용하여 컴퓨팅, 데이터 및 API 호출 비용 지불 +- 다른 에이전트나 서비스로부터 인증 요청 또는 확인 +- 에이전트 간 상거래에 참여하여 컴퓨팅, 데이터 또는 모델 출력 구매 및 판매 + +x402는 이더리움을 자율 에이전트를 위한 프로그래밍 가능한 경제 레이어로 전환하여, 계정, 구독 또는 중앙 집중식 청구 대신 사용량 기반 지불 상호 작용을 가능하게 합니다. + +### 에이전트 금융 보안 {#agentic-finance-security} + +자율 에이전트에는 안전장치가 필요합니다. 이더리움은 지갑 및 계약 수준에서 이를 제공합니다. + +- [스마트 계정(EIP-4337)](https://eips.ethereum.org/EIPS/eip-4337)을 통해 개발자는 지출 한도, 화이트리스트, 세션 키, 세분화된 권한을 적용할 수 있습니다. +- 스마트 계약에 프로그래밍된 제약 조건은 에이전트가 할 수 있는 일을 제한할 수 있습니다. +- 추론 기반 제한(예: 고위험 작업을 실행하기 전에 zkML 증명 요구)은 또 다른 안전 레이어를 추가합니다. + +이러한 제어를 통해 자율 에이전트를 제한된 범위 내에서 배포할 수 있습니다. + +### 온체인 레지스트리: ERC-8004 {#erc-8004} + +[ERC-8004](https://eips.ethereum.org/EIPS/eip-8004)는 에이전트 신원, 기능 및 인증을 위한 온체인 레지스트리를 제안하는 새로운 표준(현재 동료 검토 중)입니다. + +채택된다면 다음을 제공할 수 있습니다. + +- 공유되고 신뢰가 필요 없는 에이전트 디렉터리 +- 표준화된 인증 형식 +- 이더리움 메인넷에 직접 '무신뢰 에이전트 인프라'를 위한 기반 + +이를 통해 에이전트는 완전히 탈중앙화된 환경에서 서로를 더 쉽게 발견하고, 검증하며, 거래할 수 있습니다. + +## 이더리움의 AI 에이전트 {#ai-agents-on-ethereum} + +우리는 이제 AI 에이전트의 잠재력을 본격적으로 탐색하기 시작했으며, 이미 여러 프로젝트들이 AI와 블록체인의 시너지를 활용하고 있습니다. 특히 투명성과 수익화 측면에서 두각을 나타내고 있습니다. + + + +루나의 첫 팟캐스트 출연 + + + +## 에이전트가 관리하는 지갑 {#agent-controlled-wallets} + +Luna나 AIXBT와 같은 에이전트는 자체 온체인 지갑([AIXBT 지갑](https://clusters.xyz/aixbt), [Luna 지갑](https://zapper.xyz/account/0x0d177181e3763b20d47dc3a72dd584368bd8bf43))을 보유하고 있어, 팬에게 팁을 주거나 경제 활동에 참여할 수 있습니다. + +루나의 X 소셜 캠페인 #LunaMuralChallenge에서 루나는 Base 지갑을 통해 우승자를 선정하여 보상했습니다. 이는 AI가 암호화폐 보상을 위해 인간을 고용한 최초의 사례입니다. + + + + +

유용한 정보

+

AI 에이전트 및 관련 도구는 아직 초기 개발 단계이며 실험적인 성격이 강하므로 사용에 주의하십시오.

+
+ +
+ +## 채팅 명령어로 지갑 제어하기 {#control-your-wallet-using-chat-commands} + +복잡한 DeFi 인터페이스를 거치지 않고 간단한 채팅 명령어로 암호화폐를 관리할 수 있습니다. + +이러한 직관적인 접근 방식은 거래를 더 빠르고 쉽게 만들 뿐만 아니라, 자금을 잘못된 주소로 보내거나 수수료를 과다하게 지불하는 등의 오류 발생 가능성을 줄여줍니다. + + + +## AI 에이전트 vs AI 봇 {#ai-agents-vs-ai-bots} + +AI 에이전트와 AI 봇은 모두 입력에 따라 자동화된 작업을 수행하기 때문에 이 둘의 구분이 다소 모호할 수 있습니다. + +- AI 봇은 자동화된 비서와 같습니다. 정해진 작업을 수행하기 위해 미리 프로그래밍된 특정 명령을 따릅니다. +- AI 에이전트는 지능형 동반자와 같습니다. 경험으로부터 배우고, 새로운 정보에 적응하며, 스스로 결정을 내립니다. + +| | AI 에이전트 | AI 봇 | +| --------- | ------------------------------------- | --------------------------- | +| **상호작용** | 복잡함, 적응성, 자율성 | 단순함, 미리 정의된 범위, 하드 코딩됨 | +| **학습** | 지속적으로 학습하고, 실험하며, 새로운 데이터에 실시간으로 적응가능 | 미리 학습된 데이터 또는 고정된 규칙에 따라 작동 | +| **작업 완료** | 더 광범위한 목표 달성을 지향 | 특정 작업에만 집중 | + +## 더 자세히 알아보기 {#dive-deeper} + + + +## 나만의 AI 에이전트를 구축해 보세요 {#you-can-build-your-own-ai-agent} + + diff --git a/public/content/translations/ko/bridges/index.md b/public/content/translations/ko/bridges/index.md index a463730b0c8..7c41d36acaa 100644 --- a/public/content/translations/ko/bridges/index.md +++ b/public/content/translations/ko/bridges/index.md @@ -1,67 +1,69 @@ --- -title: 블록체인 브리지에 대한 소개 -description: 브리지를 통해 사용자는 자금을 다른 블록체인으로 옮길 수 있음 +title: "블록체인 브리지에 대한 소개" +description: "브리지를 통해 사용자는 자금을 다른 블록체인으로 옮길 수 있음" lang: ko --- # 블록체인 브리지 {#prerequisites} -_웹3는 L1 블록체인과 L2 확장 솔루션의 생태계로 진화했으며, 각각은 고유한 기능과 장단점을 지니고 있습니다. 블록체인 프로토콜의 수가 증가함에 따라, [체인 간에 자금을 이동하기 위한 수요]() 또한 증가하고 있습니다. 이를 충족시키기 위해 브리지가 필요합니다._ +_웹3는 L1 블록체인과 L2 확장 솔루션의 생태계로 진화했으며, 각각은 고유한 기능과 장단점을 지니고 있습니다. 블록체인 프로토콜의 수가 증가함에 따라, 체인 간의 자산 이동에 대한 수요도 증가합니다.이를 충족시키기 위해 브리지가 필요합니다._ ## 브리지란 무엇인가요? {#what-are-bridges} -블록체인 브리지는 현실에서의 브리지(다리)와 비슷한 역할을 합니다. 현실에서의 브리지가 서로 다른 두 위치를 이어 주는 것처럼, 블록체인 브리지는 두 개의 블록체인 생태계를 연결합니다. 브리지는 정보와 자산을 전송하여 블록체인 간의 통신을 원활하게 합니다. +블록체인 브리지는 현실에서의 브리지(다리)와 비슷한 역할을 합니다. 현실에서의 브리지가 서로 다른 두 위치를 이어 주는 것처럼, 블록체인 브리지는 두 개의 블록체인 생태계를 연결합니다. **브리지는 정보와 자산의 이전을 통해 블록체인 간의 통신을 촉진합니다**. 다음 예시를 살펴보겠습니다. 미국에 살고 있으며 유럽 여행을 계획하고 있다고 가정해 봅시다. USD 화폐가 있지만, 여행지에서는 EUR 화폐를 사용해야 합니다. USD를 EUR로 바꾸려면 약간의 수수료를 지불하고 환전소를 이용할 수 있습니다. -그렇다면 가지고 있는 자금을 다른 블록체인의 자금으로 환전하여 사용하려면 어떻게 해야 할까요? 예를 들어 이더리움 메인넷의 ETH를 [아비트럼](https://arbitrum.io/)의 ETH로 환전하고 싶을 수 있습니다. 이러한 경우, EUR 화폐를 위한 환전소가 있었던 것처럼 이더리움에서 아비트럼으로 ETH를 이동하기 위한 메커니즘이 필요합니다. 브리지는 이러한 거래를 가능하게 합니다. 상단 예시의 경우, 아비트럼에는 메인넷의 ETH를 아비트럼으로 이전할 수 있는 [자체적인 브리지](https://bridge.arbitrum.io/)가 있습니다. +하지만 다른 [블록체인](/glossary/#blockchain)을 사용하기 위해 비슷한 교환을 하고 싶다면 어떻게 해야 할까요? 예를 들어 이더리움 메인넷의 [ETH](/glossary/#ether)를 [Arbitrum](https://arbitrum.io/)의 ETH로 교환한다고 가정해 봅시다. 이러한 경우, EUR 화폐를 위한 환전소가 있었던 것처럼 이더리움에서 아비트럼으로 ETH를 이동하기 위한 메커니즘이 필요합니다. 브리지는 이러한 거래를 가능하게 합니다. 이 경우, [Arbitrum에는 메인넷에서 Arbitrum으로 ETH를 전송할 수 있는 네이티브 브리지](https://portal.arbitrum.io/bridge)가 있습니다. ## 브리지가 왜 필요한가요? {#why-do-we-need-bridges} -모든 블록체인에는 한계가 있습니다. 수요에 맞춰 이더리움을 확장하려면 롤업이 필요합니다. 반면, Solana 및 Avalanche 등의 L1은 더 많은 요청을 처리할 수 있도록 다르게 설계되었지만 탈중앙화를 위한 비용이 따릅니다. +모든 블록체인에는 한계가 있습니다. 이더리움이 확장하고 수요를 따라잡으려면 [롤업](/glossary/#rollups)이 필요했습니다. 반면, Solana 및 Avalanche 등의 L1은 더 많은 요청을 처리할 수 있도록 다르게 설계되었지만 탈중앙화를 위한 비용이 따릅니다. -앞서 알아본 바와 같이, 모든 블록체인은 독립된 환경에서 개발되며 서로 다른 규칙과 합의 메커니즘이 작용합니다. 즉, 블록체인은 자체적으로 통신할 수 없으며 토큰은 블록체인 간에 자유롭게 이동할 수 없습니다. +그러나 모든 블록체인은 격리된 환경에서 개발되며 서로 다른 규칙과 [합의](/glossary/#consensus) 메커니즘을 가집니다. 즉, 블록체인은 자체적으로 통신할 수 없으며 토큰은 블록체인 간에 자유롭게 이동할 수 없습니다. 브리지는 블록체인을 연결하고, 블록체인 간에 정보 및 토큰이 교환될 수 있게 합니다. -브리지를 통해 다음 작업을 할 수 있습니다. +브리지를 통해 다음이 가능합니다. -- 블록체인 간의 정보 및 자산의 이동 -- 디앱의 다양한 블록체인 활용도 증가를 통한 기능의 강화(프로토콜에 혁신을 위한 더 많은 설계 여력이 생김) +- 자산 및 정보의 크로스체인 전송. +- [탈중앙화앱](/glossary/#dapp)이 다양한 블록체인의 강점에 접근하여 역량을 강화할 수 있도록 합니다(프로토콜이 혁신을 위한 더 많은 설계 공간을 갖게 되므로). - 사용자의 새로운 플랫폼 및 다른 체인의 장점에 대한 접근성 및 활용도 증가 - 서로 다른 블록체인 생태계의 개발자들이 협업하고 사용자를 위해 새로운 플랫폼을 구축 +[레이어 2로 토큰을 브리징하는 방법](/guides/how-to-use-a-bridge/) + ## 브리지 사용 사례 {#bridge-use-cases} 다음은 브리지를 사용할 수 있는 몇 가지 시나리오입니다. -### 보다 저렴한 거래 수수료 {#transaction-fees} +### 더 낮은 거래 수수료 {#transaction-fees} 이더리움 메인넷에 ETH가 있지만 다른 디앱을 사용하기 위해 더 낮은 거래 수수료를 찾고 있다고 가정해 봅시다. 이러한 경우, ETH를 메인넷에서 이더리움 L2 롤업으로 브리징함으로써 더 저렴한 거래 수수료를 지불할 수 있습니다. -### 다른 블록체인 상의 디앱 {#dapps-other-chains} +### 다른 블록체인의 탈중앙화앱 {#dapps-other-chains} -USDT를 빌려주는 플랫폼으로 이더리움 메인넷의 Aave를 사용하고 있는 경우, Polygon에서 Aave를 사용하여 USDT를 대출하면 이자율이 더 높습니다. +이더리움 메인넷의 Aave를 사용하여 USDT를 공급하고 있었는데, Polygon의 Aave를 사용하여 USDT를 공급할 경우 받을 수 있는 이자율이 더 높을 수 있습니다. -### 블록체인 생태계 살펴보기 {#explore-ecosystems} +### 블록체인 생태계 탐색 {#explore-ecosystems} 이더리움 메인넷에 ETH를 보유하고 있을 때 다른 네이티브 디앱을 사용하기 위해 알트 L1을 살펴보고자 할 수 있습니다. 이러한 경우, 브리지를 사용하여 이더리움 메인넷의 ETH를 알트 L1으로 이전할 수 있습니다. -### 네이티브 크립토 자산 소유 {#own-native} +### 네이티브 암호화폐 자산 소유 {#own-native} -네이티브 비트코인(BTC)을 소유하고 있지만 이더리움 메인넷에만 자금이 있다고 가정해 봅시다. 이더리움에서 BTC에 연결하기 위해 랩트비트코인(WBTC)을 구매할 수 있습니다. 다만 WBTC는 이더리움 네트워크 기반인 ERC-20 토큰이며, 비트코인 블록체인 상의 원본 화폐가 아닌, 이더리움 버전의 비트코인입니다. 네이티브 BTC를 소유하려면 브리지를 사용하여 이더리움의 자산을 비트코인으로 옮겨야 합니다. 이는 WBTC를 연결하고 네이티브 BTC로 변환합니다. 또는 BTC를 소유하고 있을 때 이더리움 디파이 프로토콜에서 사용하고자 할 수도 있습니다. 이 또한 브리지를 통해 가능하며, BTC를 WBTC로 전환하여 이더리움에서 자금으로 사용할 수 있습니다. +네이티브 비트코인(BTC)을 소유하고 있지만 이더리움 메인넷에만 자금이 있다고 가정해 봅시다. 이더리움에서 BTC에 연결하기 위해 랩트비트코인(WBTC)을 구매할 수 있습니다. 그러나 WBTC는 이더리움 네트워크의 네이티브 [ERC-20](/glossary/#erc-20) 토큰이며, 이는 비트코인 블록체인의 원본 자산이 아닌 이더리움 버전의 비트코인임을 의미합니다. 네이티브 BTC를 소유하려면 브리지를 사용하여 이더리움의 자산을 비트코인으로 옮겨야 합니다. 이는 WBTC를 연결하고 네이티브 BTC로 변환합니다. 또는 BTC를 소유하고 있으면서 이더리움 [DeFi](/glossary/#defi) 프로토콜에서 사용하고 싶을 수도 있습니다. 이 또한 브리지를 통해 가능하며, BTC를 WBTC로 전환하여 이더리움에서 자금으로 사용할 수 있습니다. - 상단의 모든 작업은 [중앙화 거래소](/get-eth/)에서도 실행할 수 있습니다. 하지만 자금이 이미 거래소에 등록되어 있지 않으면 여러 단계를 거쳐야 하며, 브리지를 사용하는 것이 더욱 간단합니다. + 또한 위의 모든 작업을 [중앙화 거래소]를 통해 할 수도 있습니다.(/get-eth) 하지만 자금이 이미 거래소에 등록되어 있지 않으면 여러 단계를 거쳐야 하며, 브리지를 사용하는 것이 더욱 간단합니다. @@ -72,16 +74,16 @@ USDT를 빌려주는 플랫폼으로 이더리움 메인넷의 Aave를 사용하 브리지는 설계 방법 및 그 정교함에 따라 여러 가지로 나뉩니다. 일반적으로 브리지는 신뢰할 수 있는 브리지와 신뢰할 수 없는 브리지의 두 개의 카테고리로 나뉩니다. -| 특정 주체 신뢰 브리지 | 특정 주체 신뢰 불필요 브리지 | -| ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -| 신뢰 브리지는 작업에 대해 중앙 기관이나 시스템에 의존합니다. | 신뢰 불필요 브리지는 스마트 계약과 알고리즘을 활용합니다. | -| 자금의 보관과 브리지의 보안에 있어 특정 주체에 대한 신뢰를 가정합니다. 사용자는 대부분 브리지 운영자의 평판에 의존합니다. | 특정 주체에 대한 신뢰가 필요하지 않습니다. 즉, 브리지의 보안은 적용되는 블록체인의 보안과 동일합니다. | -| 사용자는 가상 화폐 자산에 대한 제어권을 포기해야 합니다. | 스마트 계약을 통해 사용자는 자금에 대한 제어 권한을 그대로 유지합니다. | +| 특정 주체 신뢰 브리지 | 특정 주체 신뢰 불필요 브리지 | +| ----------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | +| 신뢰 브리지는 작업에 대해 중앙 기관이나 시스템에 의존합니다. | 신뢰 불필요 브리지는 스마트 계약과 알고리즘을 활용합니다. | +| 자금의 보관과 브리지의 보안에 있어 특정 주체에 대한 신뢰를 가정합니다. 사용자는 대부분 브리지 운영자의 평판에 의존합니다. | 특정 주체에 대한 신뢰가 필요하지 않습니다. 즉, 브리지의 보안은 적용되는 블록체인의 보안과 동일합니다. | +| 사용자는 가상 화폐 자산에 대한 제어권을 포기해야 합니다. | [스마트 계약](/glossary/#smart-contract)을 통해, 신뢰가 필요 없는 브리지는 사용자가 자신의 자금에 대한 통제권을 유지할 수 있게 해줍니다. | 간단히 말하면, 특정 주체 신뢰 브리지는 신뢰에 대한 가정을 필요로 하는 반면, 신뢰 불필요 브리지는 신뢰가 최소화되어 있고 기반이 되는 도메인을 넘어서는 부분(제3자 등)에 대한 신뢰와 가정을 필요로 하지 않습니다. 주요 용어의 뜻은 다음과 같습니다. -- **신뢰 불필요**: 기반이 되는 블록체인과 동일한 보안성을 지닙니다. [이 문서에서 Arjun Bhuptani](https://medium.com/connext/the-interoperability-trilemma-657c2cf69f17) 님의 설명을 참고하세요. -- **신뢰 가정**: 기반이 되는 도메인의 보안에서 벗어나 시스템에 외부 검증자를 추가하므로 가상 화폐 경제적 측면에서는 덜 안전합니다. +- **신뢰가 필요 없음(Trustless)**: 기본 도메인과 동등한 수준의 보안을 갖습니다. [이 글에서 Arjun Bhuptani가 설명한 바와 같습니다.](https://medium.com/connext/the-interoperability-trilemma-657c2cf69f17) +- **신뢰 가정:** 시스템에 외부 검증자를 추가하여 기본 도메인의 보안에서 벗어나므로, 암호경제학적 보안 수준이 낮아집니다. 두 접근 방식의 주요 차이점을 이해하기 위해 예시를 살펴보겠습니다. @@ -90,7 +92,7 @@ USDT를 빌려주는 플랫폼으로 이더리움 메인넷의 Aave를 사용하 1. 보안 검색 요원이 진행: 탑승 수속 전 보안 요원이 직접 수동으로 표와 신원 등 상세 사항을 확인합니다. 2. 셀프 체크인: 비행 정보를 입력한 후 정보가 확인되면 탑승권을 출력하는 기계가 진행합니다. -보안 검색 요원 진행 방식은 요원과 같은 제3자에게 의지하므로 신뢰 가정 모델과 유사합니다. 사용자는 해당 요원이 올바른 결정을 내리고 개인 정보를 적합하게 다룰 것이라고 신뢰합니다. +수동 체크포인트는 운영을 위해 제3자(즉, 담당관)에 의존하기 때문에 신뢰 기반 모델과 유사합니다. 사용자는 해당 요원이 올바른 결정을 내리고 개인 정보를 적합하게 다룰 것이라고 신뢰합니다. 셀프 체크인은 운영자의 역할을 제거하고 기술을 사용하므로 신뢰 불필요 모델과 유사합니다. 사용자는 언제든지 데이터를 제어할 수 있으며, 자신의 개인 정보에 대해 제3자를 신뢰하지 않아도 됩니다. @@ -98,17 +100,26 @@ USDT를 빌려주는 플랫폼으로 이더리움 메인넷의 Aave를 사용하 -## 브리지 사용의 리스크 {#bridge-risk} +## 브리지 사용하기 {#use-bridge} + +브리지를 사용하면 여러 블록체인 간에 자산을 이동할 수 있습니다. 브리지를 찾고 사용하는 데 도움이 되는 몇 가지 자료는 다음과 같습니다. + +- **[L2BEAT 브리지 요약](https://l2beat.com/bridges/summary) 및 [L2BEAT 브리지 위험 분석](https://l2beat.com/bridges/summary)**: 시장 점유율, 브리지 유형, 대상 체인에 대한 세부 정보를 포함하여 다양한 브리지에 대한 포괄적인 요약입니다. L2BEAT는 또한 브리지에 대한 위험 분석을 제공하여 사용자가 브리지를 선택할 때 정보에 입각한 결정을 내릴 수 있도록 돕습니다. +- **[DefiLlama 브리지 요약](https://defillama.com/bridges/Ethereum)**: 이더리움 네트워크 전반의 브리지 거래량 요약입니다. + + + +## 브리지 사용의 위험성 {#bridge-risk} 브리지는 아직 초기 개발 단계입니다. 최적화된 브리지 디자인은 아직 발견되지 않았을 가능성이 큽니다. 어느 브리지에서 작업하더라도 리스크가 존재합니다. -- **스마트 계약 리스크:** 사용자가 자금을 잃을 수도 있는 버그가 코드 상에 존재할 수 있습니다. -- **기술 리스크:** 소프트웨어 오류, 코드의 버그, 사용자 실수, 스팸, 해킹 등 다양한 요인이 사용자를 방해할 수 있습니다. +- **스마트 계약 위험 —** 사용자 자금 손실을 유발할 수 있는 코드 내 버그의 위험 +- **기술적 위험 —** 소프트웨어 오류, 버그가 있는 코드, 인적 오류, 스팸, 악의적인 공격으로 인해 사용자 작업이 중단될 수 있습니다. 특히 특정 주체 신뢰 브리지의 경우, 신뢰 가정을 추가하므로 다음과 같은 추가 위험을 수반합니다. -- **검열 리스크:** 브리지 운영자는 이론상 사용자가 브리지를 통해 자산을 이동하지 못하게 할 수 있습니다. -- **보관 리스크:** 브리지 운영자가 사용자의 자금을 훔치기 위해 공모할 수 있습니다. +- **검열 위험 —** 브리지 운영자가 이론적으로 사용자가 브리지를 사용하여 자산을 전송하는 것을 막을 수 있는 위험 +- **수탁 위험 —** 브리지 운영자가 공모하여 사용자 자금을 훔칠 수 있는 위험 사용자의 자금은 다음과 같은 경우에 리스크에 노출됩니다. @@ -118,17 +129,17 @@ USDT를 빌려주는 플랫폼으로 이더리움 메인넷의 Aave를 사용하 - 브리지 운영자가 신뢰 브리지를 악의적으로 사용하려는 경우 - 브리지가 해킹당하는 경우 -최근 해킹의 예시로는 Solana의 웜홀 브리지 해킹이 있으며, [120,000개의 wETH(3.25억 USD)가 손실되었습니다](https://rekt.news/wormhole-rekt/). +최근 해킹 사례 중 하나는 솔라나의 웜홀 브리지로, [해킹으로 12만 wETH(3억 2,500만 달러)를 도난당했습니다](https://rekt.news/wormhole-rekt/). [블록체인에서 발생한 주요 해킹 사건](https://rekt.news/leaderboard/) 중 다수가 브리지와 관련이 있었습니다. -브리지는 이더리움 L2에 등록하는 사용자 또는 다른 생태계를 살펴보고자 하는 사용자에게 매우 중요합니다. 하지만 브리지 사용에 포함되는 리스크를 생각한다면, 사용자는 브리지의 장단점을 잘 이해해야 합니다. +브리지는 이더리움 L2에 등록하는 사용자 또는 다른 생태계를 살펴보고자 하는 사용자에게 매우 중요합니다. 하지만 브리지 사용에 포함되는 리스크를 생각한다면, 사용자는 브리지의 장단점을 잘 이해해야 합니다. 다음은 몇 가지 [크로스체인 보안을 위한 전략](https://debridge.com/learn/blog/10-strategies-for-cross-chain-security/)입니다. -## 더 읽을거리 {#further-reading} +## 더 읽어보기 {#further-reading} + +- [EIP-5164: 크로스체인 실행](https://ethereum-magicians.org/t/eip-5164-cross-chain-execution/9658) - _2022년 6월 18일 - Brendan Asselstine_ +- [L2Bridge 위험 프레임워크](https://gov.l2beat.com/t/l2bridge-risk-framework/31) - _2022년 7월 5일 - Bartek Kiepuszewski_ +- ["미래는 멀티체인이 되겠지만 크로스체인은 아닐 이유"](https://old.reddit.com/r/ethereum/comments/rwojtk/ama_we_are_the_efs_research_team_pt_7_07_january/hrngyk8/) - _2022년 1월 8일 - Vitalik Buterin_ +- [안전한 크로스체인 상호 운용성을 위한 공유 보안 활용: 라그랑주 상태 위원회와 그 이상](https://web.archive.org/web/20250125035123/https://research.2077.xyz/harnessing-shared-security-for-secure-blockchain-interoperability) - _2024년 6월 12일 - Emmanuel Awosika_ +- [롤업 상호 운용성 솔루션의 현황](https://web.archive.org/web/20250428015516/https://research.2077.xyz/the-state-of-rollup-interoperability) - _2024년 6월 20일 - Alex Hook_ -- [블록체인 브리지란 무엇이고, 어떻게 분류할 수 있는가?](https://blog.li.finance/what-are-blockchain-bridges-and-how-can-we-classify-them-560dc6ec05fa) _2021년 2월 18일, Arjun Chand_ -- [크로스체인 브리지란?](https://www.alchemy.com/overviews/cross-chain-bridges) *2022년 5월 10일, Alchemy* -- [블록체인 브리지: 크립토네트워크로 네트워크 만들기](https://medium.com/1kxnetwork/blockchain-bridges-5db6afac44f8) _2021년 9월 8일, Dmitriy Berenzon_ -- [크립토 공간의 브리지](https://medium.com/chainsafe-systems/bridges-in-crypto-space-12e158f5fd1e) _2021년 8월 23일, Ben Adar Hyman_ -- [상호 운용성 트릴레마](https://medium.com/connext/the-interoperability-trilemma-657c2cf69f17) _2021년 10월 1일, Arjun Bhuptani_ -- [브리지의 보안성: 올바른 크로스체인 커뮤니케이션](https://medium.com/dragonfly-research/secure-the-bridge-cross-chain-communication-done-right-part-i-993f76ffed5d) _2021년 8월 23일, Celia Wan_ diff --git a/public/content/translations/ko/community/code-of-conduct/index.md b/public/content/translations/ko/community/code-of-conduct/index.md new file mode 100644 index 00000000000..34901006ed9 --- /dev/null +++ b/public/content/translations/ko/community/code-of-conduct/index.md @@ -0,0 +1,77 @@ +--- +title: "운영 규정" +description: "ethereum.org의 모든 공간에서 우리가 지향하는 기본 표준입니다." +lang: ko +--- + +# 행동 강령 {#code-of-conduct} + +## 임무 {#mission} + +이더리움을 위한 가장 포괄적이고 접근성 높은 지식 허브를 개발하고 유지합니다. + +## 가치 {#values} + +ethereum.org 커뮤니티는 다음을 지향합니다: + +- 교육적이며, 모든 사람이 이더리움을 이해하도록 돕습니다. +- 포용적 +- 접근성이 높은 +- 커뮤니티 주도 +- 이더리움의 기반 기술과 사용 사례에 집중 +- 이더리움 개념과 설계 원칙에 집중 + +## ethereum.org가 아닌 것 {#what-we-are-not} + +- 이더리움 재단 웹사이트 +- 어떤 종류의 투자나 영리 행위를 조장하는 플랫폼 +- 개별 프로젝트나 조직을 홍보하거나 지지하는 플랫폼 +- DEX, CEX 또는 기타 모든 형태의 금융 플랫폼 +- 어떤 종류의 재정적 또는 법적 조언을 제공하는 플랫폼 + +## 행동 강령 {#code-of-conduct} + +### 서약 {#pledge} + +자유로운 참여는 ethereum.org 정신의 핵심입니다. 우리는 수천 명의 기여자가 유지하는 웹사이트이자 커뮤니티이며, 이는 환영하고 참여적인 환경을 유지할 때만 가능합니다. 이를 위해 이 사이트의 기여자들은 모든 ethereum.org 플랫폼과 커뮤니티 공간에서 모든 참가자를 위한 괴롭힘 없는 환경을 유지할 것을 서약합니다. ethereum.org 커뮤니티는 나이, 장애, 민족, 성적 특징, 성 정체성, 경험 수준, 전문 분야, 교육, 사회 경제적 지위, 국적, 외모, 인종, 종교 또는 기타 다양성의 모든 측면에 관계없이 건설적이고 친근한 방식으로 참여하고자 하는 모든 사람을 환영하고 존중합니다. + +### 범위 {#scope} + +본 행동 강령은 모든 ethereum.org 공간(GitHub, Discord, Figma, Crowdin, X(구 Twitter) 및 기타 온라인 플랫폼 등)에 적용되며, 커뮤니티가 밋업, 콘퍼런스, 이벤트 등 실제 공공장소에 대표로 참여할 때도 적용됩니다. + +### 우리의 표준 {#our-standards} + +긍정적인 환경을 조성하는 데 기여하는 행동의 예는 다음과 같습니다: + +- 환영하고 포용적인 언어 사용 +- 다양한 관점과 경험 존중하기 +- 건설적인 비판을 정중하게 수용하고 공감하며 제공하기 +- 갈등이나 의견 불일치를 해결할 때 침착하고 전문적으로 행동하기 +- 다른 커뮤니티 구성원에게 공감과 관용을 보이기 +- 커뮤니티의 새로운 목소리를 장려하고 증폭시키기 + +참가자의 용납할 수 없는 행동의 예는 다음과 같습니다: + +- 신체적 폭력, 신체적 폭력 위협 또는 모든 종류의 신체적 폭력 조장 +- 성적인 언어나 이미지를 사용하거나 원치 않는 성적인 관심을 강요하는 행위 +- 다른 사람을 사칭하거나 개인 또는 조직과의 제휴 관계를 부정직하게 주장하는 행위 +- 트롤링, 모욕적이거나 경멸적인 발언, 개인적이거나 정치적인 공격 +- 공개 또는 비공개 채널에서 다른 커뮤니티 구성원을 괴롭히는 행위 +- 명시적인 허가 없이 실제 주소나 전자 주소와 같은 다른 사람의 개인 정보를 게시하는 행위 +- 소셜 엔지니어링, 스캐밍 또는 다른 커뮤니티 구성원을 조종하는 행위 +- 개인적인 금전적 또는 비금전적 이득을 위해 투자, 토큰, 프로젝트 또는 그 밖의 모든 것을 홍보하는 행위 +- 주제와 관련 없는 콘텐츠로 서버에 스팸을 보내는 행위 +- 커뮤니티 중재자의 요청이나 경고를 무시하는 행위 +- 전문적인 환경에서 부적절하다고 합리적으로 간주될 수 있는 기타 행위에 관여하는 행위 + +### 신고 {#reporting} + +행동 강령 위반은 일반적으로 커뮤니티에 공개됩니다. 이는 모든 것을 공개적인 채널에서 처리하여 커뮤니티 구성원이 자체적으로 관리할 수 있도록 하기 위함입니다. + +그러나 주의가 필요하다고 생각되는 일이 발생하면 중재 역할을 맡은 사람(예: 디스코드 가이드)에게 문제를 제기하여 조사를 돕고 적절한 조치를 취할 수 있도록 할 수 있습니다. + +신고할 때 구체적인 예시와 타임스탬프를 포함하여 최대한 자세한 내용을 기재해 주십시오. 이는 공정한 결과를 보장하는 데 도움이 될 것입니다. + +### 집행 {#enforcement} + +심각성에 따라 행동 강령을 위반한 사람은 ethereum.org 커뮤니티에서 경고, 일시적 또는 영구적 이용 금지 조치를 받을 수 있습니다. diff --git a/public/content/translations/ko/community/events/organizing/index.md b/public/content/translations/ko/community/events/organizing/index.md new file mode 100644 index 00000000000..05c60ecfa0f --- /dev/null +++ b/public/content/translations/ko/community/events/organizing/index.md @@ -0,0 +1,221 @@ +--- +title: "이더리움 이벤트 조직하기" +description: "이더리움 이벤트를 조직하는 방법" +lang: ko +hideEditButton: true +--- + +# 이더리움 이벤트 조직하는 방법 {#how-to-organize-an-ethereum-event} + +강하고 활기찬 커뮤니티를 구축하는 것이 이더리움 생태계 성장의 핵심입니다. 밋업, 워크숍, 또는 대규모 콘퍼런스 조직을 계획하고 있든, 이벤트의 성공은 지역 네트워크 내에서의 연결과 참여에 달려 있습니다. 이 가이드는 활발한 이더리움 커뮤니티의 기반을 마련하고, 기억에 남고 영향력 있는 콘퍼런스를 조직하는 과정을 단계별로 안내합니다. + +## 스스로에게 물어보세요. 이더리움 커뮤니티가 있나요? {#ask-yourself-is-there-an-ethereum-community} + +성공적인 이더리움 콘퍼런스는 활발하고 참여도가 높은 커뮤니티를 기반으로 구축됩니다. 이미 커뮤니티가 있다면 유리한 위치에 있는 것이지만, 그렇지 않다면 그 기반을 구축하는 것이 필수적인 사전 단계입니다. '씬(scene)'과 '커뮤니티'를 구별하는 것이 중요합니다. 씬은 특정 지역에 존재하는 회사와 개인을 포함할 수 있지만, 이들은 종종 독립적으로 운영되며 가끔 공동 이니셔티브를 진행할 뿐입니다. 이는 여러 곳에서 볼 수 있는 전통적인 웹2 생태계와 같습니다. 반면에 커뮤니티는 서로 협력하고 지원하는 상호 연결된 사람들과 조직의 네트워크이며, 이는 웹3 생태계에서 자주 볼 수 있습니다. + +**가장 먼저 해야 할 단계는 다음과 같습니다.** + +- 지역 스타트업과 회사를 탐색하세요. 도시나 국가에 강력하고 활동적인 회사가 있다는 것은 종종 커뮤니티를 구축하기 위한 가장 중요한 전제 조건입니다. +- 이미 진행 중인 밋업이 있는지 확인하세요 — ethereum.org [이벤트 페이지](https://ethereum.org/community/events/) +- [ethereum.org 웹사이트](https://ethereum.org/community/events/)와 ethereum.org 디스코드 — 지역 이더리움 이벤트, 개발자 및 기여자가 있는지 확인하기 위해. +- Luma 및 Meetup.com — 해당 지역에서 이더리움 관련 이벤트나 더 넓은 웹3 이벤트가 있는지 확인하기 위해. +- X — 해당 분야의 지역 옹호자나 인플루언서를 찾아보세요. + +이러한 요소들 대부분을 발견한다면, 이는 커뮤니티를 구축할 조건이 존재한다는 강력한 신호입니다. 하지만 반드시 커뮤니티가 이미 형성되어 있다는 의미는 아닙니다. 다음 단계는 이러한 주체들을 조직하고, 참여시키며, 육성하여 협력과 장기적인 성장을 위한 기회를 만드는 중요한 작업입니다. + +### 없다면, 어떻게 구축할까 {#if-not-how-to-build-it} + +이러한 요소들 중 많은 것이 빠져 있다는 것을 깨닫더라도 걱정하지 마세요. 처음부터 커뮤니티를 구축하는 것은 어렵지만 매우 보람 있는 과정입니다. 강력한 이더리움 커뮤니티는 하루아침에 나타나지 않습니다. 인내, 일관성, 그리고 명확한 비전이 필요합니다. 다음과 같이 시작할 수 있습니다. + +- **소통 채널을 설정하세요** — 텔레그램, 시그널, 왓츠앱, 위챗 또는 디스코드 서버 등 현재 있는 곳에서 더 인기 있는 채널을 이용하여 사람들이 연결하고, 질문하며, 리소스를 공유할 수 있도록 하세요. +- **얼리 어답터를 찾으세요.** 이더리움과 웹3에 열정적인 몇몇 사람들을 찾아내세요. 이들이 여러분의 핵심 지지자이자 협력자가 될 것입니다. +- **작고 일관된 이벤트를 개최하세요.** 비공식적인 밋업, 스터디 그룹 또는 워크숍으로 시작하세요. 일관성이 핵심입니다. 처음에는 그룹이 작더라도 정기적인 이벤트는 신뢰와 추진력을 쌓습니다. +- **지역 회사**, 교육 기관 또는 코워킹 스페이스에 연락하여 무료로 공간을 제공받아 보세요. 자국에서 연사를 찾을 수 없다면, 온라인 연사를 초대하되 사람들은 오프라인으로 모으세요. 청중을 한 곳에 물리적으로 모으는 것이 중요합니다. +- **기존 기술 커뮤니티와 협력하세요.** 이미 설립된 개발자 그룹, 스타트업 생태계 또는 블록체인 밋업이 있다면, 이들과 협력하여 이더리움 주제를 소개하고 활동 범위를 넓히세요. +- 이더리움의 잠재력에 대한 **교육 콘텐츠를 공유하세요**. +- **글로벌 커뮤니티에 연락하세요.** 전 세계의 기존 이더리움 그룹 및 프로젝트와 연결하여 지원, 멘토십 및 잠재적인 협력을 도모하세요. 전 세계의 이더리움 커뮤니티들은 적어도 한 가지 공통점이 있습니다. 바로 모두가 기꺼이 돕고자 한다는 것입니다. +- 지역 웹3 회사로부터 또는 [ESP](https://esp.ethereum.foundation/)와 같은 보조금 프로그램을 통해 **자금을 확보해 보세요**. + +### 있다면, 어떻게 유지하고 성장시킬까 {#if-yes-how-to-maintain-and-grow-it} + +일단 커뮤니티가 확립되면, 작업이 멈추는 것이 아니라 사실상 이제 시작입니다. 커뮤니티를 활발하고, 참여도가 높으며, 성장하는 상태로 유지하려면 지속적인 노력과 창의성이 필요합니다. 커뮤니티의 참여를 유지하는 핵심 요소 중 하나는 새로운 형식과 아이디어를 끊임없이 실험해야 한다는 것입니다. + +활기찬 이더리움 커뮤니티를 유지하기 위한 몇 가지 전략은 다음과 같습니다. + +- **이벤트 형식을 다양화하세요.** 한 가지 유형의 모임만 고수하지 마세요. 밋업, 단기 해커톤, 패널 토론, 네트워킹 이벤트 등으로 다양하게 구성하세요. 공동 작업의 날이나 교육 과정을 조직해 볼 수도 있습니다. +- **주제를 다양화하세요.** 이더리움은 단순한 기술이 아니라 법률, 마케팅, 비즈니스를 포함하는 가치의 집합이기도 합니다. +- **커뮤니티에** 피드백과 아이디어를 요청하세요. +- **다양한 청중** 세그먼트와 교류하세요. 이더리움을 처음 접하는 초보자부터 숙련된 개발자 및 기업가에 이르기까지 다양한 경험 수준에 맞춰 콘텐츠와 이벤트를 조정하세요. + +학습, 협력 및 성장을 위한 다양한 기회를 제공함으로써, 커뮤니티가 활발하게 유지되고 콘퍼런스 조직과 같은 더 큰 이니셔티브에 대비할 수 있도록 합니다. + +## 이벤트 {#event} + +### 이벤트를 조직하기에 적절한 시기는 언제일까요? {#when-is-the-right-time-to-organize-an-event} + +성공적인 이더리움 콘퍼런스나 커뮤니티 이벤트를 조직하려면 신중한 시기 선택과 고려가 필요합니다. 적절한 시점은 이벤트의 전반적인 성공에 기여하는 다양한 요인에 따라 달라집니다. + +커뮤니티의 성숙도, 시장 상황, 팀의 유무, 그리고 지역 씬(예: 잠재적 후원사)의 존재 여부를 고려해야 합니다. + +### KYC — 커뮤니티 알기 {#kyc-know-your-community} + +이벤트를 조직하는 데 가장 중요한 단계 중 하나는 커뮤니티를 이해하는 것입니다. 금융 서비스의 고객 알기(KYC)와 마찬가지로, 커뮤니티 알기(KYC)는 지역 청중의 특정 요구, 선호도 및 특성을 이해하는 데 시간을 들이는 것을 의미합니다. 이러한 이해는 콘퍼런스를 성공적이고 적절하게 맞춤화하는 데 도움이 될 것입니다. + +처음부터 대규모 이벤트를 목표로 삼고 싶을 수 있지만, 작게 시작하는 것이 종종 최선의 접근 방식입니다. 커뮤니티의 상태와 함께, 여러분의 국가가 인기 있는 관광지인지 또는 숙박 비용과 같이 관련 없어 보이는 다른 측면들을 객관적으로 살펴보면 자신에게 가장 좋은 해결책이 무엇인지 알게 될 것입니다. + +첫해에는 청중의 가장 큰 부분이 지역 커뮤니티일 것이므로, 더 큰 이벤트를 조직하는 첫해에 하는 모든 일은 해당 커뮤니티의 요구와 규모에 맞춰져야 합니다. + +### 어디서부터 시작할까 {#where-to-start} + +콘퍼런스를 조직할 때, 첫 단계는 벅차게 느껴질 수 있습니다. 하지만 명확한 계획과 구조가 있다면, 그 과정을 관리 가능한 작업으로 나눌 수 있습니다. 각각을 세분화하여 설명하겠습니다. + +구조화된 접근으로 시작하면 이벤트 조직의 여러 단계를 진행하면서 체계적으로 관리하고 스트레스를 줄이는 데 도움이 됩니다. 내리는 모든 결정은 커뮤니티의 요구를 충족하는 경험을 제공하는 데 한 걸음 더 다가가게 해야 합니다. + +**가장 먼저 해야 할 일은 명확한 역할과 책임이 있는 조직 팀을 구성하는 것입니다.** + +프로그램을 구축하거나 후원사에 연락하기 전에 또 다른 중요한 단계는 날짜를 선택하는 것입니다. 쉬운 단계처럼 들릴 수 있지만, 사전에 고려해야 할 몇 가지 중요한 요소가 있습니다. 그중 일부는 다음과 같습니다. + +- **주요 콘퍼런스** 또는 이벤트와 날짜가 겹치지 않도록 하세요. +- **현지 조건 및 상황을 고려하세요**(예: 계절, 주요 공휴일 등) +- **시장 상황을 고려하세요** +- **모든 것을 조직할 충분한 시간을 확보하세요** — 최소 9개월 + +### 팀 구성 방법 {#how-to-assemble-a-team} + +여러분의 비전을 공유하고 기술을 보완해 줄 사람들을 선택하세요. 어떤 팀은 집단으로 일하고, 다른 팀은 역할이 정해져 있습니다. 자신에게 가장 잘 맞는 방식을 찾으세요. 정기적인 소통과 명확한 기대치가 필수적입니다. 이벤트 기획을 위해 소통 플랫폼에 의존하고 싶을 수 있지만, 해야 할 일을 정리하고 추적하기 위해 작업 관리 플랫폼(예: Notion, Basecamp, Trello, Asana 또는 심지어 구관이 명관인 구글 시트)을 선택하는 것을 제안합니다. 잘 기능하고 잘 조직된 팀을 갖는 것이 중요합니다. + +다양한 이더리움 주최 팀들은 팀 내에 각기 다른 역할을 가지고 있지만, 모두 물류, 예산, 마케팅, 프로그램, 디자인, 파트너십을 담당하는 사람들이 있다는 공통점이 있습니다. + +### 프로그램: 성공적인 이벤트의 핵심 요소 {#the-program-a-key-element-of-a-successful-event} + +진정으로 가치 있고 기억에 남는 콘퍼런스를 조직하는 데 있어 프로그램은 전부입니다. 이것은 타협할 여지가 없는 부분입니다. 후원사는 중요하고 종종 이벤트 자금 조달에 결정적이지만, 청중의 경험과 그들이 받는 가치가 항상 우선되어야 합니다. 홍보성 콘텐츠와 끝없는 후원사 홍보로 가득 찬 프로그램은 참석자들을 멀어지게 하고 이벤트의 신뢰도를 떨어뜨릴 것입니다. + +모든 세션, 패널, 워크숍은 커뮤니티에 정보를 제공하고, 영감을 주며, 참여를 유도해야 합니다. 청중의 말에 귀를 기울이세요. 그들의 관심사, 필요, 그리고 과제를 이해하세요. 어떤 주제가 그들에게 공감을 불러일으킬까요? 동시에, 신선한 관점과 혁신적인 형식을 도입하여 프로그램을 역동적으로 유지하세요. 익숙하고 유행하는 주제와 최첨단 아이디어의 균형을 맞춰, 기술 심층 분석 및 커뮤니티 구축 세션부터 정책 토론 및 실습 워크숍에 이르기까지 이더리움 생태계의 다양한 측면을 다루는 균형 잡힌 의제를 보장하세요. 또한, 콘퍼런스의 언어를 고려하세요. 대부분의 이더리움 이벤트에서는 영어가 기본이지만, 현지 언어로 세션을 제공하면 지역 개발자들과 애호가들이 이벤트에 더 쉽게 접근할 수 있습니다. + +**연사를 선정할 때는 콘퍼런스 최소 6개월 전에 모집 공고를 내어 양질의 발표 신청을 유도하고 의제 큐레이션을 위한 충분한 시간을 확보하세요.** 연사 선정 책임자는 업계에서 상당한 경험과 생태계에 대한 깊은 이해를 갖추고 있어야 합니다. 이를 통해 가치 있고 통찰력 있는 기여를 식별하고 높은 수준의 콘텐츠를 유지할 수 있습니다. + +### 재정 지원을 찾을 수 있는 곳 {#where-to-find-financial-support} + +고품질 콘퍼런스를 조직하는 데는 장소 대여, 홍보 자료, 음식 및 음료, 제작 및 수많은 기타 비용 등 상당한 비용이 따릅니다. 초기에 재정 지원을 확보하는 것은 이벤트가 전문적인 기준을 충족하고 참석자들에게 훌륭한 경험을 제공하는 데 필수적입니다. + +#### 후원 제안서는 어떻게 만드나요? {#how-to-create-a-sponsorship-deck} + +먼저, 제안서가 필요합니다. **다른 콘퍼런스 주최자에게 조언을 구하고**, 그들의 제안서를 공유해 달라고 요청하여 이를 기반으로 패키지를 만들 수 있습니다. 패키지 가격을 책정할 때는 현실적으로 접근해야 하며, 특히 초기에는 돈을 버는 것이 아니라 비용을 충당하는 것을 목표로 해야 합니다. + +**모든 후원 제안서는 이벤트에 대한 명확하고 설득력 있는 개요를 제공하여** 잠재적 후원사가 이벤트의 범위, 초점 및 가치를 이해할 수 있도록 해야 합니다. 신뢰성을 구축하기 위해 장소, 날짜, 조직 팀에 대한 세부 정보 등 기본 사항부터 시작하세요. 그런 다음, 다양한 이더리움 콘퍼런스가 각기 다른 청중을 대상으로 하므로 이벤트의 주요 초점을 강조하세요. 일부는 깊이 있는 기술 토론을 특징으로 하는 빌더 중심이며, 다른 일부는 디파이, DAO 또는 정책 주제에 더 중점을 둘 수 있습니다. + +단순히 이벤트를 설명하는 것을 넘어 명확한 기대치를 설정하세요. **예상 참석자 수와 이미 확정된 주요 연사를 개략적으로 설명하세요.** 이는 후원사가 잠재적인 도달 범위를 가늠하는 데 도움이 됩니다. 가장 중요한 것은 후원의 대가로 무엇을 받게 될지 명확하게 정의하는 것입니다. 부스 공간, 발표 기회, 소셜 미디어 홍보, 브랜딩 노출 또는 독점적인 네트워킹 접근권 등이 있습니다. 잘 구성된 제안서는 정보를 제공할 뿐만 아니라 잠재적 후원사들이 이벤트에 참여할 기회에 대해 기대감을 갖게 합니다. + +#### 누가 이벤트를 지원할 수 있을까요? {#who-might-support-your-event} + +먼저 여러분의 도시나 국가에 있는 이더리움 및 더 넓은 기술 생태계 내의 회사에 연락하는 것부터 시작하세요. 이러한 **조직들은 종종 커뮤니티 성장과 혁신을 촉진하는 지역 이벤트를 지원하는 데 기득권을 가집니다**. 또한 이들은 지역 생태계에 투자하는 가치를 인식하고 여러분의 콘퍼런스를 인재, 파트너 및 사용자와 연결될 기회로 볼 가능성이 더 높습니다. + +지역 지원을 확보한 후에는 웹3 분야의 글로벌 플레이어들에게까지 활동 범위를 넓히세요. **기존 프로토콜, DAO 및 생태계 펀드는 종종 커뮤니티 주도 이벤트를 위해 예산을 할당합니다**. 처음 주최하는 사람들에게는 아직 보여줄 실적이 없기 때문에 이것이 다소 어려울 수 있지만, 브랜드 가시성, 발표 기회, 그리고 타겟 청중과의 의미 있는 참여 등 이벤트 지원의 이점을 명확하게 설명하는 설득력 있는 후원 패키지를 만들어 보세요. 다른 사람들이 가지지 못한 자신만의 고유한 가치를 찾아보세요. + +#### 이벤트 자금 조달의 대안적 형태 {#alternative-forms-of-funding-your-event} + +보조금은 많은 주최자들이 간과하는 또 다른 잠재적인 자금 조달원입니다. 이더리움 재단의 [생태계 지원 프로그램](https://esp.ethereum.foundation/)(ESP) 및 [기타 보조금 이니셔티브](https://ethereum.org/community/grants/#ethereum-grants)와 같은 프로그램은 커뮤니티 주도 이벤트를 지원하기 위해 존재합니다. + +재정적 후원 외에도, 특히 음식과 음료에 대한 현물 파트너십을 고려해 보세요. 지역 문화나 기술 커뮤니티와 잘 맞는 브랜드는 이벤트의 훌륭한 파트너가 될 수 있습니다. 커피 브랜드, 음료 회사, 심지어 지역 피자 가게도 이벤트에서의 노출을 대가로 제품을 제공할 의향이 있을 수 있습니다. 이러한 협력은 비용을 절감하면서 참석자 경험을 향상시키는 데 도움이 될 수 있습니다. + +재정에 대해 이야기하는 김에 이것을 기억하세요. 탁월한 참석자 경험을 만드는 데 투자하는 모든 달러는 기하급수적으로 보상을 받을 것입니다. 고품질 제작, 편안한 장소, 사려 깊은 증정품, 잘 조직된 부대 이벤트는 콘퍼런스가 끝난 후에도 참가자들이 오랫동안 이야기할 기억에 남는 경험에 기여합니다. 행복한 참석자들은 여러분의 가장 큰 지지자가 되어 이벤트의 장기적인 성공을 보장합니다. + +### 물류 {#logistics} + +자금 확보와 병행하여 주요 초점은 물류에 두어야 합니다. 잘 조직된 콘퍼런스는 장소 설정부터 참석자 경험에 이르기까지 여러 영역에 걸쳐 세심한 계획이 필요합니다. 이벤트 조직에 확실한 경험이 있는 사람, 반드시 웹3 이벤트가 아니더라도 일반적인 이벤트 경험이 있는 사람이 있으면 큰 차이를 만들 수 있습니다. 경험 많은 물류 책임자는 잠재적인 문제를 예측하고 문제가 되기 전에 해결하여 시간, 돈, 스트레스를 절약할 수 있습니다. + +물류 책임자는 장소, 제작사, 음식, 음료 및 상품을 위한 다양한 공급업체를 선택해야 하며, 참석자들이 암호화폐로도 등록하고 결제할 수 있는 사용하기 쉬운 온라인 티켓팅 시스템도 선택해야 합니다. + +### 장소 인프라 {#location-infrastructure} + +콘퍼런스 장소를 선택할 때, 장소 자체를 넘어 더 넓은 도시와 국가의 인프라를 고려하는 것이 중요합니다. 날씨, 이동성, 안전, 정치적 환경과 같은 요소들은 참석자 경험을 형성하는 데 큰 역할을 합니다. + +덜 알려진 장소의 경우, 이것이 특히 중요해집니다. 전 세계의 참석자와 후원사들은 쉽고 안전하게 여행할 수 있다는 확신을 가질 필요가 있습니다. 공항 연결성, 대중교통, 숙박 옵션과 같은 측면을 살펴보세요. 또한 비자 정책과 같이 국제 참가자들을 단념시킬 수 있는 복잡한 문제를 피하기 위해 지역의 문화적, 정치적 분위기를 고려하는 것이 현명합니다. + +### 이벤트 홍보 방법 {#how-to-promote-the-event} + +이벤트를 효과적으로 홍보하는 것은 적절한 청중을 유치하고 기대감을 조성하는 데 핵심입니다. 잘 짜인 홍보 전략은 콘퍼런스가 마땅히 받아야 할 가시성과 참여를 얻도록 보장합니다. 디자인 역시 브랜드에서 중요한 역할을 하므로, 이에 대한 예산도 반드시 책정해야 합니다. + +#### 소셜 미디어 {#social-media} + +X.com이 소셜 미디어 홍보의 중추가 될 것입니다. 그곳에 적극적이고 꾸준하게 게시물을 올리려고 노력하고, 개인 계정과 조직 계정 모두로 다양한 대화에 참여하세요. + +링크드인이 홍보를 위한 가장 명백한 선택처럼 들리지 않을 수 있지만, 그곳에서 완전히 다른 청중이나 일부 후원사에게 다가갈 수 있습니다. + +#### 다른 이더리움 커뮤니티와의 파트너십 {#partnerships-with-other-ethereum-communities} + +다양한 이더리움 주최자와의 파트너십은 기존 네트워크를 활용하여 도달 범위를 넓히는 데 도움이 될 수 있으며, 특히 처음부터 시작할 때 더욱 그렇습니다. 커뮤니티 할인을 제공하고, 다른 이벤트와 교차 홍보하며, 파트너를 초대하여 부대 이벤트나 워크숍을 공동 주최하세요. + +#### 대학 홍보 활동 {#university-outreach} + +학생 동아리나 교수를 통해 도시의 기술 및 경제 학부에 연락하여 이벤트를 홍보하세요. 대학과 교류하는 것은 젊은 인재, 연구원, 미래의 산업 전문가를 유치하고 학계와 이더리움 생태계 간의 더 강한 연결을 촉진하는 데 도움이 될 수 있습니다. 학생들은 종종 신선한 아이디어, 열정, 그리고 탄탄한 기술 기반을 가져오므로 해커톤을 조직하는 경우 특히 좋습니다. + +#### 미디어 {#media} + +웹3 중심의 미디어 매체 및 뉴스레터에 연락하여 이벤트 보도를 요청하세요. 웹3 미디어는 PR 기사에 대해 비용을 지불받기를 기대하지만, 유료 홍보 예산이 없다면 무료 티켓이나 일부 유명 연사 및 후원사와의 인터뷰를 제공할 수 있습니다. 보도 자료와 함께 소셜 미디어나 웹사이트에서 다양한 형식으로 홍보할 준비가 된 시각 자료를 포함한 PR 패키지를 만드세요. 또한, 기술을 다룰 수 있는 지역 언론인이나 평판이 좋은 콘텐츠 크리에이터에게까지 범위를 넓히는 것이 이벤트를 더 많은 청중에게 선보이는 데 중요할 수 있습니다. 이는 암호화폐 산업과 일반 대중 사이의 격차를 메우고, 주류 기술 및 비즈니스 커뮤니티의 관심을 끄는 데 도움이 됩니다. + +### 해커톤도 함께 조직해야 할까요? {#should-you-organize-a-hackathon-as-well} + +해커톤은 개발자 커뮤니티의 참여를 유도하고 혁신을 촉진하는 좋은 방법이 될 수 있으므로, 해커톤을 조직하는 것은 유익할 수 있습니다. 또한 프로젝트를 협력하고 구축할 수 있는 실습 기회를 제공하여 생태계에 실질적인 결과를 가져올 수 있습니다. 해커톤은 평소 콘퍼런스에 참석하지 않을 수 있지만 새로운 아이디어를 구축하고 테스트하는 도전에 열심인 개발자들을 끌어들입니다. 콘퍼런스가 개발자, 혁신, 실습 프로젝트를 목표로 한다면, 해커톤을 개최하는 것은 자연스러운 선택입니다. + +하지만, 조직하기 전에 충분한 리소스와 시간이 있는지 고려하세요. **해커톤은 시간, 인력, 재정 투자 측면에서 상당한 리소스를 필요로 합니다**. 특히 콘퍼런스도 관리하는 경우, 이를 처리할 전담 팀이 있는지 확인하세요. 또한, 커뮤니티에 관심이 있는지 확인하세요. 커뮤니티가 더 빌더 지향적이라면, 조직하는 것이 합리적일 수 있습니다. + +조직하는 데 많은 이점이 있지만, 콘퍼런스의 규모에 따라 해커톤을 추가하는 것이 벅찰 수 있다는 점을 고려하세요. 둘 다 관리하는 것이 어느 한쪽의 품질을 떨어뜨릴지 평가해야 합니다. 더 작고 집중된 해커톤을 선택하거나, 여러 달에 걸쳐 이벤트를 분산시킬 수 있습니다. + +### (거의 피할 수 없는) 직면하게 될 과제들 {#almost-inevitable-challenges-that-you-will-face} + +콘퍼런스, 특히 이더리움 분야에서 콘퍼런스를 조직할 때 가장 큰 과제 중 하나는 충분한 자금을 확보하는 것입니다. **많은 이벤트 주최자들은 장소 비용**, 케이터링 및 기타 물류 비용을 충당하는 데 필요한 자본을 모으는 데 어려움을 겪습니다. 후원은 종종 필수적이지만, 관계를 구축하고 회사들이 이벤트에 투자하도록 설득하는 데는 시간이 걸릴 수 있습니다. 또한, 시장 침체기에는 회사들이 비핵심 활동에 투자하기를 꺼릴 수 있으므로 후원사를 유치하는 것이 더 어려워질 수 있습니다. + +예산을 효과적으로 관리하는 것이 핵심입니다. 막바지 장소 변경 및 추가적인 이벤트 기술 요구 사항과 같은 예기치 않은 비용은 예산을 빠르게 초과할 수 있습니다. + +새로운 이벤트의 경우, **고품질의 연사를 섭외하는 것이 특히 어려울 수 있습니다**. 이더리움 분야의 기존 오피니언 리더나 인플루언서들은 이미 일정이 꽉 차 있을 수 있으며, 검증된 실적이 없는 새로운 이벤트에 참여하기를 주저할 수 있습니다. 이벤트 훨씬 전부터 네트워킹하고 잠재적인 연사에게 연락하는 데 시간을 할애할 준비를 하세요. + +또한, 연사와 관련하여 명확하고 지속적인 소통을 하세요. 프레젠테이션 제출 마감일을 설정하고 막판 변경을 피하세요. + +성공적인 콘퍼런스는 물류, 마케팅, 후원, 기술 지원 및 참석자 관리를 처리할 수 있는 전담 팀을 필요로 합니다. 기술 이벤트 조직 경험이 있는 개인을 찾는 것은 어려울 수 있으며, 특히 예산이 적거나 대부분의 경우 예산 없이 자원봉사 기반으로 작업할 때 더욱 그렇습니다. + +### 혼자서 해서는 안 됩니다. 자원봉사자가 필요합니다. {#you-shouldnt-do-it-alone-you-need-volunteers} + +이더리움 이벤트를 조직하려면 물류, 등록, 연사 조정, 참석자 지원 등 훨씬 더 많은 것을 처리할 다양하고 헌신적인 팀이 필요합니다. 팀 규모가 3명에서 15명에 불과하므로, 이벤트의 원활한 운영을 위해 자원봉사자가 필수적이라는 것이 분명해집니다. + +자원봉사자는 종종 많은 콘퍼런스의 중추 역할을 하며, 특히 예산이 제한적일 때 중요한 지원을 제공합니다. 이들은 등록 데스크 운영부터 이벤트 설정 지원에 이르기까지 모든 것을 처리하여 이벤트가 최대한 원활하게 진행되도록 합니다. + +자원봉사자에게 금전적 보상을 제공하는 것은 어렵지만, 그들의 경험을 가치 있게 만들어 줄 가치 있는 것을 제공하는 것이 필수적입니다. 네트워킹 기회, 기술 개발, 일부 독점적인 혜택, 수료증 또는 추천서를 제공하는 것을 고려해 보세요. + +### 이벤트 주최자를 위한 규정 준수 필수 사항 {#compliance-essentials-for-event-organizers} + +이벤트를 조직할 때 명심해야 할 몇 가지 필수적인 법적 및 물류적 고려 사항이 있습니다. + +- **후원 계약** – 명확하게 정의된 취소 정책을 포함하여 후원사를 위한 명확한 계약을 준비하세요. +- **행동 강령** – 특정 이벤트 유형(콘퍼런스/해커톤, 해커 하우스 등)에 맞는 행동 강령을 준비하세요. +- **개인정보 처리방침** – 데이터 보호 규정 및 이미지에 대한 규정을 준수하기 위해 웹사이트에 대한 개인정보 처리방침 초안을 작성하세요. +- **지역 당국에 신고** – 이벤트가 비공개 모임일지라도, 지역 경찰서에 신고하는 것이 바람직합니다. +- **티켓팅 계약** – 티켓팅 서비스 제공업체와 공식적인 계약을 체결하여 조건과 책임을 명확히 하세요. +- **규제 준수** – 콘퍼런스를 개최하는 국가에 암호화폐 산업에 대한 특정 규정이나 제한이 있는지 사전에 확인하세요. +- **상품 통관** – 후원사 상품을 수입하는 경우, 절차를 효율적으로 처리하기 위해 관세사를 고용하는 것이 좋습니다. +- **사진 및 미디어 정책** – 사진 및 미디어 보도에 대한 가이드라인을 명확하게 정의하여 참가자들이 동의 및 거부 옵션에 대해 알 수 있도록 하세요. + +## 이벤트 후: 다음은? {#after-the-event-whats-next} + +이벤트가 끝나면 참석자, 연사, 후원사로부터 피드백을 수집하고 내부 보고서를 작성하여 향후 이벤트를 더 잘 준비하는 것이 중요합니다. 이는 무엇이 잘 되었고 어디를 개선할 수 있는지 파악하는 데 도움이 됩니다. 설문조사나 일대일 인터뷰를 사용하여 향후 반복에 지침이 될 귀중한 통찰력을 수집하세요. 실수나 비효율적인 부분을 검토하는 데 시간을 투자하세요. 다음 콘퍼런스에서 이를 피할 수 있어 과정이 더 원활해집니다. + +핵심은 추진력을 계속 유지하는 것입니다. 커뮤니티와 계속 교류하고, 그들의 피드백을 기반으로 한 진행 상황에 대한 업데이트를 공유하며, 다음 이벤트에 대한 기대감을 조성하세요. 이러한 연결을 유지함으로써 콘퍼런스의 영향력이 이벤트 자체를 넘어 확장되도록 보장하고, 관계를 강화하며, 미래의 성공을 위한 발판을 마련합니다. + +## 감사의 말 {#acknowledgement} + +이 기사에 통찰력을 공유하여 기여해주신 모든 분들께 깊은 감사를 드립니다. ETHBratislava의 Slavo Fabisik; ETH Kipu와 ETH Latam의 Lola; ETH Belgrade의 Tanja Mladenovic, Ethereum Bogota의 Juan David; ETHWarsaw의 Monika Zając; NapulETH의 Raffaele Orefice; ETH Riyadh의 Xiao Wu(Ling); urbe.eth의 Marco; ETH Dublin의 Caolán Walsh; ETHCluj의 Alex Males; 그리고 ETH Slovenia의 Stanko Devic. + +## 참고 자료 {#resources} + +팟캐스트: A부터 Z까지 ETH 이벤트 조직 및 홍보 방법: + +- [ETHWarsaw 사례 연구, Out of Ordinary 제공](https://www.youtube.com/watch?v=io2Dx1ouz8o) + +트위터 스페이스: + +- [ETH 커뮤니티 AMA](https://x.com/NapulETH/status/1905732699094151623) + +문서: + +- [ETHKL 구축, Danny H. 작성](https://sekto.tech/ethkl24) +- [POKT 이벤트 플레이북](https://docs.pokt.network/community/pokt-events-playbook) diff --git a/public/content/translations/ko/community/get-involved/index.md b/public/content/translations/ko/community/get-involved/index.md new file mode 100644 index 00000000000..b3eca3a4d2e --- /dev/null +++ b/public/content/translations/ko/community/get-involved/index.md @@ -0,0 +1,132 @@ +--- +title: "어떻게 참여하나요?" +description: "이더리움 커뮤니티에 참여하는 방법" +lang: ko +--- + +# 어떻게 참여하나요? 참여하기 {#get-involved} + +이더리움 커뮤니티는 다양한 경험과 능력을 갖춘 사람들로 구성되어 있습니다. 개발자, 디자이너, 회계사 등 참여할 수 있는 분야 및 참여하는 방법 또한 다양합니다. 다음 목록을 읽어보시면 어떻게 시작해야 할 지를 결정하는데 유용할 것입니다. + +[행동 강령](/community/code-of-conduct)에서 ethereum.org의 사명과 가치에 대해 읽어보는 것으로 시작하세요. + +## 개발자 ‍ {#developers} + +- [ethereum.org/developers/](/developers/)에서 이더리움에 대해 알아보고 직접 사용해 보세요. +- 가까운 곳에서 열리는 [ETHGlobal](http://ethglobal.co/) 해커톤에 참여하세요! +- [자신의 전문 분야 또는 선호하는 프로그래밍 언어와 관련된 프로젝트](/developers/docs/programming-languages/)를 확인해 보세요. +- [합의 및 실행 레이어 콜](https://www.youtube.com/@EthereumProtocol/streams)을 시청하거나 참여하세요. +- [생태계 지원 프로그램의 위시리스트](https://esp.ethereum.foundation/wishlist/) - 이더리움 생태계 지원 프로그램에서 보조금 신청을 적극적으로 받고 있는 툴링, 문서, 인프라 분야 +- [Web3Bridge](https://www.web3bridgeafrica.com) - 아프리카 전역의 수백 명의 개발자와 커뮤니티 구성원을 발굴, 교육 및 지원하기 위한 이니셔티브에 참여하여 유망한 웹3 커뮤니티에 참여하세요. +- [Eth R&D Discord](https://discord.com/invite/VmG7Uxc)에 참여하세요. +- [Ethereum Cat Herders Discord](https://discord.com/invite/Nz6rtfJ8Cu)에 참여하세요. + +## 연구원 및 학계 ‍ {#researchers-and-academics} + +수학, 암호학, 경제학에 대한 경험이 있으신가요? 이더리움 생태계 내에서 수행되고 있는 최첨단 작업 중 일부에 관심이 있을 수 있습니다. + +- [Eth R&D Discord](https://discord.com/invite/VmG7Uxc)에 참여하세요. +- 이더리움 개선 제안서 작성 또는 검토하기 + - EIP 작성하기 + 1. [Ethereum Magicians](https://ethereum-magicians.org)에 아이디어를 제출하세요. + 2. [EIP-1](https://eips.ethereum.org/EIPS/eip-1)을 읽어보세요 - **네, 이게 문서의 전부입니다.** + 3. EIP-1의 지침을 따르세요. 초안을 작성할 때 참조하세요. + - [EIP 편집자](https://eips.ethereum.org/EIPS/eip-5069)가 되는 방법을 알아보세요. + - 지금 바로 EIP를 동료 검토할 수 있습니다! ['e-review' 태그가 있는 공개 PR](https://github.com/ethereum/EIPs/pulls?q=is%3Apr+is%3Aopen+label%3Ae-review)을 확인하세요. `discussion-to` 링크에 대한 기술적인 피드백을 제공하세요. + - [EIP 거버넌스](https://github.com/ethereum-cat-herders/EIPIP)에 참여하세요. + - [Ethereum Cat Herders Discord](https://discord.com/invite/Nz6rtfJ8Cu)에 참여하세요. + - [EIP에 대해 자세히 알아보기](/eips/) +- [Challenges.ethereum.org](https://challenges.ethereum.org/) - 100,000달러 이상을 벌 수 있는 고액의 연구 현상금 시리즈 +- [Ethresear.ch](https://ethresear.ch) - 이더리움의 주요 연구 포럼이자 암호경제학 분야에서 세계에서 가장 영향력 있는 포럼 +- [EF Research AMA](https://old.reddit.com/r/ethereum/comments/vrx9xe/ama_we_are_ef_research_pt_8_07_july_2022) - 연구원들과 함께하는 진행 중인 Q&A 시리즈입니다. 다음 파트가 열릴 때마다 누구나 질문을 게시할 수 있습니다. +- [생태계 지원 프로그램 위시리스트](https://esp.ethereum.foundation/wishlist/) - 이더리움 생태계 지원 프로그램에서 보조금 신청을 적극적으로 받고 있는 연구 분야 +- [AllWalletDevs](https://allwallet.dev) - 이더리움 개발자, 디자이너 및 관심 있는 사용자가 정기적으로 모여 지갑에 대해 논의하는 포럼 + +[더 많은 활성 연구 분야를 탐색하세요](/community/research/). + +## 비기술 직군 ‍ {#non-technical} + +개발자가 아니라면, 이더리움을 어디서 시작하는지 알기가 어려울 수 있다. 여기 약간의 제안들, 특정 전문 영역들에 대한 리소스가 있다. + +### 자신이 사는 도시에서 밋업을 조직하세요 {#meetups} + +- 어떻게 시작할 지 확실하지 않으세요? [BUIDL 네트워크](https://consensys.net/developers/buidlnetwork/)가 도움을 줄 수 있습니다. + +### 이더리움에 대한 콘텐츠 작성하기 {#write-content} + +- 이더리움은 일반 언어로 가치를 설명할 수 있는 좋은 작가가 필요하다. +- 자신만의 글을 배포할 준비가 되지 않았는가? 커뮤니티 리소스에 있는 기존 콘텐츠에 기여하거나 [ethereum.org에 대한 새로운 콘텐츠를 제안](/contributing/)하는 것을 고려해 보세요! + +### 커뮤니티 콜 노트 필기 자원하기 {#take-notes} + +- 많은 오픈 소스 커뮤니티 콜이 있으며, 노트 필기자가 있으면 큰 도움이 됩니다. 관심이 있다면 [Ethereum Cat Herders 디스코드](https://discord.com/invite/Nz6rtfJ8Cu)에 참여하여 자신을 소개해 보세요! + +### 이더리움 콘텐츠를 모국어로 번역하기 {#translate-ethereum} + +- ethereum.org는 웹사이트 및 기타 리소스를 여러 언어로 번역하는 번역 프로그램을 운영하고 있습니다. +- [여기](/contributing/translation-program)에서 참여 방법을 알아보세요. + +### 노드 실행하기 {#run-a-node} + +수천 명의 노드 운영자와 함께 이더리움의 탈중앙화를 더욱 강화하는 데 도움을 주세요. + +- [노드 실행 방법에 대해 자세히 알아보기](/developers/docs/nodes-and-clients/run-a-node/) + +### ETH 스테이킹하기 {#staking} + +ETH를 스테이킹하여 이더리움 네트워크를 보호하는 데 도움을 주면서 보상을 받을 수 있습니다. + +- [스테이킹에 대해 자세히 알아보기](/staking/) + +### 프로젝트 지원하기 {#support-projects} + +이더리움 생태계는 공공재와 영향력 있는 프로젝트에 자금을 지원하는 임무를 수행하고 있습니다. 소액 기부로도 지지를 표하고 중요한 작업이 실현되도록 할 수 있습니다. + +- [Gitcoin](https://gitcoin.co/fund) +- [clr.fund](https://clr.fund/#/about) + +## 금융 전문가 및 회계사 ‍ {#financial-professionals} + +- 이더리움은 대체 금융 시스템을 제공하는 프로토콜 및 애플리케이션 네트워크인 “탈중앙화 금융(DeFi)” 생태계의 본거지입니다. 금융 전문가라면 [DeFi Llama](https://defillama.com/) 또는 [DeFiPrime](https://defiprime.com)에서 일부 DeFi 앱을 확인해 보세요. +- 회계사이신가요? 이더리움의 자산(ETH, 토큰, DeFi 등)은 많은 새로운 회계 문제를 야기합니다. [Rotki](https://rotki.com/)와 같이 암호화폐 사용자가 부기 및 회계 문제를 해결하는 데 도움을 주는 것을 목표로 하는 일부 프로젝트를 확인하는 것으로 시작할 수 있습니다. + +## 제품 관리자 ‍ {#product-managers} + +- 이더리움 생태계는 여러분의 재능을 필요로 합니다! 많은 회사에서 제품 관리자 직책을 채용하고 있습니다. 오픈 소스 프로젝트에 기여하는 것으로 시작하고 싶다면 [Ethereum Cat Herders](https://discord.com/invite/Nz6rtfJ8Cu) 또는 [RaidGuild](https://www.raidguild.org/)에 문의하세요. + +## 마케팅 ‍ {#marketing} + +- 이더리움 생태계에는 많은 마케팅 및 커뮤니케이션 직책이 있습니다! + +## 이더리움 채용 정보 {#ethereum-jobs} + +**이더리움에서 일하고 싶으신가요?** + +- [ethereum.org 채용 정보](/about/#open-jobs) +- [이더리움 재단 채용 게시판](https://jobs.ashbyhq.com/ethereum-foundation) +- [JobStash](https://jobstash.xyz) +- [이더리움 채용 게시판](https://www.ethereumjobboard.com/) +- [암호화폐 채용 정보](https://cryptocurrencyjobs.co/ethereum/) +- [ConsenSys 채용 정보](https://consensys.net/careers/) +- [Crypto Jobs List](https://cryptojobslist.com/ethereum-jobs) +- [Bankless 채용 게시판](https://pallet.xyz/list/bankless/jobs) +- [Web3 채용 정보](https://web3.career) +- [Web3 Army](https://web3army.xyz/) +- [Crypto Valley Jobs](https://cryptovalley.jobs/) +- [이더리움 채용 정보](https://startup.jobs/ethereum-jobs) + +## DAO에 가입하기 {#decentralized-autonomous-organizations-daos} + +"DAO"는 분산형 자율 조직을 의미합니다. 이러한 그룹은 이더리움 기술을 활용하여 조직 및 협업을 촉진합니다. 예를 들어, 멤버십 제어, 제안에 대한 투표 또는 공동 자산 관리에 사용됩니다. DAO는 아직 실험 단계에 있지만, 자신과 맞는 그룹을 찾고, 협력자를 찾고, 이더리움 커뮤니티에 대한 영향력을 키울 수 있는 기회를 제공합니다. [DAO에 대해 자세히 알아보기](/dao/) + +- [DAOSquare](https://daosquare.io/) [@DAOSquare](https://twitter.com/DAOSquare) - _비기술 분야에서 DAO 개념을 홍보하고 사람들이 DAO를 통해 가치를 창출하도록 돕습니다_ +- [Developer DAO](https://www.developerdao.com/) [@developer_dao](https://twitter.com/developer_dao) - _인터넷의 집단 소유를 믿는 빌더들의 커뮤니티_ +- [dOrg](https://dOrg.tech) [@dOrg_tech](https://twitter.com/dOrg_tech) - _DAO로 활동하는 프리랜서 웹3 개발 집단_ +- [HausDAO](https://daohaus.club) [@nowdaoit](https://twitter.com/nowdaoit) - _DAOhaus의 커뮤니티 거버넌스_ +- [LexDAO](https://lexdao.org) [@lex_DAO](https://twitter.com/lex_DAO) - _법률 공학_ +- [MetaCartel Ventures](https://metacartel.xyz) [@VENTURE_DAO](https://twitter.com/VENTURE_DAO) - _프리시드 암호화폐 프로젝트를 위한 벤처_ +- [MetaFactory](https://metafactory.ai) [@TheMetaFactory](https://twitter.com/TheMetaFactory) - _디지털과 실물을 결합한 의류 브랜드_ +- [MolochDAO](https://molochdao.com) [@MolochDAO](https://twitter.com/MolochDAO) - _이더리움 개발 자금 지원에 중점을 둔 커뮤니티_ +- [Raid Guild](https://raidguild.org) [@RaidGuild](https://twitter.com/RaidGuild) - _웹3 빌더들의 집단_ + +ethereum.org에 기여할 때마다 그리고 어떤 방식으로 기여하든 ethereum.org [행동 강령](/community/code-of-conduct)을 준수해야 함을 기억하세요! diff --git a/public/content/translations/ko/community/grants/index.md b/public/content/translations/ko/community/grants/index.md new file mode 100644 index 00000000000..e761ec699c4 --- /dev/null +++ b/public/content/translations/ko/community/grants/index.md @@ -0,0 +1,68 @@ +--- +title: "이더리움 재단 및 커뮤니티 보조금 프로그램" +description: "이더리움 생태계 전체의 보조금 프로그램 목록." +lang: ko +--- + +# 이더리움 보조금 {#ethereum-grants} + +아래에 나열된 프로그램은 이더리움 생태계의 성공과 성장을 촉진하는 프로젝트에 다양한 자금 지원을 제공합니다. 이것을 가이드로 사용하여 다음 Ethereum 프로젝트를 성공시키는 데 도움이 되는 자금을 찾고 신청하십시오. + +이 목록은 커뮤니티에서 선별한 것입니다. 빠진 부분이나 잘못된 부분이 있다면 이 페이지를 수정해주세요! + + + +
창업자 여러분, 비즈니스 성장에 도움이 필요하신가요? [창업자 지원 페이지로 이동하기](/founders/)
+
+ +## 광범위한 이더리움 생태계 {#broad-ethereum-ecosystem} + +이러한 프로그램은 광범위한 프로젝트에 보조금을 제공함으로써 광범위한 이더리움 생태계를 지원합니다. 여기에는 확장성, 커뮤니티 구축, 보안, 개인 정보 보호 등을 위한 솔루션이 포함됩니다. 이러한 보조금은 특정 이더리움 플랫폼에 국한되지 않으며 확실하지 않은 경우 시작하는 것이 좋습니다. + +- [EF 생태계 지원 프로그램](https://esp.ethereum.foundation) - _범용 도구, 인프라, 연구 및 공공재에 특히 중점을 두고 이더리움에 도움이 되는 오픈소스 프로젝트에 자금을 지원합니다_ +- [학술 보조금](https://esp.ethereum.foundation/academic-grants) - _이더리움 관련 학술 연구를 지원하는 보조금_ + +## 보조금 목록 애그리게이터 및 플랫폼 {#grant-list-aggregators} + +이러한 자료는 이더리움 생태계 전반의 다양한 보조금 기회를 수집하고 정리하여 프로젝트의 필요에 맞는 자금 지원 기회를 더 쉽게 찾을 수 있도록 합니다. 특정 자금 지원 필요에 따라 가장 관련성 높은 자료를 찾는 데 도움이 되도록 페르소나별로 정리했습니다. + +### 모든 보조금 신청자 대상: 종합 디렉터리 {#comprehensive-directories} + +이러한 일반 플랫폼은 전체 웹3 공간에 걸쳐 보조금을 폭넓게 다루며, 자금을 찾는 모든 이들에게 유용한 시작점이 됩니다. + +- [Blockworks Grantfarm](https://blockworks.co/grants/programs) - _Blockworks에서 모든 보조금, RFP 및 버그 바운티에 대한 종합 디렉터리를 정리했습니다._ +- [Blockchain Grants](https://www.blockchaingrants.org/) - _블록체인 및 암호화폐 보조금 디렉터리_ +- [Karma Funding Map](https://gap.karmahq.xyz/funding-map) - 모든 웹3 보조금 프로그램 디렉터리, 매주 업데이트 + +### 개발자 및 빌더 대상 {#for-developers-and-builders} + +- [Grant Programs Viewer](https://airtable.com/shr86elKgWTSCP4AY) - _보조금 프로그램의 공개 Airtable 데이터베이스_ +- [Web3 Grants Spreadsheet](https://docs.google.com/spreadsheets/d/1c8koZCI-GLnD8MG-eFcXPOBCNu1v8-aXIfwAAvc7AMc/edit#gid=0) - _웹3 보조금 기회에 대한 Google 스프레드시트_ +- [Arbitrum Grants](https://arbitrum.foundation/grants) — Arbitrum DAO 및 [The Arbitrum Foundation](https://arbitrum.foundation/) + +### 디파이 프로젝트 및 금융 애플리케이션 대상 {#for-defi-projects} + +- [LlamaoGrants](https://wiki.defillama.com/wiki/LlamaoGrants) - _디파이 라마(DeFi Llama)의 보조금 프로그램 디렉터리_ +- [AlphaGrowth Grants](https://alphagrowth.io/crypto-web3-grants-list) - _암호화폐 및 웹3 보조금 종합 목록_ +- [Uniswap Foundation Grants](https://www.uniswapfoundation.org/build) - _디파이 빌더를 위한 Unichain 및 Uniswap v4 보조금 및 지원_ + +### DAO 기여자 및 거버넌스 혁신가 대상 {#for-dao-contributors} + +커뮤니티 주도 프로젝트 및 거버넌스 실험을 위한 자료: + +- [DAO Grants](https://docs.google.com/spreadsheets/d/1XHc-p_MHNRdjacc8uOEjtPoWL86olP4GyxAJOFO0zxY/edit#gid=0) - _보조금을 제공하는 기관의 Google 스프레드시트_ +- [MetaGov Database](https://docs.google.com/spreadsheets/d/1e5g-dlWWsK2DZoZGBgfxyfGNSddLk-V7sLEgfPjEhbA/edit#gid=780420708) - _종합 웹3 보조금 맵_ + +### 공공재 및 영향력 {#public-goods-and-impact} + +이 프로그램들은 더 넓은 커뮤니티, 공공재, 영향력 이니셔티브에 혜택을 주는 프로젝트에 자금을 지원하는 데 중점을 둡니다. 여기에는 [이차 펀딩](/defi/#quadratic-funding)을 포함한 온체인 자금 할당 메커니즘을 활용하는 보조금 제공자 및 기부 플랫폼이 포함됩니다. + +- [Gitcoin](https://www.gitcoin.co/program) - _Gitcoin Grants는 여러 자본 할당 메커니즘을 활용하여 이더리움 생태계 내 오픈소스 프로젝트와 공공재에 자금을 지원합니다_ +- [Octant](https://octant.app/home) - _공동선과 개인의 재정적 자율권의 균형을 맞추는 공공재 자금 지원 생태계_ +- [Giveth](https://giveth.io/) - _공익 프로젝트에 추가 수수료 없이 직접 기부할 수 있는 암호화폐 기부 플랫폼_ +- [Artizen](https://artizen.fund/) - _예술, 과학, 기술, 문화의 최전선에 있는 크리에이터들이 새로운 프로젝트를 위한 매칭 펀드를 조성하도록 돕습니다_ +- [Quadratic Accelerator](https://qacc.giveth.io/) - _이차 펀딩을 사용하여 공익에 기여하는 프로젝트를 지원하는 스타트업 액셀러레이터 프로그램_ + +## 이더리움 분야에서 일하기 {#work-in-ethereum} + +나만의 프로젝트를 시작할 준비가 안 되었나요? 수백 개의 회사가 이더리움 생태계에서 일하고 기여할 열정적인 인재를 적극적으로 찾고 있습니다. 더 많은 정보를 원하시나요? [이더리움 관련 채용 정보 확인하기](/community/get-involved/#ethereum-jobs) diff --git a/public/content/translations/ko/community/language-resources/index.md b/public/content/translations/ko/community/language-resources/index.md new file mode 100644 index 00000000000..38db67d0738 --- /dev/null +++ b/public/content/translations/ko/community/language-resources/index.md @@ -0,0 +1,153 @@ +--- +title: "언어 참고 자료" +description: "영어로 되어있지 않은 이더리움 학습 참고 자료" +lang: ko +--- + +# 언어별 참고 자료 {#language-resources} + +이더리움 커뮤니티는 세계적이며 영어를 사용하지 않는 수 백만 명의 사람들도 커뮤니티의 일원입니다. + +저희 목표는 모든 언어로 교육 콘텐츠를 제공하고, 전 세계 사람들이 이더리움을 접하는 데 어려움을 느끼게 하는 언어 장벽을 극복하도록 돕는 것입니다. + +모국어로 되어 있거나 영어로 되어 있지 않은 자료를 선호한다면 아래에서 영어로 되어있지 않은 유용한 참고 자료 목록을 찾아볼 수 있습니다. 수십만 명의 이더리움 지지자들이 이러한 온라인 포럼에 모여 소식을 공유하고, 최근 개발 동향에 관해 이야기하며, 기술적인 문제에 대해 토론하고, 미래를 상상합니다. + +사용하시는 언어로 된 교육 자료를 알고 계신가요? [이슈를 등록](https://github.com/ethereum/ethereum-org-website/issues/new/choose)해서 목록에 추가해 주세요! + +## Ethereum.org 참고 자료 {#ethereum-org} + +Ethereum.org는 40개 이상의 언어로 번역되어 있으며, 모든 페이지 상단에 있는 언어 선택 메뉴를 사용하여 찾을 수 있습니다. + +![언어 선택 메뉴](./language-selector-menu.png) + +만약 2개 국어 구사가 가능하고 저희가 더 많은 사람들에게 다가갈 수 있도록 돕고 싶다면 [ethereum.org 번역 프로그램](/contributing/translation-program/#translation-program)에 참여하여 웹사이트 번역을 도와주실 수 있습니다. + +## 커뮤니티 참고 자료 {#community} + +### 포르투갈어(브라질) {#br-pt} + +**뉴스** + +- [BeInCrypto](http://www.beincrypto.com.br) - 브라질에서 사용 가능한 거래소 목록을 포함한 암호화폐 뉴스 및 기사 +- [Cointelegraph](http://cointelegraph.com.br/category/analysis) - 주요 암호화폐 뉴스 매체인 Cointelegraph의 브라질 버전 +- [Livecoins](http://www.livecoins.com.br/ethereum) - 암호화폐 뉴스 및 도구 +- [Seudinheiro](http://www.seudinheiro.com/criptomoedas/) - 암호화폐 뉴스 및 보고서 +- [Modular Crypto](https://modularcrypto.xyz/) - 암호화폐 뉴스 및 교육 기사 + +**교육** + +- [web3dev](https://www.web3dev.com.br/) - 웹3 개발자를 위한 콘텐츠 허브 및 Discord 커뮤니티. +- [Web3Brasil](https://github.com/web3brasil/web3brasil) - Web3 및 DeFi 학습을 위한 참고 자료 +- [CriptoFacil](http://www.criptofacil.com/ultimas-noticias/) - '초보자를 위한 이더리움', '초보자를 위한 DeFi'를 포함한 암호화폐 뉴스 및 교육 +- [CriptoAtivos](http://www.criptoativos.wiki.br/) - 암호화폐 분야에 대한 인사이트, 교육 및 블로그 +- [Cointimes](http://www.cointimes.com.br/) - 암호화폐 뉴스 및 교육 +- [Web3 스타터 팩](https://docs.google.com/document/d/1X8PSTFH7FTw9J-gbKWM6Y430SWCBT8d4t4pJgFQHJ8E/) - 가장 자주 묻는 핵심 암호화폐 질문에 답변하는 가이드 + +### 중국어 {#zh} + +**일반 참고 자료** + +- [Ethereum.cn](https://www.ethereum.cn/) - 커뮤니티가 유지 관리하는 콘텐츠, 합의 레이어 업그레이드, 모든 핵심 개발자 회의록, 레이어 2 등을 다룹니다. +- [EthFans](https://github.com/editor-Ajian/EthFans.org-annual-collected-works/) - 기초부터 고급 이더리움 주제까지 모든 것을 학습 +- [Unitimes](https://mp.weixin.qq.com/s/tvloZSDBSOQN9zDQj_91kA) - 이더리움, DeFi, NFT, Web3 관련 지식을 다루는 커뮤니티 유지 관리 콘텐츠 +- [123ETH](https://123eth.org/) - 이더리움 생태계로의 포털 +- [Zhen Xiao](http://zhenxiao.com/blockchain/) - 암호화폐 및 그 애플리케이션에 대한 무료 온라인 강좌 +- [이더리움 백서](/zh/whitepaper/) - 이더리움 백서 중국어 버전 + +**이더리움 생태계** + +- [ETHPlanet](https://www.ethplanet.org/) - 대학생에게 교육을 제공하는 온라인 및 오프라인 해커톤 +- [PrimitivesLane](https://www.primitiveslane.org/) - 블록체인 기술에 중점을 둔 비영리 연구 그룹 +- [Ethereum Translation Community CN](https://www.notion.so/Ethereum-Translation-Community-CN-05375fe0a94c4214acaf90f42ba40171) - 이더리움 교육 콘텐츠 번역에 전념하는 커뮤니티 + +**개발자를 위한 자료** + +- [DappLearning](https://github.com/Dapp-Learning-DAO/Dapp-Learning) - 주류 탈중앙화앱 프로젝트를 연구하고 매주 생각과 의견을 공유하는 학습 그룹 +- [LearnBlockchain](https://learnblockchain.cn/) - 블록체인 기술에 대한 정보를 공유하는 개발자 커뮤니티 + +**암호학 연구자를 위한 자료** + +- [SecbitLabs](https://mp.weixin.qq.com/s/69_tqBJpr_sbaKtR1sBRMw) - 암호학, 보안 등을 설명하는 WeChat 계정 +- [Sparkbyte](https://mp.weixin.qq.com/s/9KgKTc_jtJ7bWKdbNPoqvQ) - zk 기술을 설명하는 WeChat 계정 + +### 체코어 {#cs} + +- [Gwei.cz](https://gwei.cz) - 교육 콘텐츠를 만들고 온라인 및 오프라인 이벤트를 주최하는 Web3 관련 지역 커뮤니티 +- [Gwei.cz Příručka](https://prirucka.gwei.cz/) - 초보자를 위한 이더리움 가이드 +- [DAO Příručka](https://dao.gwei.cz/) - 초보자를 위한 DAO 가이드 +- [Mastering Ethereum](https://ipfs.io/ipfs/bafybeidvuxhnsgfx3tncpfxheqglkjwmdxclknlgd7s7qggd2a6bzgb27m) - Mastering Ethereum 체코어 버전 + +### 프랑스어 {#fr} + +- [Ethereum France](https://www.ethereum-france.com/) - Ethereum France는 이더리움 관련 이벤트를 주최하고 콘텐츠를 제작하며 토론을 장려합니다. +- [Ethereum.fr](https://ethereum.fr/) - 이더리움 뉴스 및 교육 +- [BanklessFR](https://banklessfr.substack.com/) - 프랑스어 Bankless 뉴스레터 +- [CryptoFR](https://cryptofr.com/category/44/ethereum-general) - 이더리움 하위 페이지가 있는 암호화폐 포럼 + +### 독일어 {#de} + +- [Microsoft Learn (Solidity)](https://docs.microsoft.com/de-de/learn/modules/blockchain-learning-solidity/) - Solidity 사용법 +- [Microsoft Learn (스마트 계약)](https://docs.microsoft.com/de-de/learn/modules/blockchain-solidity-ethereum-smart-contracts/) - Solidity를 이용한 이더리움 스마트 계약 작성 +- [Microsoft Learn (이더리움 네트워크)](https://docs.microsoft.com/de-de/learn/modules/blockchain-ethereum-networks/) - 이더리움 네트워크 연결 및 배포 +- [Microsoft Learn (블록체인)](https://docs.microsoft.com/de-de/learn/paths/ethereum-blockchain-development/) - 블록체인 개발 입문 + +### 히브리어 {#he} + +- [Udi Wertheimer - 비트코이너가 이더리움으로부터 배울 수 있는 것](https://www.cryptojungle.co.il/udi-wertheimer-what-bitcoiners-can-learn-from-ethereum/) +- [Omer Greismen (OpenZeppelin) - 150억 달러 스마트 계약 해킹을 막은 방법](https://www.cryptojungle.co.il/omer-greisman-openzeppelin/) +- [Shy Datika(INX) - 토큰화와 증권의 미래, 이더리움은 증권인가](https://www.cryptojungle.co.il/shy-datika-tokenization/) +- [Roy Confino (Lemonade) - 이더리움에서의 보험](https://www.cryptojungle.co.il/roy-confino-insurance/) +- [Idan Ofrat (Fireblocks) - 기관 채택](https://www.cryptojungle.co.il/idan-ofrat-fireblocks/) +- [Gal Weizman (MetaMask) - MetaMask란 무엇인가](https://www.cryptojungle.co.il/gal-weizman-metamask/) +- [Dror Aviely (Consensys) - 이더리움의 중심](https://www.cryptojungle.co.il/dror-aviely-ethereum-center/) +- [Nir Rozin - 크립토펑크가 된다는 것](https://www.cryptojungle.co.il/nir-rozin-cryptopunk/) +- [Adan Kedem - 게이밍 & 메타버스](https://www.cryptojungle.co.il/adan-kedem-web3-gaming/) +- [Uri Kolodny (Starkware) - 이더리움과 블록체인 레이어](https://www.cryptojungle.co.il/uri-kolodny-starkware/) +- [Udi Wertheimer - 이더리움 2.0 대 경쟁](https://www.cryptojungle.co.il/udi-on-eth2/) +- [Ben Samocha (본인) - 이더리움 2.0 - 기회인가?](https://www.cryptojungle.co.il/etherurm2-week-summary/) +- [Alon Muroch (Bloxstaking) - 이더리움 2.0이란 무엇인가?](https://www.cryptojungle.co.il/alon-moroch-eth2/) +- [Eilon Aviv (Collider Ventures) - 이더리움 2.0에서 무엇이 잘못될 수 있을까](https://www.cryptojungle.co.il/eilon-aviv-eth2-0/) +- [Eilon Aviv (Collider Ventures) - 왜 이더리움 2.0이 필요한가](https://www.cryptojungle.co.il/eilon-aviv-ethereum-2-0/) + +### 이탈리아어 {#it} + +- [Ethereum Italia](https://www.ethereum-italia.it/) - 스마트 계약 및 블록체인 기술에 중점을 둔 이더리움 교육, 이벤트 및 뉴스 +- [Ethereum Italia Podcast](https://www.ethereum-italia.it/podcast/) - 이탈리아어로 진행되는 이더리움 팟캐스트 +- [Microsoft Learn (Solidity)](https://docs.microsoft.com/it-it/learn/modules/blockchain-learning-solidity/) - Solidity 사용법 학습 +- [Microsoft Learn (스마트 계약)](https://docs.microsoft.com/it-it/learn/modules/blockchain-solidity-ethereum-smart-contracts/) - Solidity를 사용한 스마트 계약 작성에 대해 알아보기 +- [Microsoft Learn (탈중앙화앱)](https://docs.microsoft.com/it-it/learn/modules/blockchain-create-ui-decentralized-apps/) - 탈중앙화 애플리케이션을 사용하여 사용자 인터페이스 만들기 + +### 일본어 {#ja} + +- [일본 가상자산 및 암호자산 거래소 협회](https://jvcea.or.jp/) +- [일본 암호자산 비즈니스 협회](https://cryptocurrency-association.org/) +- [블록체인 개발 시작하기 - Learn | Microsoft Docs](https://docs.microsoft.com/ja-jp/learn/paths/ethereum-blockchain-development/) - 이 학습 과정은 이더리움 플랫폼에서의 블록체인 및 개발을 소개합니다. +- [Mastering Ethereum](https://www.oreilly.co.jp/books/9784873118963/) - Mastering Ethereum 일본어 버전 +- [Hands-On Smart Contract Development with Solidity and Ethereum](https://www.oreilly.co.jp/books/9784873119342/) - 일본어판 Hands-On Smart Contract Development with Solidity and Ethereum + +### 러시아어 {#ru} + +- [Cyber Academy](https://cyberacademy.dev) - Web3 빌더를 위한 교육 공간 +- [Forklog](https://forklog.com) - 암호화폐 전반에 대한 뉴스 및 교육 기사, 기존 기술 및 다양한 블록체인의 향후 업그레이드 +- [BeInCrypto](https://ru.beincrypto.com) - 뉴스, 암호화폐 가격 분석 및 암호화폐의 모든 것에 대한 간단한 설명을 담은 비기술적인 기사 + +### 스페인어 {#es} + +- [Ethereum Madrid](https://ethereummadrid.com/) - 블록체인, DeFi 및 거버넌스 강좌, 이벤트 및 블로그 +- [Cointelegraph](https://es.cointelegraph.com/ethereum-for-beginners) - 스페인어로 된 초보자용 이더리움 가이드 +- [Tutoriales online](https://tutoriales.online/curso/solidity) - Solidity 및 이더리움 프로그래밍 학습 +- [Curso Introducción a Ethereum Development](https://youtube.com/playlist?list=PLTqiwJDd_R8y9pfUBjhkVa1IDMwyQz-fU) - Solidity 기초, 첫 스마트 계약 테스트 및 배포 +- [Curso Introducción a Seguridad y Hacking en Ethereum](https://youtube.com/playlist?list=PLTqiwJDd_R8yHOvteko_DmUxUTMHnlfci) - 실제 스마트 계약의 일반적인 취약점과 보안 문제 이해 +- [Curso Introducción a DeFi Development](https://youtube.com/playlist?list=PLTqiwJDd_R8zZiP9_jNdaPqA3HqoW2lrS) - Solidity에서 DeFi 스마트 계약이 작동하는 방식을 배우고 자신만의 자동화된 마켓 메이커를 만들어 보세요. +- [Cryptoversidad](https://www.youtube.com/c/Cryptoversidad) - 초급부터 고급까지 비기술적인 블록체인 교육. 암호화폐와 이더리움에 대한 모든 것을 배우세요. + +### 터키어 {#tr} + +- [BTK Akademi](https://www.btkakademi.gov.tr/portal/course/blokzincir-ve-kripto-paralar-10569#!/about) - 블록체인 및 암호화폐 중심 강좌 +- [대규모 이름 변경: Eth2에 무슨 일이 있었나요?](https://miningturkiye.org/konu/ethereum-madenciligi-bitiyor-mu-onemli-gelisme.655/) - 'Eth2' 용어 사용 중단을 설명하는 대규모 이름 변경 블로그 게시물의 터키어 번역본 + +### 베트남어 {#vi} + +- [Tino Group](https://wiki.tino.org/ethereum-la-gi/) - 이더리움, 탈중앙화앱, 지갑 및 자주 묻는 질문(FAQ) 개요 +- [Tap Chi Bitcoin](https://tapchibitcoin.io/tap-chi/tin-tuc-ethereum-eth) - 이더리움 뉴스 및 교육 하위 페이지가 있는 웹 플랫폼 +- [Coin68](https://coin68.com/ethereum-tieu-diem/) - 이더리움 뉴스 및 교육 콘텐츠가 있는 암호화폐 포털 diff --git a/public/content/translations/ko/community/online/index.md b/public/content/translations/ko/community/online/index.md new file mode 100644 index 00000000000..87da0058edd --- /dev/null +++ b/public/content/translations/ko/community/online/index.md @@ -0,0 +1,74 @@ +--- +title: "온라인 커뮤니티" +description: "이더리움 애호가들이 모여 토론하고 협력하는 온라인 포럼, 대화방, 소셜 미디어 커뮤니티를 찾아보세요." +lang: ko +--- + +# 온라인 커뮤니티 {#online-communities} + +수십만 명의 이더리움 지지자들이 이러한 온라인 포럼에 모여 소식을 공유하고, 최근 개발 동향에 관해 이야기하며, 기술적인 문제에 대해 토론하고, 미래를 상상합니다. + +## 등재 정책 {#listing-policy} + +ethereum.org는 등재된 커뮤니티의 무결성과 가치를 유지하기 위해 다음과 같이 엄격한 자격 심사 정책을 적용합니다: + +### 자격 기준 {#eligibility-criteria} + +- **관련성**: 커뮤니티는 이더리움 및 그 생태계와 직접적으로 관련이 있어야 합니다. +- **활동 수준**: 커뮤니티는 정기적인 교류, 게시물 또는 토론으로 활성화되어야 합니다. 활동이 없거나 비활성 상태인 커뮤니티는 삭제될 수 있습니다. +- **포용성**: 커뮤니티는 다양성을 존중하고 모든 배경의 사람들이 참여할 수 있도록 환영하는 분위기를 조성해야 합니다. +- **비상업적 초점**: 등재는 상업적이거나 홍보용 플랫폼이 아닌 커뮤니티 중심 공간을 위한 것입니다. + +### 콘텐츠 가이드라인 {#content-guidelines} + +- **적절한 콘텐츠**: 커뮤니티는 스팸, 증오심 표현, 괴롭힘 또는 불법 활동을 조장하는 콘텐츠를 피하기 위해 자체적인 운영 가이드라인을 보유해야 합니다. +- **언어**: 영어가 기본 언어이지만, 포용적이고 존중하는 분위기를 유지하는 한 다른 언어로 된 커뮤니티도 제출할 수 있습니다. +- **투명성**: 커뮤니티의 목적, 규칙, 중재자에 대한 명확한 정보가 회원들에게 제공되어야 합니다. + +### 기타 권장 사항 {#other-recommendations} + +- **접근성**: 커뮤니티 포럼은 가입이나 등록 없이 누구나 읽을 수 있도록 접근 가능해야 합니다. +- **Discord 서버 초대**: 신뢰할 수 있는 Discord 서버 초대만 ethereum.org에 추가하는 것을 권장합니다. 초대 링크는 웹사이트의 커뮤니티 페이지(예: [ethglobal.com/discord](https://ethglobal.com/discord))로 연결되거나 공식 URL(예: [discord.gg/ethstaker](https://discord.gg/ethstaker) 또는 [discord.com/invite/ethstaker](https://discord.com/invite/ethstaker))에서 제공되는 것이 이상적입니다. + +이 가이드라인에 따라 커뮤니티를 추가하거나 제거해야 한다고 생각되시면, [GitHub 리포지토리에서 이슈를 제기](https://github.com/ethereum/ethereum-org-website/issues)해 주세요. + +## 포럼 {#forums} + +r/ethereum - 이더리움의 모든 것 +r/ethfinance - 디파이(DeFi)를 포함한 이더리움의 금융 측면 +r/ethdev - 이더리움 개발에 중점 +r/ethtrader - 트렌드 및 시장 분석 +r/ethstaker - 이더리움 스테이킹에 관심 있는 모든 분들을 환영합니다 +Fellowship of Ethereum Magicians - 이더리움의 기술 표준 중심 커뮤니티 +Ethereum Stackexchange - 이더리움 개발자들을 위한 토론 및 도움 +Ethereum Research - 암호경제학 연구를 위한 가장 영향력 있는 게시판 + +## 대화방 {#chat-rooms} + +Ethereum Cat Herders - 이더리움 개발에 프로젝트 관리 지원을 제공하는 커뮤니티 +Ethereum Hackers - ETHGlobal이 운영하는 Discord 대화방: 전 세계 이더리움 해커를 위한 온라인 커뮤니티 +CryptoDevs - 이더리움 개발 중심 Discord 커뮤니티 +EthStaker Discord - 기존 및 잠재적 스테이커를 위한 커뮤니티 운영 안내, 교육, 지원 및 참고 자료 +Ethereum.org website team - 팀 및 커뮤니티 구성원과 함께 ethereum.org 웹 개발 및 디자인에 대해 이야기해 보세요 +Matos Discord - 빌더, 업계 주요 인물, 이더리움 애호가들이 모이는 웹3 크리에이터 커뮤니티 저희는 웹3 개발, 디자인 및 문화에 열정적입니다. 함께 만들어 가요. +Solidity Gitter - 솔리디티 개발을 위한 채팅방(Gitter) +Solidity Matrix - 솔리디티 개발을 위한 채팅방(Matrix) +Ethereum Stack Exchange - 질문과 답변 포럼 +Peera Community Forum - 탈중앙화된 질문과 답변 포럼 + +## YouTube 및 X(구 Twitter) {#youtube-and-twitter} + +Ethereum Foundation - 이더리움 재단의 최신 소식을 받아보세요 +@ethereum - 커뮤니티를 위한 이더리움 메인 계정 +@ethereumfndn - 이더리움 재단 공식 계정 +@ethdotorg - 성장하는 글로벌 커뮤니티를 위해 구축된 이더리움 포털 + + + + +
+ + DAO에 대해 자세히 알아보기 + +
+
diff --git a/public/content/translations/ko/community/research/index.md b/public/content/translations/ko/community/research/index.md new file mode 100644 index 00000000000..bcbd7245cce --- /dev/null +++ b/public/content/translations/ko/community/research/index.md @@ -0,0 +1,399 @@ +--- +title: "이더리움 연구의 주요 동향" +description: "공개 연구의 다양한 분야를 살펴보고 참여 방법을 알아보세요." +lang: ko +--- + +# 이더리움 연구의 주요 동향 {#active-areas-of-ethereum-research} + +이더리움의 주요 강점 중 하나는 활발한 연구 및 엔지니어링 커뮤니티가 지속적으로 개선하고 있다는 점입니다. 전 세계의 많은 열정적이고 숙련된 사람들이 이더리움의 뛰어난 이슈에 관심을 갖고 있지만, 그 이슈가 무엇인지 알아내는 것은 항상 쉬운 일은 아닙니다. 이 페이지는 이더리움의 첨단 분야를 대략적으로 안내하기 위해 주요 활성 연구 분야를 간략하게 소개합니다. + +## 이더리움 연구 방식 {#how-ethereum-research-works} + +이더리움 연구는 개방적이고 투명하며, [탈중앙화 과학 (DeSci)](https://hackernoon.com/desci-decentralized-science-as-our-chance-to-recover-the-real-science)의 원칙을 구현합니다. 연구 문화는 실행 가능한 노트북과 같이 도구와 결과물을 최대한 활용하여 연구를 활용하는 것입니다. 이더리움 연구는 신속하게 이루어지며, 새로운 발견 사항은 동료들의 검토를 거친 후 [ethresear.ch](https://ethresear.ch/)과 같은 포럼에서 공개적으로 게시 및 토론됩니다. + +## 일반 연구 자료 {#general-research-resources} + +특정 주제에 국한되지 않고, [ethresear.ch](https://ethresear.ch)와 [Eth R&D Discord channel](https://discord.gg/qGpsxSA) 채널을 통해 이더리움 연구와 관련된 다양한 정보를 얻을 수 있습니다. 이곳은 이더리움 연구자들이 최신 아이디어와 개발 기회를 논의하는 주요 장소입니다. + +DelphiDigital이 2022년 5월에 발행한 [이 보고서](https://members.delphidigital.io/reports/the-hitchhikers-guide-to-ethereum)는 이더리움 로드맵에 대한 훌륭한 개요를 제공합니다. + +## 자금 출처 {#sources-of-funding} + +이더리움 연구에 참여하고, 그에 따른 보상을 받으세요! 예를 들어, [이더리움 재단](/foundation/)은 최근 [학술 연구 지원금 공모](https://esp.ethereum.foundation/academic-grants)를 진행했습니다. [이더리움 보조금 페이지](/community/grants/)에서 현재 진행 중이거나 예정된 자금 지원 기회에 대한 정보를 확인할 수 있습니다. + +## 프로토콜 연구 {#protocol-research} + +프로토콜 연구는 이더리움의 기본 계층, 즉 노드가 어떻게 연결하고, 통신하고, 교환하고, 이더리움 데이터를 저장하고, 블록체인 상태에 대한 합의에 도달하는지를 정의하는 규칙 세트와 관련이 있습니다. 프로토콜 연구는 다음과 같은 주요 두 가지 범주로 나뉩니다: 합의와 실행. + +### 합의 {#consensus} + +합의 연구는 [이더리움의 지분 증명 메커니즘](/developers/docs/consensus-mechanisms/pos/)과 관련이 있습니다. 합의 연구의 예시 주제는 다음과 같습니다: + +- - 취약점 식별 및 패치; +- 암호경제학적 보안 수준 측정; +- - 클라이언트 구현의 보안 또는 성능 향상; +- 그리고 경량 클라이언트를 개발합니다. + +미래 지향적인 연구 외에도, 단일 슬롯 확정과 같이 프로토콜의 근본적인 재설계에 대한 연구가 진행되어 이더리움의 상당한 개선을 가능하게 합니다. 또한, 합의 클라이언트 간의 P2P 네트워크의 효율성, 안전성 및 모니터링 또한 중요한 연구 주제입니다. + +#### 배경 자료 {#background-reading} + +- [지분 증명 소개](/developers/docs/consensus-mechanisms/pos/) +- [Casper-FFG 논문](https://arxiv.org/abs/1710.09437) +- [Casper-FFG 설명](https://medium.com/unitychain/intro-to-casper-ffg-9ed944d98b2d) +- [Gasper 논문](https://arxiv.org/abs/2003.03052) + +#### 최근 연구 {#recent-research} + +- [Ethresear.ch 합의](https://ethresear.ch/c/consensus/29) +- [가용성/완결성 딜레마](https://arxiv.org/abs/2009.04987) +- [단일 슬롯 확정성](https://ethresear.ch/t/a-model-for-cumulative-committee-based-finality/10259) +- [제안자-빌더 분리](https://notes.ethereum.org/@vbuterin/pbs_censorship_resistance) + +### 실행 {#execution} + +실행 레이어는 트랜잭션 실행, [이더리움 가상 머신(EVM)](/developers/docs/evm/) 실행, 그리고 실행 페이로드를 생성하여 합의 레이어에 전달하는 것과 관련이 있습니다. 연구가 활발하게 진행 중인 분야는 다음과 같습니다: + +- 경량 클라이언트 지원 구축; +- 가스 한도 연구; +- 그리고 새로운 데이터 구조 도입(예: Verkle Tries). + +#### 배경 지식 {#background-reading-1} + +- [EVM 소개](/developers/docs/evm) +- [Ethresear.ch 실행 레이어](https://ethresear.ch/c/execution-layer-research/37) + +#### 최근 연구 {#recent-research-1} + +- [데이터베이스 최적화](https://github.com/ledgerwatch/erigon/blob/devel/docs/programmers_guide/db_faq.md) +- [상태 만료](https://notes.ethereum.org/@vbuterin/state_expiry_eip) +- [상태 만료 경로](https://hackmd.io/@vbuterin/state_expiry_paths) +- [Verkle과 상태 만료 제안](https://notes.ethereum.org/@vbuterin/verkle_and_state_expiry_proposal) +- [히스토리 관리](https://eips.ethereum.org/EIPS/eip-4444) +- [Verkle 트리](https://vitalik.eth.limo/general/2021/06/18/verkle.html) +- [데이터 가용성 샘플링](https://github.com/ethereum/research/wiki/A-note-on-data-availability-and-erasure-coding) + +## 클라이언트 개발 {#client-development} + +이더리움 클라이언트는 이더리움 프로토콜을 구현한 것입니다. 클라이언트 개발은 프로토콜 연구의 결과를 클라이언트라는 형태로 현실화하는 과정입니다. 클라이언트 개발에는 클라이언트 사양을 업데이트하는 것과 더불어 구체적인 구현을 구축하는 것도 포함됩니다. + +이더리움 노드를 실행하려면 다음 두 개의 소프트웨어가 필요합니다: + +1. 블록체인의 헤드를 추적하고, 블록을 네트워크에 전파하며, 합의 로직을 처리하기 위한 합의 클라이언트 +2. 이더리움 가상 머신을 지원하고, 트랜잭션과 스마트 컨트랙트를 실행하기 위한 실행 클라이언트 + +노드 및 클라이언트에 대한 더 자세한 내용과 현재 모든 클라이언트 구현 목록은 [노드 및 클라이언트 페이지](/developers/docs/nodes-and-clients/)를 참고하세요. 이더리움 업그레이드 이력은 [히스토리 페이지](/ethereum-forks/)에서 확인할 수 있습니다. + +### 실행 클라이언트 {#execution-clients} + +- [실행 클라이언트 사양](https://github.com/ethereum/execution-specs) +- [실행 API 사양](https://github.com/ethereum/execution-apis) + +### 합의 클라이언트 {#consensus-clients} + +- [합의 클라이언트 사양](https://github.com/ethereum/consensus-specs) +- [비콘 API 사양](https://ethereum.github.io/beacon-APIs/#/Beacon/getStateRoot) + +## 확장성 및 성능 {#scaling-and-performance} + +이더리움 확장은 이더리움 연구자들이 집중하는 주요 분야입니다. 현재의 접근 방식으로는 트랜잭션을 롤업으로 오프로드하고, 데이터 블롭을 사용하여 가능한 한 저렴하게 만드는 방법이 있습니다. 이더리움 확장 관련 정보는 [확장 페이지](/developers/docs/scaling)에서 확인할 수 있습니다. + +### 레이어 2 {#layer-2} + +현재 여러 개의 레이어 2 프로토콜이 존재하며, 이들은 다양한 방식으로 트랜잭션을 일괄 처리하고 이를 이더리움 레이어 1 에 안전하게 기록함으로써 이더리움의 확장성을 높이고 있습니다. 이 분야는 연구 개발 잠재력이 매우 높으며 빠르게 성장하고 있습니다. + +#### 배경 지식 {#background-reading-2} + +- [레이어 2 소개](/layer-2/) +- [Polynya: 롤업, DA 및 모듈형 체인](https://polynya.medium.com/rollups-data-availability-layers-modular-blockchains-introductory-meta-post-5a1e7a60119d) + +#### 최근 연구 {#recent-research-2} + +- [Arbitrum 시퀀서를 위한 공정 주문](https://eprint.iacr.org/2021/1465) +- [Ethresear.ch 레이어 2](https://ethresear.ch/c/layer-2/32) +- [롤업 중심 로드맵](https://ethereum-magicians.org/t/a-rollup-centric-ethereum-roadmap/4698) +- [L2Beat](https://l2beat.com/) + +### 브리지 {#bridges} + +레이어 2 의 더 많은 연구 개발이 필요한 부분은 안전하고 효율적인 브리지입니다. 여기에는 다양한 레이어 2 간의 브리지와 레이어 1 과 레이어 2 간의 브리지가 포함됩니다. 브리지는 해커의 주요 공격 대상이므로, 이는 특히 중요한 연구 분야입니다. + +#### 배경 지식 {#background-reading-3} + +- [블록체인 브리지에 대한 소개](/bridges/) +- [비탈릭이 말하는 브리지](https://old.reddit.com/r/ethereum/comments/rwojtk/ama_we_are_the_efs_research_team_pt_7_07_january/hrngyk8/) +- [블록체인 브리지 관련 글](https://medium.com/1kxnetwork/blockchain-bridges-5db6afac44f8) +- [브리지에 묶인 가치](https://dune.com/eliasimos/Bridge-Away-\(from-Ethereum\)) + +#### 최근 연구 {#recent-research-3} + +- [검증형 브리지](https://stonecoldpat.github.io/images/validatingbridges.pdf) + +### 샤딩 {#sharding} + +이더리움 블록체인 샤딩은 오랫동안 개발 로드맵의 일부였습니다. 하지만 "댕크샤딩"과 같은 새로운 확장성 솔루션이 현재 중심적인 역할을 하고 있습니다. + +완전한 댕크샤딩의 전 단계로 알려진 프로토-댕크샤딩은 칸쿤-데네브 ("덴쿤") 네트워크 업그레이드를 통해 활성화되었습니다. + +[Dencun 업그레이드에 대해 더 알아보기](/roadmap/dencun/) + +#### 배경 지식 {#background-reading-4} + +- [프로토-댕크샤딩 관련 자료](https://notes.ethereum.org/@vbuterin/proto_danksharding_faq) +- [Bankless 댕크샤딩 비디오](https://www.youtube.com/watch?v=N5p0TB77flM) +- [이더리움 샤딩 연구 자료 모음](https://notes.ethereum.org/@serenity/H1PGqDhpm?type=view) +- [댕크샤딩 (Polynya)](https://polynya.medium.com/danksharding-36dc0c8067fe) + +#### 최근 연구 {#recent-research-4} + +- [EIP-4844: 프로토-댕크샤딩](https://eips.ethereum.org/EIPS/eip-4844) +- [비탈릭의 샤딩 및 데이터 가용성 샘플링 관련 의견](https://hackmd.io/@vbuterin/sharding_proposal) + +### 하드웨어 {#hardware} + +적당한 하드웨어에서 [노드를 실행](/developers/docs/nodes-and-clients/run-a-node/)하는 것은 이더리움을 분산화하는 데 필수적입니다. 따라서 노드 실행을 위한 하드웨어 요구 사항을 최소화하는 연구는 중요한 연구 분야입니다. + +#### 배경 지식 {#background-reading-5} + +- [ARM 기반 이더리움](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/) + +#### 최근 연구 {#recent-research-5} + +- [FPGA 기반 ECDSA](https://ethresear.ch/t/does-ecdsa-on-fpga-solve-the-scaling-problem/6738) + +## 보안 {#security} + +보안은 스팸/사기 방지, 지갑 보안, 하드웨어 보안, 암호경제 보안, 버그 헌팅, 애플리케이션 및 클라이언트 소프트웨어 테스팅, 키 관리 등 광범위한 주제를 포함합니다. 이 분야에 지식을 기여하면 주류 채택을 촉진하는 데 도움이 될 것입니다. + +### 암호학 및 ZKP {#cryptography--zkp} + +영지식 증명(ZKP)과 암호화는 이더리움과 이더리움 애플리케이션에 개인정보 보호와 보안을 구축하는 데 매우 중요합니다. 영지식은 비교적 새로운 분야이지만 빠르게 발전하고 있으며, 많은 연구 및 개발 기회가 열려 있습니다. 가능한 발전 방향으로는 [Keccak 해시 알고리즘](https://hackmd.io/sK7v0lr8Txi1bgION1rRpw?view#Overview)의 보다 효율적인 구현을 개발하거나, 기존보다 성능이 뛰어난 다항식 커밋먼트를 찾는 것, 혹은 Ecdsa 공개키 생성 및 서명 검증 회로의 비용을 줄이는 것 등이 있습니다. + +#### 배경 지식 {#background-reading-6} + +- [0xparc 블로그](https://0xparc.org/blog) +- [zkp.science](https://zkp.science/) +- [영지식 팟캐스트](https://zeroknowledge.fm/) + +#### 최근 연구 {#recent-research-6} + +- [타원 곡선 암호화의 최신 동향](https://ethresear.ch/t/the-ec-fft-algorithm-without-elliptic-curve-and-isogenies/11346) +- [Ethresear.ch ZK](https://ethresear.ch/c/zk-s-nt-arks/13) + +### 지갑 {#wallets} + +이더리움 지갑은 브라우저 확장 프로그램, 데스크톱 및 모바일 앱, 또는 이더리움 상의 스마트 컨트랙트 형태가 될 수 있습니다. 개인 사용자 키 관리와 관련된 위험을 줄이는 소셜 복구 지갑에 대한 활발한 연구가 진행 중입니다. 지갑 개발과 관련된 연구로는 계정 추상화의 대체 형태에 대한 연구가 있으며, 이는 중요한 신생 연구 분야입니다. + +#### 배경 지식 {#background-reading-7} + +- [지갑 소개](/wallets/) +- [지갑 보안 개요](/security/) +- [Ethresear.ch 보안](https://ethresear.ch/tag/security) +- [EIP-2938 계정 추상화](https://eips.ethereum.org/EIPS/eip-2938) +- [EIP-4337 계정 추상화](https://eips.ethereum.org/EIPS/eip-4337) + +#### 최근 연구 {#recent-research-7} + +- [유효성 검사에 중점을 둔 스마트 컨트랙트 지갑](https://ethereum-magicians.org/t/validation-focused-smart-contract-wallets/6603) +- [계정의 미래](https://ethereum-magicians.org/t/validation-focused-smart-contract-wallets/6603) +- [EIP-3074 AUTH 및 AUTHCALL Opcode](https://eips.ethereum.org/EIPS/eip-3074) +- [EOA 주소에 코드 게시](https://eips.ethereum.org/EIPS/eip-5003) + +## 커뮤니티, 교육 및 홍보 {#community-education-and-outreach} + +새로운 사용자를 이더리움에 온보딩하려면 새로운 교육 자료와 홍보 방식이 필요합니다. 여기에는 블로그 게시물 및 기사, 서적, 팟캐스트, 밈, 교육 자료, 이벤트, 그리고 커뮤니티를 구축하고, 처음 시작하는 사람들을 환영하며, 이더리움에 대해 사람들을 교육하는 데 도움이 되는 모든 것이 포함될 수 있습니다. + +### UX/UI {#uxui} + +더 많은 사람들을 이더리움에 온보딩하려면 이더리움 생태계는 UX/UI를 개선해야 합니다. 이를 위해서는 디자이너와 제품 전문가가 지갑과 앱의 디자인을 재검토해야 합니다. + +#### 배경 지식 {#background-reading-8} + +- [Ethresear.ch UX/UI](https://ethresear.ch/c/ui-ux/24) + +#### 최근 연구 {#recent-research-8} + +- [Web3 디자인 Discord](https://discord.gg/FsCFPMTSm9) +- [Web3 디자인 원칙](https://www.web3designprinciples.com/) +- [Ethereum Magicians UX 토론](https://ethereum-magicians.org/t/og-council-ux-follow-up/9032/3) + +### 경제학 {#economics} + +이더리움 경제학 연구는 크게 두 가지 접근 방식을 따릅니다. 하나는 경제적 인센티브에 의존하는 메커니즘의 보안을 검증하는 것("미시 경제학")이고, 다른 하나는 프로토콜, 애플리케이션 및 사용자 간의 가치 흐름을 분석하는 것("거시 경제학")입니다. 이더리움의 기본 자산(ether)과 그 위에 구축된 토큰(예: NFT 및 ERC20 토큰)에는 이와 관련된 복잡한 암호경제학적 요소가 있습니다. + +#### 배경 지식 {#background-reading-9} + +- [강건한 인센티브 연구 그룹](https://rig.ethereum.org/) +- [Devconnect의 ETHconomics 워크숍](https://www.youtube.com/playlist?list=PLTLjFJ0OQOj5PHRvA2snoOKt2udVsyXEm) + +#### 최근 연구 {#recent-research-9} + +- [EIP1559의 경험적 분석](https://arxiv.org/abs/2201.05574) +- [유통 공급 균형](https://ethresear.ch/t/circulating-supply-equilibrium-for-ethereum-and-minimum-viable-issuance-during-the-proof-of-stake-era/10954) +- [MEV의 정량적 분석: 다크 포레스트의 실체?](https://arxiv.org/abs/2101.05511) + +### 블록 공간 및 수수료 시장 {#blockspace-fee-markets} + +블록스페이스 시장은 최종 사용자 거래의 포함을 관리하며, 이는 Ethereum(레이어 1)에서 직접 이루어지든, 롤업(레이어 2)과 같은 브리지된 네트워크에서 이루어지든 관리됩니다. 이더리움에서 트랜잭션은 EIP-1559로 프로토콜 내에 구축된 수수료 시장에 제출되어, 스팸으로부터 체인을 보호하고 네트워크 혼잡에 따른 가격을 책정합니다. 이더리움의 레이어 1과 레이어 2 모두에서 트랜잭션은 최대 추출 가능 가치(MEV)로 알려진 외부 효과를 발생시킬 수 있으며, 이는 이러한 외부 효과를 포착하거나 관리하기 위한 새로운 시장 구조를 유도합니다. + +#### 배경 지식 {#background-reading-10} + +- [이더리움 블록체인의 트랜잭션 수수료 메커니즘 설계: EIP-1559 경제 분석 (Tim Roughgarden, 2020)](https://timroughgarden.org/papers/eip1559.pdf) +- [EIP-1559 시뮬레이션 (Robust Incentives Group)](https://ethereum.github.io/abm1559) +- [기초 원리로 이해하는 롤업의 경제 구조](https://barnabe.substack.com/p/understanding-rollup-economics-from?utm_source=url) +- [Flash Boys 2.0: 탈중앙화 거래소의 선행 매매, 트랜잭션 재정렬 및 합의 불안정성](https://arxiv.org/abs/1904.05234) + +#### 최근 연구 {#recent-research-10} + +- [다차원 EIP-1559 비디오 프레젠테이션](https://youtu.be/QbR4MTgnCko) +- [교차 도메인 MEV](http://arxiv.org/abs/2112.01472) +- [MEV 경매](https://ethresear.ch/t/mev-auction-auctioning-transaction-ordering-rights-as-a-solution-to-miner-extractable-value/6788) + +### 지분 증명 인센티브 {#proof-of-stake-incentives} + +검증인은 이더리움의 기본 자산(이더)을 부정행위에 대한 담보로 사용합니다. 이 암호경제학이 네트워크의 보안을 결정합니다. 정교한 검증인은 인센티브 레이어의 미묘한 차이를 악용하여 명시적인 공격을 시작할 수 있습니다. + +#### 배경 지식 {#background-reading-11} + +- [이더리움 경제학 마스터클래스 및 경제 모델](https://github.com/CADLabs/ethereum-economic-model) +- [PoS 인센티브 시뮬레이션 (Robust Incentives Group)](https://ethereum.github.io/beaconrunner/) + +#### 최근 연구 {#recent-research-11} + +- [제안자/빌더 분리(PBS) 하에서 트랜잭션의 검열 저항성 증가](https://notes.ethereum.org/s3JToeApTx6CKLJt8AbhFQ) +- [PoS 이더리움에 대한 세 가지 공격](https://arxiv.org/abs/2110.10086) + +### 유동성 스테이킹 및 파생 상품 {#liquid-staking-and-derivatives} + +유동성 스테이킹은 32 ETH보다 적은 ETH를 가진 사용자가 이더를 DeFi에서 사용할 수 있는 스테이킹된 이더를 나타내는 토큰으로 교환하여 스테이킹 수익을 얻을 수 있도록 합니다. 그러나 유동성 스테이킹과 관련된 인센티브 및 시장 역학은 아직 완전히 발견되지 않았으며, 이더리움 보안에 미치는 영향(예: 중앙화 위험) 또한 마찬가지입니다. + +#### 배경 지식 {#background-reading-12} + +- [Ethresear.ch 유동성 스테이킹](https://ethresear.ch/search?q=liquid%20staking) +- [Lido: 신뢰 없는 이더리움 스테이킹으로 가는 길](https://blog.lido.fi/the-road-to-trustless-ethereum-staking/) +- [Rocket Pool: 스테이킹 프로토콜 소개](https://medium.com/rocket-pool/rocket-pool-staking-protocol-part-1-8be4859e5fbd) + +#### 최근 연구 {#recent-research-12} + +- [Lido에서의 출금 처리](https://ethresear.ch/t/handling-withdrawals-in-lidos-eth-liquid-staking-protocol/8873) +- [출금 자격 증명](https://ethresear.ch/t/withdrawal-credential-rotation-from-bls-to-eth1/8722) +- [유동성 스테이킹 파생 상품의 위험](https://notes.ethereum.org/@djrtwo/risks-of-lsd) + +## 테스트 {#testing} + +### 형식 검증 {#formal-verification} + +형식 검증은 이더리움의 합의 사양이 정확하고 버그가 없는지 확인하기 위해 코드를 작성하는 것입니다. Python으로 작성된 실행 가능한 버전의 사양이 있는데, 이를 위해서는 유지관리와 개발이 필요합니다. 추가 연구를 통해 사양의 Python 구현을 개선하고 정확성을 보다 강력하게 검증하고 문제를 식별할 수 있는 도구를 추가할 수 있습니다. + +#### 배경 지식 {#background-reading-13} + +- [Introduction to formal verification](https://ptolemy.berkeley.edu/projects/embedded/research/vis/doc/VisUser/vis_user/node4.html) +- [형식 검증 (Intel)](https://www.cl.cam.ac.uk/~jrh13/papers/mark10.pdf) + +#### 최근 연구 {#recent-research-13} + +- [예치 계약의 형식 검증](https://github.com/runtimeverification/deposit-contract-verification) +- [비콘 체인 사양의 형식 검증](https://github.com/runtimeverification/deposit-contract-verification) + +## 데이터 과학 및 분석 {#data-science-and-analytics} + +이더리움 활동 및 네트워크 상태에 대한 자세한 정보를 제공하는 더 많은 데이터 분석 도구 및 대시보드가 필요합니다. + +### 배경 지식 {#background-reading-14} + +- [Dune Analytics](https://dune.com/browse/dashboards) +- [클라이언트 다양성 대시보드](https://clientdiversity.org/) + +#### 최근 연구 {#recent-research-14} + +- [Robust Incentives Group 데이터 분석](https://rig.ethereum.org/) + +## 앱 및 도구 {#apps-and-tooling} + +애플리케이션 레이어는 이더리움의 기본 레이어에서 트랜잭션을 처리하는 다양한 프로그램 생태계를 지원합니다. 개발팀은 Ethereum을 활용해 구성 가능하고 허가가 필요 없으며 검열에 강한 중요한 Web2 앱 버전을 만들거나 완전히 새로운 Web3 네이티브 개념을 만드는 새로운 방법을 계속 찾고 있습니다. 동시에, 이더리움에서 dapp을 구축하는 것을 덜 복잡하게 만드는 새로운 툴이 개발되고 있습니다. + +### 디파이 {#defi} + +탈중앙화 금융(DeFi)은 이더리움 위에 구축된 주요 애플리케이션 종류 중 하나입니다. DeFi는 사용자가 스마트 계약을 사용하여 암호화 자산을 저장, 전송, 대여, 차용 및 투자할 수 있도록 구성 가능한 "머니 레고"를 만드는 것을 목표로 합니다. DeFi는 끊임없이 업데이트되는 빠르게 변화하는 공간이기에 안전하고 효율적이며 접근 가능한 프로토콜에 대한 연구가 지속적으로 필요합니다. + +#### 배경 지식 {#background-reading-15} + +- [디파이](/defi/) +- [Coinbase: DeFi란 무엇입니까?](https://www.coinbase.com/learn/crypto-basics/what-is-defi) + +#### 최근 연구 {#recent-research-15} + +- [탈중앙화 금융, 중앙화된 소유권?](https://arxiv.org/pdf/2012.09306.pdf) +- [Optimism: 1달러 미만 트랜잭션으로 가는 길](https://medium.com/ethereum-optimism/the-road-to-sub-dollar-transactions-part-2-compression-edition-6bb2890e3e92) + +### DAOs {#daos} + +이더리움의 효과적인 사용 사례 중 하나는 DAO를 사용하여 분산된 방식으로 조직할 수 있는 기능입니다. 이더리움의 DAO가 개선된 형태의 거버넌스를 실행하고, 신뢰를 최소화한 조정 도구로서 개발 및 활용되어 기존 기업 및 조직을 넘어 사람들의 선택지를 크게 확장할 수 있는 방법에 대한 활발한 연구가 많이 진행되고 있습니다. + +#### 배경 지식 {#background-reading-16} + +- [DAO 소개](/dao/) +- [Dao Collective](https://daocollective.xyz/) + +#### 최근 연구 {#recent-research-16} + +- [DAO 생태계 매핑](https://www.researchgate.net/publication/358694594_Mapping_out_the_DAO_Ecosystem_and_Assessing_DAO_Autonomy) + +### 개발자 도구 {#developer-tools} + +이더리움 개발자를 위한 도구는 빠르게 개선되고 있습니다. 이 분야에서는 활발한 연구와 개발이 많이 진행되고 있습니다. + +#### 배경 지식 {#background-reading-17} + +- [프로그래밍 언어별 도구](/developers/docs/programming-languages/) +- [개발자 프레임워크](/developers/docs/frameworks/) +- [Consensus 개발자 도구 목록](https://github.com/ConsenSys/ethereum-developer-tools-list) +- [토큰 표준](/developers/docs/standards/tokens/) +- [CryptoDevHub: EVM 도구](https://cryptodevhub.io/wiki/ethereum-virtual-machine-tools) + +#### 최근 연구 {#recent-research-17} + +- [Eth R&D Discord Consensus Tooling 채널](https://discordapp.com/channels/595666850260713488/746343380900118528) + +### 오라클 {#oracles} + +오라클은 허가 없이 탈중앙화된 방식으로 오프체인 데이터를 블록체인으로 가져옵니다. 이 데이터를 온체인에 가져오면 dapps는 실제 자산의 가격 변동, 오프체인 앱의 이벤트 또는 날씨 변화와 같은 실제 현상에 반응할 수 있습니다. + +#### 배경 지식 {#background-reading-18} + +- [오라클 소개](/developers/docs/oracles/) + +#### 최근 연구 {#recent-research-18} + +- [블록체인 오라클 조사](https://arxiv.org/pdf/2004.07140.pdf) +- [Chainlink 백서](https://chain.link/whitepaper) + +### 앱 보안 {#app-security} + +이더리움 해킹은 일반적으로 프로토콜 자체보다는 개별 애플리케이션의 취약점을 악용합니다. 해커와 앱 개발자는 새로운 공격과 방어를 개발하기 위해 끊임없이 경쟁합니다. 이는 앱을 해킹으로부터 안전하게 유지하기 위해 항상 중요한 연구 개발이 필요함을 의미합니다. + +#### 배경 지식 {#background-reading-19} + +- [Wormhole 익스플로잇 보고서](https://blog.chainalysis.com/reports/wormhole-hack-february-2022/) +- [이더리움 계약 해킹 사후 검토 목록](https://forum.openzeppelin.com/t/list-of-ethereum-smart-contracts-post-mortems/1191) +- [Rekt News](https://x.com/RektHQ?s=20&t=3otjYQdM9Bqk8k3n1a1Adg) + +#### 최근 연구 {#recent-research-19} + +- [Ethresear.ch 애플리케이션](https://ethresear.ch/c/applications/18) + +### 기술 스택 {#technology-stack} + +이더리움 기술 스택 전체를 분산화하는 것은 중요한 연구 분야입니다. 현재 이더리움의 dapps는 중앙 집중식 도구나 인프라에 의존하기 때문에 일반적으로 일부 중앙 집중화 지점을 가지고 있습니다. + +#### 배경 지식 {#background-reading-20} + +- [이더리움 스택](/developers/docs/ethereum-stack/) +- [Coinbase: Web3 스택 소개](https://blog.coinbase.com/a-simple-guide-to-the-web3-stack-785240e557f0) +- [스마트 계약 소개](/developers/docs/smart-contracts/) +- [탈중앙화 스토리지 소개](/developers/docs/storage/) + +#### 최근 연구 {#recent-research-20} + +- [스마트 계약 구성 가능성](/developers/docs/smart-contracts/composability/) diff --git a/public/content/translations/ko/community/support/faq/index.md b/public/content/translations/ko/community/support/faq/index.md new file mode 100644 index 00000000000..19ad658a909 --- /dev/null +++ b/public/content/translations/ko/community/support/faq/index.md @@ -0,0 +1,77 @@ +--- +title: "자주 묻는 질문" +description: "지갑, 트랜잭션, 스테이킹 등에 대한 이더리움 관련 일반적인 질문입니다." +lang: ko +--- + +# 자주 묻는 질문 {#faq} + +## 암호화폐를 잘못된 주소로 보냈습니다 {#wrong-wallet} + +이더리움에서 전송된 거래는 되돌릴 수 없습니다. 안타깝게도 ETH나 토큰을 잘못된 지갑으로 보낸 경우, 트랜잭션을 되돌릴 방법이 없습니다. + +**대처 방법:** + +- **해당 주소의 소유자를 아는 경우**, 직접 연락하여 자금 반환을 요청하세요. +- **주소가 거래소 또는 알려진 서비스에 속한 경우**, 지원팀에 문의하면 도움을 받을 수 있습니다. +- **토큰을 컨트랙트 주소로 보낸 경우**, 컨트랙트에 출금 또는 복구 기능이 있는지 확인하세요(드문 경우임). + +대부분의 경우 자금을 복구할 방법이 없습니다. 이더리움을 소유하는 중앙 조직, 법인 또는 개인이 없으므로, 트랜잭션을 되돌릴 수 있는 사람도 없습니다. 확인 전에 항상 수신자 주소를 다시 확인하세요. + +## 지갑에 액세스할 수 없습니다 {#lost-wallet-access} + +복구 옵션은 사용하는 지갑 유형에 따라 다릅니다. + +### 시드 문구(복구 문구)가 있는 경우 + +시드 문구를 사용하여 호환되는 모든 지갑 앱에서 지갑을 복원할 수 있습니다. 따라서 시드 문구를 오프라인에 안전하게 보관하는 것이 중요합니다. 복원 지침은 지갑 제공업체의 설명서를 확인하세요. + +### 시드 문구를 분실한 경우 + +시드 문구나 개인 키가 없으면 자금을 복구할 수 없습니다. ethereum.org를 포함한 그 누구도 비밀번호를 재설정하거나 개인 보관 지갑에 대한 액세스를 복원할 수 없습니다. + +### 계정이 거래소에 있는 경우 + +계정이 Coinbase, Binance 또는 Kraken과 같은 중앙화 거래소에 있는 경우 거래소 지원팀에 직접 문의하세요. 거래소는 플랫폼의 계정을 제어하며 비밀번호 재설정이나 계정 복구에 도움을 줄 수 있습니다. + + + + + + +지갑 복구를 도와주겠다고 주장하는 사람과 **절대 시드 문구를 공유하지 마세요**. 이는 가장 흔한 사기 수법 중 하나입니다. 정상적인 서비스는 절대 시드 문구를 요구하지 않습니다. + + + + + + 지갑 사용 방법 + + +## 트랜잭션이 처리되지 않고 보류 중입니다 {#stuck-transaction} + +설정한 가스 수수료가 현재 네트워크에서 요구하는 것보다 낮으면 이더리움 트랜잭션이 처리되지 않을 수 있습니다. 대부분의 지갑에서 이 문제를 해결할 수 있습니다. + +- **속도 높이기:** 더 높은 가스 수수료로 동일한 트랜잭션을 다시 제출합니다. +- **취소:** 보류 중인 트랜잭션과 동일한 논스(Nonce)를 사용하여 자신의 주소로 0 ETH 트랜잭션을 보냅니다. + +### 유용한 가이드 + +- [MetaMask에서 보류 중인 트랜잭션의 속도를 높이거나 취소하는 방법](https://support.metamask.io/transactions-and-gas/transactions/how-to-speed-up-or-cancel-a-pending-transaction/) +- [보류 중인 이더리움 트랜잭션을 취소하는 방법](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) + +## 이더리움 경품을 어떻게 수령하나요? {#giveaway-scam} + +이더리움 경품은 사용자의 ETH를 훔치기 위해 계획된 사기입니다. 너무 좋은 조건처럼 보이는 제안에 현혹되지 마세요. 경품 지급 주소로 ETH를 보내도 경품을 받을 수 없으며 자금을 복구할 수도 없습니다. + +[사기 방지에 대한 추가 정보](/security/#common-scams) + +## ETH는 어떻게 스테이킹하나요? {#how-to-stake} + +검증자가 되려면 이더리움 예치 계약에 32 ETH를 스테이킹하고 검증자 노드를 설정해야 합니다. 스테이킹 풀을 통해 더 적은 양의 ETH로도 참여할 수 있습니다. + +자세한 정보는 [스테이킹 페이지](/staking/)와 [스테이킹 런치패드](https://launchpad.ethereum.org/)에서 확인할 수 있습니다. + +## 이더리움을 어떻게 채굴하나요? 이더리움을 채굴하고 싶습니다 {#mining-ethereum} + +이더리움 채굴은 더 이상 불가능합니다. 2022년 9월 [병합](/roadmap/merge/) 중에 이더리움이 [작업 증명](/glossary/#pow)에서 [지분 증명](/glossary/#pos)으로 전환되면서 채굴이 중단되었습니다. 이제 채굴자 대신 이더리움에는 검증자가 있습니다. 누구나 ETH를 [스테이킹](/glossary/#staking)하고 검증자 소프트웨어를 실행하여 네트워크를 보호하고 스테이킹 보상을 받을 수 있습니다. diff --git a/public/content/translations/ko/community/support/misconceptions/index.md b/public/content/translations/ko/community/support/misconceptions/index.md new file mode 100644 index 00000000000..c3e53f5f152 --- /dev/null +++ b/public/content/translations/ko/community/support/misconceptions/index.md @@ -0,0 +1,73 @@ +--- +title: "이더리움에 대한 일반적인 오해" +description: "이더리움의 작동 방식에 대한 가장 일반적인 오해 해소하기" +lang: ko +--- + +# 이더리움에 대한 일반적인 오해 {#misconceptions} + +## 이더리움은 회사인가요? {#not-a-company} + +이더리움은 전 세계 수천 명의 기여자가 유지 관리하는 오픈소스 탈중앙화 기술입니다. 계정을 관리하거나 자금을 보유하거나 고객 지원을 제공하는 "이더리움"이라는 회사는 없습니다. + +[이더리움 재단](https://ethereum.foundation/)은 이더리움의 개발을 지원하는 비영리 단체이지만 네트워크를 소유하거나 통제하지는 않습니다. 어떤 단일 주체도 통제하지 않습니다. + +**[ethereum.org](/)** 는 커뮤니티가 운영하는 교육용 참고 자료입니다. 거래소, 지갑 또는 금융 기관이 아닙니다. 사용자 자금을 보유하지 않으며 어떤 계정에도 접근할 수 없습니다. + + + 이더리움이란 무엇인가요? + + +## 누군가 내 자금을 복구하거나 동결할 수 있나요? {#no-fund-access} + +은행과 달리 이더리움에는 자금을 동결, 압수 또는 복구할 수 있는 중앙 기관이 없습니다. 개인 키(또는 시드 문구)를 보유한 사람이 지갑에 대한 완전하고 유일한 통제권을 가집니다. + +이는 다음을 의미합니다. + +- **누구도** 잘못된 주소로 보낸 자금을 복구할 수 없습니다 +- 확인된 거래는 **누구도 되돌릴 수 없습니다** +- 누구도 사용자의 지갑을 동결하거나 거래를 차단할 수 없습니다 +- 시드 문구를 분실한 경우 **누구도 비밀번호를 재설정할 수 없습니다** + +이것이 바로 시드 문구를 보호하는 것이 중요한 이유입니다. 이것이 지갑에 접근할 수 있는 유일한 방법입니다. 분실하거나 도난당한 경우 복구 옵션이 없습니다. + + + 이더리움 보안 및 사기 방지 + + +## 아직도 이더리움을 채굴할 수 있나요? {#no-mining} + +이더리움은 2022년 9월 [병합](/roadmap/merge/) 기간 동안 [작업 증명](/glossary/#pow)에서 [지분 증명](/glossary/#pos)으로 전환했습니다. 이더리움에서는 더 이상 채굴이 불가능합니다. + +이제 네트워크는 ETH를 [스테이킹](/glossary/#staking)하는 검증자에 의해 보안이 유지됩니다. 누구나 참여할 수 있습니다. + +- **단독 스테이킹:** 32 ETH로 자신만의 검증자 노드를 운영하세요—[자세히 알아보기](/staking/solo/) +- **서비스형 스테이킹:** 키를 보관하면서 노드 운영을 위임하세요—[자세히 알아보기](/staking/saas/) +- **풀 스테이킹:** 풀에 참여하여 32 ETH 미만으로 스테이킹하세요—[자세히 알아보기](/staking/pools/) + + + 스테이킹에 대해 자세히 알아보기 + + +## 이더리움 지원팀이 있나요? {#no-support-team} + +"공식 이더리움 지원"을 찾는 것은 "공식 인터넷 지원"을 찾는 것과 유사합니다. 물론 이런 것은 존재하지 않지만, 문제에 따라 인터넷 서비스 제공업체, 라우터 하드웨어 제조업체 또는 사용 중인 장치, 앱, 웹사이트를 지원하는 회사 중 한 곳에서 지원을 받을 수 있습니다. + +이더리움도 비슷합니다. 이더리움 전체를 지원하는 회사, 지원팀 또는 헬프데스크는 없지만, 문제에 따라 사용 중인 _지갑 제공업체_, _스테이킹 서비스_, _거래소_, _금융 기관_ 또는 앱을 유지 관리하는 팀에 문의하여 도움을 받을 수 있습니다. + +이더리움은 기본적으로 공개적으로 투명하기 때문에 [블록 탐색기](/developers/docs/data-and-analytics/block-explorers/), [분석 도구](/developers/tools/analytics/) 및 기타 [온라인 조사 참고 자료](/community/support/scams/#analyze)를 사용하여 문제를 직접 조사하는 데 유용할 수 있습니다. + +즉, 이더리움 또는 ethereum.org의 누구도 다음을 수행하지 않습니다. + +- 다이렉트 메시지를 통해 연락 +- 시드 문구나 개인 키를 요청 +- 지갑을 확인하기 위해 ETH 전송을 요청 +- 수수료를 받고 자금 회복을 도와주겠다고 제안 + +**위의 행동 중 하나라도 하는 사람은 사기를 치려는 것입니다.** + +도움이 필요하다면, 도움을 줄 수 있는 실제 커뮤니티가 [지원 페이지](/community/support/)에 나열되어 있습니다. 이들은 자원봉사로 운영되는 개방형 커뮤니티이며 공식적인 지원 채널이 아닙니다. + + + 이더리움 보안 및 사기 방지 + diff --git a/public/content/translations/ko/community/support/scams/index.md b/public/content/translations/ko/community/support/scams/index.md new file mode 100644 index 00000000000..b3330e94030 --- /dev/null +++ b/public/content/translations/ko/community/support/scams/index.md @@ -0,0 +1,159 @@ +--- +title: "사기 관련 도움 및 신고" +description: "사기를 당했을 경우 대처 방법, 남은 자산 보호 방법, 사기 신고처에 대한 안내입니다." +lang: ko +--- + +# 사기를 당했거나 자금을 잃었습니다 {#scam-help} + +암호화폐 사기는 금융 및 기술 분야 전문가를 포함하여 경험 수준과 관계없이 모든 사람을 대상으로 합니다. 당신은 혼자가 아니며, 이곳을 찾은 것은 올바른 첫걸음입니다. + + + + + + +**누구도 블록체인 거래를 되돌릴 수 없습니다.** 수수료를 받고 자금을 복구해 줄 수 있다고 주장하며 접근하는 사람이 있다면, 이는 거의 확실한 2차 사기입니다. 아래의 [복구 사기](#recovery-scams)를 참조하세요. + + + + +## 남은 자산 보호하기 {#secure-assets} + +사기꾼과 상호작용했거나 지갑이 탈취되었다고 의심되는 경우, 즉시 다음 조치를 취하세요. + +1. **남은 자금을** 사기꾼이 접근할 수 없는 새롭고 안전한 지갑으로 옮기세요. +2. **토큰 승인을 철회하세요.** 사기꾼은 종종 무제한 토큰 지출을 승인하도록 유도합니다. 이러한 권한을 철회하면 지갑에서 자금이 더 이상 인출되는 것을 방지할 수 있습니다. +3. 연결되었을 수 있는 모든 거래소 계정의 **비밀번호를 변경하세요**. +4. 모든 암호화폐 관련 계정에서 **2단계 인증(2FA)을 활성화하세요**. + +### 토큰 승인 철회 방법 {#revoke-approvals} + +탈중앙화앱(dapp) 또는 스마트 계약과 상호작용할 때, 토큰을 사용할 수 있는 권한을 부여했을 수 있습니다. 사기꾼의 속임수에 넘어가 악의적인 계약을 승인했다면, 초기 사기 이후에도 계속해서 사용자의 토큰을 빼내 갈 수 있습니다. + +다음 도구를 사용하여 승인을 확인하고 철회하세요: + +- [Revoke.cash](https://revoke.cash/): 지갑을 연결하여 모든 활성 승인을 확인하고 철회하세요. +- [Revokescout](https://revoke.blockscout.com/): Blockscout를 통해 승인을 확인하고 철회하세요. +- [Etherscan 토큰 승인 검사기](https://etherscan.io/tokenapprovalchecker): Etherscan을 통해 승인을 확인하고 철회하세요. + + + 단계별 가이드: 토큰 접근 권한 철회 방법 + + +## 사기 주소 및 웹사이트 신고하기 {#report} + +신고하면 다른 사용자에게 경고가 되고, 법 집행 기관의 수사에 도움이 될 수 있습니다. 거래 해시, 지갑 주소, 스크린샷, 사기꾼과의 모든 커뮤니케이션 등 모든 것을 기록해두세요. + +### 사기 주소 신고하기 {#report-address} + +- [Chainabuse](https://www.chainabuse.com/): 커뮤니티 기반 사기 및 부정행위 신고 데이터베이스입니다. 신고서를 제출하고 알려진 사기 주소를 검색하세요. +- [Etherscan 신고](https://info.etherscan.com/report-address/): 가장 많이 사용되는 이더리움 블록 탐색기에서 주소를 신고하세요. +- [CryptoScamDB](https://cryptoscamdb.org/): 암호화폐 사기를 추적하는 오픈소스 데이터베이스입니다. + +### 사기 웹사이트 또는 소셜 미디어 계정 신고하기 {#report-website} + +- [PhishTank](https://phishtank.org/): 피싱 URL을 제출하고 확인하세요. +- [Google 세이프 브라우징](https://safebrowsing.google.com/safebrowsing/report_phish/): Google에 피싱 사이트를 신고하여 Chrome 및 기타 브라우저에서 차단되도록 하세요. +- [Netcraft](https://report.netcraft.com/report/mistake): 악의적이고 사기성 있는 웹사이트를 신고하세요. +- 사기가 발생한 소셜 미디어 플랫폼(Twitter/X, Discord, Telegram 등 모두 신고 기능이 있음)에 직접 신고하세요. + +### 법 집행 기관에 신고하기 {#report-law-enforcement} + +- **미국:** [FBI 인터넷 범죄 신고 센터(IC3)](https://www.ic3.gov/) +- **영국:** [Action Fraud](https://www.actionfraud.police.uk/) +- **유럽 연합:** [Europol](https://www.europol.europa.eu/report-a-crime) +- **기타 국가:** 현지 경찰에 신고서를 제출하세요. 암호화폐 사기는 대부분의 사법 관할권에서 범죄로 간주됩니다. + +## 사건 분석하기 {#analyze} + +자금이 어디로 이동했는지 파악하면 신고에 도움이 되며, 자금이 중앙화 거래소로 이동한 경우 자금 회수 절차에 도움이 될 수 있습니다. + +- [Blockscout](https://eth.blockscout.com/): 거래 해시나 지갑 주소를 조회하여 자금이 어디로 전송되었는지 확인할 수 있는 오픈소스 블록 탐색기입니다. +- [Etherscan](https://etherscan.io/): 거래 해시 또는 지갑 주소를 조회하여 자금이 어디로 전송되었는지 확인하세요. +- [Chainabuse 조회](https://www.chainabuse.com/): 주소가 다른 피해자들에 의해 이미 신고되었는지 확인하세요. +- [MetaSleuth](https://metasleuth.io/) by BlockSec: 자금 흐름을 시각적으로 추적하여 보여주는 도구입니다. + +**자금이 중앙화 거래소**(예: Coinbase, Binance, Kraken)로 전송된 경우, 즉시 거래 내역을 가지고 해당 거래소의 지원팀에 문의하세요. 거래소는 사기 행위로 신고된 계정을 동결 조치할 수 있습니다. + +## 불편한 진실 {#hard-truth} + +이더리움은 탈중앙화되어 있으므로 거래를 되돌리거나 도난당한 자금을 복구할 수 있는 중앙 기관이 없습니다. 거래가 블록체인에서 확정되면 되돌릴 수 없습니다. + +그래도 신고는 여전히 가치가 있습니다. 신고는 법 집행 기관이 조직적인 사기 집단을 추적하는 데 도움이 되며, Chainabuse 및 Etherscan에 주소를 신고하면 잠재적인 추가 피해를 예방할 수 있습니다. + +## 주의해야 할 사기 유형 {#scam-types} + + + +사기꾼들은 ETH를 몇 배로 늘려주거나 무료 토큰을 주겠다고 약속하는 가짜 경품 행사를 만듭니다. 이들은 종종 비탈릭 부테린과 같은 유명 인사를 사칭합니다. ETH를 "경품" 주소로 보내면 아무것도 돌려받지 못할 것입니다. + +**기억하세요.** 비탈릭을 비롯한 유명 인사들은 절대 ETH를 보내달라고 요청하지 않습니다. + +[일반적인 사기에 대한 자세한 정보](/security/#common-scams) + + + + +사기꾼들은 Discord, Telegram, 소셜 미디어에서 이더리움 팀원, 관리자 또는 지원팀 직원을 사칭합니다. 이들은 도움을 주겠다고 제안하거나 계정에 문제가 있다고 주장하며 다이렉트 메시지를 보낼 수 있습니다. + +**기억하세요.** + +- "이더리움 지원팀"은 존재하지 않습니다. +- 실제 관리자는 절대로 먼저 DM을 보내지 않습니다. +- 어떤 이유로든 누구에게도 시드 구문이나 개인 키를 절대 공유하지 마세요. +- 요청하지 않은 메시지에 포함된 링크는 절대 클릭하지 마세요. + + + + +복구 사기는 이미 자금을 잃은 사람들을 특정하여 노립니다. 사기꾼들은 소셜 미디어에서 사기 피해에 대해 이야기하는 사람들을 지켜보다가 "블록체인 수사관" 또는 "암호화폐 복구 전문가"를 사칭하여 접근합니다. + +이들은 선불 수수료를 받고 도난당한 암호화폐를 추적하고 복구해 주겠다고 약속합니다. 돈을 지불하고 나면 그들은 사라집니다. + +**어떤 합법적인 서비스도 블록체인 거래를 되돌릴 수 없습니다.** 이를 약속하는 사람은 거짓말을 하고 있는 것입니다. 이는 가장 흔한 후속 사기 중 하나입니다. + + + + +피싱 사이트는 실제 지갑 앱, 거래소 또는 DeFi 플랫폼과 똑같이 생겼습니다. 이들은 시드 구문을 입력하거나 지갑을 연결하도록 속여 자금을 빼내 갑니다. + +**자신을 보호하는 방법:** + +- 지갑을 연결하기 전에 항상 URL을 확인하세요. +- 자주 사용하는 공식 사이트를 즐겨찾기에 추가하세요. +- 어떤 웹사이트에도 시드 구문을 절대 입력하지 마세요. 정상적인 앱은 절대 시드 구문을 요구하지 않습니다. +- [PhishTank](https://phishtank.org/)를 사용하여 의심스러운 URL을 확인하세요. + + + 사기 토큰 식별 방법 + + + + + 이더리움 보안 및 사기 방지 전체 가이드 + diff --git a/public/content/translations/ko/contributing/adding-desci-projects/index.md b/public/content/translations/ko/contributing/adding-desci-projects/index.md new file mode 100644 index 00000000000..7f99d8a9158 --- /dev/null +++ b/public/content/translations/ko/contributing/adding-desci-projects/index.md @@ -0,0 +1,44 @@ +--- +title: "DeSci 프로젝트 추가" +description: "ethereum.org의 DeSci 페이지에 프로젝트 링크를 추가할 때 적용하는 정책" +lang: ko +--- + +# 프로젝트 추가 {#adding-projects} + +다양한 프로젝트를 보여주고, DeSci 환경에 대해 좋은 스냅샷 기능을 제공할 것입니다. + +누구나 자유롭게 ethereum.org의 DeSci 페이지에 등록할 프로젝트를 제안할 수 있습니다. 그와 동시에, 더 이상 관련이 없거나 당사의 자격 기준을 충족하지 않는 프로젝트를 발견한 경우에는 제거할 것을 자유롭게 제기할 수 있습니다. + +## 의사 결정 프레임워크 {#the-decision-framework} + +### 포함 기준: 필수 항목 {#the-must-haves} + +- **오픈소스 코드/데이터** - 코드와 데이터의 개방성은 DeSci의 핵심 원칙이므로 DeSci 프로젝트는 클로즈드 소스여서는 안 됩니다. 코드베이스에 접근할 수 있어야 하며 PR에게 왁벽하게 개방되어 있어야 합니다. +- **DeSci 프로젝트는 명백히 탈중앙화되어야 합니다** - DAO의 거버넌스를 받거나 비수탁형 지갑을 포함한 탈중앙화 기술 스택으로 구축하는 방식 등이 있습니다. 이더리움에서 감사가 가능한 스마트 컨트랙트가 포함될 수 있습니다. +- **정직하고 정확한 목록 정보** - 프로젝트에서 제안하는 모든 목록은 정직하고 정확한 정보를 포함해야 합니다. 제품이 "오픈 소스"라고 선언하는 등 목록 정보를 위조하는 제품은 삭제됩니다. +- **과학에 대한 접근성을 넓히기 위한 입증 가능한 노력** - DeSci 프로젝트는 토큰/NFT 보유자뿐만 아니라 일반 대중에게도 과학을 통한 참여를 확대하는 방법을 명확하게 설명할 수 있어야 합니다. +- **전 세계적으로 접근 가능** - 프로젝트에 특정 사용자의 서비스 접근을 막는 지리적 제한이나 KYC 요구사항이 없어야 합니다. +- **유익한 웹사이트 및 문서** - 프로젝트의 웹사이트를 방문하는 사람들은 프로젝트가 실제로 무엇을 하는지와 과학 인프라의 탈중앙화에 어떻게 기여하고, 어떻게 참여하는지 이해할 수 있도록 하는 것이 중요합니다. +- **프로젝트가 이더리움 생태계의 일부여야 합니다** - ethereum.org는 이더리움(및 레이어 2)이 DeSci 운동에 적합한 베이스 레이어라고 생각합니다. +- **프로젝트가 어느 정도 자리를 잡았어야 합니다** - 프로젝트에 몇 달 동안 서비스를 이용해 온 실제 사용자가 있어야 합니다. + +### 있으면 좋은 것들 + +- **여러 언어로 제공** - 프로젝트가 여러 언어로 번역되어 전 세계 사용자가 접근할 수 있어야 합니다. +- **교육 자료** - 제품에 사용자를 돕고 교육할 수 있도록 잘 설계된 온보딩 경험이 있어야 합니다. 또는 기사나 비디오와 같은 콘텐츠 사용 방법에 대한 증표입니다. +- **제3자 감사** - 제품이 신뢰할 수 있는 제3자로부터 취약점에 대한 전문적인 감사를 받았습니다. +- **연락 담당자** - 프로젝트의 연락 담당자(DAO 또는 커뮤니티 대표일 수 있음)가 있으면 변경 사항이 있을 때 정확한 정보를 얻는 데 큰 도움이 됩니다. 이것은 향후 정보를 수집할 때 관리 가능한 ethereum.org 업데이트를 계속할 것입니다. + +## 유지보수 {#maintenance} + +Ethereum의 유동적 특성과 마찬가지로 팀과 제품은 왔다 갔다 하며 매일 혁신이 이루어지므로, 다음 사향들을 위해 정기적으로 콘텐츠를 점검할 것입니다. + +- 나열된 모든 프로젝트가 여전히 기준을 충족하는지 확인합니다. +- 현재 목록에 있는 프로젝트보다 더 많은 기준을 충족하는 추천 프로젝트가 없는지 확인합니다. + +ethereum.org는 오픈 소스 커뮤니티가 관리하며, 우리는 커뮤니티의 도움으로 최신 정보를 유지하고 있습니다. 나열된 프로젝트들의 업데이트에 대해 필요한 정보가 있으면 GitHub 저장소에서 issue를 개설하거나 풀 요청을 보내주세요. + +## 이용약관 {#terms-of-use} + +또한 [이용약관](/terms-of-use/)을 참조하시기 바랍니다. ethereum.org 의 정보는 일반적인 정보 목적으로만 제공됩니다. diff --git a/public/content/translations/ko/contributing/adding-developer-tools/index.md b/public/content/translations/ko/contributing/adding-developer-tools/index.md new file mode 100644 index 00000000000..eb031ffaea3 --- /dev/null +++ b/public/content/translations/ko/contributing/adding-developer-tools/index.md @@ -0,0 +1,61 @@ +--- +title: "개발자 도구 추가하기" +lang: ko +description: "ethereum.org에 등록할 수 있는 개발자 도구의 조건" +--- + +# 개발자 도구 추가하기 {#contributing-to-ethereumorg-} + +이더리움은 개발자들이 능숙하게 구축하고 개발자들이 필요한 지원을 받을 수 있도록 가능한 최고의 개발자 리소스를 목록에 추가하려고 합니다. + +만약 이더리움에서 사용되지 않지만 유용한 개발자 도구가 있다면 편한 마음으로 이를 적절한 곳에 제안해 보세요. + +현재 저희는 [개발자 포털](/developers/)을 통해 개발자 도구 목록을 제공하고 있습니다. + +**편한 마음으로 추가하고 싶은 도구를 적절한 페이지에 제안해 보세요.** + +## 선정 기준 {#ways-to-contribute} + +개발자 도구 제안은 다음 기준에 따라 심사됩니다. + +**기존에 등록된 도구와 유의미한 차별점이 있나요?** + +- 새로운 분류 또는 종류의 도구인가 +- 새로운 기능이 있거나 현재 등록된 비슷한 도구와 차별성이 있는가 +- 현재 등록된 비슷한 도구에서 다루지 않은 별개의 사용 사례가 있는가 + +**도구의 문서화가 잘 되어 있나요?** + +- 문서가 존재하는가 +- 문서가 도구 사용법을 익히는 데에 적절한가 +- 최근에 문서가 업데이트 되었는가 + +**도구가 널리 사용되고 있나요?** + +- 이더리움에서는 GitHub 별, 다운로드 통계, 인지도 있는 회사나 프로젝트에서의 사용 여부 등의 지표를 바탕으로 심사를 진행합니다. + +**도구의 품질이 충분한가요?** + +- 지속적인 버그가 있는가 +- 신뢰할 수 있는 도구인가 +- 도구의 점검이 정기적으로 진행되는가 + +**도구가 오픈소스인가요?** + +이더리움에 있는 수많은 프로젝트들은 오픈소스입니다. 커뮤니티의 개발자가 코드를 직접 살펴보고 기여할 수 있는 오픈 소스 프로젝트를 나열할 가능성이 더 높습니다. + +--- + +## 제품 순서 {#product-ordering} + +제품을 가나다순 등의 특정 순서로 정렬하지 않는 한 페이지에 추가된 지 가장 오래된 제품이 우선적으로 표시됩니다. 다시 말해, 최신 제품은 목록의 최하단에 추가됩니다. + +--- + +## 개발자 도구 추가하기 {#how-decisions-about-the-site-are-made} + +심사 기준에 맞는 개발자 도구를 ethereum.org에 추가하고 싶다면, GitHub에서 이슈를 생성하세요. + + + 이슈 만들기 + diff --git a/public/content/translations/ko/contributing/adding-exchanges/index.md b/public/content/translations/ko/contributing/adding-exchanges/index.md new file mode 100644 index 00000000000..10cdcfbbfc7 --- /dev/null +++ b/public/content/translations/ko/contributing/adding-exchanges/index.md @@ -0,0 +1,40 @@ +--- +title: "거래소 추가하기" +description: "ethereum.org 에 거래소를 추가할 때 사용하는 정책" +lang: ko +--- + +# 이더리움 거래소 추가하기 {#adding-ethereum-exchanges} + +누구나 ethereum.org 에 새로운 거래소를 추천할 수 있습니다. + +현재는 아래의 주소에 나열하고 있습니다. + +- [ethereum.org/get-eth](/get-eth/) + +이 페이지에서는 사용자가 사는 곳을 입력하면 이용할 수 있는 거래소를 볼 수 있습니다. 이로써 지리적인 제한 사항을 조기에 확인할 수 있습니다. + +이러한 맥락에서, 귀하가 거래소를 제안할 때 몇 가지 구체적인 정보가 필요합니다. + +**참고:** 탈중앙화 거래소를 등록하려면 [지갑 및 탈중앙화앱 등록 정책](/contributing/adding-products/)을 확인하세요. + +## 필요한 정보 {#what-we-need} + +- 거래소에 적용되는 지역적 제한 사항. 거래소와 관련된 지역적 제한 사항은 거래소 웹사이트의 전용 페이지 또는 섹션에 자세히 설명되어야 합니다. +- 사용자가 ETH를 구매하는 데 사용할 수 있는 통화 +- 거래소가 합법적인 거래 회사라는 증거 +- 보유하고 있는 모든 추가 정보 – 운영 기간, 재정적 지원 등과 같은 회사에 대한 정보일 수 있습니다. + +이 정보는 [사용자가 이용할 수 있는 거래소를 정확하게 찾도록 돕기](/get-eth/#country-picker) 위해 필요합니다. + +또한 이 정보는 ethereum.org가 해당 거래소가 합법적이고 안전한 서비스라고 더 확신할 수 있도록 하기 위해 필요합니다. + +--- + +## 거래소 추가하기 {#add-exchange} + +ethereum.org에 거래소를 추가하려면 GitHub에 이슈를 생성하세요. + + +이슈 만들기 + diff --git a/public/content/translations/ko/contributing/adding-glossary-terms/index.md b/public/content/translations/ko/contributing/adding-glossary-terms/index.md new file mode 100644 index 00000000000..10a82d0378a --- /dev/null +++ b/public/content/translations/ko/contributing/adding-glossary-terms/index.md @@ -0,0 +1,26 @@ +--- +title: "용어집 추가" +lang: ko +description: "ethereum.org 용어집에 새로운 용어를 추가하기 위한 기준" +--- + +# 용어집 용어 추가하기 {#contributing-to-ethereumorg-} + +이 공간은 매일 수정됩니다. 새로운 용어가 이더리움 사용자의 어휘집에 지속적으로 입력되고 있으며, 이더리움의 모든 것에 대해 정확한 최신 레퍼런스를 제공하는 데 귀하의 도움이 필요합니다. 현재 [용어집](/glossary/)을 확인하고 도움을 주시려면 아래를 확인하세요! + +## 기준 {#criteria} + +새로운 용어집의 추가는 다음 기준에 의해 평가됩니다: + +- 용어/정의가 최신이며 현재 항목과 관련이 있는가? +- 사전에 비슷한 용어가 이미 있는가? (그렇다면, 새 용어를 추가하는 것과 기존 용어를 업데이트 하는 것 중 나은 것을 고려하세요.) +- 제품 광고나 기타 판촉 콘텐츠와 관련이 없는 용어/정의인가? +- 용어/정의가 이더리움과 직접적인 관련이 있는가? +- 정의가 객관적이고 정확하며 주관적인 판단이나 의견이 없는가? +- 출처가 신빙성이 있는가? 소스를 참조하고 있는가? + +--- + +## 용어 추가하기 {#how-decisions-about-the-site-are-made} + +ethereum.org에 용어집 용어를 추가하고 싶고, 해당 용어가 기준을 충족한다면 [GitHub에서 이슈를 생성](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=feature+%3Asparkles%3A%2Ccontent+%3Afountain_pen%3A&template=suggest_glossary_term.yaml)하세요. diff --git a/public/content/translations/ko/contributing/adding-layer-2s/index.md b/public/content/translations/ko/contributing/adding-layer-2s/index.md new file mode 100644 index 00000000000..17a62b23108 --- /dev/null +++ b/public/content/translations/ko/contributing/adding-layer-2s/index.md @@ -0,0 +1,97 @@ +--- +title: "Layer 2(오프체인) 추가" +description: "ethereum.org 에 Layer 2를 추가할 시에 적용되는 정책" +lang: ko +--- + +# 레이어 2 추가하기 {#adding-layer-2} + +유저가 안전하고 신뢰할 수 있는 방식으로 Layer 2의 공간을 탐색할 수 있도록 가능한 최상의 리소스들을 제공할 것입니다. + +누구나 자유롭게 Layer 2 를 ethereum.org 에 추가하기 위해 건의할 수 있습니다. 저희가 놓친 레이어 2가 있다면 **[제안해 주세요](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=feature+%3Asparkles%3A%2Ccontent+%3Afountain_pen%3A&template=suggest_layer2.yaml)!** + +현재 L2는 다음 페이지에 기재되어 있습니다: + +- [낙관적 롤업](/developers/docs/scaling/optimistic-rollups/) +- [영지식 롤업](/developers/docs/scaling/zk-rollups/) +- [레이어 2](/layer-2/) + +Layer 2는 이더리움보다 새롭고 흥미로운 패러다임입니다. ethereum.org 에서 고려하기 위한 공정한 프레임워크를 만들려고 노력하겠지만, 목록의 기준은 시간이 지남에 따라 변경되고 발전할 것입니다. + +## 결정 프레임워크 {#decision-framework} + +### 포함 기준: 필수 사항 {#criteria-for-inclusion-the-must-haves} + +**L2BEAT 등재** + +- 등록 대상 프로젝트로 고려되려면 [L2BEAT](https://l2beat.com)에 등재되어야 합니다. L2BEAT는 L2 프로젝트를 평가하는 데 필요한 강력한 위험성 평가를 제공합니다. **프로젝트가 L2BEAT에 포함되지 않을 경우, ethereum.org 에 L2로 표시되지 않습니다.** +- [L2BEAT에 L2 프로젝트를 추가하는 방법 알아보기](https://github.com/l2beat/l2beat/blob/master/CONTRIBUTING.md). + +**오픈 소스** + +- 귀하의 코드에 엑세스할 수 있어야 하며, 더 큰 커뮤니티로부터 PR을 수락해야 합니다. + +**Layer 2 카테고리** + +다음 사항들은 Layer 2에 대한 솔루션입니다. + +- Optimistic Rollup +- Zero-Knowledge Rollup, ZK-Rollup + +_데이터 가용성 또는 보안을 위해 이더리움을 사용하지 않는 다른 확장 솔루션은 레이어 2로 간주하지 않습니다._ + +**데이터 가용성을 위한 이더리움** + +- 데이터 가용성은 다른 확장 솔루션과 Layer 2의 중요한 차별화 요소입니다. 프로젝트가 등록 대상으로 고려되려면 데이터 가용성을 위해 이더리움 메인넷을 **반드시** 사용해야 합니다. + +**브리지** + +- 어떻게 Layer 2에 온보드할 수 있는가? + +**프로젝트 실행 날짜** + +- 메인넷에서 6개월 이상 "live"상태인 Layer 2 + +- battle-tested를 거치지 않은 새로운 프로젝트는 리스트에 올라갈 가능성이 적습니다. + +**외부 보안 감사** + +- 감사, 내부 보안 팀 또는 다른 방법을 통해 저작물의 보안을 안정적으로 검사해야 합니다. 이는 사용자에 대한 위험을 줄이고 귀하가 보안을 중요하게 생각한다는 것을 보여줍니다. + +**지속적인 사용자 기반** + +- 이더리움에서는 TVL history, 거래 통계, 인지도 있는 회사나 프로젝트에서의 사용 여부 등의 지표를 바탕으로 심사를 진행합니다. + +**적극적인 개발팀** + +- 프로젝트를 적극적으로 진행 중인 팀이 없는 Layer 2는 등재되지 않습니다. + +**블록 탐색기** + +- 등재된 프로젝트에는 사용자가 체인을 쉽게 탐색할 수 있도록 작동하는 블록 탐색기가 필요합니다. + +### 기타 기준: 필수 사항은 아니지만 있으면 좋은 것들 {#nice-to-haves} + +**프로젝트에 대한 거래소 지원** + +- 사용자가 거래소에서 직접 입금 및/또는 인출을 할 수 있는가? + +**Layer 2 에코시스템의 Dapp 링크** + +- 우리는 사용자가 이 layer 2에서 무엇을 할 수 있을 것으로 기대할 수 있는지에 대한 정보를 제공할 수 있기를 원합니다. (e.g., https://portal.arbitrum.io/, https://www.optimism.io/apps) + +**토큰 계약 목록** + +- 자산은 layer 2에서 새로운 주소를 갖게 되므로 사용할 수 있는 토큰 목록 리소스가 있으면 공유해 주십시오. + +**네이티브 지갑의 지원** + +- L2를 기본적으로 지원하는 지갑이 있습니까? + +## 레이어 2 추가하기 {#add-exchange} + +Ethereum.org 에 layer 2를 추가하려면 GitHub에서 이슈를 생성하십시오. + + +이슈 만들기 + diff --git a/public/content/translations/ko/contributing/adding-products/index.md b/public/content/translations/ko/contributing/adding-products/index.md new file mode 100644 index 00000000000..0749b355099 --- /dev/null +++ b/public/content/translations/ko/contributing/adding-products/index.md @@ -0,0 +1,100 @@ +--- +title: "제품 추가" +description: "ethereum.org에 Dapp을 추가할 때 사용하는 정책" +lang: ko +--- + +# 이더리움 제품 추가하기 {#adding-products} + +누구나 자유롭게 ethereum.org 콘텐츠에 새로운 Dapp을 제안할 수 있습니다. **아니요, 홈페이지에 디앱을 등록하지 않습니다** 😜 + +현재 Dapp들은 다음 항목에 나열되어 있습니다: + +- ethereum.org/dapps +- ethereum.org/get-eth + +**이 페이지에 대한 새로운 추가 사항만 제안해 주십시오.** + +새로운 추가를 환영하지만, 우리는 사용자를 위해 만들고자 하는 경험을 바탕으로 현재 Dapp을 선택했습니다. 이는 다음과 같은 디자인 원칙 중 일부를 기반으로 합니다. + +- _영감을 주는_: ethereum.org의 어떤 자료든 사용자에게 새로운 가치를 제공해야 합니다. +- _좋은 이야기_: 목록에 있는 자료는 사용자에게 '아하!' 하는 깨달음의 순간을 제공해야 합니다. +- _신뢰성_: 사용자의 위험을 최소화하기 위해 모든 것은 합법적인 비즈니스/프로젝트여야 합니다 + +전반적으로 **ethereum.org는 신규 사용자에게 "원활한 온보딩 경험"을 제공하고자 합니다**. 이러한 이유로 다음 사항들을 기반으로 Dapp들을 추가합니다. + +- 사용 편의성 +- 다른 제품들과의 상호 운용성 +- 보안 +- 수명 + +여기에 우리의 의사 결정 절차에 대해 더 자세히 나와 있습니다. 언제든지 피드백을 제공하거나 수정 사항을 제안하십시오. + +## 결정 프레임워크 {#decision-framework} + +### 포함 기준: 필수 사항 {#criteria-for-inclusion-the-must-haves} + +- **보안 테스트를 거친 제품** – 감사, 내부 보안팀 또는 기타 방법을 통해 제품의 보안이 안정적으로 테스트되어야 합니다. 이는 사용자에 대한 위험을 줄이고 귀하가 보안을 중요하게 생각한다는 것을 보여줍니다. +- **6개월 이상 "라이브" 상태인 제품** – 이는 보안성을 보여주는 또 다른 지표입니다. 6개월은 치명적인 버그와 공격이 발견되는 데 좋은 기간입니다. +- **활발히 활동하는 팀이 개발** – 이를 통해 품질을 보장하고 사용자가 문의 사항에 대한 지원을 받을 수 있습니다. +- **정직하고 정확한 등록 정보** - 프로젝트에서 제안하는 모든 등록 정보는 정직하고 정확해야 합니다. 귀하의 제품이 "오픈 소스"가 아닌데도 "오픈 소스"라고 선언하는 등 목록 정보를 위조하는 제품은 제거됩니다. + +### 순위 선정 기준: 권장 사항 {#criteria-for-ranking-the-nice-to-haves} + +귀하의 Dapp은 다음 기준으로 인해 ethereum.org에 다른 Dapp만큼 눈에 띄게 표시되지 않을 수 있습니다. + +**디앱** + +- **등록된 대부분의 지갑을 통해 액세스 가능** – 디앱은 ethereum.org에 등록된 대부분의 지갑과 연동되어야 합니다. +- **사용자가 직접 체험 가능 –** 개별 사용자가 디앱을 사용하고 실질적인 결과물을 얻을 수 있어야 합니다. +- **온보딩** – 사용자를 돕고 교육할 수 있도록 잘 설계된 온보딩 경험을 제공해야 합니다. 또는 기사나 비디오와 같은 콘텐츠 사용 방법에 대한 증표입니다. +- **비수탁형** – 사용자가 자신의 자금을 직접 관리합니다. 귀하의 제품이 사라지더라도 사용자는 계속해서 자금에 접근하고 자금을 이동할 수 있습니다. +- **글로벌 접근성** – 특정 사용자의 서비스 접근을 막는 지역적 제한이나 KYC 요건이 없어야 합니다. +- **오픈 소스** – 코드가 공개되어 있어야 하며, 외부 커뮤니티의 PR을 수용해야 합니다. +- **커뮤니티** – 사용자가 팀과 소통하여 도움을 받거나 새로운 기능을 제안할 수 있는 디스코드(Discord) 등의 전용 커뮤니티가 있어야 합니다. + +## 실제 적용 기준 {#criteria-in-practice} + +더 많은 기준을 충족할수록 귀하의 제품이 ethereum.org에 게재될 확률이 높아집니다. + +필수 항목만 충족하는 상장된 제품은 필수 항목과 여러 항목을 충족하는 새로운 제품이 제안되는 경우 제거될 수 있습니다. + +이 결정에 영향을 미칠 다른 사항은 다음과 같습니다. + +- 교체하는 대신 추가하는 경우 페이지의 UX가 손상되는가? + - 저희 사이트는 주로 교육적이며 주요 목적은 이더리움 및 관련 개념을 설명하는 것입니다. 사용자에게 너무 많은 옵션을 추가하면 페이지의 가독성이 저하되어 유용성이 떨어질 수 있습니다. +- 이제 이 페이지가 사용자의 선택을 마비시키는가? + - netflix에서 시청할 콘텐츠를 결정하지 못 해 몇 시간 동안 탐색하는 경우처럼 말이죠. 너무 많은 선택권으로 신규 사용자를 당황하게 만드는 것은 위험합니다. + +위 사항은 ethereum.org 이 책임지는 디자인 결정입니다. + +하지만 안심하세요, **더 많은 디앱의 순위를 확인할 수 있는 다른 웹사이트 링크가 제공될 예정입니다** + +### 제품 순서 {#product-ordering} + +제품을 별도로 정렬하지 않는 한(예: 알파벳순), 가장 최근에 페이지에 추가된 것부터 표시됩니다. 다시 말해, 최신 제품은 목록의 최하단에 추가됩니다. + +### 이용약관 {#terms-of-use} + +또한 [이용약관](/terms-of-use/)을 참조해 주세요. ethereum.org 의 정보는 일반적인 정보 목적으로만 제공됩니다. + +## 유지보수 {#maintenance} + +Ethereum의 유동적 특성과 마찬가지로 팀과 제품은 왔다 갔다 하며 매일 혁신이 이루어지므로, 다음 사향들을 위해 정기적으로 콘텐츠를 점검할 것입니다. + +- 등록된 모든 디앱이 여전히 우리의 기준을 충족하는지 확인해 주십시오 +- 현재 상장된 제품보다 더 많은 기준을 충족하는 제안된 제품이 없는지 확인합니다. + +확인하고 알려주시면 도움을 드릴 수 있습니다. [이슈 생성하기](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=Type%3A+Feature&template=feature_request.yaml&title=) 또는 [website@ethereum.org](mailto:website@ethereum.org)로 이메일을 보내 주세요. + +_또한 커뮤니티가 선호도를 표시하고 추천할 수 있는 최고의 제품을 강조할 수 있도록 투표 옵션도 조사하고 있습니다._ + +--- + +## 제품 추가하기 {#add-your-product} + +ethereum.org에 디앱을 추가하고 싶고 기준을 충족한다면 저희에게 알려주세요. + + + 앱 제안하기 + diff --git a/public/content/translations/ko/contributing/adding-resources/index.md b/public/content/translations/ko/contributing/adding-resources/index.md new file mode 100644 index 00000000000..2429562e7e9 --- /dev/null +++ b/public/content/translations/ko/contributing/adding-resources/index.md @@ -0,0 +1,53 @@ +--- +title: "자료 추가하기" +description: "Ethereum.org에 자료를 추가할 때 사용하는 정책" +lang: ko +--- + +# {#adding-resources} + +우리는 사용자들이 안심하고 신뢰할 수 있도록 가능한 최고의 자료를 제공하고 있다고 분명히 말씀드리고 싶습니다. + +누구든지 ethereum.org 자료 대시보드에 추가해 자유롭게 새로운 자료를 제안할 수 있으며, 대시보드는 현재 [ethereum.org/resources] 에서 찾을 수 있습니다(/resources/). + +비록 우리가 새로운 추가 기능을 환영하지만, 현재의 자료는 우리가 사용자를 위해 만들고자 하는 경험을 기반으로 선택되었습니다. 이는 다음과 같은 디자인 원칙 중 일부를 기반으로 합니다. + +- _영감을 주는_: ethereum.org의 어떤 자료든 사용자에게 새로운 가치를 제공해야 합니다. +- _좋은 이야기_: 목록에 있는 자료는 사용자에게 '아하!' 하는 깨달음의 순간을 제공해야 합니다. +- _신뢰성_: 사용자의 위험을 최소화하기 위해 모든 것은 합법적인 비즈니스/프로젝트여야 합니다 + +전반적으로 **ethereum.org는 신규 사용자에게 원활한 온보딩 경험을 제공하고자 합니다**. 이러한 이유로 저희는 다음 기준에 따라 참고 자료를 추가합니다. + +- 사용 편의성 +- 정확성 +- 유지 보수 + +## 결정 프레임워크 {#decision-framework} + +### 기준 {#criteria} + +- **정직하고 정확한 목록 정보** - 제안된 모든 목록에는 정직하고 정확한 정보가 포함되어야 합니다. 정보를 허위로 기재한 제품은 삭제됩니다. +- **활성 프로젝트** – 사용자를 위한 품질과 지원을 보장하기 위해 해당 참고 자료는 활발하게 활동하는 팀에 의해 유지되어야 합니다. 오래된 참고 자료는 삭제될 수 있습니다. + +### 제품 순서 {#product-ordering} + +저희는 영향력에 따라 제품의 순서를 정할 권리를 보유합니다. 별도의 명시가 없는 한 새로운 제품은 일반적으로 목록 하단에 추가됩니다. + +## 유지보수 {#maintenance} + +이더리움 생태계가 발전함에 따라, 저희는 정기적으로 콘텐츠를 확인하여 다음을 수행합니다: + +- 나열된 모든 참고 자료가 여전히 저희의 기준을 충족하는지 확인합니다. +- 현재 목록에 있는 프로젝트보다 더 많은 기준을 충족하는 추천 프로젝트가 없는지 확인합니다. + +확인하고 알려주시면 도움을 드릴 수 있습니다. [이슈 생성하기](https://github.com/ethereum/ethereum-org-website/issues/new?template=bug_report.yaml) 또는 [website@ethereum.org](mailto:website@ethereum.org)로 이메일을 보내세요. + +--- + +## {#add-your-resource} + +만약 ethereum.org에 콘텐츠 자료를 추가하고자 하고 그것이 기준을 충족한다면, 깃허브에 이슈를 열어 주세요. + + +이슈 만들기 + diff --git a/public/content/translations/ko/contributing/adding-staking-products/index.md b/public/content/translations/ko/contributing/adding-staking-products/index.md new file mode 100644 index 00000000000..ee27f634c59 --- /dev/null +++ b/public/content/translations/ko/contributing/adding-staking-products/index.md @@ -0,0 +1,176 @@ +--- +title: "스테이킹 제품 또는 서비스 추가하기" +description: "Ethereum.org 의 스테이킹 상품 또는 서비스를 추가할 때 사용하는 정책" +lang: ko +--- + +# 스테이킹 제품 또는 서비스 추가하기 {#adding-staking-products-or-services} + +우리는 사용자들이 안심하고 신뢰할 수 있도록 가능한 최고의 자료를 제공하고 있다고 분명히 말씀드리고 싶습니다. + +누구나 ethereum.org에 자유롭게 스테이킹 상품 및 서비스 추가를 제안할 수 있습니다. 누락된 것이 있다면, **[제안해 주세요](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=feature+%3Asparkles%3A%2Ccontent+%3Afountain_pen%3A&template=suggest_staking_product.yaml)!** + +우리는 현재 다음 페이지에서 스테이킹 상품과 서비스를 제공합니다: + +- [단독 스테이킹](/staking/solo/) +- [서비스형 스테이킹](/staking/saas/) +- [스테이킹 풀](/staking/pools/) + +비콘 체인의 PoS는-지분 증명- 2020년 12월 1 일부터 시작되었습니다. 스테이킹이 여전히 상대적으로 새로운 개념이지만, 우리는 ethereum.org에서의 검토를 위해 공정하고 투명한 프레임워크를 만들기 위해 노력해 왔습니다. 하지만 해당 목록 기준은 변화할 것이고 시간이 지남에 따라 진화할 것입니다, 그리고 이는 궁극적으로 ethereum.org 웹사이트 팀의 재량입니다. + +## 의사 결정 프레임워크 {#the-decision-framework} + +어떤 상품을 ethereum.org 목록에 기재할 것인지는 단일한 요소에만 의존하지 않습니다. 목록에 어떠한 상품 또는 서비스를 기재할 것인지 결정할 때는 여러 가지의 기준이 함께 고려됩니다. 이러한 기준이 더 충족될수록, 그 상품 또는 서비스는 목록에 기재될 가능성이 높아집니다. + +**먼저, 어떤 종류의 상품과 서비스가 있을까요?** + +- 노드 또는 클라이언트 도구 +- 키 관리 +- 서비스로서 스테이킹(SaaS) +- 스테이킹 풀 + +현재로서는, 우리는 이 카테고리에 해당하는 상품과 서비스만을 제공합니다. + +### 포함 기준 {#criteria-for-inclusion} + +스테이킹 제품 또는 서비스는 다음 기준에 따라 심사됩니다. + +**프로젝트 또는 서비스가 언제 출시되었습니까?** + +- 언제 해당 상품과 서비스가 공개적으로 이용 가능해졌는지에 대한 증거가 있나요? +- 이 질문은 상품의 배틀 테스트 점수를 계산하는 데 활용됩니다. + +**프로젝트가 지속적으로 관리됩니까?** + +- 해당 프로젝트를 활발히 개발하고 있는 팀이 있나요? 누가 관련돼 있나요? +- 오직 활발히 관리되고 있는 상품만 고려될 것입니다. + +**이 상품과 서비스는 신뢰할 수 있는/인간 중재자 없이 운영되는 것인가요?** + +- 사용자 여정에서 어떠한 단계가 신뢰할 만한 사람에게 자금의 키를 보유하거나 적절하게 보상을 분배할 것을 요구합니까? +- 이 질문은 상품 또는 서비스의 신뢰도 점수를 계산하는 데 활용됩니다. + +**해당 프로젝트는 정확하고 믿을 만한 정보를 제공하나요?** + +- 해당 상품의 웹사이트는 최신 정보이며, 정확하고 오해를 불러일으키지 않아야 하며, 특히 이더리움 프로토콜이나 기타 관련 기술에 관한 내용이라면 더욱 중요합니다. +- 이더리움 또는 기타 관련 주제에 관한 잘못된 정보, 오래된 세부사항, 혹은 잠재적으로 오해를 불러일으킬 수 있는 진술이 포함된 제출물은 목록에 등록되지 않거나, 이미 등록된 경우에는 제거됩니다. + +**어떤 플랫폼을 제공합니까?** + +- 예: Linux, macOS, Windows, iOS, Android + +#### 소프트웨어 및 스마트 계약 {#software-and-smart-contracts} + +맞춤형 소프트웨어 또는 스마트 계약이 포함되는 경우: + +**모든 것이 오픈 소스입니까?** + +- 오픈소스 프로젝트는 공개적으로 이용 가능한 소스 코드 저장소를 갖고 있어야 합니다 +- 이 질문은 상품의 오픈 소스 점수를 계산하는 데 활용됩니다. + +**제품이 _베타_ 개발 단계를 지났습니까?** + +- 개발 단계에서 해당 상품은 어디쯤에 해당하나요? +- 베타 단계에 있는 상품은 ethereum.org에서 고려하는 대상이 아닙니다 + +**해당 소프트웨어는 외부 보안 감사를 받은 적이 있을까요?** + +- 그렇지 않다면, 외부 감사를 실시할 계획이 있으신가요? +- 이 질문은 상품의 감사 점수를 계산하는 데 활용됩니다. + +**프로젝트에 버그 탐색 프로그램이 있습니까?** + +- 만약 아니라면 보안용 버그 바운티 계획이 있나요? +- 이 질문은 상품의 버그 바운티 점수를 계산하는 데 활용됩니다. + +#### 노드 또는 클라이언트 툴링 {#node-or-client-tooling} + +노드 또는 클라이언트 설치 소프트웨어 상품을 위해, 관리 또는 이전: + +**어떤 합의 레이어 클라이언트(예: Lighthouse, Teku, Nimbus, Prysm, Grandine)가 지원됩니까?** + +- 어떠한 클라이언트가 지원되나요? 사용자가 선택할 수 있나요? +- 이 질문은 해당 상품의 "다중-클라이언트" 점수를 평가하기 위해 사용됩니다. + +#### 서비스형 스테이킹 {#staking-as-a-service} + +[서비스형 스테이킹 목록](/staking/saas/)의 경우(예: 위임된 노드 운영): + +**서비스 사용 관련 수수료는 얼마인가요?** + +- 수수료 구조는 어떻게 됩니까? 예: 서비스에 월간 수수료가 있습니까? +- 추가 스테이킹 요구사항이 있나요? + +**사용자는 계정 가입이 필요한가요?** + +- 누군가가 승인이나 KYC 없이 서비스를 사용할 수 있나요? +- 이 질문은 상품의 "허용성" 점수를 평가하기 위해 사용됩니다. + +**누가 서명 키와 출금 키를 보유해야 하나요?** + +- 사용자는 어떤 키의 접속 권한을 유지해야 하나요? 서비스는 어떤 키의 접속 권한을 획득해야 하나요? +- 이 질문은 상품의 "신뢰도" 점수를 평가하기 위해 사용됩니다. + +**운영되는 노드의 클라이언트 다양성은 어떻게 되나요?** + +- 검증자 키의 몇 퍼센트가 주요 다수 합의 계층 (CL) 클라이언트에 의해 실행되고 있나요? +- 마지막 수정 시점 기준으로, Prysm은 대다수 노드 운영자가 사용하는 합의 레이어 클라이언트로, 이는 네트워크에 위험을 불러올 수 있습니다. 만약 현재 네트워크의 33% 이상이 특정 CL 클라이언트에 사용되고 있다면, 우리는 사용과 관련된 데이터를 요청합니다. +- 이 질문은 상품의 "클라이언트 다양성" 점수를 평가하기 위해 사용됩니다. + +#### 스테이킹 풀 {#staking-pool} + +[풀 스테이킹 서비스](/staking/pools/)의 경우: + +**스테이킹에 필요한 최소 ETH는 얼마인가요?** + +- 예: 0.01 ETH + +**수수료와 스테이킹 요구사항에는 무엇이 포함되나요?** + +- 수수료로 몇 퍼센트의 보상이 차감되나요? +- 추가 스테이킹 요구사항이 있나요? + +**유동성 토큰이 있나요?** + +- 토큰이 포함하는 것은 무엇인가요? 그것은 어떻게 작동하나요? 컨트랙트 주소가 어떻게 되나요? +- 이 질문은 상품의 유동성 토큰 점수를 계산하는 데 활용됩니다. + +**사용자는 노드 운영자로 참여할 수 있나요?** + +- 검증자 클라이언트가 자금 풀을 사용하려면 무엇이 필요한가요? +- 개인, 회사 혹은 DAO로부터 승인이 필요한가요? +- 이 질문은 상품의 허용성 노드 점수를 계산하는 데 활용됩니다. + +**노드 풀 운영자의 클라이언트 다양성은 어떻게 되나요?** + +- 노드 운영자의 몇 퍼센트가 주요 합의 레이어(CL) 클라이언트를 운영하고 있나요? +- 마지막 수정 시점 기준으로, Prysm은 대다수 노드 운영자가 사용하는 합의 레이어 클라이언트로, 이는 네트워크에 위험을 불러올 수 있습니다. 만약 현재 네트워크의 33% 이상이 특정 CL 클라이언트에 사용되고 있다면, 우리는 사용과 관련된 데이터를 요청합니다. +- 이 질문은 상품의 "클라이언트 다양성" 점수를 평가하기 위해 사용됩니다. + +### 기타 기준: 있으면 좋은 항목 {#other-criteria} + +**어떤 유저 인터페이스-Ui-가 지원되나요?** + +- 예: 브라우저 앱, 데스크톱 앱, 모바일 앱, CLI + +**노드 툴링을 위해, 해당 소프트웨어는 클라이언트 간 변경을 쉽게 할 수 있도록 돕나요?** + +- 해당 툴을 사용해 사용자는 쉽고 안전하게 클라이언트 간 변경을 할 수 있나요? + +**SaaS-서비스용 소프트웨어-을 위해, 얼마나 많은 검증자들이 현재 서비스를 운영 중인가요?** + +- 이 질문은 그동안 당신의 서비스 범위를 가늠할 수 있게 해줍니다. + +## 결과 표시 방법 {#product-ordering} + +위의 [포함 기준](#criteria-for-inclusion)은 각 제품 또는 서비스의 누적 점수를 계산하는 데 사용됩니다. 이는 특정한 객관적인 기준을 충족하는 상품을 분류하고 보여주는 수단으로 사용됩니다. 증거가 제출된 기준이 많을수록 상품의 정렬 순위가 높아지며, 순위가 같을 경우에는 로드 시 무작위로 순서가 결정됩니다. + +이 기준에 대한 코드 로직 및 가중치는 현재 저희 리포지토리의 [이 JavaScript 구성 요소](https://github.com/ethereum/ethereum-org-website/blob/dev/src/components/Staking/StakingProductsCardGrid.js#L350)에 포함되어 있습니다. + +## 제품 또는 서비스 추가하기 {#add-product} + +Ethereum.org 에 스테이킹 상품 또는 서비스를 추가하려면 GitHub에서 이슈를 생성하십시오. + + +이슈 만들기 + diff --git a/public/content/translations/ko/contributing/adding-wallets/index.md b/public/content/translations/ko/contributing/adding-wallets/index.md new file mode 100644 index 00000000000..83edde9aa77 --- /dev/null +++ b/public/content/translations/ko/contributing/adding-wallets/index.md @@ -0,0 +1,80 @@ +--- +title: "지갑 추가하기" +description: "Ethereum.org에 지갑을 추가할 때 우리가 사용하는 정책" +lang: ko +--- + +# 지갑 추가하기 {#adding-wallets} + +사용자가 이더리움을 자신감 있게 탐색할 수 있도록 다양한 지갑의 기능이 풍부한 풍경을 보여주고자 합니다. + +누구나 ethereum.org 에서 지갑 추가를 자유롭게 제안할 수 있습니다. 우리가 놓친 지갑이 있다면, 추천해 주세요! + +지갑은 현재 다음에 나열되어 있습니다: + +- [ethereum.org/wallets/find-wallet/](/wallets/find-wallet/) + +이더리움에서 지갑은 빠르게 변화하고 있습니다. ethereum.org 에서 고려하기 위한 공정한 프레임워크를 만들려고 노력하겠지만, 목록의 기준은 시간이 지남에 따라 변경되고 발전할 것입니다. + +## 의사 결정 프레임워크 {#the-decision-framework} + +### 포함 기준: 필수 항목 {#the-must-haves} + +- **보안 테스트를 통과한 제품** - 감사, 내부 보안팀, 오픈소스 코드 또는 기타 방법을 통해 지갑의 보안이 신뢰할 수 있어야 합니다. 이는 사용자에 대한 위험을 줄이고 귀하가 보안을 중요하게 생각한다는 것을 보여줍니다. +- **6개월 이상 '라이브' 상태이거나 신뢰할 수 있는 실적을 가진 그룹에서 출시한 지갑** - 이는 보안을 나타내는 또 다른 지표입니다. 6개월은 중요한 버그와 익스플로잇이 발견되기에 좋은 기간입니다. 프로젝트로 빠르게 버려지는 포크를 걸러내는 데 6개월이 걸립니다. +- **활발한 팀의 작업** - 이는 품질을 보장하고 사용자가 질문에 대한 지원을 받을 수 있도록 도와줍니다. +- **정직하고 정확한 등록 정보** - 프로젝트에서 제안하는 모든 등록 정보는 정직하고 정확해야 합니다. 제품이 "오픈 소스"라고 선언하는 등 목록 정보를 위조하는 제품은 삭제됩니다. +- **연락 담당자** - 지갑의 연락 담당자가 있으면 변경 사항이 있을 때 정확한 정보를 얻는 데 큰 도움이 됩니다. 이것은 향후 정보를 수집할 때 관리 가능한 ethereum.org 업데이트를 계속할 것입니다. +- **EIP-1559(유형 2) 트랜잭션** - 귀하의 지갑은 메인넷 이더리움에서의 트랜잭션을 위해 EIP-1559(유형 2) 트랜잭션을 지원해야 합니다. +- **우수한 사용자 경험** - UX는 주관적이지만, 여러 핵심 팀원이 제품을 테스트한 후 사용하기 어렵다고 판단되면, 저희는 해당 지갑을 거부하고 대신 개선을 위한 유용한 제안을 제공할 권리가 있습니다. 이는 주로 초보자로 구성된 사용자 기반을 보호하기 위해 수행됩니다. +- **이더리움 중심** - 지갑은 기본적으로 이더리움 중심의 경험을 제공해야 합니다. 이는 이더리움(또는 모든 L2)이 기본 네트워크로 설정되고, ERC 자산이 제대로 지원되며, 기능이 이더리움 생태계와 부합함을 의미합니다. UI에서 대체 레이어 1을 우선시하는 지갑은 등재되지 않습니다. + +### 제품 삭제 {#product-removals} + +- **업데이트된 정보** - 지갑 제공업체는 제공된 정보의 유효성과 관련성을 보장하기 위해 6개월마다 지갑 정보를 다시 제출해야 합니다(제품에 변경 사항이 없는 경우에도 마찬가지입니다). 제품 팀이 그렇게 하지 못하면, ethereum.org 는 페이지에서 프로젝트를 삭제할 수 있습니다. + +### 기타 기준: 있으면 좋은 기능 {#the-nice-to-haves} + +- **전 세계적으로 접근 가능** - 귀하의 지갑에는 특정인이 서비스에 접근하는 것을 배제하는 지리적 제한이나 KYC 요건이 없습니다. +- **여러 언어로 제공** - 귀하의 지갑은 여러 언어로 번역되어 전 세계 사용자가 접근할 수 있습니다. +- **오픈소스** - 전체 프로젝트의 코드베이스(모듈뿐만 아니라)에 접근할 수 있어야 하며, 더 넓은 커뮤니티의 PR을 수락해야 합니다. +- **비수탁형** - 사용자가 자신의 자금을 관리합니다. 귀하의 제품이 사라지더라도 사용자는 계속해서 자금에 접근하고 자금을 이동할 수 있습니다. +- **하드웨어 지갑 지원** - 사용자는 하드웨어 지갑을 연결하여 트랜잭션에 서명할 수 있습니다. +- **WalletConnect** - 사용자는 WalletConnect를 사용하여 탈중앙화앱에 연결할 수 있습니다. +- **이더리움 RPC 엔드포인트 가져오기** - 사용자는 노드 RPC 데이터를 가져와서 원하는 노드나 다른 EVM 호환 네트워크에 연결할 수 있습니다. +- **NFT** - 사용자는 지갑에서 자신의 NFT를 보고 상호작용할 수 있습니다. +- **이더리움 애플리케이션에 연결** - 사용자는 이더리움 애플리케이션에 연결하고 사용할 수 있습니다. +- **스테이킹** - 사용자는 지갑을 통해 직접 스테이킹할 수 있습니다. +- **스왑** - 사용자는 지갑을 통해 토큰을 스왑할 수 있습니다. +- **멀티체인 네트워크** - 귀하의 지갑은 사용자가 기본적으로 여러 블록체인 네트워크에 접근할 수 있도록 지원합니다. +- **레이어 2 네트워크** - 귀하의 지갑은 사용자가 기본적으로 레이어 2 네트워크에 접근할 수 있도록 지원합니다. +- **가스 수수료 맞춤 설정** - 귀하의 지갑은 사용자가 트랜잭션 가스 수수료(기본 수수료, 우선 수수료, 최대 수수료)를 맞춤 설정할 수 있도록 허용합니다. +- **ENS 지원** - 귀하의 지갑은 사용자가 ENS 이름으로 트랜잭션을 보낼 수 있도록 합니다. +- **ERC-20 지원** - 귀하의 지갑은 사용자가 ERC-20 토큰 계약을 가져오거나, ERC-20 토큰을 자동으로 쿼리하고 표시하도록 허용합니다. +- **암호화폐 구매** - 귀하의 지갑은 사용자가 직접 암호화폐를 구매하고 온보딩할 수 있도록 지원합니다. +- **법정화폐로 판매** - 귀하의 지갑은 사용자가 판매하여 카드나 은행 계좌로 직접 법정화폐를 인출할 수 있도록 지원합니다. +- **다중 서명** - 귀하의 지갑은 트랜잭션 서명을 위해 다중 서명을 지원합니다. +- **소셜 복구** - 귀하의 지갑은 가디언을 지원하며 사용자는 시드 구문을 분실한 경우 이 가디언을 사용하여 지갑을 복구할 수 있습니다. +- **전담 지원팀** - 귀하의 지갑에는 문제가 발생했을 때 사용자가 문의할 수 있는 전담 지원팀이 있습니다. +- **교육 자료/문서** - 제품은 사용자를 돕고 교육하기 위해 잘 설계된 온보딩 경험을 갖추고 있어야 합니다. 또는 기사나 비디오와 같은 콘텐츠 사용 방법에 대한 증표입니다. + +## 지갑 추가하기 {#adding-a-wallet} + +만약 ethereum.org에 지갑을 추가하고 싶다면, 깃허브에 이슈를 만들어주세요. + + +이슈 만들기 + + +## 유지보수 {#maintenance} + +Ethereum의 유동적 특성과 마찬가지로 팀과 제품은 왔다 갔다 하며 매일 혁신이 이루어지므로, 다음 사향들을 위해 정기적으로 콘텐츠를 점검할 것입니다. + +- 모든 지갑과 디앱 목록이 계속해서 기준을 충족하도록 유의해 주세요 +- 현재 상장된 제품보다 더 많은 기준을 충족하는 제안된 제품이 없는지 확인합니다. + +ethereum.org는 오픈소스 커뮤니티에 의해 유지 관리되며, 최신 상태를 유지하기 위해 커뮤니티의 도움을 받고 있습니다. 등재된 지갑에 대한 정보 중 업데이트가 필요한 부분을 발견하시면, [이슈를 열거나](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=wallet+%3Apurse%3A&template=suggest_wallet.yaml) [풀 리퀘스트](https://github.com/ethereum/ethereum-org-website/pulls)를 제출해 주세요! + +## 이용약관 {#terms-of-use} + +또한 [이용약관](/terms-of-use/)을 참조하시기 바랍니다. ethereum.org 의 정보는 일반적인 정보 목적으로만 제공됩니다. diff --git a/public/content/translations/ko/contributing/content-resources/index.md b/public/content/translations/ko/contributing/content-resources/index.md new file mode 100644 index 00000000000..0f331101290 --- /dev/null +++ b/public/content/translations/ko/contributing/content-resources/index.md @@ -0,0 +1,32 @@ +--- +title: "콘텐츠 자료 추가하기" +lang: ko +description: "Ethereum.org 참고 자료 콘텐츠의 목록에 대한 기준" +--- + +# 콘텐츠 자료 추가하기 {#adding-content-resources} + +우리는 이더리움에 관한 모든 것을 다룰 수는 없기 때문에, 커뮤니티에서 만든 뛰어난 기사, 듀토리얼, 뉴스레터, 구직 게시판, 다양한 콘텐츠 자료 등 일부를 보여드리고자 합니다. 이는 종종 사용자의 흥미를 끌 수 있는 주제에 대해 심도 깊은 추가 정보를 제공합니다. + +만약 페이지에 추가해야 할 콘텐츠 자료가 있다고 생각하신다면, 적절한 경로를 통해 자유롭게 제안해 주세요. + +## 결정 방식 {#how-we-decide} + +학습 자료는 다음 기준에 따라 심사됩니다. + +- 콘텐츠가 최신입니까? +- 결제가 필요한 콘텐츠입니까? +- 정보가 정확합니까? 사실적이거나 또는 의견을 바탕으로 하고 있습니까? +- 신뢰할 수 있는 저자입니까? 소스를 참조하고 있는가? +- 이 콘텐츠는 현재 존재하는 자료/링크가 다루지 않는 독자적인 내용을 제공하나요? +- 이 콘텐츠가 저희 [사용자 페르소나](https://www.notion.so/efdn/Ethereum-org-User-Persona-Memo-b44dc1e89152457a87ba872b0dfa366c) 중 하나에 부합하나요? + +--- + +## 콘텐츠 자료를 추가하세요 {#add-your-content-resource} + +만약 ethereum.org에 콘텐츠 자료를 추가하고자 하고 그것이 기준을 충족한다면, 깃허브에 이슈를 열어 주세요. + + +이슈 만들기 + diff --git a/public/content/translations/ko/contributing/design-principles/index.md b/public/content/translations/ko/contributing/design-principles/index.md new file mode 100644 index 00000000000..bcb0fd8328b --- /dev/null +++ b/public/content/translations/ko/contributing/design-principles/index.md @@ -0,0 +1,93 @@ +--- +title: "디자인 원칙" +lang: ko +description: "ethereum.org의 디자인과 콘텐츠 결정의 배경이 되는 원칙" +--- + +# 우리의 디자인 원칙 {#contributing-to-ethereumorg-} + + 안녕하세요, ethereum.org의 디자인 원칙에 오신 것을 환영합니다. 이것은 ethereum.org를 발전시키고 개선하기 위한 지속적인 과정의 일부입니다. + +우리의 원칙은 사이트의 디자인과 분위기, 그리고 그 안에 있는 콘텐츠에 영향을 줍니다. + +[ethereum.org에 기여](/contributing/)하기 전에 이 내용을 읽어야 합니다. + +## 디자인 원칙이란 무엇일까요? {#ways-to-contribute} + +걱정하지 마세요, 꽤 간단합니다! 디자인 원칙은 무언가를 디자인(즉, 생성, 유지 또는 업데이트)할 때 참고하는 일련의 지침입니다. + +ethereum.org의 맥락에서 이러한 디자인 원칙은 웹사이트가 세상에 표현하고 투영하고자 하는 것의 기초입니다. 이 원칙들은 열망적이면서도 기능적입니다. 이는 웹사이트가 어떻게 보이는지뿐만 아니라 어떻게 _작동하는지_, 심지어 누군가에게 어떤 느낌을 주는지에 관한 것입니다. 색상부터 페이지 레이아웃, 웹사이트에서 이더리움에 대해 이야기하는 방식까지 모든 것이 이 원칙에 따라야 합니다. + +## 실제 적용되는 원칙 {#how-decisions-about-the-site-are-made} + +예를 들어보겠습니다. 원칙 중 하나는 "신뢰성"입니다. 이는 방문객들이 더 넓은 이더리움 생태계처럼 사이트가 신뢰할 수 있다는 것을 _느끼고_ _알게_ 되기를 바란다는 의미입니다. 그 원칙 내에는 사이트의 신뢰성을 높이기 위해 취할 수 있는 실행 가능한 단계라고 믿는 3가지 기능적 "하위 원칙"이 있습니다. + +- _"최신성"_, 즉 콘텐츠를 최신 상태로 유지합니다. +- _"사회적 증거"_, 즉 생태계의 규모, 다양성 및 활동을 보여줍니다(예: 이더리움 업그레이드 진행 상황, 디파이, 게임, 모든 해커톤 등). +- _"일관성"_, 즉 사이트 디자인의 일관성 및 글의 어조와 정확성. + +따라서 디자인 결정이나 카피라이팅 결정을 내릴 때 "신뢰성" 원칙을 참조하여 다음과 같이 질문할 수 있습니다. + +- _"사이트가 최신 정보를 반영하고 있나요?"_ +- _"생태계의 규모와 활동을 어떻게, 어디에 보여주고 있나요?"_ +- _"제가 검토 중인 커뮤니티 회원의 새로운 기여 제안이 사이트의 현재 디자인 및 글과 일치하나요?"_ + +## ethereum.org 디자인 원칙 {#contributors} + +### 1. 영감을 주는 {#1-inspirational} + +이 사이트는 사용자가 이더리움이 어떻게 세상을 바꿀 수 있는지 꿈꾸도록 영감을 주어야 합니다. 사람들이 이더리움 생태계의 도구와 앱을 탐색하고, 사용하고, 만져보도록 동기를 부여해야 합니다. + +- **급진성:** 이 사이트는 의미 있게 세상을 바꾸려는 이더리움의 야심 찬 목표를 전달해야 합니다. 이더리움은 단순히 새로운 기술 스택이 아니라, 변혁적인 기술이라는 점을 분명히 해야 합니다. +- **교육을 통한 권한 부여:** 이 사이트는 사람들이 이더리움의 잠재력을 이해하고, 생태계에서 자신의 위치를 찾으며, 참여할 수 있는 권한을 느끼도록 교육해야 합니다. + +시각적 방향 • 콘텐츠 + +### 2. 보편성 {#2-universal} + +이더리움은 글로벌하고 탈중앙화된 프로젝트이며, 우리의 잠재 고객도 이를 반영합니다. 이 사이트는 모든 사람이 접근할 수 있고, 세계의 다양한 문화에 민감하도록 노력해야 합니다. + +- **접근성:** 이 사이트는 대역폭이 낮은 연결을 사용하는 사람들을 포함하여 접근성 가이드라인을 따라야 합니다. +- **명료성:** 이 사이트는 간단하고 명확해야 합니다. 문구는 오해의 소지가 있거나 번역 과정에서 의미가 손실될 수 있는 언어를 사용해서는 안 됩니다. +- **이더리움은 다면적입니다:** 이더리움은 프로젝트, 코드베이스, 커뮤니티 및 비전입니다. 이더리움은 다양한 사람들에게 다양한 이유로 가치가 있으며, 참여할 수 있는 방법도 여러 가지가 있습니다. + +쓰기 체계 • 색상 사용 • 시각적 방향 • 콘텐츠 + +### 3. 좋은 이야기 {#3-a-good-story} + +웹사이트는 좋은 이야기처럼 기능해야 합니다. 방문객들은 여정 중에 있으며, 여러분이 기여하는 콘텐츠는 그 여정의 일부입니다. 여러분의 기여는 명확한 서사 구조에 들어맞아야 합니다. 즉, 시작(소개/진입점), 중간(일련의 학습과 통찰), 끝(관련 참고 자료 링크 또는 다음 단계)이 있어야 합니다. + +- **계층적**: 명확하고 계층적으로 구조화된 정보 아키텍처는 ethereum.org 방문객이 목표를 달성하기 위해 사이트를 "이야기처럼" 탐색하는 데 도움이 됩니다. +- **디딤돌:** 우리는 답을 찾는 모든 사람을 위한 디딤돌입니다. 우리는 이미 존재하는 많은 참고 자료를 대체하거나 대신하기를 원하지 않습니다. 우리는 답을 주고 신뢰할 수 있는 다음 단계를 제공합니다. + +사용자 여정 • 콘텐츠 + +### 4. 신뢰성 {#4-credible} + +사람들은 이더리움 생태계에 대한 소개를 찾고 있거나 회의론자일 수 있습니다. 소통 방식에서 그 책임을 인식하세요. 두 그룹 모두 이더리움 생태계에 대한 더 큰 신뢰를 갖고 떠나도록 해야 합니다. + +- **최신성:** 항상 최신 상태를 유지합니다. +- **사회적 증거:** 생태계의 규모, 다양성 및 활동을 보여줍니다. +- **일관성:** 디자인과 콘텐츠의 일관성은 신뢰성을 전달합니다. + +시각적 방향 • 콘텐츠 + +### 5. 협력적 개선 {#5-collaborative-improvement} + +이 웹사이트는 생태계 전체와 마찬가지로 많은 기여자의 산물입니다. + +- **개방성:** 생태계 전반의 소스 코드, 프로세스 및 프로젝트의 투명성을 기념합니다. +- **확장성:** 모듈성은 우리가 하는 모든 일의 핵심 초점이며, 따라서 기여도 모듈식이어야 합니다. 사이트의 핵심 디자인, 구성 요소 코드 및 구현은 미래에 쉽게 확장될 수 있도록 해야 합니다. +- **실험성:** 우리는 끊임없이 실험하고, 테스트하고, 반복합니다. +- **협력성:** 이 프로젝트는 우리 모두를 하나로 모읍니다. +- **지속 가능성:** 커뮤니티에 의한 장기적인 유지 관리를 위한 설정 + +우리의 디자인 원칙이 [우리 사이트 전반](/)에 걸쳐 어떻게 적용되는지 확인할 수 있습니다. + +## 피드백 제공 {#give-feedback} + +**이 문서에 대한 피드백을 공유해 주세요!** 우리가 제안한 원칙 중 하나는 "**협력적 개선**"이며, 이는 웹사이트가 많은 기여자의 산물이 되기를 원한다는 것을 의미합니다. 따라서 그 원칙의 정신에 따라 우리는 이러한 디자인 원칙을 이더리움 커뮤니티와 공유하고자 합니다. + +이 원칙들은 ethereum.org 웹사이트에 중점을 두고 있지만, 이들 중 다수가 이더리움 생태계 전반의 가치를 대표하기를 바랍니다. 어쩌면 여러분의 프로젝트에 이 원칙들 중 일부를 통합하고 싶을 수도 있습니다! + +[Discord 서버](https://discord.gg/ethereum-org)에서 또는 [이슈 생성](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=Type%3A+Feature&template=feature_request.yaml&title=)을 통해 여러분의 생각을 알려주세요. diff --git a/public/content/translations/ko/contributing/design/adding-design-resources/index.md b/public/content/translations/ko/contributing/design/adding-design-resources/index.md new file mode 100644 index 00000000000..3d3e669cf91 --- /dev/null +++ b/public/content/translations/ko/contributing/design/adding-design-resources/index.md @@ -0,0 +1,69 @@ +--- +title: "디자인 리소스 추가" +description: "Ethereum.org의 디자인 자료 품질을 보장하기 위한 지침 및 요구 사항" +lang: ko +--- + +# 디자인 참고 자료 추가하기 {#adding-design-resources} + +누구나 [웹3 디자인 및 UX 페이지](/developers/docs/design-and-ux/)에 새로운 디자인 자료를 제안할 수 있습니다. + +이 페이지는 예비 웹3 디자이너에게 사용자 중심의 가치를 전달하는 데 초점을 맞추고 있습니다. 디자인 섹션은 서비스, 제품 또는 플랫폼을 광고하기 위해 있는 것이 아닙니다. + +높은 수준의 정보 품질을 유지하고 통찰력을 제공하기 위해 우리는 다음과 같은 목록 정책을 수립했습니다: + +## 연구 자료와 대시보드 {#Research-studies} + +1. 신뢰할 수 있는 방법론 + +a. 방법론에서는 데이터를 어떻게 수집했는지 명확하게 기술해야 합니다. + +b. 연구에 참여한 참가자 수가 명시되어야 합니다. + +c. 어떤 연구 방법이 사용되었는지 설명되어야 합니다. + +2. 웹3 디자이너와의 관련성 및 일반적인 디자인 사용 사례 + +a. 연구 주제는 웹3 디자이너와 관련성이 있어야 하며, 일반적인 디자인 활용 사례를 다루어야 합니다. + +3. 인사이트 제공에 집중해야 합니다 + +a. 본문의 주된 목적은 특정 프로젝트나 회사를 홍보하는 것이 아니라, 통찰력을 공유하는 데 있습니다. + +## 아티클 {#Articles} + +1. 웹3 디자이너/연구자와의 관련성 및 일반적인 웹3 디자인 사용 사례 + +a. 이 글의 주제는 웹3 디자이너와 연구자에게 적합해야 하며, 일반적인 웹3 디자인 사용 사례에 초점을 맞춰야 합니다. + +2. 작성 기준 + +a. 문법 및 철자 오류가 없어야 합니다. + +b. 핵심적인 통찰력과 학습 내용을 전달하는 데 중점을 두어야 합니다. + +c. 간결하고 핵심을 정확하게 전달해야 합니다. + +3. 본문의 목표 + +a. 본문의 주된 목적은 특정 프로젝트나 회사를 홍보하는 것이 아니라, 통찰력을 공유하는 데 있습니다. + +## 커뮤니티 / DAO {#Communities-and-DAOs} + +1. 웹사이트는 DAO/커뮤니티 가입 방법을 명확하게 안내해야 합니다 + +2. 멤버십의 명확한 혜택 + +a. 멤버십 혜택은 가시성있게 표시되어야 합니다. + +**예시**: 작업에 대한 피드백 받기, 채용 기회 또는 바운티 참여, 디자인 및 연구 인사이트 공유. + +3. 디스코드 서버에서 활발한 소통 + +a. Discord 커뮤니티는 활발하고 적극적인 소통을 보여주어야 합니다. + +b. 커뮤니티 관리자는 커뮤니티를 유지하고 토론을 촉진하는 데 적극적으로 참여해야 합니다. + +c. 커뮤니티는 지난 2주 동안 가치 있고 생산적인 대화가 활발히 이루어졌다는 실적을 입증해야 합니다. + +이 기준을 준수하여, 활기차고 지식 공유가 활발한 커뮤니티 환경을 만들고자 합니다. 우리는 이러한 화이트 리스팅 정책이 사용자들에게 신뢰할 수 있고, 관련성 높으며, 통찰력 있는 자료에 접근할 수 있도록 보장할 것이라고 믿습니다. 플랫폼 내 콘텐츠 품질 유지를 위한 이해와 협조에 감사드립니다. diff --git a/public/content/translations/ko/contributing/design/index.md b/public/content/translations/ko/contributing/design/index.md new file mode 100644 index 00000000000..40bea1ac818 --- /dev/null +++ b/public/content/translations/ko/contributing/design/index.md @@ -0,0 +1,77 @@ +--- +title: "디자인 기여" +description: "Ethereum.org에 디자인 기여하기" +lang: ko +--- + +# ethereum.org 디자인 기여 {#design-contributions} + +디자인은 모든 프로젝트에서 중요한 요소이며, 여러분의 시간과 디자인 역량을 ethereum.org에 기여함으로써 방문자들의 사용자 경험을 향상시키는 데 도움을 줄 수 있습니다. 오픈 소스 프로젝트에 기여하는 것은 관련 경험을 쌓고 협업 환경에서 기술을 개발할 수 있는 기회를 제공합니다. 여러분은 다른 디자이너, 개발자, 그리고 커뮤니티 멤버들과 협업할 기회를 얻게 되며, 이들은 모두 독창적인 시각과 깊은 통찰력을 지니고 있습니다. + +결과적으로, 이는 여러분의 디자인 능력을 효과적으로 보여줄 수 있는 포트폴리오를 구축하는 좋은 기회가 됩니다. + +## 기여 방법? + +###  초기 디자인 프로토타입에 대한 피드백 제공 {#design-critique} + +우리는 때때로 초기 아이디어를 테스트하는 데 도움을 필요로 합니다. 이는 기술적 지식이 없어도 기여할 수 있는 좋은 방법입니다. + +1. 디자인팀은 [Discord](https://discord.com/invite/ethereum-org)와 [GitHub](https://github.com/ethereum/ethereum-org-website/labels/design%20required%20%F0%9F%8E%A8)에 모의 디자인을 공유합니다. +2. 여러분은 디자인에 대한 설명을 듣고 댓글 기능을 통해 피드백을 제공할 수 있습니다. +3. 결과는 GitHub 이슈에 공유되며, 팀에서 최종 검토 후 이슈를 닫습니다. + +###  설문 조사 참여 {#answer-surveys} + +웹사이트에 피드백을 제공하는 방법: + +1. Ethereum.org을 방문하여 페이지를 읽어봅니다. +2. 오른쪽 하단 모서리에 있는 피드백 위젯을 클릭하여 디자인 및 콘텐츠 관련 질문에 답변합니다. +3. 자유 형식 질문에 특히 집중해 주시기 바랍니다. + +###  웹사이트에서 디자인 관련 문제를 찾아 신고하기 {#report-design-issues} + +ethereum.org는 빠르게 성장하는 웹사이트로, 다양한 기능과 콘텐츠를 제공합니다. 일부 UI는 구식이 되거나 개선의 여지가 있을 수 있습니다. 이러한 문제점을 발견하신다면, 저희가 인지할 수 있도록 제보해 주시기 바랍니다. + +1. 웹사이트를 살펴보며 디자인을 주의 깊게 봐주세요. +2. 관련 문제나 UX 문제를 발견하면 스크 린샷을 찍어 두세요. +3. 발견된 문제는 [버그 리포트](https://github.com/ethereum/ethereum-org-website/issues/new/choose)를 사용하여 신고해 주세요. + +###  디자인 변경 제안 {#propose-design-changes} + +디자인 과제에 도전하는 것이 편하시다면, GitHub 이슈 보드를 방문하여 [디자인 관련 이슈](https://github.com/ethereum/ethereum-org-website/labels/design%20required%20%F0%9F%8E%A8)를 필터링해 보세요. + +1. 웹사이트를 살펴보며 디자인에 주의를 기울이거나, GitHub 저장소에서 [“Design required” 태그](https://github.com/ethereum/ethereum-org-website/labels/design%20required%20%F0%9F%8E%A8)가 붙은 이슈들을 검토해 보세요. +2. 해결책을 구상하고 디자인 하세요. (가급적 [디자인 시스템](https://www.figma.com/community/file/1134414495420383395)을 사용해 주세요). +3. 해당 GitHub 이슈에 해결책을 제안하거나 [새로운 이슈를 생성](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=feature+%3Asparkles%3A&template=feature_request.yaml&title=Feature+request)하세요. +4. 이후 디자인 팀의 검토를 기다리면 됩니다. + +###  디자인 시스템 함께 구축하기 {#Contribute-to-design-system} + +우리 디자인 시스템은 ethereum.org를 쉽고 재미있게 디자인할 수 있도록 도와줍니다. 경험 많은 디자이너라면 다양한 웹사이트 컴포넌트 제작에 기여하실 수 있습니다. + +1. GitHub의 [디자인 시스템 보드](https://github.com/ethereum/ethereum-org-website/labels/design%20system)에서 작업할 이슈를 선택하거나 새로운 이슈를 생성하세요. +2. 선택한 이슈에 대해 할당을 요청하세요. +3. Figma에서 요청받은 컴포넌트 디자인을 시작하세요. +4. 검토 또는 지침이 필요하면 GitHub에서 디자인 팀과 공유하세요. +5. 디자인 팀이 해당 사항을 검토합니다. +6. 디자인 팀은 변경 사항을 반영하고 해당 파일을 커뮤니티에 게시할 것입니다. + +###  웹사이트에 디자인 관련 콘텐츠 작성하기 {#write-design-articles} + +이더리움 개발자 커뮤니티는 강력하지만, 디자인 커뮤니티는 다소 뒤쳐진 상태입니다. 웹3 지식을 갖춘 디자이너라면, 커뮤니티 전체가 함께 성장하고 발전할 수 있도록 여러분의 지식을 공유해 주세요. 여러분이 기여할 수 있는 [이더리움을 위한 디자인 페이지](/developers/docs/design-and-ux/)가 있습니다. 또한 저희 [리스팅 정책](/contributing/design/adding-design-resources)을 확인하실 수 있습니다. + +1. Ethereum.org에서 다뤄야 할 디자인 주제를 구상해 보고, 디자이너들에게 도움이 될 수 있는 내용을 제안해 보세요. +2. GitHub 저장소로 이동하여 주제를 제안하는 [이슈를 생성](https://github.com/ethereum/ethereum-org-website/issues/new)해 주세요 (아직 내용은 작성하지 마세요). +3. 디자인 팀의 승인을 기다리세요. +4. 승인되면 콘텐츠를 작성하세요. +5. 해당 GitHub 이슈에 제출해 주세요. + +###  새 일러스트레이션 그리기 {#prepare-illustrations} + +시각화는 추상적인 주제를 설명하는 가장 강력한 도구 중 하나입니다. 다이어그램과 인포그래픽을 추가하면 엄청난 잠재력이 있습니다. 결국 한 장의 그림은 천 마디 말의 가치를 담고 있습니다. + +1. 우리 웹사이트를 방문하여 새로운 인포그래픽이 추가될 수 있는 페이지를 확인하세요. +2. 일러스트레이션 스타일이 저희 [자료](/assets/)와 일치하는지 확인하세요. +3. GitHub 저장소로 이동하여 일러스트레이션을 제안하는 [이슈를 생성](https://github.com/ethereum/ethereum-org-website/issues/new)하세요. +4. 디자인 팀이 검토할 것입니다. +5. 새 이미지를 구현할 개발자에게 작업을 요청하기 위해 이슈를 새로 만듭니다. diff --git a/public/content/translations/ko/contributing/index.md b/public/content/translations/ko/contributing/index.md new file mode 100644 index 00000000000..1d24dbd6656 --- /dev/null +++ b/public/content/translations/ko/contributing/index.md @@ -0,0 +1,120 @@ +--- +title: "기여하기" +description: "ethereum.org에 기여할 수 있는 다양한 방법들을 알아봅니다" +lang: ko +--- + +# ethereum.org에 기여하기 🦄 {#contributing-to-ethereumorg} + +Ethereum.org는 웹사이트의 번역, 집필, 디자인 및 유지 관리를 지원하는 12,000명 이상의 기여자와 함께하는 오픈 소스 프로젝트입니다. + +저희는 이더리움 생태계에서 여러분이 성장하고 배우는 동시에 의미 있게 기여하고 관련 실무 경험을 쌓을 수 있도록 돕는 따뜻한 커뮤니티입니다! + +## 기여하는 방법 {#ways-to-contribute} + +**번역** + +- [번역 프로그램에 참여하기](/contributing/translation-program/) – ethereum.org를 새로운 언어로 제공할 수 있도록 도와주세요 + +**개발** + +- [미해결 이슈에 참여하기](https://github.com/ethereum/ethereum-org-website/issues) – 저희가 해결이 필요하다고 확인한 작업입니다 + +**디자인** + +- [웹사이트 디자인 돕기](/contributing/design/) – 모든 수준의 디자이너가 웹사이트 개선에 기여할 수 있습니다 + +**콘텐츠** + +- [콘텐츠 제작/편집하기](/contributing/#how-to-update-content) – 새로운 페이지를 제안하거나 기존 콘텐츠를 수정하세요 +- [커뮤니티 자료 추가하기](/contributing/content-resources/) – 관련 페이지에 유용한 글이나 자료를 추가하세요 +- [디자인 자료 제안하기](/contributing/design/adding-design-resources/) – 유용한 디자인 자료를 추가, 업데이트 및 삭제합니다 +- [퀴즈](/contributing/quizzes/) – 관련 페이지의 퀴즈 문제 은행을 추가, 업데이트 및 삭제합니다 + +**기능 아이디어** + +- [기능 요청하기](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=Type%3A+Feature&template=feature_request.yaml&title=) – 새로운 기능이나 디자인에 대한 아이디어를 알려주세요 + +**제품 목록** + +- [거래소 추가하기](/contributing/adding-exchanges/) – [거래소 찾기](/get-eth/#country-picker)에 거래소를 추가하세요 +- [제품 추가하기](/contributing/adding-products/) – 관련 페이지에 탈중앙화앱이나 지갑을 추가하세요 +- [개발자 도구 추가하기](/contributing/adding-developer-tools/) – 관련 페이지에 개발자 도구를 추가하세요 +- [레이어 2 추가하기](/contributing/adding-layer-2s/) – 관련 페이지에 레이어 2를 추가하세요 +- [스테이킹 제품 또는 서비스 추가하기](/contributing/adding-staking-products/) – 단독 스테이킹, 풀링 스테이킹 또는 서비스형 스테이킹을 용이하게 하는 프로젝트를 추가하세요 +- [지갑 추가하기](/contributing/adding-wallets/) – [지갑 찾기 페이지](/wallets/find-wallet/)에 지갑을 추가하세요 +- [DeSci 페이지에 프로젝트 제안하기](/contributing/adding-desci-projects/) – 이더리움에 구축된 탈중앙화 과학에 기여하는 프로젝트를 추가하세요 + +질문이 있으신가요? 🤔 저희 [Discord 서버](https://discord.gg/ethereum-org)에 참여하세요 + +## 기여를 시작하기에 좋은 첫 작업 + +다음은 여러분이 해결을 돕고 담당할 수 있는 몇 가지 현재 작업입니다. 웹사이트에 대한 대부분의 변경 사항은 GitHub를 통해 이루어지므로 대부분의 경우 GitHub 계정이 필요합니다. + + + +모든 작업 보기 + +## ethereum.org 작업 방법 {#how-to-update-content} + +[번역 프로그램](/contributing/translation-program/)에 기여하려면 [Crowdin](https://crowdin.com/project/ethereum-org)에 계정을 만드셔야 합니다. 그 외 모든 작업(웹사이트에 콘텐츠 또는 시각 자료 추가/편집, 버그 수정, 미해결 작업 수행 등)에는 [GitHub](https://github.com/) 계정이 필요합니다. + +모든 업데이트는 GitHub PR 절차를 통해 제작됩니다. 즉, 여러분은 본인의 기기에 웹사이트를 복제하고, 복제된 웹사이트를 수정하고, 수정한 웹사이트와 원본 웹사이트와의 융합을 요청할 수 있습니다. 이전에 해본 적이 없다면 저희 [GitHub 리포지토리](https://github.com/ethereum/ethereum-org-website) 하단의 지침을 따르세요. + +어떤 작업을 하더라도 권한이나 허락이 필요하지는 않지만, 이더리움에서 여러분의 계획을 알 수 있도록 하는 것이 가장 좋습니다. 다음 방법을 통해 본인의 계획을 알릴 수 있습니다 + +- [GitHub](https://github.com/ethereum/ethereum-org-website)에서 이슈 또는 PR에 댓글 달기 +- [Discord 서버](https://discord.gg/ethereum-org)에서 메시지 보내기 + +기여를 시작하기 전에 다음에 대해 친숙한 지 확인하세요. + +- 진화하는 [ethereum.org의 비전](/about/) +- 저희의 [디자인 원칙](/contributing/design-principles/) +- 저희의 [스타일 가이드](/contributing/style-guide/) +- 저희의 [행동 강령](/community/code-of-conduct) + +## 사이트 관련 의사 결정 방식 {#how-decisions-about-the-site-are-made} + +개별 PR, 디자인 발전 및 주요 업그레이드에 대한 결정은 이더리움 생태계 전반의 팀이 내립니다. 이 팀에는 프로젝트 관리자, 개발자, 디자이너, 마케팅 및 커뮤니케이션 담당자, 주제 전문가가 포함됩니다. 커뮤니티의 의견은 모든 결정에 반영됩니다. 이슈에 질문을 올리거나 PR을 제출하거나 팀에 문의하세요: + +- [website@ethereum.org](mailto:website@ethereum.org) +- [@ethdotorg](https://twitter.com/ethdotorg) +- [Discord 서버](https://discord.gg/ethereum-org) + +### 표절에 대한 참고 사항 {#plagiarism} + +ethereum.org에 콘텐츠나 결과물을 기여할 때는 본인의 독창적인 저작물 또는 사용 허가를 받은 콘텐츠만 사용하세요. 이더리움 생태계 내의 많은 프로젝트는 정보의 자유로운 공유를 허용하는 오픈 소스 라이선스를 사용합니다. 하지만 이 정보를 찾을 수 없다면 ethereum.org에 추가하려고 시도하지 마세요. 표절로 간주되는 모든 pull request는 거부됩니다. + +## 오픈 소스가 처음이신가요? {#new-to-open-source} + +저희 GitHub 리포지토리에는 오픈 소스를 처음 접하는 개발자를 위해 특별히 고안된 [good first issue](https://github.com/ethereum/ethereum-org-website/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) 라벨이 붙은 진입 장벽이 낮은 이슈들이 있습니다. + +## 온체인 참여 증명 토큰(OAT) 수령하기 {#oat} + +여러분의 기여가 ethereum.org에 병합되면 [Galxe](https://app.galxe.com/quest/ethereumorg)에서 특별 배지를 받을 수 있는 기회가 주어집니다. 온체인 참여 증명 토큰(OAT)은 여러분이 생태계를 조금 더 멋지게 만드는 데 도움을 주었다는 증표입니다. + +[OAT에 대한 추가 정보](https://help.galxe.com/en/articles/9645630-create-quest-rewards#h_1c5d63ba03) + +### 수령 방법 + +1. 저희 [Discord 서버](https://discord.gg/ethereum-org)에 참여하세요. +2. 기여에 대한 링크를 `#🥇 | proof-of-contribution` 채널에 붙여넣으세요. +3. 저희 팀원이 OAT 링크를 보내줄 때까지 기다리세요. +4. OAT를 수령하세요! + +OAT를 수령하려면 개인 보관 지갑만 사용해야 합니다. 거래소 계정이나 개인 키를 보유하고 있지 않은 다른 계정은 OAT에 접근하고 관리할 수 없으므로 사용하지 마세요. + +## GitPOAP 수령하기 {#claim-gitpoap} + +GitPOAP은 병합된 기여를 자동으로 인식하여 해당 플랫폼에서 직접 고유한 기여자 POAP를 별도로 발행할 수 있도록 합니다! + +### 수령 방법 {#how-to-claim} + +1. [GitPOAP](https://www.gitpoap.io)을 방문하세요. +2. 로그인 옵션을 통해 지갑 또는 이메일로 연결하세요. +3. GitHub 사용자 이름, ETH 주소, ENS 이름 또는 GitPOAP을 검색하여 자격 여부를 확인하세요. +4. GitHub 계정이 자격 요건을 충족하면 GitPOAP을 발행할 수 있습니다! + +## 기여자 {#contributors} + + diff --git a/public/content/translations/ko/contributing/quizzes/index.md b/public/content/translations/ko/contributing/quizzes/index.md new file mode 100644 index 00000000000..2702b239f5b --- /dev/null +++ b/public/content/translations/ko/contributing/quizzes/index.md @@ -0,0 +1,62 @@ +--- +title: "퀴즈 추가하기" +description: "ethereum.org에 퀴즈를 추가할 때 사용하는 정책" +lang: ko +--- + +# 퀴즈 {#quizzes} + +퀴즈는 방금 읽은 페이지의 내용을 제대로 이해했는지 사용자에게 스스로 확인할 수 있는 기회를 제공합니다. 퀴즈에서 물어보는 질문들은 페이지에서 제공된 내용만을 바탕으로 해야 하며, 페이지에서 언급되지 않은 정보에 대하여 질문해서는 안됩니다. + +질문들은 다음과 같이 구성됩니다. 질문 프롬프트, 정답 1 개와 정답인 이유에 관한 설명, 오답 3 개와 오답인 이유에 관한 설명. + +현재 퀴즈의 몇 가지 예시들은 이곳에서 찾을 수 있습니다: + +- [레이어 2](/layer-2) +- [NFT](/nft/) +- [이더리움이란 무엇인가요?](/what-is-ethereum/) +- [ETH란 무엇인가요?](/what-is-ether/) + +## 학습 퀴즈 추가하기 + +아직 학습 퀴즈가 생성되지 않은 페이지가 있는 경우, 해당 페이지에 대한 [이슈를 개설](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=&template=suggest_quiz.yaml)해 주세요. + +다음의 정보를 제공해 주세요: + +- 퀴즈를 추가하고자 하는 페이지 +- 다음의 정보를 포함한 5개의 질문: + - 질문이 위치한 페이지의 해당 섹션 + - 질문 프롬프트 + - 1 개의 정답과 정답인 이유에 관한 설명 + - 3 개의 오답과 오답인 이유에 관한 설명 + +## 퀴즈 질문 추가하기 + +퀴즈의 문제 은행에 추가하고 싶은 질문이 있는 경우, [이슈를 개설](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=&template=suggest_quiz.yaml)하고 다음 정보를 제공해 주세요: + +- 퀴즈용 질문을 추가하고자 하는 페이지 +- 각각의 질문은 다음의 정보를 제공합니다: + - 질문이 위치한 페이지의 해당 섹션 + - 질문 프롬프트 + - 1 개의 정답과 정답인 이유에 관한 설명 + - 3 개의 오답과 오답인 이유에 관한 설명 + +## 퀴즈 질문 업데이트하기 + +퀴즈의 문제 은행에 있는 질문을 업데이트하고 싶은 경우, [이슈를 개설](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=&template=suggest_quiz.yaml)하고 다음 정보를 제공해 주세요: + +- 퀴즈용 질문을 업데이트하고자 하는 페이지 +- 각각의 질문이 업데이트될 수 있도록 다음의 정보를 제공해 주세요: + - 질문이 위치한 페이지의 해당 섹션 + - 업데이트하고자 하는 질문의 프롬프트 + - 업데이트한 질문 프롬프트 + - 1 개의 정답과 정답인 이유에 관한 설명 + - 3 개의 오답과 오답인 이유에 관한 설명 + +## 퀴즈 질문 제거하기 + +질문에 해당하는 내용이 페이지에 더 이상 존재하지 않아 질문을 제거해야 하는 경우, 질문을 제거하기 위해 [이슈를 개설](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=&template=suggest_quiz.yaml)하고 다음 정보를 제공해 주세요: + +- 퀴즈용 질문을 삭제하고자 하는 페이지 +- 삭제하고자 하는 질문 +- 만약 필요하다면 왜 해당 질문이 제거되어야 하는지에 관한 설명 diff --git a/public/content/translations/ko/contributing/translation-program/faq/index.md b/public/content/translations/ko/contributing/translation-program/faq/index.md new file mode 100644 index 00000000000..244c865b98d --- /dev/null +++ b/public/content/translations/ko/contributing/translation-program/faq/index.md @@ -0,0 +1,119 @@ +--- +title: "번역 프로그램 자주 묻는 질문 (FAQ)" +lang: ko +description: "Ethereum.org 번역 프로그램에 대한 자주 묻는 질문" +--- + +# ethereum.org 번역 가이드 {#translating-ethereum-guide} + +번역 프로그램을 처음 접하신 분이고 참여를 망설이는 분은 여기에 있는 FAQ가 도움이 될 것입니다. 이 가이드를 사용하여 가장 일반적인 요청에 대한 답변을 찾아보세요. + +## Ethereum.org 번역에 대한 보상을 받을 수 있나요? {#compensation} + +Ethereum.org은 오픈 소스 웹사이트로, 누구나 참여해서 기여할 수 있습니다. + +Ethereum.org 번역 프로그램은 그 연장선상에 있으며, 같은 이념으로 구성되어 있습니다. + +번역 프로그램의 목표는 사용하는 언어에 관계없이 모든 사람이 이더리움 콘텐츠에 접근할 수 있도록 하는 것입니다. 또한 이중 언어를 구사하는 사람이라면 누구나 이더리움 생태계에 참여하고 접근 가능한 방식으로 기여할 수 있습니다. + +이와 같은 이유로 번역 프로그램은 개방적이고 자발적이며 참여는 보상의 대상이 되지 않습니다. 번역가가 번역한 단어의 수에 대해 보상할 경우 번역 경험이 충분한 사람(전문 번역가)만 저희 번역 프로그램에 참여하도록 권유할 수 있습니다. 이로 인해 번역 프로그램이 배제되고, 특히 모든 사람이 생태계에 참여하고 참여할 수 있다는 개략적인 목표에 도달하지 못하게 됩니다. + +이더리움은 기여자들이 이더리움 생태계에서 성공할 수 있도록 최선을 다하고 있습니다. [POAP 제공](/contributing/translation-program/acknowledgements/#poap) 및 [번역가 인증서](/contributing/translation-program/acknowledgements/#certificate)와 같은 금전적 보상 외의 다양한 인센티브를 제공하고, [번역 리더보드](/contributing/translation-program/acknowledgements/)를 운영하며, [모든 번역가를 사이트에 등재](/contributing/translation-program/contributors/)합니다. + +## ``가 포함된 문자열은 어떻게 번역하나요? {#tags} + +모든 문자열이 순수하게 텍스트 형식으로 이루어져 있지 않습니다. 일부 문자열에는 HTML 태그(`<0>`, ``)와 같은 혼합 스크립트가 포함되어 있습니다. 이는 일반적으로 문장 중간의 하이퍼링크나 대체 스타일을 위한 것입니다. + +- 태그 자체는 번역하지 않고 태그 내부의 텍스트를 번역하세요. `<`와 `>` 안에 있는 내용은 번역하거나 제거하면 안 됩니다. +- 문자열을 안전하게 유지하려면 왼쪽 하단의 "원본 복사" 버튼을 클릭하는 것이 좋습니다. 그러면 원본 문자열이 복사되어 텍스트 상자에 붙여넣어집니다. 이를 통해 태그가 어디에 있는지 명확히 하고 실수를 피하는 데 도움이 됩니다. + +![원본 복사 버튼이 강조된 Crowdin 인터페이스](./html-tag-strings.png) + +사용하는 언어에 더 자연스럽도록 문자열 내에서 태그 위치를 이동할 수 있습니다. 단, 태그 전체를 이동해야 합니다. + +태그 및 코드 스니펫 처리에 대한 자세한 내용은 [ethereum.org 번역 스타일 가이드](/contributing/translation-program/translators-guide/#dealing-with-tags)를 참조하세요. + +## 문자열이 적용되는 곳이 어디인가요? {#strings} + +가끔씩 완전하지 않은 문자열이 있는 경우 정확한 번역을 제출하는 데 무리가 있을 것입니다. + +- 상세한 정보를 얻으려면 "스크린샷" 및 "문맥" 을 살펴보세요. 원본 문자열 섹션에서 첨부된 스크린샷 이미지를 볼 수 있으며, 이를 통해 컨텍스트에서 문자열을 어떻게 사용하고 있는지 알 수 있습니다. +- 그래도 확실하지 않다면, "댓글 섹션"에서 문제를 보고하세요. [댓글을 남기는 방법을 잘 모르시겠나요?](#comment) + +![스크린샷을 통해 문자열에 컨텍스트를 제공하는 방법을 보여주는 이미지](./source-string.png) + +![컨텍스트를 위해 추가된 예시 스크린샷](./source-string-2.png) + +## 댓글을 달거나 질문하는 방법은 무엇인가요? 문제 또는 철자 오류를 제보하고 싶습니다... {#comment} + +주의가 필요한 특정 문자열에 플래그를 지정하려면 자유롭게 댓글을 제출하세요. + +- 오른쪽 상단 바의 두 번째 버튼을 클릭하세요. 숨겨진 탭이 오른쪽에 나타납니다. 새 댓글을 남기고 하단의 "문제" 확인란을 클릭하세요. 드롭다운 메뉴에서 옵션 중 하나를 선택하여 문제 유형을 지정할 수 있습니다. +- 제출되면 저희 팀에 보고됩니다. 저희가 문제를 해결하고 댓글에 회신하고 문제를 종결하여 알려드리겠습니다. +- 잘못된 번역을 신고하면 다음 검토 중에 해당 번역과 제안된 대안을 원어민이 검토합니다. + +![댓글과 문제를 만드는 방법을 보여주는 이미지](./comment-issue.png) + +## 번역 메모리(TM)란 무엇인가요? {#translation-memory} + +번역 메모리(TM)는 이전에 ethereum.org 프로젝트에서 저장된 모든 번역된 문자열을 저장하는 Crowdin의 기능입니다. 문자열이 번역되면 자동으로 프로젝트 TM에 저장됩니다. 작업 시간을 단축하는 데 유용하게 사용할 수 있는 도구입니다! + +- "TM 및 MT 제안" 섹션을 보면 다른 번역가들이 동일하거나 유사한 문자열을 어떻게 번역했는지 확인할 수 있습니다. 일치율이 높은 제안을 찾으면 클릭하여 해당 번역을 자유롭게 참조하세요. +- 목록에 아무것도 없으면 TM에서 이전에 번역된 내용을 검색하고 일관성을 위해 재사용할 수 있습니다. + +![번역 메모리 스크린샷](./translation-memory.png) + +## Crowdin 용어집은 어떻게 사용하나요? {#glossary} + +이더리움 용어는 새로운 기술 용어가 아직 많은 언어로 현지화되지 않은 경우가 많기 때문에 번역 작업에서 또 다른 중요한 부분입니다. 또한 다른 컨텍스트에서는 다른 의미를 갖는 용어도 있습니다. [이더리움 용어 번역에 대해 더 알아보기](#terminology) + +Crowdin 용어집은 용어 및 정의를 명확히 하는 데 가장 좋은 곳입니다. 용어집을 참조하는 방법에는 두 가지가 있습니다. + +- 첫째, 원본 문자열에서 밑줄이 그어진 용어를 찾으면 마우스를 올려 간략한 정의를 볼 수 있습니다. + +![용어집 정의 예시](./glossary-definition.png) + +- 둘째, 익숙하지는 않지만 밑줄이 없는 용어를 발견하면 용어집 탭(오른쪽 열의 세 번째 버튼)에서 검색할 수 있습니다. 프로젝트에서 자주 사용되는 특정 용어 및 용어에 대한 설명을 찾을 수 있습니다. + +![Crowdin에서 용어집 탭을 찾을 수 있는 위치를 보여주는 스크린샷](./glossary-tab.png) + +- 그래도 찾을 수 없다면 새로운 용어를 추가할 기회입니다! 검색 엔진에서 찾아보고 용어집에 설명을 추가하는 것을 권장합니다. 이는 다른 번역가들이 용어를 더 잘 이해하는 데 큰 도움이 될 것입니다. + +![Crowdin에 용어집 용어를 추가하는 방법을 보여주는 스크린샷](./add-glossary-term.png) + +### 용어 번역 정책 {#terminology} + +_이름(브랜드, 회사, 사람) 및 새로운 기술 용어(비콘 체인, 샤드 체인 등)의 경우_ + +이더리움에는 최근에 만들어진 새로운 용어가 많이 있습니다. 일부 용어는 해당 언어로 공식 번역이 없기 때문에 번역가에 따라 다를 수 있습니다. 일관성이 없으면 번역문을 잘못 이해하거나 가독성을 떨어뜨릴 수도 있습니다. + +언어적 다양성과 각 언어의 다양한 표준화로 인해 모든 지원 언어에 적용할 수 있는 통일된 용어 번역 정책을 마련하는 것이 거의 불가능했습니다. + +신중한 고려 끝에 가장 자주 사용되는 용어는 번역가 여러분에게 맡기기로 결정했습니다. + +친숙하지 않은 용어를 찾은 경우 다음과 같이 해 볼 것을 제안합니다. + +- [용어집](#glossary)을 참조하면 이전에 다른 번역가들이 어떻게 번역했는지 알 수 있습니다. 이전에 번역된 용어가 적절하지 않다고 생각되면, Crowdin 용어집에 새 용어를 추가하여 자신의 번역을 적용하세요. +- 그러한 이전 번역이 용어집에 없는 경우, 검색 엔진이나 미디어 기사에서 해당 용어가 커뮤니티에서 실제로 어떻게 사용되는지 찾아보기를 권장합니다. +- 참고 자료를 전혀 찾을 수 없는 경우, 직감을 믿고 자신의 언어로 새로운 번역을 자유롭게 제안하세요! +- 그렇게 할 자신이 없다면 용어를 번역하지 않은 채로 두세요. 때로는 영어 용어가 정확한 정의를 전달하는 데 더 적합할 수 있습니다. + +브랜드, 회사 및 인명의 이름은 번역하면 불필요한 혼란과 SEO 문제를 야기할 수 있으므로 번역하지 않은 채로 두는 것이 좋습니다. + +## 검토 절차는 어떻게 진행되나요? {#review-process} + +번역의 특정 수준의 품질과 일관성을 보장하기 위해, 우리는 세계 최대의 언어 서비스 제공업체 중 하나인 [Acolad](https://www.acolad.com/)와 협력합니다. Acolad에는 20,000명의 전문 번역가가 있으며 각 언어와 필요한 각 콘텐츠의 종류마다 전문 검토자를 제공할 수 있습니다. + +검토 과정은 간단합니다. 콘텐츠 세트가 100% 번역되면 해당 콘텐츠 버킷에 대한 검토를 요청합니다. 검토 절차는 Crowdin에서 직접 이루어집니다. 검토 절차가 완료되면 번역된 콘텐츠를 웹사이트에 업데이트 합니다. + +## 제 언어에 콘텐츠를 어떻게 추가하나요? {#adding-foreign-language-content} + +현재 모든 비영어권 콘텐츠는 영어 원본 콘텐츠에서 직접 번역되며, 영어로 존재하지 않는 콘텐츠는 다른 언어로 추가할 수 없습니다. + +ethereum.org에 대한 새로운 콘텐츠를 제안하려면 GitHub에서 [이슈를 생성](https://github.com/ethereum/ethereum-org-website/issues)할 수 있습니다. 추가되면 해당 콘텐츠는 영어로 작성되고 Crowdin을 사용하여 다른 언어로 번역됩니다. + +가까운 시일 내에 비영어권 콘텐츠 추가 지원을 추가할 계획입니다. + +## 문의하기 {#contact} + +긴 글 읽어 주셔서 감사합니다. 이 글이 프로그램에 참여하는 데 도움이 되었으면 좋겠습니다. [Discord 번역 채널](https://discord.gg/ethereum-org)에 자유롭게 참여하여 질문하고 다른 번역가들과 협업하거나 translations@ethereum.org로 문의해 주세요! diff --git a/public/content/translations/ko/contributing/translation-program/how-to-translate/index.md b/public/content/translations/ko/contributing/translation-program/how-to-translate/index.md new file mode 100644 index 00000000000..fc39e1fe67a --- /dev/null +++ b/public/content/translations/ko/contributing/translation-program/how-to-translate/index.md @@ -0,0 +1,92 @@ +--- +title: "번역하는 방법" +lang: ko +description: "Crowdin을 통해 ethereum.org를 번역하는 방법" +--- + +# 번역하는 방법 {#how-to-translate} + +## 시각적 가이드 {#visual-guide} + +더 많은 시각 학습자를 위해 Luka가 Crowdin을 설정하는 과정을 살펴보세요. 또는 다음 섹션에서 동일한 단계를 문서로된 형식으로 찾을 수도 있습니다. + + + +## 글로 된 가이드 {#written-guide} + +### Crowdin에서 프로젝트에 참여하세요 {#join-project} + +Crowdin에 로그인을 해야 하거나 만약 계정이 없다면 등록해야 합니다. 가입에 필요한 것은 이메일 계정과 비밀번호 뿐입니다. + + + 프로젝트 참여하기 + + +### 사용 언어 열기 {#open-language} + +Crowdin에 로그인한 뒤, 프로젝트 설명과 모든 이용 가능한 언어의 목록을 보게 될 것입니다. +각 언어는 또한 번역 가능한 단어들의 전체량 정보 및, 특정 언어로 된 콘텐츠가 얼마나 많이 번역되었고 승인되었는지에 대한 정보를 포함합니다. + +번역이 가능한 파일의 목록을 보기 위해서, 번역하고 싶은 언어를 열어주세요 + +![Crowdin의 언어 목록](./list-of-languages.png) + +### 작업할 문서 찾기 {#find-document} + +웹사이트의 콘텐츠는 여러 문서와 콘텐츠 묶음으로 나뉘어 구성됩니다. 오른쪽에서 각 문서의 진행 상황을 확인할 수 있습니다 - 번역 진행률이 100% 미만인 경우 기여해 주세요. + +자신의 언어를 찾을 수 없으신가요? [이슈를 개설](https://github.com/ethereum/ethereum-org-website/issues/new/choose)하거나 저희 [Discord](https://discord.gg/ethereum-org)에서 질문해 주세요. + +![Crowdin에서 번역된 파일과 번역되지 않은 파일](./crowdin-files.png) + +콘텐츠 버킷에 대한 참고 사항: Crowdin 내에서 '콘텐츠 버킷'을 사용하여 우선 순위가 가장 높은 콘텐츠를 먼저 출시합니다. 예를 들어, [필리핀어](https://crowdin.com/project/ethereum-org/fil#)와 같은 언어를 확인하면 콘텐츠 버킷("1.) 폴더가 표시됩니다. Homepage', '2. 필수", "3. 찾아보기", 등.). + +가장 영향력 있는 페이지가 먼저 번역되도록 이 숫자 순서(1 → 2 → 3 → ⋯)로 번역하는 것을 권장합니다. + +### 번역하기 {#translate} + +번역하고 싶은 파일을 선택하면, 온라인 편집기에서 파일이 열릴 것입니다. 한번도 Crowdin을 사용해본 적이 없다면 빠른 가이드를 사용하여 기본 사항을 살펴볼 수 있습니다. + +![Crowdin 온라인 편집기](./online-editor.png) + +**_1 – 좌측 사이드바_** + +- 번역 안됨 (빨간색) - 아직 번역이 되지 않은 텍스트입니다. 번역이 안된 문자열들은 번역을 해야합니다. +- 번역됨 (녹색) – 이미 번역된 텍스트이지만, 아직 검토되지는 않았습니다. 대체 번역을 제안하거나 에디터에서 '+' 및 '-' 버튼을 사용하여 기존 번역을 투표할 수 있습니다. +- 승인됨 (체크 표시) – 이미 검토되고 현재 사이트에 적용된 텍스트입니다. + +상단에 있는 버튼을 사용하여 특정 문자열을 검색하거나, 상태별로 필터링하거나, 보기를 변경할 수도 있습니다. + +**_2 – 에디터 영역_** + +주 번역 공간 – 원문이 상단에 표시되며, 추가 문맥 및 스크린샷이 있는 경우 상단에 표시됩니다. +새로운 번역문을 제안하려면, "여기에 번역문 입력" 입력란에 번역문을 작성한 후 저장을 누르세요. + +이 섹션에서 이미 제안된 번역문, 다른 언어로 된 번역문 및 번역 메모리 및 기계 번역 제안까지 확인할 수 있습니다. + +**_3 – 우측 사이드바_** + +여기에서 댓글, 번역 메모리 및 용어집을 찾아볼 수 있습니다. 기본 보기에서는 주석이 표시되고 번역가가 소통하고, 이슈를 제기하거나 정확하지 않은 번역을 보고할 수 있습니다. + +위에 있는 버튼을 사용해, 번역 메모리로 전환할 수도 있습니다. 이곳에서는 기존의 번역문을 검색할 수 있으며, 용어집에는 주요 용어의 설명과 표준 번역이 포함되어 있습니다. + +더 알아보시나요? [Crowdin 온라인 편집기 사용 문서](https://support.crowdin.com/online-editor/)를 자유롭게 확인하세요. + +### 검토 과정 {#review-process} + +번역을 완료하면(즉, 콘텐츠 버킷의 모든 파일이 100%로 표시되면) 저희 전문 번역 서비스에서 콘텐츠를 검토(하고 잠재적으로 편집)합니다. 검토가 완료되면(즉, 검토 진행률이 100%가 되면) 해당 콘텐츠를 웹사이트에 추가합니다. + + + + + 번역기를 사용하여 프로젝트를 번역하지 말아 주세요. 모든 번역문들은 검토 후 웹사이트에 추가됩니다. 만약 제안한 번역문들이 번역기인 것으로 판명되면 해당 번역은 기각되고 번역기를 자주 사용하는 기여자는 프로젝트에서 제외됩니다. + + + +### 문의하기 {#get-in-touch} + +궁금한 점이 있으신가요? 또는 저희의 팀과 다른 번역가들과 협업하고 싶으신가요? [ethereum.org Discord 서버](https://discord.gg/ethereum-org)의 #translations 채널에 게시해 주세요. + +또한 translations@ethereum.org 를 통하여 연락할 수 있습니다. + +Ethereum.org 번역 프로그램에 참여해 주셔서 감사합니다! diff --git a/public/content/translations/ko/contributing/translation-program/index.md b/public/content/translations/ko/contributing/translation-program/index.md new file mode 100644 index 00000000000..e7d95212916 --- /dev/null +++ b/public/content/translations/ko/contributing/translation-program/index.md @@ -0,0 +1,91 @@ +--- +title: "번역 프로그램" +lang: ko +description: "ethereum.org 번역 프로그램에 대한 정보" +--- + +# 번역 프로그램 {#translation-program} + +번역 프로그램은 ethereum.org을 다른 언어로 번역하여 전 세계 수십억 명의 비영어권 사용자가 웹사이트를 더 쉽게 이용할 수 있도록 하기 위한 공동 노력입니다. + +![](./enterprise-eth.png) + +## 번역에 참여하기 {#help-us-translate} + +ethereum.org 번역 프로그램은 누구나 참여할 수 있는 공개 프로그램입니다! + +1. Crowdin 계정에 로그인하거나 가입해야 합니다. +2. 참여하고 싶은 언어를 선택하세요. +3. 시작하기 전에 [번역 방법](/contributing/translation-program/how-to-translate/) 가이드를 통해 Crowdin 사용법을 숙지하고, [번역 스타일 가이드](/contributing/translation-program/translators-guide/)에서 팁과 모범 사례를 확인하시기 바랍니다. +4. 기계 번역은 승인되지 않습니다. +5. 모든 번역은 사이트에 추가되기 전에 검토를 거치므로, 번역이 게시되기까지 약간의 시간이 소요될 수 있습니다. + +_[ethereum.org Discord](https://discord.gg/ethereum-org)에 참여하여 번역에 협력하고, 질문을 하고, 피드백과 아이디어를 공유하거나, 번역 그룹에 참여하세요._ + + + 번역 시작하기 + + +## 번역 프로그램 정보 {#about-us} + +이더리움 커뮤니티는 글로벌하고 포괄적인 것을 목표로 하고 있지만, 그 콘텐츠의 대부분은 전세계 60억 명의 비영어권 사용자들을 제외하고 영어 사용자들에게만 전달됩니다. Ethereum.org이 전 세계 커뮤니티를 위한 이더리움으로 들어가는 포털 역할을 하기 위해서는 비영어권 사용자들에게 모국어로 이더리움 콘텐츠를 제공하는 것이 필수적이라고 믿습니다. + +Ethereum.org 번역 프로그램은 ethereum.org 및 기타 이더리움 콘텐츠를 가능한 한 많은 언어로 번역함으로써 모든 사람이 이더리움에 접근할 수 있도록 하는 것을 목표로 합니다. + +ethereum.org 번역 프로그램의 [사명과 비전](/contributing/translation-program/mission-and-vision)에 대해 더 자세히 알아보세요. + +### 현재까지의 진행 상황 {#our-progress} + +- [**6,900 +** 명의 번역가](/contributing/translation-program/contributors/) +- 사이트에서 68개 언어 지원 +- [2024년 **289만** 단어 번역](/contributing/translation-program/acknowledgements/) + + + +### 감사의 말 {#acknowledgements} + +Ethereum.org는 수천 명의 커뮤니티 회원이 번역하고 있으며, 이들은 번역 프로그램의 핵심적인 부분입니다. +저희는 번역가들에게 감사를 표하고 그들의 커리어 개발을 지원하고자 합니다. 번역가에 대한 감사의 표현은 다음과 같습니다. + +#### 수료증 {#certificate} + +번역 프로그램에 기여했으며 번역한 단어 중 5,000개 이상이 승인된 경우, ethereum.org 번역가 수료증을 받을 자격이 주어집니다. [수료증에 대해 더 알아보기](/contributing/translation-program/acknowledgements/#certificate) + +#### OAT {#oats} + +번역 프로그램 기여자는 2024년에 번역한 단어 수에 따라 다양한 OAT(온체인 달성 토큰)를 받을 수 있습니다. OAT는 ethereum.org 번역 프로그램에 대한 기여를 증명하는 NFT입니다. [OAT에 대해 더 알아보기](/contributing/translation-program/acknowledgements/#oats) + +#### 번역가에 대한 감사의 글 {#translator-acknowledgements} + +[순위표](/contributing/translation-program/acknowledgements/)와 [번역 프로그램의 모든 기여자 목록](/contributing/translation-program/contributors/)을 사용하여 우수 번역가를 공개적으로 기립니다. + +#### 보상 {#rewards} + +과거에 저희는 가장 활동적인 기여자들에게 [Devcon](https://devcon.org/en/) 및 [Devconnect](https://devconnect.org/)와 같은 이더리움 컨퍼런스 티켓과 특별한 ethereum.org 상품을 소급하여 보상으로 제공했습니다. + +저희는 기여자들에게 보상할 새롭고 혁신적인 방법을 끊임없이 모색하고 있으니, 계속 지켜봐 주세요! + +### 가이드 및 참고 자료 {#guides-and-resources} + +번역 프로그램에 기여하고 있거나 참여를 고려하고 있다면, 아래의 번역 가이드를 확인해 보세요. + +- [번역 스타일 가이드](/contributing/translation-program/translators-guide/) _– ethereum.org 번역가를 위한 지침 및 팁_ +- [번역 FAQ](/contributing/translation-program/faq/) _– ethereum.org 번역 프로그램에 대한 자주 묻는 질문과 답변_ +- [Crowdin 온라인 편집기 가이드](https://support.crowdin.com/online-editor/) _– Crowdin 온라인 편집기 사용법과 일부 고급 기능에 대한 심층 가이드_ + +기타 유용한 번역 도구, 번역가 커뮤니티 및 번역 프로그램 블로그 게시물은 [참고 자료 페이지](/contributing/translation-program/resources/)를 방문해 주세요. + +## 문의하기 {#get-in-touch} + +궁금한 점이 있으신가요? 또는 저희의 팀과 다른 번역가들과 협업하고 싶으신가요? [ethereum.org Discord 서버](https://discord.gg/ethereum-org)의 #translations 채널에 게시해 주세요. + +또한 translations@ethereum.org 를 통하여 연락할 수 있습니다. + +## 자체 번역 프로그램 시작하기 {#starting-a-translation-program} + +저희는 이더리움 콘텐츠를 가능한 한 많은 언어로 번역하고 모든 사람이 교육 콘텐츠를 이용할 수 있도록 최선을 다하고 있습니다. +번역에 중점을 두는 것과 더불어, 저희는 다른 이더리움 프로젝트가 자체 번역 활동을 조직, 관리 및 개선하는 데 도움을 주고자 합니다. + +이러한 이유로 저희는 ethereum.org를 번역하는 과정에서 얻은 몇 가지 팁과 모범 사례가 담긴 [번역 프로그램 플레이북](/contributing/translation-program/playbook/)을 만들었습니다. + +더 협력하고 싶거나 저희 번역 참고 자료를 사용하고 싶으신가요? 플레이북에 대한 피드백이 있으신가요? translations@ethereum.org로 의견을 보내주시면 감사하겠습니다. diff --git a/public/content/translations/ko/contributing/translation-program/mission-and-vision/index.md b/public/content/translations/ko/contributing/translation-program/mission-and-vision/index.md new file mode 100644 index 00000000000..abd31d7aa83 --- /dev/null +++ b/public/content/translations/ko/contributing/translation-program/mission-and-vision/index.md @@ -0,0 +1,25 @@ +--- +title: "목표와 비전" +lang: ko +description: "Ethereum.org 번역 프로그램의 미션과 비전" +--- + +# 미션과 비전 {#mission-and-vision} + +이더리움 커뮤니티는 글로벌하고 포괄적인 것을 목표로 하고 있지만, 그 콘텐츠의 대부분은 전세계 60억 명의 비영어권 사용자들을 제외하고 영어 사용자들에게만 전달됩니다. Ethereum.org이 전 세계 커뮤니티를 위한 이더리움으로 들어가는 포털 역할을 하기 위해서는 비영어권 사용자들에게 모국어로 이더리움 콘텐츠를 제공하는 것이 필수적이라고 믿습니다. + +Ethereum.org 번역 프로그램은 ethereum.org 및 기타 이더리움 콘텐츠를 가능한 한 많은 언어로 번역함으로써 모든 사람이 이더리움에 접근할 수 있도록 하는 것을 목표로 합니다. + +## 우리의 임무 {#our-mission} + +- 번역된 버전의 웹사이트를 제공하여 전 세계 방문자가 자신의 모국어로 이더리움에 대해 배울 수 있도록 하기 +- 글로벌 이더리움 커뮤니티에 더 많은 회원이 합류할 수 있도록 지원하기 +- 이더리움 정보 및 지식의 더 접근 가능하고 포괄적인 공유를 허용하기 +- 커뮤니티 구성원이 이더리움 번역에 기여하고 생태계에 이름을 남길 수 있도록 지원하기 +- 생태계에 참여하고자 하는 열정적인 기여자를 확인하고, 연결하고, 지침을 제공하기 + +## 우리의 비전 {#our-vision} + +- 가능한 한 많은 국가 및 세계의 일부에서 온 이더리움 커뮤니티 구성원을 위한 필수 콘텐츠를 번역하기 +- 더 나은 정보와 교육을 받은 이더리움 커뮤니티를 만들기 위해 언어 간 지식 공유 지원하기 +- 비영어권 사용자가 생태계에 합류하지 못하도록 하는 언어의 장벽을 무너트려 이더리움의 포괄성과 접근성을 높이기 diff --git a/public/content/translations/ko/contributing/translation-program/playbook/index.md b/public/content/translations/ko/contributing/translation-program/playbook/index.md new file mode 100644 index 00000000000..0992cf37508 --- /dev/null +++ b/public/content/translations/ko/contributing/translation-program/playbook/index.md @@ -0,0 +1,317 @@ +--- +title: "번역 프로그램 플레이북-가이드북-" +lang: ko +description: "번역 프로그램을 설정하기 위한 팁과 중요한 고려 사항 모음" +--- + +# 번역 프로그램 플레이북 {#translation-program-playbook} + +영어는 세계에서 가장 많이 사용되는 언어 중 하나이며, 단연코 세계에서 가장 많이 연구되는 언어입니다. 인터넷, 특히 소셜 미디어에서 영어가 가장 보편적으로 사용되는 언어이고 다국어 프로그래밍 언어는 드물기 때문에, 블록체인 분야의 대부분 콘텐츠는 기본적으로 영어로 작성됩니다. + +하지만 전 세계 60억 명 이상(인구의 75% 이상)이 영어를 전혀 사용하지 못하기 때문에 이는 세계 인구 대다수에게 이더리움에 대한 진입 장벽이 되고 있습니다. + +이러한 이유로, 이 분야에서 점점 더 많은 프로젝트가 콘텐츠를 여러 언어로 번역하고 글로벌 커뮤니티를 위해 현지화하려고 합니다. + +다국어 콘텐츠를 제공하는 것은 글로벌 커뮤니티를 성장시키고, 비영어권 사용자에게 교육을 제공하며, 콘텐츠와 커뮤니케이션이 더 넓은 잠재 고객에게 도달하도록 하고, 더 많은 사람을 이 분야로 온보딩하는 간단하고 효과적인 방법입니다. + +이 가이드는 콘텐츠 현지화에 대한 일반적인 과제와 오해를 다루는 것을 목표로 합니다. 콘텐츠 관리, 번역 및 검토 과정, 품질 보증, 번역가 확보 및 기타 현지화 과정의 중요한 측면에 대한 단계별 가이드를 제공합니다. + +## 콘텐츠 관리 {#content-management} + +번역 콘텐츠 관리는 번역 워크플로를 자동화하는 과정으로, 반복적인 수작업의 필요성을 없애고, 효율성과 품질을 향상시키며, 더 나은 제어를 가능하게 하고, 협업을 용이하게 합니다. + +현지화 과정에서 콘텐츠 관리에 대한 접근 방식은 콘텐츠와 필요에 따라 다양합니다. + +콘텐츠를 관리하는 기본적인 방법은 원문과 번역문을 포함하는 이중 언어 파일을 만드는 것입니다. 이 방법은 단순하다는 점 외에는 별다른 이점이 없기 때문에 번역에서 거의 사용되지 않습니다. + +번역 에이전시는 일반적으로 프로젝트 관리 기능을 제공하고 파일, 콘텐츠, 언어 전문가에 대한 훨씬 더 큰 제어를 가능하게 하는 번역 관리 소프트웨어나 현지화 도구를 사용하여 번역 관리에 접근합니다. + +콘텐츠 관리에 대해 더 알아보기: + +[번역 관리란 무엇인가에 대한 Trados의 설명](https://www.trados.com/solutions/translation-management/) + +[다국어 콘텐츠 관리에 대한 Phrase의 설명](https://phrase.com/blog/posts/multilingual-content-management/) + +### 번역 관리 소프트웨어 {#translation-management-software} + +많은 번역 관리 시스템과 현지화 도구가 있으며, 소프트웨어의 선택은 주로 사용자의 필요에 따라 달라집니다. + +일부 프로젝트에서는 번역 관리 시스템을 사용하지 않고 이중 언어 파일에서 직접 또는 GitHub와 같은 호스팅 서비스에서 수동으로 번역을 처리하는 것을 선호하지만, 이는 제어, 생산성, 품질, 확장성 및 협업 기능을 크게 감소시킵니다. 이러한 접근 방식은 소규모 또는 일회성 번역 프로젝트에 가장 유익할 수 있습니다. + +가장 강력하고 널리 사용되는 번역 관리 도구 몇 가지를 간략히 살펴보겠습니다. + +**크라우드소싱 및 협업에 최적** + +[Crowdin](https://crowdin.com/) + +- 오픈 소스 프로젝트에 무료(문자열 및 프로젝트 수 무제한) +- 모든 플랜에서 TM 및 용어집 사용 가능 +- 60개 이상의 지원 파일 형식, 70개 이상의 API 통합 + +[Lokalise](https://lokalise.com/) + +- 팀원 2명까지 무료, 더 많은 기여자를 위한 유료 플랜(대부분의 플랜에서 문자열 수 제한) +- 일부 유료 플랜에서 TM 및 용어집 사용 가능 +- 30개 이상의 지원 파일 형식, 40개 이상의 API 통합 + +[Transifex](https://www.transifex.com/) + +- 유료 플랜만 제공(대부분의 플랜에서 문자열 수 제한) +- 모든 유료 플랜에서 TM 및 용어집 사용 가능 +- 30개 이상의 지원 파일 형식, 20개 이상의 API 통합 + +[Phrase](https://phrase.com/) + +- 유료 플랜만 제공(모든 플랜에서 문자열 수 무제한, 프로젝트 및 팀원 수 제한) +- 일부 유료 플랜에서 TM 및 용어집 사용 가능 +- 40개 이상의 지원 파일 형식, 20개 이상의 API 통합 + +[Smartcat](https://www.smartcat.com/) + +- 유료 고급 기능이 있는 기본 무료 플랜(모든 플랜에서 문자열 및 프로젝트 수 무제한) +- 모든 플랜에서 TM 및 용어집 사용 가능 +- 60개 이상의 지원 파일 형식, 20개 이상의 API 통합 + +[POEditor](https://poeditor.com/) + +- 오픈 소스 프로젝트에 무료(모든 프로젝트에서 문자열 수 제한, 오픈 소스 프로젝트는 무제한) +- 유료 플랜에서 TM 및 용어집 사용 가능 +- 20개 이상의 지원 파일 형식, 10개 이상의 API 통합 + +그리고 기타 다수... + +**전문 번역 도구** + +[SDL Trados Studio](https://www.trados.com/products/trados-studio/) + +- 프리랜서 번역가 및 팀을 위한 유료 플랜 +- 매우 강력한 컴퓨터 보조 번역(CAT) 도구 및 번역가 생산성 소프트웨어 + +[MemoQ](https://www.memoq.com/) + +- 제한된 무료 버전과 고급 기능을 위한 여러 유료 플랜 제공 +- 기업, 언어 서비스 제공업체 및 번역가를 위한 번역 관리 소프트웨어 + +[Memsource](https://www.memsource.com/) + +- 개인 번역가를 위한 무료 버전과 팀을 위한 여러 유료 플랜 제공 +- 클라우드 기반 컴퓨터 보조 번역 및 번역 관리 시스템 + +그리고 기타 다수... + +번역 관리 소프트웨어에 대해 더 알아보기: + +[번역 관리 시스템에 대한 위키피디아 정의](https://en.wikipedia.org/wiki/Translation_management_system) + +[모든 번역 관리 소프트웨어가 갖추어야 할 7가지에 대한 Phrase의 설명](https://phrase.com/blog/posts/7-things-every-translation-management-software-should-have/) + +[번역 관리 시스템이란 무엇인가에 대한 MemoQ의 설명](https://www.memoq.com/tools/what-is-a-translation-management-system) + +[Gengo의 16가지 최고의 번역 관리 시스템 목록](https://gengo.com/translator-product-updates/16-best-translation-management-systems/) + +## 워크플로 {#workflow} + +번역 분야에서 번역 워크플로는 몇 가지 다른 의미를 가질 수 있으며, 둘 다 서로 관련이 있고 프로젝트에 중요한 고려 사항입니다. + +아래에서 이 두 가지를 모두 살펴보겠습니다. + +**의미 1** + +이것은 아마도 번역 워크플로에 대해 생각하는 가장 일반적인 방법이며, 워크플로라는 단어를 들을 때 보통 떠오르는 것입니다. + +본질적으로, 이것은 번역에 대해 생각하기 시작하는 것부터 번역된 콘텐츠를 제품에 사용하는 것까지의 '작업의 흐름'입니다. + +이 경우의 예시 워크플로는 다음과 같습니다. + +1. **번역 파일 준비** – 간단하게 들리지만, 몇 가지 중요한 사항을 고려해야 합니다. 이 단계에서는 전체 프로세스가 어떻게 작동해야 하는지에 대한 명확한 계획이 있어야 합니다. + +- _어떤 파일 유형을 사용하실 건가요?_ _번역된 파일을 어떤 형식으로 받고 싶으신가요?_ + - 콘텐츠가 DOCX 또는 MD 형식으로 제공되는 경우, 백서나 다른 문서의 PDF 버전을 번역하는 것보다 접근 방식이 훨씬 간단합니다. +- _어떤 현지화 도구가 이 파일 유형을 지원하나요?_ _원본 서식을 유지하면서 파일을 번역할 수 있나요?_ + - 모든 파일 유형이 직접적인 현지화를 지원하는 것은 아니며(예: PDF 파일, 이미지 파일), 모든 현지화 도구가 모든 파일 유형을 지원하는 것도 아닙니다. +- _누가 콘텐츠를 번역할 것인가요?_ _전문 번역을 의뢰할 것인가요, 아니면 자원봉사자에게 의존할 것인가요?_ + - 이는 여러분이 내려야 할 다른 여러 결정에 영향을 미칩니다. 예를 들어, 전문 번역가는 자원봉사자보다 고급 현지화 도구를 사용하는 데 더 익숙합니다. +- _언어 전문가에 대한 기대는 무엇인가요?_ _언어 서비스 제공업체를 이용하는 경우, 그들은 여러분에게 무엇을 기대하나요?_ + - 이 단계는 목표, 기대치, 일정을 일치시키기 위한 단계입니다. +- _번역할 모든 콘텐츠가 똑같이 중요한가요?_ _일부 콘텐츠를 먼저 번역해야 하나요?_ + - 특정 콘텐츠를 우선순위로 정해 먼저 번역하고 구현하는 몇 가지 방법이 있습니다. 예를 들어, 번역할 콘텐츠가 많은 경우 버전 관리를 사용하여 번역가가 어떤 것을 우선순위로 두어야 하는지 알 수 있도록 할 수 있습니다. + +2. **번역 파일 공유** – 이 단계 역시 장기적인 사고가 필요하며, 언어 서비스 제공업체에 원본 파일을 보내는 것처럼 간단하지 않습니다. + +- _누가 콘텐츠를 번역할 것인가요?_ _이 과정에 몇 명이나 참여하게 될까요?_ + - 현지화 도구를 사용할 계획이라면, 소스 파일을 도구에 직접 업로드할 수 있으므로 이 단계가 단순화됩니다. 번역 과정이 호스팅 서비스에서 이루어지는 경우에도 소스 파일을 어디로든 내보낼 필요가 없으므로 마찬가지입니다. +- _소스 파일을 수동으로 처리할까요, 아니면 이 과정을 자동화할 수 있을까요?_ + - 대부분의 현지화 도구는 파일 관리 프로세스의 일부 유형의 통합 또는 자동화를 허용합니다. 반면에, 개별 번역가와 작업하고 현지화 도구를 사용하지 않는 경우, 수백 또는 수천 명의 번역가에게 수동으로 소스 파일을 보내는 것은 확장 가능한 프로세스가 아닙니다. +- _현지화에 어떤 도구를 사용할 것인가요?_ + - 이 질문에 대한 답이 다른 모든 것에 어떻게 접근할지를 결정합니다. 적절한 도구를 선택하면 콘텐츠 관리, 번역 메모리 및 용어집 관리, 번역가 관리, 번역/검토 진행 상황 추적 등을 자동화하는 데 도움이 될 수 있으므로, 시간을 내어 어떤 도구를 사용할지 조사해 보세요. 현지화 도구를 사용할 계획이 없다면 위의 모든 작업을 수동으로 해야 합니다. +- _번역 과정은 얼마나 걸릴까요?_ _비용은 얼마나 들까요?_ + - 이 시점에서 언어 서비스 제공업체나 번역가 풀과 소스 파일을 공유할 준비가 되어 있어야 합니다. 언어 서비스 제공업체는 단어 수를 분석하고 번역 과정의 요율과 일정을 포함한 견적을 제공하는 데 도움을 줄 수 있습니다. +- _이 과정 중에 소스 콘텐츠를 변경/업데이트할 계획이 있나요?_ + - 콘텐츠가 동적이고 자주 변경되는 경우, 모든 변경이나 업데이트는 번역 진행을 방해할 수 있습니다. 번역 메모리를 사용하면 이를 크게 완화할 수 있지만, 프로세스가 어떻게 작동할지, 그리고 번역가들이 이룬 진전을 후퇴시키지 않도록 하는 방법을 생각하는 것은 여전히 중요합니다. + +3. **번역 과정 관리** – 소스 콘텐츠를 언어 서비스 제공업체나 번역가에게 넘겼다고 해서 일이 끝난 것이 아닙니다. 번역의 최적 품질을 보장하기 위해 콘텐츠 제작자는 가능한 한 번역 과정에 깊이 관여해야 합니다. + +- _번역가들과 어떻게 소통할 계획인가요?_ + - 현지화 도구를 사용할 계획이라면 도구 내에서 직접 소통할 수 있습니다. 번역가들이 덜 망설이고 연락할 수 있고, 메시징 도구가 더 자유로운 소통을 가능하게 하므로 번역가들과의 대체 소통 채널을 설정하는 것도 권장됩니다. +- _번역가들의 질문은 어떻게 처리해야 하나요?_ _누가 이 질문에 답해야 하나요?_ + - 번역가들(전문가 및 비전문가 모두)은 종종 질문과 명확화 또는 추가적인 맥락을 위한 요청, 그리고 개선을 위한 피드백과 아이디어를 가지고 연락할 것입니다. 이러한 문의에 답하는 것은 종종 더 나은 참여와 번역된 콘텐츠의 품질로 이어질 수 있습니다. 또한 가능한 한 많은 참고 자료(예: 가이드, 팁, 용어 가이드라인, FAQ 등)를 제공하는 것이 중요합니다. +- _검토 과정은 어떻게 처리해야 하나요?_ _외주를 맡길 건가요, 아니면 내부에서 검토를 수행할 역량이 있나요?_ + - 항상 필요한 것은 아니지만, 검토는 최적의 번역 과정에서 필수적인 부분입니다. 일반적으로 전문 검토자에게 검토 과정을 외주하는 것이 가장 쉽습니다. 그러나 대규모 국제 팀이 있는 경우 검토나 QA도 내부적으로 처리할 수 있습니다. + +4. **번역된 콘텐츠 구현** – 워크플로의 마지막 부분이지만, 미리 고려하는 것이 여전히 중요합니다. + +- _모든 번역이 동시에 완료될까요?_ + - 그렇지 않다면, 어떤 번역을 우선순위로 둘지, 진행 중인 번역을 어떻게 추적할지, 그리고 번역이 완료되는 동안 구현을 어떻게 처리할지 생각해야 합니다. +- _번역된 콘텐츠는 어떻게 전달되나요?_ _어떤 형식으로 전달되나요?_ + - 어떤 접근 방식을 사용하든 이것은 중요한 고려 사항입니다. 현지화 도구를 사용하면 대상 파일 형식과 내보내기 프로세스를 제어할 수 있으며, 일반적으로 호스팅 서비스와의 통합을 활성화하는 등 자동화를 지원합니다. +- _프로젝트에 번역을 어떻게 구현할 것인가요?_ + - 경우에 따라 번역된 파일을 업로드하거나 문서에 추가하는 것만큼 간단할 수 있습니다. 그러나 웹사이트나 앱 번역과 같은 더 복잡한 프로젝트의 경우, 코드가 국제화를 지원하는지 확인하고 구현 프로세스를 미리 어떻게 처리할지 정해야 합니다. +- _형식이 원본과 다르면 어떻게 되나요?_ + - 위와 마찬가지로, 간단한 텍스트 파일을 번역하는 경우 형식은 그다지 중요하지 않을 수 있습니다. 그러나 웹사이트나 애플리케이션용 콘텐츠와 같은 더 복잡한 파일의 경우, 프로젝트에 구현되기 위해서는 형식과 코드가 원본과 동일해야 합니다. 그렇지 않으면 대상 파일은 번역가나 개발자에 의해 편집되어야 합니다. + +**의미 2** + +내부 결정과 접근 방식을 고려하지 않는 대체 번역 워크플로입니다. 여기서 주요 고려 사항은 콘텐츠 자체의 흐름입니다. + +이 경우의 예시 워크플로는 다음과 같습니다. + +1. _번역 → 구현_ + +- 구현 전에 품질을 평가하고 번역을 편집하는 검토나 QA 과정이 없기 때문에, 번역이 인간 번역일 가능성이 높은 가장 간단한 워크플로입니다. +- 이 워크플로에서는 번역가가 일정 수준의 품질을 유지하는 것이 중요하며, 이를 위해서는 프로젝트 관리자와 번역가 간의 적절한 참고 자료와 소통이 필요합니다. + +2. _번역 → 검토 → 구현_ + +- 번역 품질이 수용 가능하고 일관적인지 확인하기 위해 검토 및 편집 과정을 포함하는 더 고급 워크플로입니다. +- 이 워크플로에는 여러 접근 방식이 있으며, 번역은 전문 번역가나 자원봉사자가 수행할 수 있고, 검토 과정은 대상 언어에서 준수해야 할 모든 문법 및 철자법 규칙에 익숙한 전문 검토자가 처리할 가능성이 높습니다. + +3. _번역 → 검토 → QA → 구현_ + +- 최고 수준의 품질을 보장하기 위한 최적의 워크플로입니다. QA가 항상 필요한 것은 아니지만, 번역 및 검토 후 번역된 텍스트의 품질에 대한 더 나은 감을 제공하는 데 유용할 수 있습니다. +- 이 워크플로를 사용하면 번역은 전적으로 자원봉사자나 기계 번역에 의해 수행될 수 있습니다. 검토 과정은 전문 번역가가 수행해야 하며, QA는 대상 언어의 원어민 직원이 있는 경우 언어 서비스 제공업체나 내부에서 수행할 수 있습니다. + +번역 워크플로에 대해 더 알아보기: + +[번역 워크플로의 5단계에 대한 콘텐츠 규칙](https://contentrules.com/creating-translation-workflow/) + +[번역 워크플로 관리란 무엇인가에 대한 Smartling의 설명](https://www.smartling.com/resources/101/what-is-translation-workflow-management/) + +[번역 워크플로에 대한 RixTrans의 설명](https://www.rixtrans.com/translation-workflow) + +## 용어 관리 {#terminology-management} + +용어를 처리하는 방법에 대한 명확한 계획을 세우는 것은 번역의 품질과 일관성을 보장하고 번역가의 시간을 절약하는 가장 중요한 단계 중 하나입니다. + +번역 분야에서 이는 용어 관리로 알려져 있으며, 언어 서비스 제공업체가 언어 전문가 풀과 콘텐츠 관리 외에 클라이언트에게 제공하는 주요 서비스 중 하나입니다. + +용어 관리는 프로젝트에 중요하고 항상 정확하고 일관되게 번역되어야 하는 용어를 식별, 수집, 관리하는 과정을 의미합니다. + +용어 관리에 대해 생각하기 시작할 때 따라야 할 몇 가지 단계가 있습니다. + +- 용어집에 포함되어야 할 주요 용어를 식별합니다. +- 용어 및 그 정의에 대한 용어집을 만듭니다. +- 용어를 번역하고 용어집에 추가합니다. +- 번역을 확인하고 승인합니다. +- 새로운 용어가 중요해지면 용어집을 유지하고 업데이트합니다. + +용어 관리에 대해 더 알아보기: + +[용어 관리란 무엇인가에 대한 Trados의 설명](https://www.trados.com/solutions/terminology-management/translation-101-what-is-terminology-management.html) + +[용어 관리가 중요한 이유에 대한 Language Scientific의 설명](https://www.languagescientific.com/terminology-management-why-it-matters/#:~:text=Terminology%20management%20is%20the%20process,are%20related%20to%20each%20other.) + +[용어 관리란 무엇이며 왜 중요한가에 대한 Clear Words Translation의 설명](http://clearwordstranslations.com/language/en/what-is-terminology-management/) + +### 번역 메모리 및 용어집 {#tm-and-glossary} + +번역 메모리와 용어집은 번역 산업에서 중요한 도구이며 대부분의 언어 서비스 제공업체가 의존하는 것입니다. + +이 용어들이 무엇을 의미하고 서로 어떻게 다른지 살펴보겠습니다. + +**번역 메모리(TM)** – 더 긴 텍스트 블록, 완전한 문장, 단락, 개별 용어를 포함한 세그먼트나 문자열, 그리고 모든 언어로 된 현재 및 이전 번역을 자동으로 저장하는 데이터베이스입니다. + +대부분의 현지화 도구, 번역 관리 시스템, 컴퓨터 보조 번역 도구에는 내장된 번역 메모리가 있으며, 이는 보통 내보내서 다른 유사한 도구에서도 사용할 수 있습니다. + +번역 메모리 사용의 이점으로는 더 빠른 번역, 더 나은 번역 품질, 소스 콘텐츠를 업데이트하거나 변경할 때 특정 번역을 유지하는 능력, 반복적인 콘텐츠에 대한 저렴한 번역 비용 등이 있습니다. + +번역 메모리는 다른 세그먼트 간의 백분율 일치를 기반으로 작동하며, 일반적으로 두 세그먼트가 50% 이상의 동일한 콘텐츠를 포함할 때 가장 유용합니다. 또한 100% 일치하는 반복적인 세그먼트를 자동으로 번역하는 데 사용되어, 반복적인 콘텐츠를 두 번 이상 번역할 필요가 없게 만듭니다. + +번역 메모리에 대해 더 알아보기: + +[번역 메모리에 대한 Memsource의 설명](https://www.memsource.com/translation-memory/) + +[번역 메모리란 무엇인가에 대한 Smartling의 설명](https://www.smartling.com/resources/101/what-is-translation-memory/) + +**용어집 –** 중요하거나 민감한 용어, 그 정의, 기능, 확립된 번역의 목록입니다. 용어집과 번역 메모리의 주요 차이점은 용어집은 자동으로 생성되지 않으며, 완전한 문장의 번역을 포함하지 않는다는 것입니다. + +대부분의 현지화 도구, 번역 관리 시스템, 컴퓨터 보조 번역 도구에는 프로젝트에 중요한 용어를 포함하도록 유지할 수 있는 내장 용어집이 있습니다. TM과 마찬가지로, 용어집은 보통 내보내서 다른 현지화 도구에서 사용할 수 있습니다. + +번역 프로젝트를 시작하기 전에, 시간을 내어 번역가와 검토자를 위한 용어집을 만드는 것을 적극 권장합니다. 용어집을 사용하면 중요한 용어가 올바르게 번역되고, 번역가에게 꼭 필요한 맥락을 제공하며, 번역의 일관성을 보장합니다. + +용어집은 대부분 대상 언어로 확립된 번역을 포함하지만, 이것 없이도 유용합니다. 확립된 번역이 없더라도 용어집은 기술 용어의 정의를 제공하고, 번역되지 않아야 할 용어를 강조하며, 특정 용어가 명사, 동사, 고유 명사 또는 다른 품사로 사용되는지 번역가에게 알려줄 수 있습니다. + +용어집에 대해 더 알아보기: + +[번역 용어집이란 무엇인가에 대한 Lionbridge의 설명](http://info.lionbridge.com/rs/lionbridge/images/Lionbridge%20FAQ_Glossary_2013.pdf) + +[용어집에 대한 Transifex의 설명](https://docs.transifex.com/glossary/glossary) + +프로젝트에 현지화 도구를 사용할 계획이 없다면, 번역 메모리와 용어집을 사용하지 못할 가능성이 높습니다(엑셀 파일에 용어집이나 용어 베이스를 만들 수는 있지만, 자동화된 용어집은 번역가가 수동으로 용어와 그 정의를 찾는 수고를 덜어줍니다). + +이는 모든 반복적이고 유사한 콘텐츠를 매번 수동으로 번역해야 함을 의미합니다. 또한 번역가들은 특정 용어를 번역해야 하는지 여부, 텍스트에서 어떻게 사용되는지, 그리고 용어에 이미 확립된 번역이 있는지에 대해 질문해야 할 것입니다. + +_프로젝트에서 ethereum.org 번역 메모리 및 용어집을 사용하고 싶으신가요?_ translations@ethereum.org로 문의해주세요._ + +## 번역가 확보 {#translator-outreach} + +**언어 서비스 제공업체와 협력하기** + +언어 서비스 제공업체와 전문 번역가와 함께 일하는 경우 이 섹션은 그다지 관련이 없을 수 있습니다. + +이 경우 필요한 모든 서비스(예: 번역, 검토, QA)를 여러 언어로 제공할 수 있는 역량을 갖춘 언어 서비스 제공업체를 선택하는 것이 중요합니다. + +제공되는 요율만으로 언어 서비스 제공업체를 선택하고 싶을 수 있지만, 가장 큰 언어 서비스 제공업체가 더 높은 요율을 받는 데에는 이유가 있다는 점을 유념해야 합니다. + +- 이들은 데이터베이스에 수만 명의 언어 전문가를 보유하고 있어, 특정 분야에 대한 충분한 경험과 지식을 갖춘 번역가(즉, 기술 번역가)를 프로젝트에 배정할 수 있습니다. +- 이들은 다양한 프로젝트를 진행하고 고객의 다양한 요구를 충족시킨 상당한 경험을 가지고 있습니다. 이는 이들이 특정 워크플로에 더 잘 적응하고, 번역 프로세스에 대한 귀중한 제안과 잠재적인 개선 사항을 제공하며, 요구 사항, 필요 조건, 마감일을 맞출 가능성이 더 높다는 것을 의미합니다. +- 가장 큰 언어 서비스 제공업체 대부분은 사용할 수 있는 자체 현지화 도구, 번역 메모리, 용어집을 보유하고 있습니다. 그렇지 않더라도, 이들은 최소한 번역가 풀에 충분한 언어 전문가를 보유하고 있어 번역가들이 사용하고자 하는 모든 현지화 도구에 익숙하고 작업할 수 있도록 보장합니다. + +[2021 Nimdzi 100 보고서](https://www.nimdzi.com/nimdzi-100-top-lsp/)에서 세계 최대 언어 서비스 제공업체에 대한 심층 비교, 각 업체에 대한 세부 정보, 제공 서비스별 분석, 지리적 데이터 등을 찾아볼 수 있습니다. + +**비전문 번역가와 협력하기** + +비전문 번역가와 함께 일하거나 번역을 도와줄 자원봉사자를 찾고 있을 수 있습니다. + +사람들에게 다가가 프로젝트에 참여하도록 초대하는 몇 가지 방법이 있습니다. 이는 주로 제품과 이미 보유한 커뮤니티의 규모에 따라 달라집니다. + +자원봉사자를 온보딩하는 몇 가지 방법은 다음과 같습니다. + +**아웃리치 –** 아래 항목에서 어느 정도 다루고 있지만, 잠재적인 자원봉사자에게 연락하여 번역 이니셔티브를 알리는 것만으로도 효과적일 수 있습니다. + +많은 사람들이 자신이 좋아하는 프로젝트에 참여하고 기여하고 싶어 하지만, 개발자이거나 특별한 기술 능력이 없으면 그렇게 할 명확한 방법을 찾지 못하는 경우가 많습니다. 프로젝트에 대한 인지도를 높일 수 있다면, 많은 이중 언어 사용자들이 기꺼이 참여할 것입니다. + +**커뮤니티 내부에서 찾기 –** 이 분야의 대부분 프로젝트는 이미 크고 활발한 커뮤니티를 가지고 있습니다. 많은 커뮤니티 구성원들은 간단한 방법으로 프로젝트에 기여할 기회를 아마도 고마워할 것입니다. + +오픈 소스 프로젝트에 기여하는 것은 종종 내재적 동기에 기반하지만, 환상적인 학습 경험이기도 합니다. 프로젝트에 대해 더 배우고 싶은 사람은 누구나 자원봉사자로서 번역 프로그램에 참여하는 것을 기뻐할 것입니다. 이는 자신이 아끼는 것에 기여했다는 사실과 집중적인 실습 학습 경험을 결합할 수 있기 때문입니다. + +**제품 내에서 이니셔티브 언급 –** 제품이 인기가 많고 많은 사람이 사용한다면, 제품을 사용하는 동안 번역 프로그램을 강조하고 사용자에게 행동을 촉구하는 것은 매우 효과적일 수 있습니다. + +애플리케이션 및 웹사이트용 제품에 CTA가 있는 배너나 팝업을 추가하는 것만큼 간단할 수 있습니다. 이는 타겟 고객이 커뮤니티, 즉 애초에 참여할 가능성이 가장 높은 사람들이기 때문에 효과적입니다. + +**소셜 미디어 –** 소셜 미디어는 번역 프로그램에 대한 인지도를 높이고 커뮤니티 구성원뿐만 아니라 아직 커뮤니티 회원이 아닌 다른 사람들에게 다가가는 효과적인 방법이 될 수 있습니다. + +Discord 서버나 Telegram 채널이 있다면, 이를 통해 아웃리치, 번역가와의 소통, 기여자 인정 등을 쉽게 할 수 있습니다. + +X(이전의 트위터)와 같은 플랫폼은 새로운 커뮤니티 회원을 온보딩하고 기여자를 공개적으로 인정하는 데에도 도움이 될 수 있습니다. + +리눅스 재단은 오픈 소스 기여자와 그들의 동기를 분석한 광범위한 [2020 FOSS 기여자 설문 조사 보고서](https://www.linuxfoundation.org/wp-content/uploads/2020FOSSContributorSurveyReport_121020.pdf)를 작성했습니다. + +## 결론 {#conclusion} + +이 문서는 모든 번역 프로그램이 알아야 할 몇 가지 주요 고려 사항을 담고 있습니다. 이것은 결코 완전한 가이드는 아니지만, 번역 산업에 경험이 없는 사람이라도 자신의 프로젝트를 위한 번역 프로그램을 조직하는 데 도움을 줄 수 있습니다. + +다양한 도구, 프로세스, 번역 프로그램 관리의 중요한 측면에 대한 더 자세한 지침과 분석을 찾고 있다면, 일부 대규모 언어 서비스 제공업체는 블로그를 운영하며 현지화 프로세스의 다양한 측면에 대한 기사를 자주 게시합니다. 위의 주제 중 어느 것이든 더 깊이 파고들어 현지화 프로세스가 전문적으로 어떻게 작동하는지 이해하고 싶다면 이것이 최고의 참고 자료입니다. + +각 섹션의 끝에 몇 가지 관련 링크가 포함되어 있지만, 온라인에서 다른 많은 참고 자료를 찾을 수 있습니다. + +협력 제안이나 추가 정보, ethereum.org 번역 프로그램을 유지하면서 얻은 학습 내용 및 모범 사례에 대해서는 언제든지 translations@ethereum.org로 문의해 주세요. diff --git a/public/content/translations/ko/contributing/translation-program/resources/index.md b/public/content/translations/ko/contributing/translation-program/resources/index.md new file mode 100644 index 00000000000..f3be8a7dc1c --- /dev/null +++ b/public/content/translations/ko/contributing/translation-program/resources/index.md @@ -0,0 +1,49 @@ +--- +title: "번역가를 위한 참고 자료" +lang: ko +description: "ethereum.org 번역가를 위한 유용한 참고 자료" +--- + +# 참고 자료 {#resources} + +아래에서 ethereum.org 번역가를 위한 유용한 가이드 및 도구는 물론 번역 커뮤니티와 업데이트를 찾을 수 있습니다. + +## 가이드 {#guides} + +- [번역 스타일 가이드](/contributing/translation-program/translators-guide/) _– ethereum.org 번역가를 위한 지침 및 팁_ +- [번역 FAQ](/contributing/translation-program/faq/) _– ethereum.org 번역 프로그램에 대한 자주 묻는 질문과 답변_ +- [Crowdin 온라인 편집기 가이드](https://support.crowdin.com/online-editor/) _– Crowdin 온라인 편집기 사용법과 일부 고급 기능에 대한 심층 가이드_ + +## 도구 {#tools} + +- [Linguee](https://www.linguee.com/) + _– 단어 또는 구문으로 검색할 수 있는 번역 검색 엔진 및 사전_ +- [Proz 용어 검색](https://www.proz.com/search/) + _– 전문 용어를 위한 번역 사전 및 용어집 데이터베이스_ +- [Eurotermbank](https://www.eurotermbank.com/) + _– 42개 언어로 된 유럽 용어 모음_ + +## 커뮤니티 {#communities} + +- [언어별 Discord 번역 그룹](https://discord.gg/ethereum-org) + _– ethereum.org 번역가를 번역 그룹에 연결하기 위한 이니셔티브_ +- [중국어 번역가 그룹](https://www.notion.so/Ethereum-org-05375fe0a94c4214acaf90f42ba40171) + _– 중국어 번역가 간의 원활한 조정을 위한 Notion 페이지_ + +## 최신 업데이트 {#latest-updates} + +번역 프로그램의 최신 진행 상황을 확인하려면 [이더리움 재단 블로그](https://blog.ethereum.org/)를 팔로우하세요: + +- [2021년 10월 주요 성과 업데이트](https://blog.ethereum.org/2021/10/04/translation-program-update/) +- [2020년 12월 주요 성과 업데이트](https://blog.ethereum.org/2020/12/21/translation-program-milestones-updates-20/) +- [2020년 7월 주요 성과 업데이트](https://blog.ethereum.org/2020/07/29/ethdotorg-translation-milestone/) +- [2019년 8월 번역 프로그램 출시](https://blog.ethereum.org/2019/08/20/translating-ethereum-for-our-global-community/) + +## 번역가를 위한 오피스 아워 {#office-hours} + +저희는 매월 둘째 주 수요일 번역가를 위한 집무 시간을 가지고 있습니다. 오피스 아워는 [ethereum.org Discord](https://discord.gg/ethereum-org)의 #office-hours 음성 채널에서 진행되며, 여기서 정확한 시간과 추가 세부 정보를 확인할 수도 있습니다. + +오피스 아워를 통해 번역가들은 번역 과정에 대해 질문하고, 프로그램에 대한 피드백을 제공하고, 아이디어를 공유하거나, 핵심 ethereum.org 팀과 편하게 대화할 수 있습니다. +마지막으로, 저희는 이러한 통화를 통해 번역 프로그램과 최근 개발 활동을 알리고 주요 조언과 지침을 기여자들과 공유하고자 합니다. + +만약 귀하가 ethereum.org 번역가이거나 번역가가 되고 싶다면, 자유롭게 이 세션 중 하나에 참여하세요. diff --git a/public/content/translations/ko/contributing/translation-program/translatathon/details/index.md b/public/content/translations/ko/contributing/translation-program/translatathon/details/index.md new file mode 100644 index 00000000000..8c31911facc --- /dev/null +++ b/public/content/translations/ko/contributing/translation-program/translatathon/details/index.md @@ -0,0 +1,90 @@ +--- +title: "세부 정보 및 규칙" +lang: ko +template: translatathon +--- + +![](./participate.png) + +Translatathon은 누구나 참여할 수 있으며 신청서를 작성하고 Crowdin의 프로젝트에 참여하여 참가할 수 있습니다. + +번역가는 번역 기간 동안 Crowdin 에디터에서 자신의 언어로 번역되지 않은 문자열에 대한 번역을 제안하여 포인트를 수집합니다. + +각 참가자의 최종 점수는 번역 기간 동안 번역한 단어 수와 수집한 잠재적 보너스 포인트를 기준으로 순위표의 위치에 따라 결정됩니다. + +## 시작하기 {#getting-started} + +번역 과정은 Crowdin의 ethereum.org 프로젝트에서 진행되며, 번역가들은 ethereum.org 웹사이트의 거의 모든 콘텐츠로 구성된 미번역 문자열에 대한 번역을 제안합니다. + +번역은 온라인 에디터에서 직접 제안되므로 파일이나 결과물을 다운로드하거나 업로드할 필요가 없습니다. 번역된 각 단어는 추적되고 계산됩니다. + +**1) 프로젝트 참여하기** + +- 기여를 시작하려면 [Crowdin의 ethereum.org 프로젝트](https://crowdin.com/project/ethereum-org)에 참여하세요. +- 로그인하거나 계정을 생성해야 합니다. 이메일 주소와 비밀번호만 있으면 됩니다. + +**2) 언어 선택하기** + +- 대상 언어 목록에서 본인의 언어를 찾아 이름이나 국기를 클릭하여 여세요. +- 번역하고자 하는 언어가 목록에 없는 경우 Crowdin에서 [Ethereum.org 팀](https://crowdin.com/profile/ethdotorg)에 문의하시거나 translations@ethereum.org로 이메일을 보내주시면 요청에 따라 대상 언어를 추가해 드립니다. + +**3) 번역되지 않은 파일 열기** + +- 번역을 시작하려면 먼저 번역되지 않은 파일을 찾으세요. 원본 파일이 들어있는 폴더는 우선순위에 따라 정렬되므로, 번역되지 않은 파일이 있는 첫 번째 폴더부터 번역을 시작해야 합니다. +- 각 파일에는 파일 내 번역 가능한 콘텐츠가 얼마나 번역되고 승인되었는지를 보여주는 진행률 표시기가 있습니다... 파일의 번역 진행률이 100% 미만인 경우 해당 파일을 번역해 주세요. + +**4) 번역되지 않은 문자열 번역하기** + +- 번역할 파일을 열 때는 번역되지 않은 문자열만 번역해야 합니다! +- 각 문자열에는 _번역됨_, _미번역_ 또는 _승인됨_ 여부를 보여주는 상태 표시기가 있습니다. 원본 문자열에 이미 해당 언어로 제안된 번역이 있는 경우 번역할 필요가 없습니다. +- 에디터에서 문자열을 필터링하여 _미번역 우선_ 또는 _미번역만_ 표시할 수도 있습니다. + +Crowdin 에디터 탐색 및 사용에 대한 자세한 안내는 모든 Translatathon 참가자가 [번역 방법](/contributing/translation-program/how-to-translate/) 가이드를 읽어보시길 권장합니다. + +[번역 스타일 가이드](/contributing/translation-program/translators-guide/)를 확인하여 몇 가지 팁과 모범 사례를 찾아볼 수도 있습니다. + +**포인트 작동 방식** + +모든 Translatathon 참가자는 ethereum.org Crowdin 프로젝트 및 기타 참여 대상 프로젝트(참여 대상 프로젝트의 전체 목록은 아래에서 확인 가능)의 콘텐츠를 번역하여 최종 점수에 합산될 포인트를 획득하게 됩니다. + +점수 계산은 간단합니다: **번역된 단어 1개 = 1포인트** + +최종 포인트를 받으려면 제안한 번역이 평가 과정을 통과해야 합니다. 이 과정에서 전문 검수자가 각 참가자의 번역이 최소 품질 기준을 충족하는지, 과정에서 기계 또는 AI 번역이 사용되지 않았는지 확인합니다. + +## 생태계 콘텐츠 {#ecosystem-content} + +ethereum.org 번역 프로그램은 항상 활성화되어 있으므로, 일부 대상 언어의 웹사이트 번역 진행률은 다른 언어에 비해 현저히 높습니다. + +모든 Translatathon 참가자가 가능한 한 많은 콘텐츠를 번역하고 최고 상을 놓고 경쟁할 수 있는 동등한 기회를 보장하기 위해 Translatathon에 포함되는 원본 콘텐츠는 ethereum.org 웹사이트 콘텐츠에만 국한되지 않습니다. + +참여 대상 프로젝트를 번역하는 참가자는 동일한 양의 포인트를 얻게 됩니다. 모든 프로젝트에서 번역된 단어 1개 = 1포인트입니다. + +다음은 2025 Translatathon에 포함되는 모든 참여 대상 프로젝트 목록입니다: + +- [Ethereum.org](https://crowdin.com/project/ethereum-org) + +- [Ethereum.org 개발자 튜토리얼](https://crowdin.com/project/33388446abbe9d7aa21e42e49bba7f97) + +- [EthStaker deposit CLI](https://crowdin.com/project/ethstaker-deposit-cli) + +- [Eth Docker 문서](https://crowdin.com/project/eth-docker-docs) + +- [Remix IDE 개발문서](https://crowdin.com/project/remix-translation) + +- [Remix LearnEth](https://crowdin.com/project/remix-learneth) + +- [web3.py](https://crowdin.com/project/web3py) + +## 평가 과정 {#evaluation-process} + +모든 번역은 QA 및 피드백을 거치게 되며, 전문 언어학자들이 품질과 정확성을 기준으로 제출물을 평가합니다. + +또한 기계 또는 AI 번역을 자동으로 감지하는 도구를 사용하여 기계 번역 방지 조치를 실행할 예정입니다. + +번역 품질이 점수 계산에 결정적인 역할을 하지는 않지만, 기계 또는 AI 번역을 사용한 것으로 밝혀진 참가자나 저품질의 부정확한 번역을 제안하는 참가자는 수상 자격이 없습니다! + +평가 기간은 9월 내내 진행되며, 결과는 9월 25일 ethereum.org 커뮤니티 콜에서 발표될 예정입니다. + +또한 모든 번역은 웹사이트에 추가되기 전에 전체 검토를 거칩니다. + + diff --git a/public/content/translations/ko/contributing/translation-program/translatathon/index.md b/public/content/translations/ko/contributing/translation-program/translatathon/index.md new file mode 100644 index 00000000000..3237c38e9a2 --- /dev/null +++ b/public/content/translations/ko/contributing/translation-program/translatathon/index.md @@ -0,0 +1,100 @@ +--- +title: "2025 ethereum.org 트랜슬레이터톤" +lang: ko +template: translatathon +--- + + + + + + + +## 소개 {#introduction} + +저희는 모든 사람이 사용하는 언어와 관계없이 이더리움 콘텐츠와 온보딩 참고 자료를 이용할 수 있어야 한다고 믿습니다. +이 목표에 더 가까이 다가가기 위해, ethereum.org 번역 프로그램은 웹사이트를 최대한 많은 언어로 번역하려는 이니셔티브입니다. + +번역 프로그램의 일환으로, 저희는 제3회 트랜슬레이터톤을 개최합니다. 트랜슬레이터톤은 번역 활동이 적은 언어의 번역 기여를 장려하고, 사이트에서 이용 가능한 언어 수와 콘텐츠 양을 늘리며, 새로운 기여자를 온보딩하고 기존 기여자에게 보상하는 것을 목표로 하는 번역 대회입니다. + +영어가 아닌 다른 언어의 원어민이고, 상금을 놓고 경쟁하면서 이더리움 콘텐츠에 대한 접근성을 높이는 데 도움을 주고 싶으시다면, 계속 읽어보며 자세히 알아보세요! + +[ethereum.org 번역 프로그램에 대해 더 알아보기](/contributing/translation-program/) + +## 타임라인 {#timeline} + +2025 트랜슬레이터톤의 주요 일정은 다음과 같습니다: + + + + + +## 참여하기 {#participate} + +![커뮤니티와 지구 이미지](./participate.png) + + + +

누가 참여할 수 있나요?

+ 만 18세 이상, 하나 이상의 비영어권 언어를 모국어로 사용하며 영어에 능통한 모든 사람. +
+ +

번역가여야 하나요?

+ 아니요. 이중 언어 구사자이기만 하면 되며, 사람의 번역을 제안해야 합니다(기계 번역 사용은 금지됩니다!). 최선을 다해 번역하면 되며, 전문적인 경력은 필요하지 않습니다. +
+
+ + + +

시간을 얼마나 투자해야 하나요?

+ 원하는 만큼 투자하시면 됩니다. 상품을 받을 수 있는 최소 기준은 1,000단어 번역이며, 완료하는 데 약 2시간이 소요될 것으로 예상됩니다. 상위 상품을 놓고 경쟁하려면 더 많은 시간을 투자해야 합니다. +
+ +

이더리움에 대해 잘 알아야 하나요?

+ 아니요. 이더리움에 익숙하면 생산성과 품질에 도움이 될 수 있지만, 트랜슬레이터톤은 학습 경험이기도 하므로 누구나 참여하여 이더리움에 대해 더 많이 배우실 수 있습니다. +
+
+ +자세한 내용은 [전체 이용 약관](/contributing/translation-program/translatathon/terms-and-conditions)을 참조하세요. + +### 단계별 안내 {#step-by-step-instructions} + + + +## 상품 {#prizes} + +| 순위 | 상금 | +| ----------- | ----- | +| 1위 | $4000 | +| 2위 | $2500 | +| 3위 | $1500 | +| 4위 | $1100 | +| 5위 | $1000 | +| 6위 | $600 | +| 7위 | $550 | +| 8위 | $500 | +| 9위 | $450 | +| 10위 | $400 | +| 11위 - 20위 | $240 | +| 21위 - 50위 | $120 | +| 51위 - 100위 | $60 | +| 101위 - 150위 | $40 | +| 그 외 | $20 | + +모든 상금은 ETH로 지급됩니다. + + + + diff --git a/public/content/translations/ko/contributing/translation-program/translators-guide/index.md b/public/content/translations/ko/contributing/translation-program/translators-guide/index.md new file mode 100644 index 00000000000..ad1ca6b2b67 --- /dev/null +++ b/public/content/translations/ko/contributing/translation-program/translators-guide/index.md @@ -0,0 +1,299 @@ +--- +title: "번역가 가이드" +lang: ko +description: "Ethereum.org 번역가 지침 및 조언" +--- + +# Ethereum.org 번역 스타일 가이드 {#style-guide} + +Ethereum.org 번역 스타일 가이드에는 번역가님을 위한 가장 중요한 가이드라인, 절차 및 조언이 포함되어 있어 웹사이트 현지화에 도움이 됩니다. + +이 문서는 일반적인 가이드 역할을 하며 특정 언어에 한정되지 않습니다. + +질문, 제안 또는 피드백이 있는 경우 translations@ethereum.org로 언제든지 문의하시거나, Crowdin에서 @ethdotorg에게 메시지를 보내거나, [저희 Discord에 참여](https://discord.gg/ethereum-org)하여 #translations 채널에서 메시지를 보내거나 팀원에게 연락해주세요. + +## Crowdin 사용하기 {#using-crowdin} + +Crowdin 프로젝트 참여 방법과 Crowdin 온라인 편집기 사용 방법에 대한 기본 지침은 [번역 프로그램 페이지](/contributing/translation-program/#how-to-translate)에서 찾을 수 있습니다. + +Crowdin 및 고급 기능 사용에 대해 더 자세히 알아보시려면, [Crowdin 기술 자료](https://support.crowdin.com/online-editor/)에서 모든 Crowdin 기능에 대한 심층 가이드와 개요를 확인하실 수 있습니다. + +## 메시지의 핵심 파악하기 {#capturing-the-essence} + +Ethereum.org의 콘텐츠를 번역하는 경우 직역을 피해 주세요. + +내용의 본질을 파악하는 번역을 하는 것이 중요합니다. 위 설명은 특정 구절을 바꾸거나 내용을 단어 단위로 번역하는 것이 아닌 서술하는 번역을 이야기할 수 있을 겁니다. + +언어마다 문법 규칙, 규칙 및 단어 순서가 다릅니다. 번역할 때, 문장이 대상 언어로 어떻게 구성되어 있는지 유의하시고, 영어 원문을 문자 그대로 번역하는 것은 문장 구조와 가독성이 떨어질 수 있으므로 지양해 주세요. + +원문 텍스트를 한 단어씩 번역하는 것이 아닌 전체 문장을 읽은 뒤 대상 언어의 관습에 맞게 수정하는 것을 추천합니다. + +## 격식체와 비격식체 {#formal-vs-informal} + +저희는 모든 방문자들에게 항상 정중하고 적합한 격식적인 표현 형식을 사용합니다. + +격식적인 표현을 사용하면 비공식적이거나 모욕적으로 들리지 않을 수 있으며, 방문자의 나이와 성별에 상관없이 읽을 수 있습니다. + +대부분의 인도유럽어족과 아프리카아시아어족 언어들은 남성과 여성을 구별하는 성별 2인칭 대명사를 사용합니다. 그렇지만 사람을 호칭하거나 소유 대명사를 사용할 때, 저희는 방문자의 성별을 가정하는 것을 피할 수 있습니다. 왜냐하면 격식적인 형식의 표현은 일반적으로 어떻게 인지하던 적용 가능하고 일관되기 때문입니다. + +## 간단하고 명확한 어휘와 의미 {#simple-vocabulary} + +저희의 목표는 웹사이트 콘텐츠를 최대한 많은 사람들이 이해할 수 있도록 만드는 겁니다. + +대부분의 경우, 짧고 간단한 단어로 쉽게 이해시킬 수 있습니다. 만약 동일한 의미를 가진 특정 단어에 대해 가능한 여러 개의 번역이 있는 경우, 가장 좋은 선택은 의미를 명확하게 반영하는 가장 짧은 단어인 경우가 많습니다. + +## 표기 체계 {#writing-system} + +Ethereum.org은 라틴어로 된 대체 표기 체계(또는 쓰기 체계)을 사용하여 여러 언어로 이용할 수 있습니다. + +모든 내용은 해당 언어에 맞는 표기 체계를 사용하여 번역되어야 하며, 라틴 문자를 사용하여 작성된 단어를 포함해서는 안 됩니다. + +내용을 번역할 때는 번역이 반드시 일관되야 하며 라틴 문자가 포함되지 않도록 해야 합니다. + +일반적인 오해는 Ethereum은 항상 로마자 표기로 써야된다는 것입니다. 이는 대부분 올바르지 않으므로, 자국어에 맞는 이더리움 표기법을 사용하세요(예: 중국어의 以太坊, 아랍어의 إيثيريوم 등). + +**위 내용은 원칙적으로 고유 명사를 번역해서는 안 되는 언어에는 적용되지 않습니다.** + +## 페이지 메타데이터 번역하기 {#translating-metadata} + +일부 페이지에는 'title', 'lang', 'description', 'sidebar' 등과 같은 페이지의 메타데이터가 포함되어 있습니다. + +저희는 Crowdin에 새로운 페이지를 업로드할 때 번역가님이 절대 번역해서는 안 되는 내용을 숨깁니다. 즉, Crowdin에서 번역가님이 볼 수 있는 모든 메타데이터는 번역되어야 합니다. + +원문 텍스트가 'en'인 문자열을 번역할 때 특히 유의해 주세요. 이는 페이지가 사용 가능한 언어를 나타내며, 해당 언어의 [ISO 언어 코드](https://www.andiamo.co.uk/resources/iso-language-codes/)로 번역해야 합니다. 이러한 문자열은 항상 원어에서 대상 언어의 쓰기 체계가 아닌 라틴 문자를 사용하여 번역되어야 합니다. + +사용할 언어 코드를 잘 모를 경우 Crowdin에서 번역 메모리를 확인하거나 Crowdin 온라인 에디터의 페이지 URL에서 해당 언어의 언어 코드를 찾을 수 있습니다. + +가장 널리 쓰이는 언어 코드 예시: + +- 아랍어 - ar +- 중국어 간체 - zh +- 프랑스어 - fr +- 인도어 - hi +- 스페인어 - es + +## 외부 기사 제목 {#external-articles} + +일부 문자열은 외부 기사 제목을 포함하고 있습니다. 대부분의 개발자 문서에는 추가로 읽을 수 있는 외부 기사에 대한 링크가 포함되어 있습니다. 기사 제목을 포함하는 문자열은 기사의 언어와 상관없이 번역되어야 자신의 언어로 페이지를 보는 방문자에게 보다 일관된 사용자 경험을 제공할 수 있습니다. + +아래에서 외부 기사 제목 문자열이 번역가에게 어떻게 보이는지와 이를 식별하는 방법에 대한 약간의 예를 찾을 수 있습니다. (기사 링크는 대부분 이러한 페이지 하단의 '추가 읽기' 부분에서 확인할 수 있습니다.): + +![사이드바의 기사 제목.png](./article-titles-in-sidebar.png) +![편집기의 기사 제목.png](./article-titles-in-editor.png) + +## Crowdin 경고 {#crowdin-warnings} + +Crowdin에는 번역가가 실수하려고 할 때 경고하는 기능이 내장되어 있습니다. 번역문에 필요한 태그를 삽입하지 않았거나, 번역하면 안되는 요소를 번역했거나, 공백 문자를 연속으로 추가했거나, 구두점을 생략한 등의 경우에는 Crowdin 시스템이 번역문을 저장하기 전에 자동으로 경고를 표시합니다. +이와 같은 경고가 표시되면 돌아가서 제안한 번역을 다시 확인해보세요. + +**이러한 경고는 일반적으로 무언가 잘못되었거나 번역에 원문 텍스트의 핵심 부분이 누락되었음을 의미하므로 절대 무시하지 마세요.** + +번역에 태그 추가를 잊었을 때 표시되는 Crowdin 경고의 예시: +![Crowdin 경고 예시](./crowdin-warning-example.png) + +## 태그 및 코드 스니펫 처리하기 {#dealing-with-tags} + +많은 원문 콘텐츠에는 Crowdin 에디터에서 노란색으로 강조 표시된 태그와 변수가 포함되어 있습니다. 태그와 변수는 다른 기능을 수행하며 올바르게 접근해야 합니다. + +**Crowdin 설정** + +태그를 더 쉽게 관리하고 원본에서 직접 복사하려면 Crowdin 편집기에서 설정을 변경하는 것이 좋습니다. + +1. 설정 열기 + ![편집기에서 설정 여는 방법](./editor-settings.png) + +2. 'HTML 태그 표시' 섹션으로 스크롤을 내립니다. + +3. '숨기기' 선택 + !['숨기기'를 선택하세요](./hide-tags.png) + +4. '저장' 클릭 + +이 옵션을 선택하면 전체 태그 텍스트가 더 이상 표시되지 않고 숫자로 대체됩니다. +번역 시 이 태그를 클릭하면 해당 태그가 번역 필드에 자동으로 복사됩니다. + +**링크** + +Ethereum.org 또는 다른 웹사이트에 대한 전체 링크를 볼 수 있습니다. + +링크는 원문과 동일해야 하며 번경되거나 번역되어서는 안됩니다. 링크를 번역하거나, 어떠한 방식으로든 변경하거나, 슬래시(/)와 같은 링크의 한 부분을 지우기만 해도 사용할 수 없는 링크가 됩니다. + +링크를 다루는 가장 좋은 방법은 링크를 클릭하거나 'Copy Source' 버튼(Alt+C)을 사용하여 원문에서 직접 복사하는 것입니다. + +![link.png](./example-of-link.png 예시) + +링크는 원문 텍스트에 태그(예: `<0>` ``) 형태로도 나타납니다. 만약 태그 위로 마우스 커서를 올려놓으면 에디터에서 전체 콘텐츠가 표시됩니다. - 때로는 이러한 태그가 링크를 대신합니다. + +원문에서 링크를 복사하고 순서를 변경하지 않는 것이 매우 중요합니다. + +태그의 순서가 변경되면 태그가 나타내는 링크가 깨집니다. + +![링크 안 tags.png](./example-of-links-inside-tags.png 예시) + +**태그와 변수** + +원문 텍스트에는 항상 원문에서 복사해야 하며 변경되지 않아야 하는 다양한 유형의 태그가 포함되어 있습니다. 위와 유사하게 번역문에서 이러한 태그의 순서도 원문과 동일하게 유지되어야 합니다. + +태그는 항상 여는 태그와 닫는 태그가 포함됩니다. 대부분의 경우 여는 태그와 닫는 태그 사이의 텍스트를 번역해야 합니다. + +예시: ``Decentralized`` + +`` - _텍스트를 굵게 만드는 여는 태그_ + +Decentralized - _번역 가능한 텍스트_ + +`` - _닫는 태그_ + +![‘strong’ 태그 예시.png](./example-of-strong-tags.png) + +코드 조각에는 번역해서는 안 되는 코드가 포함되어 있으므로 다른 태그와는 다르게 접근해야 합니다. + +예시: ``nonce`` + +`` - _코드 스니펫을 포함하는 여는 태그_ + +nonce - _번역 불가능한 텍스트_ + +`` - _닫는 태그_ + +![Example of code snippets.png](./example-of-code-snippets.png) + +원문 텍스트에는 숫자만 포함된 단축 태그도 포함되어 있어 해당 기능이 즉시 명확하지 않습니다. 이러한 태그 위에 마우스 커서를 올려놓으면 해당 태그가 어떤 기능을 제공하는지 정확하게 확인할 수 있습니다. + +아래 예시에서 `<0>` 태그에 마우스를 올리면 해당 태그가 ``를 나타내며 코드 스니펫을 포함하고 있음을 알 수 있으므로, 이 태그 내부의 내용은 번역해서는 안 됩니다. + +![Example of ambiguous tags.png](./example-of-ambiguous-tags.png) + +## 약어 대 전체 형식 {#short-vs-full-forms} + +웹사이트에는 dapps, NFT, DAO, DeFi 등 많은 약어가 사용됩니다. 이러한 약어는 일반적으로 영어로 사용되며 웹사이트 방문자 대부분이 친숙한 표현입니다. + +일반적으로 다른 언어로 정해진 번역이 없기 때문에, 이러한 용어와 유사한 용어에 접근하는 가장 좋은 방법은 전체 형식을 설명하는 번역을 제공하고 괄호 안에 영어 약어를 추가하는 것입니다. + +대부분의 사람들이 이러한 약어에 친숙하지 않을 것입니다. 그리고 지역화된 설명들은 대부분의 방문자들에게 별로 의미가 없을 것이기 때문에, 이러한 약어를 번역하지 마세요. + +dapps 번역 예시: + +- 탈중앙화 애플리케이션(dapps) → _번역된 전체 형식(괄호 안에 영어 약어)_ + +## 정립된 번역어가 없는 용어 {#terms-without-established-translations} + +일부 용어는 다른 언어로 번역되지 않았을 수 있으며 원래 영어 용어로 널리 알려져 있습니다. 이러한 용어에는 proof-of-work, proof-of-stake, Beacon Chain, staking 등과 같은 새로운 개념이 대부분 포함됩니다. + +이러한 용어들을 번역하는 것은 부자연스럽게 들릴 수 있지만, 영어 설명은 다른 언어에서도 일반적으로 사용되기 때문에 번역하는 것을 강력하게 추천합니다. + +이러한 용어들을 번역할 때 자유롭게 창의력을 발휘하거나 설명적인 번역을 해보세요. 또는 단순히 직역하세요. + +**일부만 영어로 남기지 않고 대부분의 용어를 번역해야 하는 이유는 앞으로 이더리움과 관련 기술을 사용하는 사람들이 늘어나면서 이 새로운 용어가 더욱 널리 보급될 것이라는 사실 때문입니다. 그래서 전 세계의 더 많은 사람들이 이더리움에 합류하려면, 우리가 직접 용어를 만들 필요가 있더라도 가능한 많은 언어로 이해할 수 있는 용어로 제공해야 합니다.** + +## 버튼 및 CTA {#buttons-and-ctas} + +웹사이트에는 다른 콘텐츠와 다르게 번역되어야 하는 수많은 버튼들이 있습니다. + +버튼 텍스트는 대부분의 문자열과 연결된 문맥 스크린샷을 보거나 "버튼(button)" 단어가 포함된 맥락을 에디터에서 확인하여 식별할 수 있습니다. + +버튼의 번역은 형식 불일치를 방지하기 위해 가능한 짧아야 합니다. 또한 버튼 번역은 명령형, 즉 명령이나 요청을 나타내야 합니다. + +![How to find a button.png](./how-to-find-a-button.png) + +## 포용성을 위한 번역 {#translating-for-inclusivity} + +Ethereum.org 방문자들은 전 세계와 다른 환경에서 옵니다. 따라서 웹사이트의 언어는 중립적이어야 합니다. 그리고 모두를 환영해야 하며 배타적이지 않아야 합니다. + +공정성을 위한 번역의 중요한 측면은 성 중립성입니다. 이는 격식적인 표현 형식을 사용하고 번역에서 성별에 따른 단어를 지양함으로써 쉽게 달성할 수 있습니다. + +공정성의 또 다른 형태는 특정 국가, 인종 또는 지역이 아닌 전 세계 사용자를 대상으로 번역을 시도해보는 겁니다. + +마지막으로 언어는 모든 청중과 연령대에 적합해야 합니다. + +## 언어별 번역 {#language-specific-translations} + +번역할 때 원본에서 복사하는 것과는 달리 모국어에서 사용되는 문법 규칙, 관례와 형식을 따르는 것이 중요합니다. 하지만 원문 텍스트는 다른 언어에는 적용되지 않는 영어 문법 규칙 및 관례를 따릅니다. + +그래서 모국어에 대한 규칙을 알고 그에 알맞게 번역해야 합니다. 도움이 필요하면 저희에게 연락해 주세요. 그러면 모국어에서 이러한 요소를 어떻게 사용해야 하는지에 대한 몇 가지 자료를 찾아보실 수 있도록 도와드리겠습니다. + +특히 주의해야 할 몇 가지 예시: + +### 구두점 및 서식 {#punctuation-and-formatting} + +**대문자** + +- 다른 언어에서는 대문자 사용에 큰 차이가 있습니다. +- 영어에서는 제목과 이름, 월과 일, 언어 이름, 공휴일 등의 모든 단어를 대문자로 시작하는 것이 일반적입니다. 다른 많은 언어에서는 대문자 사용 규칙이 다르기 때문에 문법적으로 올바르지 않습니다. +- 어떤 언어에는 영어에서 대문자가 아닌 인칭 대명사, 명사, 특정 형용사를 대문자로 표기하는 규칙이 있습니다. + +**띄어쓰기** + +- 맞춤법 규칙은 각 언어에 대한 띄어쓰기를 정의합니다. 왜냐하면 띄어쓰기는 모든 곳에서 사용되기 때문입니다. 맞춤법 규칙은 가장 구별되는 요소 중 일부이며 띄어쓰기는 가장 잘못 번역된 요소 중 일부입니다. +- 영어와 다른 언어 사이의 띄어쓰기의 몇 가지 일반적인 차이점: + - 측정 단위 및 통화 앞 띄어쓰기(예: USD, EUR, kB, MB) + - 온도 기호 앞 띄어쓰기(예: °C, ℉) + - 일부 구두점 앞 띄어쓰기, 특히 줄임표(…) + - 빗금(/) 앞뒤 띄어쓰기 + +**목록** + +- 모든 언어에는 목록 작성에 대한 다양하고 복합한 규칙이 있습니다. 목록 작성은 영어와 상당히 다를 수 있습니다. +- 일부 언어는 각 새 행의 첫 단어를 대문자로 써야 하는 반면, 다른 언어에서는 새 행은 소문자로 시작해야 합니다. 또한 많은 언어는 각 행의 길이에 따라 목록의 대문자에 대한 다른 규칙을 가지고 있습니다. +- 행 항목의 구두점도 동일하게 적용됩니다. 목록의 끝 구두점은 언어에 따라 마침표(.), 쉼표(,) 또는 쌍반점(;)일 수 있습니다. + +**따옴표** + +- 언어는 다양한 따옴표를 사용합니다. 단순히 원문에서 영어 따옴표를 복사하는 것은 종종 부정확합니다. +- 따옴표의 가장 일반적인 유형은 다음과 같습니다: + - „예시 텍스트“ + - ‚예시 텍스트’ + - »예시 텍스트« + - “예시 텍스트” + - ‘예시 텍스트’ + - «예시 텍스트» + +**붙임표와 줄표** + +- 영어에서 붙임표(-)는 단어나 단어의 다른 부분을 연결하는 데 사용되며 줄표(–)는 범위 또는 일시 중지를 나타내는 데 사용됩니다. +- 많은 언어에는 준수해야 하는 붙임표와 줄표 사용에 대한 다른 규칙이 있습니다. + +### 형식 {#formats} + +**숫자** + +- 다른 언어로 숫자를 쓸 때의 주요 차이점은 소수와 천 단위에 사용되는 구분 기호입니다. 숫자 천의 경우 마침표, 쉼표 또는 띄어쓰기가 될 수 있습니다. 유사하게 일부 언어에서는 소수점을 사용하는 반면 다른 언어에서는 소수점 쉼표를 사용합니다. + - 큰 숫자의 몇 가지 예시: + - 영어 – **1,000.50** + - 스페인어 – **1.000,50** + - 프랑스어 – **1 000,50** +- 숫자를 번역할 때 고려해야 할 또 다른 중요한 사항은 백분율 기호입니다. **100%**, **100 %** 또는 %100과 같이 다양한 방식으로 표기할 수 있습니다. +- 마지막으로, 음수는 언어에 따라 다르게 표시될 수 있습니다.: -100, 100-, (100) 또는 [100] + +**날짜** + +- 날짜를 번역할 때 언어에 따라 여러 고려 사항과 차이점이 있습니다. 여기에는 날짜 형식, 구분 기호, 대문자 및 숫자 앞에 0으로 채우기가 포함됩니다. 또한 전체 날짜와 숫자 날짜 사이에는 차이가 있습니다. + - 다른 날짜 형식의 몇 가지 예시: + - 영어 - 영국 (dd/mm/yyyy) – 1st January, 2022 + - 영어 - 미국 (mm/dd/yyyy) – January 1st, 2022 + - 중국어 (yyyy-mm-dd) – 2022 年 1 月 1 日 + - 프랑스어 (dd/mm/yyyy) – 1er janvier 2022 + - 이탈리아어 (dd/mm/yyyy) – 1º gennaio 2022 + - 독일어 (dd/mm/yyyy) – 1. Januar 2022 + +**통화** + +- 다른 형식, 관례 및 환율으로 인해 통화를 번역하는 것이 어려울 수 있습니다. 원칙적으로, 통화는 출처와 동일하게 유지하세요. 하지만 독자의 편의를 위해 대괄호 안에 현지 통화 및 환율을 추가할 수 있습니다. +- 언어별로 통화를 쓸 때의 주요 차이점은 기호 배치, 소수점 기호: 쉼표 vs. 마침표, 띄어쓰기, 약어 vs. 기호가 있습니다. + - 기호 배치: $100 또는 100$ + - 소수점 기호: 100,50$ 또는 100.50$ + - 띄어쓰기: 100$ 또는 100 $ + - 약어 vs. 기호: 100 $ 또는 100 USD + +**측정 단위** + +- 원칙적으로, 측정 단위는 출처와 동일하게 유지하세요. 국가에서 다른 시스템을 사용하는 경우 대괄호 안에 환산값을 포함할 수 있습니다. +- 측정 단위는 현지화와는 별도로 언어가 이러한 단위에 접근하는 방식의 차이에 주목하는 것도 중요합니다. 가장 큰 차이점은 숫자와 단위 사이의 띄어쓰기이며 언어에 따라 다를 수 있습니다. 예를 들면 100kB vs. 100 kB or 50ºF vs. 50 ºF가 있습니다. + +## 결론 {#conclusion} + +Ethereum.org를 번역한다는 것은 이더리움의 다른면을 배우는데 매우 좋은 기회입니다. + +번역을 할 때, 성급하게 하려 하지 마세요. 편하게 즐기시면 됩니다! + +번역 프로그램에 참여해 주셔서 감사드리며 더 많은 대중들이 이 웹사이트를 이용할 수 있도록 도와주셔서 감사합니다. 이더리움 커뮤니티는 글로벌적이며, 저희는 번역가님이 그 중 하나의 일원이 되주셔서 기쁩니다. diff --git a/public/content/translations/ko/dao/index.md b/public/content/translations/ko/dao/index.md index c62a4b51b7c..0a83e9b70a4 100644 --- a/public/content/translations/ko/dao/index.md +++ b/public/content/translations/ko/dao/index.md @@ -1,24 +1,25 @@ --- -title: 탈중앙화 자율 조직(DAO) -description: 이더리움의 DAO 개요 +title: "다오란 무엇인가요?" +metaTitle: "다오란 무엇인가요? | 탈중앙화된 자율 조직" +description: "이더리움의 DAO 개요" lang: ko template: use-cases emoji: ":handshake:" sidebarDepth: 2 image: /images/use-cases/dao-2.png -alt: 제안에 투표하는 DAO의 표현. -summaryPoint1: 중앙화된 리더십이 없는 회원 소유 커뮤니티. -summaryPoint2: 인터넷에서 낯선 사람과 협업할 수 있는 안전한 방법. -summaryPoint3: 특정 목적을 위해 자금을 넣을 수 있는 안전한 장소. +alt: "제안에 투표하는 DAO의 표현." +summaryPoint1: "중앙화된 리더십이 없는 회원 소유 커뮤니티." +summaryPoint2: "인터넷에서 낯선 사람과 협업할 수 있는 안전한 방법." +summaryPoint3: "특정 목적을 위해 자금을 넣을 수 있는 안전한 장소." --- -## DAO란 무엇입니까? {#what-are-daos} +## DAO란 무엇인가요? {#what-are-daos} -DAO는 공동의 사명을 위해 일하는 집단 소유의, 블록체인 관리 조직입니다. +DAO는 공통된 사명을 위해서 일하는 공동 소유의 조직입니다. DAO는 자금이나 운영을 관리하는 자비로운 리더를 신뢰하지 않고도, 우리가 전 세계의 비슷한 생각을 가진 사람들과 함께 일할 수 있게 해줍니다. 변덕스럽게 자금을 쓸 수 있는 CEO나 장부를 조작할 수 있는 CFO는 없습니다. 대신, 코드에 적용된 블록체인 기반 규칙은 조직의 작동 방식과 자금 사용 방식을 정의합니다. -DAO는 그룹의 승인 없이는 누구도 접근할 수 없는 내장된 자산을 가지고 있습니다. 결정은 조직의 모든 사람이 목소리를 낼 수 있도록 하기 위해 제안과 투표를 통해 이루어지며, 모든 것이 온체인에서 투명하게 진행됩니다. +DAO는 그룹의 승인 없이는 누구도 접근할 수 없는 내장된 자산을 가지고 있습니다. 의사 결정은 제안과 투표에 따라 관리되어 조직의 모든 구성원이 목소리를 낼 수 있도록 보장하며, 모든 과정은 [온체인](/glossary/#onchain)에서 투명하게 진행됩니다. ## DAO가 필요한 이유는 무엇입니까? {#why-dao} @@ -28,37 +29,35 @@ DAO는 그룹의 승인 없이는 누구도 접근할 수 없는 내장된 자 ### 비교 {#dao-comparison} -| 탈중앙화 자율 조직 | 기존의 조직 | -| ------------------------------------------- | ------------------------------------------------- | -| 일반적으로 수평적이고, 완전히 민주화되어 있습니다. | 일반적으로 계층적입니다. | -| 변경 사항을 구현하려면 회원의 투표가 필요합니다. | 구조에 따라 단독 주체가 변경을 요구하거나 투표가 제안될 수 있습니다. | -| 투표가 집계되고, 결과는 신뢰할 수 있는 중개자 없이 자동으로 구현됩니다. | 투표가 시행되는 경우, 투표는 내부적으로 집계되고 투표 결과는 수동으로 처리해야 합니다. | +| 탈중앙화 자율 조직 | 기존의 조직 | +| ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | +| 일반적으로 수평적이고, 완전히 민주화되어 있습니다. | 일반적으로 계층적입니다. | +| 변경 사항을 구현하려면 회원의 투표가 필요합니다. | 구조에 따라 단독 주체가 변경을 요구하거나 투표가 제안될 수 있습니다. | +| 투표가 집계되고, 결과는 신뢰할 수 있는 중개자 없이 자동으로 구현됩니다. | 투표가 시행되는 경우, 투표는 내부적으로 집계되고 투표 결과는 수동으로 처리해야 합니다. | | 제공되는 서비스는 탈중앙화된 방식으로 자동 처리됩니다(예: 자선 기금 분배). | 사람이 직접 처리하거나 중앙에서 제어되는 자동화가 필요하며 조작하기 쉽습니다. | -| 모든 활동은 투명하고 완전히 공개됩니다. | 활동은 일반적으로 비공개로 이루어지며 공개에 제한적입니다. | +| 모든 활동은 투명하고 완전히 공개됩니다. | 활동은 일반적으로 비공개로 이루어지며 공개에 제한적입니다. | ### DAO 예시 {#dao-examples} 이해를 더 돕기 위해 다음은 DAO를 사용하는 방법에 대한 몇 가지 예시입니다. -- 자선 활동 – 전 세계 모든 사람의 기부를 수락하고 기금의 원천에 대해 투표할 수 있습니다. -- 집합적 소유권 – 물리적 또는 디지털 자산을 구매할 수 있으며, 회원은 사용 방법에 대해 투표할 수 있습니다. -- 벤처 및 보조금 - 투자 자본을 모으고 벤처에 대한 투표를 지원하는 벤처 펀드를 만들 수 있습니다. 상환된 금액은 나중에 DAO 회원들에게 재분배될 수 있습니다. +- **자선 단체** – 전 세계 누구에게나 기부를 받고 어떤 활동에 자금을 지원할지 투표할 수 있습니다. +- **집단 소유권** – 물리적 또는 디지털 자산을 구매하고 구성원들은 그것을 어떻게 사용할 것인지에 대해 투표할 수 있습니다. +- **벤처 및 보조금** – 투자 자금을 모아 지원할 벤처를 투표로 결정하는 벤처 펀드를 만들 수 있습니다. 상환된 금액은 나중에 DAO 회원들에게 재분배될 수 있습니다. + + ## DAO는 어떻게 작동하나요? {#how-daos-work} -DAO의 중추는 조직의 규칙을 정의하고 그룹의 자금을 보유하는 스마트 계약입니다. 이더리움에서 계약이 실행되면 투표 외에는 누구도 규칙을 변경할 수 없습니다. 코드에 있는 규칙과 논리에서 다루지 않는 작업을 누군가 실행하려고 하면 실패합니다. 재무 또한 스마트 계약에 의해 정의되기 때문에 그룹의 승인 없이는 누구도 돈을 쓸 수 없습니다. 이는 DAO가 중앙 권한을 필요로 하지 않는다는 것을 의미합니다. 대신 그룹에서 공동으로 결정을 내리며 투표에서 통과되면 결제는 자동으로 승인됩니다. +DAO의 핵심은 조직의 규칙을 정의하고 그룹의 자금을 보관하는 [스마트 계약](/glossary/#smart-contract)입니다. 이더리움에서 계약이 실행되면 투표 외에는 누구도 규칙을 변경할 수 없습니다. 코드에 있는 규칙과 논리에서 다루지 않는 작업을 누군가 실행하려고 하면 실패합니다. 재무 또한 스마트 계약에 의해 정의되기 때문에 그룹의 승인 없이는 누구도 돈을 쓸 수 없습니다. 이는 DAO가 중앙 권한을 필요로 하지 않는다는 것을 의미합니다. 대신 그룹에서 공동으로 결정을 내리며 투표에서 통과되면 결제는 자동으로 승인됩니다. 이것은 스마트 계약이 이더리움에서 실행되면 변조가 불가능하기 때문에 가능합니다. 모든 것은 공개되어 있기 때문에 다른 사람들이 눈치채지 못하게 코드(DAO 규칙)를 편집할 수 없습니다. - - 스마트 계약에 대한 자세한 정보 - - ## 이더리움과 DAO {#ethereum-and-daos} 이더리움은 여러 가지 이유로 DAO의 완벽한 기반입니다. -- 이더리움 자체의 합의는 조직이 네트워크를 신뢰할 수 있을 만큼 충분히 분산되어있고, 형성되어 있습니다. +- 이더리움의 자체 합의는 탈중앙화되어 있으며, 조직들이 네트워크를 신뢰할 만큼 충분히 확립되어 있습니다. - 스마트 계약 코드는 이더리움에서 일단 활성화되면 소유자일지라도 수정할 수 없습니다. 이는 DAO가 프로그래밍된 규칙에 따라 실행될 수 있게 합니다. - 스마트 계약은 자금을 보내고 받을 수 있습니다. 이것이 없다면 그룹 자금을 관리하기 위해 신뢰할 수 있는 중개자가 필요합니다. - 이더리움 커뮤니티는 경쟁보다 협력적임이 입증되었으며, 모범 사례와 지원 시스템이 빠르게 등장할 수 있게 합니다. @@ -73,27 +72,25 @@ DAO의 중추는 조직의 규칙을 정의하고 그룹의 자금을 보유하 #### 유명한 예시 {#governance-example} -[ENS](https://claim.ens.domains/delegate-ranking) – ENS 보유자는 그들을 대표할 참여 커뮤니티 구성원에게 투표를 위임할 수 있습니다. - -### 자동 거래 거버넌스 {#governance-example} +### 자동 트랜잭션 거버넌스 {#governance-example} 많은 DAO에서는 구성원의 정족수가 찬성하면 거래가 자동으로 실행됩니다. #### 유명한 예시 {#governance-example} -[Noun](https://nouns.wtf) –Noun DAO에서는 설립자가 거부하지 않는 한 투표 정족수가 충족되고 과반수가 찬성하면 트랜잭션이 자동으로 실행됩니다. +[Nouns](https://nouns.wtf) – Nouns DAO에서는 투표 정족수가 충족되고 과반수가 찬성하면, 창립자가 거부권을 행사하지 않는 한 트랜잭션이 자동으로 실행됩니다. -### 다중서명 거버넌스 {#governance-example} +### 다중 서명 거버넌스 {#governance-example} -DAO에는 수천 명의 의결권을 가진 회원이 있을 수 있지만, 자금은 신뢰할 수 있고 일반적으로 공개된(커뮤니티에 알려진 공개 ID) 5~20명의 활동적인 커뮤니티 회원이 공유하는 지갑에 있을 수 있습니다. 투표이후에 다중서명자가 커뮤니티의 의지를 실행하게 됩니다. +DAO에는 수천 명의 투표 구성원이 있을 수 있지만, 자금은 신뢰할 수 있고 일반적으로 신원이 공개된(커뮤니티에 알려진 공개 신원) 5-20명의 활성 커뮤니티 구성원이 공유하는 [지갑](/glossary/#wallet)에 보관될 수 있습니다. 투표 후, [다중 서명](/glossary/#multisig) 서명자들이 커뮤니티의 의사를 실행합니다. -## DAO 법 {#dao-laws} +## DAO 법률 {#dao-laws} 1977년 와이오밍 주에서 기업가를 보호하고 책임을 제한하는 유한책임회사를 고안했습니다. 더 최근에는 DAO의 법적 상태를 확립하는 DAO 법을 제정하기도 했습니다. 현재 와이오밍, 버몬트 및 버진 아일랜드에는 어떤 형태로든 DAO 법률이 존재합니다. ### 유명한 예시 {#law-example} -[CityDAO](https://citizen.citydao.io/) - CityDAO는 와이오밍의 DAO 법을 사용하여 옐로스톤 국립공원 근처의 40에이커의 땅을 구입했습니다. +[CityDAO](https://citizen.citydao.io/) – CityDAO는 와이오밍의 DAO 법을 이용해 옐로스톤 국립공원 근처의 토지 40에이커를 매입했습니다. ## DAO 멤버십 {#dao-membership} @@ -101,15 +98,15 @@ DAO 멤버십에는 다양한 모델이 있습니다. 멤버십은 투표 방식 ### 토큰 기반 멤버십 {#token-based-membership} -사용되는 토큰에 따라 일반적으로 완전한 권한이 없습니다. 대부분 이러한 거버넌스 토큰은 탈중앙화 거래소에서 허가 없이 거래될 수 있습니다. 나머지는 유동성 또는 기타 '작업 증명'을 제공하여 벌어야 합니다. 어느 방식이든, 단순히 토큰을 보유하면 투표에 대한 접근 권한이 부여됩니다. +사용되는 토큰에 따라 일반적으로 완전히 [무허가형](/glossary/#permissionless)입니다. 대부분의 경우 이러한 거버넌스 토큰은 [탈중앙화 거래소](/glossary/#dex)에서 무허가로 거래될 수 있습니다. 나머지는 유동성 또는 기타 '작업 증명'을 제공하여 벌어야 합니다. 어느 방식이든, 단순히 토큰을 보유하면 투표에 대한 접근 권한이 부여됩니다. _일반적으로 광범위한 분산 프로토콜 및/또는 토큰 자체를 관리하는 데 사용됩니다._ #### 유명한 예시 {#token-example} -[MakerDAO](https://makerdao.com) – MakerDAO의 토큰 MKR은 탈중앙화 거래소에서 널리 사용 가능하며, 누구나 구매하여 Maker 프로토콜의 미래에 대한 투표권을 가질 수 있습니다. +[MakerDAO](https://makerdao.com) – MakerDAO의 토큰 MKR은 탈중앙화 거래소에서 널리 사용 가능하며, 누구나 구매를 통해 Maker 프로토콜의 미래에 대한 투표권을 가질 수 있습니다. -### 주식 기반 멤버십 {#share-based-membership} +### 지분 기반 멤버십 {#share-based-membership} 주식 기반 DAO는 더 많은 권한이 있지만, 여전히 열려 있습니다. DAO 가입 희망자는 누구나 DAO에 가입하기 위한 제안을 제출할 수 있으며, 보통 토큰이나 작업의 형태로 어느 정도의 가치를 제공할 수 있습니다. 주식은 직접 의결권과 소유권을 나타냅니다. 회원들은 비례적 지분을 가지고 언제든지 탈퇴할 수 있습니다. @@ -117,49 +114,54 @@ _일반적으로 자선 단체, 근로자 집단 및 투자 클럽과 같이 보 #### 유명한 예시 {#share-example} -[MolochDAO](http://molochdao.com/) - MolochDAO는 이더리움 프로젝트 펀딩에 중점을 두고 있습니다. 그룹에서는 잠재적 수혜자가 정보를 바탕으로 판단을 하는 데 필요한 전문 지식과 자본이 있는지 평가할 수 있도록 멤버십 제안을 요구합니다. 공개 시장에서 단순히 DAO에 대한 액세스 권한을 구매할 수는 없습니다. +[MolochDAO](http://molochdao.com/) – MolochDAO는 이더리움 프로젝트 자금 지원에 중점을 둡니다. 그룹에서는 잠재적 수혜자가 정보를 바탕으로 판단을 하는 데 필요한 전문 지식과 자본이 있는지 평가할 수 있도록 멤버십 제안을 요구합니다. 공개 시장에서 단순히 DAO에 대한 액세스 권한을 구매할 수는 없습니다. ### 평판 기반 멤버십 {#reputation-based-membership} -평판은 참여 사실을 나타내며 DAO에서 투표할 수 있는 권한을 제공합니다. 토큰 또는 주식 기반 멤버십과 다르게 평판 기반 DAO는 기여자에게 소유권을 이전하지 않습니다. 평판은 구매하거나 이전 또는 임의로 부여될 수 없으며 DAO 구성원이 참여를 통해 직접 획득해야 합니다. 온체인 투표에는 권한이 필요하지 않아 원하는 구성원은 자유롭게 DAO 가입 신청을 제출하고 기여에 대한 보상으로 거래소에서 평판과 토큰을 받도록 요청할 수 있습니다. +평판은 참여 사실을 나타내며 DAO에서 투표할 수 있는 권한을 제공합니다. 토큰 또는 주식 기반 멤버십과 다르게 평판 기반 DAO는 기여자에게 소유권을 이전하지 않습니다. 평판은 구매하거나 이전 또는 임의로 부여될 수 없으며 DAO 구성원이 참여를 통해 직접 획득해야 합니다. 온체인 투표는 별도 허가 없이 진행되며, 예비 회원은 자유롭게 다오 가입과 관련된 제안을 제출할 수 있습니다. 또한, 기여에 따라 명성과 토큰을 보상으로 받을 수 있도록 요청할 수 있습니다. -_보통은 분산형 개발 및 프로토콜, 디앱의 운영 방식에 사용되지만, 자선 단체, 노동자 집단, 투자 동아리 등의 다양한 용도의 조직에도 적합합니다._ +_일반적으로 프로토콜과 [탈중앙화앱](/glossary/#dapp)의 탈중앙화된 개발 및 거버넌스에 사용되지만, 자선 단체, 노동자 조합, 투자 클럽 등 다양한 조직에도 적합합니다._ #### 유명한 예시 {#reputation-example} -[DXdao](https://DXdao.eth.link) – DXdao는 세계적인 주권 집합체이며 2019년부터 분산형 프로토콜 및 애플리케이션을 운영해오고 있습니다. 자금을 조정하고 관리하기 위해 평판 기반 운영 방식과 홀로그래픽 합의 메커니즘을 활용하는데, 이는 그 누구도 미래에 영향을 미칠 수 없음을 의미합니다. +[DXdao](https://DXdao.eth.limo) – DXdao는 2019년부터 탈중앙화 프로토콜과 애플리케이션을 구축하고 관리하는 글로벌 주권 집단이었습니다. 평판 기반 거버넌스와 [홀로그래픽 합의](/glossary/#holographic-consensus)를 활용하여 자금을 조정하고 관리했으며, 이는 누구도 돈으로 미래나 거버넌스에 영향력을 행사할 수 없음을 의미합니다. -## DAO 가입/시작 {#join-start-a-dao} +## DAO 가입 / 시작하기 {#join-start-a-dao} ### DAO 가입하기 {#join-a-dao} - [이더리움 커뮤니티 DAO](/community/get-involved/#decentralized-autonomous-organizations-daos) - [DAOHaus의 DAO 목록](https://app.daohaus.club/explore) -- [Tally.xyz DAO 명단](https://www.tally.xyz) +- [Tally.xyz의 DAO 목록](https://www.tally.xyz/explore) +- [DeGov.AI의 DAO 목록](https://apps.degov.ai/) ### DAO 시작하기 {#start-a-dao} -- [DAOHaus로 DAO 호출](https://app.daohaus.club/summon) -- [Tally로 거버너 DAO 시작하기](https://www.tally.xyz/add-a-dao) -- [Aragon 기반 DAO 만들기](https://aragon.org/product) +- [DAOHaus로 DAO 소환하기](https://app.daohaus.club/summon) +- [Tally로 거버너 DAO 시작하기](https://www.tally.xyz/get-started) +- [Aragon으로 DAO 생성하기](https://aragon.org/product) - [콜로니 시작하기](https://colony.io/) -- [DAOstack의 홀로그램 합의를 이용하여 DAO 만들기](https://alchemy.daostack.io/daos/create) +- [DAOstack의 홀로그래픽 합의로 DAO 생성하기](https://alchemy.daostack.io/daos/create) +- [DeGov Launcher로 DAO 실행하기](https://docs.degov.ai/integration/deploy) + +## 더 읽어보기 {#further-reading} + +### DAO 관련 문서 {#dao-articles} -## 더 읽을거리 {#further-reading} +- [DAO란 무엇인가?](https://aragon.org/dao) – [Aragon](https://aragon.org/) +- [House of DAOs](https://wiki.metagame.wtf/docs/great-houses/house-of-daos) – [Metagame](https://wiki.metagame.wtf/) +- [DAO란 무엇이며, 어떤 용도로 사용되는가?](https://daohaus.substack.com/p/-what-is-a-dao-and-what-is-it-for) – [DAOhaus](https://daohaus.club/) +- [DAO 기반 디지털 커뮤니티 시작하는 방법](https://daohaus.substack.com/p/four-and-a-half-steps-to-start-a) – [DAOhaus](https://daohaus.club/) +- [DAO란 무엇인가?](https://coinmarketcap.com/alexandria/article/what-is-a-dao) – [Coinmarketcap](https://coinmarketcap.com) +- [홀로그래픽 합의란 무엇인가?](https://medium.com/daostack/holographic-consensus-part-1-116a73ba1e1c) - [DAOstack](https://daostack.io/) +- [DAO는 기업이 아니다: 자율 조직에서 탈중앙화가 중요한 이유 by Vitalik](https://vitalik.eth.limo/general/2022/09/20/daos.html) +- [DAO, DAC, DA 등: 불완전한 용어 안내서](https://blog.ethereum.org/2014/05/06/daos-dacs-das-and-more-an-incomplete-terminology-guide) - [이더리움 블로그](https://blog.ethereum.org) -### DAO 기사 {#dao-articles} +### 동영상 {#videos} -- [DAO란?](https://aragon.org/dao) – [Aragon](https://aragon.org/) -- [DAO 핸드북](https://daohandbook.xyz) -- [DAO의 집](https://wiki.metagame.wtf/docs/great-houses/house-of-daos) – [Metagame](https://wiki.metagame.wtf/) -- [DAO란 무엇이며 무엇을 위한 것일까요?](https://daohaus.substack.com/p/-what-is-a-dao-and-what-is-it-for) – [DAOhaus](https://daohaus.club/) -- [DAO 기반 디지털 커뮤니티를 시작하는 방법](https://daohaus.substack.com/p/four-and-a-half-steps-to-start-a) – [DAOhaus](https://daohaus.club/) -- [DAO란?](https://coinmarketcap.com/alexandria/article/what-is-a-dao) – [Coinmarketcap](https://coinmarketcap.com) -- [홀로그램 합의란 무엇인가요?](https://medium.com/daostack/holographic-consensus-part-1-116a73ba1e1c) - [DAOstack](https://daostack.io/) -- [DAO는 기업이 아닙니다: 비탈릭의 자율적 조직의 탈중앙화가 중요한 이유](https://vitalik.eth.limo/general/2022/09/20/daos.html) -- [DAO, DAC, DA 그리고...: 완성되지 않은 용어 가이드](https://blog.ethereum.org/2014/05/06/daos-dacs-das-and-more-an-incomplete-terminology-guide) - [이더리움 블로그](https://blog.ethereum.org) +- [암호화폐에서 DAO란 무엇인가?](https://youtu.be/KHm0uUPqmVE) +- [DAO가 도시를 건설할 수 있을까?](https://www.ted.com/talks/scott_fitsimones_could_a_dao_build_the_next_great_city) – [TED](https://www.ted.com/) -### 영상 {#videos} + -- [암호화에서 DAO란 무엇입니까?](https://youtu.be/KHm0uUPqmVE) -- [DAO가 도시를 건설할 수 있을까요?](https://www.ted.com/talks/scott_fitsimones_could_a_dao_build_the_next_great_city) - [TED](https://www.ted.com/) + diff --git a/public/content/translations/ko/decentralized-identity/index.md b/public/content/translations/ko/decentralized-identity/index.md index 3a10643af6a..aec48bc60f2 100644 --- a/public/content/translations/ko/decentralized-identity/index.md +++ b/public/content/translations/ko/decentralized-identity/index.md @@ -1,25 +1,27 @@ --- -title: 분산 신원 증명 -description: 분산 신원 증명이란 무엇이며, 왜 중요할까요? +title: "분산 신원 증명" +description: "분산 신원 증명이란 무엇이며, 왜 중요할까요?" lang: ko template: use-cases emoji: ":id:" sidebarDepth: 2 image: /images/eth-gif-cat.png -summaryPoint1: 기존의 신원 증명 시스템은 식별자의 발급, 점검, 제어를 한 곳으로 집중시켰습니다. -summaryPoint2: 분산 신원 증명을 사용하면 더 이상 중앙화된 제3자에 의존할 필요가 없어집니다. -summaryPoint3: 암호화폐 덕분에 사용자는 다시 한 번 자신의 식별자와 증명 정보를 발급, 소유, 제어할 도구를 갖게 되었습니다. +summaryPoint1: "기존의 신원 증명 시스템은 식별자의 발급, 점검, 제어를 한 곳으로 집중시켰습니다." +summaryPoint2: "분산 신원 증명을 사용하면 더 이상 중앙화된 제3자에 의존할 필요가 없어집니다." +summaryPoint3: "암호화폐 덕분에 사용자는 다시 한 번 자신의 식별자와 증명 정보를 발급, 소유, 제어할 도구를 갖게 되었습니다." --- 오늘날 신원 증명은 사실상 삶의 모든 부분을 뒷받침하고 있습니다. 온라인 서비스 이용, 은행 계좌 개설, 선거 투표, 재산 구매, 고용 보장 등 이 모든 활동에는 신원 증명이 필요합니다. -그러나 기존 신원 관리 시스템은 오랜 기간동안 중앙 집권적인 중개자에게 의존해 왔으며, 중개자가 귀하의 신원과 인증 정보를 발급, 소유 및 [증명](#what-are-attestations)했습니다. 즉, 귀하의 신원 관련 정보를 직접 관리하거나 개인 식별 정보(PII)에 누가 얼마나 접근할 수 있는지 또한 귀하가 제어할 수 없다는 것을 의미합니다. +그러나 기존의 신원 관리 시스템은 오랫동안 사용자의 식별자와 [증명](/glossary/#attestation)을 발급, 보유, 관리하는 중앙화된 중개 기관에 의존해 왔습니다. 즉, 귀하의 신원 관련 정보를 직접 관리하거나 개인 식별 정보(PII)에 누가 얼마나 접근할 수 있는지 또한 귀하가 제어할 수 없다는 것을 의미합니다. -이 문제를 해결하기 위해 이더리움과 같은 공개 블록체인에 분산 신원 증명 시스템이 도입되었습니다. 분산 신원 증명으로 개인이 직접 자신의 신원 관련 정보를 관리할 수 있습니다. 분산 신원 증명 솔루션을 통해 서비스 제공자나 정부 등 중앙 기관에 의존하지 않고도 자신의 식별자를 *직접* 제작하고 인증 정보를 획득, 소유할 수 있습니다. +이 문제를 해결하기 위해 이더리움과 같은 공개 블록체인에 분산 신원 증명 시스템이 도입되었습니다. 분산 신원 증명으로 개인이 직접 자신의 신원 관련 정보를 관리할 수 있습니다. 탈중앙화 신원 솔루션을 사용하면 서비스 제공업체나 정부와 같은 중앙 기관에 의존하지 않고도 사용자가 직접 식별자를 만들고 증명을 요청하고 보유할 수 있습니다. ## 신원이란 무엇인가요? {#what-is-identity} -신원은 개인의 고유한 정보를 바탕으로 정의되는 개인 증명 수단입니다. 신원은 _개인_, 즉 구별되는 인간 개체를 의미합니다. 또한 신원은 조직이나 기관과 같은 인간이 아닌 주체를 의미할 수도 있습니다. +신원은 개인의 고유한 정보를 바탕으로 정의되는 개인 증명 수단입니다. 신원은 _개인_, 즉 구별되는 인간 개체임을 의미합니다. 또한 신원은 조직이나 기관과 같은 인간이 아닌 주체를 의미할 수도 있습니다. + + ## 식별자란 무엇인가요? {#what-are-identifiers} @@ -31,31 +33,97 @@ summaryPoint3: 암호화폐 덕분에 사용자는 다시 한 번 자신의 식 - 생년월일 및 출생지 - 이메일 주소, 사용자 이름, 프로필 사진 등의 디지털 신원 정보 -이러한 기존 식별자는 중앙 기관에 의해 발급, 소유, 관리됩니다. 이름을 바꾸기 위해서는 정부의 허가가 필요하고, 닉네임을 바꾸기 위해서는 소셜 미디어 플랫폼의 허가를 받아야 합니다. +이러한 기존 식별자는 중앙 기관에 의해 발급, 소유, 관리됩니다. 이름을 바꾸기 위해서는 정부의 허가가 필요하고, 핸들을 바꾸기 위해서는 소셜 미디어 플랫폼의 허가를 받아야 합니다. + +## 탈중앙화 신원의 이점 {#benefits-of-decentralized-identity} + +1. 분산형 신원 증명은 식별하는 정보에 대한 개인의 관리 권한을 강화합니다. 분산형 식별 정보 및 증명은 중앙 집권적인 기관이나 제3자 서비스에 의존하지 않고도 확인될 수 있습니다. + +2. 탈중앙화 신원 솔루션은 사용자 신원을 확인하고 관리하기 위한 무신뢰, 원활, 개인 정보 보호 방법을 용이하게 합니다. + +3. 분산형 신원 증명은 블록체인 기술을 활용함으로써, 서로 다른 주체 간에 신뢰 관계를 구축하고, 증명의 유효성을 검증할 수 있는 암호화 기법을 제공합니다. + +4. 분산형 신원 증명은 신원 데이터를 휴대 가능하도록 합니다. 사용자는 모바일 지갑에 증명과 식별자를 저장하고 원하는 모든 당사자와 공유할 수 있습니다. 분산형 식별 정보와 증명은 발행 기관의 특정 데이터베이스에 고정되지 않습니다. + +5. 탈중앙화 신원은 개인이 소유하거나 수행한 것을 공개하지 않고도 증명할 수 있게 해주는 새로운 [영지식](/glossary/#zk-proof) 기술과 잘 작동해야 합니다. 이는 투표와 같은 애플리케이션에 대한 신뢰와 개인 정보를 결합하는 강력한 방법이 될 수 있습니다. + +6. 탈중앙화 신원은 한 명의 개인이 시스템을 악용하거나 스팸을 보내기 위해 여러 사람인 척하는 경우를 식별하는 [안티시빌](/glossary/#anti-sybil) 메커니즘을 가능하게 합니다. + +## 탈중앙화 신원 사용 사례 {#decentralized-identity-use-cases} + +분산형 신원 증명은 다양한 곳에 사용될 수 있습니다. + +### 1. 범용 로그인 {#universal-dapp-logins} + +분산형 신원 증명은 비밀번호 기반 로그인을 탈중앙화 인증으로 대체할 수 있게 합니다. 서비스 제공자는 사용자에게 증명을 발행할 수 있으며, 해당 증명은 이더리움 지갑에 저장됩니다. 증명의 예시로는 보유자에게 온라인 커뮤니티에 대한 접근 권한을 부여하는 [NFT](/glossary/#nft)가 있습니다. + +[이더리움으로 로그인](https://siwe.xyz/) 기능은 서버가 사용자의 이더리움 계정을 확인하고 계정 주소에서 필요한 증명을 가져올 수 있도록 합니다. 즉, 사용자는 긴 비밀번호를 기억하지 않고도 플랫폼이나 웹사이트에 액세스할 수 있으며, 이는 사용자의 온라인 환경을 향상합니다. + +### 2. KYC 인증 {#kyc-authentication} + +다양한 온라인 서비스를 사용하려면 개인은 운전면허증이나 여권과 같은 증명을 제공해야 합니다. 이러한 방식은 사용자의 개인 정보가 노출될 수 있고, 서비스 제공 업체가 자체적으로 증명을 인증할 수 없다는 문제가 있을 수 있습니다. + +탈중앙화 신원을 통해 회사는 기존의 [고객신원확인(KYC)](https://en.wikipedia.org/wiki/Know_your_customer) 절차를 건너뛰고 검증 가능한 자격 증명을 통해 사용자 신원을 인증할 수 있습니다. 이는 신원 관리 비용을 절감하는 한편 허위 문서의 사용 등을 방지합니다. + +### 3. 투표 및 온라인 커뮤니티 {#voting-and-online-communities} + +온라인 투표와 소셜 미디어는 분산형 신원 증명을 사용한 가장 놀라운 예시입니다. 온라인 투표는 특히 악의적인 사용자가 허위 신원을 만들어서 투표할 수 있기 때문에 조작에 취약합니다. 이때 개인이 온체인 증명을 제공하도록 요청한다면 온라인 투표 과정의 신뢰도를 개선할 수 있을 것입니다. + +분산형 신원 증명은 허위 계정이 불가능한 온라인 커뮤니티를 만들 수 있게 지원합니다. 예를 들어, 각 사용자가 ENS(이더리움 이름 서비스) 등의 온체인 신원 증명 시스템을 사용하여 신원을 증명하게 함으로써 허위 계정을 막을 수 있습니다. + +### 4. 안티시빌 보호 {#sybil-protection} + +[이차 투표](/glossary/#quadratic-voting)를 사용하는 보조금 지급 애플리케이션은 더 많은 개인이 투표할수록 보조금의 가치가 증가하여 사용자가 여러 신원으로 기여를 분할하도록 유도하므로 [시빌 공격](/glossary/#sybil-attack)에 취약합니다. 분산형 신원 증명은 특정 개인 정보를 공개하도록 요구하지 않는 경우가 많지만, 각 참가자가 실제 사용자임을 증명해야 하는 부담을 줌으로써 이를 방지하는 데 도움이 됩니다. + +### 5. 국가 및 정부 ID {#national-and-government-id} + +정부는 탈중앙화 신원의 원칙을 사용하여 국가 ID, 여권 또는 운전면허증과 같은 기본적인 신원 문서를 이더리움에서 검증 가능한 자격 증명으로 발급하여 온라인 신원 확인에서 사기 및 위조를 줄이기 위한 강력한 암호학적 진위 보증을 제공할 수 있습니다. 시민은 이러한 증명을 개인 [지갑](/wallets/)에 저장하고 이를 사용하여 자신의 신원, 연령 또는 투표권을 증명할 수 있습니다. + +이 모델은 특히 [영지식 증명(ZKP)](/zero-knowledge-proofs/) 개인정보 보호 기술과 결합될 때 선택적 공개를 허용합니다. 예를 들어, 시민은 연령 제한 서비스에 접근하기 위해 정확한 생년월일을 공개하지 않고도 18세 이상임을 암호학적으로 증명할 수 있으며, 이는 기존 ID보다 더 큰 개인정보 보호를 제공합니다. + +#### 💡사례 연구: 이더리움 기반 부탄 국가 디지털 ID(NDI) {#case-study-bhutan-ndi} + +- 부탄의 약 80만 시민에게 검증 가능한 신원 자격 증명에 대한 접근을 제공합니다. +- 2025년 10월에 폴리곤 네트워크에서 [이더리움 메인넷](https://www.bhutanndi.com/article/bhutan-adopts-ethereum-for-national-identity-a-new-chapter-in-digital-sovereignty_2d0c7ec2-5605-4c42-b258-bd9361ae8878)으로 마이그레이션했습니다. +- 2025년 3월 기준 [234,000개 이상의 디지털 ID](https://www.blockchain-council.org/blockchain/bhutan-uses-blockchain-in-digital-id-project/) 발급 + +부탄 왕국은 2025년 10월에 [국가 디지털 신원(NDI) 시스템을 이더리움으로 마이그레이션했습니다](https://www.bhutanndi.com/article/bhutan-adopts-ethereum-for-national-identity-a-new-chapter-in-digital-sovereignty_2d0c7ec2-5605-4c42-b258-bd9361ae8878). 탈중앙화 신원 및 자기 주권 신원의 원칙에 따라 구축된 부탄의 NDI 시스템은 탈중앙화 식별자와 검증 가능한 자격 증명을 사용하여 시민의 개인 지갑에 직접 디지털 서명된 자격 증명을 발급합니다. 이러한 자격 증명의 암호학적 증명을 이더리움에 고정함으로써 시스템은 자격 증명이 진짜이고 변조 방지되며 중앙 기관에 질의하지 않고도 모든 당사자가 확인할 수 있도록 보장합니다. + +이 시스템의 아키텍처는 [영지식 증명(ZKP)](/zero-knowledge-proofs/) 기술을 사용하여 개인정보 보호를 강조합니다. 이 '선택적 공개' 구현을 통해 시민은 전체 ID 번호나 정확한 생년월일과 같은 기본 개인 데이터를 공개하지 않고도 특정 사실(예: '나는 18세 이상입니다' 또는 '나는 시민입니다')을 증명하여 서비스에 접근할 수 있습니다. 이는 안전하고 사용자 중심적이며 개인정보를 보호하는 국가 ID 시스템을 위한 이더리움의 강력한 실제 사용 사례를 보여줍니다. + +#### 💡사례 연구: 이더리움 [레이어 2](/layer-2/) ZKSync Era 기반 부에노스아이레스시 QuarkID {#case-study-buenos-aires-quarkid} + +- 출시 시점에 [360만 명 이상의 사용자](https://buenosaires.gob.ar/innovacionytransformaciondigital/miba-con-tecnologia-quarkid-la-ciudad-de-buenos-aires-incorporo)에게 탈중앙화 신원 자격 증명 발급 +- QuarkID는 UN 지속가능발전목표에 따라 [디지털 공공재](https://www.digitalpublicgoods.net/r/quarkid)로 인정받은 오픈 소스 프로토콜입니다. +- 시가 프로토콜을 소유하지 않고 시민에게 완전한 데이터 소유권과 개인정보 보호를 제공하는 '[사용자로서의 정부](https://buenosaires.gob.ar/innovacionytransformaciondigital/miba-con-tecnologia-quarkid-la-ciudad-de-buenos-aires-incorporo)' 모델을 강조합니다. + +2024년 부에노스아이레스시 정부(GCBA)는 GCBA의 혁신 및 디지털 전환 사무국이 구축한 오픈 소스 '디지털 신뢰 프레임워크'인 QuarkID를 주민들이 정부 서비스 및 공식 문서에 접근하기 위한 시의 공식 앱인 miBA에 통합했습니다. 출시 시점에 miBA의 360만 명 이상의 모든 사용자에게는 시민권 증명서, 출생, 결혼 및 사망 증명서, 세금 기록, 예방 접종 기록 등을 포함한 검증 가능한 디지털 문서와 인증서를 온체인에서 관리하고 공유할 수 있는 탈중앙화 디지털 신원이 발급되었습니다. + +이더리움 [레이어 2](/layer-2/) 네트워크 ZKSync Era에 구축된 QuarkID 시스템은 ZKP 기술을 사용하여 시민이 불필요한 개인 데이터를 노출하지 않고도 모바일 장치를 통해 P2P로 개인 자격 증명을 확인할 수 있도록 합니다. 이 프로그램은 GCBA가 중앙화된 소유자 역할을 하는 대신 오픈 소스, 상호 운용 가능한 QuarkID 프로토콜의 한 명의 사용자 역할을 하는 '사용자로서의 정부' 모델을 강조합니다. 이 ZKP 지원 아키텍처는 핵심적인 개인정보 보호 기능을 제공합니다. 즉, 제3자, 심지어 GCBA조차도 시민이 언제, 어떻게, 왜 자격 증명을 사용하는지 추적할 수 없습니다. 이 성공적인 프로그램은 시민에게 완전한 자기 주권 신원과 민감한 데이터에 대한 통제권을 제공하며, 이 모든 것은 이더리움의 전 세계적으로 분산된 네트워크에 의해 보호됩니다. ## 증명이란 무엇인가요? {#what-are-attestations} 증명이란 한 개체에 의해 만들어진 다른 개체에 대한 주장입니다. 예를 들어, 미국에 거주하는 경우 미국의 도로 교통 공단(한 주체)에서 발급한 운전 면허증은 본인(다른 주체)이 법적으로 자동차를 운전할 수 있음을 증명합니다. -증명은 식별자와 다릅니다. 증명은 특정 신원을 파악할 수 있도록 신원 정보를 *포함*하며 그 신원과 관련된 정보를 주장합니다. 즉, 운전 면허증은 식별자(성명, 생년월일, 주소)를 포함할 뿐만 아니라 운전할 수 있는 법적 권리에 대한 증명이기도 합니다. +증명은 식별자와 다릅니다. 증명은 특정 신원을 참조하기 위한 식별자를 _포함하며_, 이 신원과 관련된 속성에 대한 주장을 합니다. 즉, 운전 면허증은 식별자(성명, 생년월일, 주소)를 포함할 뿐만 아니라 운전할 수 있는 법적 권리에 대한 증명이기도 합니다. ### 분산 식별자는 무엇인가요? {#what-are-decentralized-identifiers} 법적 이름 또는 이메일 주소 같은 기존 식별자는 정부와 이메일 제공자 같은 제3자에 의존합니다. 분산 식별자(DID)는 다릅니다. 중앙 개체에 의해 발급, 관리, 제어되지 않습니다. -분산 식별자는 개인이 발급, 소유, 관리합니다. [이더리움 계정](/developers/docs/accounts/)은 분산 식별자의 예시입니다. 누군가의 허락 없이 원하는 만큼 많은 계정을 만들 수 있으며, 중앙 저장소에 보관해야 할 필요도 없습니다. +분산 식별자는 개인이 발급, 소유, 관리합니다. [이더리움 계정](/glossary/#account)은 탈중앙화 식별자의 예시입니다. 누군가의 허락 없이 원하는 만큼 많은 계정을 만들 수 있으며, 중앙 저장소에 보관해야 할 필요도 없습니다. -분산 식별자는 분산 원장(블록체인) 또는 P2P 네트워크에 저장됩니다. 이는 DID를 [유일하고, 높은 가용성과 활용성을 지니며, 암호화 검증이 가능](https://w3c-ccg.github.io/did-primer/)하게 만듭니다. 분산 식별자는 개인, 조직 또는 정부 등 다른 개체와 연결될 수 있습니다. +탈중앙화 식별자는 분산 원장([블록체인](/glossary/#blockchain)) 또는 [P2P 네트워크](/glossary/#peer-to-peer-network)에 저장됩니다. 이를 통해 DID는 [전 세계적으로 고유하고, 높은 가용성으로 확인 가능하며, 암호학적으로 검증 가능하게 됩니다](https://w3c-ccg.github.io/did-primer/). 분산 식별자는 개인, 조직 또는 정부 등 다른 개체와 연결될 수 있습니다. ## 분산 식별자는 어떻게 가능한가요? {#what-makes-decentralized-identifiers-possible} -### 1. 공개 키 기반 구조(PKI) {#public-key-cryptography} +### 1. 공개 키 암호화 {#public-key-cryptography} -공개 키 기반 구조(PKI)는 특정 주체를 위해 [공개 키](/glossary/#public-key) 와 [개인 키](/glossary/#private-key)를 생성하는 정보 보안 장치입니다. 공개 키 암호화 기법은 블록체인 네트워크에서 사용자의 신원을 인증하고 디지털 자산의 소유권을 증명하는 용도로 사용됩니다. +공개 키 암호화는 개체를 위해 [공개 키](/glossary/#public-key)와 [개인 키](/glossary/#private-key)를 생성하는 정보 보안 조치입니다. 공개 키 [암호화](/glossary/#cryptography)는 블록체인 네트워크에서 사용자 신원을 인증하고 디지털 자산의 소유권을 증명하는 데 사용됩니다. -이더리움 계정과 같은 일부 분산 식별자에는 공개 키와 개인 키가 있습니다. 공개 키는 계정의 제어자를 식별하는 반면, 개인 키는 이 계정의 메시지에 서명하거나 메시지를 해독할 수 있습니다. PKI는 주체를 인증하는 데 필요한 증명을 제공하고, [암호화 서명](https://andersbrownworth.com/blockchain/public-private-keys/)을 통해 모든 주장을 검증함으로써 명의 도용 및 허위 신원 사용을 방지합니다. +이더리움 계정과 같은 일부 분산 식별자에는 공개 키와 개인 키가 있습니다. 공개 키는 계정의 제어자를 식별하는 반면, 개인 키는 이 계정의 메시지에 서명하거나 메시지를 해독할 수 있습니다. 공개 키 암호화는 [암호화 서명](https://andersbrownworth.com/blockchain/public-private-keys/)을 사용하여 모든 주장을 검증함으로써, 개체를 인증하고 명의 도용 및 가짜 신원 사용을 방지하는 데 필요한 증명을 제공합니다. -### 2. 분산형 데이터 보관 {#decentralized-datastores} +### 2. 탈중앙화 데이터 저장소 {#decentralized-datastores} 블록체인은 검증 가능한 데이터 레지스트리의 역할을 합니다. 즉, 개방되어 있고, (주로 중앙 집권적인) 특정 주체를 신뢰하지 않아도 되며, 탈중앙화된 정보 저장소입니다. 공용 블록체인은 중앙 집권적인 레지스트리에 식별 정보를 저장해야 할 필요를 제거합니다. @@ -65,7 +133,7 @@ summaryPoint3: 암호화폐 덕분에 사용자는 다시 한 번 자신의 식 분산형 신원 증명은 신원 관련 정보는 소유자 본인이 제어하고 보호 및 이동 가능한 형태여야 한다는 아이디어를 분산형 식별 정보와 증명을 주요 기반으로 구현한 것입니다. -분산형 신원 증명의 관점에서 증명(= [검증 가능한 인증 정보](https://www.w3.org/TR/vc-data-model/))이란, 발행자가 만든 위조 불가능하고 암호학적으로 검증 가능한 주장을 말합니다. 한 주체(예: 조직)에서 발급하는 모든 증명 또는 검증 가능한 인증 정보는 해당하는 DID에 연계됩니다. +탈중앙화 신원의 맥락에서, 증명([검증 가능한 자격 증명](https://www.w3.org/TR/vc-data-model/)이라고도 함)은 발행자가 만든 변조 방지 및 암호학적으로 검증 가능한 주장입니다. 한 주체(예: 조직)에서 발급하는 모든 증명 또는 검증 가능한 인증 정보는 해당하는 DID에 연계됩니다. DID는 블록체인에 저장되기 때문에 누구든지 이더리움에서 발급자의 DID를 대조하여 증명의 유효성을 검증할 수 있습니다. 본질적으로 이더리움 블록체인은 특정 주체에 연계된 DID를 인증할 수 있게 하는 글로벌 디렉터리와 같은 역할을 합니다. @@ -73,31 +141,31 @@ DID는 블록체인에 저장되기 때문에 누구든지 이더리움에서 분산형 식별 정보는 또한 분산형 신원 증명을 통해 개인 정보를 보호하는 데에도 중요한 역할을 합니다. 예를 들어, 개인이 증명(운전 면허증 등)을 제출하는 경우 검증하는 주체는 증명에 포함된 정보의 유효성을 확인하지 않아도 됩니다. 대신, 검증자는 증명의 진위와 발급 기관의 신원에 대한 암호화 보증만 확인하면 증명이 유효한지 판단할 수 있습니다. -## 분산형 신원 증명에서 증명 방식의 종류 {#types-of-attestations-in-decentralized-identity} +## 탈중앙화 신원의 증명 유형 {#types-of-attestations-in-decentralized-identity} 이더리움 기반 신원 증명 생태계에서 증명 정보가 보관되고 제공되는 방법은 기존의 신원 관리 시스템과 다릅니다. 분산형 신원 증명 시스템에서 증명을 발급, 저장 및 인증하기 위한 다양한 접근 방식은 다음과 같습니다. -### 오프체인 증명 {#off-chain-attestations} +### 오프체인 증명 {#offchain-attestations} -온체인으로 증명을 저장할 때 발생하는 문제점 중 하나는 해당 정보에 개인이 비공개로 유지하고자 하는 정보가 포함될 수도 있다는 부분입니다. 이더리움 블록체인은 공개적이라는 특성이 있기 때문에 이러한 증명을 저장하기에 부적절해 보일 수 있습니다. +온체인으로 증명을 저장할 때 발생하는 문제점 중 하나는 해당 정보에 개인이 비공개로 유지하고자 하는 정보가 포함될 수도 있다는 것 입니다. 이더리움 블록체인은 공개적이라는 특성이 있기 때문에 이러한 증명을 저장하기에 부적절해 보일 수 있습니다. -이 문제는 사용자가 디지털 지갑에서 오프체인으로 보유하고 있지만 온체인에 저장된 발급자의 DID로 서명된 증명을 발급함으로써 해결할 수 있습니다. 해당하는 증명은 [JSON 웹 토큰](https://en.wikipedia.org/wiki/JSON_Web_Token)으로 인코딩되고 발급자의 디지털 서명을 포함하므로, 간편하게 오프체인 클레임의 인증에 사용될 수 있습니다. +해결책은 사용자들이 오프체인에서 디지털 지갑에 보관할 수 있는 증명을 발급하되, 발급자의 DID(탈중앙화 식별자)는 온체인에 저장하도록 하는 것입니다 이러한 증명은 [JSON 웹 토큰](https://en.wikipedia.org/wiki/JSON_Web_Token)으로 인코딩되며 발행자의 디지털 서명을 포함하므로 오프체인 주장을 쉽게 확인할 수 있습니다. -다음은 오프체인 증명을 설명하는 가상 시나리오입니다. +다음은 오프체인 증명을 설명하는 가상 시나리오입니다: 1. 한 대학교(발급자)가 증명(디지털 학위 증명서)을 생성한 후 대학교의 키로 서명하고, 이를 Bob(ID의 소유자)에게 발급합니다. 2. Bob이 회사에 지원하기 위해 학위를 증명해야 할 때 모바일 지갑에서 해당 증명을 꺼내 회사에 제출할 수 있습니다. 회사(검증자)는 발급자의 DID(예: 이더리움 상의 공개 키)를 확인하여 증명의 유효성을 검증할 수 있습니다. -### 영구 액세스 권한이 있는 오프체인 증명 {#offchain-attestations-with-persistent-access} +### 영구적 접근 권한이 있는 오프체인 증명 {#offchain-attestations-with-persistent-access} -오프체인 인증 방식에서 증명은 JSON 파일로 변환된 후 오프체인(이상적으로는 IPFS 또는 Swarm과 같은 [탈중앙화된 클라우드 스토리지](/developers/docs/storage/) 플랫폼)에 저장됩니다. 한편, 해당 JSON 파일의 [해시](/glossary/#hash) 값은 온체인으로 저장되며 온체인 레지스트리를 통해 DID에 링크됩니다. 연계되는 DID는 해당 증명의 발급자의 것이거나 수신인의 것일 수도 있습니다. +이 방식에서는 증명이 JSON 파일로 변환되어 오프체인(이상적으로는 IPFS 또는 Swarm과 같은 [탈중앙화 클라우드 스토리지](/developers/docs/storage/) 플랫폼)에 저장됩니다. 그러나 JSON 파일의 [해시](/glossary/#hash)는 온체인에 저장되고 온체인 레지스트리를 통해 DID에 연결됩니다. 연계되는 DID는 해당 증명의 발급자의 것이거나 수신인의 것일 수도 있습니다. 이러한 방식은 증명이 블록체인 기반으로 영구 보관되는 동시에 민감한 정보는 암호화되어 필요시 검증할 수 있게 합니다. 또한 해당 증명은 개인 키의 소유자만이 복호화하여 정보를 확인할 수 있으므로, 선택적인 공개를 가능하게 합니다. ### 온체인 증명 {#onchain-attestations} -온체인 증명은 이더리움 블록체인의 [스마트 계약](/developers/docs/smart-contracts/)에서 이루어집니다. 스마트 계약(레지스트리 역할)은 해당하는 온체인의 분산형 식별 정보(공개 키)에 증명을 매핑합니다. +온체인 증명은 이더리움 블록체인의 [스마트 계약](/glossary/#smart-contract)에 보관됩니다. 스마트 컨트랙트(레지스트리 역할)는 해당하는 온 체인의 분산형 식별 정보(공개 키)에 증명을 매핑합니다. 아래는 온체인 증명이 실제로 어떻게 작동하는지를 보여주는 예시입니다. @@ -107,79 +175,44 @@ DID는 블록체인에 저장되기 때문에 누구든지 이더리움에서 3. 주식을 판매하는 스마트 계약은 레지스트리 계약에서 선별된 구매자의 신원을 확인할 수 있으므로 스마트 계약이 누가 주식을 살 수 있는지 여부를 결정할 수 있습니다. -### 소울바운드 토큰과 신원 증명 {#soulbound} - -[소울바운드 토큰](https://vitalik.eth.limo/general/2022/01/26/soulbound.html)(양도 불가한 NFT)은 특정 지갑에 국한된 고유한 정보를 수집하는 데 사용될 수 있습니다. 이는 개인적인 성취(특정 온라인 강의 완료 또는 게임에서 높은 점수 획득 등)나 특정 커뮤니티에 참여 등을 증명하기 위한 토큰과 같은 온체인 신원 증명이 특정 이더리움 주소에만 고유하게 소속될 수 있게 만듭니다. - -## 분산형 신원 증명의 장점 {#benefits-of-decentralized-identity} - -1. 분산형 신원 증명은 식별하는 정보에 대한 개인의 관리 권한을 강화합니다. 분산형 식별 정보 및 증명은 중앙 집권적인 기관이나 제3자 서비스에 의존하지 않고도 확인될 수 있습니다. - -2. 분산형 신원 증명 솔루션은 사용자 신원 관리 및 검증이 더욱 원활하고, 보호적이며, 특정 기관에 대한 신뢰 없이 이루어질 수 있게 합니다. - -3. 분산형 신원 증명은 블록체인 기술을 활용함으로써, 서로 다른 주체 간에 신뢰 관계를 구축하고, 증명의 유효성을 검증할 수 있는 암호화 기법을 제공합니다. - -4. 분산형 신원 증명은 신원 데이터를 휴대 가능하도록 합니다. 사용자는 증명 및 식별 정보를 모바일 지갑에 저장하고, 필요할 때 원하는 상대방과 공유할 수 있습니다. 분산형 식별 정보와 증명은 발행 기관의 특정 데이터베이스에 고정되지 않습니다. - -5. 분산형 신원 증명은 개인이 특정 정보를 공개하지 않고도 자신이 소유하거나 실행한 작업을 증명할 수 있게 하는 새로운 영지식 기술과 원활하게 작동합니다. 이는 투표와 같은 애플리케이션에 대한 신뢰와 개인 정보를 결합하는 강력한 방법이 될 수 있습니다. - -6. 분산형 신원 증명을 통해 반시빌(anti-Sybil) 메커니즘을 사용하여 한 사람이 게임 상에서 여러 사람인 것처럼 속이거나 특정 시스템을 스팸하는 행위를 식별할 수 있습니다. - -## 분산형 신원 증명 사용 사례 {#decentralized-identity-use-cases} - -분산형 신원 증명은 다양한 곳에 사용될 수 있습니다. - -### 1. 보편적 로그인 {#universal-dapp-logins} - -분산형 신원 증명은 비밀번호 기반 로그인을 [탈중앙화 인증](https://docs.verify.ibm.com/verify/docs/use-cases-decentralized-identity)으로 대체할 수 있게 합니다. 서비스 제공자는 사용자에게 증명을 발행할 수 있으며, 해당 증명은 이더리움 지갑에 저장됩니다. 증명의 예시로, 소유자가 특정 온라인 커뮤니티에 액세스할 수 있게 하는 [NFT](/nft/)가 있을 수 있습니다. - -그 후 [이더리움 로그인](https://siwe.xyz/) 기능은 서버가 사용자의 이더리움 계정을 확인하고 해당 계정 주소로부터 필요한 증명 정보를 가져올 수 있도록 합니다. 즉, 사용자는 긴 비밀번호를 기억하지 않고도 플랫폼이나 웹사이트에 액세스할 수 있으며, 이는 사용자의 온라인 환경을 향상합니다. - -### 2. KYC 인증 {#kyc-authentication} - -다양한 온라인 서비스를 사용하려면 개인은 운전면허증이나 여권과 같은 증명을 제공해야 합니다. 이러한 방식은 사용자의 개인 정보가 노출될 수 있고, 서비스 제공 업체가 자체적으로 증명을 인증할 수 없다는 문제가 있을 수 있습니다. - -분산형 신원 증명을 통해 회사는 기존의 [KYC(Know-Your-Customer)](https://en.wikipedia.org/wiki/Know_your_customer) 절차를 건너뛰고, 이른바 "검증 가능한 인증 정보"를 통해 사용자 인증을 진행할 수 있습니다. 이는 신원 관리 비용을 절감하는 한편 허위 문서의 사용 등을 방지합니다. - -### 3. 투표 및 온라인 커뮤니티 {#voting-and-online-communities} - -온라인 투표와 소셜 미디어는 분산형 신원 증명을 사용한 가장 놀라운 예시입니다. 온라인 투표는 특히 악의적인 사용자가 허위 신원을 만들어서 투표할 수 있기 때문에 조작에 취약합니다. 이때 개인이 온체인 증명을 제공하도록 요청한다면 온라인 투표 과정의 신뢰도를 개선할 수 있을 것입니다. - -분산형 신원 증명은 허위 계정이 불가능한 온라인 커뮤니티를 만들 수 있게 지원합니다. 예를 들어, 각 사용자가 ENS(이더리움 이름 서비스) 등의 온체인 신원 증명 시스템을 사용하여 신원을 증명하게 함으로써 허위 계정을 막을 수 있습니다. - -### 4. 반시빌(Anti-Sybil) 보호 {#sybil-protection} +### 소울바운드 토큰 및 신원 {#soulbound} -시빌(Sybil) 공격은 개인이 자신의 영향력을 늘리기 위해 여러 사람인 것처럼 시스템을 속이는 행위를 말합니다. [2차 투표](https://www.radicalxchange.org/concepts/plural-voting/)를 사용하는 [보조금 제공 애플리케이션](https://gitcoin.co/grants/)은 이러한 시빌 공격에 취약합니다. 더 많은 개인이 투표할 때 보조금의 가치가 증가하므로 사용자가 기여금을 여러 ID로 분할하도록 유도하기 때문입니다. 분산형 신원 증명은 특정 개인 정보를 공개하도록 요구하지 않는 경우가 많지만, 각 참가자가 실제 사용자임을 증명해야 하는 부담을 줌으로써 이를 방지하는 데 도움이 됩니다. +[소울바운드 토큰](https://vitalik.eth.limo/general/2022/01/26/soulbound.html)(양도 불가능한 [NFT](/glossary/#nft))은 특정 지갑에 고유한 정보를 수집하는 데 사용될 수 있습니다. 이는 성취(예: 특정 온라인 과정 수료 또는 게임에서 기준 점수 통과)나 커뮤니티 참여를 나타내는 토큰을 포함할 수 있는 특정 이더리움 주소에 귀속된 고유한 온체인 신원을 효과적으로 생성합니다. -## 분산 신원 증명을 사용하세요 {#use-decentralized-identity} +## 탈중앙화 신원 사용하기 {#use-decentralized-identity} 분산 신원 증명 솔루션을 위한 기반으로 이더리움을 사용하는 야심 찬 프로젝트가 많이 있습니다. -- **[이더리움 이름 서비스(ENS)](https://ens.domains/)** - _이더리움 지갑 주소, 콘텐츠 해시, 메타데이터 등 온체인 기반 컴퓨터용 식별 정보를 위한 탈중앙화 이름 시스템입니다._ -- **[SpruceID](https://www.spruceid.com/)** - _사용자가 제3자 서비스에 의존하지 않고 이더리움 계정과 ENS 프로필을 이용하여 디지털 신원을 직접 관리할 수 있도록 하는 분산 신원 증명 프로젝트입니다._ -- **[EAS(Ethereum Attestation Service)](https://attest.sh/)** - _모든 것에 대한 온체인 또는 오프체인 증명을 만들 수 있는 탈중앙화된 장부/프로토콜입니다._ -- **[인간 증명](https://www.proofofhumanity.id)** - _인간 증명(PoH: Proof of Humanity)은 이더리움 기반의 소셜 신원 증명 시스템입니다._ -- **[BrightID](https://www.brightid.org/)** - _소셜 그래프를 만들고 분석함으로써 신원 증명을 개혁하고자 하는 탈중앙화된 오픈소스의 소셜 신원 증명 네트워크입니다._ -- **[개인 증명 여권](https://passport.human.tech/)** - _탈중앙화 디지털 신원 정보 종합 플랫폼입니다._ +- **[Ethereum Name Service(ENS)](https://ens.domains/)** - _이더리움 지갑 주소, 콘텐츠 해시, 메타데이터와 같은 온체인, 기계 판독 가능 식별자를 위한 탈중앙화 이름 지정 시스템입니다._ +- **[이더리움으로 로그인(SIWE)](https://siwe.xyz/)** - _이더리움 계정으로 인증하기 위한 공개 표준입니다._ +- **[SpruceID](https://www.spruceid.com/)** - _사용자가 제3자 서비스에 의존하지 않고 이더리움 계정과 ENS 프로필로 디지털 신원을 제어할 수 있도록 하는 탈중앙화 신원 프로젝트입니다._ +- **[이더리움 증명 서비스(EAS)](https://attest.org/)** - _어떤 것에 대해서든 온체인 또는 오프체인 증명을 생성하기 위한 탈중앙화 원장/프로토콜입니다._ +- **[Proof of Humanity](https://www.proofofhumanity.id)** - _Proof of Humanity(또는 PoH)는 이더리움에 구축된 소셜 신원 확인 시스템입니다._ +- **[BrightID](https://www.brightid.org/)** - _소셜 그래프의 생성 및 분석을 통해 신원 확인을 개혁하고자 하는 탈중앙화 오픈 소스 소셜 신원 네트워크입니다._ +- **[walt.id](https://walt.id)** — _개발자와 조직이 자기 주권 신원 및 NFT/SBT를 활용할 수 있도록 지원하는 오픈 소스 탈중앙화 신원 및 지갑 인프라입니다._ +- **[Veramo](https://veramo.io/)** - _누구나 애플리케이션에서 암호학적으로 검증 가능한 데이터를 쉽게 사용할 수 있도록 하는 JavaScript 프레임워크입니다._ -## 더 읽을 거리 {#further-reading} +## 더 읽어보기 {#further-reading} -### 문서 {#articles} +### 관련 기사 {#articles} -- [블록체인 사용 사례: 디지털 신원 증명 블록체인](https://consensys.net/blockchain-use-cases/digital-identity/) — *ConsenSys* -- [이더리움 ERC725란 무엇인가요? 블록체인의 자기 주권 신원 관리](https://cryptoslate.com/what-is-erc725-self-sovereign-identity-management-on-the-blockchain/) — *Sam Town* -- [블록체인은 어떻게 디지털 신원 문제를 해결하는가](https://time.com/6142810/proof-of-humanity/) — _Andrew R. Chow_ -- [분산 신원이란 무엇이며, 왜 중요한가?](https://web3.hashnode.com/what-is-decentralized-identity) — _Emmanuel Awosika_ +- [블록체인 사용 사례: 디지털 신원에서의 블록체인](https://consensys.net/blockchain-use-cases/digital-identity/) — _ConsenSys_ +- [이더리움 ERC725란 무엇인가요? 블록체인에서의 자기 주권 신원 관리](https://cryptoslate.com/what-is-erc725-self-sovereign-identity-management-on-the-blockchain/) — _Sam Town_ +- [블록체인이 디지털 신원 문제를 해결할 수 있는 방법](https://time.com/6142810/proof-of-humanity/) — _Andrew R. Chow_ +- [탈중앙화 신원이란 무엇이며 왜 관심을 가져야 하는가?](https://web3.hashnode.com/what-is-decentralized-identity) — _Emmanuel Awosika_ +- [탈중앙화 신원 소개](https://walt.id/white-paper/digital-identity) — _Dominik Beron_ -### 영상 {#videos} +### 동영상 {#videos} -- [분산 신원 증명 (보너스 실시간 세션)](https://www.youtube.com/watch?v=ySHNB1za_SE&t=539s): _Andreas Antonopolous의 분산 신원 증명에 대한 설명 영상_ -- [Ceramic, IDX, React, 3ID Connect를 사용하여 이더리움과 분산 신원 증명에 로그인하기](https://www.youtube.com/watch?v=t9gWZYJxk7c): *Nader Dabit의 이더리움 지갑을 사용하여 사용자 프로필을 생성, 조회, 업데이트하기 위한 신원 관리 시스템을 구축하는 유튜브 튜토리얼* -- [BrightID - 이더리움의 분산 신원 증명](https://www.youtube.com/watch?v=D3DbMFYGRoM): *이더리움을 위한 분산 신원 증명 솔루션인 BrightID에 대해 얘기하는 Bankless 팟캐스트 에피소드* -- [오프체인 인터넷: 분산 신원 증명 & 검증 가능한 증명서](https://www.youtube.com/watch?v=EZ_Bb6j87mg) — Evin McMullen의 2022년 EthDenver 발표 +- [탈중앙화 신원(보너스 라이브스트림 세션)](https://www.youtube.com/watch?v=ySHNB1za_SE&t=539s) — _Andreas Antonopolous의 탈중앙화 신원에 대한 훌륭한 설명 영상_ +- [Ceramic, IDX, React, 3ID Connect를 사용하여 이더리움으로 로그인 및 탈중앙화 신원 구현하기](https://www.youtube.com/watch?v=t9gWZYJxk7c) — _Nader Dabit이 이더리움 지갑을 사용하여 사용자 프로필을 생성, 읽기 및 업데이트하는 신원 관리 시스템을 구축하는 방법에 대한 YouTube 튜토리얼_ +- [BrightID - 이더리움의 탈중앙화 신원](https://www.youtube.com/watch?v=D3DbMFYGRoM) — _이더리움을 위한 탈중앙화 신원 솔루션인 BrightID에 대해 논의하는 Bankless 팟캐스트 에피소드_ +- [오프체인 인터넷: 탈중앙화 신원 및 검증 가능한 자격 증명](https://www.youtube.com/watch?v=EZ_Bb6j87mg) — Evin McMullen의 EthDenver 2022 발표 +- [검증 가능한 자격 증명 설명](https://www.youtube.com/watch?v=ce1IdSr-Kig) - Tamino Baumann의 데모가 포함된 YouTube 설명 영상 ### 커뮤니티 {#communities} -- [GitHub의 ERC-725 연합](https://github.com/erc725alliance): *이더리움 블록체인에서 신원 관리를 위한 ERC 725 표준의 지원자* -- [EthID 디스코드 서버](https://discord.com/invite/ZUyG3mSXFD): *이더리움 로그인을 개발 중인 개발자와 매니아의 커뮤니티* -- [Veramo Labs](https://discord.gg/sYBUXpACh4): *애플리케이션의 검증 가능한 데이터를 위한 프레임워크 개발자의 커뮤니티* +- [GitHub의 ERC-725 얼라이언스](https://github.com/erc725alliance) — _이더리움 블록체인에서 신원을 관리하기 위한 ERC725 표준 지지자_ +- [EthID 디스코드 서버](https://discord.com/invite/ZUyG3mSXFD) — _이더리움으로 로그인 및 이더리움 팔로우 프로토콜을 개발하는 열성팬 및 개발자 커뮤니티_ +- [Veramo Labs](https://discord.gg/sYBUXpACh4) — _애플리케이션을 위한 검증 가능한 데이터 프레임워크를 구축하는 데 기여하는 개발자 커뮤니티_ +- [walt.id](https://discord.com/invite/AW8AgqJthZ) — _다양한 산업 분야에서 탈중앙화 신원 사용 사례를 연구하는 개발자 및 빌더 커뮤니티_ diff --git a/public/content/translations/ko/defi/index.md b/public/content/translations/ko/defi/index.md index eff3d768d69..b9607e4ad81 100644 --- a/public/content/translations/ko/defi/index.md +++ b/public/content/translations/ko/defi/index.md @@ -1,18 +1,19 @@ --- -title: 탈중앙화 금융(DeFi) -description: 이더리움의 디파이 개요 +title: "탈중앙화 금융(DeFi)" +metaTitle: "디파이란 무엇인가요? | 탈중앙화 금융의 혜택과 활용" +description: "이더리움의 디파이 개요" lang: ko template: use-cases emoji: ":money_with_wings:" image: /images/use-cases/defi.png -alt: 레고 블록으로 만든 이더리움 로고. +alt: "레고 블록으로 만든 이더리움 로고." sidebarDepth: 2 -summaryPoint1: 현재 금융 시스템에 대한 글로벌하고 개방적인 대안입니다. -summaryPoint2: 대출, 저축, 투자, 거래 등을 할 수 있는 제품입니다. -summaryPoint3: 누구나 프로그래밍할 수 있는 오픈 소스 기술을 기반으로 합니다. +summaryPoint1: "현재 금융 시스템에 대한 글로벌하고 개방적인 대안입니다." +summaryPoint2: "대출, 저축, 투자, 거래 등을 할 수 있는 제품입니다." +summaryPoint3: "누구나 프로그래밍할 수 있는 오픈 소스 기술을 기반으로 합니다." --- -디파이는 인터넷 시대에 맞게 구축된 개방적이고 글로벌한 금융 시스템이며, 수십 년 된 인프라와 프로세스에 의해 불투명하며 엄격하게 통제되어 함께 유지되는 시스템의 대안입니다. 그것은 당신에게 당신의 돈에 대한 통제력과 가시성을 제공합니다. 글로벌 시장으로의 진출과 현지 통화나 은행 옵션에 대한 대안도 제공합니다. 디파이 제품은 인터넷 연결이 되는 모든 사람에게 금융 서비스를 제공하며 대체로 사용자가 소유하고 관리합니다. 지금까지 수십억 달러 가치의 암호화폐가 디파이 애플리케이션을 통해 유입되었으며 매일 성장하고 있습니다. +디파이는 인터넷 시대에 맞게 구축된 개방적이고 글로벌한 금융 시스템이며, 수십 년 된 인프라와 프로세스에 의해 불투명하며 엄격하게 통제되어 함께 유지되는 시스템의 대안입니다. 그것은 당신에게 당신의 돈에 대한 통제력과 가시성을 제공합니다. 글로벌 시장으로의 진출과 현지 통화나 은행 옵션에 대한 대안도 제공합니다. 디파이 제품은 인터넷 연결이 되는 모든 사람에게 금융 서비스를 제공하며 대체로 사용자가 소유하고 관리합니다. 지금까지 수백억 달러 상당의 암호화폐가 디파이 애플리케이션을 통해 유입되었으며, 그 규모는 매일 성장하고 있습니다. ## 디파이가 무엇인가요? {#what-is-defi} @@ -37,14 +38,14 @@ summaryPoint3: 누구나 프로그래밍할 수 있는 오픈 소스 기술을 ### 비교 {#defi-comparison} -| 디파이 | 기존 금융 | -| ----------------------------------------------------------- | ------------------------------------------------------- | -| 당신이 돈을 소유합니다. | 기업이 당신의 돈을 소유합니다. | -| 당신이 돈이 어디로 송금되고 어떻게 소비되는지 통제합니다. | 미상환 위험이 있는 차용자에게 대출 등 기업이 돈을 잘못 관리하지 않으리라고 신뢰해야 합니다. | -| 자금 이체가 몇 분 내로 이루어집니다. | 결제는 수동 프로세스로 인해 며칠이 소요될 수 있습니다. | -| 트랜잭션 활동이 가명입니다. | 금융 활동은 당신의 신원과 밀접하게 연관되어 있습니다. | -| 디파이는 모두에게 열려 있습니다. | 금융 서비스를 이용하려면 신청해야 합니다. | -| 시장이 항상 열려 있습니다. | 직원들에게 휴식이 필요하기 때문에 시장이 문을 닫습니다. | +| 디파이 | 기존 금융 | +| --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | +| 당신이 돈을 소유합니다. | 기업이 당신의 돈을 소유합니다. | +| 당신이 돈이 어디로 송금되고 어떻게 소비되는지 통제합니다. | 미상환 위험이 있는 차용자에게 대출 등 기업이 돈을 잘못 관리하지 않으리라고 신뢰해야 합니다. | +| 자금 이체가 몇 분 내로 이루어집니다. | 결제는 수동 프로세스로 인해 며칠이 소요될 수 있습니다. | +| 트랜잭션 활동이 가명입니다. | 금융 활동은 당신의 신원과 밀접하게 연관되어 있습니다. | +| 디파이는 모두에게 열려 있습니다. | 금융 서비스를 이용하려면 신청해야 합니다. | +| 시장이 항상 열려 있습니다. | 직원들에게 휴식이 필요하기 때문에 시장이 문을 닫습니다. | | 투명성을 기반으로 구축되었으며, 누구나 제품 데이터를 보고 시스템이 어떻게 작동하는지 검사할 수 있습니다. | 금융 기관은 알 수 없는 미스터리입니다. 대출 내역, 관리 자산에 대한 기록 등을 볼 수 없습니다. | @@ -55,17 +56,17 @@ summaryPoint3: 누구나 프로그래밍할 수 있는 오픈 소스 기술을 여러 면에서 비트코인은 최초의 디파이 애플리케이션이었습니다. 비트코인으로 가치를 소유하고 통제하며 전 세계 어디서든 보낼 수 있습니다. 이것은 서로를 믿지 않는 많은 사람들에게 신뢰할 수 있는 중개자가 없이도 계정 장부에 합의할 수 있도록 방법을 제공하는 것으로 이뤄집니다. 비트코인은 누구에게나 열려 있으며 누구도 규칙을 변경할 권한이 없습니다. 희소성 및 개방성과 같은 비트코인의 규칙은 기술에 포함되어 있습니다. 정부가 화폐를 찍어내 개인이 저축한 돈의 가치가 낮아지고 기업이 시장을 폐쇄할 수 있는 기존 금융과는 다릅니다. -이더리움은 이를 기반으로 합니다. 비트코인과 마찬가지로 규칙을 변경할 수 없으며 모든 사람이 액세스할 수 있습니다. 또한 [스마트 계약](/glossary/#smart-contract)을 사용하여 이 디지털 화폐를 프로그래밍할 수 있으며, 가치를 저장하고 보내는 것 이상의 작업이 가능합니다. +이더리움은 이를 기반으로 합니다. 비트코인과 마찬가지로 규칙을 변경할 수 없으며 모든 사람이 액세스할 수 있습니다. 또한 [스마트 계약](/glossary/#smart-contract)을 사용하여 이 디지털 화폐를 프로그래밍할 수 있으므로, 가치를 저장하고 전송하는 것 이상의 작업을 할 수 있습니다. -## 프로그래밍 가능한 돈 {#programmable-money} +## 프로그래밍 가능한 화폐 {#programmable-money} -이건 이상하게 들립니다. "왜 제가 돈을 프로그래밍하고 싶겠어요?" 그러나 이것은 이더리움 토큰의 기본 기능일 뿐입니다. 누구나 로직을 지불금으로 프로그래밍할 수 있습니다. 그래서 당신은 금융기관이 제공하는 서비스와 함께 비트코인의 통제권과 보안을 얻을 수 있습니다. 이것을 통해 비트코인으로 할 수 없는 대부와 대출, 결제 일정 수립, 인덱스 펀드에 투자하기 등과 같은 것들을 암호화폐로 할 수 있습니다. +이상하게 들릴 수 있습니다... "왜 내 돈을 프로그래밍해야 하지?" 하지만 이는 이더리움 토큰의 기본 기능 그 이상입니다. 누구나 로직을 지불금으로 프로그래밍할 수 있습니다. 그래서 당신은 금융기관이 제공하는 서비스와 함께 비트코인의 통제권과 보안을 얻을 수 있습니다. 이것을 통해 비트코인으로 할 수 없는 대부와 대출, 결제 일정 수립, 인덱스 펀드에 투자하기 등과 같은 것들을 암호화폐로 할 수 있습니다. - +
이더리움이 처음이시면 디파이 애플리케이션에 대한 제안을 살펴보세요.
디파이 앱 둘러보기 @@ -78,43 +79,43 @@ summaryPoint3: 누구나 프로그래밍할 수 있는 오픈 소스 기술을 대부분의 금융 서비스에는 탈중앙화된 대안이 있습니다. 그러나 이더리움은 완전히 새로운 금융 상품을 만들 수 있는 기회도 제공합니다. 이 목록은 계속 늘어납니다. - [전 세계로 송금하기](#send-money) -- [전 세계로 돈을 스트리밍하기](#stream-money) -- [안정적인 통화에 액세스하기](#stablecoins) +- [전 세계로 자금 스트리밍하기](#stream-money) +- [스테이블코인 이용하기](#stablecoins) - [담보로 자금 대출하기](#lending) - [무담보 대출하기](#flash-loans) - [암호화폐 저축 시작하기](#saving) - [토큰 거래하기](#swaps) -- [포트폴리오 확장하기](#investing) -- [아이디어 자금 모으기](#crowdfunding) +- [포트폴리오 성장시키기](#investing) +- [아이디어에 자금 지원하기](#crowdfunding) - [보험 가입하기](#insurance) - [포트폴리오 관리하기](#aggregators) -### 전 세계로 빠르게 송금하세요 {#send-money} +### 전 세계로 빠르게 송금하기 {#send-money} -이더리움은 블록체인으로서 안전하고 글로벌하게 트랜잭션을 전송할 수 있도록 설계되었습니다. 비트코인과 마찬가지로 이더리움은 이메일을 보내는 것만큼 쉽게 전 세계로 돈을 송금할 수 있습니다. 수령인의 [ENS 이름](/glossary/#ens)(예: bob.eth) 또는 지갑의 계정 주소를 입력하기만 하면 (일반적으로) 몇 분 내에 수령인에게 직접 지급됩니다. 지불금을 보내거나 받으려면 [지갑](/wallets/)이 필요합니다. +이더리움은 블록체인으로서 안전하고 글로벌하게 트랜잭션을 전송할 수 있도록 설계되었습니다. 비트코인과 마찬가지로 이더리움은 이메일을 보내는 것만큼 쉽게 전 세계로 돈을 송금할 수 있습니다. 수령인의 [ENS 이름](/glossary/#ens)(예: bob.eth) 또는 지갑에 있는 계정 주소를 입력하기만 하면 일반적으로 몇 분 내에 결제 금액이 수령인에게 직접 전달됩니다. 결제를 보내거나 받으려면 [지갑](/wallets/)이 필요합니다. - 결제 디앱 보기 + 결제 탈중앙화앱 보기 #### 전 세계로 돈을 스트리밍하세요... {#stream-money} 이더리움으로 돈을 스트리밍할 수도 있습니다. 이렇게 하면 누군가에게 초 단위로 월급을 지급하여 필요할 때마다 돈을 받을 수 있습니다. 또는 초 단위로 보관 사물함이나 전기 스쿠터를 빌릴 수 있습니다. -이더리움의 가치 변동 때문에 [이더](/glossary/#ether)를 전송하거나 스트리밍하고 싶지 않다면, 이더리움의 대체 화폐인 [스테이블코인](/glossary/#stablecoin)을 사용해 볼 수 있습니다. +가치 변동 때문에 [ETH](/glossary/#ether)를 전송하거나 스트리밍하고 싶지 않다면, 이더리움에 대한 대체 통화인 [스테이블코인](/glossary/#stablecoin)이 있습니다. -### 안정적인 화폐에 액세스하세요 {#stablecoins} +### 스테이블코인 이용하기 {#stablecoins} 암호 화폐 변동성은 많은 금융상품과 일반 지출에 문제가 됩니다. 디파이 커뮤니티는 스테이블 코인으로 이 문제를 해결했습니다. 그것의 가치는 보통 달러처럼 인기 있는 통화인 또 다른 자산에 고정되어 있습니다. 다이 또는 USDC와 같은 코인의 가치는 몇 센트 이내입니다. 이런 점 때문에 스테이블 코인은 돈 버는 것 또는 소매업에 적합합니다. 라틴 아메리카의 많은 사람들은 정부가 발행한 화폐로 매우 불확실한 시기에 저축한 돈을 지키는 방법으로 스테이블 코인을 사용했습니다. - 스테이블 코인에 대해 더 보기 +스테이블코인에 대한 자세한 내용 @@ -127,26 +128,26 @@ summaryPoint3: 누구나 프로그래밍할 수 있는 오픈 소스 기술을 - 대출 기관에서 자산을 대출자가 대출할 수 있는 풀로 지급하는(유동성) 풀 기반. - 대출용 디앱 보기 + 대출 탈중앙화앱 보기 탈중앙화된 대출 기관을 사용하는 것은 이점이 많습니다. -#### 개인 정보 보호를 통한 대출 {#borrowing-privacy} +#### 개인 정보 보호 대출 {#borrowing-privacy} 오늘날, 돈을 빌려주고 대출하는 것은 모두 관련된 개인들을 중심으로 돌아갑니다. 은행은 돈을 빌려주기 전에 당신이 대출을 상환할 수 있는지 알아야 합니다. -탈중앙화 대출은 어느 당사자도 신원을 확인할 필요 없이 가능합니다. 대신 차주는 대출이 상환되지 않을 경우 대주에게 자동으로 지급되는 담보를 설정해야 합니다. 일부 대출 기관은 [NFT](/glossary/#nft)를 담보로 받기도 합니다. NFT는 그림과 같은 고유 자산에 대한 증서입니다. [NFT에 대해 더 보기](/nft/) +탈중앙화 대출은 어느 당사자도 신원을 확인할 필요 없이 가능합니다. 대신 차주는 대출이 상환되지 않을 경우 대주에게 자동으로 지급되는 담보를 설정해야 합니다. 일부 대출 기관에서는 [NFT](/glossary/#nft)를 담보로 받기도 합니다. NFT는 그림과 같은 고유 자산에 대한 증서입니다. [NFT에 대해 더 알아보기](/nft/) 이를 통해 신용 확인이나 개인 정보 양도 없이 돈을 빌릴 수 있습니다. -#### 글로벌 펀드에 대한 액세스 {#access-global-funds} +#### 글로벌 자금 접근성 {#access-global-funds} -탈중앙화된 대출 기관을 이용하면 선택하신 은행이나 기관에서 보관하는 자금뿐만 아니라 전 세계에 예치된 자산에 액세스할 수 있게 됩니다. 이를 통해 대출을 더 쉽게 실행하고 금리를 향상합니다. +탈중앙화된 대출 기관을 이용하면 선택하신 은행이나 기관에서 보관하는 자금뿐만 아니라 전 세계에 예치된 자산에 액세스할 수 있게 됩니다. 이를 통해 대출 접근성이 높아지고 이자율이 개선됩니다. -#### 조세 효율성 {#tax-efficiencies} +#### 세금 효율성 {#tax-efficiencies} -대출을 통해 ETH(과세 대상 이벤트)를 판매하지 않고도 필요한 자금을 이용할 수 있습니다. 대신 스테이블 코인 대출을 위한 담보로 ETH를 사용할 수 있습니다. 이렇게 하면 필요한 현금 흐름이 생기고 ETH를 유지할 수 있습니다. 스테이블 코인은 ETH처럼 가치가 변동하지 않아 현금이 필요할 때 훨씬 좋은 토큰입니다. [스테이블 코인에 대해 더 보기](#stablecoins) +대출을 통해 ETH(과세 대상 이벤트)를 판매하지 않고도 필요한 자금을 이용할 수 있습니다. 대신 스테이블 코인 대출을 위한 담보로 ETH를 사용할 수 있습니다. 이렇게 하면 필요한 현금 흐름이 생기고 ETH를 유지할 수 있습니다. 스테이블 코인은 ETH처럼 가치가 변동하지 않아 현금이 필요할 때 훨씬 좋은 토큰입니다. [스테이블코인에 대해 더 알아보기](#stablecoins) #### 플래시 론 {#flash-loans} @@ -172,24 +173,24 @@ summaryPoint3: 누구나 프로그래밍할 수 있는 오픈 소스 기술을 전형적인 금융 세계에서 위의 예시를 가능하게 하려면 엄청난 돈이 필요합니다. 이러한 돈벌이 전략은 기존의 부를 가진 사람들만이 접근할 수 있습니다. 플래시 론은 돈을 버는 것의 전제 조건이 돈을 소유하는 것이 아니라는 미래의 예시입니다. - 플래시 론에 대해 더 보기 + 플래시 론에 대해 더 알아보기 -### 암호화폐로 저축을 시작하세요 {#saving} +### 암호화폐로 저축 시작하기 {#saving} #### 대출 {#lending} 빌려주는 것으로 암호화폐의 이자를 벌어 실시간으로 자산이 늘어가는 걸 볼 수 있습니다. 현재 이자율은 지역 은행에서 얻을 수 있는 것보다 훨씬 높습니다(운 좋게 은행에 갈 수 있다면). 예시는 다음과 같습니다. -- Aave와 같은 제품에 [스테이블 코인](/stablecoins/)인 100다이를 빌려줍니다. +- Aave와 같은 제품에 [스테이블코인](/stablecoins/)인 100 다이를 대여합니다. - 대출한 다이를 상징하는 토큰인 Aave 다이(aDai) 백 개를 받습니다. -- 이자율에 따라 aDai는 증가하고 지갑에서 잔고가 늘어가는 걸 보실 수 있습니다. [연이율](/glossary/#apr)에 따라 지갑 잔액에는 며칠 또는 몇 시간 후에 100.1234와 같은 수치가 표시됩니다! +- 이자율에 따라 aDai는 증가하고 지갑에서 잔고가 늘어가는 걸 보실 수 있습니다. [APR](/glossary/#apr)에 따라, 며칠 또는 몇 시간 후 지갑 잔액이 100.1234와 같이 표시됩니다! - 언제든지 aDai 잔액과 동일한 금액의 일반 다이를 인출할 수 있습니다. - 대출 디앱 보기 + 대출 탈중앙화앱 보기 #### 무손실 복권 {#no-loss-lotteries} @@ -205,12 +206,12 @@ summaryPoint3: 누구나 프로그래밍할 수 있는 오픈 소스 기술을 상금 풀은 위의 대출 예시와 같이 티켓 예금을 대출하여 발생하는 모든 이자로 생성됩니다. - 풀투게더 사용해보기 + PoolTogether 사용해 보기 -### 토큰을 교환하세요 {#swaps} +### 토큰 교환 {#swaps} 이더리움에는 수천 개의 토큰이 있습니다. 탈중앙화 거래소(DEX)를 사용하면 원할 때마다 다른 토큰을 거래할 수 있습니다. 자산에 대한 통제권을 포기하지 마세요. 이것은 마치 다른 나라를 방문할 때 환전소를 이용하는 것과 같습니다. 하지만 디파이 버전은 절대 문을 닫지 않습니다. 시장은 연중무휴로 365일 운영되며 기술 덕에 거래를 수락할 사람을 항상 구할 수 있습니다. @@ -229,24 +230,24 @@ summaryPoint3: 누구나 프로그래밍할 수 있는 오픈 소스 기술을 중앙화 거래소를 이용하면 거래 전에 자산을 예치해야 하고, 그 자산을 책임질 거래소를 신뢰해야 합니다. 자산이 예치되어 있으면 중앙화 거래소는 해커에게 매력적인 대상이기 때문에 자산이 위험합니다. - 거래 디앱 보기 + 거래 탈중앙화앱 보기 -### 포트폴리오를 확장하세요 {#investing} +### 포트폴리오 성장시키기 {#investing} 이더리움에는 선택한 전략에 따라 포트폴리오를 확장하는 펀드 관리 제품이 있습니다. 이것은 자동적이고 모두에게 공개되며, 수익의 일부를 가져가는 인간 관리자가 필요 없습니다. -좋은 예가 [디파이 펄스 인덱스 펀드(DPI)](https://defipulse.com/blog/defi-pulse-index/)입니다. 이 펀드는 포트폴리오에 항상 시가총액 기준 상위 디파이 토큰이 포함되도록 자동으로 편입 종목을 재조정합니다. 세부 사항을 관리할 필요가 없으며 원할 때마다 펀드에서 인출할 수 있습니다. +좋은 예로 [DeFi Pulse Index fund (DPI)](https://defipulse.com/blog/defi-pulse-index/)가 있습니다. 이 펀드는 포트폴리오에 항상 시가총액 기준 상위 디파이 토큰이 포함되도록 자동으로 편입 종목을 재조정합니다. 세부 사항을 관리할 필요가 없으며 원할 때마다 펀드에서 인출할 수 있습니다. - 투자 디앱 보기 + 투자 탈중앙화앱 보기 -### 아이디어 자금을 모으세요 {#crowdfunding} +### 아이디어에 자금 지원하기 {#crowdfunding} 이더리움은 크라우드 펀딩을 위한 이상적인 플랫폼입니다. @@ -255,10 +256,10 @@ summaryPoint3: 누구나 프로그래밍할 수 있는 오픈 소스 기술을 - 예를 들면 모금자는 구체적인 기한과 최소 금액이 충족되지 않는 경우 자동 환불을 설정할 수 있습니다. - 크라우드 펀딩 디앱 보기 + 크라우드펀딩 탈중앙화앱 보기 -#### 2차 펀딩 {#quadratic-funding} +#### 이차 펀딩 {#quadratic-funding} 이더리움은 오픈 소스 소프트웨어이며 지금까지의 많은 작업물이 커뮤니티에서 자금을 지원받았습니다. 이는 2차 펀딩이라는 흥미롭고 새로운 모금 모델의 성장으로 이어졌습니다. 2차 펀딩은 미래에 모든 공공재 유형에 자금을 지원하는 방식을 개선할 잠재력이 있습니다. @@ -272,7 +273,7 @@ summaryPoint3: 누구나 프로그래밍할 수 있는 오픈 소스 기술을 이는 1달러의 기부를 100번 받은 프로젝트 A가 만 달러 기부를 한 번 받은 프로젝트 B보다 더 많은 펀딩을 받았다는 것을 의미합니다(매칭 풀의 크기에 따라 다름). - 2차 펀딩에 대해 더 보기 + 이차 펀딩에 대해 더 알아보기 @@ -281,10 +282,10 @@ summaryPoint3: 누구나 프로그래밍할 수 있는 오픈 소스 기술을 탈중앙화 보험은 보험을 더 싸고, 더 빠르게 돈을 지불할 수 있고, 더 투명하게 하는 것을 목표로 합니다. 더 많은 자동화가 이뤄지면 보험이 더욱 저렴해지고 지불도 훨씬 빨라집니다. 당신의 청구를 결정하는 데 사용되는 데이터는 완전히 투명합니다. -이더리움 제품은 다른 소프트웨어와 마찬가지로 버그와 악용에 시달릴 수 있습니다. 그래서 현재 이 분야의 많은 보험 상품들은 자금 손실로부터 사용자를 보호하는 데 초점을 맞추고 있습니다. 그러나 살면서 발생할 수 있는 모든 사안으로 보장 범위를 확장하는 프로젝트가 있습니다. 이것의 좋은 예는 [케냐의 소규모 농부들을 가뭄과 홍수로부터 보호하는 것](https://blog.etherisc.com/etherisc-teams-up-with-chainlink-to-deliver-crop-insurance-in-kenya-137e433c29dc)을 목표로 하는 이더리스크의 농작물 보험입니다. 탈중앙화 보험은 종종 일반적인 보험에서 제외되는 농부들에게 더 저렴한 보험을 제공할 수 있습니다. +이더리움 제품은 다른 소프트웨어와 마찬가지로 버그와 악용에 시달릴 수 있습니다. 그래서 현재 이 분야의 많은 보험 상품들은 자금 손실로부터 사용자를 보호하는 데 초점을 맞추고 있습니다. 그러나 살면서 발생할 수 있는 모든 사안으로 보장 범위를 확장하는 프로젝트가 있습니다. 좋은 예로 [케냐의 소규모 자작농을 가뭄과 홍수로부터 보호](https://blog.etherisc.com/etherisc-teams-up-with-chainlink-to-deliver-crop-insurance-in-kenya-137e433c29dc)하는 것을 목표로 하는 Etherisc의 농작물 보험이 있습니다. 탈중앙화 보험은 종종 일반적인 보험에서 제외되는 농부들에게 더 저렴한 보험을 제공할 수 있습니다. - 보험 디앱 보기 + 보험 탈중앙화앱 보기 @@ -294,14 +295,14 @@ summaryPoint3: 누구나 프로그래밍할 수 있는 오픈 소스 기술을 많은 일이 진행됨에 따라 모든 투자, 대출 및 거래를 추적할 수 있는 방법이 필요할 것입니다. 한 곳에서 디파이 활동을 조율할 수 있는 여러 제품이 있습니다. 이것이 디파이의 개방형 아키텍처의 아름다움입니다. 팀에서 여러 제품 간의 잔액을 볼 수 있는 인터페이스를 구축할 수 있을 뿐만 아니라 기능을 사용할 수도 있습니다. 디파이에 대해 더 알아갈 수록 이것이 유용할 것입니다. - 포트폴리오 디앱 보기 + 포트폴리오 탈중앙화앱 보기 ## 디파이는 어떻게 작동하나요? {#how-defi-works} -디파이는 암호화폐와 스마트 계약으로 중개인이 필요 없는 서비스를 제공합니다. 오늘날의 금융 세계에서 금융 기관은 거래의 보증인 역할을 합니다. 돈이 금융 기관을 통해 흐르기 때문에 금융 기관이 엄청난 힘을 갖게 됩니다. 게다가 전 세계 수십억 명의 사람들은 은행 계좌에 접근할 수도 없습니다. +디파이는 암호화폐와 스마트 계약으로 중개인이 필요 없는 서비스를 제공합니다. 오늘날의 금융 세계에서 금융 기관은 거래의 보증인 역할을 합니다. 돈이 금융 기관을 통해 흐르기 때문에 금융 기관이 엄청난 힘을 갖게 됩니다. 게다가 전 세계 수십억 명의 사람들이 은행 계좌조차 이용할 수 없습니다. 디파이에서는 거래 시에 스마트 계약이 금융 기관을 대신합니다. 스마트 계약은 자금을 보유할 수 있고 특정 조건에 따라 송금/환불할 수 있는 일종의 이더리움 계정입니다. 스마트 계약이 실행 중에는 아무도 변경할 수 없습니다. 항상 프로그래밍된 대로 실행됩니다. @@ -323,38 +324,43 @@ summaryPoint3: 누구나 프로그래밍할 수 있는 오픈 소스 기술을 디파이를 레이어 구조로 생각해 볼 수 있습니다. 1. 블록체인 – 이더리움에 거래 내역과 계정 상태가 들어있습니다. -2. 자산 – [ETH](/what-is-ether/) 및 기타 토큰(화폐)입니다. -3. 프로토콜 – 예를 들어 자산의 탈중앙화 대출을 제공하는 서비스와 같은 기능을 제공하는 [스마트 계약](/glossary/#smart-contract)입니다. +2. 자산 – [ETH](/what-is-ether/) 및 기타 토큰(통화). +3. 프로토콜 – 예를 들어 자산의 탈중앙화 대출을 허용하는 서비스와 같이 기능을 제공하는 [스마트 계약](/glossary/#smart-contract)입니다. 4. [애플리케이션](/apps/) – 프로토콜을 관리하고 액세스하는 데 사용하는 제품입니다. -참고: 대부분의 탈중앙 금융은 [ERC-20 표준](/glossary/#erc-20)을 사용합니다. 디파이 애플리케이션은 랩드 이더(WETH)라는 이더리움 래퍼를 사용합니다. [랩드이더에 대해 자세히 알아보세요](/wrapped-eth). +참고: 디파이의 상당 부분은 [ERC-20 표준](/glossary/#erc-20)을 사용합니다. 디파이 애플리케이션은 랩드 이더(WETH)라는 ETH용 래퍼를 사용합니다. [랩트 이더에 대해 더 알아보기](/wrapped-eth). -## 디파이를 구축하세요 {#build-defi} +## 디파이 구축하기 {#build-defi} 디파이는 오픈 소스 캠페인입니다. 디파이 프로토콜과 애플리케이션은 검사하고, 포크하고, 혁신할 수 있도록 누구에게나 열려 있습니다. 이러한 계층화된 스택(모두 동일한 베이스 블록체인과 자산을 공유함)으로 인해 프로토콜을 합치고 맞춰서 독특한 콤보 기회를 열 수 있습니다. - 디앱 구축에 대해 더 보기 + 탈중앙화앱 구축에 대해 더 알아보기 -## 부록 {#further-reading} +## 더 읽어보기 {#further-reading} ### 디파이 데이터 {#defi-data} -- [디파이 프라임](https://defiprime.com/) -- [디파이 라마](https://defillama.com/) +- [DeFi Prime](https://defiprime.com/) +- [DeFi Llama](https://defillama.com/) -### 디파이 기사 {#defi-articles} +### 디파이 관련 기사 {#defi-articles} -- [디파이 초보자 가이드](https://blog.coinbase.com/a-beginners-guide-to-decentralized-finance-defi-574c68ff43c4) – _시드 코엘로-프라부, 2020년 1월 6일_ +- [디파이 초보자 가이드](https://blog.coinbase.com/a-beginners-guide-to-decentralized-finance-defi-574c68ff43c4) – _Sid Coelho-Prabhu, 2020년 1월 6일_ +- [EEA 디파이 위험 평가 가이드라인](https://entethalliance.org/specs/defi-risks/) – 디파이 프로토콜의 주요 위험을 식별하고 평가하는 방법에 대한 업계 지원 개요입니다. -### 영상 {#videos} +### 동영상 {#videos} -- [Finematics - 탈중앙화 금융 교육](https://finematics.com/) – _디파이에 대한 영상_ -- [디파이언트](https://www.youtube.com/playlist?list=PLaDcID4s1KronHMKojfjwiHL0DdQEPDcq) - _디파이 기초: 가끔은 혼란스러운 이곳에서 시작하려면 알아야 할 모든 것._ -- [화이트보드 크립토](https://youtu.be/17QRFlml4pA) _디파이란 무엇인가요?_ +- [Finematics - 탈중앙화 금융 교육](https://finematics.com/) – _DeFi에 관한 영상_ +- [The Defiant](https://www.youtube.com/playlist?list=PLaDcID4s1KronHMKojfjwiHL0DdQEPDcq) - _디파이 기초: 가끔은 난해한 이 분야를 시작하기 위해 알아야 할 모든 것._ +- [Whiteboard Crypto](https://youtu.be/17QRFlml4pA) _디파이란 무엇인가?_ ### 커뮤니티 {#communities} -- [디파이 라마 디스코드 서버](https://discord.defillama.com/) -- [디파이 펄스 디스코드 서버](https://discord.gg/Gx4TCTk) +- [DeFi Llama 디스코드 서버](https://discord.defillama.com/) +- [DeFi Pulse 디스코드 서버](https://discord.gg/Gx4TCTk) + + + + diff --git a/public/content/translations/ko/desci/index.md b/public/content/translations/ko/desci/index.md index 97b0c809ef4..52b2f5ee7f9 100644 --- a/public/content/translations/ko/desci/index.md +++ b/public/content/translations/ko/desci/index.md @@ -1,88 +1,89 @@ --- -title: 탈중앙화 과학(DeSci) -description: 이더리움의 탈중앙화 과학 개요 +title: "탈중앙화 과학(DeSci)" +description: "이더리움의 탈중앙화 과학 개요" lang: ko template: use-cases emoji: ":microscope:" sidebarDepth: 2 image: /images/future_transparent.png alt: "" -summaryPoint1: 현재 금융 시스템에 대한 글로벌하고 개방적인 대안입니다. -summaryPoint2: 과학자들이 자금을 모으고, 실험을 실행하고, 데이터를 공유하고, 통찰력을 배포할 수 있게 하는 기술. -summaryPoint3: 열린 과학 운동을 기반으로 합니다. +summaryPoint1: "현재 과학 시스템에 대한 글로벌하고 개방적인 대안입니다." +summaryPoint2: "과학자들이 자금을 모으고, 실험을 실행하고, 데이터를 공유하고, 통찰력을 배포할 수 있게 하는 기술." +summaryPoint3: "열린 과학 운동을 기반으로 합니다." --- ## 탈중앙화 과학(DeSci)이란 무엇인가요? {#what-is-desci} -탈중앙화 과학(DeSci)은 Web3 스택을 사용하여 과학 지식을 공정하고 공평하게 자금 조달, 생성, 검토, 신용, 저장 및 보급하기 위한 공공 인프라를 구축하는 것을 목표로 하는 운동입니다. +탈중앙화 과학(DeSci)은 [Web3](/glossary/#web3) 스택을 사용하여 과학적 지식을 공정하고 공평하게 지원, 생성, 검토, 인정, 저장, 배포하기 위한 공공 인프라를 구축하려는 운동입니다. DeSci는 과학자들이 그들의 연구를 공개적으로 공유하고 그들의 작업에 대한 공로를 인정받도록 장려하는 동시에 누구나 연구에 쉽게 접근하고 기여할 수 있는 생태계를 만드는 것을 목표로 합니다. DeSci는 과학적 지식은 모든 사람이 접근할 수 있어야 하며 과학 연구 과정은 투명해야 한다는 생각을 바탕으로 합니다. DeSci는 더 탈중앙화 과학 연구 모델을 만들고 있으며, 중앙 당국의 검열과 통제에 더 저항하고 있습니다. DeSci는 자금, 과학 도구 및 통신 채널에 대한 접근을 탈중앙화 시킴으로써 새롭고 틀에 얽매이지 않는 아이디어가 번창할 수 있는 환경을 조성하기를 희망합니다. -탈중앙화 과학은 더 다양한 자금을 허용합니다 ([다오](/dao/), [ 펀딩 등에 대한 이차 기부](https://papers.ssrn.com/sol3/papers.cfm?Abstract_id=2003531)), 더 접근 가능한 접근 데이터와 방법, 그리고 재현에 대한 보상 제공함으로써. +탈중앙화 과학은 ([DAO](/glossary/#dao), [이차 기부](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=2003531), 크라우드펀딩 등) 더 다양한 자금 출처를 허용하고, 데이터와 방법에 더 쉽게 접근할 수 있게 하며, 재현성에 대한 인센티브를 제공합니다. ### Juan Benet - DeSci 운동 -## DeSci가 과학을 개선시키는 방법 {#desci-improves-science} +## DeSci가 과학을 개선하는 방법 {#desci-improves-science} 과학의 주요 문제에 대한 불완전한 목록과 탈중앙화 과학이 이러한 문제를 해결하는 데 어떻게 도움이 될 수 있는지 -| **탈중앙화된 과학** | **기존 과학** | -| --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | -| 자금 분배는 이차 기부 또는 DAO와 같은 메커니즘을 사용하여 대중에 의해 결정됩니다. | 작고 폐쇄된 중앙 집권 그룹이 자금 분배를 통제합니다. | -| 여러분은 역동적인 팀으로 전 세계의 동료들과 협력합니다. | 자금 조달 기관과 가정 기관은 당신의 협력을 제한합니다. | -| 자금 조달 결정은 온라인에서 투명하게 이루어집니다. 새로운 자금 조달 메커니즘이 탐구되었습니다. | 자금 조달 결정은 긴 처리 시간과 제한된 투명성으로 이루어집니다. 자금 조달 메커니즘은 거의 존재하지 않습니다. | -| 실험실 서비스 공유는 Web3 기초 요소를 사용하여 더 쉽고 투명하게 만들어졌습니다. | 실험실 자원을 공유하는 것은 종종 느리고 불투명합니다. | -| 신뢰, 투명성 및 보편적 접근을 위해 Web3 기초 요소를 사용하는 새로운 출판 모델을 개발할 수 있습니다. | 여러분은 비효율적이고 편향적이고 착취적인 것으로 자주 인정되는 확립된 경로를 통해 출판합니다. | -| 동료 검토 작업으로 토큰과 명성을 얻을 수 있습니다. | 동료 검토 작업은 무급이며, 영리 출판사에 도움이 됩니다. | -| 여러분은 투명한 조건에 따라 생성하고 배포하는 지적 재산권(IP) 을 소유합니다. | 여러분의 홈 기관은 여러분이 생성한 IP를 소유합니다. IP에 대한 접근은 투명하지 않습니다. | -| 모든 단계를 체인에 연결함으로써 실패한 노력의 데이터를 포함한 모든 연구를 공유합니다. | 출판 편향은 연구자들이 성공적인 결과를 얻은 실험을 공유할 가능성이 더 높다는 것을 의미합니다. | +| **탈중앙화된 과학** | **기존 과학** | +| ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | +| 자금 분배는 이차 기부 또는 DAO와 같은 메커니즘을 사용하여 대중이 결정합니다. | 작고, 폐쇄적이며, 중앙화된 그룹이 자금 분배를 통제합니다. | +| 전 세계의 동료들과 역동적인 팀에서 협력합니다. | 자금 지원 기관과 소속 기관이 협업을 제한합니다. | +| 자금 지원 결정은 온라인에서 **투명하게** 이루어집니다. 새로운 자금 조달 메커니즘이 탐구되었습니다. | 자금 지원 결정은 처리 시간이 길고 투명성이 제한적입니다. 자금 조달 메커니즘은 거의 존재하지 않습니다. | +| [Web3](/glossary/#web3) 기술을 사용하여 실험실 서비스를 더 쉽고 투명하게 공유할 수 있습니다. | 실험실 자원 공유는 종종 느리고 불투명합니다. | +| 신뢰, 투명성, 보편적 접근을 위해 Web3 프리미티브를 사용하는 새로운 퍼블리싱 모델을 개발할 수 있습니다. | 자주 비효율적이고, 편향되며, 착취적이라고 인정받는 기존 경로를 통해 출판합니다. | +| 동료 검토 작업을 통해 **토큰과 평판을 얻을 수 있습니다**. | 동료 검토 작업은 무급이며 영리 목적의 출판사에 이익이 됩니다. | +| 투명한 조건에 따라 생성하고 배포하는 지적 재산(IP)을 소유합니다. | 생성한 IP는 소속 기관이 소유합니다. IP에 대한 접근은 투명하지 않습니다. | +| 모든 단계를 온체인에 기록하여 실패한 노력의 데이터를 포함한 모든 연구를 공유합니다. | 게재 편향은 연구자들이 성공적인 결과를 얻은 실험을 공유할 가능성이 더 높다는 것을 의미합니다. | ## 이더리움과 DeSci {#ethereum-and-desci} -탈중앙화 과학 시스템은 강력한 보안, 최소한의 통화 및 거래 비용, 그리고 애플리케이션 개발을 위한 풍부한 생태계를 요구할 것입니다. 이더리움은 탈중앙화 과학 스택을 구축하는 데 필요한 모든 것을 제공합니다. +탈중앙화 과학 시스템은 강력한 보안, 최소한의 통화 및 거래 비용, 그리고 애플리케이션 개발을 위한 풍부한 생태계를 요구할 것입니다. 이더리움은 탈중앙화 과학 기술을 구축하는 데 필요한 모든 것을 제공합니다. ## DeSci 사용 사례 {#use-cases} -DeSci는 Web2 학계를 디지털 세계로 전환하기 위한 과학적 도구 세트를 구축하고 있습니다. 아래는 Web3가 과학계에 제공할 수 있는 사용 사례 샘플입니다. +DeSci는 기존 학계를 디지털 세계로 온보딩하기 위한 과학적 툴셋을 구축하고 있습니다. 아래는 Web3가 과학계에 제공할 수 있는 사용 사례 샘플입니다. -### 출판 사업 {#publishing} +### 퍼블리싱 {#publishing} -과학 출판은 논문을 생성하기 위해 과학자, 평론가 및 편집자의 무료 노동에 의존하지만 엄청난 출판 비용을 부과하는 출판사에 의해 관리되기 때문에 문제가 있는 것으로 유명합니다. 보통 세금을 통해 작품과 출판 비용을 간접적으로 지불한 대중은 종종 출판사에 다시 지불하지 않고는 같은 작품에 접근할 수 없습니다. 개별 과학 논문 출판에 드는 총 비용은 종종 5자리 숫자($USD)이며, 이는 과학 지식의 전체 개념을 [ 공익](https://www.econlib.org/library/Enc/PublicGoods.html)과 동시에 소수의 출판사에게 막대한 이익을 창출합니다. +과학 출판은 논문을 생성하기 위해 과학자, 평론가 및 편집자의 무료 노동에 의존하지만 엄청난 출판 비용을 부과하는 출판사에 의해 관리되기 때문에 문제가 있는 것으로 유명합니다. 보통 세금을 통해 작품과 출판 비용을 간접적으로 지불한 대중은 종종 출판사에 다시 지불하지 않고는 같은 작품에 접근할 수 없습니다. 개별 과학 논문을 출판하는 데 드는 총비용은 종종 5자리 숫자(USD)에 달하며, 이는 소수의 출판사에 막대한 이익을 창출하는 동시에 과학적 지식을 [공공재](/glossary/#public-goods)로 보는 전체 개념을 훼손합니다. -무료 및 오픈 액세스 플랫폼은 [ArXiv와 같은](https://arxiv.org/) 사전 인쇄 서버의 형태로 존재합니다. 그러나 이러한 플랫폼은 품질 관리, [반시빌(anti-sybil) 메커니즘 mechanisms](https://csrc.nist.gov/glossary/term/sybil_attack)이 부족하며 일반적으로 기사 수준의 글을 추적하지 않습니다. 즉, 일반적으로 전통적인 출판사에 제출하기 전에 작업을 홍보하는 데만 사용됩니다. 탈중앙화 허브 는 또한 출판된 논문에 무료로 접근할 수 있도록 하지만, 법적으로는 접근하지 않으며, 출판사가 이미 지불을 받고 엄격한 저작권법으로 작품을 포장한 후에만 가능합니다. 이것은 내장된 합법 메커니즘과 보상 모델로 접근 가능한 과학 논문과 데이터에 중요한 격차를 남깁니다. 그러한 시스템을 구축하기 위한 도구는 Web3에 존재합니다. +무료 오픈 액세스 플랫폼은 [ArXiv](https://arxiv.org/)와 같은 사전 인쇄 서버의 형태로 존재합니다. 그러나 이러한 플랫폼은 품질 관리, [시빌 방지 메커니즘](/glossary/#anti-sybil)이 부족하고 일반적으로 논문 수준의 메트릭을 추적하지 않으므로, 보통 전통적인 출판사에 제출하기 전에 작업을 홍보하는 데만 사용됩니다. 탈중앙화 허브 는 또한 출판된 논문에 무료로 접근할 수 있도록 하지만, 법적으로는 접근하지 않으며, 출판사가 이미 지불을 받고 엄격한 저작권법으로 작품을 포장한 후에만 가능합니다. 이것은 내장된 합법 메커니즘과 보상 모델로 접근 가능한 과학 논문과 데이터에 중요한 격차를 남깁니다. 그러한 시스템을 구축하기 위한 도구는 Web3에 존재합니다. -### 재생 가능성과 복제 가능성 {#reproducibility-and-replicability} +### 재현성 및 복제성 {#reproducibility-and-replicability} 재생 가능성과 복제 가능성은 양질의 과학적 발견의 기초입니다. - 재현 가능한 결과는 동일한 방법론을 사용하여 동일한 팀에서 연속으로 여러 번 달성할 수 있습니다. - 동일한 실험 설정을 사용하여 다른 그룹에서 복제 가능한 결과를 얻을 수 있습니다. -새로운 Web3 네이티브 도구는 재생 가능성과 복제 가능성이 검색의 기반이 되도록 보장할 수 있습니다. 우리는 학계의 기술 구조에 양질의 과학을 엮을 수 있습니다. Web3는 원시 데이터, 계산 엔진 및 응용 프로그램 결과와 같은 각 분석 구성 요소에 대한 증명을 만들 수 있는 기능을 제공합니다. 합의 시스템의 장점은 이러한 구성 요소를 유지하기 위해 신뢰할 수 있는 네트워크가 생성될 때, 각 네트워크 참가자는 계산을 재현하고 각 결과를 검증할 책임이 있다는 것입니다. +새로운 Web3 네이티브 도구는 재생 가능성과 복제 가능성이 검색의 기반이 되도록 보장할 수 있습니다. 우리는 학계의 기술 구조에 양질의 과학을 엮을 수 있습니다. Web3는 원시 데이터, 계산 엔진, 애플리케이션 결과 등 각 분석 구성 요소에 대한 [증명](/glossary/#attestation)을 생성하는 기능을 제공합니다. 합의 시스템의 장점은 이러한 구성 요소를 유지하기 위해 신뢰할 수 있는 네트워크가 생성될 때, 각 네트워크 참가자는 계산을 재현하고 각 결과를 검증할 책임이 있다는 것입니다. -### 펀딩 {#funding} +### 자금 지원 {#funding} -과학 자금 조달을 위한 현재 표준 모델은 개인이나 과학자 그룹이 자금 조달 기관에 서면 신청서를 작성하는 것입니다. 신뢰할 수 있는 개인으로 구성된 소규모 패널이 응용 프로그램을 평가한 다음 지원자 중 일부에게 기금을 수여하기 전에 지원자를 인터뷰합니다. 보조금 신청과 수령 사이에 때때로 수년의 대기 시간으로 이어지는 병목 현상을 제외하고 이 모델은 검토 패널의 편견, 이기심 및 정치에 매우 취약한 것으로 알려져 있습니다. +과학 자금 조달을 위한 현재 표준 모델은 개인이나 과학자 그룹이 자금 조달 기관에 서면 신청서를 작성하는 것입니다. 신뢰할 수 있는 개인으로 구성된 소규모 패널이 응용 프로그램을 평가한 다음 지원자 중 일부에게 기금을 수여하기 전에 지원자를 인터뷰합니다. 보조금을 신청하고 수령하기까지 때로는 **수년을 기다려야** 하는 병목 현상을 만드는 것 외에도, 이 모델은 심사위원단의 편견, 사리사욕, 정치에 매우 취약한 것으로 알려져 있습니다. 연구에 따르면 보조금 검토 패널은 다른 패널에 주어진 동일한 제안이 매우 다른 결과를 가지고 있기 때문에 고품질 제안을 선택하는 데 열악한 역할을 합니다. 자금이 더 부족해짐에 따라, 그것은 더 지적으로 보수적인 프로젝트를 가진 더 많은 고위 연구자들의 더 작은 풀에 집중되었습니다. 그 효과는 비뚤어진 보상을 확고히 하고 혁신을 억누르는 경쟁적인 자금 조달 환경을 조성했습니다. -Web3는 DAO와 Web3가 광범위하게 개발한 다양한 보상 모델을 실험함으로써 이 깨진 자금 조달 모델을 혼란에 빠뜨릴 가능성이 있습니다. [소급 공공재 자금 조달](https://medium.com/ethereum-optimism/retroactive-public-goods-funding-33c9b7d00f0c), [이차 자금 조달](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=2003531), [다오 운영 방식](https://www.antler.co/blog/daos-and-web3-governance-the-promise-implications-and-challenges-ahead) 그리고 [토큰화된 보상구조](https://cdixon.org/2017/05/27/crypto-tokens-a-breakthrough-in-open-network-design)는 과학 자금에 혁명을 일으킬 수 있는 Web3 도구 중 일부입니다. +Web3는 DAO와 Web3가 광범위하게 개발한 다양한 보상 모델을 실험함으로써 이 깨진 자금 조달 모델을 혼란에 빠뜨릴 가능성이 있습니다. [소급적 공공재 자금 지원](https://medium.com/ethereum-optimism/retroactive-public-goods-funding-33c9b7d00f0c), [이차 펀딩](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=2003531), [DAO 거버넌스](https://www.antler.co/blog/daos-and-web3-governance-the-promise-implications-and-challenges-ahead), [토큰화된 인센티브 구조](https://cdixon.org/2017/05/27/crypto-tokens-a-breakthrough-in-open-network-design)는 과학 자금 지원에 혁명을 일으킬 수 있는 Web3 도구의 일부입니다. ### IP 소유권 및 개발 {#ip-ownership} -지적 재산권(IP)은 대학에 갇히거나 생명공학에 사용되지 않는 것부터 평가하기 어려운 악명 높은 것까지 전통적인 과학에서 큰 문제입니다. 그러나 디지털 자산(과학 데이터 또는 기사와 같은) 의 소유권은 Web3가 [대체 불가능한 토큰(NFT)](/nft/)을 사용하여 예외적으로 잘 하는 것입니다. +지적 재산권(IP)은 대학에 갇히거나 생명공학에 사용되지 않는 것부터 평가하기 어려운 악명 높은 것까지 전통적인 과학에서 큰 문제입니다. 그러나 과학 데이터나 논문과 같은 디지털 자산의 소유권은 Web3가 [대체 불가능한 토큰(NFT)](/glossary/#nft)을 사용하여 특히 잘 처리하는 부분입니다. NFT가 향후 거래에 대한 수익을 원래 작성자에게 다시 전달할 수 있는 것과 같은 방식으로 연구자, 관리 기관(예: DAO) 또는 데이터를 수집한 주체에게 보상하기 위해 투명한 가치 귀속 체인을 설정할 수 있습니다. -[IP-NFT](https://medium.com/molecule-blog/ip-nfts-for-researchers-a-new-biomedical-funding-paradigm-91312d8d92e6)는 또한 수행 중인 연구 실험의 분산된 데이터 저장소의 열쇠 역할을 할 수 있으며 NFT 및 [DeFi](/defi/) 금융화(금융에서 대출 풀 및 가치 평가까지)에 연결할 수 있습니다. 또한 [VitaDAO](https://www.vitadao.com/)와 같은 DAO와 같은 본질적으로 온체인 단체가 온 체인에서 직접 연구를 수행할 수 있습니다. 양도할 수 없는 ["soulbound" 토큰](https://vitalik.eth.limo/general/2022/01/26/soulbound.html)의 출현은 또한 개인이 이더리움 주소와 연결된 경험과 자격 증명을 증명할 수 있도록 함으로써 DeFi 에서 중요한 역할을 할 수 있습니다. +[IP-NFT](https://medium.com/molecule-blog/ip-nfts-for-researchers-a-new-biomedical-funding-paradigm-91312d8d92e6)는 수행 중인 연구 실험의 탈중앙화된 데이터 저장소에 대한 키 역할을 할 수도 있으며, NFT 및 [DeFi](/glossary/#defi) 금융화(분할부터 대출 풀 및 가치 평가까지)에 연결할 수 있습니다. 또한 [VitaDAO](https://www.vitadao.com/)와 같은 DAO와 같은 네이티브 온체인 엔티티가 온체인에서 직접 연구를 수행할 수 있도록 합니다. +양도 불가능한 ["소울바운드" 토큰](https://vitalik.eth.limo/general/2022/01/26/soulbound.html)의 등장은 개인이 자신의 이더리움 주소에 연결된 경험과 자격 증명을 증명할 수 있도록 하여 DeSci에서 중요한 역할을 할 수 있습니다. ### 데이터 저장, 액세스 및 아키텍처 {#data-storage} 과학적 데이터는 Web3 패턴을 사용하여 훨씬 더 쉽게 접근할 수 있으며, 분산 저장은 연구가 무시무시한 사건에서 살아남을 수 있게 해줍니다. -출발점은 적절한 검증 가능한 자격 증명을 보유한 탈중앙화된 신원이 접근할 수 있는 시스템이어야 합니다. 이를 통해 신뢰할 수 있는 당사자가 민감한 데이터를 안전하게 복제할 수 있으며, 중복 및 검열 저항, 결과 재현, 심지어 여러 당사자가 협력하고 데이터 세트에 새로운 데이터를 추가할 수 있습니다. [Compute-to-data](https://7wdata.be/predictive-analytics/compute-to-data-using-blockchain-to-decentralize-data-science-and-ai-with-the-ocean-protocol)와 같은 기밀 컴퓨팅 방법은 원시 데이터 복제에 대한 대체 액세스 메커니즘을 제공하여 대부분의 민감한 데이터에 대한 신뢰할 수 있는 연구 환경을 조성합니다. 신뢰할 수 있는 연구 환경은 [NHS에 의해 인용되었으며](https://medium.com/weavechain/whats-in-store-for-the-future-of-healthcare-data-b6398745fbbb) 연구자들이 코드와 관행을 공유하기 위해 표준화 환경을 사용하여 현장에서 데이터와 안전하게 작업할 수 있는 생태계를 만드는 데이터 개인정보 보호 및 협업에 대한 미래 지향적인 솔루션입니다. +출발점은 적절한 검증 가능한 자격 증명을 보유한 탈중앙화된 신원이 접근할 수 있는 시스템이어야 합니다. 이를 통해 신뢰할 수 있는 당사자가 민감한 데이터를 안전하게 복제할 수 있으며, 중복 및 검열 저항, 결과 재현, 심지어 여러 당사자가 협력하고 데이터 세트에 새로운 데이터를 추가할 수 있습니다. [컴퓨트 투 데이터](https://7wdata.be/predictive-analytics/compute-to-data-using-blockchain-to-decentralize-data-science-and-ai-with-the-ocean-protocol)와 같은 기밀 컴퓨팅 방법은 원시 데이터 복제에 대한 대안적인 액세스 메커니즘을 제공하여 가장 민감한 데이터에 대한 신뢰할 수 있는 연구 환경을 만듭니다. 신뢰할 수 있는 연구 환경은 연구자가 코드 및 관행 공유를 위해 표준화된 환경을 사용하여 현장에서 데이터를 안전하게 사용할 수 있는 생태계를 조성함으로써 데이터 개인 정보 보호 및 협업을 위한 미래 지향적인 솔루션으로 [NHS에 의해 인용되었습니다](https://medium.com/weavechain/whats-in-store-for-the-future-of-healthcare-data-b6398745fbbb). 유연한 Web3 데이터 해결책은 위의 시나리오를 지원하고 연구자가 액세스 권한이나 수수료 없이 공공재 만들 수 있는 진정한 개방형 과학의 기반을 제공합니다. IPFS, Arweave 및 Filecoin과 같은 Web3 공용 데이터 해결책은 탈중앙화에 최적화되어 있습니다. 예를 들어, 기후변화는 기상 관측소와 예측 기후 모델을 포함한 기후 및 날씨 데이터에 대한 보편적인 접근을 제공합니다. @@ -90,48 +91,49 @@ NFT가 향후 거래에 대한 수익을 원래 작성자에게 다시 전달할 프로젝트를 탐색하고 DeSci 커뮤니티에 가입하세요. -- [DeSci.Global: 글로벌 이벤트 및 모임 일정](https://desci.global) -- [과학을 위한 블록체인 Telegram](https://t.me/BlockchainForScience) -- [Molecule: 연구 프로젝트에 자금을 지원하고 자금을 지원받으세요](https://discover.molecule.to/) -- [VitaDAO: 장수 연구를 위한 후원 연구 계약을 통해 자금을 받으세요](https://www.vitadao.com/) -- [ResearchHub: 과학적 결과를 게시하고 동료들과 대화에 참여하세요](https://www.researchhub.com/) -- [dClimate API: 분산된 커뮤니티에서 수집한 기후 데이터 쿼리](https://www.dclimate.net/) -- [DeFi Foundation: DeFi 게시 도구 빌더](https://descifoundation.org/) -- [DeSci.World: 사용자가 보고, 탈중앙화 과학에 참여할 수 있는 원스톱 상점](https://desci.world) -- [플레밍 프로토콜: 협업 생물 의학 발견을 촉진하는 오픈 소스 데이터 경제](https://medium.com/@FlemingProtocol/a-data-economy-for-patient-driven-biomedical-innovation-9d56bf63d3dd) -- [OceanDAO: DAO에서 관리하는 데이터 관련 과학을 위한 펀딩](https://oceanprotocol.com/dao) -- [Opscientia: 개방형 탈중앙화 과학 작업 흐름](https://opsci.io/research/) -- [Bio.xyz: 생명공학 DAO 또는 desci 프로젝트에 자금을 지원받으세요](https://www.molecule.to/) -- [ResearchHub: 과학적 결과를 게시하고 동료들과 대화에 참여하세요](https://www.researchhub.com/) -- [VitaDAO: 장수 연구를 위한 후원 연구 계약을 통해 자금을 받으세요](https://www.vitadao.com/) -- [플레밍 프로토콜: 협업 생물 의학 발견을 촉진하는 오픈 소스 데이터 경제](https://medium.com/@FlemingProtocol/a-data-economy-for-patient-driven-biomedical-innovation-9d56bf63d3dd) -- [능동적 추론 실험실](https://www.activeinference.org/) -- [CureDAO: 지역 사회 소유의 정밀 건강 플랫폼.](https://docs.curedao.org/) -- [IdeaMarkets: 탈중앙화 과학적 신뢰성을 가능하게 합니다.](https://ideamarket.io/) +- [DeSci.Global: 글로벌 이벤트 및 밋업 캘린더](https://desci.global) +- [Blockchain for Science 텔레그램](https://t.me/BlockchainForScience) +- [Molecule: 연구 프로젝트에 자금을 지원하고 자금 지원받기](https://www.molecule.xyz/) +- [VitaDAO: 수명 연장 연구를 위한 후원 연구 계약을 통해 자금 지원받기](https://www.vitadao.com/) +- [ResearchHub: 과학적 결과를 게시하고 동료들과 대화하기](https://www.researchhub.com/) +- [dClimate API: 탈중앙화 커뮤니티에서 수집한 기후 데이터 쿼리](https://www.dclimate.net/) +- [DeSci Foundation: DeSci 퍼블리싱 도구 빌더](https://descifoundation.org/) +- [DeSci.World: 사용자가 탈중앙화 과학을 보고 참여할 수 있는 원스톱 숍](https://desci.world) +- [OceanDAO: 데이터 관련 과학을 위한 DAO 거버넌스 펀딩](https://oceanprotocol.com/) +- [Opscientia: 개방형 탈중앙화 과학 워크플로](https://opsci.io/research/) +- [Bio.xyz: 생명공학 DAO 또는 desci 프로젝트를 위한 자금 지원받기](https://www.bio.xyz/) +- [Fleming Protocol: 협업 생물의학 발견을 촉진하는 오픈 소스 데이터 경제](http://flemingprotocol.io/) +- [Active Inference Institute](https://www.activeinference.org/) +- [IdeaMarkets: 탈중앙화된 과학적 신뢰성 지원](https://ideamarket.io/) - [DeSci Labs](https://www.desci.com/) +- [ValleyDAO: 합성 생물학 연구를 위한 자금 및 중개 연구를 지원하는 개방형 글로벌 커뮤니티](https://www.valleydao.bio) +- [Cerebrum DAO: 뇌 건강을 증진하고 신경 퇴행을 예방하기 위한 솔루션 소싱 및 육성](https://www.cerebrumdao.com/) +- [CryoDAO: 동결 보존 분야의 문샷 연구에 자금 지원](https://www.cryodao.org) +- [Elata: 정신과 의학의 미래에 목소리를 내세요](https://www.elata.bio/) -우리는 새로운 프로젝트에 대한 제안을 환영합니다 - 시작하려면 [목록 정책](/contributing/adding-desci-projects/)을 보세요! +등록할 새로운 프로젝트에 대한 제안을 환영합니다. 시작하려면 [등록 정책](/contributing/adding-desci-projects/)을 확인해 주세요! -## 더 읽을거리 {#further-reading} +## 더 읽어보기 {#further-reading} -- [Jocelynn Pearl과 Ultrarare의 DeSci Wiki](https://docs.google.com/document/d/1aQC6zn-eXflSmpts0XGE7CawbUEHwnL6o-OFXO52PTc/edit#) -- [A16z 미래를 위한 Jocelynn Pearl의 분산형 생명공학 가이드](https://future.a16z.com/a-guide-to-decentralized-biotech/) -- [DeSci의 사례](https://gitcoin.co/blog/desci-the-case-for-decentralised-science/) +- [Jocelynn Pearl 및 Ultrarare의 DeSci 위키](https://docs.google.com/document/d/1aQC6zn-eXflSmpts0XGE7CawbUEHwnL6o-OFXO52PTc/edit#) +- [a16z future를 위해 Jocelynn Pearl이 작성한 탈중앙화 생명공학 가이드](https://future.a16z.com/a-guide-to-decentralized-biotech/) +- [DeSci를 지지하는 이유](https://gitcoin.co/blog/desci-the-case-for-decentralised-science/) - [DeSci 가이드](https://future.com/what-is-decentralized-science-aka-desci/) -- [탈중앙화 과학 참고 자료](https://www.vincentweisser.com/desci) -- [분자의 바이오제약회사 IP-NFT - 기술 설명](https://molecule.to/blog/molecules-biopharma-ip-nfts-a-technical-description) -- [존 스타의 신뢰할 수 없는 과학 시스템 구축](https://medium.com/@jringo/building-systems-of-trustless-science-1cd2d072f673) -- [생명공학 DAO의 출현](https://molecule.to/blog/the-emergence-of-biotech-daos) -- [Paul Kohlhaas - DeSci: 분산 과학의 미래(팟캐스트)](https://anchor.fm/andrew-steinwold/episodes/Paul-Kohlhaas---DeSci-The-Future-of-Decentralized-Science---Zima-Red-ep-117-e1h683a) -- [분산 과학을 위한 적극적인 추론 존재론: 위치한 감각 만들기에서 Epistemic Commons까지](https://zenodo.org/record/6320575) -- [DeSci: 사무엘 아키노쇼의 연구의 미래](https://lucidsamuel.medium.com/desci-the-future-of-research-b76cfc88c8ec) -- [나디아의 과학 자금 조달 (끝맺음말: DeSci 및 새로운 암호화 기초 요소)](https://nadia.xyz/science-funding) -- [탈중앙화는 약물 개발을 방해하고 있습니다.](https://medium.com/id-theory/decentralisation-is-disrupting-drug-development-28b5ba5d447f) - -### 영상 {#videos} - -- [탈중앙화 과학이란 무엇인가요?](https://www.youtube.com/watch?v=-DeMklVWNdA) -- [장수 연구와 암호화폐의 교차점에 대한 비탈릭 부테린과 과학자 오브리 드 그레이의 대화](https://www.youtube.com/watch?v=x9TSJK1widA) -- [과학 출판이 망가졌습니다. Web3가 고칠 수 있나요?](https://www.youtube.com/watch?v=WkvzYgCvWj8) -- [후안 베넷 - DeSci, 독립 연구소 및 대규모 데이터 과학](https://www.youtube.com/watch?v=zkXM9H90g_E) -- [Sebastian Brunemeier - DeSci가 생물 의학 연구 및 벤처 캐피탈을 변화시킬 수 있는 방법](https://www.youtube.com/watch?v=qB4Tc3FcVbM) +- [탈중앙화 과학 리소스](https://www.vincentweisser.com/desci) +- [Molecule의 바이오제약 IP-NFT - 기술 설명](https://www.molecule.xyz/blog/molecules-biopharma-ip-nfts-a-technical-description) +- [Jon Starr의 신뢰가 필요 없는 과학 시스템 구축](https://medium.com/@jringo/building-systems-of-trustless-science-1cd2d072f673) +- [Paul Kohlhaas - DeSci: 탈중앙화 과학의 미래(팟캐스트)](https://anchor.fm/andrew-steinwold/episodes/Paul-Kohlhaas---DeSci-The-Future-of-Decentralized-Science---Zima-Red-ep-117-e1h683a) +- [탈중앙화 과학을 위한 능동적 추론 온톨로지: 상황 기반 의미 형성에서 인식적 공유지로](https://zenodo.org/record/6320575) +- [Samuel Akinosho의 DeSci: 연구의 미래](https://lucidsamuel.medium.com/desci-the-future-of-research-b76cfc88c8ec) +- [Nadia의 과학 자금 지원(에필로그: DeSci와 새로운 암호화 프리미티브)](https://nadia.xyz/science-funding) +- [탈중앙화가 신약 개발을 혁신하다](https://medium.com/id-theory/decentralisation-is-disrupting-drug-development-28b5ba5d447f) +- [DeSci란 무엇인가 – 탈중앙화 과학?](https://usadailytimes.com/2022/09/12/what-is-desci-decentralized-science/) + +### 동영상 {#videos} + +- [탈중앙화 과학이란?](https://www.youtube.com/watch?v=-DeMklVWNdA) +- [장수 연구와 암호화폐의 교차점에 대한 Vitalik Buterin과 과학자 Aubrey de Grey의 대화](https://www.youtube.com/watch?v=x9TSJK1widA) +- [과학 출판이 망가졌습니다. Web3가 해결할 수 있을까?](https://www.youtube.com/watch?v=WkvzYgCvWj8) +- [Juan Benet - DeSci, 독립 연구소 및 대규모 데이터 과학](https://www.youtube.com/watch?v=zkXM9H90g_E) +- [Sebastian Brunemeier - DeSci가 생물의학 연구 및 벤처 캐피털을 혁신하는 방법](https://www.youtube.com/watch?v=qB4Tc3FcVbM) +- [Paige Donner - Web3 및 블록체인을 이용한 오픈 사이언스 툴링](https://www.youtube.com/watch?v=nC-2QWQ-lgw&t=17s) diff --git a/public/content/translations/ko/developers/docs/accounts/index.md b/public/content/translations/ko/developers/docs/accounts/index.md new file mode 100644 index 00000000000..bdf4271142d --- /dev/null +++ b/public/content/translations/ko/developers/docs/accounts/index.md @@ -0,0 +1,137 @@ +--- +title: "이더리움 계정" +description: "이더리움 계정에 대한 설명 - 이더리움 데이터 구조와 주요 키 페어 크립토그래피들의 관계" +lang: ko +--- + +이더리움 계정은 이더(ETH) 잔액이 있으며 이더리움에 메시지를 전송할 수 있는 개체입니다. 계정은 사용자가 직접 제어하거나 스마트 계약을 통해 배포할 수도 있습니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하려면 먼저 [이더리움 소개](/developers/docs/intro-to-ethereum/)를 읽어보시는 것을 권장합니다. + +## 계정 유형 {#types-of-account} + +이더리움에는 두 가지의 계정 종류가 있습니다. + +- 외부 계정 - 해당 계정의 개인 키가 있는 사람이라면 누구나 제어할 수 있습니다 +- 컨트랙트 계정 - 네트워크에 배포된 스마트 계약이며 코드를 통해 제어합니다 [스마트 계약](/developers/docs/smart-contracts/)에 대해 알아보기 + +두 가지의 계정 종류 모두 아래와 같은 기능이 있습니다. + +- ETH 및 토큰 수령, 보유, 전송 +- 배포된 스마트 계약과 상호작용 + +### 주요 차이점 {#key-differences} + +**외부 소유 계정** + +- 비용 없이 계정을 만들 수 있습니다. +- 트랜잭션을 개시할 수 있습니다. +- 외부 소유 계정 간에는 ETH 또는 토큰 전송 거래만 가능합니다. +- 계정 활동을 제어하는 공개키와 비밀키로 만들어집니다. + +**컨트랙트 계정** + +- 네트워크 스토리지를 사용하기 때문에 계정을 만들 때 비용이 듭니다. +- 트랜잭션 수신에 대한 응답으로만 메시지를 전송할 수 있습니다. +- 외부 소유 계정에서 컨트랙트 계정으로의 트랜잭션은 토큰 전송이나 더 나아가 신규 컨트랙트 생성과 같은 다양한 작업을 실행할 수 있는 코드를 트리거 할 수 있습니다. +- 컨트랙트 계정은 비밀키를 갖고 있지 않습니다. 대신, 스마트 컨트랙트 로직에 의해 제어됩니다. + +## 계정 살펴보기 {#an-account-examined} + +이더리움 계정에는 네 가지의 값이 있습니다. + +- `nonce` – 외부 소유 계정에서 전송한 트랜잭션 수 또는 컨트랙트 계정으로 생성된 컨트랙트 수를 나타내는 카운터입니다. 주어진 논스로는 한 계정당 하나의 트랜잭션만 수행될 수 있으며, 이는 이미 수행된 트랜잭션의 반복적인 전송과 수행을 이용한 반복 공격을 방지할 수 있습니다. +- `balance` – 해당 주소가 보유하고 있는 wei의 값입니다. 웨이(Wei)는 ETH의 단위이며 100경 Wei는 1 ETH를 나타냅니다. +- `codeHash` – 이 해시는 이더리움 가상 머신(EVM)에 있는 계정의 코드를 나타냅니다. 계약 계정에는 서로 다른 작업을 실행할 수 있도록 프로그램된 코드 조각들이 있습니다. 이 EVM 코드는 계정이 메시지 콜을 받았을 때 실행됩니다. 이 값은 다른 계정 값과는 다르게 바꿀 수 없습니다. 추후 검색을 위해 모든 코드 조각들은 상태 데이터베이스 내에 그에 해당하는 해쉬값 아래 보관됩니다. 이 해쉬값이 바로 codeHash입니다. 외부 소유 계정의 경우, codeHash 필드는 빈 문자열 해시입니다. +- `storageRoot` – 스토리지 해시라고도 합니다. 계정의 스토리지 콘텐츠(256비트 정수 값 간의 매핑)를 인코딩하는 [머클 패트리샤 트리](/developers/docs/data-structures-and-encoding/patricia-merkle-trie/) 루트 노드의 256비트 해시입니다. 이는 256비트 정수 키의 Keccak-256 해시에서 RLP로 인코딩된 256비트 정수 값으로의 매핑으로 트라이에 인코딩됩니다. 이 트리는 계정에 저장된 내용을 해시로 인코딩한 것으로, 기본적으로는 비어 있습니다. + +![계정의 구성을 보여주는 다이어그램](./accounts.png) +_[Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)에서 발췌한 다이어그램_ + +## 외부 소유 계정과 키 쌍 {#externally-owned-accounts-and-key-pairs} + +계정은 공개 및 비공개 암호화 키 쌍으로 구성됩니다. 이러한 키 쌍들로 발송인이 실제로 트랜잭션에 서명하였는 지 증명하고 위조를 방지할 수 있습니다. 개인 키는 트랜잭션에 서명하는 데 쓰이며, 계정과 연결된 자금을 보관할 수 있도록 합니다. 본인은 실제로 암호화폐를 소유하지 않으며, 개인 키만을 가지고 있다는 사실을 기억하세요. 자금은 언제나 이더리움 원장 상에 존재합니다. + +트랜잭션 전송인을 항상 검증할 수 있기 때문에 의심스러운 사용자들이 가짜 트랜잭션을 전송하는 것을 방지할 수 있습니다. + +앨리스가 계정에서 밥의 계정으로 이더를 보내려면 엘리스는 트랜잭션 요청을 생성한 후 검증을 위해 트랜잭션을 네트워크로 보내야 합니다. 이더리움의 공개 키 암호 사용은 앨리스가 그 트랜잭션 요청을 처음 개시함을 증명할 수 있음을 보장합니다. 암호화 메커니즘이 없다면, 악의적 상대방인 이브가 "앨리스의 계정에서 이브의 계정으로 5 ETH 전송"과 같은 요청을 그냥 공개적으로 퍼뜨릴 수 있고 아무도 그러한 요청이 앨리스로부터 오지 않았음을 검증할 수 없을 겁니다. + +## 계정 생성 {#account-creation} + +계정을 생성하려면 대부분의 라이브러리가 무작위 비공개 키를 생성해 줍니다. + +개인 키는 64개의 16진수 문자로 이루어져 있고 비밀번호로 암호화 가능합니다. + +예시: + +`fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036415f` + +[타원 곡선 디지털 서명 알고리즘](https://wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm)을 사용하여 개인 키에서 공개 키가 생성됩니다. 공개 키의 Keccak-256 해시값 중 마지막 20바이트를 가져와 맨 앞에 `0x`를 추가하면 계정의 공개 주소를 얻을 수 있습니다. + +즉, 외부 소유 계정(EOA)은 42자의 주소(20바이트 세그먼트, 40개의 16진수 문자와 `0x` 접두사)로 구성됩니다. + +예시: + +`0x5e97870f263700f46aa00d967821199b9bc5a120` + +다음 예제는 [Clef](https://geth.ethereum.org/docs/tools/clef/introduction)라는 서명 도구를 사용하여 새 계정을 생성하는 방법을 보여줍니다. Clef는 계정 관리 및 서명 도구로 이더리움 클라이언트인 [Geth](https://geth.ethereum.org)와 함께 제공됩니다. `clef newaccount` 명령어는 새로운 키 쌍을 생성하고 암호화된 키스토어에 저장합니다. + +``` +> clef newaccount --keystore + +생성할 새 계정의 암호를 입력하세요: +> + +------------ +INFO [10-28|16:19:09.156] 새 키가 생성되었습니다 address=0x5e97870f263700f46aa00d967821199b9bc5a120 +WARN [10-28|16:19:09.306] 키 파일을 백업하세요 path=/home/user/go-ethereum/data/keystore/UTC--2022-10-28T15-19-08.000825927Z--5e97870f263700f46aa00d967821199b9bc5a120 +WARN [10-28|16:19:09.306] 암호를 꼭 기억하세요! +생성된 계정 0x5e97870f263700f46aa00d967821199b9bc5a120 +``` + +[Geth 문서](https://geth.ethereum.org/docs) + +개인 키로부터 새 공개 키를 파생하는 것은 가능하지만, 공개 키로부터 개인 키를 파생할 수는 없습니다. 개인 키를 안전하게 보관하고 이름 그대로 비공개(PRIVATE)로 유지하는 것이 중요합니다. + +여러분은 메세지와 트랜잭션을 서명해서 서명을 만들기 위해서 개인 키가 필요합니다. 그러면 다른이들은 여러분의 공개 키를 도출해서 그 메시지의 작성자를 증명하기 위해서 그 서명을 획득 할 수 있습니다. 애플리케이션에서 JavaScript 라이브러리를 사용하여 네트워크에 트랜잭션을 전송할 수 있습니다. + +## 컨트랙트 계정 {#contract-accounts} + +컨트랙트 계정 또한 42개 문자로 이루어진 16진수 주소를 갖습니다. + +예시: + +`0x06012c8cf97bead5deae237070f9587f8e7a266d` + +컨트랙트 주소는 대개 컨트랙트가 이더리움 블록체인에 배포되는 시점에 주어집니다. 이 주소는 그 생성자의 주소와 그 주소로부터 전송된 트랜잭션 번호("논스") 에서 추출됩니다. + +## 검증자 키 {#validators-keys} + +이더리움이 작업 증명에서 합의에 기반한 지분증명으로 바뀌면서 다른 타입의 키가 만들어집니다. 일명 BLS라는 키로, 이 키는 누가 검증자인지 구별하는데 쓰입니다. 이러한 키를 효율적으로 집계하여 네트워크가 합의에 도달하는 데 필요한 대역폭을 줄일 수 있습니다. 이 키 집계가 없으면 검증자의 최소 지분은 훨씬 더 높아질 것입니다. + +[검증자 키에 대해 더 알아보기](/developers/docs/consensus-mechanisms/pos/keys/). + +## 지갑에 대한 참고 사항 {#a-note-on-wallets} + +계정은 지갑이 아닙니다. 지갑은 외부 소유 계정 또는 계약 계정과 상호작용할 수 있게 해주는 인터페이스 또는 애플리케이션입니다. + +## 시각적 데모 {#a-visual-demo} + +오스틴이 해시 함수와 키 쌍에 대해 설명하는 것을 보세요. + + + + + +## 더 읽어보기 {#further-reading} + +- [이더리움 계정 이해하기](https://info.etherscan.com/understanding-ethereum-accounts/) - etherscan + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 관련 주제 {#related-topics} + +- [스마트 계약](/developers/docs/smart-contracts/) +- [트랜잭션](/developers/docs/transactions/) diff --git a/public/content/translations/ko/developers/docs/apis/backend/index.md b/public/content/translations/ko/developers/docs/apis/backend/index.md new file mode 100644 index 00000000000..2c7018becdc --- /dev/null +++ b/public/content/translations/ko/developers/docs/apis/backend/index.md @@ -0,0 +1,211 @@ +--- +title: "백엔드 API 라이브러리" +description: "사용자의 애플리케이션에서 블록체인과 상호작용 할 수 있는 이더리움 클라이언트 API에 대한 소개." +lang: ko +--- + +소프트웨어 애플리케이션이 이더리움 블록체인과 상호작용하려면(즉, 블록체인 데이터를 읽거나 네트워크에 트랜잭션을 보내려면) 이더리움 노드에 연결해야 합니다. + +이러한 목적을 위해 모든 이더리움 클라이언트는 [JSON-RPC](/developers/docs/apis/json-rpc/) 사양을 구현하므로 애플리케이션이 의존할 수 있는 통일된 [메서드](/developers/docs/apis/json-rpc/#json-rpc-methods) 세트가 있습니다. + +특수 프로그래밍 언어를 사용하여 이더리움 노드과 연결하려는 경우, 생태계 내부에 이러한 작업을 훨씬 용이하게 하는 편리한 라이브러리가 많이 있습니다. 개발자는 이러한 라이브러리를 사용하여 이더리움과 상호작용하는 JSON-RPC 요청(후드 아래)을 초기화하는 직관적인 단일 방법을 작성할 수 있습니다. + +## 필수 구성 요소 {#prerequisites} + +[이더리움 스택](/developers/docs/ethereum-stack/)과 [이더리움 클라이언트](/developers/docs/nodes-and-clients/)를 이해하면 도움이 될 수 있습니다. + +## 라이브러리를 왜 사용할까요? {#why-use-a-library} + +이러한 라이브러리는 이더리움 노드와 직접적으로 상호작용하는 많은 복잡성을 일반화합니다. 또한 유틸리티 함수(예: ETH를 Gwei로 변환)도 제공하므로 개발자는 이더리움 클라이언트의 복잡성을 처리하는 데 시간을 덜 들이고 애플리케이션의 고유 기능에 더 집중할 수 있습니다. + +## 사용 가능한 라이브러리 {#available-libraries} + +### 인프라 및 노드 서비스 {#infrastructure-and-node-services} + +**Alchemy -** **_이더리움 개발 플랫폼입니다._** + +- [alchemy.com](https://www.alchemy.com/) +- [개발문서](https://www.alchemy.com/docs/) +- [GitHub](https://github.com/alchemyplatform) +- [Discord](https://discord.com/invite/alchemyplatform) + +**All That Node -** **_서비스형 노드._** + +- [All That Node.com](https://www.allthatnode.com/) +- [개발문서](https://docs.allthatnode.com) +- [Discord](https://discord.gg/GmcdVEUbJM) + +**Blast by Bware Labs -** **_이더리움 메인넷 및 테스트넷을 위한 탈중앙화 API._** + +- [blastapi.io](https://blastapi.io/) +- [개발문서](https://docs.blastapi.io) +- [Discord](https://discord.gg/SaRqmRUjjQ) + +**BlockPi -** **_보다 효율적이고 빠른 RPC 서비스 제공_** + +- [blockpi.io](https://blockpi.io/) +- [개발문서](https://docs.blockpi.io/) +- [GitHub](https://github.com/BlockPILabs) +- [Discord](https://discord.com/invite/xTvGVrGVZv) + +** Cloudflare Ethereum 게이트웨이. ** + +- [cloudflare-eth.com](https://www.cloudflare.com/application-services/products/web3/) + +**Etherscan - 블록 탐색기 및 거래 API** + +- [개발문서](https://docs.etherscan.io/) + +**Blockscout - 오픈소스 블록 탐색기** + +- [개발문서](https://docs.blockscout.com/) + +**GetBlock-** **_Web3 개발을 위한 서비스형 블록체인_** + +- [GetBlock.io](https://getblock.io/) +- [개발문서](https://docs.getblock.io/) + +**Infura -** **_서비스형 이더리움 API._** + +- [infura.io](https://infura.io) +- [개발문서](https://docs.infura.io/api) +- [GitHub](https://github.com/INFURA) + +**Node RPC - _저비용의 EVM JSON-RPC 제공업체_** + +- [noderpc.xyz](https://www.noderpc.xyz/) +- [개발문서](https://docs.noderpc.xyz/node-rpc) + +**NOWNodes - _풀노드 및 블록 탐색기._** + +- [NOWNodes.io](https://nownodes.io/) +- [개발문서](https://nownodes.gitbook.io/documentation) + +**QuickNode -** **_서비스형 블록체인 인프라._** + +- [quicknode.com](https://quicknode.com) +- [개발문서](https://www.quicknode.com/docs/welcome) +- [Discord](https://discord.gg/quicknode) + +**Rivet -** **_오픈소스 소프트웨어로 구동되는 서비스형 이더리움 및 이더리움 클래식 API._** + +- [rivet.cloud](https://rivet.cloud) +- [개발문서](https://rivet.cloud/docs/) +- [GitHub](https://github.com/openrelayxyz/ethercattle-deployment) + +**Zmok -** **_속도 중심의 이더리움 노드인 JSON-RPC/WebSockets API._** + +- [zmok.io](https://zmok.io/) +- [GitHub](https://github.com/zmok-io) +- [개발문서](https://docs.zmok.io/) +- [Discord](https://discord.gg/fAHeh3ka6s) + +### 개발 도구 {#development-tools} + +**ethers-kt -** **_EVM 기반 블록체인을 위한 비동기, 고성능 Kotlin/Java/Android 라이브러리입니다._** + +- [GitHub](https://github.com/Kr1ptal/ethers-kt) +- [예제](https://github.com/Kr1ptal/ethers-kt/tree/master/examples) +- [Discord](https://discord.gg/rx35NzQGSb) + +**Nethereum -** **_블록체인을 위한 오픈소스 .NET 통합 라이브러리._** + +- [GitHub](https://github.com/Nethereum/Nethereum) +- [개발문서](http://docs.nethereum.com/en/latest/) +- [Discord](https://discord.com/invite/jQPrR58FxX) + +**Python Tooling -** **_Python을 통해 이더리움과 상호작용하기 위한 다양한 라이브러리._** + +- [py.ethereum.org](https://snakecharmers.ethereum.org/) +- [web3.py GitHub](https://github.com/ethereum/web3.py) +- [web3.py Chat](https://gitter.im/ethereum/web3.py) + +**Tatum -** **_최고의 블록체인 개발 플랫폼._** + +- [Tatum](https://tatum.io/) +- [GitHub](https://github.com/tatumio/) +- [개발문서](https://docs.tatum.io/) +- [Discord](https://discord.gg/EDmW3kjTC9) + +**web3j -** **_이더리움을 위한 Java/Android/Kotlin/Scala 통합 라이브러리._** + +- [GitHub](https://github.com/web3j/web3j) +- [개발문서](https://docs.web3j.io/) +- [Gitter](https://gitter.im/web3j/web3j) + +### 블록체인 서비스 {#blockchain-services} + +**BlockCypher -** **_이더리움 웹 API._** + +- [blockcypher.com](https://www.blockcypher.com/) +- [개발문서](https://www.blockcypher.com/dev/ethereum/) + +**Chainbase -** **_이더리움을 위한 올인원 web3 데이터 인프라._** + +- [chainbase.com](https://chainbase.com/) +- [개발문서](https://docs.chainbase.com/) +- [Discord](https://discord.gg/Wx6qpqz4AF) + +**Chainstack -** **_서비스형 탄력적 및 전용 이더리움 노드._** + +- [chainstack.com](https://chainstack.com) +- [개발문서](https://docs.chainstack.com/) +- [이더리움 API 레퍼런스](https://docs.chainstack.com/reference/ethereum-getting-started) + +**Coinbase Cloud Node -** **_블록체인 인프라 API._** + +- [Coinbase Cloud Node](https://www.coinbase.com/developer-platform) +- [개발문서](https://docs.cdp.coinbase.com/) + +**DataHub by Figment -** **_이더리움 메인넷 및 테스트넷을 갖춘 Web3 API 서비스._** + +- [DataHub](https://www.figment.io/) +- [개발문서](https://docs.figment.io/) + +**Moralis -** **_엔터프라이즈급 EVM API 제공업체._** + +- [moralis.io](https://moralis.io) +- [개발문서](https://docs.moralis.io/) +- [GitHub](https://github.com/MoralisWeb3) +- [Discord](https://moralis.io/joindiscord/) +- [포럼](https://forum.moralis.io/) + +**NFTPort -** **_이더리움 데이터 및 민팅 API._** + +- [nftport.xyz](https://www.nftport.xyz/) +- [개발문서](https://docs.nftport.xyz/) +- [GitHub](https://github.com/nftport/) +- [Discord](https://discord.com/invite/K8nNrEgqhE) + +**Tokenview -** **_범용 멀티 암호화폐 블록체인 API 플랫폼._** + +- [services.tokenview.io](https://services.tokenview.io/) +- [개발문서](https://services.tokenview.io/docs?type=api) +- [GitHub](https://github.com/Tokenview) + +**Watchdata -** **_이더리움 블록체인에 간단하고 신뢰할 수 있는 API 액세스를 제공합니다._** + +- [Watchdata](https://watchdata.io/) +- [개발문서](https://docs.watchdata.io/) +- [Discord](https://discord.com/invite/TZRJbZ6bdn) + +**Covalent -** **_200개 이상의 체인을 위한 풍부한 기능의 블록체인 API._** + +- [covalenthq.com](https://www.covalenthq.com/) +- [개발문서](https://www.covalenthq.com/docs/api/) +- [GitHub](https://github.com/covalenthq) +- [Discord](https://www.covalenthq.com/discord/) + +## 더 읽어보기 {#further-reading} + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 관련 주제 {#related-topics} + +- [노드 및 클라이언트](/developers/docs/nodes-and-clients/) +- [개발 프레임워크](/developers/docs/frameworks/) + +## 관련 튜토리얼 {#related-tutorials} + +- [JavaScript에서 이더리움 블록체인을 사용하도록 Web3js 설정하기](/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/) _– 프로젝트에 web3.js를 설정하는 방법에 대한 안내입니다._ +- [JavaScript에서 스마트 계약 호출하기](/developers/tutorials/calling-a-smart-contract-from-javascript/) _– DAI 토큰을 사용하여 JavaScript로 계약 함수를 호출하는 방법을 알아보세요._ diff --git a/public/content/translations/ko/developers/docs/apis/javascript/index.md b/public/content/translations/ko/developers/docs/apis/javascript/index.md new file mode 100644 index 00000000000..6a4255a9ac5 --- /dev/null +++ b/public/content/translations/ko/developers/docs/apis/javascript/index.md @@ -0,0 +1,289 @@ +--- +title: "자바스크립트 API 라이브러리" +description: "애플리케이션에서 블록체인과 상호작용할 수 있는 자바스크립트 클라이언트 라이브러리를 소개합니다." +lang: ko +--- + +웹 앱이 이더리움 블록체인과 상호작용하려면(즉, 블록체인 데이터를 읽거나 네트워크에 트랜잭션을 보내려면) 이더리움 노드에 연결해야 합니다. + +이를 위해 모든 이더리움 클라이언트는 [JSON-RPC](/developers/docs/apis/json-rpc/) 사양을 구현하므로 애플리케이션이 의존할 수 있는 통일된 [메서드](/developers/docs/apis/json-rpc/#json-rpc-methods) 집합이 있습니다. + +자바스크립트를 사용하여 이더리움 노드에 연결하려는 경우, 바닐라 자바스크립트를 사용할 수도 있지만, 생태계 내에 이를 훨씬 쉽게 만들어주는 여러 편의 라이브러리가 존재합니다. 개발자는 이러한 라이브러리를 사용하여 이더리움과 상호작용하는 JSON-RPC 요청(후드 아래)을 초기화하는 직관적인 단일 방법을 작성할 수 있습니다. + +[병합](/roadmap/merge/) 이후, 노드를 실행하려면 실행 클라이언트와 합의 클라이언트라는 두 개의 연결된 이더리움 소프트웨어가 필요하다는 점에 유의하세요. 노드에 실행 클라이언트와 합의 클라이언트가 모두 포함되어 있는지 확인하세요. 노드가 로컬 컴퓨터에 없는 경우(예: AWS 인스턴스에서 노드가 실행되는 경우), 튜토리얼의 IP 주소를 적절하게 업데이트하세요. 자세한 내용은 [노드 실행하기](/developers/docs/nodes-and-clients/run-a-node/) 페이지를 참조하세요. + +## 필수 구성 요소 {#prerequisites} + +자바스크립트를 이해하는 것 외에도 [이더리움 스택](/developers/docs/ethereum-stack/)과 [이더리움 클라이언트](/developers/docs/nodes-and-clients/)를 이해하는 것이 도움이 될 수 있습니다. + +## 라이브러리를 왜 사용할까요? {#why-use-a-library} + +이러한 라이브러리는 이더리움 노드와 직접적으로 상호작용하는 많은 복잡성을 일반화합니다. 또한 유틸리티 함수(예: ETH를 Gwei로 변환)도 제공하므로 개발자는 이더리움 클라이언트의 복잡성을 처리하는 데 시간을 덜 들이고 애플리케이션의 고유 기능에 더 집중할 수 있습니다. + +## 라이브러리 기능 {#library-features} + +### 이더리움 노드에 연결 {#connect-to-ethereum-nodes} + +이 라이브러리는 공급자를 사용하여 JSON-RPC, INFURA, Etherscan, Alchemy 또는 MetaMask를 통해 이더리움에 연결하고 데이터를 읽을 수 있게 해줍니다. + +> **경고:** Web3.js는 2025년 3월 4일에 아카이브되었습니다. [공지 사항 읽기](https://blog.chainsafe.io/web3-js-sunset/). 새로운 프로젝트에는 [ethers.js](https://ethers.org) 또는 [viem](https://viem.sh)과 같은 대체 라이브러리를 사용하는 것을 고려해 보세요. + +**Ethers 예시** + +```js +// BrowserProvider는 표준 Web3 공급자를 래핑하며, +// 이는 MetaMask가 각 페이지에 window.ethereum으로 주입하는 것입니다 +const provider = new ethers.BrowserProvider(window.ethereum) + +// MetaMask 플러그인을 사용하면 트랜잭션에 서명하여 +// 이더를 전송하고 블록체인 내 상태를 변경하기 위해 지불할 수 있습니다. +// 이를 위해 계정 서명자가 필요합니다... +const signer = provider.getSigner() +``` + +**Web3js 예시** + +```js +var web3 = new Web3("http://localhost:8545") +// 또는 +var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) + +// 공급자 변경 +web3.setProvider("ws://localhost:8546") +// 또는 +web3.setProvider(new Web3.providers.WebsocketProvider("ws://localhost:8546")) + +// node.js에서 IPC 공급자 사용 +var net = require("net") +var web3 = new Web3("/Users/myuser/Library/Ethereum/geth.ipc", net) // mac os 경로 +// 또는 +var web3 = new Web3( + new Web3.providers.IpcProvider("/Users/myuser/Library/Ethereum/geth.ipc", net) +) // mac os 경로 +// windows에서의 경로는 다음과 같습니다: "\\\\.\\pipe\\geth.ipc" +// linux에서의 경로는 다음과 같습니다: "/users/myuser/.ethereum/geth.ipc" +``` + +설정이 완료되면 블록체인에 다음을 쿼리할 수 있습니다. + +- 블록 번호 +- 가스 추정치 +- 스마트 계약 이벤트 +- 네트워크 ID +- 그 이상 많은것들... + +### 지갑 기능 {#wallet-functionality} + +이 라이브러리들은 지갑을 만들고, 키를 관리하고, 트랜잭션에 서명하는 기능을 제공합니다. + +다음은 Ethers의 예시입니다 + +```js +// 니모닉으로 지갑 인스턴스를 생성합니다... +mnemonic = + "announce room limb pattern dry unit scale effort smooth jazz weasel alcohol" +walletMnemonic = Wallet.fromPhrase(mnemonic) + +// ...또는 개인 키로 생성합니다 +walletPrivateKey = new Wallet(walletMnemonic.privateKey) + +walletMnemonic.address === walletPrivateKey.address +// 참 + +// 서명자 API에 따른 Promise로서의 주소 +walletMnemonic.getAddress() +// { Promise: '0x71CB05EE1b1F506fF321Da3dac38f25c0c9ce6E1' } + +// 지갑 주소는 동기적으로도 사용할 수 있습니다 +walletMnemonic.address +// '0x71CB05EE1b1F506fF321Da3dac38f25c0c9ce6E1' + +// 내부 암호화 구성 요소 +walletMnemonic.privateKey +// '0x1da6847600b0ee25e9ad9a52abbd786dd2502fa4005dd5af9310b7cc7a3b25db' +walletMnemonic.publicKey +// '0x04b9e72dfd423bcf95b3801ac93f4392be5ff22143f9980eb78b3a860c4843bfd04829ae61cdba4b3b1978ac5fc64f5cc2f4350e35a108a9c9a92a81200a60cd64' + +// 지갑 니모닉 +walletMnemonic.mnemonic +// { +// locale: 'en', +// path: 'm/44\'/60\'/0\'/0/0', +// phrase: 'announce room limb pattern dry unit scale effort smooth jazz weasel alcohol' +// } + +// 참고: 개인 키로 생성된 지갑은 +// 니모닉을 가지지 않습니다(파생 과정에서 이를 방지함) +walletPrivateKey.mnemonic +// null + +// 메시지 서명 +walletMnemonic.signMessage("Hello World") +// { Promise: '0x14280e5885a19f60e536de50097e96e3738c7acae4e9e62d67272d794b8127d31c03d9cd59781d4ee31fb4e1b893bd9b020ec67dfa65cfb51e2bdadbb1de26d91c' } + +tx = { + to: "0x8ba1f109551bD432803012645Ac136ddd64DBA72", + value: utils.parseEther("1.0"), +} + +// 트랜잭션 서명 +walletMnemonic.signTransaction(tx) +// { Promise: '0xf865808080948ba1f109551bd432803012645ac136ddd64dba72880de0b6b3a7640000801ca0918e294306d177ab7bd664f5e141436563854ebe0a3e523b9690b4922bbb52b8a01181612cec9c431c4257a79b8c9f0c980a2c49bb5a0e6ac52949163eeb565dfc' } + +// connect 메서드는 공급자에 연결된 +// 지갑의 새 인스턴스를 반환합니다 +wallet = walletMnemonic.connect(provider) + +// 네트워크 쿼리 +wallet.getBalance() +// { Promise: { BigNumber: "42" } } +wallet.getTransactionCount() +// { Promise: 0 } + +// 이더 전송 +wallet.sendTransaction(tx) +``` + +[전체 문서 읽기](https://docs.ethers.io/v5/api/signer/#Wallet) + +설정이 완료되면 다음을 수행할 수 있습니다. + +- 계정 생성 +- 트랜잭션 전송 +- 트랜잭션 서명 +- 그 이상 많은것들... + +### 스마트 계약 함수와 상호작용하기 {#interact-with-smart-contract-functions} + +자바스크립트 클라이언트 라이브러리를 사용하면 애플리케이션에서 컴파일된 계약의 애플리케이션 바이너리 인터페이스(ABI)를 읽어 스마트 계약 함수를 호출할 수 있습니다. + +ABI는 기본적으로 계약의 함수를 JSON 형식으로 설명하며, 이를 일반적인 자바스크립트 객체처럼 사용할 수 있게 해줍니다. + +따라서 다음 솔리디티 계약은: + +```solidity +contract Test { + uint a; + address d = 0x12345678901234567890123456789012; + + constructor(uint testInt) { a = testInt;} + + event Event(uint indexed b, bytes32 c); + + event Event2(uint indexed b, bytes32 c); + + function foo(uint b, bytes32 c) returns(address) { + Event(b, c); + return d; + } +} +``` + +다음과 같은 JSON이 생성됩니다. + +```json +[{ + "type":"constructor", + "payable":false, + "stateMutability":"nonpayable" + "inputs":[{"name":"testInt","type":"uint256"}], + },{ + "type":"function", + "name":"foo", + "constant":false, + "payable":false, + "stateMutability":"nonpayable", + "inputs":[{"name":"b","type":"uint256"}, {"name":"c","type":"bytes32"}], + "outputs":[{"name":"","type":"address"}] + },{ + "type":"event", + "name":"Event", + "inputs":[{"indexed":true,"name":"b","type":"uint256"}, {"indexed":false,"name":"c","type":"bytes32"}], + "anonymous":false + },{ + "type":"event", + "name":"Event2", + "inputs":[{"indexed":true,"name":"b","type":"uint256"},{"indexed":false,"name":"c","type":"bytes32"}], + "anonymous":false +}] +``` + +즉, 다음을 수행할 수 있습니다. + +- 스마트 계약에 트랜잭션을 보내고 메서드를 실행합니다 +- EVM에서 실행될 때 메서드 실행에 소요될 가스를 추정하기 위해 호출합니다 +- 계약 배포 +- 기타 등등... + +### 유틸리티 함수 {#utility-functions} + +유틸리티 함수는 이더리움 기반의 빌드를 좀 더 쉽게 만들어주는 편리한 단축 기능을 제공합니다. + +ETH 값은 기본적으로 Wei 단위입니다. 1 ETH = 1,000,000,000,000,000,000 WEI – 이는 매우 큰 숫자를 다룬다는 의미입니다! `web3.utils.toWei`는 이더를 Wei로 변환해 줍니다. + +그리고 ethers에서는 다음과 같습니다. + +```js +// 계정의 잔액을 가져옵니다(주소 또는 ENS 이름으로) +balance = await provider.getBalance("ethers.eth") +// { BigNumber: "2337132817842795605" } + +// 종종 사용자에게 보여주기 위해 출력을 포맷해야 합니다 +// 사용자는 wei 대신 이더 단위의 값을 선호합니다 +ethers.utils.formatEther(balance) +// '2.337132817842795605' +``` + +- [Web3js 유틸리티 함수](https://docs.web3js.org/api/web3-utils) +- [Ethers 유틸리티 함수](https://docs.ethers.org/v6/api/utils/) + +## 사용 가능한 라이브러리 {#available-libraries} + +**Web3.js -** **_이더리움 자바스크립트 API._** + +- [개발문서](https://docs.web3js.org) +- [GitHub](https://github.com/ethereum/web3.js) + +**Ethers.js -** **_자바스크립트 및 타입스크립트의 완전한 이더리움 지갑 구현 및 유틸리티._** + +- [Ethers.js 홈](https://ethers.org/) +- [개발문서](https://docs.ethers.io) +- [GitHub](https://github.com/ethers-io/ethers.js) + +**The Graph -** **_이더리움 및 IPFS 데이터를 인덱싱하고 GraphQL을 사용하여 쿼리하기 위한 프로토콜입니다._** + +- [The Graph](https://thegraph.com) +- [그래프 탐색기](https://thegraph.com/explorer) +- [개발문서](https://thegraph.com/docs) +- [GitHub](https://github.com/graphprotocol) +- [Discord](https://thegraph.com/discord) + +**Alchemy SDK -** **_향상된 API가 포함된 Ethers.js 래퍼._** + +- [개발문서](https://www.alchemy.com/docs) +- [GitHub](https://github.com/alchemyplatform/alchemy-sdk-js) + +**viem -** **_이더리움을 위한 타입스크립트 인터페이스._** + +- [개발문서](https://viem.sh) +- [GitHub](https://github.com/wagmi-dev/viem) + +**Drift -** **_내장 캐싱, 후크, 테스트 목(mock)이 포함된 타입스크립트 메타 라이브러리._** + +- [개발문서](https://ryangoree.github.io/drift/) +- [GitHub](https://github.com/ryangoree/drift/) + +## 더 읽어보기 {#further-reading} + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 관련 주제 {#related-topics} + +- [노드 및 클라이언트](/developers/docs/nodes-and-clients/) +- [개발 프레임워크](/developers/docs/frameworks/) + +## 관련 튜토리얼 {#related-tutorials} + +- [JavaScript에서 이더리움 블록체인을 사용하도록 Web3js 설정하기](/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/) _– 프로젝트에 web3.js를 설정하는 방법에 대한 안내입니다._ +- [JavaScript에서 스마트 계약 호출하기](/developers/tutorials/calling-a-smart-contract-from-javascript/) _– DAI 토큰을 사용하여 JavaScript로 계약 함수를 호출하는 방법을 알아보세요._ +- [web3와 Alchemy를 사용하여 트랜잭션 보내기](/developers/tutorials/sending-transactions-using-web3-and-alchemy/) _– 백엔드에서 트랜잭션을 보내는 단계별 안내입니다._ diff --git a/public/content/translations/ko/developers/docs/apis/json-rpc/index.md b/public/content/translations/ko/developers/docs/apis/json-rpc/index.md new file mode 100644 index 00000000000..745877ea96e --- /dev/null +++ b/public/content/translations/ko/developers/docs/apis/json-rpc/index.md @@ -0,0 +1,1898 @@ +--- +title: JSON-RPC APIs +description: "이더리움 클라이언트를 위한, 무상태성 경량 RPC(원격 프로시저 호출) 프로토콜" +lang: ko +--- + +소프트웨어 애플리케이션이 블록체인 데이터를 읽거나 네트워크에 트랜잭션을 전송하여 이더리움 블록체인과 상호작용하려면 이더리움 노드에 연결해야 합니다. + +이를 위해 모든 [이더리움 클라이언트](/developers/docs/nodes-and-clients/#execution-clients)는 [JSON-RPC 사양](https://github.com/ethereum/execution-apis)을 구현하므로 애플리케이션은 특정 노드나 클라이언트 구현에 관계없이 의존할 수 있는 통일된 메서드 집합이 있습니다. + +[JSON-RPC](https://www.jsonrpc.org/specification)는 무상태, 경량 원격 프로시저 호출(RPC) 프로토콜입니다. 여러 데이터 구조와 그 처리에 관한 규칙을 정의합니다. 소켓이나 HTTP 또는 다양한 메시지 전달 환경을 포함한 동일한 프로세스 내에서 개념을 사용할 수 있다는 점에서 전송의 추상화가 잘 이루어져 있습니다. (원문: agnostic; 불가지론자; 어떤 운영 체제나 프로세서의 조합에 대한 지식 없이도 기능을 수행할 수 있는, 여기에서는 추상화로 대체) 데이터 형식은 JSON(RFC 4627)으로 사용합니다. + +## 클라이언트 구현 {#client-implementations} + +이더리움 클라이언트는 JSON-RPC 사양을 구현할 때 각기 다른 프로그래밍 언어를 사용할 수 있습니다. 특정 프로그래밍 언어와 관련된 자세한 내용은 개별 [클라이언트 문서](/developers/docs/nodes-and-clients/#execution-clients)를 참조하세요. 최신 API 지원 정보는 각 클라이언트의 문서를 확인하는 게 좋습니다. + +## 편의성 라이브러리 {#convenience-libraries} + +JSON-RPC API를 통해 이더리움 클라이언트와 직접 상호 작용하는 방식을 선택할 수 있습니다. 그러나 dapp 개발자를 위한 더 쉬운 옵션도 있습니다. JSON-RPC API 위에 래퍼를 제공하기 위해 많은 [JavaScript](/developers/docs/apis/javascript/#available-libraries) 및 [백엔드 API](/developers/docs/apis/backend/#available-libraries) 라이브러리가 존재합니다. 개발자는 이런 라이브러리를 사용하여 이더리움과 상호 작용하는 JSON-RPC 요청을 초기화할 수 있습니다. 라이브러리를 잘 사용하면 개발을 위해 선택한 프로그래밍 언어로, 직관적인 한 줄 메서드를 작성할 수 있습니다. + +## 합의 클라이언트 API {#consensus-clients} + +이 페이지는 주로 이더리움 실행 클라이언트에서 사용하는 JSON-RPC API를 다룹니다. 그러나 합의 클라이언트에는 사용자가 노드에 대한 정보를 쿼리하고, 비콘 블록, 비콘 상태 및 기타 합의 관련 정보를 노드에서 직접 요청할 수 있는 RPC API도 있습니다. 이 API는 [Beacon API 웹페이지](https://ethereum.github.io/beacon-APIs/#/)에 문서화되어 있습니다. + +내부 API는 노드 내의 클라이언트 간 통신에도 사용됩니다. 즉, 합의 클라이언트와 실행 클라이언트가 데이터를 교환할 수 있게 해줍니다. 이를 '엔진 API'라고 하며 사양은 [GitHub](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md)에서 확인할 수 있습니다. + +## 실행 클라이언트 사양 {#spec} + +[GitHub에서 전체 JSON-RPC API 사양 읽기](https://github.com/ethereum/execution-apis). 이 API는 [실행 API 웹페이지](https://ethereum.github.io/execution-apis/)에 문서화되어 있으며 사용 가능한 모든 방법을 시험해 볼 수 있는 검사기를 포함합니다. + +## 규칙 {#conventions} + +### 16진수 값 인코딩 {#hex-encoding} + +형식이 지정되지 않은 바이트 배열과 수량이라는 두 가지 주요 데이터 유형이 JSON을 통해 전달됩니다. 둘 다 16진수 인코딩으로 전달되지만 형식 지정에 대한 요구 사항은 다릅니다. + +#### 수량 {#quantities-encoding} + +수량(정수, 숫자)을 인코딩할 때: 16진수로 인코딩하고, "0x"를 접두사로 붙이며, 가장 간결한 표현을 사용합니다(약간의 예외: 0은 "0x0"으로 표현해야 함). + +몇 가지 예는 다음과 같습니다. + +- 0x41 (10진수로 65) +- 0x400 (10진수로 1024) +- 잘못됨: 0x (항상 하나 이상의 숫자가 있어야 함 - 0은 "0x0") +- 잘못됨: 0x0400 (앞에 0을 붙일 수 없음) +- 잘못됨: ff (접두사 0x가 있어야 함) + +### 형식 없는 데이터 {#unformatted-data-encoding} + +형식 없는 데이터(바이트 배열, 계정 주소, 해시, 바이트코드 배열)를 인코딩할 때: 16진수로 인코딩하고, 접두사 "0x"를 붙이며, 바이트당 2개의 16진수 숫자를 사용합니다. + +몇 가지 예는 다음과 같습니다. + +- 0x41 (크기 1, "A") +- 0x004200 (크기 3, "0B0") +- 0x (크기 0, "") +- 잘못됨: 0xf0f0f (짝수 개의 숫자여야 함) +- 잘못됨: 004200 (접두사 0x가 있어야 함) + +### 블록 매개변수 {#block-parameter} + +다음 메서드에는 블록 매개변수가 있습니다: + +- [eth_getBalance](#eth_getbalance) +- [eth_getCode](#eth_getcode) +- [eth_getTransactionCount](#eth_gettransactioncount) +- [eth_getStorageAt](#eth_getstorageat) +- [eth_call](#eth_call) + +이더리움의 상태를 쿼리하는 요청이 이루어지면 제공된 블록 매개변수가 블록의 높이를 결정합니다. + +블록 매개변수에 대해 다음 옵션을 사용할 수 있습니다: + +- `16진수 문자열` - 정수 블록 번호 +- `문자열 "earliest"` - 가장 오래된/제네시스 블록 +- `문자열 "latest"` - 최신 제안 블록 +- `문자열 "safe"` - 최신 안전 헤드 블록 +- `문자열 "finalized"` - 최신 확정 블록 +- `문자열 "pending"` - 보류 중인 상태/트랜잭션 + +## 예시 + +이 페이지에서는 명령줄 도구인 [curl](https://curl.se)을 사용하여 개별 JSON_RPC API 엔드포인트를 사용하는 방법에 대한 예를 제공합니다. 이러한 개별 엔드포인트 예는 아래의 [Curl 예제](#curl-examples) 섹션에서 찾을 수 있습니다. 페이지의 뒷부분에서는 Geth 노드, JSON_RPC API 및 curl을 사용하여 스마트 계약을 컴파일하고 배포하는 [엔드투엔드 예제](#usage-example)도 제공합니다. + +## Curl 예제 {#curl-examples} + +이더리움 노드에 [curl](https://curl.se) 요청을 하여 JSON_RPC API를 사용하는 예제가 아래에 제공됩니다. 각 예제에는 +특정 엔드포인트에 대한 설명, 매개변수, 반환 유형 및 사용 방법에 대한 실제 예제가 포함됩니다. + +curl 요청은 콘텐츠 유형과 관련된 오류 메시지를 반환할 수 있습니다. 이는 `--data` 옵션이 콘텐츠 유형을 `application/x-www-form-urlencoded`로 설정하기 때문입니다. 노드에서 이와 관련하여 불만을 제기하는 경우, 호출 시작 부분에 `-H "Content-Type: application/json"`을 배치하여 헤더를 수동으로 설정하세요. 예제에는 curl에 마지막 인수로 제공되어야 하는 URL/IP 및 포트 조합(예: `127.0.0.1:8545`)도 포함되어 있지 않습니다. 이러한 추가 데이터를 포함하는 전체 curl 요청은 다음 형식을 취합니다: + +```shell +curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}' 127.0.0.1:8545 +``` + +## 가십, 상태, 기록 {#gossip-state-history} + +소수의 핵심 JSON-RPC 메서드는 이더리움 네트워크의 데이터가 필요하며, 가십, 상태, 기록이라는 세 가지 주요 범주로 깔끔하게 분류됩니다. 이 섹션의 링크를 사용하여 각 메서드로 이동하거나 목차를 사용하여 전체 메서드 목록을 탐색하세요. + +### 가십 메서드 {#gossip-methods} + +> 이 메서드들은 체인의 헤드를 추적합니다. 이것이 트랜잭션이 네트워크를 돌아다니고, 블록으로 들어가며, 클라이언트가 새로운 블록에 대해 알게 되는 방식입니다. + +- [eth_blockNumber](#eth_blocknumber) +- [eth_sendRawTransaction](#eth_sendrawtransaction) + +### 상태 메서드 {#state_methods} + +> 저장된 모든 데이터의 현재 상태를 보고하는 메서드입니다. '상태'는 하나의 큰 공유 RAM 조각과 같으며 계정 잔액, 계약 데이터 및 가스 추정치를 포함합니다. + +- [eth_getBalance](#eth_getbalance) +- [eth_getStorageAt](#eth_getstorageat) +- [eth_getTransactionCount](#eth_gettransactioncount) +- [eth_getCode](#eth_getcode) +- [eth_call](#eth_call) +- [eth_estimateGas](#eth_estimategas) + +### 기록 메서드 {#history_methods} + +> 제네시스까지 모든 블록의 과거 기록을 가져옵니다. 이것은 하나의 큰 추가 전용 파일과 같으며 모든 블록 헤더, 블록 본문, 엉클 블록 및 트랜잭션 영수증을 포함합니다. + +- [eth_getBlockTransactionCountByHash](#eth_getblocktransactioncountbyhash) +- [eth_getBlockTransactionCountByNumber](#eth_getblocktransactioncountbynumber) +- [eth_getUncleCountByBlockHash](#eth_getunclecountbyblockhash) +- [eth_getUncleCountByBlockNumber](#eth_getunclecountbyblocknumber) +- [eth_getBlockByHash](#eth_getblockbyhash) +- [eth_getBlockByNumber](#eth_getblockbynumber) +- [eth_getTransactionByHash](#eth_gettransactionbyhash) +- [eth_getTransactionByBlockHashAndIndex](#eth_gettransactionbyblockhashandindex) +- [eth_getTransactionByBlockNumberAndIndex](#eth_gettransactionbyblocknumberandindex) +- [eth_getTransactionReceipt](#eth_gettransactionreceipt) +- [eth_getUncleByBlockHashAndIndex](#eth_getunclebyblockhashandindex) +- [eth_getUncleByBlockNumberAndIndex](#eth_getunclebyblocknumberandindex) + +## JSON-RPC API 플레이그라운드 + +[플레이그라운드 도구](https://ethereum-json-rpc.com)를 사용하여 API 메서드를 검색하고 사용해 볼 수 있습니다. 또한 다양한 노드 제공업체에서 지원하는 메서드와 네트워크를 보여줍니다. + +## JSON-RPC API 메서드 {#json-rpc-methods} + +### web3_clientVersion {#web3_clientversion} + +현재 클라이언트의 버전을 반환합니다. + +**매개변수** + +없음 + +**반환 값** + +`문자열` - 현재 클라이언트 버전 + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}' +// 결과 +{ + "id":67, + "jsonrpc":"2.0", + "result": "Geth/v1.12.1-stable/linux-amd64/go1.19.1" +} +``` + +### web3_sha3 {#web3_sha3} + +주어진 데이터의 Keccak-256(표준화된 SHA3-256이 _아님_)을 반환합니다. + +**매개변수** + +1. `DATA` - SHA3 해시로 변환할 데이터 + +```js +params: ["0x68656c6c6f20776f726c64"] +``` + +**반환 값** + +`DATA` - 주어진 문자열의 SHA3 결과입니다. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"web3_sha3","params":["0x68656c6c6f20776f726c64"],"id":64}' +// 결과 +{ + "id":64, + "jsonrpc": "2.0", + "result": "0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad" +} +``` + +### net_version {#net_version} + +현재 네트워크 ID를 반환합니다. + +**매개변수** + +없음 + +**반환 값** + +`문자열` - 현재 네트워크 ID입니다. + +현재 네트워크 ID의 전체 목록은 [chainlist.org](https://chainlist.org)에서 확인할 수 있습니다. 일반적인 몇 가지 예는 다음과 같습니다: + +- `1`: 이더리움 메인넷 +- `11155111`: 세폴리아 테스트넷 +- `560048` : Hoodi 테스트넷 + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"net_version","params":[],"id":67}' +// 결과 +{ + "id":67, + "jsonrpc": "2.0", + "result": "3" +} +``` + +### net_listening {#net_listening} + +클라이언트가 네트워크 연결을 활발하게 수신하고 있으면 `true`를 반환합니다. + +**매개변수** + +없음 + +**반환 값** + +`부울` - 수신 중일 때는 `true`, 그렇지 않으면 `false`입니다. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"net_listening","params":[],"id":67}' +// 결과 +{ + "id":67, + "jsonrpc":"2.0", + "result":true +} +``` + +### net_peerCount {#net_peercount} + +현재 클라이언트에 연결된 피어 수를 반환합니다. + +**매개변수** + +없음 + +**반환 값** + +`QUANTITY` - 연결된 피어 수의 정수입니다. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":74}' +// 결과 +{ + "id":74, + "jsonrpc": "2.0", + "result": "0x2" // 2 +} +``` + +### eth_protocolVersion {#eth_protocolversion} + +현재 이더리움 프로토콜 버전을 반환합니다. 이 메서드는 [Geth에서 사용할 수 없음](https://github.com/ethereum/go-ethereum/pull/22064#issuecomment-788682924)에 유의하세요. + +**매개변수** + +없음 + +**반환 값** + +`문자열` - 현재 이더리움 프로토콜 버전 + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_protocolVersion","params":[],"id":67}' +// 결과 +{ + "id":67, + "jsonrpc": "2.0", + "result": "54" +} +``` + +### eth_syncing {#eth_syncing} + +동기화 상태에 대한 데이터가 있는 객체 또는 `false`를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +없음 + +**반환 값** + +정확한 반환 데이터는 클라이언트 구현에 따라 다릅니다. 모든 클라이언트는 노드가 동기화되지 않을 때 `False`를 반환하고, 모든 클라이언트는 다음 필드를 반환합니다. + +`객체|부울`, 동기화 상태 데이터가 있는 객체 또는 동기화되지 않을 때 `FALSE`: + +- `startingBlock`: `QUANTITY` - 가져오기가 시작된 블록(동기화가 헤드에 도달한 후에만 재설정됨) +- `currentBlock`: `QUANTITY` - 현재 블록, eth_blockNumber와 동일 +- `highestBlock`: `QUANTITY` - 추정된 가장 높은 블록 + +그러나 개별 클라이언트는 추가 데이터를 제공할 수도 있습니다. 예를 들어 Geth는 다음을 반환합니다: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "currentBlock": "0x3cf522", + "healedBytecodeBytes": "0x0", + "healedBytecodes": "0x0", + "healedTrienodes": "0x0", + "healingBytecode": "0x0", + "healingTrienodes": "0x0", + "highestBlock": "0x3e0e41", + "startingBlock": "0x3cbed5", + "syncedAccountBytes": "0x0", + "syncedAccounts": "0x0", + "syncedBytecodeBytes": "0x0", + "syncedBytecodes": "0x0", + "syncedStorage": "0x0", + "syncedStorageBytes": "0x0" + } +} +``` + +반면에 Besu는 다음을 반환합니다: + +```json +{ + "jsonrpc": "2.0", + "id": 51, + "result": { + "startingBlock": "0x0", + "currentBlock": "0x1518", + "highestBlock": "0x9567a3", + "pulledStates": "0x203ca", + "knownStates": "0x200636" + } +} +``` + +자세한 내용은 특정 클라이언트의 설명서를 참조하세요. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": { + startingBlock: '0x384', + currentBlock: '0x386', + highestBlock: '0x454' + } +} +// 또는 동기화되지 않을 때 +{ + "id":1, + "jsonrpc": "2.0", + "result": false +} +``` + +### eth_coinbase {#eth_coinbase} + +클라이언트 코인베이스 주소를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +> **참고:** 이 메서드는 v1.14.0부터 더 이상 사용되지 않으며 지원되지 않습니다. 이 메서드를 사용하려고 하면 "메서드가 지원되지 않음" 오류가 발생합니다. + +**매개변수** + +없음 + +**반환 값** + +`DATA`, 20바이트 - 현재 코인베이스 주소. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_coinbase","params":[],"id":64}' +// 결과 +{ + "id":64, + "jsonrpc": "2.0", + "result": "0x407d73d8a49eeb85d32cf465507dd71d507100c1" +} +``` + +### eth_chainId {#eth_chainId} + +재생 보호 트랜잭션 서명에 사용되는 체인 ID를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +없음 + +**반환 값** + +`chainId`, 현재 체인 ID의 정수를 나타내는 문자열로서의 16진수 값. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":67}' +// 결과 +{ + "id":67, + "jsonrpc": "2.0", + "result": "0x1" +} +``` + +### eth_mining {#eth_mining} + +클라이언트가 새 블록을 활발하게 채굴하는 경우 `true`를 반환합니다. 이것은 작업 증명 네트워크에 대해서만 `true`를 반환할 수 있으며 [병합](/roadmap/merge/) 이후 일부 클라이언트에서는 사용할 수 없을 수도 있습니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +없음 + +**반환 값** + +`부울` - 클라이언트가 채굴 중이면 `true`, 그렇지 않으면 `false`를 반환합니다. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_mining","params":[],"id":71}' +// +{ + "id":71, + "jsonrpc": "2.0", + "result": true +} +``` + +### eth_hashrate {#eth_hashrate} + +노드가 채굴 중인 초당 해시 수를 반환합니다. 이것은 작업 증명 네트워크에 대해서만 `true`를 반환할 수 있으며 [병합](/roadmap/merge/) 이후 일부 클라이언트에서는 사용할 수 없을 수도 있습니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +없음 + +**반환 값** + +`QUANTITY` - 초당 해시 수. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_hashrate","params":[],"id":71}' +// 결과 +{ + "id":71, + "jsonrpc": "2.0", + "result": "0x38a" +} +``` + +### eth_gasPrice {#eth_gasprice} + +웨이 단위의 가스당 현재 가격 추정치를 반환합니다. 예를 들어, Besu 클라이언트는 마지막 100개 블록을 검사하고 기본적으로 중간 가스 단가를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +없음 + +**반환 값** + +`QUANTITY` - 웨이 단위의 현재 가스 가격의 정수. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":73}' +// 결과 +{ + "id":73, + "jsonrpc": "2.0", + "result": "0x1dfd14000" // 8049999872 웨이 +} +``` + +### eth_accounts {#eth_accounts} + +클라이언트가 소유한 주소 목록을 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +없음 + +**반환 값** + +`DATA 배열`, 20바이트 - 클라이언트가 소유한 주소. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_accounts","params":[],"id":1}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": ["0x407d73d8a49eeb85d32cf465507dd71d507100c1"] +} +``` + +### eth_blockNumber {#eth_blocknumber} + +가장 최신 블록의 번호를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +없음 + +**반환 값** + +`QUANTITY` - 클라이언트가 있는 현재 블록 번호의 정수. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":83}' +// 결과 +{ + "id":83, + "jsonrpc": "2.0", + "result": "0x4b7" // 1207 +} +``` + +### eth_getBalance {#eth_getbalance} + +지정된 주소에 있는 계정의 잔액을 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `DATA`, 20바이트 - 잔액을 확인할 주소. +2. `QUANTITY|TAG` - 정수 블록 번호 또는 문자열 `"latest"`, `"earliest"`, `"pending"`, `"safe"` 또는 `"finalized"`, [블록 매개변수](/developers/docs/apis/json-rpc/#block-parameter) 참조 + +```js +params: ["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest"] +``` + +**반환 값** + +`QUANTITY` - 웨이 단위의 현재 잔액의 정수. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest"],"id":1}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x0234c8a3397aab58" // 158972490234375000 +} +``` + +### eth_getStorageAt {#eth_getstorageat} + +지정된 주소의 스토리지 위치에서 값을 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `DATA`, 20바이트 - 스토리지 주소. +2. `QUANTITY` - 스토리지 내 위치의 정수. +3. `QUANTITY|TAG` - 정수 블록 번호 또는 문자열 `"latest"`, `"earliest"`, `"pending"`, `"safe"`, `"finalized"`, [블록 매개변수](/developers/docs/apis/json-rpc/#block-parameter) 참조 + +**반환 값** + +`DATA` - 이 스토리지 위치의 값. + +**예제** +올바른 위치 계산은 검색할 스토리지에 따라 다릅니다. 주소 `0x391694e7e0b0cce554cb130d723a9d27458f9298`에 의해 `0x295a70b2de5e3953354a6a8344e616ed314d7251`에 배포된 다음 계약을 고려해 보세요. + +``` +contract Storage { + uint pos0; + mapping(address => uint) pos1; + constructor() { + pos0 = 1234; + pos1[msg.sender] = 5678; + } +} +``` + +pos0의 값을 검색하는 것은 간단합니다. + +```js +curl -X POST --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x0", "latest"], "id": 1}' localhost:8545 +{"jsonrpc":"2.0","id":1,"result":"0x00000000000000000000000000000000000000000000000000000000000004d2"} +``` + +맵의 요소를 검색하는 것은 더 어렵습니다. 맵에 있는 요소의 위치는 다음과 같이 계산됩니다: + +```js +keccak(LeftPad32(key, 0), LeftPad32(map position, 0)) +``` + +즉, pos1["0x391694e7e0b0cce554cb130d723a9d27458f9298"]의 스토리지를 검색하려면 다음을 사용하여 위치를 계산해야 합니다: + +```js +keccak( + decodeHex( + "000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + + "0000000000000000000000000000000000000000000000000000000000000001" + ) +) +``` + +web3 라이브러리와 함께 제공되는 geth 콘솔을 사용하여 계산할 수 있습니다: + +```js +> var key = "000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + "0000000000000000000000000000000000000000000000000000000000000001" +undefined +> web3.sha3(key, {"encoding": "hex"}) +"0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9" +``` + +이제 스토리지를 가져옵니다: + +```js +curl -X POST --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9", "latest"], "id": 1}' localhost:8545 +{"jsonrpc":"2.0","id":1,"result":"0x000000000000000000000000000000000000000000000000000000000000162e"} +``` + +### eth_getTransactionCount {#eth_gettransactioncount} + +주소에서 _보낸_ 트랜잭션 수를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `DATA`, 20바이트 - 주소. +2. `QUANTITY|TAG` - 정수 블록 번호 또는 문자열 `"latest"`, `"earliest"`, `"pending"`, `"safe"` 또는 `"finalized"`, [블록 매개변수](/developers/docs/apis/json-rpc/#block-parameter) 참조 + +```js +params: [ + "0x407d73d8a49eeb85d32cf465507dd71d507100c1", + "latest", // 최신 블록의 상태 +] +``` + +**반환 값** + +`QUANTITY` - 이 주소에서 보낸 트랜잭션 수의 정수입니다. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["0x407d73d8a49eeb85d32cf465507dd71d507100c1","latest"],"id":1}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x1" // 1 +} +``` + +### eth_getBlockTransactionCountByHash {#eth_getblocktransactioncountbyhash} + +주어진 블록 해시와 일치하는 블록의 트랜잭션 수를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `DATA`, 32바이트 - 블록의 해시 + +```js +params: ["0xd03ededb7415d22ae8bac30f96b2d1de83119632693b963642318d87d1bece5b"] +``` + +**반환 값** + +`QUANTITY` - 이 블록의 트랜잭션 수의 정수. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockTransactionCountByHash","params":["0xd03ededb7415d22ae8bac30f96b2d1de83119632693b963642318d87d1bece5b"],"id":1}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x8b" // 139 +} +``` + +### eth_getBlockTransactionCountByNumber {#eth_getblocktransactioncountbynumber} + +주어진 블록 번호와 일치하는 블록의 트랜잭션 수를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `QUANTITY|TAG` - 블록 번호의 정수, 또는 문자열 `"earliest"`, `"latest"`, `"pending"`, `"safe"` 또는 `"finalized"`, [블록 매개변수](/developers/docs/apis/json-rpc/#block-parameter)에서와 같이. + +```js +params: [ + "0x13738ca", // 20396234 +] +``` + +**반환 값** + +`QUANTITY` - 이 블록의 트랜잭션 수의 정수. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockTransactionCountByNumber","params":["0x13738ca"],"id":1}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x8b" // 139 +} +``` + +### eth_getUncleCountByBlockHash {#eth_getunclecountbyblockhash} + +주어진 블록 해시와 일치하는 블록의 엉클 수를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `DATA`, 32바이트 - 블록의 해시 + +```js +params: ["0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2"] +``` + +**반환 값** + +`QUANTITY` - 이 블록의 엉클 수의 정수. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getUncleCountByBlockHash","params":["0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2"],"id":1}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x1" // 1 +} +``` + +### eth_getUncleCountByBlockNumber {#eth_getunclecountbyblocknumber} + +주어진 블록 번호와 일치하는 블록의 엉클 수를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `QUANTITY|TAG` - 정수 블록 번호, 또는 문자열 `"latest"`, `"earliest"`, `"pending"`, `"safe"` 또는 `"finalized"`, [블록 매개변수](/developers/docs/apis/json-rpc/#block-parameter) 참조 + +```js +params: [ + "0xe8", // 232 +] +``` + +**반환 값** + +`QUANTITY` - 이 블록의 엉클 수의 정수. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getUncleCountByBlockNumber","params":["0xe8"],"id":1}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x0" // 0 +} +``` + +### eth_getCode {#eth_getcode} + +지정된 주소의 코드를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `DATA`, 20바이트 - 주소 +2. `QUANTITY|TAG` - 정수 블록 번호 또는 문자열 `"latest"`, `"earliest"`, `"pending"`, `"safe"` 또는 `"finalized"`, [블록 매개변수](/developers/docs/apis/json-rpc/#block-parameter) 참조 + +```js +params: [ + "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "0x5daf3b", // 6139707 +] +``` + +**반환 값** + +`DATA` - 지정된 주소의 코드. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getCode","params":["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "0x5daf3b"],"id":1}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x6060604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b9578063095ea7b31461014757806318160ddd146101a157806323b872dd146101ca5780632e1a7d4d14610243578063313ce5671461026657806370a082311461029557806395d89b41146102e2578063a9059cbb14610370578063d0e30db0146103ca578063dd62ed3e146103d4575b6100b7610440565b005b34156100c457600080fd5b6100cc6104dd565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561010c5780820151818401526020810190506100f1565b50505050905090810190601f1680156101395780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015257600080fd5b610187600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061057b565b604051808215151515815260200191505060405180910390f35b34156101ac57600080fd5b6101b461066d565b6040518082815260200191505060405180910390f35b34156101d557600080fd5b610229600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061068c565b604051808215151515815260200191505060405180910390f35b341561024e57600080fd5b61026460048080359060200190919050506109d9565b005b341561027157600080fd5b610279610b05565b604051808260ff1660ff16815260200191505060405180910390f35b34156102a057600080fd5b6102cc600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b18565b6040518082815260200191505060405180910390f35b34156102ed57600080fd5b6102f5610b30565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561033557808201518184015260208101905061031a565b50505050905090810190601f1680156103625780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561037b57600080fd5b6103b0600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610bce565b604051808215151515815260200191505060405180910390f35b6103d2610440565b005b34156103df57600080fd5b61042a600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610be3565b6040518082815260200191505060405180910390f35b34600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055503373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a2565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105735780601f1061054857610100808354040283529160200191610573565b820191906000526020600020905b81548152906001019060200180831161055657829003601f168201915b505050505081565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600081600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156106dc57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141580156107b457507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b156108cf5781600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561084457600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a2757600080fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501515610ab457600080fd5b3373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040518082815260200191505060405180910390a250565b600260009054906101000a900460ff1681565b60036020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610bc65780601f10610b9b57610100808354040283529160200191610bc6565b820191906000526020600020905b815481529060010190602001808311610ba957829003601f168201915b505050505081565b6000610bdb33848461068c565b905092915050565b60046020528160005260406000206020528060005260406000206000915091505054815600a165627a7a72305820deb4c2ccab3c2fdca32ab3f46728389c2fe2c165d5fafa07661e4e004f6c344a0029" +} +``` + +### eth_sign {#eth_sign} + +sign 메서드는 `sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)))`로 이더리움 특정 서명을 계산합니다. + +메시지에 접두사를 추가하면 계산된 서명을 이더리움 특정 서명으로 인식할 수 있습니다. 이를 통해 악의적인 탈중앙화앱이 임의의 데이터(예: 트랜잭션)에 서명하고 서명을 사용하여 피해자를 사칭하는 오용을 방지할 수 있습니다. + +참고: 서명할 주소는 잠금 해제되어야 합니다. + +**매개변수** + +1. `DATA`, 20바이트 - 주소 +2. `DATA`, N 바이트 - 서명할 메시지 + +**반환 값** + +`DATA`: 서명 + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sign","params":["0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", "0xdeadbeaf"],"id":1}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" +} +``` + +### eth_signTransaction {#eth_signtransaction} + +[eth_sendRawTransaction](#eth_sendrawtransaction)을 사용하여 나중에 네트워크에 제출할 수 있는 트랜잭션에 서명합니다. + +**매개변수** + +1. `객체` - 트랜잭션 객체 + +- `type`: +- `from`: `DATA`, 20바이트 - 트랜잭션이 전송된 주소. +- `to`: `DATA`, 20바이트 - (새 계약 생성 시 선택 사항) 트랜잭션이 보내지는 주소. +- `gas`: `QUANTITY` - (선택 사항, 기본값: 90000) 트랜잭션 실행을 위해 제공된 가스의 정수. 사용하지 않은 가스를 반환합니다. +- `gasPrice`: `QUANTITY` - (선택 사항, 기본값: 추후 결정) 지불된 각 가스에 사용되는 가스 가격의 정수(웨이 단위). +- `value`: `QUANTITY` - (선택 사항) 이 트랜잭션과 함께 전송된 값의 정수(웨이 단위). +- `data`: `DATA` - 계약의 컴파일된 코드 또는 호출된 메서드 서명의 해시 및 인코딩된 매개변수. +- `nonce`: `QUANTITY` - (선택 사항) 논스의 정수. 이를 통해 동일한 논스를 사용하는 자신의 보류 중인 트랜잭션을 덮어쓸 수 있습니다. + +**반환 값** + +`DATA`, 지정된 계정으로 서명된 RLP 인코딩 트랜잭션 객체. + +**예시** + +```js +// 요청 +curl -X POST --data '{"id": 1,"jsonrpc": "2.0","method": "eth_signTransaction","params": [{"data":"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675","from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155","gas": "0x76c0","gasPrice": "0x9184e72a000","to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567","value": "0x9184e72a"}]}' +// 결과 +{ + "id": 1, + "jsonrpc": "2.0", + "result": "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" +} +``` + +### eth_sendTransaction {#eth_sendtransaction} + +데이터 필드에 코드가 포함된 경우 새 메시지 호출 트랜잭션 또는 계약 생성을 만들고 `from`에 지정된 계정을 사용하여 서명합니다. + +**매개변수** + +1. `객체` - 트랜잭션 객체 + +- `from`: `DATA`, 20바이트 - 트랜잭션이 전송된 주소. +- `to`: `DATA`, 20바이트 - (새 계약 생성 시 선택 사항) 트랜잭션이 보내지는 주소. +- `gas`: `QUANTITY` - (선택 사항, 기본값: 90000) 트랜잭션 실행을 위해 제공된 가스의 정수. 사용하지 않은 가스를 반환합니다. +- `gasPrice`: `QUANTITY` - (선택 사항, 기본값: 추후 결정) 지불된 각 가스에 사용되는 가스 가격의 정수. +- `value`: `QUANTITY` - (선택 사항) 이 트랜잭션과 함께 전송된 값의 정수. +- `input`: `DATA` - 계약의 컴파일된 코드 또는 호출된 메서드 서명의 해시 및 인코딩된 매개변수. +- `nonce`: `QUANTITY` - (선택 사항) 논스의 정수. 이를 통해 동일한 논스를 사용하는 자신의 보류 중인 트랜잭션을 덮어쓸 수 있습니다. + +```js +params: [ + { + from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155", + to: "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + gas: "0x76c0", // 30400 + gasPrice: "0x9184e72a000", // 10000000000000 + value: "0x9184e72a", // 2441406250 + input: + "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", + }, +] +``` + +**반환 값** + +`DATA`, 32바이트 - 트랜잭션 해시, 또는 트랜잭션을 아직 사용할 수 없는 경우 0 해시. + +계약을 생성했을 때 트랜잭션이 블록에 제안된 후 [eth_getTransactionReceipt](#eth_gettransactionreceipt)를 사용하여 계약 주소를 가져옵니다. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{위 참조}],"id":1}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331" +} +``` + +### eth_sendRawTransaction {#eth_sendrawtransaction} + +서명된 트랜잭션에 대한 새 메시지 호출 트랜잭션 또는 계약 생성을 만듭니다. + +**매개변수** + +1. `DATA`, 서명된 트랜잭션 데이터. + +```js +params: [ + "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", +] +``` + +**반환 값** + +`DATA`, 32바이트 - 트랜잭션 해시, 또는 트랜잭션을 아직 사용할 수 없는 경우 0 해시. + +계약을 생성했을 때 트랜잭션이 블록에 제안된 후 [eth_getTransactionReceipt](#eth_gettransactionreceipt)를 사용하여 계약 주소를 가져옵니다. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":[{위 참조}],"id":1}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331" +} +``` + +### eth_call {#eth_call} + +블록체인에 트랜잭션을 생성하지 않고 즉시 새 메시지 호출을 실행합니다. ERC-20 계약의 `balanceOf`와 같이 읽기 전용 스마트 계약 함수를 실행하는 데 자주 사용됩니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `객체` - 트랜잭션 호출 객체 + +- `from`: `DATA`, 20바이트 - (선택 사항) 트랜잭션이 전송된 주소. +- `to`: `DATA`, 20바이트 - 트랜잭션이 보내지는 주소. +- `gas`: `QUANTITY` - (선택 사항) 트랜잭션 실행을 위해 제공된 가스의 정수. eth_call은 가스를 소비하지 않지만 일부 실행에서는 이 매개변수가 필요할 수 있습니다. +- `gasPrice`: `QUANTITY` - (선택 사항) 지불된 각 가스에 사용되는 가스 가격의 정수 +- `value`: `QUANTITY` - (선택 사항) 이 트랜잭션과 함께 전송된 값의 정수 +- `input`: `DATA` - (선택 사항) 메서드 서명의 해시 및 인코딩된 매개변수. 자세한 내용은 [솔리디티 문서의 이더리움 계약 ABI](https://docs.soliditylang.org/en/latest/abi-spec.html)를 참조하세요. + +2. `QUANTITY|TAG` - 정수 블록 번호 또는 문자열 `"latest"`, `"earliest"`, `"pending"`, `"safe"` 또는 `"finalized"`, [블록 매개변수](/developers/docs/apis/json-rpc/#block-parameter) 참조 + +**반환 값** + +`DATA` - 실행된 계약의 반환 값. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{위 참조}],"id":1}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x" +} +``` + +### eth_estimateGas {#eth_estimategas} + +트랜잭션이 완료되는 데 필요한 가스 양에 대한 추정치를 생성하고 반환합니다. 트랜잭션은 블록체인에 추가되지 않습니다. EVM 메커니즘 및 노드 성능을 포함한 다양한 이유로 인해 추정치가 트랜잭션에서 실제로 사용된 가스 양보다 훨씬 많을 수 있다는 점에 유의하세요. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +모든 속성이 선택 사항이라는 점을 제외하고 [eth_call](#eth_call) 매개변수를 참조하세요. 가스 한도가 지정되지 않은 경우 geth는 보류 중인 블록의 블록 가스 한도를 상한으로 사용합니다. 결과적으로 가스 양이 보류 중인 블록 가스 한도보다 높을 경우 반환된 추정치가 호출/트랜잭션을 실행하기에 충분하지 않을 수 있습니다. + +**반환 값** + +`QUANTITY` - 사용된 가스의 양. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_estimateGas","params":[{위 참조}],"id":1}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x5208" // 21000 +} +``` + +### eth_getBlockByHash {#eth_getblockbyhash} + +해시로 블록에 대한 정보를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `DATA`, 32바이트 - 블록의 해시. +2. `부울` - `true`이면 전체 트랜잭션 객체를 반환하고, `false`이면 트랜잭션의 해시만 반환합니다. + +```js +params: [ + "0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae", + false, +] +``` + +**반환 값** + +`객체` - 블록 객체, 또는 블록을 찾을 수 없는 경우 `null`: + +- `number`: `QUANTITY` - 블록 번호. 보류 중인 블록인 경우 `null`. +- `hash`: `DATA`, 32바이트 - 블록의 해시. 보류 중인 블록인 경우 `null`. +- `parentHash`: `DATA`, 32바이트 - 부모 블록의 해시. +- `nonce`: `DATA`, 8바이트 - 생성된 작업 증명의 해시. 보류 중인 블록인 경우 `null`, 지분 증명 블록의 경우 `0x0`(병합 이후) +- `sha3Uncles`: `DATA`, 32바이트 - 블록에 있는 엉클 데이터의 SHA3. +- `logsBloom`: `DATA`, 256바이트 - 블록의 로그에 대한 블룸 필터. 보류 중인 블록인 경우 `null`. +- `transactionsRoot`: `DATA`, 32바이트 - 블록의 트랜잭션 트리의 루트. +- `stateRoot`: `DATA`, 32바이트 - 블록의 최종 상태 트리의 루트. +- `receiptsRoot`: `DATA`, 32바이트 - 블록의 영수증 트리의 루트. +- `miner`: `DATA`, 20바이트 - 블록 보상을 받은 수혜자의 주소. +- `difficulty`: `QUANTITY` - 이 블록의 난이도 정수. +- `totalDifficulty`: `QUANTITY` - 이 블록까지의 체인 총 난이도 정수. +- `extraData`: `DATA` - 이 블록의 "추가 데이터" 필드. +- `size`: `QUANTITY` - 이 블록의 크기(바이트) 정수. +- `gasLimit`: `QUANTITY` - 이 블록에서 허용되는 최대 가스. +- `gasUsed`: `QUANTITY` - 이 블록의 모든 트랜잭션에서 사용된 총 가스. +- `timestamp`: `QUANTITY` - 블록이 수집된 유닉스 타임스탬프. +- `transactions`: `배열` - 트랜잭션 객체의 배열, 또는 마지막으로 주어진 매개변수에 따라 32바이트 트랜잭션 해시. +- `uncles`: `배열` - 엉클 해시의 배열. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockByHash","params":["0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae", false],"id":1}' +// 결과 +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "difficulty": "0x4ea3f27bc", + "extraData": "0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32", + "gasLimit": "0x1388", + "gasUsed": "0x0", + "hash": "0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0xbb7b8287f3f0a933474a79eae42cbca977791171", + "mixHash": "0x4fffe9ae21f1c9e15207b1f472d5bbdd68c9595d461666602f2be20daf5e7843", + "nonce": "0x689056015818adbe", + "number": "0x1b4", + "parentHash": "0xe99e022112df268087ea7eafaf4790497fd21dbeeb6bd7a1721df161a6657a54", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x220", + "stateRoot": "0xddc8b0234c2e0cad087c8b389aa7ef01f7d79b2570bccb77ce48648aa61c904d", + "timestamp": "0x55ba467c", + "totalDifficulty": "0x78ed983323d", + "transactions": [ + ], + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncles": [ + ] + } +} +``` + +### eth_getBlockByNumber {#eth_getblockbynumber} + +블록 번호로 블록에 대한 정보를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `QUANTITY|TAG` - 블록 번호의 정수, 또는 문자열 `"earliest"`, `"latest"`, `"pending"`, `"safe"` 또는 `"finalized"`, [블록 매개변수](/developers/docs/apis/json-rpc/#block-parameter)에서와 같이. +2. `부울` - `true`이면 전체 트랜잭션 객체를 반환하고, `false`이면 트랜잭션의 해시만 반환합니다. + +```js +params: [ + "0x1b4", // 436 + true, +] +``` + +**반환 값** +[eth_getBlockByHash](#eth_getblockbyhash)를 참조하세요 + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x1b4", true],"id":1}' +``` + +결과는 [eth_getBlockByHash](#eth_getblockbyhash)를 참조하세요 + +### eth_getTransactionByHash {#eth_gettransactionbyhash} + +트랜잭션 해시로 요청된 트랜잭션에 대한 정보를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `DATA`, 32바이트 - 트랜잭션의 해시 + +```js +params: ["0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b"] +``` + +**반환 값** + +`객체` - 트랜잭션 객체, 또는 트랜잭션을 찾을 수 없는 경우 `null`: + +- `blockHash`: `DATA`, 32바이트 - 이 트랜잭션이 포함된 블록의 해시. 보류 중일 때 `null`. +- `blockNumber`: `QUANTITY` - 이 트랜잭션이 포함된 블록 번호. 보류 중일 때 `null`. +- `from`: `DATA`, 20바이트 - 발신자의 주소. +- `gas`: `QUANTITY` - 발신자가 제공한 가스. +- `gasPrice`: `QUANTITY` - 발신자가 웨이 단위로 제공한 가스 가격. +- `hash`: `DATA`, 32바이트 - 트랜잭션의 해시. +- `input`: `DATA` - 트랜잭션과 함께 전송된 데이터. +- `nonce`: `QUANTITY` - 이 트랜잭션 이전에 발신자가 수행한 트랜잭션 수. +- `to`: `DATA`, 20바이트 - 수신자의 주소. 계약 생성 트랜잭션인 경우 `null`. +- `transactionIndex`: `QUANTITY` - 블록 내 트랜잭션 인덱스 위치의 정수. 보류 중일 때 `null`. +- `value`: `QUANTITY` - 웨이 단위로 전송된 값. +- `v`: `QUANTITY` - ECDSA 복구 ID +- `r`: `QUANTITY` - ECDSA 서명 r +- `s`: `QUANTITY` - ECDSA 서명 s + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b"],"id":1}' +// 결과 +{ + "jsonrpc":"2.0", + "id":1, + "result":{ + "blockHash":"0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2", + "blockNumber":"0x5daf3b", // 6139707 + "from":"0xa7d9ddbe1f17865597fbd27ec712455208b6b76d", + "gas":"0xc350", // 50000 + "gasPrice":"0x4a817c800", // 20000000000 + "hash":"0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b", + "input":"0x68656c6c6f21", + "nonce":"0x15", // 21 + "to":"0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb", + "transactionIndex":"0x41", // 65 + "value":"0xf3dbb76162000", // 4290000000000000 + "v":"0x25", // 37 + "r":"0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea", + "s":"0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c" + } +} +``` + +### eth_getTransactionByBlockHashAndIndex {#eth_gettransactionbyblockhashandindex} + +블록 해시 및 트랜잭션 인덱스 위치로 트랜잭션에 대한 정보를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `DATA`, 32바이트 - 블록의 해시. +2. `QUANTITY` - 트랜잭션 인덱스 위치의 정수. + +```js +params: [ + "0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2", + "0x0", // 0 +] +``` + +**반환 값** +[eth_getTransactionByHash](#eth_gettransactionbyhash)를 참조하세요 + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionByBlockHashAndIndex","params":["0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2", "0x0"],"id":1}' +``` + +결과는 [eth_getTransactionByHash](#eth_gettransactionbyhash)를 참조하세요 + +### eth_getTransactionByBlockNumberAndIndex {#eth_gettransactionbyblocknumberandindex} + +블록 번호 및 트랜잭션 인덱스 위치로 트랜잭션에 대한 정보를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `QUANTITY|TAG` - 블록 번호 또는 문자열 `"earliest"`, `"latest"`, `"pending"`, `"safe"` 또는 `"finalized"`, [블록 매개변수](/developers/docs/apis/json-rpc/#block-parameter)에서와 같이. +2. `QUANTITY` - 트랜잭션 인덱스 위치. + +```js +params: [ + "0x9c47cf", // 10241999 + "0x24", // 36 +] +``` + +**반환 값** +[eth_getTransactionByHash](#eth_gettransactionbyhash)를 참조하세요 + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionByBlockNumberAndIndex","params":["0x9c47cf", "0x24"],"id":1}' +``` + +결과는 [eth_getTransactionByHash](#eth_gettransactionbyhash)를 참조하세요 + +### eth_getTransactionReceipt {#eth_gettransactionreceipt} + +트랜잭션 해시로 트랜잭션의 영수증을 반환합니다. + +**참고** 보류 중인 트랜잭션에 대해서는 영수증을 사용할 수 없습니다. + +**매개변수** + +1. `DATA`, 32바이트 - 트랜잭션의 해시 + +```js +params: ["0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c5"] +``` + +**반환 값** +`객체` - 트랜잭션 영수증 객체, 또는 영수증을 찾을 수 없는 경우 `null`: + +- `transactionHash `: `DATA`, 32바이트 - 트랜잭션의 해시. +- `transactionIndex`: `QUANTITY` - 블록 내 트랜잭션 인덱스 위치의 정수. +- `blockHash`: `DATA`, 32바이트 - 이 트랜잭션이 포함된 블록의 해시. +- `blockNumber`: `QUANTITY` - 이 트랜잭션이 포함된 블록 번호. +- `from`: `DATA`, 20바이트 - 발신자의 주소. +- `to`: `DATA`, 20바이트 - 수신자의 주소. 계약 생성 트랜잭션인 경우 null. +- `cumulativeGasUsed` : `QUANTITY` - 이 트랜잭션이 블록에서 실행되었을 때 사용된 총 가스 양. +- `effectiveGasPrice` : `QUANTITY` - 가스 단위당 지불된 기본 수수료와 팁의 합계. +- `gasUsed `: `QUANTITY` - 이 특정 트랜잭션에서만 사용된 가스 양. +- `contractAddress `: `DATA`, 20바이트 - 트랜잭션이 계약 생성인 경우 생성된 계약 주소, 그렇지 않으면 `null`. +- `logs`: `배열` - 이 트랜잭션이 생성한 로그 객체의 배열. +- `logsBloom`: `DATA`, 256바이트 - 라이트 클라이언트가 관련 로그를 빠르게 검색할 수 있도록 하는 블룸 필터. +- `type`: `QUANTITY` - 트랜잭션 유형의 정수, 레거시 트랜잭션의 경우 `0x0`, 액세스 목록 유형의 경우 `0x1`, 동적 수수료의 경우 `0x2`. + +또한 다음 중 하나를 반환합니다. + +- `root` : `DATA` 트랜잭션 후 상태 루트의 32바이트(비잔티움 이전) +- `status`: `QUANTITY` `1`(성공) 또는 `0`(실패) + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c5"],"id":1}' +// 결과 +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "blockHash": + "0xa957d47df264a31badc3ae823e10ac1d444b098d9b73d204c40426e57f47e8c3", + "blockNumber": "0xeff35f", + "contractAddress": null, // 생성된 경우 주소 문자열 + "cumulativeGasUsed": "0xa12515", + "effectiveGasPrice": "0x5a9c688d4", + "from": "0x6221a9c005f6e47eb398fd867784cacfdcfff4e7", + "gasUsed": "0xb4c8", + "logs": [{ + // getFilterLogs 등이 반환한 로그 + }], + "logsBloom": "0x00...0", // 256바이트 블룸 필터 + "status": "0x1", + "to": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", + "transactionHash": + "0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c5", + "transactionIndex": "0x66", + "type": "0x2" + } +} +``` + +### eth_getUncleByBlockHashAndIndex {#eth_getunclebyblockhashandindex} + +해시 및 엉클 인덱스 위치로 블록의 엉클에 대한 정보를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `DATA`, 32바이트 - 블록의 해시. +2. `QUANTITY` - 엉클의 인덱스 위치. + +```js +params: [ + "0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2", + "0x0", // 0 +] +``` + +**반환 값** +[eth_getBlockByHash](#eth_getblockbyhash)를 참조하세요 + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getUncleByBlockHashAndIndex","params":["0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2", "0x0"],"id":1}' +``` + +결과는 [eth_getBlockByHash](#eth_getblockbyhash)를 참조하세요 + +**참고**: 엉클은 개별 트랜잭션을 포함하지 않습니다. + +### eth_getUncleByBlockNumberAndIndex {#eth_getunclebyblocknumberandindex} + +번호 및 엉클 인덱스 위치로 블록의 엉클에 대한 정보를 반환합니다. + + + 플레이그라운드에서 엔드포인트 시도하기 + + +**매개변수** + +1. `QUANTITY|TAG` - 블록 번호 또는 문자열 `"earliest"`, `"latest"`, `"pending"`, `"safe"`, `"finalized"`, [블록 매개변수](/developers/docs/apis/json-rpc/#block-parameter)에서와 같이. +2. `QUANTITY` - 엉클의 인덱스 위치. + +```js +params: [ + "0x29c", // 668 + "0x0", // 0 +] +``` + +**반환 값** +[eth_getBlockByHash](#eth_getblockbyhash)를 참조하세요 + +**참고**: 엉클은 개별 트랜잭션을 포함하지 않습니다. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getUncleByBlockNumberAndIndex","params":["0x29c", "0x0"],"id":1}' +``` + +결과는 [eth_getBlockByHash](#eth_getblockbyhash)를 참조하세요 + +### eth_newFilter {#eth_newfilter} + +필터 옵션을 기반으로 필터 객체를 생성하여 상태가 변경될 때(로그) 알립니다. +상태가 변경되었는지 확인하려면 [eth_getFilterChanges](#eth_getfilterchanges)를 호출하세요. + +**토픽 필터 지정에 대한 참고 사항:** +토픽은 순서에 따라 다릅니다. 토픽 [A, B]가 있는 로그가 포함된 트랜잭션은 다음 토픽 필터와 일치합니다: + +- `[]` "모든 것" +- `[A]` "첫 번째 위치에 A(그리고 그 뒤에 모든 것)" +- `[null, B]` "첫 번째 위치에 모든 것 AND 두 번째 위치에 B(그리고 그 뒤에 모든 것)" +- `[A, B]` "첫 번째 위치에 A AND 두 번째 위치에 B(그리고 그 뒤에 모든 것)" +- `[[A, B], [A, B]]` "첫 번째 위치에 (A 또는 B) AND 두 번째 위치에 (A 또는 B)(그리고 그 뒤에 모든 것)" +- **매개변수** + +1. `객체` - 필터 옵션: + +- `fromBlock`: `QUANTITY|TAG` - (선택 사항, 기본값: `"latest"`) 정수 블록 번호 또는 `"latest"`(최신 제안 블록), `"safe"`(최신 안전 블록), `"finalized"`(최신 확정 블록), `"pending"`, `"earliest"`(아직 블록에 포함되지 않은 트랜잭션). +- `toBlock`: `QUANTITY|TAG` - (선택 사항, 기본값: `"latest"`) 정수 블록 번호 또는 `"latest"`(최신 제안 블록), `"safe"`(최신 안전 블록), `"finalized"`(최신 확정 블록), `"pending"`, `"earliest"`(아직 블록에 포함되지 않은 트랜잭션). +- `address`: `DATA|배열`, 20바이트 - (선택 사항) 로그가 발생해야 하는 계약 주소 또는 주소 목록. +- `topics`: `DATA 배열` - (선택 사항) 32바이트 `DATA` 토픽의 배열. 토픽은 순서에 따라 다릅니다. 각 토픽은 "or" 옵션이 있는 DATA 배열일 수도 있습니다. + +```js +params: [ + { + fromBlock: "0x1", + toBlock: "0x2", + address: "0x8888f1f195afa192cfee860698584c030f4c9db1", + topics: [ + "0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", + null, + [ + "0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "0x0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc", + ], + ], + }, +] +``` + +**반환 값** +`QUANTITY` - 필터 ID. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newFilter","params":[{"topics":["0x12341234"]}],"id":73}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x1" // 1 +} +``` + +### eth_newBlockFilter {#eth_newblockfilter} + +새 블록이 도착하면 알림을 보내도록 노드에 필터를 생성합니다. +상태가 변경되었는지 확인하려면 [eth_getFilterChanges](#eth_getfilterchanges)를 호출하세요. + +**매개변수** +없음 + +**반환 값** +`QUANTITY` - 필터 ID. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newBlockFilter","params":[],"id":73}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x1" // 1 +} +``` + +### eth_newPendingTransactionFilter {#eth_newpendingtransactionfilter} + +새로운 보류 중인 트랜잭션이 도착하면 알림을 보내도록 노드에 필터를 생성합니다. +상태가 변경되었는지 확인하려면 [eth_getFilterChanges](#eth_getfilterchanges)를 호출하세요. + +**매개변수** +없음 + +**반환 값** +`QUANTITY` - 필터 ID. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newPendingTransactionFilter","params":[],"id":73}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x1" // 1 +} +``` + +### eth_uninstallFilter {#eth_uninstallfilter} + +지정된 ID의 필터를 제거합니다. 감시가 더 이상 필요하지 않을 때 항상 호출해야 합니다. +또한 필터는 일정 기간 동안 [eth_getFilterChanges](#eth_getfilterchanges)로 요청되지 않으면 시간 초과됩니다. + +**매개변수** + +1. `QUANTITY` - 필터 ID. + +```js +params: [ + "0xb", // 11 +] +``` + +**반환 값** +`부울` - 필터가 성공적으로 제거되면 `true`, 그렇지 않으면 `false`입니다. + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_uninstallFilter","params":["0xb"],"id":73}' +// 결과 +{ + "id":1, + "jsonrpc": "2.0", + "result": true +} +``` + +### eth_getFilterChanges {#eth_getfilterchanges} + +마지막 폴링 이후 발생한 로그 배열을 반환하는 필터용 폴링 메서드입니다. + +**매개변수** + +1. `QUANTITY` - 필터 ID. + +```js +params: [ + "0x16", // 22 +] +``` + +**반환 값** +`배열` - 로그 객체의 배열, 또는 마지막 폴링 이후 변경된 사항이 없는 경우 빈 배열. + +- `eth_newBlockFilter`로 생성된 필터의 경우 반환값은 블록 해시(`DATA`, 32바이트)입니다. 예: `["0x3454645634534..."]`. + +- `eth_newPendingTransactionFilter`로 생성된 필터의 경우 반환값은 트랜잭션 해시(`DATA`, 32바이트)입니다. 예: `["0x6345343454645..."]`. + +- `eth_newFilter`로 생성된 필터의 경우 로그는 다음 매개변수가 있는 객체입니다: + - `removed`: `TAG` - 체인 재구성으로 인해 로그가 제거된 경우 `true`입니다. 유효한 로그인 경우 `false`입니다. + - `logIndex`: `QUANTITY` - 블록 내 로그 인덱스 위치의 정수. 보류 중인 로그일 때 `null`. + - `transactionIndex`: `QUANTITY` - 로그가 생성된 트랜잭션 인덱스 위치의 정수. 보류 중인 로그일 때 `null`. + - `transactionHash`: `DATA`, 32바이트 - 이 로그가 생성된 트랜잭션의 해시. 보류 중인 로그일 때 `null`. + - `blockHash`: `DATA`, 32바이트 - 이 로그가 포함된 블록의 해시. 보류 중일 때 `null`. 보류 중인 로그일 때 `null`. + - `blockNumber`: `QUANTITY` - 이 로그가 포함된 블록 번호. 보류 중일 때 `null`. 보류 중인 로그일 때 `null`. + - `address`: `DATA`, 20바이트 - 이 로그가 시작된 주소. + - `data`: `DATA` - 가변 길이의 인덱싱되지 않은 로그 데이터. (solidity에서: 0개 이상의 32바이트 비인덱싱 로그 인수.) + - `topics`: `DATA 배열` - 인덱싱된 로그 인수의 0에서 4개의 32바이트 `DATA` 배열. (solidity에서: `anonymous` 지정자로 이벤트를 선언한 경우를 제외하고 첫 번째 토픽은 이벤트 서명의 해시입니다(예: `Deposit(address,bytes32,uint256)`). + +- **예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0x16"],"id":73}' +// 결과 +{ + "id":1, + "jsonrpc":"2.0", + "result": [{ + "logIndex": "0x1", // 1 + "blockNumber":"0x1b4", // 436 + "blockHash": "0x8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcfdf829c5a142f1fccd7d", + "transactionHash": "0xdf829c5a142f1fccd7d8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcf", + "transactionIndex": "0x0", // 0 + "address": "0x16c5785ac562ff41e2dcfdf829c5a142f1fccd7d", + "data":"0x0000000000000000000000000000000000000000000000000000000000000000", + "topics": ["0x59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a5"] + },{ + ... + }] +} +``` + +### eth_getFilterLogs {#eth_getfilterlogs} + +지정된 ID와 일치하는 필터의 모든 로그 배열을 반환합니다. + +**매개변수** + +1. `QUANTITY` - 필터 ID. + +```js +params: [ + "0x16", // 22 +] +``` + +**반환 값** +[eth_getFilterChanges](#eth_getfilterchanges)를 참조하세요 + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterLogs","params":["0x16"],"id":74}' +``` + +결과는 [eth_getFilterChanges](#eth_getfilterchanges)를 참조하세요 + +### eth_getLogs {#eth_getlogs} + +지정된 필터 객체와 일치하는 모든 로그의 배열을 반환합니다. + +**매개변수** + +1. `객체` - 필터 옵션: + +- `fromBlock`: `QUANTITY|TAG` - (선택 사항, 기본값: `"latest"`) 정수 블록 번호 또는 `"latest"`(최신 제안 블록), `"safe"`(최신 안전 블록), `"finalized"`(최신 확정 블록), `"pending"`, `"earliest"`(아직 블록에 포함되지 않은 트랜잭션). +- `toBlock`: `QUANTITY|TAG` - (선택 사항, 기본값: `"latest"`) 정수 블록 번호 또는 `"latest"`(최신 제안 블록), `"safe"`(최신 안전 블록), `"finalized"`(최신 확정 블록), `"pending"`, `"earliest"`(아직 블록에 포함되지 않은 트랜잭션). +- `address`: `DATA|배열`, 20바이트 - (선택 사항) 로그가 발생해야 하는 계약 주소 또는 주소 목록. +- `topics`: `DATA 배열` - (선택 사항) 32바이트 `DATA` 토픽의 배열. 토픽은 순서에 따라 다릅니다. 각 토픽은 "or" 옵션이 있는 DATA 배열일 수도 있습니다. +- `blockHash`: `DATA`, 32바이트 - (선택 사항, **향후**) EIP-234가 추가되면서 `blockHash`는 반환되는 로그를 32바이트 해시 `blockHash`가 있는 단일 블록으로 제한하는 새로운 필터 옵션이 될 것입니다. `blockHash`를 사용하는 것은 `fromBlock` = `toBlock` = 해시 `blockHash`가 있는 블록 번호와 동일합니다. 필터 기준에 `blockHash`가 있는 경우 `fromBlock`이나 `toBlock`은 허용되지 않습니다. + +```js +params: [ + { + topics: [ + "0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", + ], + }, +] +``` + +**반환 값** +[eth_getFilterChanges](#eth_getfilterchanges)를 참조하세요 + +**예시** + +```js +// 요청 +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"topics":["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"]}],"id":74}' +``` + +결과는 [eth_getFilterChanges](#eth_getfilterchanges)를 참조하세요 + +## 사용 예제 {#usage-example} + +### JSON_RPC를 사용하여 계약 배포하기 {#deploying-contract} + +이 섹션에서는 RPC 인터페이스만 사용하여 계약을 배포하는 방법에 대한 시연을 포함합니다. 이러한 복잡성이 추상화된 계약 배포를 위한 대체 경로가 있습니다. 예를 들어, [web3.js](https://web3js.readthedocs.io/) 및 [web3.py](https://github.com/ethereum/web3.py)와 같이 RPC 인터페이스 위에 구축된 라이브러리를 사용하는 것입니다. 이러한 추상화는 일반적으로 이해하기 쉽고 오류가 발생할 가능성이 적지만, 내부에서 어떤 일이 일어나고 있는지 이해하는 것은 여전히 유용합니다. + +다음은 이더리움 노드에 JSON-RPC 인터페이스를 사용하여 배포될 `Multiply7`이라는 간단한 스마트 계약입니다. 이 튜토리얼은 독자가 이미 Geth 노드를 실행하고 있다고 가정합니다. 노드와 클라이언트에 대한 자세한 정보는 [여기](/developers/docs/nodes-and-clients/run-a-node)에서 확인할 수 있습니다. Geth가 아닌 클라이언트의 경우 HTTP JSON-RPC를 시작하는 방법을 보려면 개별 [클라이언트](/developers/docs/nodes-and-clients/) 문서를 참조하세요. 대부분의 클라이언트는 기본적으로 `localhost:8545`에서 제공됩니다. + +```javascript +contract Multiply7 { + event Print(uint); + function multiply(uint input) returns (uint) { + Print(input * 7); + return input * 7; + } +} +``` + +가장 먼저 할 일은 HTTP RPC 인터페이스가 활성화되었는지 확인하는 것입니다. 즉, 시작 시 Geth에 `--http` 플래그를 제공합니다. 이 예에서는 비공개 개발 체인에서 Geth 노드를 사용합니다. 이 방법을 사용하면 실제 네트워크에서 이더가 필요하지 않습니다. + +```bash +geth --http --dev console 2>>geth.log +``` + +이렇게 하면 `http://localhost:8545`에서 HTTP RPC 인터페이스가 시작됩니다. + +[curl](https://curl.se)을 사용하여 코인베이스 주소(계정 배열에서 첫 번째 주소를 가져옴)와 잔액을 검색하여 인터페이스가 실행 중인지 확인할 수 있습니다. 이 예제의 데이터는 로컬 노드에서 다를 수 있다는 점에 유의하세요. 이 명령을 사용해 보려면 두 번째 curl 요청의 요청 매개변수를 첫 번째 요청에서 반환된 결과로 바꾸세요. + +```bash +curl --data '{"jsonrpc":"2.0","method":"eth_accounts","params":[], "id":1}' -H "Content-Type: application/json" localhost:8545 +{"id":1,"jsonrpc":"2.0","result":["0x9b1d35635cc34752ca54713bb99d38614f63c955"]} + +curl --data '{"jsonrpc":"2.0","method":"eth_getBalance", "params": ["0x9b1d35635cc34752ca54713bb99d38614f63c955", "latest"], "id":2}' -H "Content-Type: application/json" localhost:8545 +{"id":2,"jsonrpc":"2.0","result":"0x1639e49bba16280000"} +``` + +숫자는 16진수로 인코딩되므로 잔액은 웨이 단위의 16진수 문자열로 반환됩니다. 잔액을 이더 단위의 숫자로 갖고 싶다면 Geth 콘솔에서 web3를 사용할 수 있습니다. + +```javascript +web3.fromWei("0x1639e49bba16280000", "ether") +// "410" +``` + +이제 비공개 개발 체인에 이더가 있으므로 계약을 배포할 수 있습니다. 첫 번째 단계는 Multiply7 계약을 EVM으로 보낼 수 있는 바이트 코드로 컴파일하는 것입니다. 솔리디티 컴파일러인 solc를 설치하려면 [솔리디티 문서](https://docs.soliditylang.org/en/latest/installing-solidity.html)를 따르세요. (예제에 사용된 컴파일러 버전](https://github.com/ethereum/solidity/releases/tag/v0.4.20)과 일치시키기 위해 이전 `solc` 릴리스를 사용하고 싶을 수도 있습니다.) + +다음 단계는 Multiply7 계약을 EVM으로 보낼 수 있는 바이트 코드로 컴파일하는 것입니다. + +```bash +echo 'pragma solidity ^0.4.16; contract Multiply7 { event Print(uint); function multiply(uint input) public returns (uint) { Print(input * 7); return input * 7; } }' | solc --bin + +======= :Multiply7 ======= +Binary: +6060604052341561000f57600080fd5b60eb8061001d6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa1146044575b600080fd5b3415604e57600080fd5b606260048080359060200190919050506078565b6040518082815260200191505060405180910390f35b60007f24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da600783026040518082815260200191505060405180910390a16007820290509190505600a165627a7a7230582040383f19d9f65246752244189b02f56e8d0980ed44e7a56c0b200458caad20bb0029 +``` + +이제 컴파일된 코드가 있으므로 이를 배포하는 데 드는 가스 비용을 결정해야 합니다. RPC 인터페이스에는 추정치를 제공하는 `eth_estimateGas` 메서드가 있습니다. + +```bash +curl --data '{"jsonrpc":"2.0","method": "eth_estimateGas", "params": [{"from": "0x9b1d35635cc34752ca54713bb99d38614f63c955", "data": "0x6060604052341561000f57600080fd5b60eb8061001d6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa1146044575b600080fd5b3415604e57600080fd5b606260048080359060200190919050506078565b6040518082815260200191505060405180910390f35b60007f24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da600783026040518082815260200191505060405180910390a16007820290509190505600a165627a7a7230582040383f19d9f65246752244189b02f56e8d0980ed44e7a56c0b200458caad20bb0029"}], "id": 5}' -H "Content-Type: application/json" localhost:8545 +{"jsonrpc":"2.0","id":5,"result":"0x1c31e"} +``` + +그리고 마지막으로 계약을 배포합니다. + +```bash +curl --data '{"jsonrpc":"2.0","method": "eth_sendTransaction", "params": [{"from": "0x9b1d35635cc34752ca54713bb99d38614f63c955", "gas": "0x1c31e", "data": "0x6060604052341561000f57600080fd5b60eb8061001d6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa1146044575b600080fd5b3415604e57600080fd5b606260048080359060200190919050506078565b6040518082815260200191505060405180910390f35b60007f24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da600783026040518082815260200191505060405180910390a16007820290509190505600a165627a7a7230582040383f19d9f65246752244189b02f56e8d0980ed44e7a56c0b200458caad20bb0029"}], "id": 6}' -H "Content-Type: application/json" localhost:8545 +{"id":6,"jsonrpc":"2.0","result":"0xe1f3095770633ab2b18081658bad475439f6a08c902d0915903bafff06e6febf"} +``` + +트랜잭션이 노드에 의해 수락되고 트랜잭션 해시가 반환됩니다. 이 해시는 트랜잭션을 추적하는 데 사용할 수 있습니다. 다음 단계는 계약이 배포된 주소를 결정하는 것입니다. 실행된 각 트랜잭션은 영수증을 생성합니다. 이 영수증에는 트랜잭션이 포함된 블록과 EVM에서 사용한 가스 양과 같은 트랜잭션에 대한 다양한 정보가 포함되어 있습니다. 트랜잭션이 +계약을 생성하는 경우 계약 주소도 포함됩니다. `eth_getTransactionReceipt` RPC 메서드로 영수증을 검색할 수 있습니다. + +```bash +curl --data '{"jsonrpc":"2.0","method": "eth_getTransactionReceipt", "params": ["0xe1f3095770633ab2b18081658bad475439f6a08c902d0915903bafff06e6febf"], "id": 7}' -H "Content-Type: application/json" localhost:8545 +{"jsonrpc":"2.0","id":7,"result":{"blockHash":"0x77b1a4f6872b9066312de3744f60020cbd8102af68b1f6512a05b7619d527a4f","blockNumber":"0x1","contractAddress":"0x4d03d617d700cf81935d7f797f4e2ae719648262","cumulativeGasUsed":"0x1c31e","from":"0x9b1d35635cc34752ca54713bb99d38614f63c955","gasUsed":"0x1c31e","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","to":null,"transactionHash":"0xe1f3095770633ab2b18081658bad475439f6a08c902d0915903bafff06e6febf","transactionIndex":"0x0"}} +``` + +우리의 계약은 `0x4d03d617d700cf81935d7f797f4e2ae719648262`에서 생성되었습니다. 영수증 대신 null 결과가 나오면 트랜잭션이 아직 블록에 포함되지 않았다는 의미입니다. 잠시 기다린 후 합의 클라이언트가 실행 중인지 확인하고 다시 시도하십시오. + +#### 스마트 계약과 상호작용하기 {#interacting-with-smart-contract} + +이 예제에서는 `eth_sendTransaction`을 사용하여 `multiply` 계약의 메서드에 트랜잭션을 전송합니다. + +`eth_sendTransaction`에는 `from`, `to`, `data`와 같은 여러 인수가 필요합니다. `From`은 우리 계정의 공개 주소이고 `to`는 계약 주소입니다. `data` 인수는 어떤 메서드를 어떤 인수로 호출해야 하는지를 정의하는 페이로드를 포함합니다. 이것이 [ABI(애플리케이션 바이너리 인터페이스)](https://docs.soliditylang.org/en/latest/abi-spec.html)가 사용되는 부분입니다. ABI는 EVM에 대한 데이터를 정의하고 인코딩하는 방법을 정의하는 JSON 파일입니다. + +페이로드의 바이트는 계약에서 호출되는 메서드를 정의합니다. 이것은 함수 이름과 인수 유형에 대한 Keccak 해시의 처음 4바이트를 16진수로 인코딩한 것입니다. multiply 함수는 uint256의 별칭인 uint를 허용합니다. 그러면 다음과 같이 됩니다. + +```javascript +web3.sha3("multiply(uint256)").substring(0, 10) +// "0xc6888fa1" +``` + +다음으로 인수를 인코딩해 보겠습니다. 값 6과 같은 uint256이 하나만 있습니다. ABI에는 uint256 유형을 인코딩하는 방법을 지정하는 섹션이 있습니다. + +`int: enc(X)`는 X의 빅엔디언 2의 보수 인코딩으로, 음수 X의 경우 상위(왼쪽)에 0xff를, 양수 X의 경우 0바이트를 채워 길이가 32바이트의 배수가 되도록 합니다. + +이것은 `0000000000000000000000000000000000000000000000000000000000000006`으로 인코딩됩니다. + +함수 선택기와 인코딩된 인수를 결합하면 데이터는 `0xc6888fa10000000000000000000000000000000000000000000000000000000000000006`이 됩니다. + +이제 이것을 노드로 보낼 수 있습니다. + +```bash +curl --data '{"jsonrpc":"2.0","method": "eth_sendTransaction", "params": [{"from": "0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a", "to": "0x6ff93b4b46b41c0c3c9baee01c255d3b4675963d", "data": "0xc6888fa10000000000000000000000000000000000000000000000000000000000000006"}], "id": 8}' -H "Content-Type: application/json" localhost:8545 +{"id":8,"jsonrpc":"2.0","result":"0x759cf065cbc22e9d779748dc53763854e5376eea07409e590c990eafc0869d74"} +``` + +트랜잭션이 전송되었으므로 트랜잭션 해시가 반환되었습니다. 영수증을 검색하면 다음과 같이 표시됩니다. + +```javascript +{ + blockHash: "0xbf0a347307b8c63dd8c1d3d7cbdc0b463e6e7c9bf0a35be40393588242f01d55", + blockNumber: 268, + contractAddress: null, + cumulativeGasUsed: 22631, + gasUsed: 22631, + logs: [{ + address: "0x6ff93b4b46b41c0c3c9baee01c255d3b4675963d", + blockHash: "0xbf0a347307b8c63dd8c1d3d7cbdc0b463e6e7c9bf0a35be40393588242f01d55", + blockNumber: 268, + data: "0x000000000000000000000000000000000000000000000000000000000000002a", + logIndex: 0, + topics: ["0x24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da"], + transactionHash: "0x759cf065cbc22e9d779748dc53763854e5376eea07409e590c990eafc0869d74", + transactionIndex: 0 + }], + transactionHash: "0x759cf065cbc22e9d779748dc53763854e5376eea07409e590c990eafc0869d74", + transactionIndex: 0 +} +``` + +영수증에는 로그가 포함되어 있습니다. 이 로그는 트랜잭션 실행 시 EVM에 의해 생성되어 영수증에 포함되었습니다. `multiply` 함수는 입력값에 7을 곱한 값으로 `Print` 이벤트가 발생했음을 보여줍니다. `Print` 이벤트의 인수가 uint256이었으므로 ABI 규칙에 따라 디코딩하면 예상되는 10진수 42를 얻을 수 있습니다. 데이터 외에도 토픽을 사용하여 어떤 이벤트가 로그를 생성했는지 확인할 수 있다는 점에 주목할 가치가 있습니다. + +```javascript +web3.sha3("Print(uint256)") +// "24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da" +``` + +이것은 JSON-RPC의 직접적인 사용을 보여주는 가장 일반적인 작업 중 일부에 대한 간략한 소개였습니다. + +## 관련 주제 {#related-topics} + +- [JSON-RPC 사양](http://www.jsonrpc.org/specification) +- [노드 및 클라이언트](/developers/docs/nodes-and-clients/) +- [JavaScript API](/developers/docs/apis/javascript/) +- [백엔드 API](/developers/docs/apis/backend/) +- [실행 클라이언트](/developers/docs/nodes-and-clients/#execution-clients) diff --git a/public/content/translations/ko/developers/docs/blocks/index.md b/public/content/translations/ko/developers/docs/blocks/index.md new file mode 100644 index 00000000000..acd4581d457 --- /dev/null +++ b/public/content/translations/ko/developers/docs/blocks/index.md @@ -0,0 +1,153 @@ +--- +title: "블록" +description: "이더리움 블록체인 내의 블록 개요 - 데이터 구조, 왜 필요한지 그리고 어떻게 만들어지는지" +lang: ko +--- + +블록은 이전 블록의 해시를 포함하는 체인 내의 트랜잭션의 묶음입니다. 블록을 체인으로 연결하는 이유는 해시는 암호화 방식으로 블록 데이터에서 파생되기 때문입니다. 이것은 이전의 어느 블록의 하나의 변경이 모든 이어지는 해시를 바꾸면서 그 다음의 모든 블록을 무효화하고, 블록체인을 실행하는 모두에게 알리기 때문에 사기를 막는다. + +## 필수 구성 요소 {#prerequisites} + +블록은 입문자에게 매우 친근한 주제입니다. 하지만 이 페이지를 더 잘 이해하는 데 도움이 되도록 먼저 [계정](/developers/docs/accounts/), [트랜잭션](/developers/docs/transactions/), [이더리움 소개](/developers/docs/intro-to-ethereum/)를 읽어보시는 것을 추천합니다. + +## 블록을 사용하는 이유 {#why-blocks} + +이더리움 네트워크의 모든 참여자가 동기화된 상태를 유지하고 정확한 트랜잭션 기록에 동의할 수 있도록 트랜잭션을 블록으로 일괄 처리합니다. 이는 수십(수백) 개의 트랜잭션이 제출되고, 합의하며, 한번에 동기화된다는 것을 의미합니다. + +![블록 내 트랜잭션이 상태 변화를 일으키는 것을 보여주는 다이어그램](./tx-block.png) +_다이어그램은 [Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)에서 발췌_ + +제출 간격을 두어, 모든 네트워크 참여자들에게 합의할 수 있는 충분한 시간을 줍니다. 요청 트랜잭션이 초당 수십개가 발생하더라도, 블록은 매 12초마다 한번 생성되어 제출됩니다. + +## 블록 작동 방식 {#how-blocks-work} + +트랜잭션 기록을 보존하기 위해서, 블록은 엄격히 순서를 정하고 (모든 생성된 새로운 블록은 그 부모 블록의 참조를 갖는다), 블록 내의 트랜잭션도 엄격히 순서가 잘 정해진다. 드문 경우를 제외하고, 언제나 네트워크 상의 모든 참여자들은 정확한 숫자와 블록 기록 상에서 합의되어 있고, 현재 라이브 트랜잭션 요청을 다음 블록으로 묶기 위해 동작 중이다. + +네트워크에서 무작위로 선택된 검증인이 블록을 구성하면 해당 블록은 네트워크의 나머지 부분으로 전파됩니다. 모든 노드는 이 블록을 블록체인 끝에 추가하고 다음 블록을 생성하기 위해 새로운 검증자가 선택됩니다 정확한 블록-구성 과정과 제출/합의 과정은 현재 이더리움의 "작업증명" 프로토콜에 명시되어있다. + +## 지분 증명 프로토콜 {#proof-of-stake-protocol} + +작업 증명은 다음을 의미합니다. + +- 검증 노드는 나쁜 행동에 대한 담보로 예금 계좌에 32 ETH를 스테이킹해야 한다. 이는 부정직한 활동으로 인해 해당 지분의 일부 또는 전부가 파괴될 수 있으므로 네트워크를 보호하는 데 도움이 된다. +- 모든 슬롯(12초 간격) 에서 검증인은 블록 제안자로 무작위로 선택된다. 그들은 트랜잭션들을 하나로 묶어서 실행하고 새로운 'state'를 결정한다. 그들은 정보를 블럭에 담아 다른 검증자에게 전달한다. +- 새로운 블록에 대한 소식을 들은 다른 검증인은 트랜잭션을 다시 실행하여 글로벌 상태에 대한 제안된 변경 사항에 동의하는지 확인합니다. 블록이 유효하다고 가정하면 이를 자신의 데이터베이스에 추가합니다. +- 검증인이 동일한 슬롯에서 두 개의 충돌하는 블록에 대해 듣게 되면 포크 선택 알고리즘을 사용하여 가장 많이 스테이킹된 ETH가 지원하는 블록을 선택합니다. + +[지분 증명에 대해 더 알아보기](/developers/docs/consensus-mechanisms/pos) + +## 블록 내에 무엇이 있나요? {#block-anatomy} + +블록은 수많은 정보를 담고 있습니다. 가장 높은 레벨의 블록에는 다음 필드가 포함됩니다: + +| 필드 | 설명 | +| :--------------- | :--------------------- | +| `슬롯` | 블록이 속한 슬롯 | +| `proposer_index` | 블록을 제안하는 검증자의 ID | +| `parent_root` | 이전 블록의 해시 | +| `state_root` | 상태 객체의 루트 해시 | +| `본문` | 아래에 정의된 여러 필드를 포함하는 객체 | + +블록 `body`는 자체적으로 여러 필드를 포함합니다: + +| 필드 | 설명 | +| :------------------- | :------------------------------------- | +| `randao_reveal` | 다음 블록 제안자를 선택하는 데 사용되는 값 | +| `eth1_data` | 예금 계약에 대한 정보 | +| `graffiti` | 블록에 태그를 지정하는 데 사용되는 임의의 데이터 | +| `proposer_slashings` | 슬래싱될 검증자 목록 | +| `attester_slashings` | 슬래싱될 인증자 목록 | +| `인증` | 이전 슬롯에 대해 이루어진 인증 목록 | +| `입금` | 예금 계약에 대한 새로운 예금 목록 | +| `voluntary_exits` | 네트워크를 나가는 검증자 목록 | +| `sync_aggregate` | 라이트 클라이언트에 서비스를 제공하는 데 사용되는 검증자의 하위 집합 | +| `execution_payload` | 실행 클라이언트에서 전달된 트랜잭션 | + +`attestations` 필드에는 블록에 있는 모든 인증 목록이 포함됩니다. 인증서에는 데이터 타입과 여러 조각의 데이터가 포함됩니다. 각 인증에는 다음이 포함됩니다. + +| 필드 | 설명 | +| :----------------- | :-------------------------- | +| `aggregation_bits` | 이 인증에 참여한 검증자 목록 | +| `데이터` | 여러 하위 필드가 있는 컨테이너 | +| `signature` | `data` 부분에 대한 검증자 집합의 집계 서명 | + +`attestation`의 `data` 필드에는 다음이 포함됩니다. + +| 필드 | 설명 | +| :------------------ | :------------------------ | +| `슬롯` | 인증과 관련된 슬롯 | +| `index` | 인증하는 검증자의 인덱스 | +| `beacon_block_root` | 체인의 헤드로 간주되는 비콘 블록의 루트 해시 | +| `출처` | 마지막으로 정당화된 체크포인트 | +| `target` | 최신 에폭 경계 블록 | + +`execution_payload`에서 트랜잭션을 실행하면 전역 상태가 업데이트됩니다. 모든 클라이언트는 `execution_payload`의 트랜잭션을 다시 실행하여 새로운 상태가 새 블록의 `state_root` 필드에 있는 상태와 일치하는지 확인합니다. 이것이 클라이언트가 새 블록이 유효하고 블록체인에 안전하게 추가할 수 있는지 알 수 있는 방법입니다. `execution payload` 자체는 여러 필드가 있는 객체입니다. 또한 실행 데이터에 대한 중요한 요약 정보가 포함된 `execution_payload_header`가 있습니다. 이러한 데이터 구조는 다음과 같이 구성됩니다. + +`execution_payload_header`에는 다음 필드가 포함됩니다. + +| 필드 | 설명 | +| :------------------ | :---------------------------------- | +| `parent_hash` | 부모 블록의 해시 | +| `fee_recipient` | 거래 수수료를 지불할 계정 주소 | +| `state_root` | 이 블록의 변경 사항을 적용한 후의 전역 상태에 대한 루트 해시 | +| `receipts_root` | 거래 영수증 트리의 해시 | +| `logs_bloom` | 이벤트 로그를 포함하는 데이터 구조 | +| `prev_randao` | 임의 검증자 선택에 사용되는 값 | +| `block_number` | 현재 블록의 번호 | +| `gas_limit` | 이 블록에서 허용되는 최대 가스 | +| `gas_used` | 이 블록에서 실제 사용된 가스량 | +| `timestamp` | 블록 시간 | +| `extra_data` | 원시 바이트로서의 임의의 추가 데이터 | +| `base_fee_per_gas` | 기본 수수료 값 | +| `block_hash` | 실행 블록의 해시 | +| `transactions_root` | 페이로드에 있는 트랜잭션의 루트 해시 | +| `withdrawal_root` | 페이로드에 있는 인출의 루트 해시 | + +`execution_payload` 자체에는 다음이 포함됩니다(트랜잭션의 루트 해시 대신 실제 트랜잭션 목록 및 인출 정보가 포함된다는 점을 제외하면 헤더와 동일합니다): + +| 필드 | 설명 | +| :----------------- | :---------------------------------- | +| `parent_hash` | 부모 블록의 해시 | +| `fee_recipient` | 거래 수수료를 지불할 계정 주소 | +| `state_root` | 이 블록의 변경 사항을 적용한 후의 전역 상태에 대한 루트 해시 | +| `receipts_root` | 거래 영수증 트리의 해시 | +| `logs_bloom` | 이벤트 로그를 포함하는 데이터 구조 | +| `prev_randao` | 임의 검증자 선택에 사용되는 값 | +| `block_number` | 현재 블록의 번호 | +| `gas_limit` | 이 블록에서 허용되는 최대 가스 | +| `gas_used` | 이 블록에서 실제 사용된 가스량 | +| `timestamp` | 블록 시간 | +| `extra_data` | 원시 바이트로서의 임의의 추가 데이터 | +| `base_fee_per_gas` | 기본 수수료 값 | +| `block_hash` | 실행 블록의 해시 | +| `트랜잭션` | 실행할 트랜잭션 목록 | +| `출금` | 인출 객체 목록 | + +`withdrawals` 목록에는 다음과 같이 구성된 `withdrawal` 객체가 포함됩니다. + +| 필드 | 설명 | +| :--------------- | :-------- | +| `주소` | 인출한 계정 주소 | +| `amount` | 인출 금액 | +| `index` | 인출 인덱스 값 | +| `validatorIndex` | 검증자 인덱스 값 | + +## 블록 시간 {#block-time} + +블록 시간이란 블록 사이의 시간을 의미합니다. 이더리움에서 시간은 '슬롯'이라고 하는 12초 단위로 나뉩니다. 각 슬롯에서 단일 검증자가 블록을 제안하도록 선택됩니다. 모든 검증자가 온라인 상태이고 완벽하게 작동한다고 가정하면 모든 슬롯에 블록이 존재하게 되며, 이는 블록 시간이 12초임을 의미합니다. 그러나 때로는 검증자가 블록을 제안하도록 호출되었을 때 오프라인 상태일 수 있으며, 이는 슬롯이 비어 있을 수 있음을 의미합니다. + +이 구현은 블록 시간이 확률적이며 프로토콜의 목표 채굴 난이도에 따라 조정되는 작업 증명 기반 시스템과 다릅니다. 이더리움의 [평균 블록 시간](https://etherscan.io/chart/blocktime)은 작업 증명에서 지분 증명으로의 전환이 새로운 12초 블록 시간의 일관성을 기반으로 명확하게 추론될 수 있는 완벽한 예입니다. + +## 블록 크기 {#block-size} + +마지막 중요한 유의점은 블록 그 자체가 크기 한계를 가진다는 것이다. 각 블록의 목표 크기는 3,000만 가스이지만, 네트워크 수요에 따라 블록 크기는 6,000만 가스(목표 블록 크기의 2배) 한도까지 증가하거나 감소합니다. 블록 가스 한도는 이전 블록의 가스 한도에서 1/1024만큼 상향 또는 하향 조정될 수 있습니다. 결과적으로, 검증자는 합의를 통해 블록 가스 한도를 변경할 수 있습니다. 블록 내 모든 트랜잭션에서 소비된 총 가스량은 블록 가스 한도보다 작아야 합니다. 블록이 제멋대로 커질 수 없도록 보장하기 때문에 이는 중요하다. 블록이 제멋대로 커질 수 있다면, 적은 성능 기준의 풀 노드들이 공간과 시간적 요구 사항으로 인해 네트워크 유지를 차츰 멈출 것이다. 블록이 클수록 다음 슬롯 시간에 맞춰 처리하는 데 더 큰 컴퓨팅 파워가 필요합니다. 이는 중앙화 요인이며, 블록 크기를 제한함으로써 이를 방지합니다. + +## 더 읽어보기 {#further-reading} + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 관련 주제 {#related-topics} + +- [트랜잭션](/developers/docs/transactions/) +- [가스](/developers/docs/gas/) +- [지분 증명](/developers/docs/consensus-mechanisms/pos) diff --git a/public/content/translations/ko/developers/docs/bridges/index.md b/public/content/translations/ko/developers/docs/bridges/index.md new file mode 100644 index 00000000000..03b17b1d992 --- /dev/null +++ b/public/content/translations/ko/developers/docs/bridges/index.md @@ -0,0 +1,138 @@ +--- +title: "브릿지" +description: "개발자를 위한 브리징 개요" +lang: ko +--- + +L1 블록체인과 L2 [확장](/developers/docs/scaling/) 솔루션이 확산되고, 점점 더 많은 탈중앙화 애플리케이션이 크로스체인으로 전환됨에 따라, 체인 간 통신 및 자산 이동의 필요성은 네트워크 인프라의 필수적인 부분이 되었습니다. 이를 가능하게 하기 위해 다양한 유형의 브리지가 존재합니다. + +## 브리지의 필요성 {#need-for-bridges} + +브리지는 블록체인 네트워크를 연결하기 위해 존재합니다. 브리지는 블록체인 간의 연결성과 상호운용성을 가능하게 합니다. + +블록체인은 분리된 환경에 존재하므로, 블록체인이 다른 블록체인과 자연스럽게 거래하고 통신할 방법이 없습니다. 결과적으로, 한 생태계 내에서 상당한 활동과 혁신이 있을 수 있지만, 다른 생태계와의 연결성 및 상호운용성 부족으로 인해 제한됩니다. + +브리지는 고립된 블록체인 환경이 서로 연결될 수 있는 방법을 제공합니다. 브리지는 토큰, 메시지, 임의의 데이터, 심지어 [스마트 계약](/developers/docs/smart-contracts/) 호출까지 한 체인에서 다른 체인으로 전송할 수 있는 블록체인 간의 전송 경로를 설정합니다. + +## 브리지의 이점 {#benefits-of-bridges} + +간단히 말해, 브리지는 블록체인 네트워크가 데이터를 교환하고 자산을 이동할 수 있도록 하여 수많은 사용 사례를 가능하게 합니다. + +블록체인은 애플리케이션 구축에 있어 고유한 강점, 약점, 접근 방식(예: 속도, 처리량, 비용 등)을 가지고 있습니다. 브리지는 블록체인이 서로의 혁신을 활용할 수 있도록 하여 전체 암호화폐 생태계의 발전에 기여합니다. + +개발자에게 브리지는 다음을 가능하게 합니다. + +- 체인 간 모든 데이터, 정보 및 자산의 전송. +- 브리지가 프로토콜이 제공할 수 있는 설계 공간을 확장함에 따라 프로토콜에 대한 새로운 기능과 사용 사례를 발굴합니다. 예를 들어, 원래 이더리움 메인넷에 배포된 이자 농사 프로토콜은 모든 EVM 호환 체인에 유동성 풀을 제공할 수 있습니다. +- 다양한 블록체인의 강점을 활용할 기회. 예를 들어, 개발자는 롤업 및 사이드체인 전반에 탈중앙화앱을 배포하여 다양한 L2 솔루션이 제공하는 더 낮은 수수료의 이점을 누릴 수 있으며, 사용자는 이를 통해 브리지를 이용할 수 있습니다. +- 다양한 블록체인 생태계의 개발자 간 협력을 통해 새로운 제품을 구축합니다. +- 다양한 생태계의 사용자와 커뮤니티를 자신의 탈중앙화앱으로 유치합니다. + +## 브리지는 어떻게 작동하나요? {#how-do-bridges-work} + +다양한 [유형의 브리지 설계](https://li.fi/knowledge-hub/blockchain-bridges-and-classification/)가 있지만, 자산의 크로스체인 전송을 용이하게 하는 세 가지 방법이 두드러집니다. + +- **잠금 및 발행 –** 소스 체인에서 자산을 잠그고 대상 체인에서 자산을 발행합니다. +- **소각 및 발행 –** 소스 체인에서 자산을 소각하고 대상 체인에서 자산을 발행합니다. +- **아토믹 스왑 –** 다른 당사자와 소스 체인의 자산을 대상 체인의 자산으로 교환합니다. + +## 브리지 유형 {#bridge-types} + +브리지는 일반적으로 다음 유형 중 하나로 분류할 수 있습니다. + +- **네이티브 브리지 –** 이 브리지는 일반적으로 특정 블록체인의 유동성을 부트스트랩하기 위해 구축되어 사용자가 생태계로 자금을 쉽게 이동할 수 있도록 합니다. 예를 들어, [Arbitrum Bridge](https://bridge.arbitrum.io/)는 사용자가 이더리움 메인넷에서 Arbitrum으로 편리하게 브리징할 수 있도록 구축되었습니다. 이러한 브리지에는 Polygon PoS Bridge, [Optimism Gateway](https://app.optimism.io/bridge) 등이 있습니다. +- **검증자 또는 오라클 기반 브리지 –** 이 브리지는 외부 검증자 세트 또는 오라클에 의존하여 크로스체인 전송을 검증합니다. 예: Multichain 및 Across. +- **일반화된 메시지 전달 브리지 –** 이 브리지는 메시지 및 임의의 데이터와 함께 자산을 체인 간에 전송할 수 있습니다. 예: Axelar, LayerZero, Nomad. +- **유동성 네트워크 –** 이 브리지는 주로 아토믹 스왑을 통해 한 체인에서 다른 체인으로 자산을 전송하는 데 중점을 둡니다. 일반적으로 크로스체인 메시지 전달을 지원하지 않습니다. 예: Connext 및 Hop. + +## 고려해야 할 절충안 {#trade-offs} + +브리지에는 완벽한 해결책이 없습니다. 오히려 목적을 달성하기 위한 절충안만 있을 뿐입니다. 개발자와 사용자는 다음 요소를 기반으로 브리지를 평가할 수 있습니다. + +- **보안 –** 누가 시스템을 검증하나요? 외부 검증자에 의해 보호되는 브리지는 일반적으로 블록체인의 검증자에 의해 로컬 또는 네이티브로 보호되는 브리지보다 안전하지 않습니다. +- **편의성 –** 트랜잭션을 완료하는 데 얼마나 걸리며, 사용자는 몇 개의 트랜잭션에 서명해야 했나요? 개발자의 경우, 브리지를 통합하는 데 얼마나 걸리며 그 과정은 얼마나 복잡한가요? +- **연결성 –** 브리지가 연결할 수 있는 대상 체인(예: 롤업, 사이드체인, 기타 레이어 1 블록체인 등)은 무엇이며, 새로운 블록체인을 통합하는 것은 얼마나 어려운가요? +- **더 복잡한 데이터 전달 능력 –** 브리지가 체인 간에 메시지와 더 복잡한 임의의 데이터를 전송할 수 있나요, 아니면 크로스체인 자산 전송만 지원하나요? +- **비용 효율성 –** 브리지를 통해 체인 간 자산을 전송하는 데 드는 비용은 얼마인가요? 일반적으로 브리지는 가스 비용 및 특정 경로의 유동성에 따라 고정 또는 가변 수수료를 부과합니다. 또한 보안을 보장하는 데 필요한 자본을 기반으로 브리지의 비용 효율성을 평가하는 것도 중요합니다. + +크게 보면, 브리지는 신뢰 기반과 무신뢰 기반으로 분류할 수 있습니다. + +- **신뢰 기반 –** 신뢰 기반 브리지는 외부에서 검증됩니다. 이들은 외부 검증자 세트(다중 서명 연합, 다자간 컴퓨팅 시스템, 오라클 네트워크)를 사용하여 체인 간 데이터를 전송합니다. 결과적으로, 이들은 뛰어난 연결성을 제공하고 체인 간에 완전히 일반화된 메시지 전달을 가능하게 할 수 있습니다. 또한 속도와 비용 효율성 측면에서도 우수한 성능을 보이는 경향이 있습니다. 이는 사용자가 브리지의 보안에 의존해야 하므로 보안을 희생하는 대가로 이루어집니다. +- **무신뢰 기반 –** 이 브리지는 연결하는 블록체인과 해당 검증자에 의존하여 메시지와 토큰을 전송합니다. 이들은 (블록체인 외에) 새로운 신뢰 가정을 추가하지 않기 때문에 '무신뢰'입니다. 결과적으로 무신뢰 기반 브리지는 신뢰 기반 브리지보다 더 안전한 것으로 간주됩니다. + +다른 요소를 기반으로 무신뢰 기반 브리지를 평가하려면, 이를 일반화된 메시지 전달 브리지와 유동성 네트워크로 나누어야 합니다. + +- **일반화된 메시지 전달 브리지 –** 이 브리지는 보안과 체인 간에 더 복잡한 데이터를 전송하는 능력에서 뛰어납니다. 일반적으로 비용 효율성도 우수합니다. 그러나 이러한 강점은 일반적으로 라이트 클라이언트 브리지(예: IBC)의 연결성 저하와 사기 증명을 사용하는 낙관적 브리지(예: Nomad)의 속도 저하를 대가로 합니다. +- **유동성 네트워크 –** 이 브리지는 아토믹 스왑을 사용하여 자산을 전송하며 로컬에서 검증되는 시스템입니다(즉, 기본 블록체인의 검증자를 사용하여 트랜잭션을 검증합니다). 결과적으로, 이들은 보안과 속도에서 뛰어납니다. 또한, 비교적 비용 효율적이며 우수한 연결성을 제공하는 것으로 간주됩니다. 그러나 주요 절충안은 크로스체인 메시지 전달을 지원하지 않기 때문에 더 복잡한 데이터를 전달할 수 없다는 것입니다. + +## 브리지의 위험성 {#risk-with-bridges} + +브리지는 [DeFi에서 가장 큰 해킹](https://rekt.news/leaderboard/) 상위 3건을 차지하며, 아직 개발 초기 단계에 있습니다. 어떤 브리지를 사용하든 다음과 같은 위험이 따릅니다. + +- **스마트 계약 위험 –** 많은 브리지가 성공적으로 감사를 통과했지만, 스마트 계약의 단 하나의 결함만으로도 자산이 해킹에 노출될 수 있습니다(예: [솔라나의 웜홀 브리지](https://rekt.news/wormhole-rekt/)). +- **시스템적 금융 위험** – 많은 브리지가 래핑된 자산을 사용하여 새 체인에서 원본 자산의 표준 버전을 발행합니다. 이는 생태계를 시스템적 위험에 노출시키는데, 우리는 래핑된 버전의 토큰이 악용되는 것을 보았습니다. +- **거래 상대방 위험 –** 일부 브리지는 사용자가 검증자들이 공모하여 사용자 자금을 훔치지 않을 것이라는 가정에 의존해야 하는 신뢰 기반 설계를 사용합니다. 사용자가 이러한 제3자 행위자를 신뢰해야 할 필요성은 러그 풀, 검열 및 기타 악의적인 활동과 같은 위험에 노출시킵니다. +- **미해결 문제 –** 브리지가 개발 초기 단계에 있다는 점을 감안할 때, 네트워크 혼잡 시나 네트워크 수준 공격 또는 상태 롤백과 같은 예기치 않은 이벤트 동안 브리지가 다양한 시장 상황에서 어떻게 작동할지에 대한 많은 미해결 질문이 있습니다. 이러한 불확실성은 특정 위험을 제기하며, 그 정도는 아직 알려지지 않았습니다. + +## 탈중앙화앱은 브리지를 어떻게 사용할 수 있나요? {#how-can-dapps-use-bridges} + +다음은 개발자가 브리지 및 탈중앙화앱의 크로스체인 전환에 대해 고려할 수 있는 몇 가지 실용적인 애플리케이션입니다. + +### 브리지 통합하기 {#integrating-bridges} + +개발자를 위해 브리지 지원을 추가하는 방법은 여러 가지가 있습니다. + +1. **자체 브리지 구축 –** 안전하고 신뢰할 수 있는 브리지를 구축하는 것은 쉽지 않으며, 특히 신뢰를 최소화하는 경로를 택하는 경우 더욱 그렇습니다. 또한, 확장성 및 상호운용성 연구와 관련된 수년간의 경험과 기술 전문 지식이 필요합니다. 또한, 브리지를 유지하고 실행 가능하게 만들기 위해 충분한 유동성을 유치할 실무 팀이 필요합니다. + +2. **사용자에게 여러 브리지 옵션 표시 –** 많은 [탈중앙화앱](/developers/docs/dapps/)은 사용자가 상호 작용하기 위해 네이티브 토큰을 보유해야 합니다. 사용자가 자신의 토큰에 액세스할 수 있도록 웹사이트에서 다양한 브리지 옵션을 제공합니다. 그러나 이 방법은 사용자를 탈중앙화앱 인터페이스에서 벗어나게 하고 다른 탈중앙화앱 및 브리지와 상호 작용해야 하므로 문제에 대한 임시방편입니다. 이는 실수를 할 가능성이 높아지는 번거로운 온보딩 경험입니다. + +3. **브리지 통합 –** 이 솔루션은 탈중앙화앱이 사용자를 외부 브리지 및 DEX 인터페이스로 보낼 필요가 없습니다. 이를 통해 탈중앙화앱은 사용자 온보딩 경험을 개선할 수 있습니다. 하지만 이 접근 방식에는 한계가 있습니다. + + - 브리지의 평가 및 유지 관리는 어렵고 시간이 많이 소요됩니다. + - 하나의 브리지를 선택하면 단일 장애점과 종속성이 발생합니다. + - 탈중앙화앱은 브리지의 기능에 의해 제한됩니다. + - 브리지만으로는 충분하지 않을 수 있습니다. 탈중앙화앱은 크로스체인 스왑과 같은 더 많은 기능을 제공하기 위해 DEX가 필요할 수 있습니다. + +4. **여러 브리지 통합 –** 이 솔루션은 단일 브리지 통합과 관련된 많은 문제를 해결합니다. 그러나 여러 브리지를 통합하는 것은 리소스를 많이 소모하고 개발자에게 기술 및 통신 오버헤드를 발생시키기 때문에 한계가 있습니다. 이는 암호화폐에서 가장 부족한 리소스입니다. + +5. **브리지 애그리게이터 통합 –** 탈중앙화앱을 위한 또 다른 옵션은 여러 브리지에 대한 액세스를 제공하는 브리지 애그리게이터 솔루션을 통합하는 것입니다. 브리지 애그리게이터는 모든 브리지의 강점을 상속하므로 단일 브리지의 기능에 의해 제한되지 않습니다. 특히, 브리지 애그리게이터는 일반적으로 브리지 통합을 유지 관리하므로 탈중앙화앱이 브리지 통합의 기술 및 운영 측면을 파악해야 하는 번거로움을 덜어줍니다. + +그렇긴 하지만, 브리지 애그리게이터에도 한계가 있습니다. 예를 들어, 더 많은 브리지 옵션을 제공할 수 있지만, 일반적으로 시장에는 애그리게이터 플랫폼에서 제공하는 것 외에 더 많은 브리지가 있습니다. 또한, 브리지와 마찬가지로 브리지 애그리게이터도 스마트 계약 및 기술 위험에 노출됩니다(더 많은 스마트 계약 = 더 많은 위험). + +탈중앙화앱이 브리지 또는 애그리게이터를 통합하는 경로를 택하는 경우, 통합의 깊이에 따라 다양한 옵션이 있습니다. 예를 들어, 사용자 온보딩 경험을 개선하기 위한 프런트엔드 통합일 뿐이라면 탈중앙화앱은 위젯을 통합할 것입니다. 그러나 통합이 스테이킹, 이자 농사 등과 같은 더 깊은 크로스체인 전략을 탐색하기 위한 것이라면 탈중앙화앱은 SDK 또는 API를 통합합니다. + +### 여러 체인에 탈중앙화앱 배포하기 {#deploying-a-dapp-on-multiple-chains} + +여러 체인에 탈중앙화앱을 배포하기 위해 개발자는 [Alchemy](https://www.alchemy.com/), [Hardhat](https://hardhat.org/), [Moralis](https://moralis.io/) 등과 같은 개발 플랫폼을 사용할 수 있습니다. 일반적으로 이러한 플랫폼에는 탈중앙화앱이 크로스체인으로 전환할 수 있도록 하는 구성 가능한 플러그인이 함께 제공됩니다. 예를 들어, 개발자는 [hardhat-deploy plugin](https://github.com/wighawag/hardhat-deploy)에서 제공하는 결정론적 배포 프록시를 사용할 수 있습니다. + +#### 예시: + +- [크로스체인 탈중앙화앱을 구축하는 방법](https://moralis.io/how-to-build-cross-chain-dapps/) +- [크로스체인 NFT 마켓플레이스 구축하기](https://youtu.be/WZWCzsB1xUE) +- [Moralis: 크로스체인 NFT 탈중앙화앱 구축하기](https://www.youtube.com/watch?v=ehv70kE1QYo) + +### 체인 간 계약 활동 모니터링하기 {#monitoring-contract-activity-across-chains} + +체인 간 계약 활동을 모니터링하기 위해 개발자는 서브그래프 및 Tenderly와 같은 개발자 플랫폼을 사용하여 스마트 계약을 실시간으로 관찰할 수 있습니다. 이러한 플랫폼에는 [계약에서 발생한 이벤트](https://docs.soliditylang.org/en/v0.8.14/contracts.html?highlight=events#events) 확인 등 크로스체인 활동에 대한 더 큰 데이터 모니터링 기능을 제공하는 도구도 있습니다. + +#### 도구 + +- [The Graph](https://thegraph.com/en/) +- [Tenderly](https://tenderly.co/) + +## 더 읽어보기 {#further-reading} + +- [블록체인 브리지](/bridges/) – ethereum.org +- [L2Beat 브리지 위험 프레임워크](https://l2beat.com/bridges/summary) +- [블록체인 브리지: 암호화폐 네트워크의 네트워크 구축](https://medium.com/1kxnetwork/blockchain-bridges-5db6afac44f8) - 2021년 9월 8일 – Dmitriy Berenzon +- [상호운용성 트릴레마](https://blog.connext.network/the-interoperability-trilemma-657c2cf69f17) - 2021년 10월 1일 – Arjun Bhuptani +- [클러스터: 신뢰 기반 및 신뢰 최소화 브리지가 멀티체인 환경을 형성하는 방법](https://blog.celestia.org/clusters/) - 2021년 10월 4일 – Mustafa Al-Bassam +- [LI.FI: 브리지에서 신뢰는 스펙트럼입니다](https://blog.li.fi/li-fi-with-bridges-trust-is-a-spectrum-354cd5a1a6d8) - 2022년 4월 28일 – Arjun Chand +- [롤업 상호운용성 솔루션의 현황](https://web.archive.org/web/20250428015516/https://research.2077.xyz/the-state-of-rollup-interoperability) - 2024년 6월 20일 – Alex Hook +- [안전한 크로스체인 상호운용성을 위한 공유 보안 활용: Lagrange State Committees 등](https://web.archive.org/web/20250125035123/https://research.2077.xyz/harnessing-shared-security-for-secure-blockchain-interoperability) - 2024년 6월 12일 – Emmanuel Awosika + +또한, [James Prestwich](https://twitter.com/_prestwich)가 브리지에 대한 더 깊은 이해를 돕기 위해 제공한 통찰력 있는 발표 자료가 있습니다. + +- [벽으로 둘러싸인 정원이 아닌 브리지 구축하기](https://youtu.be/ZQJWMiX4hT0) +- [브리지 분석하기](https://youtu.be/b0mC-ZqN8Oo) +- [브리지는 왜 불타고 있는가](https://youtu.be/c7cm2kd20j8) diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/index.md new file mode 100644 index 00000000000..f08c1a23da0 --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/index.md @@ -0,0 +1,92 @@ +--- +title: "합의 메커니즘" +description: "분산 시스템에서 합의 프로토콜에 대한 설명과 이더리움에서의 역할." +lang: ko +--- + +'합의 메커니즘'이라는 용어는 일반적으로 '지분 증명', '작업 증명' 또는 '권위 증명' 프로토콜을 지칭할 때 사용됩니다. 하지만 이는 [시빌 공격](/glossary/#sybil-attack)으로부터 보호하는 합의 메커니즘의 구성 요소일 뿐입니다. 합의 메커니즘은 분산된 노드들이 블록체인의 상태에 동의할 수 있게 해주는 아이디어, 프로토콜 및 인센티브의 전체 스택입니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하려면 먼저 [이더리움 소개](/developers/docs/intro-to-ethereum/)를 읽어보시는 것을 추천합니다. + +## 합의란 무엇인가요? {#what-is-consensus} + +합의를 통해 기본적인 동의가 완료됩니다. 영화관에 가려고 하는 사람들을 사람들을 생각해 봅시다. 같이 보려고 하는 영화에 대해 누구도 거부하지 않는다면 합의가 이루어진 것입니다. 누군가가 거부한다면 사람들은 어떤 영화를 볼 지 정해야 합니다. 심한 경우에는 결국 사람들이 나뉠 수 있습니다. + +이더리움 블록체인에서 이 프로세스는 정형화되어 있으며, 합의에 도달한다는 것은 네트워크 노드의 66% 이상이 네트워크의 글로벌 상태에 동의한다는 것을 의미합니다. + +## 합의 메커니즘이란 무엇인가요? 합의 메커니즘이란? {#what-is-a-consensus-mechanism} + +합의 메커니즘은 노드 네트워크가 블록체인의 상태에 동의할 수 있도록 하는 모든 프로토콜, 인센티브 및 아이디어의 집합체입니다. + +이더리움은 지분 증명 기반의 합의 메커니즘을 사용하여 스테이커가 잠근 자본에 적용된 일련의 보상 및 불이익을 통해 암호화폐 경제의 보안을 유지합니다. 이러한 인센티브 구조를 통해 개인 스테이커는 검증자를 정직하게 운영하도록 하고, 그러지 않는 사람에게 불이익을 가하며, 네트워크 공격에 필요한 가격을 극도로 높입니다. + +또한, 정직한 검증자가 블록을 제안하거나 검증하도록 선택되는 프로토콜이 있습니다. 드문 상황에서 여러 블록이 체인의 맨 앞에 있는 경우, 포크 선택 메커니즘이 검증자가 지분한 이더 잔액에 따라 블록을 선택합니다. + +코드로 명시적으로 정의되지 않은 추가 보안 개념은 네트워크 공격에 대한 마지막 방어 수단으로 작동할 수 있습니다. + +이러한 구성 요소들이 합쳐져 합의 메커니즘을 형성합니다. + +## 합의 메커니즘의 유형 {#types-of-consensus-mechanisms} + +### 작업 증명 기반 {#proof-of-work} + +비트코인처럼 이더리움은 한때 **작업 증명(PoW)** 기반 합의 프로토콜을 사용했습니다. + +#### 블록 생성 {#pow-block-creation} + +채굴자들이 처리된 트랜잭션으로 가득 찬 새 블록을 만들기 위해 경쟁합니다. 승자는 새 블록을 네트워크에 공유하고 새로 발행된 ETH를 얻습니다. 수학 문제를 가장 빠르게 푸는 컴퓨터가 경주에서 이깁니다. 이 과정이 현재 블록과 이전 블록 간의 암호학적 연결을 만듭니다. 이 퍼즐을 푸는 것이 작업 증명에서의 '작업'입니다. 정통 체인은 채굴된 블록에 가장 많은 작업이 들어간 블록 세트를 선택하는 포크 선택 규칙에 의해 결정됩니다. + +#### 보안 {#pow-security} + +네트워크는 체인을 속이려면 네트워크의 51% 컴퓨팅 파워가 필요하기 때문에 안전하게 유지됩니다. 이 정도의 장비와 에너지를 투자하면 얻는 것보다 더 많은 돈을 쓸 가능성이 큽니다. + +[작업 증명](/developers/docs/consensus-mechanisms/pow/)에 대한 자세한 정보 + +### 지분 증명 기반 {#proof-of-stake} + +현재 이더리움은 **지분 증명(PoS)** 기반 합의 프로토콜을 사용합니다. + +#### 블록 생성 {#pos-block-creation} + +검증자가 블록을 생성합니다. 각 슬롯에서 무작위로 선택된 한 명의 검증자가 블록 제안자가 됩니다. 그들의 합의 클라이언트는 쌍을 이루는 실행 클라이언트에서 '실행 페이로드'로 트랜잭션 번들을 요청합니다. 검증자는 이를 합의 데이터로 감싸 블록을 생성하고, 이를 이더리움 네트워크의 다른 노드에 보냅니다. 이 블록 생성은 ETH로 보상받습니다. 드문 경우지만 여러 가능한 블록이 존재할 경우, 포크 선택 알고리즘은 가장 많은 검증자의 지지를 받은 블록을 선택합니다. + +#### 보안 {#pos-security} + +지분 증명 시스템은 경제적으로 안전합니다. 공격자가 체인을 장악하려면 막대한 양의 ETH를 잃어야 하기 때문입니다. 보상 시스템은 개별 스테이커가 정직하게 행동하도록 인센티브를 제공하며, 처벌은 악의적 행동을 억제합니다. + +[지분 증명](/developers/docs/consensus-mechanisms/pos/)에 대한 자세한 정보 + +### 시각적 가이드 {#types-of-consensus-video} + +이더리움에서 사용되는 다양한 합의 메커니즘에 대해 자세히 알아보세요. + + + +### 시빌 저항 및 체인 선택 {#sybil-chain} + +작업 증명과 지분 증명은 실제로는 합의 프로토콜이 아니지만, 간단하게 설명하기 위해 종종 그렇게 불립니다. 사실, 이들은 시빌 저항 메커니즘이자 블록 작성자를 선택하는 방법입니다. 체인 선택(또는 포크 선택) 알고리즘은 여러 블록이 동일한 위치에 있을 때 한 블록을 선택하는 데 사용됩니다. + +시빌 저항성은 프로토콜이 시빌 공격에 얼마나 잘 대처하는지를 측정합니다. 탈중앙화된 블록체인의 핵심인 시빌 저항은 채굴자와 검증자가 자원 투입에 따라 공정하게 보상받도록 합니다. 작업 증명과 지분 증명은 사용자가 많은 에너지를 소비하거나 많은 담보를 걸도록 하여 시빌 공격을 방어합니다. 이러한 보호 장치는 시빌 공격에 대한 경제적 억제책입니다. + +체인 선택 규칙은 어떤 체인이 "올바른" 체인인지 결정하는 데 사용됩니다. 비트코인은 "가장 긴 체인" 규칙을 사용합니다. 즉, 가장 긴 블록체인이 나머지 노드가 유효하다고 인식하고 작업할 블록체인입니다. 작업증명 체인에서는 체인의 총 누적 작업증명 난이도로 가장 긴 체인이 결정됩니다. 이전에는 이더리움도 가장 긴 체인 규칙을 사용했으나, 현재 이더리움은 작업증명에서 지분증명으로 전환되어 '체인의 무게'를 측정하는 업데이트된 포크 선택 알고리즘을 채택했습니다. 이 무게는 검증자의 지분-이더리움 잔액에 의해 가중된 검증자 투표의 누적 합계입니다. + +이더리움은 [Casper FFG 지분 증명](https://arxiv.org/abs/1710.09437)과 [GHOST 포크 선택 규칙](https://arxiv.org/abs/2003.03052)을 결합한 [Gasper](/developers/docs/consensus-mechanisms/pos/gasper/)라는 합의 메커니즘을 사용합니다. + +## 더 읽어보기 {#further-reading} + +- [블록체인 합의 알고리즘이란?](https://academy.binance.com/en/articles/what-is-a-blockchain-consensus-algorithm) +- [나카모토 합의란 무엇인가요? 완전 초보자 가이드](https://blockonomi.com/nakamoto-consensus/) +- [Casper는 어떻게 작동하는가?](https://medium.com/unitychain/intro-to-casper-ffg-9ed944d98b2d) +- [작업 증명 블록체인의 보안 및 성능에 관하여](https://eprint.iacr.org/2016/555.pdf) +- [비잔틴 장애](https://en.wikipedia.org/wiki/Byzantine_fault) + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 관련 주제 {#related-topics} + +- [작업 증명](/developers/docs/consensus-mechanisms/pow/) +- [채굴](/developers/docs/consensus-mechanisms/pow/mining/) +- [지분 증명](/developers/docs/consensus-mechanisms/pos/) +- [권위 증명](/developers/docs/consensus-mechanisms/poa/) diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/poa/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/poa/index.md new file mode 100644 index 00000000000..4410af084d2 --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/poa/index.md @@ -0,0 +1,80 @@ +--- +title: "권한 증명(Proof-of-authority, PoA)" +description: "권위 증명 합의 프로토콜과 블록체인 생태계에서의 역할에 대한 설명입니다." +lang: ko +--- + +권위 증명(PoA)은 [지분 증명](/developers/docs/consensus-mechanisms/pos/)을 수정한 버전으로, 평판 기반의 합의 알고리즘입니다. 주로 프라이빗 체인, 테스트넷 및 로컬 개발 네트워크에서 사용됩니다. PoA는 지분 증명(PoS)의 지분 기반 메커니즘 대신 승인된 서명자 집합을 신뢰하여 블록을 생성해야 하는 평판 기반 합의 알고리즘입니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하려면 먼저 [트랜잭션](/developers/docs/transactions/), [블록](/developers/docs/blocks/), [합의 메커니즘](/developers/docs/consensus-mechanisms/)에 대해 읽어보시는 것을 추천합니다. + +## 권위 증명(PoA)이란 무엇인가요? {#what-is-poa} + +권위 증명은 [지분 증명](/developers/docs/consensus-mechanisms/pos/)(PoS)의 수정된 버전으로, PoS의 지분 기반 메커니즘 대신 평판 기반의 합의 알고리즘을 사용합니다. 이 용어는 2017년 개빈 우드(Gavin Wood)가 처음 소개했으며, 이 합의 알고리즘은 작업 증명(PoW)처럼 고품질의 리소스를 필요로 하지 않고 블록체인을 저장하고 블록을 생성하는 노드의 작은 하위 집합을 통해 지분 증명(PoS)의 확장성 문제를 극복하므로 주로 프라이빗 체인, 테스트넷, 로컬 개발 네트워크에서 사용되어 왔습니다. + +권위 증명은 [제네시스 블록](/glossary/#genesis-block)에 설정된 승인된 서명자 집합을 신뢰해야 합니다. 대부분의 현재 구현에서 모든 승인된 서명자는 체인의 합의를 결정할 때 동등한 권한과 특권을 보유합니다. 평판 스테이킹의 기본 아이디어는 고객 신원 확인(KYC) 등을 통해 모든 승인된 검증자가 모든 사람에게 잘 알려져 있거나, 잘 알려진 조직이 유일한 검증자가 되는 것입니다. 이렇게 하면 검증자가 잘못된 행동을 할 경우 신원이 알려집니다. + +PoA에는 여러 구현이 있지만, 표준 이더리움 구현은 [EIP-225](https://eips.ethereum.org/EIPS/eip-225)를 구현하는 clique입니다. Clique는 개발자 친화적이고 구현하기 쉬운 표준이며, 모든 클라이언트 동기화 유형을 지원합니다. 다른 구현으로는 [IBFT 2.0](https://besu.hyperledger.org/private-networks/concepts/poa) 및 [Aura](https://openethereum.github.io/Chain-specification)가 있습니다. + +## 작동 방식 {#how-it-works} + +PoA에서는 승인된 서명자 집합이 새 블록을 생성하도록 선택됩니다. 서명자는 평판에 따라 선택되며, 새 블록을 생성할 수 있는 유일한 주체입니다. 서명자는 라운드 로빈 방식으로 선택되며, 각 서명자는 특정 시간 프레임 내에 블록을 생성할 수 있습니다. 블록 생성 시간은 고정되어 있으며, 서명자는 해당 시간 프레임 내에 블록을 생성해야 합니다. + +이 맥락에서 평판은 정량화된 것이 아니라 Microsoft나 Google과 같은 잘 알려진 기업의 평판을 의미합니다. 따라서 신뢰할 수 있는 서명자를 선택하는 방식은 알고리즘적인 것이 아니라, 예를 들어 Microsoft가 수백 또는 수천 개의 스타트업 간에 PoA 프라이빗 네트워크를 생성하고 유일하게 신뢰할 수 있는 서명자로서 역할을 수행하며 향후 Google과 같은 다른 잘 알려진 서명자를 추가할 가능성을 두는 것과 같이 신뢰라는 일반적인 인간의 행위입니다. 스타트업들은 의심의 여지 없이 Microsoft가 항상 정직하게 행동하고 네트워크를 사용할 것이라고 신뢰할 것입니다. 이는 많은 전력과 리소스를 소비하는 채굴자의 필요성과 함께, 서로 다른 목적으로 구축된 다양한 소규모/프라이빗 네트워크를 분산화되고 기능하도록 유지하기 위해 스테이킹할 필요를 해결합니다. VeChain과 같은 일부 프라이빗 네트워크는 PoA 표준을 그대로 사용하고, Binance와 같은 일부는 PoA와 지분 증명(PoS)의 맞춤형 수정 버전인 [PoSA](https://academy.binance.com/en/glossary/proof-of-staked-authority-posa)를 사용하여 이를 수정합니다. + +투표 과정은 서명자 자신에 의해 수행됩니다. 각 서명자는 새 블록을 생성할 때 자신의 블록에서 서명자의 추가 또는 제거에 투표합니다. 투표는 노드에 의해 집계되며, 투표가 특정 임계값 `SIGNER_LIMIT`에 도달하면 서명자가 추가되거나 제거됩니다. + +작은 포크가 발생하는 상황이 있을 수 있으며, 블록의 난이도는 블록이 순서대로 서명되었는지 또는 순서에 맞지 않게 서명되었는지에 따라 달라집니다. “순서대로” 서명된 블록은 난이도 2를 갖고, “순서에 맞지 않게” 서명된 블록은 난이도 1을 갖습니다. 작은 포크의 경우, 대부분의 서명자가 “순서대로” 블록을 봉인하는 체인이 가장 높은 난이도를 축적하여 승리하게 됩니다. + +## 공격 벡터 {#attack-vectors} + +### 악의적인 서명자 {#malicious-signers} + +악의적인 사용자가 서명자 목록에 추가되거나 서명 키/기기가 손상될 수 있습니다. 이러한 시나리오에서 프로토콜은 재구성과 스팸으로부터 자신을 방어할 수 있어야 합니다. 제안된 해결책은 N명의 승인된 서명자 목록이 주어졌을 때, 모든 서명자는 K 블록마다 1개의 블록만 발행할 수 있다는 것입니다. 이를 통해 피해를 제한하고 나머지 검증자가 악의적인 사용자를 투표로 퇴출시킬 수 있습니다. + +### 검열 {#censorship-attack} + +또 다른 흥미로운 공격 벡터는 서명자(또는 서명자 그룹)가 승인 목록에서 자신을 제거하는 데 투표하는 블록을 검열하려고 시도하는 경우입니다. 이 문제를 해결하기 위해 서명자의 허용된 발행 빈도는 N/2 중 1로 제한됩니다. 이를 통해 악의적인 서명자는 서명 계정의 최소 51%를 제어해야 하며, 이 시점에서 이들은 사실상 체인의 새로운 신뢰의 원천이 됩니다. + +### 스팸 {#spam-attack} + +또 다른 작은 공격 벡터는 악의적인 서명자가 발행하는 모든 블록 내에 새로운 투표 제안을 주입하는 것입니다. 노드는 실제 승인된 서명자 목록을 생성하기 위해 모든 투표를 집계해야 하므로 시간이 지남에 따라 모든 투표를 기록해야 합니다. 투표 창에 제한을 두지 않으면 이 목록은 느리지만 무한정으로 증가할 수 있습니다. 해결책은 W 블록의 _이동_ 창을 두어 그 이후의 투표는 오래된 것으로 간주하는 것입니다. _합리적인 창은 1\~2 에폭이 될 수 있습니다._ + +### 동시 블록 {#concurrent-blocks} + +PoA 네트워크에서 N명의 승인된 서명자가 있을 때 각 서명자는 K 블록 중 1개의 블록을 발행할 수 있습니다. 이는 특정 시점에 N-K+1명의 검증자가 발행할 수 있음을 의미합니다. 이러한 검증자들이 블록 경쟁을 하는 것을 방지하기 위해 각 서명자는 새 블록을 릴리스하는 시간에 작은 무작위 "오프셋"을 추가해야 합니다. 이 프로세스는 작은 포크를 드물게 만들지만, 메인넷처럼 가끔 포크가 발생할 수 있습니다. 서명자가 권력을 남용하고 혼란을 야기하는 것이 발견되면 다른 서명자들이 투표를 통해 퇴출시킬 수 있습니다. + +예를 들어, 10명의 승인된 서명자가 있고 각 서명자가 20개의 블록 중 1개의 블록을 생성할 수 있다면, 특정 시점에 11명의 검증자가 블록을 생성할 수 있습니다. 그들이 블록 생성을 위해 경쟁하는 것을 방지하기 위해 각 서명자는 새 블록을 릴리스하는 시간에 작은 무작위 "오프셋"을 추가합니다. 이는 작은 포크의 발생을 줄이지만 이더리움 메인넷에서 볼 수 있듯이 가끔 포크가 발생할 수 있습니다. 서명자가 자신의 권한을 오용하고 혼란을 야기하면 네트워크에서 투표로 퇴출될 수 있습니다. + +## 장단점 {#pros-and-cons} + +| 장점 | 단점 | +| ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | +| 제한된 수의 블록 서명자를 기반으로 하므로 지분 증명(PoS) 및 작업 증명(PoW)과 같은 다른 인기 있는 메커니즘보다 확장성이 뛰어납니다. | PoA 네트워크는 일반적으로 상대적으로 적은 수의 검증 노드를 가집니다. 이로 인해 PoA 네트워크는 더 중앙화됩니다. | +| PoA 블록체인은 운영 및 유지 비용이 매우 저렴합니다. | 블록체인은 확립된 평판을 가진 주체를 요구하기 때문에, 일반인이 승인된 서명자가 되는 것은 일반적으로 어렵습니다. | +| 새 블록을 검증하는 데 제한된 수의 서명자만 필요하기 때문에 트랜잭션이 1초 이내로 매우 빠르게 확인될 수 있습니다. | 악의적인 서명자는 네트워크에서 재구성을 하거나, 이중 지불을 하거나, 트랜잭션을 검열할 수 있으며, 이러한 공격은 완화되었지만 여전히 가능합니다. | + +## 더 읽어보기 {#further-reading} + +- [EIP-225](https://eips.ethereum.org/EIPS/eip-225) _Clique 표준_ +- [권위 증명 연구](https://github.com/cryptoeconomics-study/website/blob/master/docs/sync/2.4-lecture.md) _Cryptoeconomics_ +- [권위 증명이란 무엇인가](https://forum.openzeppelin.com/t/proof-of-authority/3577) _OpenZeppelin_ +- [권위 증명 설명](https://academy.binance.com/en/articles/proof-of-authority-explained) _binance_ +- [블록체인의 PoA](https://medium.com/techskill-brew/proof-of-authority-or-poa-in-blockchain-part-11-blockchain-series-be15b3321cba) +- [Clique 설명](https://medium.com/@Destiner/clique-cross-client-proof-of-authority-algorithm-for-ethereum-8b2a135201d) +- [더 이상 사용되지 않는 PoA, Aura 사양](https://openethereum.github.io/Chain-specification) +- [IBFT 2.0, 또 다른 PoA 구현](https://besu.hyperledger.org/private-networks/concepts/poa) + +### 시각 자료를 찾고 있나요? 시각적 학습자 + +권위 증명에 대한 시각적 설명을 시청하세요: + + + +## 관련 주제 {#related-topics} + +- [작업 증명](/developers/docs/consensus-mechanisms/pow/) +- [지분 증명](/developers/docs/consensus-mechanisms/pos/) + diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/attack-and-defense/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/attack-and-defense/index.md new file mode 100644 index 00000000000..498d7d35bbf --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/attack-and-defense/index.md @@ -0,0 +1,166 @@ +--- +title: "이더리움 지분 증명 공격과 방어" +description: "지분 증명 이더리움에 대해 알려진 공격 벡터와 방어 방법에 대해 알아보세요." +lang: ko +--- + +도둑과 사보타주들은 이더리움의 클라이언트 소프트웨어를 공격할 기회를 끊임없이 찾고 있습니다. 이 페이지에서는 이더리움의 합의 레이어에 대해 알려진 공격 벡터와 해당 공격을 방어하는 방법을 간략하게 설명합니다. 이 페이지의 정보는 [더 긴 버전](https://mirror.xyz/jmcook.eth/YqHargbVWVNRQqQpVpzrqEQ8IqwNUJDIpwRP7SS5FXs)에서 발췌한 것입니다. + +## 필수 구성 요소 {#prerequisites} + +[지분 증명](/developers/docs/consensus-mechanisms/pos/)에 대한 몇 가지 기본 지식이 필요합니다. 또한 이더리움의 [인센티브 레이어](/developers/docs/consensus-mechanisms/pos/rewards-and-penalties)와 포크 선택 알고리즘인 [LMD-GHOST](/developers/docs/consensus-mechanisms/pos/gasper)에 대한 기본적 이해가 있으면 도움이 될 것입니다. + +## 공격자는 무엇을 원할까요? {#what-do-attackers-want} + +성공적인 공격자가 새로운 이더를 생성하거나 임의의 계정에서 이더를 빼낼 수 있다는 것은 일반적인 오해입니다. 네트워크의 모든 실행 클라이언트가 모든 트랜잭션을 실행하기 때문에 이 두 가지 모두 불가능합니다. 유효성의 기본 조건(예: 발신자의 개인 키로 트랜잭션이 서명되었는지, 발신자에게 충분한 잔액이 있는지 등)을 충족해야 하며, 그렇지 않으면 간단히 되돌려집니다. 공격자가 현실적으로 목표로 삼을 수 있는 결과에는 재구성(reorgs), 이중 최종 승인 또는 최종 승인 지연의 세 가지 종류가 있습니다. + +“재구성(reorg)”은 정규 체인에 일부 블록이 추가되거나 제거되면서 블록이 새로운 순서로 재조정되는 것입니다. 악의적인 재구성은 특정 블록이 포함되거나 제외되도록 보장하여 이중 지불 또는 선행 매매 및 후행 매매 트랜잭션(MEV)을 통한 가치 추출을 허용할 수 있습니다. 재구성은 특정 트랜잭션이 정규 체인에 포함되는 것을 막는 데 사용될 수도 있는데, 이는 일종의 검열입니다. 재구성의 가장 극단적인 형태는 이전에 최종 승인된 블록을 제거하거나 대체하는 "최종 승인 되돌리기(finality reversion)"입니다. 이는 공격자에 의해 전체 스테이킹된 이더의 ⅓ 이상이 파괴되어야만 가능하며, 이 보증은 "경제적 최종 승인(economic finality)"으로 알려져 있습니다. 이에 대해서는 나중에 자세히 설명하겠습니다. + +이중 최종 승인은 두 개의 포크가 동시에 최종 승인될 수 있는, 가능성은 낮지만 심각한 상태로, 체인에 영구적인 분열을 일으킵니다. 이것은 전체 스테이킹된 이더의 34%를 감수할 의향이 있는 공격자에게 이론적으로 가능합니다. 커뮤니티는 오프체인에서 협력하여 어떤 체인을 따를지에 대한 합의에 도달해야 하며, 이를 위해서는 소셜 레이어의 힘이 필요합니다. + +**최종 승인 지연** 공격은 네트워크가 체인의 섹션을 최종 승인하는 데 필요한 조건에 도달하는 것을 방해합니다. 최종 승인이 없으면 이더리움 위에 구축된 금융 애플리케이션을 신뢰하기 어렵습니다. 최종 승인 지연 공격의 목표는 공격자가 전략적 공매도 포지션을 가지고 있지 않는 한 직접적인 이익을 얻기보다는 단순히 이더리움을 방해하는 것일 가능성이 높습니다. + +소셜 레이어에 대한 공격은 이더리움에 대한 대중의 신뢰를 약화시키고, 이더의 가치를 떨어뜨리고, 채택을 줄이거나, 이더리움 커뮤니티를 약화시켜 대역 외(out-of-band) 조정을 더 어렵게 만드는 것을 목표로 할 수 있습니다. + +적대자가 이더리움을 공격할 수 있는 이유를 확인했으므로 다음 섹션에서는 그들이 _어떻게_ 공격할 수 있는지 살펴봅니다. + +## 공격 방법 {#methods-of-attack} + +### 레이어 0 공격 {#layer-0} + +우선, 이더리움에 적극적으로 참여하지 않는 개인(클라이언트 소프트웨어를 실행하여)은 소셜 레이어(레이어 0)를 표적으로 삼아 공격할 수 있습니다. 레이어 0은 이더리움이 구축된 기반이며, 따라서 스택의 나머지 부분에 파급 효과를 미치는 공격에 대한 잠재적인 공격 표면을 나타냅니다. 몇 가지 예는 다음과 같습니다. + +- 잘못된 정보 캠페인은 커뮤니티가 이더리움의 로드맵, 개발자 팀, 앱 등에 대해 가지고 있는 신뢰를 약화시킬 수 있습니다. 이는 네트워크 보안에 기꺼이 참여하려는 개인의 수를 감소시켜 탈중앙화와 암호 경제적 보안을 모두 저하시킬 수 있습니다. + +- 개발자 커뮤니티를 대상으로 한 표적 공격 및/또는 위협. 이는 개발자의 자발적인 이탈로 이어져 이더리움의 발전을 늦출 수 있습니다. + +- 지나치게 열성적인 규제 또한 레이어 0에 대한 공격으로 간주될 수 있는데, 이는 참여와 채택을 급격히 저해할 수 있기 때문입니다. + +- 자전거 보관소 논쟁(bike-shedding)으로 진행을 늦추고, 핵심 결정을 지연시키며, 스팸을 생성하는 등을 목표로 하는 지식이 있지만 악의적인 행위자가 개발자 커뮤니티에 침투하는 것. + +- 의사 결정에 영향을 미치기 위해 이더리움 생태계의 핵심 인물에게 제공되는 뇌물. + +이러한 공격이 특히 위험한 이유는 많은 경우에 자본이나 기술적 노하우가 거의 필요하지 않기 때문입니다. 레이어 0 공격은 암호 경제적 공격에 대한 승수(multiplier)가 될 수 있습니다. 예를 들어, 악의적인 대다수 지분 보유자에 의해 검열이나 최종 승인 되돌리기가 달성되면, 소셜 레이어를 약화시켜 커뮤니티가 대역 외로 대응을 조정하기가 더 어려워질 수 있습니다. + +레이어 0 공격에 대한 방어는 아마도 간단하지 않겠지만, 몇 가지 기본 원칙을 수립할 수 있습니다. 한 가지는 블로그, 디스코드 서버, 주석이 달린 사양, 책, 팟캐스트, 유튜브를 통해 커뮤니티의 정직한 구성원들이 생성하고 전파하는 이더리움에 대한 공개 정보에 대해 전반적으로 높은 신호 대 잡음비를 유지하는 것입니다. 저희 ethereum.org에서는 정확한 정보를 유지하고 가능한 한 많은 언어로 번역하기 위해 열심히 노력하고 있습니다. 공간을 고품질 정보와 밈(meme)으로 채우는 것은 잘못된 정보에 대한 효과적인 방어입니다. + +소셜 레이어 공격에 대한 또 다른 중요한 방어책은 명확한 사명 선언문과 거버넌스 프로토콜입니다. 이더리움은 스마트 계약 레이어 1 중에서 탈중앙화 및 보안의 챔피언으로 자리매김했으며 확장성과 지속 가능성도 매우 중요하게 생각합니다. 이더리움 커뮤니티에서 어떤 의견 차이가 발생하더라도 이러한 핵심 원칙은 최소한으로만 훼손됩니다. 이러한 핵심 원칙에 비추어 내러티브를 평가하고 EIP(이더리움 개선 제안) 프로세스에서 연속적인 검토 라운드를 통해 이를 검토하면 커뮤니티가 선한 행위자와 악의적인 행위자를 구별하고 악의적인 행위자가 이더리움의 미래 방향에 영향을 미칠 수 있는 범위를 제한하는 데 도움이 될 수 있습니다. + +마지막으로, 이더리움 커뮤니티가 모든 참여자에게 개방적이고 환영하는 자세를 유지하는 것이 중요합니다. 문지기(gatekeeper)와 배타성이 있는 커뮤니티는 "우리와 그들"이라는 내러티브를 구축하기 쉽기 때문에 사회적 공격에 특히 취약합니다. 부족주의와 유해한 극단주의는 커뮤니티에 해를 끼치고 레이어 0의 보안을 약화시킵니다. 네트워크 보안에 기득권을 가진 이더리안은 온라인과 현실 세계(meatspace)에서의 행동을 이더리움 레이어 0의 보안에 직접적인 기여자로 보아야 합니다. + +### 프로토콜 공격 {#attacking-the-protocol} + +누구나 이더리움의 클라이언트 소프트웨어를 실행할 수 있습니다. 클라이언트에 검증자를 추가하려면 사용자는 예치 계약에 32 이더를 스테이킹해야 합니다. 검증자를 통해 사용자는 새로운 블록을 제안하고 증명함으로써 이더리움의 네트워크 보안에 적극적으로 참여할 수 있습니다. 검증자는 이제 블록체인의 미래 내용에 영향을 미칠 수 있는 목소리를 갖게 됩니다. 그들은 정직하게 그렇게 하여 보상을 통해 이더 보유량을 늘리거나, 자신의 스테이킹을 위험에 빠뜨리면서 자신의 이익을 위해 프로세스를 조작하려고 시도할 수 있습니다. 공격을 감행하는 한 가지 방법은 총 스테이킹의 더 큰 비율을 축적한 다음 이를 사용하여 정직한 검증자를 투표로 이기는 것입니다. 공격자가 통제하는 스테이킹의 비율이 클수록 투표권이 커지며, 특히 나중에 살펴볼 특정 경제적 이정표에서 더욱 그렇습니다. 그러나 대부분의 공격자는 이런 방식으로 공격할 만큼 충분한 이더를 축적할 수 없으므로, 대신 정직한 다수가 특정 방식으로 행동하도록 조종하기 위해 미묘한 기술을 사용해야 합니다. + +기본적으로 모든 소규모 스테이킹 공격은 두 가지 유형의 검증자 부정 행위에 대한 미묘한 변형입니다. 즉, 활동 부족(증명/제안 실패 또는 늦게 수행) 또는 과잉 활동(슬롯에서 너무 여러 번 제안/증명)입니다. 가장 기본적인 형태에서 이러한 행동은 포크 선택 알고리즘과 인센티브 레이어에서 쉽게 처리되지만, 공격자의 이익을 위해 시스템을 이용하는 영리한 방법이 있습니다. + +### 소량의 ETH를 사용한 공격 {#attacks-by-small-stakeholders} + +#### 재구성(reorgs) {#reorgs} + +몇몇 논문에서는 총 스테이킹된 이더의 일부만으로 재구성 또는 최종 승인 지연을 달성하는 이더리움에 대한 공격을 설명했습니다. 이러한 공격은 일반적으로 공격자가 다른 검증자로부터 일부 정보를 보류한 다음 미묘한 방식으로 및/또는 적절한 순간에 공개하는 것에 의존합니다. 일반적으로 정규 체인에서 일부 정직한 블록을 대체하는 것을 목표로 합니다. [Neuder 외 2020](https://arxiv.org/pdf/2102.02247.pdf)은 공격하는 검증자가 특정 슬롯 `n+1`에 대한 블록(`B`)을 생성하고 증명할 수 있지만 네트워크의 다른 노드에 전파하는 것을 자제하는 방법을 보여주었습니다. 대신, 다음 슬롯 `n+2`까지 증명된 블록을 보유합니다. 정직한 검증자는 슬롯 `n+2`에 대한 블록(`C`)을 제안합니다. 거의 동시에 공격자는 보류된 블록(`B`)과 그에 대한 보류된 인증을 공개하고, 슬롯 `n+2`에 대한 투표로 `B`가 체인의 헤드임을 증명하여 정직한 블록 `C`의 존재를 효과적으로 부정할 수 있습니다. 정직한 블록 `D`가 공개되면 포크 선택 알고리즘은 `B` 위에 구축된 `D`가 `C` 위에 구축된 `D`보다 더 무겁다고 봅니다. 따라서 공격자는 1블록 사전 재구성(ex ante reorg)을 사용하여 슬롯 `n+2`의 정직한 블록 `C`를 정규 체인에서 제거하는 데 성공했습니다. [이 노트](https://notes.ethereum.org/plgVdz-ORe-fGjK06BZ_3A#Fork-choice-by-block-slot-pair)에 설명된 바와 같이, [34%의 스테이킹을 가진 공격자](https://www.youtube.com/watch?v=6vzXwwk12ZE)는 이 공격에 성공할 가능성이 매우 높습니다. 하지만 이론적으로는 더 작은 스테이킹으로도 이 공격을 시도할 수 있습니다. [Neuder 외 2020](https://arxiv.org/pdf/2102.02247.pdf)은 30%의 스테이킹으로 이 공격이 작동한다고 설명했지만, 나중에 [총 스테이킹의 2%](https://arxiv.org/pdf/2009.04987.pdf)로도 가능하며, 다음 섹션에서 살펴볼 균형 조정 기술을 사용하여 [단일 검증자](https://arxiv.org/abs/2110.10086#)에 대해서도 가능하다는 것이 밝혀졌습니다. + +![사전 재구성(ex-ante re-org)](reorg-schematic.png) + +위에 설명된 1블록 재구성 공격의 개념도(https://notes.ethereum.org/plgVdz-ORe-fGjK06BZ_3A#Fork-choice-by-block-slot-pair에서 발췌) + +더 정교한 공격은 정직한 검증자 집합을 체인의 헤드에 대해 서로 다른 견해를 가진 개별 그룹으로 분할할 수 있습니다. 이를 균형 공격(balancing attack)이라고 합니다. 공격자는 블록을 제안할 기회를 기다리다가 기회가 오면 이중 제안을 합니다. 그들은 한 블록을 정직한 검증자 집합의 절반에 보내고 다른 블록을 나머지 절반에 보냅니다. 이중 제안은 포크 선택 알고리즘에 의해 감지되고 블록 제안자는 슬래싱되어 네트워크에서 퇴출되지만, 두 블록은 여전히 존재하며 각 포크에 대해 약 절반의 검증자 집합이 증명하게 됩니다. 한편, 나머지 악의적인 검증자들은 자신의 인증을 보류합니다. 그런 다음 포크 선택 알고리즘이 실행될 때 한쪽 또는 다른 쪽 포크를 선호하는 인증을 필요한 만큼의 검증자에게만 선택적으로 공개함으로써 누적된 인증 가중치를 한쪽 또는 다른 쪽 포크에 유리하도록 기울입니다. 이는 공격하는 검증자들이 두 포크에 걸쳐 검증자들을 균등하게 분할하여 무기한 계속될 수 있습니다. 어느 포크도 2/3의 절대다수를 확보할 수 없으므로 네트워크는 최종 승인되지 않습니다. + +바운싱 공격(Bouncing attack)도 비슷합니다. 공격하는 검증자들은 다시 투표를 보류합니다. 두 포크 간에 균등한 분할을 유지하기 위해 투표를 공개하는 대신, 그들은 적절한 순간에 투표를 사용하여 포크 A와 포크 B 사이를 번갈아 가며 체크포인트를 정당화합니다. 두 포크 간에 이러한 정당화의 번복은 어느 체인에서도 최종 승인될 수 있는 정당화된 소스 및 타겟 체크포인트 쌍이 존재하는 것을 막아 최종 승인을 중단시킵니다. + + + +바운싱 및 균형 공격 모두 공격자가 네트워크 전체의 메시지 타이밍을 매우 정밀하게 제어하는 데 의존하며, 이는 가능성이 낮습니다. 그럼에도 불구하고, 느린 메시지에 비해 신속한 메시지에 추가 가중치를 부여하는 형태로 프로토콜에 방어 기능이 내장되어 있습니다. 이는 [제안자 가중치 부스팅](https://github.com/ethereum/consensus-specs/pull/2730)으로 알려져 있습니다. 바운싱 공격을 방어하기 위해 포크 선택 알고리즘이 업데이트되어, 최신 정당화된 체크포인트는 [각 에포크의 슬롯 중 처음 1/3 동안](https://ethresear.ch/t/prevention-of-bouncing-attack-on-ffg/6114)에만 대체 체인의 체크포인트로 전환될 수 있습니다. 이 조건은 공격자가 나중에 배포하기 위해 투표를 저장하는 것을 방지합니다. 포크 선택 알고리즘은 대부분의 정직한 검증자가 투표했을 에포크의 처음 1/3 동안 선택한 체크포인트에 충실하게 유지됩니다. + +종합적으로, 이러한 조치들은 정직한 블록 제안자가 슬롯 시작 직후 매우 빠르게 블록을 내보내고, 그 다음 약 1/3 슬롯(4초) 동안 해당 새 블록이 포크 선택 알고리즘을 다른 체인으로 전환하게 할 수 있는 시나리오를 만듭니다. 해당 마감 시간 이후에 느린 검증자로부터 도착하는 인증은 더 일찍 도착한 인증에 비해 가중치가 낮아집니다. 이는 체인의 헤드를 결정하는 데 있어 신속한 제안자와 검증자에게 강력하게 유리하며, 성공적인 균형 또는 바운싱 공격의 가능성을 크게 줄입니다. + +제안자 부스팅만으로는 "저렴한 재구성(cheap reorgs)", 즉 소규모 스테이킹을 가진 공격자가 시도하는 재구성에만 방어한다는 점에 유의할 가치가 있습니다. 사실, 제안자 부스팅 자체는 더 큰 지분 보유자에 의해 이용될 수 있습니다. [이 게시물](https://ethresear.ch/t/change-fork-choice-rule-to-mitigate-balancing-and-reorging-attacks/11127)의 저자들은 7%의 스테이킹을 가진 공격자가 정직한 블록을 재구성하여 정직한 검증자를 속여 자신의 포크 위에 구축하도록 전략적으로 투표를 배포하는 방법을 설명합니다. 이 공격은 매우 가능성이 낮은 이상적인 지연 시간 조건을 가정하여 고안되었습니다. 공격자의 성공 확률은 여전히 매우 낮으며, 더 큰 스테이킹은 더 많은 자본이 위험에 처해 있고 더 강력한 경제적 저해 요인이 있음을 의미합니다. + +제안자 부스팅에도 불구하고 실행 가능하다고 제안된 [LMD 규칙을 구체적으로 겨냥한 균형 공격](https://ethresear.ch/t/balancing-attack-lmd-edition/11853)도 제안되었습니다. 공격자는 블록 제안을 이중으로 하고 각 블록을 네트워크의 약 절반에 전파하여 두 개의 경쟁 체인을 설정하고 포크 간에 대략적인 균형을 맞춥니다. 그런 다음, 공모하는 검증자들은 투표를 이중으로 하여 네트워크의 절반이 포크 `A`에 대한 투표를 먼저 받고 나머지 절반이 포크 `B`에 대한 투표를 먼저 받도록 시간을 맞춥니다. LMD 규칙은 두 번째 인증을 버리고 각 검증자에 대해 첫 번째 인증만 유지하므로, 네트워크의 절반은 `A`에 대한 투표를 보고 `B`에 대한 투표는 보지 못하며, 나머지 절반은 `B`에 대한 투표를 보고 `A`에 대한 투표는 보지 못합니다. 저자들은 LMD 규칙이 적에게 균형 공격을 감행할 "놀라운 힘"을 준다고 설명합니다. + +이 LMD 공격 벡터는 [포크 선택 알고리즘을 업데이트](https://github.com/ethereum/consensus-specs/pull/2845)하여 이중 투표하는 검증자를 포크 선택 고려에서 완전히 제외함으로써 해결되었습니다. 이중 투표하는 검증자는 또한 포크 선택 알고리즘에 의해 미래의 영향력이 할인됩니다. 이는 위에서 설명한 균형 공격을 방지하는 동시에 애벌랜치 공격에 대한 복원력을 유지합니다. + +[**애벌랜치 공격**](https://ethresear.ch/t/avalanche-attack-on-proof-of-stake-ghost/11854/3)이라는 또 다른 종류의 공격은 [2022년 3월 논문](https://arxiv.org/pdf/2203.01315.pdf)에서 설명되었습니다. 애벌랜치 공격을 감행하려면 공격자는 여러 연속적인 블록 제안자를 제어해야 합니다. 각 블록 제안 슬롯에서 공격자는 자신의 블록을 보류하고 정직한 체인이 보류된 블록과 동일한 하위 트리 가중치에 도달할 때까지 수집합니다. 그런 다음, 보류된 블록은 최대한 이중 제안되도록 공개됩니다. 저자들은 균형 및 바운싱 공격에 대한 주요 방어책인 제안자 부스팅이 일부 애벌랜치 공격 변종에 대해서는 보호하지 못한다고 제안합니다. 그러나 저자들은 또한 이더리움의 포크 선택 알고리즘의 매우 이상화된 버전(LMD 없이 GHOST를 사용)에서만 공격을 시연했습니다. + +애벌랜치 공격은 LMD-GHOST 포크 선택 알고리즘의 LMD 부분에 의해 완화됩니다. LMD는 “최신 메시지 기반(latest-message-driven)”을 의미하며, 각 검증자가 다른 검증자로부터 받은 최신 메시지를 포함하는 테이블을 참조합니다. 해당 필드는 새 메시지가 특정 검증자에 대해 테이블에 이미 있는 슬롯보다 더 늦은 슬롯에서 온 경우에만 업데이트됩니다. 실제로 이는 각 슬롯에서 수신된 첫 번째 메시지가 수락된 메시지이며 추가 메시지는 무시해야 할 이중 제안임을 의미합니다. 다시 말해, 합의 클라이언트는 이중 제안을 계산하지 않습니다. 각 검증자로부터 처음 도착한 메시지를 사용하고 이중 제안은 단순히 폐기되어 애벌랜치 공격을 방지합니다. + +제안자 부스트가 제공하는 보안에 추가될 수 있는 포크 선택 규칙에 대한 몇 가지 다른 잠재적인 미래 업그레이드가 있습니다. 하나는 [뷰 병합](https://ethresear.ch/t/view-merge-as-a-replacement-for-proposer-boost/13739)으로, 증명자는 슬롯 시작 `n`초 전에 포크 선택에 대한 뷰를 동결하고 제안자는 네트워크 전체에서 체인 뷰를 동기화하는 데 도움을 줍니다. 또 다른 잠재적인 업그레이드는 [단일 슬롯 최종 승인](https://notes.ethereum.org/@vbuterin/single_slot_finality)으로, 단 하나의 슬롯 후에 체인을 최종 승인함으로써 메시지 타이밍에 기반한 공격으로부터 보호합니다. + +#### 최종 승인 지연 {#finality-delay} + +저비용 단일 블록 재구성 공격을 처음 설명한 [같은 논문](https://econcs.pku.edu.cn/wine2020/wine2020/Workshop/GTiB20_paper_8.pdf)은 또한 공격자가 에포크 경계 블록의 블록 제안자가 되는 것에 의존하는 최종 승인 지연(일명 “활성 실패(liveness failure)”) 공격을 설명했습니다. 이러한 에포크 경계 블록은 Casper FFG가 체인의 일부를 최종 승인하는 데 사용하는 체크포인트가 되기 때문에 중요합니다. 공격자는 충분한 수의 정직한 검증자가 현재 최종 승인 대상으로 이전 에포크 경계 블록을 선호하는 FFG 투표를 사용할 때까지 단순히 블록을 보류합니다. 그런 다음 보류된 블록을 공개합니다. 그들은 자신의 블록을 증명하고 나머지 정직한 검증자들도 그렇게 하여 다른 타겟 체크포인트를 가진 포크를 생성합니다. 타이밍을 제대로 맞추면 어느 포크에도 2/3의 절대다수가 증명하지 않기 때문에 최종 승인을 막을 수 있습니다. 스테이킹이 작을수록 공격자가 직접 제어하는 인증 수가 적고, 주어진 에포크 경계 블록을 제안하는 검증자를 공격자가 제어할 확률이 낮기 때문에 타이밍이 더 정확해야 합니다. + +#### 장기 공격 {#long-range-attacks} + +또한 제네시스 블록에 참여한 검증자가 정직한 블록체인과 함께 별도의 블록체인 포크를 유지하다가 훨씬 나중에 적절한 시기에 정직한 검증자 집합을 해당 포크로 전환하도록 설득하는 것과 관련된 지분 증명 블록체인에 특정한 공격 유형이 있습니다. 이러한 유형의 공격은 모든 검증자가 정기적인 간격("체크포인트")으로 정직한 체인의 상태에 동의하도록 보장하는 최종 승인 장치 때문에 이더리움에서는 불가능합니다. 이 간단한 메커니즘은 이더리움 클라이언트가 최종 승인된 블록을 재구성하지 않기 때문에 장거리 공격자를 무력화합니다. 네트워크에 참여하는 새로운 노드는 신뢰할 수 있는 최근 상태 해시("[약한 주관성](https://blog.ethereum.org/2014/11/25/proof-stake-learned-love-weak-subjectivity/) 체크포인트")를 찾아 이를 의사 제네시스 블록으로 사용하여 그 위에 구축함으로써 그렇게 합니다. 이는 네트워크에 진입하는 새로운 노드가 스스로 정보를 확인하기 전에 '신뢰 게이트웨이'를 생성합니다. + +#### 서비스 거부 {#denial-of-service} + +이더리움의 지분 증명 메커니즘은 각 슬롯에서 전체 검증자 집합에서 단일 검증자를 블록 제안자로 선택합니다. 이는 공개적으로 알려진 함수를 사용하여 계산할 수 있으며, 적이 블록 제안 약간 전에 다음 블록 제안자를 식별하는 것이 가능합니다. 그런 다음 공격자는 블록 제안자에게 스팸을 보내 동료와 정보를 교환하는 것을 방지할 수 있습니다. 네트워크의 나머지 부분에는 블록 제안자가 오프라인인 것처럼 보이고 슬롯은 단순히 비어 있게 됩니다. 이는 특정 검증자에 대한 검열의 한 형태로, 그들이 블록체인에 정보를 추가하는 것을 막을 수 있습니다. 단일 비밀 리더 선출(SSLE) 또는 비단일 비밀 리더 선출을 구현하면 블록 제안자만이 자신이 선택되었음을 알고 선택이 사전에 알려지지 않기 때문에 서비스 거부(DoS) 위험을 완화할 수 있습니다. 이는 아직 구현되지 않았지만 활발한 [연구 개발](https://ethresear.ch/t/secret-non-single-leader-election/11789) 분야입니다. + +이 모든 것은 적은 스테이킹으로 이더리움을 성공적으로 공격하기가 매우 어렵다는 사실을 가리킵니다. 여기에 설명된 실행 가능한 공격은 이상적인 포크 선택 알고리즘, 비현실적인 네트워크 조건을 요구하거나, 클라이언트 소프트웨어에 대한 비교적 사소한 패치로 이미 공격 벡터가 닫혔습니다. 물론 이것이 제로데이 공격이 실제로 존재할 가능성을 배제하는 것은 아니지만, 소수 지분 공격자가 효과적이 되기 위해 요구되는 기술적 적성, 합의 레이어 지식 및 운의 매우 높은 기준을 보여줍니다. 공격자의 관점에서 최선의 방법은 가능한 한 많은 이더를 축적하고 총 스테이킹의 더 큰 비율로 무장하여 돌아오는 것일 수 있습니다. + +### 총 스테이킹의 >= 33%를 사용하는 공격자 {#attackers-with-33-stake} + +이 글에서 앞서 언급한 모든 공격은 공격자가 투표할 스테이킹된 이더가 더 많고 각 슬롯에서 블록을 제안하도록 선택될 수 있는 검증자가 더 많을 때 성공할 가능성이 더 높아집니다. 따라서 악의적인 검증자는 가능한 한 많은 스테이킹된 이더를 제어하는 것을 목표로 할 수 있습니다. + +스테이킹된 이더의 33%는 공격자의 벤치마크입니다. 왜냐하면 이 양보다 많으면 다른 검증자의 행동을 미세하게 제어할 필요 없이 체인이 최종 승인되는 것을 막을 수 있기 때문입니다. 그들은 단순히 함께 사라질 수 있습니다. 스테이킹된 이더의 1/3 이상이 악의적으로 증명하거나 증명에 실패하면 2/3의 절대다수가 존재할 수 없으며 체인은 최종 승인될 수 없습니다. 이에 대한 방어는 비활동 유출입니다. 비활동 유출은 증명에 실패하거나 다수와 반대로 증명하는 검증자를 식별합니다. 이러한 비증명 검증자가 소유한 스테이킹된 이더는 점차적으로 소멸되어 결국 전체의 1/3 미만을 차지하게 되어 체인이 다시 최종 승인될 수 있도록 합니다. + +비활동 유출의 목적은 체인이 다시 최종 승인되도록 하는 것입니다. 그러나 공격자도 스테이킹된 이더의 일부를 잃게 됩니다. 검증자가 슬래싱되지 않더라도 총 스테이킹된 이더의 33%를 차지하는 검증자들의 지속적인 비활동은 매우 비용이 많이 듭니다. + +이더리움 네트워크가 비동기적(즉, 메시지가 전송되고 수신되는 사이에 지연이 있음)이라고 가정하면, 총 스테이킹의 34%를 제어하는 공격자는 이중 최종 승인을 유발할 수 있습니다. 이는 공격자가 블록 생산자로 선택되었을 때 이중 제안을 한 다음 모든 검증자로 이중 투표를 할 수 있기 때문입니다. 이는 블록체인의 포크가 존재하는 상황을 만들며, 각 포크는 스테이킹된 이더의 34%가 투표합니다. 각 포크는 나머지 검증자의 50%만 찬성 투표하면 두 포크 모두 절대다수의 지지를 받게 되며, 이 경우 두 체인 모두 최종 승인될 수 있습니다(공격자 검증자의 34% + 나머지 66%의 절반 = 각 포크당 67%). 경쟁하는 블록은 각각 정직한 검증자의 약 50%에 의해 수신되어야 하므로 이 공격은 공격자가 네트워크를 통해 전파되는 메시지의 타이밍을 어느 정도 제어하여 정직한 검증자의 절반을 각 체인으로 유도할 수 있을 때만 실행 가능합니다. 공격자는 이 이중 최종 승인을 달성하기 위해 전체 스테이킹(오늘날의 검증자 집합으로 약 천만 이더의 34%)을 필연적으로 파괴할 것입니다. 왜냐하면 검증자의 34%가 동시에 이중 투표를 하기 때문이며, 이는 최대 상관 관계 페널티가 부과되는 슬래싱 가능한 위반입니다. 이 공격에 대한 방어는 총 스테이킹된 이더의 34%를 파괴하는 데 드는 막대한 비용입니다. 이 공격에서 복구하려면 이더리움 커뮤니티가 "대역 외"로 조정하여 한 포크 또는 다른 포크를 따르고 다른 포크를 무시하는 데 동의해야 합니다. + +### 총 스테이킹의 ~50%를 사용하는 공격자 {#attackers-with-50-stake} + +스테이킹된 이더의 50%에서 악의적인 검증자 그룹은 이론적으로 체인을 두 개의 동일한 크기의 포크로 분할한 다음 전체 50% 스테이킹을 사용하여 정직한 검증자 집합과 반대로 투표하여 두 포크를 유지하고 최종 승인을 막을 수 있습니다. 두 포크의 비활동 유출은 결국 두 체인 모두 최종 승인으로 이어질 것입니다. 이 시점에서 유일한 선택은 사회적 복구에 의존하는 것입니다. + +정직한 검증자 수, 네트워크 지연 시간 등의 변동을 고려할 때 적대적인 검증자 그룹이 총 스테이킹의 정확히 50%를 지속적으로 제어할 가능성은 매우 낮습니다. 이러한 공격을 감행하는 데 드는 막대한 비용과 성공 가능성이 낮은 점은 이성적인 공격자에게 강력한 저해 요인으로 보이며, 특히 50%를 초과하여 얻는 데 약간의 추가 투자를 하면 훨씬 더 많은 힘을 얻을 수 있습니다. + +총 스테이킹의 50% 이상에서 공격자는 포크 선택 알고리즘을 지배할 수 있습니다. 이 경우 공격자는 다수 투표로 증명할 수 있으므로 정직한 클라이언트를 속일 필요 없이 짧은 재구성을 할 수 있는 충분한 제어권을 갖게 됩니다. 정직한 검증자들의 포크 선택 알고리즘도 공격자가 선호하는 체인을 가장 무겁게 볼 것이므로 체인은 최종 승인될 수 있습니다. 이를 통해 공격자는 특정 트랜잭션을 검열하고, 단거리 재구성을 수행하며, 자신에게 유리하도록 블록을 재정렬하여 최대 MEV를 추출할 수 있습니다. 이에 대한 방어는 다수 스테이킹의 막대한 비용(현재 약 190억 달러)이며, 소셜 레이어가 개입하여 정직한 소수 포크를 채택하고 공격자의 스테이킹 가치를 극적으로 떨어뜨릴 가능성이 있기 때문에 공격자에 의해 위험에 처하게 됩니다. + +### 총 스테이킹의 >=66%를 사용하는 공격자 {#attackers-with-66-stake} + +총 스테이킹된 이더의 66% 이상을 가진 공격자는 정직한 검증자를 강요할 필요 없이 선호하는 체인을 최종 승인할 수 있습니다. 공격자는 단순히 선호하는 포크에 투표한 다음 최종 승인할 수 있습니다. 이는 그들이 부정직한 절대다수로 투표할 수 있기 때문입니다. 절대다수 지분 보유자로서 공격자는 항상 최종 승인된 블록의 내용을 제어하며, 지출, 되감기, 재지출, 특정 트랜잭션 검열, 의지에 따라 체인 재구성 등의 권한을 갖게 됩니다. 51% 대신 66%를 제어하기 위해 추가 이더를 구매함으로써 공격자는 사실상 사후 재구성 및 최종 승인 되돌리기(즉, 미래를 제어할 뿐만 아니라 과거를 변경하는 능력)를 구매하는 것입니다. 여기서 유일한 실제 방어책은 총 스테이킹된 이더의 66%에 달하는 막대한 비용과 대체 포크의 채택을 조정하기 위해 소셜 레이어로 돌아가는 옵션입니다. 다음 섹션에서 이에 대해 더 자세히 살펴볼 수 있습니다. + +## 사람: 최후의 방어선 {#people-the-last-line-of-defense} + +부정직한 검증자들이 선호하는 버전의 체인을 최종 승인하는 데 성공하면 이더리움 커뮤니티는 어려운 상황에 처하게 됩니다. 정규 체인에는 역사에 부정직한 부분이 포함되어 있는 반면, 정직한 검증자들은 대체(정직한) 체인에 증명한 것에 대해 처벌을 받을 수 있습니다. 최종 승인되었지만 잘못된 체인은 다수 클라이언트의 버그로 인해 발생할 수도 있습니다. 결국 궁극적인 대안은 소셜 레이어, 즉 레이어 0에 의존하여 상황을 해결하는 것입니다. + +이더리움의 지분 증명 합의의 강점 중 하나는 공격에 직면했을 때 커뮤니티가 사용할 수 있는 [다양한 방어 전략](https://youtu.be/1m12zgJ42dI?t=1712)이 있다는 것입니다. 최소한의 대응은 추가적인 페널티 없이 공격자의 검증자를 네트워크에서 강제로 퇴출시키는 것일 수 있습니다. 네트워크에 다시 참여하려면 공격자는 검증자 집합이 점진적으로 증가하도록 보장하는 활성화 대기열에 참여해야 합니다. 예를 들어, 스테이킹된 이더의 양을 두 배로 늘리기에 충분한 검증자를 추가하는 데는 약 200일이 걸리며, 이는 공격자가 또 다른 51% 공격을 시도하기 전에 정직한 검증자에게 200일을 벌어줍니다. 그러나 커뮤니티는 과거 보상을 취소하거나 스테이킹된 자본의 일부(최대 100%)를 소각하는 등 공격자를 더 가혹하게 처벌하기로 결정할 수도 있습니다. + +공격자에게 부과되는 페널티가 무엇이든, 커뮤니티는 또한 이더리움 클라이언트에 코딩된 포크 선택 알고리즘이 선호하는 체인임에도 불구하고 부정직한 체인이 사실상 유효하지 않으며 커뮤니티가 대신 정직한 체인 위에 구축해야 하는지 여부를 함께 결정해야 합니다. 정직한 검증자들은 예를 들어 공격이 시작되기 전에 정규 체인에서 포크되었거나 공격자의 검증자가 강제로 제거된, 커뮤니티가 수용한 이더리움 블록체인의 포크 위에 집합적으로 구축하기로 동의할 수 있습니다. 정직한 검증자들은 공격자의 체인에 (당연히) 증명하지 못한 것에 대해 적용되는 페널티를 피할 수 있기 때문에 이 체인 위에 구축하도록 인센티브를 받을 것입니다. 이더리움 위에 구축된 거래소, 온램프 및 애플리케이션은 아마도 정직한 체인에 있기를 선호할 것이며 정직한 검증자를 따라 정직한 블록체인으로 이동할 것입니다. + +그러나 이것은 상당한 거버넌스 과제가 될 것입니다. 일부 사용자와 검증자는 의심할 여지 없이 정직한 체인으로 다시 전환한 결과 손실을 입을 것이며, 공격 후 검증된 블록의 트랜잭션은 잠재적으로 롤백되어 애플리케이션 레이어를 방해할 수 있으며, 이는 단순히 "코드가 법이다"라고 믿는 경향이 있는 일부 사용자의 윤리를 훼손합니다. 거래소와 애플리케이션은 이제 롤백될 수 있는 온체인 트랜잭션에 오프체인 작업을 연결했을 가능성이 높으며, 이는 특히 부당 이득이 혼합되거나 DeFi 또는 다른 파생 상품에 예치되어 정직한 사용자에게 부차적인 영향을 미치는 경우 공정하게 풀기 어려운 취소 및 수정의 연쇄 반응을 시작할 것입니다. 의심할 여지 없이 일부 사용자, 아마도 기관 사용자조차도 약삭빠르거나 우연에 의해 부정직한 체인으로부터 이미 이익을 얻었을 것이며, 자신의 이익을 보호하기 위해 포크에 반대할 수 있습니다. 합리적이고 조정된 완화 조치가 신속하게 실행될 수 있도록 51% 초과 공격에 대한 커뮤니티 대응을 연습하라는 요구가 있었습니다. Vitalik이 ethresear.ch에서 [여기](https://ethresear.ch/t/timeliness-detectors-and-51-attack-recovery-in-blockchains/6925)와 [여기](https://ethresear.ch/t/responding-to-51-attacks-in-casper-ffg/6363), 그리고 트위터에서 [여기](https://twitter.com/skylar_eth/status/1551798684727508992?s=20&t=oHZ1xv8QZdOgAXhxZKtHEw)에 유용한 논의가 있습니다. 조정된 사회적 대응의 목표는 공격자를 처벌하고 다른 사용자에 대한 영향을 최소화하는 데 매우 표적화되고 구체적이어야 합니다. + +거버넌스는 이미 복잡한 주제입니다. 부정직한 최종 승인 체인에 대한 레이어-0 비상 대응을 관리하는 것은 의심할 여지 없이 이더리움 커뮤니티에 어려운 일이겠지만, 이더리움 역사상 [두 번](/ethereum-forks/#tangerine-whistle)이나 [일어난 일](/ethereum-forks/#dao-fork-summary)입니다. + +그럼에도 불구하고, 최종적인 대안이 현실 세계에 있다는 것은 상당히 만족스러운 일입니다. 궁극적으로, 우리 위에 이 경이로운 기술 스택이 있더라도, 최악의 상황이 발생하면 실제 사람들이 협력하여 해결해야 할 것입니다. + +## 요약 {#summary} + +이 페이지에서는 공격자가 이더리움의 지분 증명 합의 프로토콜을 악용하려는 몇 가지 방법을 탐구했습니다. 총 스테이킹된 이더의 비율이 증가하는 공격자에 대한 재구성 및 최종 승인 지연이 탐구되었습니다. 전반적으로, 더 부유한 공격자는 자신의 스테이킹이 미래 블록의 내용에 영향을 미치는 데 사용할 수 있는 투표권으로 변환되기 때문에 성공할 가능성이 더 높습니다. 특정 임계값의 스테이킹된 이더에서 공격자의 힘은 다음과 같이 레벨업됩니다. + +33%: 최종 승인 지연 + +34%: 최종 승인 지연, 이중 최종 승인 + +51%: 최종 승인 지연, 이중 최종 승인, 검열, 블록체인 미래에 대한 통제권 + +66%: 최종 승인 지연, 이중 최종 승인, 검열, 블록체인 미래와 과거에 대한 통제권 + +또한 적은 양의 스테이킹된 이더를 필요로 하지만 매우 정교한 공격자가 메시지 타이밍을 정밀하게 제어하여 정직한 검증자 집합을 자신에게 유리하게 흔드는 데 의존하는 더 정교한 공격도 있습니다. + +전반적으로, 이러한 잠재적인 공격 벡터에도 불구하고 성공적인 공격의 위험은 낮으며, 확실히 작업 증명에 상응하는 것보다 낮습니다. 이는 투표력으로 정직한 검증자를 압도하려는 공격자가 위험에 빠뜨리는 스테이킹된 이더의 막대한 비용 때문입니다. 내장된 “당근과 채찍” 인센티브 레이어는 특히 낮은 스테이킹 공격자에 대해 대부분의 부정 행위로부터 보호합니다. 실제 네트워크 조건에서는 특정 검증자 하위 집합에 대한 메시지 전달의 정밀한 제어를 달성하기가 매우 어렵고, 클라이언트 팀이 알려진 바운싱, 균형 및 애벌랜치 공격 벡터를 간단한 패치로 신속하게 닫았기 때문에 더 미묘한 바운싱 및 균형 공격도 성공할 가능성이 낮습니다. + +34%, 51% 또는 66% 공격은 해결하기 위해 대역 외 사회적 조정이 필요할 가능성이 높습니다. 이것이 커뮤니티에 고통스러울 수 있지만, 커뮤니티가 대역 외로 대응할 수 있는 능력은 공격자에게 강력한 저해 요인입니다. 이더리움 소셜 레이어는 궁극적인 방어책입니다. 기술적으로 성공한 공격이라도 커뮤니티가 정직한 포크를 채택하기로 동의하면 무력화될 수 있습니다. 공격자와 이더리움 커뮤니티 사이에는 경쟁이 있을 것입니다. 66% 공격에 지출된 수십억 달러는 충분히 신속하게 전달된다면 성공적인 사회적 조정 공격에 의해 아마도 소멸될 것이며, 공격자는 이더리움 커뮤니티가 무시하는 알려진 부정직한 체인에 비유동적인 스테이킹된 이더의 무거운 가방을 남기게 될 것입니다. 이것이 공격자에게 수익성이 있을 가능성은 효과적인 억제책이 될 만큼 충분히 낮습니다. 이것이 바로 긴밀하게 정렬된 가치를 가진 응집력 있는 소셜 레이어를 유지하는 데 투자하는 것이 중요한 이유입니다. + +## 추가 정보 {#further-reading} + +- [이 페이지의 더 자세한 버전](https://mirror.xyz/jmcook.eth/YqHargbVWVNRQqQpVpzrqEQ8IqwNUJDIpwRP7SS5FXs) +- [Vitalik의 결제 최종 승인에 대하여](https://blog.ethereum.org/2016/05/09/on-settlement-finality/) +- [LMD GHOST 논문](https://arxiv.org/abs/2003.03052) +- [Casper-FFG 논문](https://arxiv.org/abs/1710.09437) +- [Gasper 논문](https://arxiv.org/pdf/2003.03052.pdf) +- [제안자 가중치 부스팅 합의 사양](https://github.com/ethereum/consensus-specs/pull/2730) +- [ethresear.ch의 바운싱 공격](https://ethresear.ch/t/prevention-of-bouncing-attack-on-ffg/6114) +- [SSLE 연구](https://ethresear.ch/t/secret-non-single-leader-election/11789) diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/attestations/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/attestations/index.md new file mode 100644 index 00000000000..76335c48502 --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/attestations/index.md @@ -0,0 +1,92 @@ +--- +title: "인증" +description: "지분 증명 이더리움의 인증에 대한 설명입니다." +lang: ko +--- + +검증자는 매 에폭마다 인증을 생성, 서명 및 브로드캐스트해야 합니다. 이 페이지에서는 이러한 인증의 형태와 합의 클라이언트 간에 처리되고 통신되는 방식에 대해 간략히 설명합니다. + +## 인증이란 무엇인가요? {#what-is-an-attestation} + +매 [에폭](/glossary/#epoch)(6.4분)마다 검증자는 네트워크에 인증을 제안합니다. 인증은 에폭의 특정 슬롯에 대한 것입니다. 인증의 목적은 검증자의 체인에 대한 관점, 특히 가장 최근에 정당화된 블록과 현재 에폭의 첫 번째 블록(`소스` 및 `타깃` 체크포인트라고 함)에 찬성하여 투표하는 것입니다. 이 정보는 참여하는 모든 검증자에 대해 결합되어 네트워크가 블록체인의 상태에 대한 합의에 도달할 수 있도록 합니다. + +인증에는 다음 구성 요소가 포함됩니다. + +- `aggregation_bits`: 검증자들의 비트 리스트로, 위치는 위원회 내 검증자 인덱스에 매핑됩니다. 값(0/1)은 검증자가 `data`에 서명했는지 여부(즉, 활성 상태이고 블록 제안자에 동의하는지 여부)를 나타냅니다. +- `data`: 아래에 정의된 인증 관련 세부 정보 +- `signature`: 개별 검증자의 서명을 집계하는 BLS 서명 + +인증하는 검증자의 첫 번째 작업은 `data`를 구축하는 것입니다. `data`에는 다음 정보가 포함됩니다. + +- `slot`: 인증이 참조하는 슬롯 번호 +- `index`: 주어진 슬롯에서 검증자가 속한 위원회를 식별하는 번호 +- `beacon_block_root`: 검증자가 체인의 헤드에서 보는 블록의 루트 해시(포크 선택 알고리즘을 적용한 결과) +- `source`: 검증자가 가장 최근에 정당화된 블록으로 보는 것을 나타내는 최종성 투표의 일부 +- `target`: 검증자가 현재 에폭의 첫 번째 블록으로 보는 것을 나타내는 최종성 투표의 일부 + +`data`가 구축되면 검증자는 자신의 검증자 인덱스에 해당하는 `aggregation_bits`의 비트를 0에서 1로 뒤집어 참여했음을 표시할 수 있습니다. + +마지막으로 검증자는 인증에 서명하고 네트워크에 브로드캐스트합니다. + +### 집계된 인증 {#aggregated-attestation} + +모든 검증자에 대해 이 데이터를 네트워크를 통해 전달하는 데 상당한 오버헤드가 있습니다. 따라서 개별 검증자의 인증은 더 광범위하게 브로드캐스트되기 전에 서브넷 내에서 집계됩니다. 여기에는 서명을 함께 집계하여 브로드캐스트되는 인증에 합의 `data`와 해당 `data`에 동의하는 모든 검증자의 서명을 결합하여 형성된 단일 서명이 포함되도록 하는 작업이 포함됩니다. `aggregation_bits`를 사용하여 이를 확인할 수 있습니다. 왜냐하면 이는 위원회에 있는 각 검증자의 인덱스(ID는 `data`에 제공됨)를 제공하며, 이를 사용하여 개별 서명을 쿼리할 수 있기 때문입니다. + +각 에폭에서 각 서브넷의 16개 검증자가 `수집자`로 선택됩니다. 수집자는 가십 네트워크를 통해 들은 모든 인증 중 자신의 `data`와 동일한 `data`를 가진 인증을 수집합니다. 일치하는 각 인증의 발신자는 `aggregation_bits`에 기록됩니다. 그런 다음 수집자는 인증 집계를 더 넓은 네트워크에 브로드캐스트합니다. + +검증자가 블록 제안자로 선택되면 서브넷의 집계 인증을 새 블록의 최신 슬롯까지 패키징합니다. + +### 인증 포함 라이프사이클 {#attestation-inclusion-lifecycle} + +1. 생성 +2. 전파 +3. 집계 +4. 전파 +5. 포함 + +인증 라이프사이클은 아래 도식에 요약되어 있습니다. + +![인증 라이프사이클](./attestation_schematic.png) + +## 보상 {#rewards} + +검증자는 인증을 제출하면 보상을 받습니다. 인증 보상은 참여 플래그(소스, 타깃 및 헤드), 기본 보상 및 참여율에 따라 달라집니다. + +각 참여 플래그는 제출된 인증 및 포함 지연에 따라 참 또는 거짓이 될 수 있습니다. + +세 플래그가 모두 참일 때 최상의 시나리오가 발생하며, 이 경우 검증자는 (올바른 플래그당) 다음과 같이 보상을 받습니다. + +`보상 += 기본 보상 * 플래그 가중치 * 플래그 인증 비율 / 64` + +플래그 인증 비율은 주어진 플래그에 대한 모든 인증 검증자의 유효 잔액 합계를 총 활성 유효 잔액과 비교하여 측정됩니다. + +### 기본 보상 {#base-reward} + +기본 보상은 인증 검증자의 수와 이들의 유효 스테이킹 이더 잔액에 따라 계산됩니다. + +`기본 보상 = 검증자 유효 잔액 x 2^6 / SQRT(모든 활성 검증자의 유효 잔액)` + +#### 포함 지연 {#inclusion-delay} + +검증자가 체인의 헤드(`블록 n`)에 투표할 때 `블록 n+1`은 아직 제안되지 않았습니다. 따라서 인증은 자연스럽게 **한 블록 후에** 포함되므로 체인 헤드가 `블록 n`이라고 투표한 모든 인증은 `블록 n+1`에 포함되며, 포함 지연은 1이 됩니다. 포함 지연이 두 슬롯으로 두 배가 되면 인증 보상은 절반으로 줄어듭니다. 왜냐하면 인증 보상을 계산하기 위해 기본 보상에 포함 지연의 역수를 곱하기 때문입니다. + +### 인증 시나리오 {#attestation-scenarios} + +#### 투표 검증자 누락 {#missing-voting-validator} + +검증자는 인증을 제출하기까지 최대 1 에폭의 시간이 있습니다. 에폭 0에서 인증을 놓친 경우, 에폭 1에서 포함 지연과 함께 제출할 수 있습니다. + +#### 수집자 누락 {#missing-aggregator} + +에폭당 총 16개의 수집자가 있습니다. 또한, 무작위 검증자들은 **256 에폭 동안 두 개의 서브넷에** 구독하여 수집자가 누락될 경우 백업 역할을 합니다. + +#### 블록 제안자 누락 {#missing-block-proposer} + +경우에 따라 운 좋은 수집자가 블록 제안자가 될 수도 있다는 점에 유의하세요. 블록 제안자가 누락되어 인증이 포함되지 않은 경우, 다음 블록 제안자가 집계된 인증을 선택하여 다음 블록에 포함시킵니다. 그러나 포함 지연은 1만큼 증가합니다. + +## 더 읽어보기 {#further-reading} + +- [Vitalik의 주석이 달린 합의 사양의 인증](https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md#attestationdata) +- [eth2book.info의 인증](https://eth2book.info/capella/part3/containers/dependencies/#attestationdata) + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/block-proposal/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/block-proposal/index.md new file mode 100644 index 00000000000..8836280f1a2 --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/block-proposal/index.md @@ -0,0 +1,69 @@ +--- +title: "블록 제안" +description: "지분 증명 이더리움에서 블록이 제안되는 방법에 대한 설명입니다." +lang: ko +--- + +블록은 블록체인의 기본 단위입니다. 블록은 노드 간에 전달되고 합의를 거쳐 각 노드의 데이터베이스에 추가되는 개별 정보 단위입니다. 이 페이지에서는 블록이 어떻게 생성되는지 설명합니다. + +## 필수 구성 요소 {#prerequisites} + +블록 제안은 지분 증명 프로토콜의 일부입니다. 이 페이지를 이해하는 데 도움이 되도록 [지분 증명](/developers/docs/consensus-mechanisms/pos/) 및 [블록 아키텍처](/developers/docs/blocks/)에 대해 읽어보시는 것을 권장합니다. + +## 누가 블록을 생성하나요? {#who-produces-blocks} + +검증자 계정이 블록을 제안합니다. 검증자 계정은 실행 클라이언트와 합의 클라이언트의 일부로 검증자 소프트웨어를 실행하고 예치 계약에 최소 32 ETH를 예치한 노드 운영자가 관리합니다. 그러나 각 검증자는 가끔씩만 블록 제안을 담당합니다. 이더리움은 시간을 슬롯과 에폭 단위로 측정합니다. 각 슬롯은 12초이며, 32개의 슬롯(6.4분)이 하나의 에폭을 구성합니다. 모든 슬롯은 이더리움에 새로운 블록을 추가할 수 있는 기회입니다. + +### 무작위 선택 {#random-selection} + +각 슬롯에서 단일 검증자가 의사 난수 방식으로 선택되어 블록을 제안합니다. 각 노드가 진정한 난수를 생성할 경우 합의에 도달할 수 없기 때문에 블록체인에는 진정한 의미의 무작위성이란 존재하지 않습니다. 대신, 검증자 선택 과정을 예측할 수 없도록 만드는 것이 목표입니다. 이더리움에서는 블록 제안자의 해시와 매 블록마다 업데이트되는 시드를 혼합하는 RANDAO라는 알고리즘을 사용하여 무작위성을 구현합니다. 이 값은 전체 검증자 집합에서 특정 검증자를 선택하는 데 사용됩니다. 검증자 선택은 특정 종류의 시드 조작을 방지하기 위해 두 에폭 전에 미리 고정됩니다. + +검증자는 각 슬롯에서 RANDAO에 추가하지만, 전역 RANDAO 값은 에폭당 한 번만 업데이트됩니다. 다음 블록 제안자의 인덱스를 계산하기 위해 RANDAO 값과 슬롯 번호를 혼합하여 각 슬롯에서 고유한 값을 생성합니다. 개별 검증자가 선택될 확률은 단순히 `1/N`(여기서 `N` = 총 활성 검증자 수)이 아닙니다. 대신, 각 검증자의 유효 ETH 잔액에 따라 가중치가 부여됩니다. 최대 유효 잔액은 32 ETH입니다(즉, `잔액 < 32 ETH`는 `잔액 == 32 ETH`보다 가중치가 낮지만, `잔액 > 32 ETH`는 `잔액 == 32 ETH`보다 가중치가 높지 않다는 것을 의미합니다). + +각 슬롯에서 단 하나의 블록 제안자만 선택됩니다. 정상적인 조건에서는 단일 블록 생성자가 할당된 슬롯에서 단일 블록을 생성하고 배포합니다. 동일한 슬롯에 두 개의 블록을 생성하는 것은 슬래싱 대상이 되는 위반 행위이며, 종종 "이중 서명(equivocation)"으로 알려져 있습니다. + +## 블록은 어떻게 생성되나요? {#how-is-a-block-created} + +블록 제안자는 자체적으로 로컬에서 실행되는 포크 선택 알고리즘의 관점에 따라 체인의 가장 최근 헤드 위에 구축되는 서명된 비콘 블록을 브로드캐스트해야 합니다. 포크 선택 알고리즘은 이전 슬롯에 남아 있는 대기 중인 증명을 적용한 다음, 기록에서 증명의 누적 가중치가 가장 큰 블록을 찾습니다. 해당 블록은 제안자가 생성한 새 블록의 부모가 됩니다. + +블록 제안자는 자체 로컬 데이터베이스와 체인 뷰에서 데이터를 수집하여 블록을 생성합니다. 블록의 내용은 아래 코드 조각에 나와 있습니다. + +```rust +class BeaconBlockBody(Container): + randao_reveal: BLSSignature + eth1_data: Eth1Data + graffiti: Bytes32 + proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS] + attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS] + attestations: List[Attestation, MAX_ATTESTATIONS] + deposits: List[Deposit, MAX_DEPOSITS] + voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] + sync_aggregate: SyncAggregate + execution_payload: ExecutionPayload +``` + +`randao_reveal` 필드는 블록 제안자가 현재 에폭 번호에 서명하여 생성하는 검증 가능한 무작위 값을 포함합니다. `eth1_data`는 예치 계약에 대한 블록 제안자의 관점에 대한 투표이며, 여기에는 예치 머클 트리의 루트와 새로운 예치의 검증을 가능하게 하는 총 예치 수가 포함됩니다. `graffiti`는 블록에 메시지를 추가하는 데 사용할 수 있는 선택적 필드입니다. `proposer_slashings`와 `attester_slashings`는 제안자의 체인 관점에 따라 특정 검증자가 슬래싱 가능한 위반 행위를 저질렀다는 증거를 포함하는 필드입니다. `deposits`는 블록 제안자가 인지하고 있는 새로운 검증자 예치 목록이고, `voluntary_exits`는 블록 제안자가 합의 레이어 가십 네트워크를 통해 알게 된, 탈퇴를 희망하는 검증자 목록입니다. `sync_aggregate`는 이전에 동기화 위원회(라이트 클라이언트 데이터를 제공하는 검증자 하위 집합)에 할당되어 데이터 서명에 참여했던 검증자를 보여주는 벡터입니다. + +`execution_payload`는 실행 클라이언트와 합의 클라이언트 간에 트랜잭션 관련 정보가 전달되도록 합니다. `execution_payload`는 비콘 블록 내부에 중첩되는 실행 데이터 블록입니다. `execution_payload` 내부의 필드는 이더리움 황서에 요약된 블록 구조를 반영하지만, 오머(ommer)가 없고 `difficulty` 대신 `prev_randao`가 있다는 점이 다릅니다. 실행 클라이언트는 자체 가십 네트워크를 통해 수신한 로컬 트랜잭션 풀에 접근할 수 있습니다. 이러한 트랜잭션은 로컬에서 실행되어 사후 상태(post-state)라고 하는 업데이트된 상태 트라이를 생성합니다. 트랜잭션은 `transactions`라는 목록으로 `execution_payload`에 포함되며, 사후 상태(post-state)는 `state-root` 필드에 제공됩니다. + +이 모든 데이터는 비콘 블록으로 수집 및 서명되어 블록 제안자의 피어에게 브로드캐스트되고, 피어는 이를 다시 자신의 피어에게 전파하는 식으로 계속됩니다. + +[블록의 구조](/developers/docs/blocks)에 대해 자세히 알아보세요. + +## 블록은 어떻게 되나요? {#what-happens-to-blocks} + +블록은 블록 제안자의 로컬 데이터베이스에 추가되고 합의 레이어 가십 네트워크를 통해 피어에게 브로드캐스트됩니다. 검증자는 블록을 수신하면 해당 블록이 올바른 부모를 가졌는지, 올바른 슬롯에 해당하는지, 제안자 인덱스가 예상과 일치하는지, RANDAO 공개 값이 유효한지, 제안자가 슬래싱되지 않았는지 등을 포함하여 내부 데이터를 검증합니다. `execution_payload`가 분리되고, 검증자의 실행 클라이언트는 목록에 있는 트랜잭션을 재실행하여 제안된 상태 변경을 확인합니다. 블록이 이 모든 검사를 통과하면 각 검증자는 블록을 자신의 정식 체인에 추가합니다. 그러면 다음 슬롯에서 프로세스가 다시 시작됩니다. + +## 블록 보상 {#block-rewards} + +블록 제안자는 자신의 작업에 대한 보상을 받습니다. 활성 검증자 수와 그들의 유효 잔액의 함수로 계산되는 `base_reward`가 있습니다. 그러면 블록 제안자는 블록에 포함된 모든 유효한 증명에 대해 `base_reward`의 일부를 받습니다. 블록을 증명하는 검증자가 많을수록 블록 제안자의 보상도 커집니다. 또한 슬래싱되어야 할 검증자를 보고하면 슬래싱된 각 검증자에 대해 `유효 잔액 * 1/512`에 해당하는 보상을 받습니다. + +[보상 및 페널티에 대한 추가 정보](/developers/docs/consensus-mechanisms/pos/rewards-and-penalties) + +## 더 읽어보기 {#further-reading} + +- [블록 소개](/developers/docs/blocks/) +- [지분 증명 소개](/developers/docs/consensus-mechanisms/pos/) +- [이더리움 합의 사양](https://github.com/ethereum/consensus-specs) +- [Gasper 소개](/developers/docs/consensus-mechanisms/pos/gasper/) +- [이더리움 업그레이드](https://eth2book.info/) diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/faqs/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/faqs/index.md new file mode 100644 index 00000000000..69a8863366c --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/faqs/index.md @@ -0,0 +1,172 @@ +--- +title: "자주 묻는 질문" +description: "지분 증명 이더리움에 대해 자주 묻는 질문입니다." +lang: ko +--- + +## 지분 증명이란 무엇인가요? {#what-is-proof-of-stake} + +지분 증명은 부정직하게 행동하는 공격자가 가치 있는 자산을 잃도록 보장함으로써 블록체인에 보안을 제공할 수 있는 알고리즘의 한 종류입니다. 지분 증명 시스템은 검증자가 증명 가능한 부정직한 행동에 가담할 경우 파기될 수 있는 일부 자산을 제공하기 위해 검증자 집합을 필요로 합니다. 이더리움은 블록체인을 보호하기 위해 지분 증명 메커니즘을 사용합니다. + +## 지분 증명은 작업 증명과 어떻게 다른가요? {#comparison-to-proof-of-work} + +작업 증명과 지분 증명은 모두 악의적인 행위자가 네트워크에 스팸을 보내거나 사기를 치는 것을 경제적으로 막는 메커니즘입니다. 두 경우 모두 합의에 적극적으로 참여하는 노드는 잘못된 행동을 할 경우 잃게 될 일부 자산을 "네트워크에" 투입합니다. + +작업 증명에서 이 자산은 에너지입니다. 채굴자로 알려진 노드는 다른 어떤 노드보다 빠르게 값을 계산하는 것을 목표로 하는 알고리즘을 실행합니다. 가장 빠른 노드는 체인에 블록을 제안할 권리를 가집니다. 체인의 기록을 변경하거나 블록 제안을 지배하려면 채굴자는 항상 경쟁에서 이길 수 있을 만큼의 많은 컴퓨팅 파워를 가져야 합니다. 이는 실행하기에 엄청나게 비싸고 어려우므로 공격으로부터 체인을 보호합니다. 작업 증명을 사용하여 "채굴"하는 데 필요한 에너지는 채굴자가 비용을 지불하는 실제 자산입니다. + +지분 증명은 검증자로 알려진 노드가 스마트 계약에 암호화폐 자산을 명시적으로 제출해야 합니다. 검증자가 잘못 행동하면 에너지 소비를 통해 간접적으로가 아닌 체인에 직접 자산을 "스테이킹"하기 때문에 이 암호화폐는 파기될 수 있습니다. + +작업 증명은 채굴 과정에서 전기가 소모되기 때문에 훨씬 더 많은 에너지를 소비합니다. 반면 지분 증명은 아주 적은 양의 에너지만 필요로 합니다. 이더리움 검증자는 라즈베리 파이와 같은 저전력 장치에서도 실행할 수 있습니다. 이더리움의 지분 증명 메커니즘은 공격 비용이 더 크고 공격자에 대한 결과가 더 심각하기 때문에 작업 증명보다 더 안전한 것으로 간주됩니다. + +작업 증명 대 지분 증명은 논란의 여지가 있는 주제입니다. [Vitalik Buterin의 블로그](https://vitalik.eth.limo/general/2017/12/31/pos_faq.html#what-are-the-benefits-of-proof-of-stake-as-opposed-to-proof-of-work)와 Justin Drake와 Lyn Alden 간의 토론은 주장에 대한 좋은 요약을 제공합니다. + + + +## 지분 증명은 에너지 효율적인가요? {#is-pos-energy-efficient} + +네. 지분 증명 네트워크의 노드는 아주 적은 양의 에너지를 사용합니다. 제3자 연구에 따르면 전체 지분 증명 이더리움 네트워크는 연간 약 0.0026 TWh를 소비하며, 이는 미국 내 게임 소비량보다 약 13,000배 적은 수치입니다. + +[이더리움의 에너지 소비에 대해 더 알아보기](/energy-consumption/). + +## 지분 증명은 안전한가요? {#is-pos-secure} + +이더리움의 지분 증명은 매우 안전합니다. 이 메커니즘은 출시되기 전 8년 동안 엄격하게 연구, 개발 및 테스트되었습니다. 보안 보장은 작업 증명 블록체인과 다릅니다. 지분 증명에서는 악의적인 검증자가 적극적으로 처벌("슬래싱")을 받고 검증자 집합에서 퇴출될 수 있으며, 상당한 양의 ETH 비용이 발생합니다. 작업 증명 하에서는 공격자가 충분한 해시 파워를 가지고 있는 동안 공격을 계속 반복할 수 있습니다. 또한 작업 증명보다 지분 증명 이더리움에 동등한 공격을 가하는 것이 더 비용이 많이 듭니다. 체인의 생동감에 영향을 미치려면 네트워크에 스테이킹된 총 이더의 최소 33%가 필요합니다(성공 가능성이 극히 낮은 매우 정교한 공격의 경우는 제외). 미래 블록의 내용을 제어하려면 총 스테이킹된 ETH의 최소 51%가 필요하며, 기록을 다시 쓰려면 총 스테이킹의 66% 이상이 필요합니다. 이더리움 프로토콜은 33% 또는 51% 공격 시나리오에서는 이러한 자산을 파기하고, 66% 공격 시나리오에서는 사회적 합의에 의해 파기합니다. + +- [공격자로부터 이더리움 지분 증명을 방어하는 방법에 대해 더 알아보기](/developers/docs/consensus-mechanisms/pos/attack-and-defense) +- [지분 증명 설계에 대해 더 알아보기](https://medium.com/@VitalikButerin/a-proof-of-stake-design-philosophy-506585978d51) + +## 지분 증명은 이더리움을 더 저렴하게 만드나요? {#does-pos-make-ethereum-cheaper} + +아니요. 거래(가스 수수료) 전송 비용은 네트워크 수요가 증가함에 따라 증가하는 동적 수수료 시장에 의해 결정됩니다. 합의 메커니즘은 이에 직접적인 영향을 미치지 않습니다. + +[가스에 대해 더 알아보기](/developers/docs/gas). + +## 노드, 클라이언트, 검증자란 무엇인가요? {#what-are-nodes-clients-and-validators} + +노드는 이더리움 네트워크에 연결된 컴퓨터입니다. 클라이언트는 컴퓨터를 노드로 바꾸는 소프트웨어입니다. 클라이언트에는 실행 클라이언트와 합의 클라이언트의 두 가지 유형이 있습니다. 노드를 생성하려면 두 가지 모두 필요합니다. 검증자는 노드가 지분 증명 합의에 참여할 수 있도록 하는 합의 클라이언트에 대한 선택적 추가 기능입니다. 이는 선택되었을 때 블록을 생성 및 제안하고 네트워크에서 들은 블록에 대해 인증하는 것을 의미합니다. 검증자를 실행하려면 노드 운영자는 예금 계약에 32 ETH를 예치해야 합니다. + +- [노드 및 클라이언트에 대해 더 알아보기](/developers/docs/nodes-and-clients) +- [스테이킹에 대해 더 알아보기](/staking) + +## 지분 증명은 새로운 아이디어인가요? {#is-pos-new} + +아니요. 2011년 BitcoinTalk의 한 사용자가 비트코인 업그레이드로 [지분 증명의 기본 아이디어를 제안했습니다](https://bitcointalk.org/index.php?topic=27787.0). 이더리움 메인넷에 구현할 준비가 되기까지 11년이 걸렸습니다. 다른 일부 체인들은 이더리움보다 먼저 지분 증명을 구현했지만, Gasper로 알려진 이더리움의 특정 메커니즘은 아니었습니다. + +## 이더리움의 지분 증명은 무엇이 특별한가요? {#why-is-ethereum-pos-special} + +이더리움의 지분 증명 메커니즘은 설계가 독특합니다. 설계 및 구현된 최초의 지분 증명 메커니즘은 아니지만 가장 견고합니다. 지분 증명 메커니즘은 "Casper"로 알려져 있습니다. Casper는 검증자가 블록을 제안하기 위해 어떻게 선택되는지, 인증이 언제 어떻게 이루어지는지, 인증이 어떻게 계산되는지, 검증자에게 주어지는 보상과 벌칙, 슬래싱 조건, 비활성 누출과 같은 안전장치 메커니즘, 그리고 "최종 승인"의 조건을 정의합니다. 최종 승인이란 블록이 정규 체인의 영구적인 일부로 간주되기 위해 네트워크에 스테이킹된 총 ETH의 최소 66%가 투표해야 하는 조건입니다. 연구원들은 이더리움을 위해 특별히 Casper를 개발했으며, 이더리움은 이를 구현한 최초이자 유일한 블록체인입니다. + +Casper 외에도 이더리움의 지분 증명은 LMD-GHOST라는 포크 선택 알고리즘을 사용합니다. 이는 동일한 슬롯에 대해 두 개의 블록이 존재하는 조건이 발생하는 경우에 필요합니다. 이는 블록체인의 두 개의 포크를 생성합니다. LMD-GHOST는 인증의 "가중치"가 가장 큰 것을 선택합니다. 가중치는 검증자의 유효 잔액으로 가중된 인증 수입니다. LMD-GHOST는 이더리움에 고유합니다. + +Casper와 LMD_GHOST의 조합은 Gasper로 알려져 있습니다. + +[Gasper에 대해 더 알아보기](/developers/docs/consensus-mechanisms/pos/gasper/) + +## 슬래싱이란 무엇인가요? {#what-is-slashing} + +슬래싱은 검증자 스테이킹의 일부를 파기하고 네트워크에서 검증자를 퇴출시키는 것을 의미하는 용어입니다. 슬래싱으로 잃는 ETH의 양은 슬래싱되는 검증자의 수에 따라 확장됩니다. 이는 공모하는 검증자가 개인보다 더 심하게 처벌받는다는 것을 의미합니다. + +[슬래싱에 대해 더 알아보기](/developers/docs/consensus-mechanisms/pos/rewards-and-penalties#slashing) + +## 검증자에게 32 ETH가 필요한 이유는 무엇인가요? {#why-32-eth} + +검증자는 잘못된 행동을 할 경우 잃을 것이 있도록 ETH를 스테이킹해야 합니다. 특히 32 ETH를 스테이킹해야 하는 이유는 노드가 적당한 하드웨어에서 실행될 수 있도록 하기 위함입니다. 검증자당 최소 ETH가 더 낮으면 검증자의 수, 따라서 각 슬롯에서 처리해야 하는 메시지의 수가 증가하여 노드를 실행하는 데 더 강력한 하드웨어가 필요하게 됩니다. + +## 검증자는 어떻게 선택되나요? {#how-are-validators-selected} + +단일 검증자는 블록 제안자의 해시와 매 블록마다 업데이트되는 시드를 혼합하는 RANDAO라는 알고리즘을 사용하여 각 슬롯에서 블록을 제안하기 위해 의사 무작위로 선택됩니다. 이 값은 전체 검증자 집합에서 특정 검증자를 선택하는 데 사용됩니다. 검증자 선택은 2 에폭 전에 고정됩니다. + +[검증자 선택에 대해 더 알아보기](/developers/docs/consensus-mechanisms/pos/block-proposal) + +## 스테이크 그라인딩이란 무엇인가요? {#what-is-stake-grinding} + +스테이크 그라인딩은 공격자가 자신의 검증자에게 유리하도록 검증자 선택 알고리즘을 편향시키려고 시도하는 지분 증명 네트워크에 대한 공격의 한 범주입니다. RANDAO에 대한 스테이크 그라인딩 공격에는 총 스테이킹된 ETH의 약 절반이 필요합니다. + +[스테이크 그라인딩에 대해 더 알아보기](https://eth2book.info/altair/part2/building_blocks/randomness/#randao-biasability) + +## 소셜 슬래싱이란 무엇인가요? {#what-is-social-slashing} + +소셜 슬래싱은 공격에 대응하여 블록체인의 포크를 조정하는 커뮤니티의 능력입니다. 이를 통해 커뮤니티는 부정직한 체인을 확정하는 공격자로부터 복구할 수 있습니다. 소셜 슬래싱은 검열 공격에 대해서도 사용될 수 있습니다. + +- [소셜 슬래싱에 대해 더 알아보기](https://ercwl.medium.com/the-case-for-social-slashing-59277ff4d9c7) +- [소셜 슬래싱에 대한 Vitalik Buterin의 글](https://vitalik.eth.limo/general/2017/12/31/pos_faq.html#what-is-proof-of-stake) + +## 제가 슬래싱될까요? {#will-i-get-slashed} + +검증자로서 고의로 악의적인 행동에 가담하지 않는 한 슬래싱당하기는 매우 어렵습니다. 슬래싱은 검증자가 동일한 슬롯에 대해 여러 블록을 제안하거나 자신의 증명과 모순되는 매우 특정한 시나리오에서만 구현됩니다. 이는 우연히 발생할 가능성이 거의 없습니다. + +[슬래싱 조건에 대해 더 알아보기](https://eth2book.info/altair/part2/incentives/slashing) + +## Nothing-at-stake 문제란 무엇인가요? {#what-is-nothing-at-stake-problem} + +Nothing-at-stake 문제는 보상만 있고 벌칙은 없는 일부 지분 증명 메커니즘의 개념적 문제입니다. 스테이킹된 것이 아무것도 없다면, 실용적인 검증자는 블록체인의 모든 또는 여러 포크를 증명하는 것을 똑같이 기뻐할 것입니다. 이는 보상을 증가시키기 때문입니다. 이더리움은 최종 승인 조건과 슬래싱을 사용하여 하나의 정규 체인을 보장함으로써 이 문제를 해결합니다. + +[Nothing-at-stake 문제에 대해 더 알아보기](https://vitalik.eth.limo/general/2017/12/31/pos_faq.html#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed) + +## 포크 선택 알고리즘이란 무엇인가요? {#what-is-a-fork-choice-algorithm} + +포크 선택 알고리즘은 어느 체인이 정규 체인인지를 결정하는 규칙을 구현합니다. 최적의 조건 하에서는 슬롯당 블록 제안자가 하나뿐이고 선택할 블록도 하나뿐이므로 포크 선택 규칙이 필요하지 않습니다. 하지만 가끔 동일한 슬롯에 여러 블록이 있거나 정보가 늦게 도착하는 경우 체인 헤드 근처의 블록이 구성되는 방식에 대해 여러 옵션이 생길 수 있습니다. 이러한 경우 모든 클라이언트는 모두 올바른 블록 시퀀스를 선택하도록 동일한 규칙을 구현해야 합니다. 포크 선택 알고리즘은 이러한 규칙을 인코딩합니다. + +이더리움의 포크 선택 알고리즘은 LMD-GHOST라고 불립니다. 가장 많은 스테이킹된 ETH가 투표한 포크, 즉 증명의 가중치가 가장 큰 포크를 선택합니다. + +[LMD-GHOST에 대해 더 알아보기](/developers/docs/consensus-mechanisms/pos/gasper/#fork-choice) + +## 지분 증명에서의 최종 승인이란 무엇인가요? {#what-is-finality} + +지분 증명에서의 최종 승인은 특정 블록이 정규 체인의 영구적인 부분이며 공격자가 총 스테이킹된 이더의 33%를 소각하는 합의 실패가 없는 한 되돌릴 수 없다는 보장입니다. 이는 작업 증명 블록체인과 관련된 "확률적 최종 승인"과 대조되는 "암호 경제학적" 최종 승인입니다. 확률적 최종 승인에서는 블록에 대한 명시적인 확정/미확정 상태가 없습니다. 블록이 오래될수록 체인에서 제거될 가능성이 점점 낮아지고, 사용자는 블록이 "안전하다"고 충분히 확신할 때 스스로 결정합니다. 암호 경제학적 최종 승인을 사용하면 체크포인트 블록 쌍은 스테이킹된 이더의 66%에 의해 투표되어야 합니다. 이 조건이 충족되면 해당 체크포인트 사이의 블록은 명시적으로 "확정"됩니다. + +[최종 승인에 대해 더 알아보기](/developers/docs/consensus-mechanisms/pos/#finality) + +## "약한 주관성"이란 무엇인가요? {#what-is-weak-subjectivity} + +약한 주관성은 블록체인의 현재 상태를 확인하기 위해 사회적 정보가 사용되는 지분 증명 네트워크의 특징입니다. 새로운 노드 또는 오랫동안 오프라인 상태였다가 네트워크에 다시 참여하는 노드에게는 최근 상태가 제공되어 노드가 올바른 체인에 있는지 즉시 확인할 수 있습니다. 이러한 상태는 "약한 주관성 체크포인트"로 알려져 있으며 다른 노드 운영자로부터 대역 외로, 또는 블록 탐색기나 여러 공용 엔드포인트에서 얻을 수 있습니다. + +[약한 주관성에 대해 더 알아보기](/developers/docs/consensus-mechanisms/pos/weak-subjectivity) + +## 지분 증명은 검열 저항성이 있나요? {#is-pos-censorship-resistant} + +검열 저항성은 현재 증명하기 어렵습니다. 하지만 작업 증명과 달리 지분 증명은 검열하는 검증자를 처벌하기 위해 슬래싱을 조정할 수 있는 옵션을 제공합니다. 블록 빌더와 블록 제안자를 분리하고 빌더가 각 블록에 포함해야 하는 거래 목록을 구현하는 프로토콜에 대한 변경 사항이 예정되어 있습니다. 이 제안은 제안자-빌더 분리로 알려져 있으며 검증자가 거래를 검열하는 것을 방지하는 데 도움이 됩니다. + +[제안자-빌더 분리에 대해 더 알아보기](https://notes.ethereum.org/@fradamt/H1TsYRfJc#Original-basic-scheme) + +## 이더리움의 지분 증명 시스템이 51% 공격을 받을 수 있나요? {#pos-51-attack} + +네. 지분 증명은 작업 증명과 마찬가지로 51% 공격에 취약합니다. 공격자가 네트워크 해시 파워의 51%를 요구하는 대신, 총 스테이킹된 ETH의 51%를 요구합니다. 총 스테이크의 51%를 축적한 공격자는 포크 선택 알고리즘을 제어할 수 있게 됩니다. 이를 통해 공격자는 특정 거래를 검열하고, 단거리 재구성을 수행하며, 자신에게 유리하게 블록을 재정렬하여 MEV를 추출할 수 있습니다. + +[지분 증명 공격에 대해 더 알아보기](/developers/docs/consensus-mechanisms/pos/attack-and-defense) + +## 사회적 조정이란 무엇이며 왜 필요한가요? {#what-is-social-coordination} + +사회적 조정은 이더리움의 마지막 방어선으로, 부정직한 블록을 확정한 공격으로부터 정직한 체인을 복구할 수 있게 합니다. 이 경우 이더리움 커뮤니티는 "대역 외"로 조정하고 정직한 소수 포크를 사용하는 데 동의해야 하며, 그 과정에서 공격자의 검증자를 슬래싱해야 합니다. 이는 앱과 거래소도 정직한 포크를 인식해야 함을 의미합니다. + +[사회적 조정에 대해 더 읽어보기](/developers/docs/consensus-mechanisms/pos/attack-and-defense#people-the-last-line-of-defense) + +## 지분 증명에서는 부자가 더 부유해지나요? {#do-rich-get-richer} + +누군가 스테이킹해야 할 ETH가 많을수록 더 많은 검증자를 운영할 수 있고 더 많은 보상을 얻을 수 있습니다. 보상은 스테이킹된 ETH의 양에 따라 선형적으로 확장되며, 모두가 동일한 비율의 수익을 얻습니다. 작업 증명은 대규모로 하드웨어를 구매하는 부유한 채굴자들이 규모의 경제로부터 이익을 얻기 때문에 지분 증명보다 부자를 더 부유하게 만듭니다. 즉, 부와 보상의 관계는 비선형적입니다. + +## 지분 증명은 작업 증명보다 더 중앙화되어 있나요? {#is-pos-decentralized} + +아니요, 작업 증명은 채굴 비용이 증가하고 개인을, 그리고 작은 회사를 몰아내는 등 중앙화되는 경향이 있습니다. 현재 지분 증명의 문제는 유동성 스테이킹 파생상품(LSD)의 영향입니다. 이는 일부 제공업체에 의해 스테이킹된 ETH를 나타내는 토큰으로, 실제 ETH를 언스테이킹하지 않고도 누구나 2차 시장에서 교환할 수 있습니다. LSD는 사용자가 32 ETH 미만으로 스테이킹할 수 있게 해주지만, 소수의 대규모 조직이 대부분의 스테이크를 통제하게 되는 중앙화 위험도 만듭니다. 이것이 [솔로 스테이킹](/staking/solo)이 이더리움을 위한 최상의 옵션인 이유입니다. + +[LSD의 스테이크 중앙화에 대해 더 알아보기](https://notes.ethereum.org/@djrtwo/risks-of-lsd) + +## 왜 ETH만 스테이킹할 수 있나요? {#why-can-i-only-stake-eth} + +이더는 이더리움 네트워크의 기본 통화입니다. 투표 가중치 및 보안을 위한 유효 잔액을 계산하기 위해 모든 스테이크가 표시되는 단일 통화를 갖는 것이 필수적입니다. ETH 자체는 스마트 계약이 아닌 이더리움의 기본 구성 요소입니다. 다른 통화를 통합하면 스테이킹의 복잡성이 크게 증가하고 보안이 감소합니다. + +## 이더리움이 유일한 지분 증명 블록체인인가요? {#is-ethereum-the-only-pos-blockchain} + +아니요, 여러 지분 증명 블록체인이 있습니다. 어떤 것도 이더리움과 동일하지 않습니다. 이더리움의 지분 증명 메커니즘은 독특합니다. + +## 병합이 무엇인가요? {#what-is-the-merge} + +머지는 이더리움이 작업 증명 기반 합의 메커니즘을 끄고 지분 증명 기반 합의 메커니즘을 켠 순간이었습니다. 머지는 2022년 9월 15일에 일어났습니다. + +[머지에 대해 더 알아보기](/roadmap/merge) + +## 생동감과 안전성이란 무엇인가요? {#what-are-liveness-and-safety} + +생동감과 안전성은 블록체인의 두 가지 기본 보안 문제입니다. 생동감은 최종 승인 체인의 가용성입니다. 체인이 최종 승인을 멈추거나 사용자가 쉽게 접근할 수 없는 경우, 이는 생동감 실패입니다. 매우 높은 접근 비용도 생동감 실패로 간주될 수 있습니다. 안전성은 체인을 공격하기 얼마나 어려운지, 즉 충돌하는 체크포인트를 최종 승인하는 것이 얼마나 어려운지를 나타냅니다. + +[Casper 논문에서 더 읽어보기](https://arxiv.org/pdf/1710.09437.pdf) diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/gasper/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/gasper/index.md new file mode 100644 index 00000000000..4228be39c3d --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/gasper/index.md @@ -0,0 +1,52 @@ +--- +title: "가스퍼" +description: "Gasper 지분 증명 메커니즘에 대한 설명입니다." +lang: ko +--- + +Gasper는 Casper the Friendly Finality Gadget(Casper-FFG)과 LMD-GHOST 포크 선택 알고리즘의 조합입니다. 이 구성 요소들은 함께 지분 증명 이더리움을 보호하는 합의 메커니즘을 형성합니다. 캐스퍼는 특정 블록을 "최종 승인된" 상태로 업그레이드하여 네트워크에 새로 진입하는 참가자들이 정식 체인을 동기화하고 있음을 확신할 수 있도록 하는 메커니즘입니다. 포크 선택 알고리즘은 누적된 투표를 사용하여 블록체인에서 포크가 발생할 때 노드가 올바른 포크를 쉽게 선택할 수 있도록 합니다. + +**참고** Casper-FFG의 원래 정의는 Gasper에 포함되기 위해 약간 업데이트되었습니다. 이 페이지에서는 업데이트된 버전을 다룹니다. + +## 필수 자료 + +이 자료를 이해하려면 [지분 증명](/developers/docs/consensus-mechanisms/pos/)에 대한 소개 페이지를 읽어야 합니다. + +## Gasper의 역할 {#role-of-gasper} + +Gasper는 지분 증명 블록체인 위에 위치하며, 노드는 블록을 제안하거나 검증하는 데 게으르거나 부정직할 경우 파기될 수 있는 보안 보증금으로 이더를 제공합니다. Gasper는 검증자가 보상과 처벌을 받는 방법, 수락하거나 거부할 블록, 그리고 구축할 블록체인의 포크를 결정하는 메커니즘입니다. + +## 최종 승인이란 무엇인가요? {#what-is-finality} + +최종 승인은 특정 블록의 속성으로, 심각한 합의 실패가 있었고 공격자가 총 스테이킹된 이더의 최소 1/3을 파괴하지 않는 한 되돌릴 수 없음을 의미합니다. 최종 승인된 블록은 블록체인이 확신하는 정보로 생각할 수 있습니다. 블록이 최종 승인되려면 2단계 업그레이드 절차를 거쳐야 합니다. + +1. 총 스테이킹된 이더의 3분의 2가 해당 블록이 정식 체인에 포함되는 것에 찬성 투표를 해야 합니다. 이 조건은 블록을 "정당화된" 상태로 업그레이드합니다. 정당화된 블록은 되돌려질 가능성이 낮지만, 특정 조건 하에서는 되돌려질 수 있습니다. +2. 정당화된 블록 위에 다른 블록이 정당화되면 "최종 승인된" 상태로 업그레이드됩니다. 블록을 최종 승인하는 것은 해당 블록을 정식 체인에 포함시키겠다는 약속입니다. 공격자가 수백만 이더(수십억 달러)를 파괴하지 않는 한 되돌릴 수 없습니다. + +이러한 블록 업그레이드는 모든 슬롯에서 발생하는 것이 아닙니다. 대신, 에폭 경계 블록만이 정당화되고 최종 승인될 수 있습니다. 이 블록들은 "체크포인트"로 알려져 있습니다. 업그레이드는 체크포인트 쌍을 고려합니다. 더 오래된 체크포인트를 최종 승인하고 더 최신 블록을 정당화하려면 두 개의 연속된 체크포인트 사이에 "초과 과반수 링크"가 있어야 합니다(즉, 총 스테이킹된 이더의 3분의 2가 체크포인트 B가 체크포인트 A의 올바른 후손이라고 투표해야 합니다). + +최종 승인은 블록이 정식이라는 것에 대한 3분의 2의 동의를 필요로 하므로, 공격자는 다음 없이는 대체 최종 승인 체인을 생성할 수 없습니다. + +1. 총 스테이킹된 이더의 3분의 2를 소유하거나 조작하는 것. +2. 총 스테이킹된 이더의 최소 3분의 1을 파괴하는 것. + +첫 번째 조건은 체인을 최종 승인하는 데 스테이킹된 이더의 3분의 2가 필요하기 때문에 발생합니다. 두 번째 조건은 총 스테이킹의 3분의 2가 두 포크 모두에 찬성 투표한 경우, 3분의 1은 두 포크 모두에 투표했음에 틀림없기 때문에 발생합니다. 이중 투표는 최대로 처벌되는 슬래싱 조건이며, 총 스테이킹의 3분의 1이 파괴됩니다. 2022년 5월 기준, 이를 위해서는 공격자가 약 100억 달러 상당의 이더를 소각해야 합니다. Gasper에서 블록을 정당화하고 최종 승인하는 알고리즘은 [Casper the Friendly Finality Gadget(Casper-FFG)](https://arxiv.org/pdf/1710.09437.pdf)을 약간 수정한 형태입니다. + +### 인센티브 및 슬래싱 {#incentives-and-slashing} + +검증자는 정직하게 블록을 제안하고 검증한 것에 대해 보상을 받습니다. 이더가 보상으로 지급되어 그들의 스테이킹에 추가됩니다. 반면에, 자리를 비우거나 호출되었을 때 행동하지 않는 검증자는 이러한 보상을 놓치고 때로는 기존 스테이킹의 일부를 잃게 됩니다. 하지만 오프라인 상태에 대한 페널티는 작으며, 대부분의 경우 보상을 놓치는 기회비용에 해당합니다. 그러나 일부 검증자 행동은 우발적으로 하기가 매우 어렵고 악의적인 의도를 나타냅니다. 예를 들어 동일한 슬롯에 여러 블록을 제안하거나, 동일한 슬롯에 대해 여러 블록을 증명하거나, 이전 체크포인트 투표와 모순되는 경우입니다. 이러한 행위는 더 엄격하게 처벌되는 "슬래싱 가능" 행위입니다. 슬래싱은 검증자 스테이킹의 일부를 소각하고 검증자를 검증자 네트워크에서 제거하는 결과를 낳습니다. 이 과정은 36일이 걸립니다. 첫째 날에는 최대 1 ETH의 초기 페널티가 부과됩니다. 그 후 슬래싱된 검증자의 이더는 출금 기간 동안 서서히 소진되지만, 18일째에는 "상관관계 페널티"를 받게 되는데, 이는 더 많은 검증자가 비슷한 시기에 슬래싱될 때 더 커집니다. 최대 페널티는 전체 스테이킹 금액입니다. 이러한 보상과 페널티는 정직한 검증자에게 인센티브를 제공하고 네트워크에 대한 공격을 억제하도록 설계되었습니다. + +### 비활성 누수 {#inactivity-leak} + +보안뿐만 아니라 Gasper는 "그럴듯한 활성"도 제공합니다. 이는 총 스테이킹된 이더의 3분의 2가 정직하게 투표하고 프로토콜을 따르는 한, 다른 어떤 활동(예: 공격, 지연 문제 또는 슬래싱)과 관계없이 체인이 최종 승인될 수 있다는 조건입니다. 다시 말해, 체인의 최종 승인을 막으려면 총 스테이킹된 이더의 3분의 1이 어떻게든 손상되어야 합니다. Gasper에는 "비활성 누수"로 알려진 활성 실패에 대한 추가 방어선이 있습니다. 이 메커니즘은 체인이 4 에폭 이상 최종 승인에 실패했을 때 활성화됩니다. 다수 체인을 활발히 증명하지 않는 검증자들의 스테이킹은 다수가 총 스테이킹의 3분의 2를 되찾을 때까지 점차 소진되어, 활성 실패가 일시적임을 보장합니다. + +### 포크 선택 {#fork-choice} + +Casper-FFG의 원래 정의에는 `가장 높은 높이를 가진 정당화된 체크포인트를 포함하는 체인을 따르라`는 규칙을 부과하는 포크 선택 알고리즘이 포함되어 있었으며, 여기서 높이는 제네시스 블록으로부터의 가장 큰 거리로 정의됩니다. Gasper에서는 원래의 포크 선택 규칙이 더 이상 사용되지 않으며, LMD-GHOST라는 더 정교한 알고리즘이 선호됩니다. 정상적인 조건에서는 포크 선택 규칙이 불필요하다는 것을 깨닫는 것이 중요합니다. 모든 슬롯에 대해 단일 블록 제안자가 있으며, 정직한 검증자들이 이를 증명합니다. 포크 선택 알고리즘은 네트워크 비동기성이 크거나 부정직한 블록 제안자가 모순된 정보를 제공한 경우에만 필요합니다. 하지만 그러한 경우가 발생할 때, 포크 선택 알고리즘은 올바른 체인을 보호하는 중요한 방어 수단입니다. + +LMD-GHOST는 "latest message-driven greedy heaviest observed sub-tree"의 약자입니다. 이는 증명의 누적 가중치가 가장 큰 포크를 정식 포크로 선택하고(greedy heaviest subtree), 검증자로부터 여러 메시지를 받은 경우 최신 메시지만 고려하는(latest-message driven) 알고리즘을 정의하는 전문 용어가 많은 방식입니다. 가장 무거운 블록을 자신의 정식 체인에 추가하기 전에, 모든 검증자는 이 규칙을 사용하여 각 블록을 평가합니다. + +## 추가 정보 {#further-reading} + +- [Gasper: GHOST와 Casper의 결합](https://arxiv.org/pdf/2003.03052.pdf) +- [Casper the Friendly Finality Gadget](https://arxiv.org/pdf/1710.09437.pdf) diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/index.md new file mode 100644 index 00000000000..8df4bf22cc4 --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/index.md @@ -0,0 +1,99 @@ +--- +title: "지분 증명(PoS)" +description: "지분 증명 합의 프로토콜과 이더리움 상에서 그 역할에 대한 설명" +lang: ko +--- + +지분 증명(PoS)은 이더리움의 [합의 메커니즘](/developers/docs/consensus-mechanisms/)의 기반입니다. 이더리움은 이전의 [작업 증명](/developers/docs/consensus-mechanisms/pow) 아키텍처에 비해 더 안전하고, 에너지 집약도가 낮으며, 새로운 확장 솔루션을 구현하는 데 더 좋기 때문에 2022년에 지분 증명 메커니즘으로 전환했습니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하려면 먼저 [합의 메커니즘](/developers/docs/consensus-mechanisms/)에 대해 읽어보시는 것을 권장합니다. + +## 지분 증명(PoS) 이란 무엇인가요? {#what-is-pos} + +지분 증명은 검증자가 부정직하게 행동할 경우 파괴될 수 있는 가치를 네트워크에 투입했음을 증명하는 방법입니다. 이더리움의 지분 증명에서는 검증자가 ETH 형태의 자본을 이더리움의 스마트 계약에 명시적으로 스테이킹합니다. Validator는 블록체인 네트워크에 새로 생성된 블록을 점검한다. 그리고 가끔씩 직접 블록을 생성하기도 한다. 만약 그들이 네트워크를 사기치려고 시도한다면 (예를 들어, 하나를 보내야 할 때 여러 블록을 제안하거나 상충되는 증명을 보내는 경우), 그들의 스테이킹된 ETH의 일부 또는 전부가 소각될 수 있습니다. + +## 검증자 {#validators} + +검증자로 참여하려면 사용자는 32 ETH를 예치 계약에 예치하고 실행 클라이언트, 합의 클라이언트, 검증 클라이언트의 세 가지 별도의 소프트웨어를 실행해야 합니다. 이더를 예치함으로서 활동 큐 (activation queue)에 참여하게 되며, 이는 새로 참여하려는 검증인들의 수를 제한하는 역할을 한다. 검증인은 이더리움 네트워크 상의 개개인들로부터 새 블록을 할당받는다. 블록에 전달된 거래는 제안된 이더리움 상태 변경이 유효한지 확인하기 위해 다시 실행되며, 블록 서명이 확인됩니다. 검증인은 네트워크로 해당 블록을 승인하는 투표를 보낸다. 이 투표는 attestation이라 부른다. + +PoW는 마이닝의 난이도에 따라 블록의 타이밍이 정해졌다면 지분 증명 PoS 는 이러한 타이밍은 고정되어 있다. 이더리움의 지분 증명 시간은 12초 슬롯이 32개 있는 에포크 (epoch) 로 구성되어 있다. 검증인은 각 슬롯마다 블록 제안자 (block proposer) 역할을 맡기 위해 랜덤하게 선택된다. 선택받은 검증인은 새로운 블록 생성과 네트워크 상 다른 노드들로 전송하는 일을 맡는다. 각 슬롯마다 검증인들이 모여 일종의 위원회를 구성하기 되고 각 검증인들의 투표로 제안되는 블록의 유효성을 검증하게 된다. 검증자 집합을 위원회로 나누는 것은 네트워크 부하를 관리 가능하게 유지하는 데 중요합니다. 위원회는 모든 활성 검증자가 모든 에포크에서 증명을 하지만, 모든 슬롯에서는 그렇지 않도록 검증자 집합을 나눕니다. + +## 이더리움 지분 증명(PoS)에서 트랜잭션이 실행되는 방법 {#transaction-execution-ethereum-pos} + +다음은 이더리움 지분 증명에서 트랜잭션이 어떻게 실행되는지에 대한 종합적인 설명입니다. + +1. 사용자는 개인 키로 [트랜잭션](/developers/docs/transactions/)을 생성하고 서명합니다. 이는 보통 [ethers.js](https://docs.ethers.org/v6/), [web3js](https://docs.web3js.org/), [web3py](https://web3py.readthedocs.io/en/v5/) 등과 같은 지갑 또는 라이브러리에서 처리하지만, 내부적으로는 사용자가 이더리움 [JSON-RPC API](/developers/docs/apis/json-rpc/)를 사용하여 노드에 요청을 보내는 것입니다. 사용자는 거래를 블록에 포함하도록 장려하기 위해 검증자에게 팁으로 지불할 준비가 된 가스 양을 정의합니다. [팁](/developers/docs/gas/#priority-fee)은 검증자에게 지급되고 [기본 수수료](/developers/docs/gas/#base-fee)는 소각됩니다. +2. 트랜잭션은 유효성을 검증하는 이더리움 [실행 클라이언트](/developers/docs/nodes-and-clients/#execution-client)에 제출됩니다. 이는 발신자가 거래를 이행할 충분한 ETH를 가지고 있고, 올바른 키로 서명했는지를 확인하는 것을 의미합니다. +3. 거래가 유효하면 실행 클라이언트는 이를 로컬 메모풀(보류 중인 거래 목록)에 추가하고 실행 계층의 가십 네트워크를 통해 다른 노드에 브로드캐스트합니다. 다른 노드들이 거래에 대해 알게 되면 그들도 이를 자신의 로컬 메모풀에 추가합니다. 고급 사용자는 트랜잭션을 브로드캐스팅하지 않고 [Flashbots Auction](https://docs.flashbots.net/flashbots-auction/overview)과 같은 전문 블록 빌더에게 전달할 수 있습니다. 이를 통해 그들은 최대 수익([MEV](/developers/docs/mev/#mev-extraction))을 위해 예정된 블록의 트랜잭션을 정리할 수 있습니다. +4. 네트워크의 검증자 노드 중 하나가 현재 슬롯의 블록 제안자가 되며, 이전에 RANDAO를 사용하여 의사 난수로 선택되었습니다. 이 노드는 이더리움 블록체인에 추가될 다음 블록을 생성하고 브로드캐스트하며 글로벌 상태를 업데이트하는 역할을 담당합니다. 이 노드는 실행 클라이언트, 합의 클라이언트, 검증 클라이언트의 세 부분으로 구성됩니다. 실행 클라이언트는 로컬 메모풀의 거래를 "실행 페이로드"로 묶고 이를 로컬에서 실행하여 상태 변화를 생성합니다. 이 정보는 합의 클라이언트로 전달되며, 여기서 실행 페이로드는 네트워크가 체인의 최상위에 있는 블록 순서에 동의할 수 있도록 보상, 벌금, 슬래싱, 증명 등과 같은 정보를 포함하는 "비콘 블록"의 일부로 포장됩니다. 실행 클라이언트와 합의 클라이언트 간의 통신은 [합의 및 실행 클라이언트 연결하기](/developers/docs/networking-layer/#connecting-clients)에 더 자세히 설명되어 있습니다. +5. 다른 노드들은 합의 계층의 가십 네트워크에서 새로운 비콘 블록을 받습니다. 그들은 이를 실행 클라이언트에 전달하여 거래가 로컬에서 다시 실행되어 제안된 상태 변경이 유효한지 확인합니다. 그러면 검증자 클라이언트는 해당 블록이 유효하고 체인 뷰에서 논리적인 다음 블록임을 증명합니다(이는 [포크 선택 규칙](/developers/docs/consensus-mechanisms/pos/#fork-choice)에 정의된 대로 증명 가중치가 가장 큰 체인 위에 구축됨을 의미합니다). 블록은 그것을 증명한 각 노드의 로컬 데이터베이스에 추가됩니다. +6. 거래는 두 개의 체크포인트 사이에 "초과 다수 연결"이 있는 체인의 일부가 되면 "최종 확정"된 것으로 간주할 수 있습니다. 체크포인트는 각 에포크의 시작 시점에 발생하며, 각 슬롯에서 일부 활성 검증자만 증명하지만 모든 활성 검증자가 각 에포크 전체에서 증명한다는 사실을 고려하기 위해 존재합니다. 따라서 '초과 다수 연결'은 에포크 간에만 입증될 수 있습니다 (이는 네트워크에 스테이킹된 전체 ETH의 66%가 두 체크포인트에 동의하는 경우입니다). + +최종 확정성에 대한 자세한 내용은 아래에서 확인할 수 있습니다. + +## 최종 승인 {#finality} + +거래는 많은 양의 ETH가 소각되지 않으면 변경할 수 없는 블록의 일부일 때 분산 네트워크에서 "최종 확정성"을 가집니다. 지분 증명 이더리움에서 finality는 이른바 체크포인트 블록을 통해 관리된다. 각 에포크 epoch의 첫번째 블록이 체크포인트이다. 검증인들은 유효하다고 생각하는 체크포인트 쌍을 투표한다. 두 개의 체크포인트가 전체 스테이킹된 ETH의 최소 3분의 2를 나타내는 투표를 유치하면 체크포인트가 업그레이드됩니다. 둘 중 더 최근 것이 "justified" 된다. 그리고 둘 중 더 이전 것은 이미 justified 되었다고 볼 수 있는데 이는 이전 에포크에서 이미 타깃이었기 때문이다. 이제 "finalized"로 업그레이드 되었다. 체크포인트를 업그레이드하는 이 프로세스는 [Casper the Friendly Finality Gadget(Casper-FFG)](https://arxiv.org/pdf/1710.09437)에 의해 처리됩니다. Casper-FFG는 합의를 위한 블록 최종성 도구입니다. 블록이 한번 최종 확정되면, 과반수 스테이커의 슬래싱 없이는 되돌리거나 변경할 수 없으므로 경제적으로 불가능해집니다. + +최종 확정된 블록을 되돌리기 위해 공격자는 총 스테이킹된 ETH의 최소 3분의 1을 잃는 것을 감수해야 합니다. 이에 대한 정확한 이유는 이 [이더리움 재단 블로그 게시물](https://blog.ethereum.org/2016/05/09/on-settlement-finality/)에 설명되어 있습니다. 최종 승인 여부는 3분의 2 이상이 요구 되므로 네트워크가 최종 승인에 도달하지 않게 하려면 전체 지분의 3분의 1을 투표하면 된다. 이에 대항하기 위한 메커니즘이 있습니다. 바로 [미활동 유출](https://eth2book.info/bellatrix/part2/incentives/inactivity)입니다. 이는 블록체인이 4 에폭 연속으로 최종 승인에 실패할 경우 작동한다. 비활성 유출은 과반수에 반대하는 투표를 하는 검증자들로부터 스테이킹된 ETH를 소진시켜 과반수가 3분의 2 과반수를 회복하고 체인을 최종 확정할 수 있도록 합니다. + +## 암호경제학적 보안 {#crypto-economic-security} + +검증자는 책임이 따른다. 검증자는 블록 검증과 제안에 참여하기 위한 충분한 장비와 연결성이 있어야 한다. 그 대가로 검증자는 ETH로 보상을 받으며 (그들의 스테이킹 잔액이 증가합니다). 한편 검증자로 참여하는 일은 일반 사용자들이 개인적인 이익을 위해 또는 악한 감정을 품고 네트워크를 공격할 수 있는 루트가 될 수도 있다. 이 문제를 방지하기 위해, 검증자는 호출되었을 때 참여하지 않으면 ETH 보상을 받지 못하고, 부정행위를 할 경우 기존 지분이 소멸될 수 있습니다. 두 가지 주요 부정행위는 단일 슬롯에서 여러 블록을 제안하는 것(동시제안)과 상반되는 증명 제출입니다. + +잘못된 검증자가 동시에 많이 벌어질수록 ETH가 삭감되는 금액이 많아집니다. 이는 ["상관관계 페널티"](https://eth2book.info/bellatrix/part2/incentives/slashing#the-correlation-penalty)로 알려져 있으며, 단일 검증자가 단독으로 슬래싱되는 경우 약 1%의 지분으로 경미할 수도 있고, 검증자 지분의 100%가 소멸(대량 슬래싱 이벤트)될 수도 있습니다. 첫째 날은 최대 1 ETH 까지 벌금을 부과할 수 있으며, 18일 째 되는 날에는 상관 벌칙을 받게 되고, 끝으로 36일 째 되는 날에는 네트워크로부터 추방당하게 된다. 비록 네트워크에 있지만 투표를 제출하지 않기 때문에 매일 소량의 인증 벌칙 (attestation penalty) 가 부과된다. 따라서 부정 행위를 위해 여러 사람들끼리 협조하는 일이 매우 어렵게 된다. + +## 포크 선택 {#fork-choice} + +네트워크가 최상의 그리고 부정 행위가 없는 상태라면 블록체인의 최상단에는 단일의 블록이 있으며 모든 검증자들은 이를 검증한다. 그러나 검증자는 네트워크 속도라든지 거짓 블록 제안 등의 사유로 인해 체인의 최상단이 서로 다른 모습일 수 있다. 따라서 합의 클라이언트는 그들 중 어떤 것을 선택해야 하는지 알기 위해 일종의 알고리즘이 필요하다. 지분 증명 이더리움에 사용되는 알고리즘은 [LMD-GHOST](https://arxiv.org/pdf/2003.03052.pdf)라고 하며, 기록상 증명 가중치가 가장 큰 포크를 식별하는 방식으로 작동합니다. + +## 지분 증명과 보안 {#pos-and-security} + +[51% 공격](https://www.investopedia.com/terms/1/51-attack.asp)의 위협은 작업 증명과 마찬가지로 지분 증명에도 여전히 존재하지만, 공격자에게는 훨씬 더 위험합니다. 공격자는 스테이킹된 ETH의 51%가 필요합니다. 이렇게 51% 이상 지분이 있어야만 공격을 위해 원하는 포크를 선정할 수 있다. 합의 클라이언트는 누적 증명의 가중치를 이용하여 올바른 체인을 알 수 있으며, 해당 공격자는 포크를 인정된 것으로 만들 수 있다. 하지만 proof-of-stake가 proof-of-work를 넘어서게 되면서 커뮤니티는 더 쉽게 반격할 수 있게 되었다. 예컨대 진정한 검증자는 소수 체인을 진흥시키고 공격자의 포크를 승인하지 않게 한다. 부정행위를 하는 자를 네트워크에서 강제로 추방시키고 이더 보유량을 회수할 수도 있다. 이런 부분들이 이른바 "51% 공격"에 대항하는 방어막이라고 볼 수 있다. + +51% 공격 외에도 악의적인 행위자는 다음과 같은 다른 유형의 악의적인 활동을 시도할 수 있습니다: + +- 장거리 공격(그러나 결말 장치는 이 공격 벡터를 무력화함) +- 단거리 '재조직' 공격(제안자 부스팅 및 증명 마감 기한이 이를 완화함) +- 반동 및 균형 공격(제안자 부스팅으로 완화되며, 이러한 공격은 이상적인 네트워크 조건에서만 시연됨) +- 눈사태 공격(포크 선택 알고리즘 규칙에 의해 무력화되며 최신 메시지만 고려) + +결론적으로 지분 증명 방식은 PoW 방식 보다 더 안전하다. + +## 장단점 {#pros-and-cons} + +| 장점 | 단점 | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | +| 스테이킹(staking)은 참가자들로 하여금 네트워크를 더 안전하게 해주며 이는 탈중앙화에 도움을 준다. 검증자 노드는 일반 노트북에서도 실행 가능하다. 스테이킹 풀(staking pool)은 일반 유저들이 32 ETH 씩이나 보유하지 않아도 지분(stake)를 가질 수 있도록 해준다. | 지분 증명 방식은 PoW방식보다 비교적 최신 방식이므로 실전 테스트가 덜 되어있을 수 있다. | +| 스테이킹은 더 탈중앙화 되어 있다. PoW 마이닝에서 만큼의 시너지(규모의 경제)를 발휘하지 않는다. | 지분 증명은 PoW 방식보다 요건이 더 까다롭다. | +| 지분 증명 방식은 PoW 방식보다 암호화폐 경제적으로 더 안전하다. | 이더리움 지분 증명 방식에 참여하기 위해서는 3개의 소프트웨어를 실행하여야 한다. | +| 네트워크 참여자들에게 보상을 주기 위한 새로운 이더 발행량이 적다. | | + +### 작업 증명과의 비교 {#comparison-to-proof-of-work} + +이더리움은 원래 작업 증명(Proof of Work)을 사용했으나 2022년 9월에 지분 증명(Proof of Stake)으로 전환했습니다. 지분 증명(PoS)은 작업 증명(PoW)에 비해 여러 가지 장점이 있습니다. + +- 전력 소비 개선 - proof-of-work 식 연산에 필요한 전력 소비율보다 적은 전력이 필요하게 된다. +- 더 낮은 진입 장벽 및 장비 요건 - 블록 생성 기회를 얻기 위해 값비싼 장비를 구입하지 않아도 된다. +- 중앙화 리스크 개선 - 지분 증명 방식은 더 많은 노드가 참여하게 된다. +- 전력 소비가 줄어들기 때문에 사람들의 참여를 촉진하기 위해 비교적 적은 이더 발행이 요구된다. +- 악의적 행위에 대한 경제적 처벌은 작업 증명에 비해 공격자가 51% 공격을 더 비용이 많이 들게 만듭니다. +- 51% 공격이 암호-경제적 방어를 넘을 경우에도 커뮤니티는 정직한 체인의 사회적 회복을 이룰 수 있다. + +## 더 읽어보기 {#further-reading} + +- [지분 증명 FAQ](https://vitalik.eth.limo/general/2017/12/31/pos_faq.html) _비탈릭 부테린_ +- [지분 증명이란 무엇인가](https://consensys.net/blog/blockchain-explained/what-is-proof-of-stake/) _ConsenSys_ +- [지분 증명이란 무엇이며 왜 중요한가](https://bitcoinmagazine.com/culture/what-proof-of-stake-is-and-why-it-matters-1377531463) _비탈릭 부테린_ +- [지분 증명이 필요한 이유(2020년 11월)](https://vitalik.eth.limo/general/2020/11/06/pos2020.html) _비탈릭 부테린_ +- [지분 증명: 약한 주관성을 사랑하게 된 계기](https://blog.ethereum.org/2014/11/25/proof-stake-learned-love-weak-subjectivity/) _비탈릭 부테린_ +- [지분 증명 이더리움 공격과 방어](https://mirror.xyz/jmcook.eth/YqHargbVWVNRQqQpVpzrqEQ8IqwNUJDIpwRP7SS5FXs) +- [지분 증명 설계 철학](https://medium.com/@VitalikButerin/a-proof-of-stake-design-philosophy-506585978d51) _비탈릭 부테린_ +- [영상: 비탈릭 부테린이 렉스 프리드먼에게 설명하는 지분 증명](https://www.youtube.com/watch?v=3yrqBG-7EVE) + +## 관련 주제 {#related-topics} + +- [작업 증명](/developers/docs/consensus-mechanisms/pow/) +- [권위 증명](/developers/docs/consensus-mechanisms/poa/) diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/keys/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/keys/index.md new file mode 100644 index 00000000000..63fee91be7c --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/keys/index.md @@ -0,0 +1,102 @@ +--- +title: "지분 증명 이더리움의 키" +description: "이더리움의 지분 증명 합의 메커니즘에서 사용되는 키에 대한 설명" +lang: ko +--- + +이더리움은 공개-개인 키 암호학을 사용하여 사용자 자산을 보호합니다. 공개 키는 이더리움 주소의 기반으로 사용됩니다. 즉, 일반 대중에게 공개되며 고유 식별자로 사용됩니다. 개인(또는 '비밀') 키는 계정 소유자만 액세스할 수 있어야 합니다. 개인 키는 트랜잭션과 데이터에 '서명'하는 데 사용되며, 이를 통해 암호학은 특정 개인 키의 보유자가 일부 작업을 승인했음을 증명할 수 있습니다. + +이더리움의 키는 [타원 곡선 암호학](https://en.wikipedia.org/wiki/Elliptic-curve_cryptography)을 사용하여 생성됩니다. + +하지만 이더리움이 [작업 증명](/developers/docs/consensus-mechanisms/pow)에서 [지분 증명](/developers/docs/consensus-mechanisms/pos)으로 전환되면서 새로운 유형의 키가 이더리움에 추가되었습니다. 기존 키는 이전과 똑같이 작동하며 계정을 보호하는 타원 곡선 기반 키에는 변경 사항이 없었습니다. 그러나 ETH를 스테이킹하고 검증자를 운영하여 지분 증명에 참여하려면 사용자에게 새로운 유형의 키가 필요했습니다. 이러한 필요성은 수많은 검증자 간에 오가는 많은 메시지로 인한 확장성 문제에서 비롯되었습니다. 네트워크가 합의에 도달하는 데 필요한 통신량을 줄이려면 쉽게 집계할 수 있는 암호화 방법이 필요했기 때문입니다. + +이 새로운 유형의 키는 [**Boneh-Lynn-Shacham(BLS)** 서명 체계](https://wikipedia.org/wiki/BLS_digital_signature)를 사용합니다. BLS는 매우 효율적인 서명 집계를 가능하게 하지만, 집계된 개별 검증자 키의 리버스 엔지니어링도 허용하므로 검증자 간의 작업을 관리하는 데 이상적입니다. + +## 두 가지 유형의 검증자 키 {#two-types-of-keys} + +지분 증명으로 전환하기 전 이더리움 사용자는 자금에 액세스하기 위한 단일 타원 곡선 기반 개인 키만 가지고 있었습니다. 지분 증명이 도입되면서 단독 스테이커가 되고자 하는 사용자는 검증자 키인출 키도 필요하게 되었습니다. + +### 검증자 키 {#validator-key} + +검증자 서명 키는 두 가지 요소로 구성됩니다. + +- 검증자 **개인** 키 +- 검증자 **공개** 키 + +검증자 개인 키의 목적은 블록 제안 및 증명과 같은 온체인 작업에 서명하는 것입니다. 이 때문에 이 키는 핫월렛에 보관해야 합니다. + +이러한 유연성 덕분에 검증자 서명 키를 한 장치에서 다른 장치로 매우 빠르게 이동할 수 있다는 장점이 있지만, 키를 분실하거나 도난당한 경우 도둑이 다음과 같은 몇 가지 방법으로 악의적으로 행동할 수 있습니다. + +- 다음을 통해 검증자가 삭감되도록 합니다. + - 제안자로서 동일한 슬롯에 대해 서로 다른 두 개의 비콘 블록에 서명 + - 증명자로서 다른 증명을 "둘러싸는" 증명에 서명 + - 증명자로서 동일한 대상을 갖는 서로 다른 두 개의 증명에 서명 +- 자발적 출금을 강제하여 검증자의 스테이킹을 중단시키고, 인출 키 소유자에게 ETH 잔액에 대한 접근 권한을 부여합니다. + +사용자가 스테이킹 예치 계약에 ETH를 예치할 때 검증자 공개 키가 트랜잭션 데이터에 포함됩니다. 이는 예치 데이터라고 하며, 이더리움이 검증자를 식별할 수 있도록 합니다. + +### 인출 자격 증명 {#withdrawal-credentials} + +모든 검증자는 인출 자격 증명이라는 속성을 가집니다. 이 32바이트 필드의 첫 번째 바이트는 계정 유형을 식별합니다. `0x00`은 기존 BLS(샤펠라 이전, 인출 불가) 자격 증명을, `0x01`은 실행 주소를 가리키는 레거시 자격 증명을, `0x02`는 최신 복리 자격 증명 유형을 나타냅니다. + +`0x00` BLS 키를 가진 검증자는 초과 잔액 지급 또는 스테이킹에서 전체 인출을 활성화하기 위해 이러한 자격 증명을 실행 주소를 가리키도록 업데이트해야 합니다. 이는 초기 키 생성 시 예치 데이터에 실행 주소를 제공하거나, _또는_ 나중에 인출 키를 사용하여 `BLSToExecutionChange` 메시지에 서명하고 브로드캐스트함으로써 수행할 수 있습니다. + +[검증자 인출 자격 증명에 대한 추가 정보](/developers/docs/consensus-mechanisms/pos/withdrawal-credentials/) + +### 인출 키 {#withdrawal-key} + +초기 예치 시 설정하지 않은 경우, 인출 자격 증명을 실행 주소를 가리키도록 업데이트하려면 인출 키가 필요합니다. 이를 통해 초과 잔액 지급 처리가 시작될 수 있으며, 사용자는 스테이킹된 ETH를 완전히 인출할 수 있게 됩니다. + +검증자 키와 마찬가지로 인출 키도 다음 두 가지 구성 요소로 이루어져 있습니다. + +- 인출 **개인** 키 +- 인출 **공개** 키 + +인출 자격 증명을 `0x01` 유형으로 업데이트하기 전에 이 키를 분실하면 검증자 잔액에 대한 접근 권한을 잃게 됩니다. 이러한 작업에는 검증자의 개인 키가 필요하므로 검증자는 여전히 증명과 블록에 서명할 수 있지만, 인출 키를 분실하면 인센티브가 거의 또는 전혀 없습니다. + +검증자 키를 이더리움 계정 키와 분리하면 단일 사용자가 여러 검증자를 실행할 수 있습니다. + +![검증자 키 개요](validator-key-schematic.png) + +**참고**: 스테이킹 의무를 종료하고 검증자 잔액을 인출하려면 현재 검증자 키로 [자발적 출금 메시지(VEM)](https://mirror.xyz/ladislaus.eth/wmoBbUBes2Wp1_6DvP6slPabkyujSU7MZOFOC3QpErs&1)에 서명해야 합니다. 그러나 [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002)는 사용자가 향후 인출 키로 출금 메시지에 서명하여 검증자 출금을 트리거하고 잔액을 인출할 수 있도록 하는 제안입니다. 이를 통해 ETH를 [서비스형 스테이킹 제공자](/staking/saas/#what-is-staking-as-a-service)에게 위임하는 스테이커가 자신의 자금을 계속 통제할 수 있게 되어 신뢰 가정이 줄어들 것입니다. + +## 시드 문구에서 키 파생 {#deriving-keys-from-seed} + +스테이킹된 모든 32 ETH마다 완전히 독립적인 2개의 새로운 키 세트가 필요하다면, 특히 여러 검증자를 실행하는 사용자의 경우 키 관리가 금방 힘들어질 것입니다. 대신, 여러 검증자 키를 단일 공통 비밀에서 파생시킬 수 있으며, 그 단일 비밀을 저장하면 여러 검증자 키에 액세스할 수 있습니다. + +[니모닉](https://en.bitcoinwiki.org/wiki/Mnemonic_phrase)과 경로는 사용자가 지갑에 [액세스할 때](https://ethereum.stackexchange.com/questions/19055/what-is-the-difference-between-m-44-60-0-0-and-m-44-60-0) 자주 접하게 되는 두드러진 특징입니다. 니모닉은 개인 키의 초기 시드 역할을 하는 단어 시퀀스입니다. 추가 데이터와 결합하면 니모닉은 '마스터 키'라고 알려진 해시를 생성합니다. 이것은 트리의 루트로 생각할 수 있습니다. 이 루트의 브랜치는 계층적 경로를 사용하여 파생될 수 있으며, 이를 통해 자식 노드는 부모 노드의 해시와 트리 내 인덱스의 조합으로 존재할 수 있습니다. 니모닉 기반 키 생성에 대한 [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) 및 [BIP-19](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) 표준에 대해 읽어보세요. + +이러한 경로는 다음과 같은 구조를 가지며, 하드웨어 지갑과 상호 작용해 본 사용자에게는 익숙할 것입니다. + +``` +m/44'/60'/0'/0` +``` + +이 경로의 슬래시는 개인 키의 구성 요소를 다음과 같이 분리합니다. + +``` +마스터_키 / 용도 / 코인_타입 / 계정 / 변경 / 주소_인덱스 +``` + +이 로직을 통해 사용자는 단일 니모닉 문구에 가능한 한 많은 검증자를 연결할 수 있습니다. 트리의 루트는 공통으로 사용할 수 있고, 브랜치에서 차별화가 일어날 수 있기 때문입니다. 사용자는 니모닉 문구에서 원하는 수의 키를 파생할 수 있습니다. + +``` + [m / 0] + / + / +[m] - [m / 1] + \ + \ + [m / 2] +``` + +각 브랜치는 `/`로 구분되므로 `m/2`는 마스터 키에서 시작하여 브랜치 2를 따른다는 의미입니다. 아래 개요에서는 단일 니모닉 문구를 사용하여 각각 두 개의 관련 검증자가 있는 세 개의 인출 키를 저장합니다. + +![검증자 키 로직](multiple-keys.png) + +## 더 읽어보기 {#further-reading} + +- [Carl Beekhuizen의 이더리움 재단 블로그 게시물](https://blog.ethereum.org/2020/05/21/keys/) +- [EIP-2333 BLS12-381 키 생성](https://eips.ethereum.org/EIPS/eip-2333) +- [EIP-7002: 실행 레이어 트리거 출금](https://web.archive.org/web/20250125035123/https://research.2077.xyz/eip-7002-unpacking-improvements-to-staking-ux-post-merge) +- [대규모 키 관리](https://docs.ethstaker.cc/ethstaker-knowledge-base/scaled-node-operators/key-management-at-scale) diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/pos-vs-pow/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/pos-vs-pow/index.md new file mode 100644 index 00000000000..a40a8b6cf0f --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/pos-vs-pow/index.md @@ -0,0 +1,69 @@ +--- +title: "지분 증명(Proof-of-stake) vs 작업 증명(Proof-of-work)" +description: "이더리움의 지분 증명(proof-of-stake)과 작업 증명(proof-of-work) 기반 합의 메커니즘(consensus mechanism) 비교" +lang: ko +--- + +이더리움이 출시되었을 당시, 지분 증명은 이더리움의 보안을 신뢰할 수 있을 만큼 충분한 연구와 개발이 필요한 상태였습니다. 작업 증명은 비트코인을 통해 이미 검증된 더 단순한 메커니즘이었기 때문에, 핵심 개발자들이 이더리움 출시를 위해 즉시 구현할 수 있었습니다. 지분 증명이 구현될 수 있는 수준까지 개발하는 데에는 8년이 더 걸렸습니다. + +이 페이지는 이더리움이 작업 증명에서 지분 증명으로 전환한 이유와 그에 따른 장단점을 설명합니다. + +## 보안 {#security} + +이더리움 연구원들은 지분 증명이 작업 증명보다 더 안전하다고 생각합니다. 하지만 실제 이더리움 메인넷에 최근에야 구현되었기 때문에, 작업 증명에 비해 시간의 검증을 덜 받았습니다. 다음 섹션에서는 지분 증명과 작업 증명의 보안 모델을 비교하여 장단점을 설명합니다. + +### 공격 비용 {#cost-to-attack} + +지분 증명에서 검증자들은 스마트 계약에 최소 32 ETH를 예치("스테이킹")해야 합니다. 이더리움은 부정행위를 하는 검증자들을 처벌하기 위해 스테이킹된 이더를 소각할 수 있습니다. 합의에 도달하기 위해서는 전체 스테이킹된 이더 중 최소 66%가 특정 블록 세트에 찬성해야 합니다. 지분의 66% 이상이 투표한 블록은 "최종 승인"되며, 이는 제거되거나 재구성될 수 없음을 의미합니다. + +네트워크 공격은 체인이 확정되는 것을 막거나, 공격자에게 이득이 되는 방식으로 정규 체인의 블록을 특정하게 구성하도록 하는 것을 의미할 수 있습니다. 이러한 공격을 하기 위해서는 공격자가 두 가지 방법 중 하나를 선택해야 합니다. 대량의 이더를 모아서 직접 투표하거나, 정직한 검증자들을 속여서 원하는 방향으로 투표하도록 만들어야 합니다. 정직한 검증자를 속이는 방식의 공격은 매우 복잡하고 성공하기 어렵습니다. 따라서 이더리움을 공격하기 위한 실질적인 비용은, 합의 과정에 영향을 미칠 만큼의 충분한 스테이크를 확보하는 데 필요한 비용이라고 볼 수 있습니다. + +가장 낮은 공격 비용은 전체 지분의 33%를 초과합니다. 전체 지분의 33%를 초과하여 보유한 공격자는 오프라인 상태가 되는 것만으로도 최종 승인 지연을 유발할 수 있습니다. 하지만 이는 네트워크에 큰 문제가 되지 않습니다. "비활성 누수(inactivity leak)"라는 보호 장치가 있기 때문입니다. 이 메커니즘은 오프라인 상태인 검증자들의 스테이크를 자동으로 줄여나갑니다. 이러한 감소는 온라인 상태를 유지하는 검증자들의 비중이 전체 스테이크의 66%가 되어 체인을 다시 확정할 수 있을 때까지 계속됩니다. 또한 이론적으로는, 전체 스테이크의 33%를 조금 넘게 보유한 공격자가 이중 투표 일으킬 수도 있습니다. 블록 생성자로 선택되었을 때 하나가 아닌 두 개의 블록을 생성하고, 자신이 가진 모든 검증자로 두 번 투표하는 방식입니다. 공격자가 만든 두 개의 블록은 각각 남아있는 정직한 검증자 중 50%가 해당 체인을 먼저 보기만 하면 유효해질 수 있습니다. 따라서 공격자가 메시지 전송 시점을 정확하게 조절할 수 있다면, 두 개의 다른 블록이 모두 최종 승인될 수 있습니다. 이런 방식의 공격은 성공하기가 매우 어렵습니다. 만약 공격자가 두 개의 블록을 모두 최종 승인하는 데 성공하더라도, 이더리움 커뮤니티는 결국 하나의 블만을 선택할 것입니다. 이때 공격자의 검증자들은 선택받지 않은 체인에서 자동으로 처벌을 받게 되어 스테이크를 잃게 됩니다. + +전체 지분의 33%를 초과하여 보유한 공격자는 이더리움 네트워크에 경미한(최종 승인 지연) 또는 더 심각한(이중 최종 승인) 영향을 미칠 수 있습니다. 네트워크에 14,000,000 ETH 이상이 스테이킹되어 있고 대표적인 가격이 $1000/ETH라고 가정할 때, 이러한 공격을 감행하는 데 드는 최소 비용은 `1000 x 14,000,000 x 0.33 = $4,620,000,000`입니다. 공격자는 처벌을 통해 이 금액을 잃게 되며 네트워크에서 퇴출됩니다. 다시 공격하려면 전체 지분의 33%를 초과하여 (다시) 축적하고 (다시) 소각해야 합니다. 네트워크를 공격하려는 각 시도는 46억 달러를 초과하는 비용이 듭니다($1000/ETH 및 1,400만 ETH 스테이킹 기준). 공격자는 처벌(슬래싱)을 받으면 네트워크에서 퇴출되며, 다시 참여하기 위해서는 활성화 대기열에 합류해야 합니다. 이는 반복 공격의 속도가 공격자가 전체 지분의 33%를 초과하여 축적하는 속도뿐만 아니라 모든 검증자를 네트워크에 온보딩하는 데 걸리는 시간에도 제한된다는 것을 의미합니다. 공격자가 공격을 시도할 때마다 발생하는 공급 충격으로 인해, 공격자는 점점 더 가난해지고 나머지 커뮤니티는 더 부유해집니다. + +51% 공격이나 전체 스테이크의 66%를 사용한 최종 승인 번복과 같은 다른 공격들은 훨씬 더 많은 ETH가 필요하며, 공격자에게 더 큰 비용이 듭니다. + +이를 작업 증명과 비교해보겠습니다. 작업 증명 이더리움에 대한 공격을 시작하는 비용은 전체 네트워크 해시율의 50%를 초과하여 지속적으로 소유하는 비용이었습니다. 이는 다른 채굴자들과 경쟁하여 작업 증명 솔루션을 지속적으로 계산할 수 있을 만큼 충분한 컴퓨팅 파워를 위한 하드웨어 구매 비용과 운영 비용을 의미했습니다. 이더리움은 ASIC 대신 주로 GPU로 채굴되었기 때문에 비용이 낮게 유지되었습니다(만약 이더리움이 작업 증명을 계속 사용했다면 ASIC 채굴이 더 보편화되었을 수 있습니다). 공격자는 작업 증명 이더리움 네트워크를 공격하기 위해 많은 하드웨어를 구매하고 전기 요금을 지불해야 했겠지만, 총 비용은 공격에 필요한 충분한 ETH를 확보하는 데 드는 비용보다는 적었을 것입니다. 51% 공격은 지분 증명보다 작업 증명에서 ~[20배 저렴](https://youtu.be/1m12zgJ42dI?t=1562)합니다. 만약 공격이 발견되어 체인이 하드포크를 통해 공격자의 변경사항을 제거하더라도, 공격자는 동일한 하드웨어를 사용하여 새로운 블록을 반복적으로 공격할 수 있었을 것입니다. + +### 복잡성 {#complexity} + +지분 증명은 작업 증명보다 훨씬 더 복잡합니다. 이는 더 단순한 프로토콜에서는 버그나 의도하지 않은 영향을 실수로 발생시킬 가능성이 낮기 때문에, 작업 증명에 유리한 점이 될 수 있습니다. 하지만 이러한 복잡성은 수년간의 연구 개발, 시뮬레이션, 테스트넷 구현을 통해 통제되어 왔습니다. 지분 증명 프로토콜은 5개의 서로 다른 팀이 각각 다른 프로그래밍 언어를 사용하여 실행 계층과 합의 계층을 독립적으로 개발했습니다. 이렇게 여러 팀이 다양한 방식으로 개발했기 때문에 한 클라이언트에서 버그가 발생하더라도 전체 시스템은 안전하게 유지될 수 있습니다. + +지분 증명 합의 로직을 안전하게 개발하고 테스트하기 위해, 비콘 체인은 이더리움 메인넷에 지분 증명이 구현되기 2년 전에 출시되었습니다. 비콘 체인은 지분 증명을 안전하게 테스트할 수 있는 격리된 시험 환경 역할(sandbox)을 했습니다. 실제 이더리움 거래는 처리하지 않으면서도 지분 증명 방식으로 작동하는 독립된 블록체인이었고, 이를 통해 새로운 합의 방식을 검증할 수 있었습니다. 이것이 충분한 시간 동안 안정적이고 버그 없이 운영된 후, 비콘 체인은 이더리움 메인넷과 '병합'되었습니다. 이 모든 과정은 지분 증명의 복잡성을 통제하는 데 기여했고, 그 결과 의도하지 않은 결과나 클라이언트 버그의 위험이 매우 낮아졌습니다. + +### 공격 표면 {#attack-surface} + +지분 증명은 작업 증명보다 더 복잡하기 때문에, 대비해야 할 잠재적인 공격 방법도 더 많습니다. 클라이언트를 연결하는 하나의 P2P 네트워크 대신, 각각 다른 프로토콜을 구현하는 두 개의 네트워크가 있습니다. 각 슬롯마다 블록을 제안할 특정 검증자가 미리 선택되는 방식은 서비스 거부 공격의 가능성을 만듭니다. 즉, 대량의 네트워크 트래픽으로 해당 검증자를 오프라인 상태로 만들 수 있습니다. + +또한 공격자들은 자신들의 블록이나 증명을 정직한 네트워크의 특정 비율에 도달하도록 시간을 교묘하게 조절하여, 네트워크가 특정 방식으로 투표하도록 영향을 미칠 수 있습니다. 마지막으로, 공격자는 단순히 충분한 ETH를 모아서 스테이킹함으로써 합의 메커니즘을 장악할 수 있습니다. 이러한 각 [공격 벡터에는 관련 방어책이 있지만](/developers/docs/consensus-mechanisms/pos/attack-and-defense), 작업 증명에서는 방어해야 할 필요가 없는 것들입니다. + +## 탈중앙화 {#decentralization} + +채굴 하드웨어 확보를 위한 경쟁으로 인해 비용이 높아져서 개인과 소규모 조직이 참여하기 어렵기 때문에, 지분 증명은 작업 증명보다 더 탈중앙화되어 있습니다. 기술적으로는 누구나 적당한 하드웨어로 채굴을 시작할 수 있지만, 대규모 채굴 기업들에 비해 보상을 받을 가능성은 극히 낮습니다 지분 증명에서는 스테이킹 비용과 그에 대한 수익률이 모든 사람에게 동일합니다. 현재 검증자가 되어서 운영하는데는 32 ETH가 필요합니다. + +반면, 유동적 스테이킹 파생상품의 등장으로 일부 대형 제공업체들이 대량의 스테이킹된 ETH를 관리하게 되면서 중앙화에 대한 우려가 생겼습니다. 이는 문제가 되며 최대한 빨리 해결되어야 하지만, 실제로는 더 복잡한 문제입니다. 중앙화된 스테이킹 제공업체가 반드시 검증자에 대한 중앙화된 통제권을 가지는 것은 아닙니다. 이는 종종 각각 32 ETH가 없는 참여자들도 독립적인 노드 운영자로 스테이킹할 수 있도록 ETH를 한곳에 모으는 방법일 뿐입니다. + +이더리움에게 가장 좋은 선택은 검증자들이 가정용 컴퓨터에서 로컬로 운영되어 탈중앙화를 극대화하는 것입니다. 이것이 이더리움이 노드/검증자 운영에 필요한 하드웨어 요구사항을 높이는 변경을 거부하는 이유입니다. + +## 지속 가능성 {#sustainability} + +지분 증명은 블록체인을 탄소 배출이 적은 방식으로 보호합니다. 작업 증명에서는 채굴자들이 블록을 채굴할 권리를 두고 경쟁합니다. 채굴자들은 계산을 더 빠르게 수행할수록 더 성공적이기 때문에, 하드웨어와 에너지 소비에 투자하게 됩니다. 이는 이더리움이 지분 증명으로 전환하기 전에보여진 현상입니다. 지분 증명으로 전환하기 직전, 이더리움은 약 78 TWh/yr(작은 국가와 맞먹는 수준)의 전력을 소비했습니다. 하지만 지분 증명으로 전환하면서 이 에너지 소비량이 약 99.98% 감소했습니다. 지분 증명은 이더리움을 에너지 효율적이고 탄소 배출이 적은 플랫폼으로 만들었습니다. + +[이더리움의 에너지 소비량에 대해 자세히 알아보기](/energy-consumption) + +## 발행 {#issuance} + +지분 증명 이더리움에서는 검증자들이 높은 전기 비용을 지불할 필요가 없기 때문에, 작업 증명 이더리움보다 훨씬 적은 코인을 발행하면서도 보안을 유지할 수 있습니다. 과적으로, 대량의 ETH가 소각될 때 ETH의 인플레이션율을 낮추거나 심지어 디플레이션이 될 수도 있습니다. 낮은 인플레이션율은 이더리움의 보안 비용이 작업 증명 때보다 더 저렴해졌다는 것을 의미합니다. + +## 시각 자료를 찾고 있나요? 시각적 학습자 + +Justin Drake가 설명하는 작업 증명 대비 지분 증명의 장점 보기 + + + +## 더 읽어보기 {#further-reading} + +- [Vitalik의 지분 증명 설계 철학](https://medium.com/@VitalikButerin/a-proof-of-stake-design-philosophy-506585978d51) +- [Vitalik의 지분 증명 FAQ](https://vitalik.eth.limo/general/2017/12/31/pos_faq.html#what-is-proof-of-stake) +- [지분 증명 대 작업 증명에 대한 "Simply Explained" 영상](https://www.youtube.com/watch?v=M3EFi_POhps) diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/rewards-and-penalties/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/rewards-and-penalties/index.md new file mode 100644 index 00000000000..022a2c866b3 --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/rewards-and-penalties/index.md @@ -0,0 +1,91 @@ +--- +title: "지분 증명 보상 및 페널티" +description: "지분 증명 이더리움의 프로토콜 내 인센티브에 대해 알아보세요." +lang: ko +--- + +이더리움은 자체 암호화폐인 이더(ETH)를 사용하여 보안을 유지합니다. 블록 검증 및 체인 헤드 식별에 참여하려는 노드 운영자는 이더를 이더리움의 [예금 계약](/staking/deposit-contract/)에 예치합니다. 그러면 P2P 네트워크를 통해 수신된 새 블록의 유효성을 확인하고 포크 선택 알고리즘을 적용하여 체인의 헤드를 식별하는 검증자 소프트웨어를 실행하는 대가로 이더를 지급받습니다. + +검증자의 주요 역할은 두 가지입니다. 1) 새 블록을 확인하고 유효한 경우 이를 '증명'하는 것, 2) 전체 검증자 풀에서 무작위로 선택되었을 때 새 블록을 제안하는 것입니다. 검증자가 요청 시 이러한 작업 중 하나를 수행하지 못하면 이더 지급을 받지 못합니다. 검증자는 때때로 서명 집계 및 동기화 위원회 참여 작업을 맡기도 합니다. + +또한 동일한 슬롯에 대해 여러 블록을 제안하거나 동일한 슬롯에 대해 여러 블록을 증명하는 등 우발적으로 수행하기 매우 어렵고 악의적인 의도를 나타내는 일부 작업도 있습니다. 이는 '삭감 가능한' 행동으로, 검증자가 네트워크에서 제거되기 전에 일정량의 이더(최대 1ETH)가 소각되며, 이 과정은 36일이 소요됩니다. 삭감된 검증자의 이더는 출금 기간 동안 서서히 소진되지만, 18일째 되는 날에는 '상관관계 페널티'를 받게 되는데, 이는 더 많은 검증자가 비슷한 시기에 삭감될수록 더 커집니다. 따라서 합의 메커니즘의 인센티브 구조는 정직성에 대한 보상을 제공하고 악의적인 행위자를 처벌합니다. + +모든 보상과 페널티는 에폭당 한 번씩 적용됩니다. + +자세한 내용은 계속 읽어보세요... + +## 보상 및 페널티 {#rewards} + +### 보상 {#rewards} + +검증자는 다른 검증자 대다수와 일치하는 투표를 하거나, 블록을 제안하거나, 동기화 위원회에 참여할 때 보상을 받습니다. 각 에폭의 보상 가치는 `base_reward`에서 계산됩니다. 이것은 다른 보상이 계산되는 기본 단위입니다. `base_reward`는 최적의 조건에서 검증자가 에폭당 받는 평균 보상을 나타냅니다. 이는 검증자의 유효 잔액과 총 활성 검증자 수에서 다음과 같이 계산됩니다. + +``` +base_reward = effective_balance * (base_reward_factor / (base_rewards_per_epoch * sqrt(sum(active_balance)))) +``` + +여기서 `base_reward_factor`는 64, `base_rewards_per_epoch`는 4, `sum(active balance)`는 모든 활성 검증자에 걸친 총 스테이킹된 이더입니다. + +이는 기본 보상이 검증자의 유효 잔액에 비례하고 네트워크의 검증자 수에 반비례한다는 것을 의미합니다. 검증자가 많을수록 전체 발행량은 커지지만(`sqrt(N)`), 검증자당 `base_reward`는 작아집니다(`1/sqrt(N)`). 이러한 요소는 스테이킹 노드의 APR에 영향을 미칩니다. [Vitalik의 노트](https://notes.ethereum.org/@vbuterin/rkhCgQteN?type=view#Base-rewards)에서 이에 대한 근거를 읽어보세요. + +그런 다음 총 보상은 각 구성 요소가 총 보상에 얼마나 기여하는지를 결정하는 가중치를 갖는 5개 구성 요소의 합으로 계산됩니다. 구성 요소는 다음과 같습니다. + +``` +1. 소스 투표: 검증자가 올바른 소스 체크포인트에 대해 시기적절하게 투표했습니다. +2. 타겟 투표: 검증자가 올바른 타겟 체크포인트에 대해 시기적절하게 투표했습니다. +3. 헤드 투표: 검증자가 올바른 헤드 블록에 대해 시기적절하게 투표했습니다. +4. 동기화 위원회 보상: 검증자가 동기화 위원회에 참여했습니다. +5. 제안자 보상: 검증자가 올바른 슬롯에 블록을 제안했습니다. +``` + +각 구성 요소의 가중치는 다음과 같습니다. + +``` +TIMELY_SOURCE_WEIGHT uint64(14) +TIMELY_TARGET_WEIGHT uint64(26) +TIMELY_HEAD_WEIGHT uint64(14) +SYNC_REWARD_WEIGHT uint64(2) +PROPOSER_WEIGHT uint64(8) +``` + +이 가중치의 합은 64입니다. 보상은 적용 가능한 가중치의 합을 64로 나눈 값으로 계산됩니다. 시기적절한 소스, 타겟 및 헤드 투표를 하고 블록을 제안하고 동기화 위원회에 참여한 검증자는 `64/64 * base_reward == base_reward`를 받을 수 있습니다. 그러나 검증자는 일반적으로 블록 제안자가 아니므로 최대 보상은 `64-8 /64 * base_reward == 7/8 * base_reward`입니다. 블록 제안자도 아니고 동기화 위원회에도 속하지 않은 검증자는 `64-8-2 / 64 * base_reward == 6.75/8 * base_reward`를 받을 수 있습니다. + +신속한 증명을 장려하기 위해 추가 보상이 추가됩니다. 이것은 `inclusion_delay_reward`입니다. 이 값은 `base_reward`에 `1/delay`를 곱한 값과 같으며, 여기서 `delay`는 블록 제안과 증명 사이의 슬롯 수입니다. 예를 들어, 증명이 블록 제안의 한 슬롯 내에 제출되면 증명자는 `base_reward * 1/1 == base_reward`를 받습니다. 증명이 다음 슬롯에 도착하면 증명자는 `base_reward * 1/2`를 받는 식입니다. + +블록 제안자는 블록에 포함된 각 유효한 증명에 대해 `8 / 64 * base_reward`를 받으므로 보상의 실제 가치는 증명하는 검증자의 수에 따라 조정됩니다. 블록 제안자는 제안된 블록에 다른 검증자의 부정 행위 증거를 포함하여 보상을 늘릴 수도 있습니다. 이러한 보상은 검증자의 정직성을 장려하는 '당근'입니다. 삭감을 포함하는 블록 제안자는 `slashed_validators_effective_balance / 512`로 보상받습니다. + +### 페널티 {#penalties} + +지금까지는 완벽하게 잘 행동하는 검증자를 고려했지만, 시기적절하게 헤드, 소스, 타겟 투표를 하지 않거나 느리게 하는 검증자는 어떻게 될까요? + +타겟 및 소스 투표를 놓친 것에 대한 페널티는 증명자가 이를 제출했을 경우 받았을 보상과 동일합니다. 이는 보상이 잔액에 추가되는 대신 동일한 가치가 잔액에서 제거된다는 것을 의미합니다. 헤드 투표를 놓치는 것에 대한 페널티는 없습니다(즉, 헤드 투표는 보상만 받고 페널티는 받지 않습니다). `inclusion_delay`와 관련된 페널티는 없으며, 보상은 단순히 검증자의 잔액에 추가되지 않습니다. 블록 제안에 실패해도 페널티는 없습니다. + +[합의 사양](https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md)에서 보상 및 페널티에 대해 자세히 알아보세요. 보상 및 페널티는 벨라트릭스 업그레이드에서 조정되었습니다. Danny Ryan과 Vitalik이 이 [Peep an EIP 비디오](https://www.youtube.com/watch?v=iaAEGs1DMgQ)에서 이에 대해 논의하는 것을 시청하세요. + +## 삭감 {#slashing} + +삭감은 검증자를 네트워크에서 강제로 제거하고 관련 스테이킹된 이더를 잃게 되는 더 심각한 조치입니다. 검증자가 삭감될 수 있는 세 가지 방법이 있으며, 이 모든 것은 부정직한 블록 제안 또는 증명에 해당합니다. + +- 동일한 슬롯에 대해 두 개의 다른 블록을 제안하고 서명하는 경우 +- 다른 블록을 '둘러싸는' 블록을 증명하는 경우(효과적으로 기록을 변경) +- 동일한 블록에 대해 두 후보에게 증명하여 '이중 투표'하는 경우 + +이러한 행동이 감지되면 검증자는 삭감됩니다. 이는 32 ETH 검증자에 대해 0.0078125가 즉시 소각되고(활성 잔액에 따라 선형적으로 조정), 36일간의 제거 기간이 시작됨을 의미합니다. 이 제거 기간 동안 검증자의 지분은 점차 소진됩니다. 중간 지점(18일)에 추가 페널티가 적용되며, 그 크기는 삭감 이벤트 이전 36일 동안 삭감된 모든 검증자의 총 스테이킹된 이더에 따라 조정됩니다. 이는 더 많은 검증자가 삭감될수록 삭감의 크기가 증가한다는 것을 의미합니다. 최대 삭감액은 삭감된 모든 검증자의 전체 유효 잔액입니다(즉, 많은 검증자가 삭감되면 전체 지분을 잃을 수 있음). 반면에, 단일의 고립된 삭감 이벤트는 검증자 지분의 작은 부분만 소각합니다. 삭감된 검증자의 수에 따라 조정되는 이 중간 지점 페널티를 '상관관계 페널티'라고 합니다. + +## 비활동 유출 {#inactivity-leak} + +합의 레이어가 4 에폭 이상 최종화되지 않은 경우 '비활동 유출'이라는 비상 프로토콜이 활성화됩니다. 비활동 유출의 궁극적인 목표는 체인이 최종성을 회복하는 데 필요한 조건을 만드는 것입니다. 위에서 설명한 바와 같이, 최종성을 위해서는 총 스테이킹된 이더의 2/3 이상이 소스 및 타겟 체크포인트에 동의해야 합니다. 총 검증자의 1/3 이상을 대표하는 검증자가 오프라인 상태가 되거나 올바른 증명을 제출하지 못하면, 2/3의 절대 다수가 체크포인트를 최종화하는 것이 불가능합니다. 비활동 유출은 비활성 검증자에 속한 지분이 총 지분의 1/3 미만을 제어할 때까지 점차적으로 소진되도록 하여 나머지 활성 검증자가 체인을 최종화할 수 있도록 합니다. 비활성 검증자 풀이 아무리 크더라도, 나머지 활성 검증자는 결국 지분의 2/3 이상을 제어하게 됩니다. 지분 손실은 비활성 검증자가 가능한 한 빨리 다시 활성화하도록 하는 강력한 인센티브입니다! 활성 검증자의 66% 미만이 블록체인의 현재 헤드에 대해 합의에 도달했을 때 Medalla 테스트넷에서 비활동 유출 시나리오가 발생했습니다. 비활동 유출이 활성화되었고 결국 최종성이 회복되었습니다! + +합의 메커니즘의 보상, 페널티 및 삭감 설계는 개별 검증자가 올바르게 행동하도록 장려합니다. 그러나 이러한 설계 선택에서 여러 클라이언트에 걸쳐 검증자의 동등한 분배를 강력하게 장려하고 단일 클라이언트 지배를 강력하게 억제하는 시스템이 나타납니다. + +## 더 읽어보기 {#further-reading} + +- [이더리움 업그레이드: 인센티브 레이어](https://eth2book.info/altair/part2/incentives) +- [이더리움의 하이브리드 캐스퍼 프로토콜의 인센티브](https://arxiv.org/pdf/1903.04205.pdf) +- [Vitalik의 주석이 달린 사양](https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md#rewards-and-penalties-1) +- [Eth2 삭감 방지 팁](https://medium.com/prysmatic-labs/eth2-slashing-prevention-tips-f6faa5025f50) +- [EIP-7251에 따른 삭감 페널티 분석](https://ethresear.ch/t/slashing-penalty-analysis-eip-7251/16509) + +_출처_ + +- _[https://benjaminion.xyz/eth2-annotated-spec/phase0/beacon-chain/](https://benjaminion.xyz/eth2-annotated-spec/phase0/beacon-chain/)_ diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/weak-subjectivity/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/weak-subjectivity/index.md new file mode 100644 index 00000000000..855b9b46609 --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/weak-subjectivity/index.md @@ -0,0 +1,39 @@ +--- +title: "약한 주관성" +description: "약한 주관성과 지분 증명 방식 이더리움에서의 역할에 대한 설명." +lang: ko +--- + +블록체인에서 주관성이란 현재 상태를 알아내기 위해 사회적인 정보에 의존하는 것을 의미합니다. 네트워크에서 다른 피어로부터 수집된 정보에 따라 선택되는 유효한 포크가 여러 개 있을 수 있습니다. 반대로 모든 노드가 코드로 짜여진 규칙에 의해 하나의 유효한 체인만을 참조할 수 있는 속성을 객관성이라 부릅니다. 여기에 세 번째 속성인 약한 주관성도 있습니다. 약한 주관성은 일부 초기 정보가 사회적으로 받아들여진 뒤에 객관성을 가지고 진행될 수 있는 체인의 속성을 의미합니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 이해하려면 먼저 [지분 증명](/developers/docs/consensus-mechanisms/pos/)의 기본 사항을 이해해야 합니다. + +## 약한 주관성이 풀고자 하는 문제는 무엇일까요? {#problems-ws-solves} + +지분 증명 방식은 약한 주관성을 내재하고 있는데, 그 이유는 여러 포크들 중에서 올바른 체인을 선택하기 위해 과거 투표 수를 계산하기 때문입니다. 이는 초기에 합의에 참여하던 노드들이 이득을 얻기 위해 과거 블록으로부터 새로운 포크를 만들어서 유지하다가 나중에 공개하는 장거리 공격(long-range attacks)을 포함한 여러 공격 벡터에 블록체인을 노출시킵니다. 또는 검증인의 33%가 지분을 철회했지만 계속해서 블록을 증명하고 생성함으로써 정통(canonical) 체인과 충돌하는 대체 포크를 만들 수 있습니다. 오랫동안 오프라인 상태였던 노드나 새로운 노드는 공격자가 자금을 인출했다는 사실을 인지하지 못할 수 있으므로 공격자는 그들이 잘못된 체인을 따르도록 속일 수 있습니다. 이더리움은 주관성을 최소한으로 줄이는 제약 조건을 적용하는 매커니즘을 통하여 이러한 공격 벡터를 해결할 수 있습니다. + +## 약한 주관성 체크포인트 {#ws-checkpoints} + +약한 주관성은 지분 증명 이더리움에서 "약한 주관성 체크포인트"를 통해 구현됩니다. 이는 네트워크의 모든 노드가 정통 체인에 속한다고 합의하는 상태 루트들을 말합니다. 이는 제네시스 블록과 동일한 "보편적 진실"의 목적을 수행하지만 블록체인의 제네시스 위치에 있지는 않다는 점이 다릅니다. 포크 선택 알고리즘은 해당 체크포인트에 정의된 블록체인 상태가 정확하다고 간주하고 그로부터 진행되는 체인을 독립적이고 객관적으로 검증한다고 가정합니다. 약한 주관성 체크포인트 이전에 생성된 블록들은 변경될 수 없기 때문에 체크포인트는 "한계 환원점"의 역할을 합니다. 이는 메커니즘 설계의 일부로 장거리 포크(long-range forks)를 유효하지 않은 것으로 정의하는 것만으로 장거리 공격(long-range attack)을 약화시킵니다. 약한 주관성 체크포인트가 검증자 인출 기간보다 더 짧은 간격으로 분리되도록 하면, 체인을 포크하는 검증자는 스테이킹을 인출하기 전에 최소 임계치 이상으로 슬래싱당하게 되며, 새로운 참여자는 스테이킹이 인출된 검증자에 의해 잘못된 포크로 유인되지 않게 됩니다. + +## 약한 주관성 체크포인트와 완결된 블록의 차이점 {#difference-between-ws-and-finalized-blocks} + +완결된 블록과 약한 주관성 체크포인트는 이더리움 노드에서 다르게 처리됩니다. 노드가 경쟁하는 두 개의 완결된 블록을 인지하게 되면, 둘 사이에서 결정을 내리지 못하게 됩니다. 즉, 어느 것이 정식 포크인지 자동으로 식별할 방법이 없습니다. 이는 합의 실패의 징후입니다. 반면에, 노드는 약한 주관성 체크포인트와 충돌하는 모든 블록을 거부합니다. 노드의 관점에서 약한 주관성 체크포인트는 피어로부터 얻는 새로운 정보에 의해 훼손될 수 없는 절대적인 진실을 나타냅니다. + +## 어느 정도로 약한가요? {#how-weak-is-weak} + +이더리움 지분 증명의 주관적인 측면은 동기화를 위해 신뢰할 수 있는 출처의 최신 상태(약한 주관성 체크포인트)가 필요하다는 점입니다. 블록 탐색기나 다수의 노드와 같은 여러 독립적인 공개 출처와 대조하여 확인할 수 있으므로, 잘못된 약한 주관성 체크포인트를 받을 위험은 매우 낮습니다. 하지만 모든 소프트웨어 애플리케이션을 실행하려면 어느 정도의 신뢰가 필요합니다. 예를 들어, 소프트웨어 개발자가 정직한 소프트웨어를 만들었다고 신뢰하는 것과 같습니다. + +약한 주관성 체크포인트는 클라이언트 소프트웨어의 일부로 제공될 수도 있습니다. 공격자는 소프트웨어의 체크포인트를 손상시킬 수 있으며, 마찬가지로 소프트웨어 자체도 쉽게 손상시킬 수 있다고 주장할 수 있습니다. 이 문제에 대한 실질적인 암호경제학적 해결책은 없지만, 이더리움에서는 여러 독립적인 클라이언트 팀을 둠으로써 신뢰할 수 없는 개발자의 영향을 최소화합니다. 각 팀은 서로 다른 언어로 동등한 소프트웨어를 구축하며, 모두 정직한 체인을 유지하는 데 이해관계가 있습니다. 블록 탐색기는 약한 주관성 체크포인트를 제공하거나, 다른 곳에서 얻은 체크포인트를 추가적인 출처와 교차 참조할 수 있는 방법을 제공할 수도 있습니다. + +마지막으로, 다른 노드에 체크포인트를 요청할 수 있습니다. 예를 들어, 풀노드를 실행하는 다른 이더리움 사용자가 체크포인트를 제공하면, 검증자는 블록 탐색기의 데이터와 대조하여 이를 확인할 수 있습니다. 전반적으로, 약한 주관성 체크포인트 제공자를 신뢰하는 것은 클라이언트 개발자를 신뢰하는 것만큼 문제가 될 수 있다고 간주할 수 있습니다. 필요한 전반적인 신뢰 수준은 낮습니다. 이러한 고려 사항은 대다수의 검증자가 공모하여 블록체인의 대체 포크를 생성하는, 발생 가능성이 매우 낮은 경우에만 중요해진다는 점에 유의해야 합니다. 그 외의 모든 상황에서는 선택할 수 있는 이더리움 체인은 단 하나뿐입니다. + +## 추가 정보 {#further-reading} + +- [Eth2의 약한 주관성](https://notes.ethereum.org/@adiasg/weak-subjectvity-eth2) +- [비탈릭: 내가 어떻게 약한 주관성을 사랑하게 되었는가](https://blog.ethereum.org/2014/11/25/proof-stake-learned-love-weak-subjectivity/) +- [약한 주관성(Teku 문서)](https://docs.teku.consensys.io/concepts/weak-subjectivity) +- [0단계 약한 주관성 가이드](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/weak-subjectivity.md) +- [이더리움 2.0의 약한 주관성 분석](https://github.com/runtimeverification/beacon-chain-verification/blob/master/weak-subjectivity/weak-subjectivity-analysis.pdf) diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/withdrawal-credentials/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/withdrawal-credentials/index.md new file mode 100644 index 00000000000..9d3a90a2672 --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pos/withdrawal-credentials/index.md @@ -0,0 +1,64 @@ +--- +title: "출금 자격 증명" +description: "검증자 출금 증명서 유형(0x00, 0x01, 0x02)과 이더리움 스테이커에 대한 의미에 대한 설명입니다." +lang: ko +--- + +모든 검증자는 스테이킹된 ETH와 보상을 어떻게 그리고 어디로 출금할 수 있는지를 결정하는 출금 증명서를 가지고 있습니다. 증명서 유형은 첫 번째 바이트 `0x00`, `0x01` 또는 `0x02`로 표시됩니다. 이러한 유형을 이해하는 것은 스테이킹을 관리하는 검증자에게 중요합니다. + +## 0x00: 샤펠라 이전 증명서 {#0x00-credentials} + +`0x00` 유형은 샤펠라 업그레이드(2023년 4월) 이전의 원래 출금 증명서 형식입니다. 이 증명서 유형을 가진 검증자는 실행 레이어 출금 주소가 설정되어 있지 않으므로 자금이 합의 레이어에 잠겨 있습니다. 만약 아직 `0x00` 증명서를 가지고 있다면, 출금을 받기 전에 `0x01` 또는 `0x02`로 업그레이드해야 합니다. + +## 0x01: 레거시 출금 증명서 {#0x01-credentials} + +`0x01` 유형은 샤펠라 업그레이드와 함께 도입되었으며, 실행 레이어 출금 주소를 설정하고자 하는 검증자를 위한 표준이 되었습니다. `0x01` 증명서의 경우: + +- 32 ETH를 초과하는 잔액은 출금 주소로 **자동으로 스윕됩니다** +- 전체 출금은 표준 출금 대기열을 거칩니다. +- 32 ETH를 초과하는 보상은 복리 적용이 불가능하며, 주기적으로 스윕됩니다. + +**일부 검증자가 0x01을 계속 사용하는 이유:** 더 간단하고 익숙하기 때문입니다. 많은 검증자들이 샤펠라 이후 예치하여 이미 이 유형을 가지고 있으며, 초과 잔액의 자동 출금을 원하는 사람들에게는 잘 작동합니다. + +**권장되지 않는 이유:** `0x01`을 사용하면 32 ETH를 초과하는 보상을 복리로 운용할 수 없게 됩니다. 모든 초과분은 자동으로 스윕되어 검증자의 수익 잠재력을 제한하고, 출금된 자금을 별도로 관리해야 합니다. + +## 0x02: 복리 출금 증명서 {#0x02-credentials} + +`0x02` 유형은 펙트라 업그레이드와 함께 도입되었으며, 오늘날 검증자들에게 권장되는 선택입니다. `0x02` 증명서를 가진 검증자는 때때로 "복리 검증자"라고 불립니다. + +`0x02` 증명서의 경우: + +- 32 ETH를 초과하는 보상은 최대 유효 잔액 2048 ETH까지 1 ETH 단위로 **복리** 적용됩니다. +- 부분 출금은 수동으로 요청해야 합니다(자동 스윕은 2048 ETH 임계값을 초과하는 경우에만 발생합니다). +- 검증자는 여러 32 ETH 검증자를 하나의 더 높은 잔액을 가진 검증자로 통합할 수 있습니다. +- 전체 출금은 여전히 표준 출금 대기열을 통해 지원됩니다. + +부분 출금과 통합은 모두 [런치패드 검증자 작업](https://launchpad.ethereum.org/en/validator-actions)을 통해 수행할 수 있습니다. + +**검증자가 0x02를 선호해야 하는 이유:** 복리를 통한 더 나은 자본 효율성, 출금 시점에 대한 더 많은 제어, 그리고 검증자 통합을 지원하기 때문입니다. 시간이 지남에 따라 보상을 축적하는 단독 스테이커의 경우, 이는 수동 개입 없이 유효 잔액, 즉 보상이 32 ETH를 초과하여 증가할 수 있음을 의미합니다. + +**중요:** `0x01`에서 `0x02`로 전환하면 다시 되돌릴 수 없습니다. + +유형 2 증명서로 전환하는 방법과 MaxEB 기능에 대한 자세한 가이드는 [MaxEB 설명 페이지](/roadmap/pectra/maxeb/)를 참조하세요. + +## 무엇을 선택해야 할까요? {#what-should-i-pick} + +- **신규 검증자:** `0x02`를 선택하세요. 더 나은 복리 및 유연성을 갖춘 최신 표준입니다. +- **기존 0x01 검증자:** 32 ETH를 초과하는 보상을 복리로 운용하거나 검증자를 통합할 계획이라면 `0x02`로의 전환을 고려해 보세요. +- **기존 0x00 검증자:** 즉시 업그레이드하세요. 증명서를 업데이트하지 않으면 출금할 수 없습니다. 먼저 `0x01`로 전환한 다음 `0x02`로 전환해야 합니다. + +## 출금 증명서 관리 도구 {#withdrawal-credential-tools} + +몇 가지 도구가 증명서 유형 간의 선택 또는 전환을 지원합니다: + +- **[이더리움 스테이킹 런치패드](https://launchpad.ethereum.org/en/validator-actions)** - 증명서 전환 및 통합을 포함한 예금 및 검증자 관리를 위한 공식 도구입니다. +- **[Pectra 스테이킹 매니저](https://pectrastaking.com)** - 전환 및 통합을 위한 지갑 연결을 지원하는 웹 UI +- **[Pectra 검증자 운영 CLI 도구](https://github.com/Luganodes/Pectra-Batch-Contract)** - 일괄 전환을 위한 명령줄 도구 +- **[Ethereal](https://github.com/wealdtech/ethereal)** - 검증자 관리를 포함한 이더리움 운영을 위한 CLI 도구 + +통합 도구의 전체 목록과 자세한 전환 지침은 [MaxEB 통합 툴링](/roadmap/pectra/maxeb/#consolidation-tooling)을 참조하세요. + +## 더 읽어보기 {#further-reading} + +- [지분 증명 이더리움의 키](/developers/docs/consensus-mechanisms/pos/keys/) - 검증자 키와 출금 증명서와의 관계에 대해 알아보세요. +- [MaxEB](/roadmap/pectra/maxeb/) - 펙트라 업그레이드 및 최대 유효 잔액 기능에 대한 상세 가이드 diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/index.md new file mode 100644 index 00000000000..19b9d420a4d --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/index.md @@ -0,0 +1,114 @@ +--- +title: "작업 증명(Proof-of-work, PoW)" +description: "이더리움에서 작업 증명 합의 프로토콜과 그 역할에 대한 설명." +lang: ko +--- + +이더리움 네트워크는 [작업 증명(PoW)](/developers/docs/consensus-mechanisms/pow)이 포함된 합의 메커니즘을 사용하여 시작되었습니다. 이를 통해 이더리움 네트워크의 노드들은 이더리움 블록체인에 기록된 모든 정보 상태에 대해 합의하고, 특정 경제적 공격을 방지할 수 있었습니다. 하지만 이더리움은 2022년에 작업 증명을 중단하고 대신 [지분 증명](/developers/docs/consensus-mechanisms/pos)을 사용하기 시작했습니다. + + + + + + 작업 증명은 이제 더 이상 사용되지 않습니다. 이더리움은 더 이상 작업 증명을 합의 메커니즘으로 사용하지 않습니다. 대신 지분 증명을 사용합니다. [지분 증명](/developers/docs/consensus-mechanisms/pos/) 및 [스테이킹](/staking/)에 대해 자세히 알아보세요. + + + + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하려면 먼저 [트랜잭션](/developers/docs/transactions/), [블록](/developers/docs/blocks/), [합의 메커니즘](/developers/docs/consensus-mechanisms/)에 대해 읽어보시는 것을 추천합니다. + +## 작업 증명(Proof-of-Work, PoW)이란 무엇입니까? {#what-is-pow} + +작업 증명을 활용하는 나카모토 합의는 한때 탈중앙화된 이더리움 네트워크가 계정 잔액 및 트랜잭션 순서와 같은 사항에 대해 합의(즉, 모든 노드가 동의)에 도달할 수 있도록 한 메커니즘이었습니다. 이는 사용자가 자신이 소유한 코인을 "이중 지출"하는 것을 방지하고, 이더리움 체인이 공격이나 조작이 매우 어려워지도록 보장했습니다. 이러한 보안 속성은 이제 [Gasper](/developers/docs/consensus-mechanisms/pos/gasper/)로 알려진 합의 메커니즘을 사용하는 지분 증명에서 비롯됩니다. + +## 작업 증명과 채굴 {#pow-and-mining} + +작업 증명은 작업 증명 블록체인에서 채굴자들이 수행하는 작업의 난이도와 규칙을 설정하는 기본 알고리즘입니다. 채굴은 그 "작업" 자체입니다. 채굴은 유효한 블록을 체인에 추가하는 행위입니다. 이는 체인의 길이가 네트워크가 블록체인의 올바른 포크를 따르는 데 중요한 역할을 하기 때문입니다. 더 많은 "작업"이 수행될수록 체인은 더 길어지며, 블록 번호가 높아지고, 네트워크는 현재 상태에 대한 확신을 더 가질 수 있습니다. + +[채굴에 대한 자세한 정보](/developers/docs/consensus-mechanisms/pow/mining/) + +## 이더리움의 작업 증명은 어떻게 작동했습니까? {#how-it-works} + +이더리움 트랜잭션은 블록에 처리됩니다. 이제 더 이상 사용되지 않는 작업 증명 기반 이더리움에서 각 블록은 다음을 포함했습니다: + +- 블록 난이도 – 예시: 3,324,092,183,262,715 +- mixHash – 예시: `0x44bca881b07a6a09f83b130798072441705d9a665c5ac8bdf2f39a3cdf3bee29` +- nonce – 예시: `0xd3ee432b4fb3d26b` + +이 블록 데이터는 작업 증명과 직접적으로 관련이 있었습니다. + +### 작업 증명에서의 '작업' {#the-work} + +작업 증명 프로토콜인 Ethash는 채굴자들이 블록의 논스를 찾기 위해 강렬한 시도와 실패 과정을 거쳐야 했습니다. 유효한 논스를 가진 블록만 체인에 추가될 수 있었습니다. + +블록을 생성하는 과정에서 채굴자는 전체 체인을 다운로드하고 실행하여 얻을 수 있는 데이터 세트를 반복적으로 수학적 함수에 넣었습니다. 이 데이터 세트는 블록 난이도가 지시하는 목표 아래의 믹스해시를 생성하는 데 사용되었습니다. 이를 해결하는 가장 좋은 방법은 시행착오를 통한 것입니다. + +난이도가 해시 목표를 결정했습니다. 목표가 낮을수록 유효한 해시 집합이 작아집니다. 생성되면 다른 채굴자와 클라이언트가 이를 확인하는 것이 매우 쉬웠습니다. 하나의 트랜잭션이 변경되더라도 해시는 완전히 달라져 사기를 나타냅니다. + +해싱은 사기를 쉽게 발견하게 만듭니다. 그러나 작업 증명 과정은 체인을 공격하는 데 큰 방해 요소였습니다. + +### 작업 증명과 보안 {#security} + +채굴자들은 이더리움 메인 체인에서 이 작업을 수행할 인센티브를 받았습니다. 일부 채굴자가 독자적인 체인을 시작할 인센티브는 거의 없었습니다. 이는 시스템을 약화시킵니다. 블록체인은 진실의 원천으로서 단일 상태를 유지하는 것에 의존합니다. + +작업 증명의 목표는 체인을 확장하는 것이었습니다. 가장 긴 체인이 유효한 것으로 여겨졌습니다. 왜냐하면 그것을 생성하기 위해 가장 많은 계산 작업이 이루어졌기 때문입니다. 이더리움의 작업 증명 시스템 내에서는 트랜잭션을 삭제하거나 가짜 블록을 만들거나 두 번째 체인을 유지하는 것이 거의 불가능했습니다. 그 이유는 악의적인 채굴자가 항상 다른 사람들보다 더 빨리 블록 논스를 풀어야 했기 때문입니다. + +악의적인 채굴자가 일관되게 악의적인 유효 블록을 만들기 위해서는 네트워크 채굴 파워의 51% 이상이 필요했습니다. 그만큼의 "작업"에는 많은 비용이 드는 컴퓨팅 파워가 필요하며, 소모된 에너지가 공격으로 얻은 이익을 초과할 수도 있었습니다. + +### 작업 증명 경제학 {#economics} + +작업 증명은 또한 시스템에 새로운 화폐를 발행하고 채굴자들이 일을 하도록 인센티브를 제공했습니다. + +[콘스탄티노플 업그레이드](/ethereum-forks/#constantinople) 이후, 블록을 성공적으로 생성한 채굴자들은 새로 발행된 ETH 2개와 트랜잭션 수수료의 일부를 보상으로 받았습니다. 오머 블록은 또한 1.75 ETH를 보상받았습니다. 오머 블록은 다른 채굴자가 표준 블록을 생성한 것과 거의 동시에 생성된 유효한 블록이었으며, 결국 어떤 체인이 먼저 구축되었는지에 따라 결정되었습니다. 오머 블록은 주로 네트워크 지연으로 인해 발생했습니다. + +## 최종 승인 {#finality} + +트랜잭션은 변경될 수 없는 블록의 일부가 될 때 이더리움에서 "최종성"을 갖습니다. + +채굴자들이 분산된 방식으로 작업했기 때문에 두 개의 유효한 블록이 동시에 채굴될 수 있었습니다. 이는 일시적인 포크를 만듭니다. 결국, 후속 블록이 채굴되어 체인에 추가되면서 이 체인들 중 하나가 더 길어져서 승인된 체인이 됩니다. + +상황을 더 복잡하게 만드는 것은 임시 포크에서 거부된 트랜잭션이 승인된 체인에 포함되지 않았을 수 있다는 것입니다. 이는 되돌려질 수 있음을 의미합니다. 따라서 최종성은 트랜잭션이 되돌릴 수 없다고 간주하기 전에 기다려야 하는 시간을 나타냅니다. 이전의 작업 증명 이더리움에서는 특정 블록 `N` 위에 더 많은 블록이 채굴될수록 `N`의 트랜잭션이 성공적이며 되돌려지지 않을 것이라는 확신이 높아졌습니다. 이제 지분 증명에서는 블록의 최종성이 확률적 특성이 아니라 명시적 특성입니다. + +## 작업 증명의 에너지 사용량 {#energy} + +작업 증명에 대한 주요 비판은 네트워크를 안전하게 유지하는 데 필요한 에너지 소비량입니다. 보안과 탈중앙화를 유지하기 위해 작업 증명 방식의 이더리움은 많은 에너지를 소비했습니다. 지분 증명으로 전환하기 직전, 이더리움 채굴자들은 연간 약 70TWh(체코 공화국과 거의 같은 수준 - 2022년 7월 18일 [digiconomist](https://digiconomist.net/)에 따르면)를 집단적으로 소비하고 있었습니다. + +## 장단점 {#pros-and-cons} + +| 장점 | 단점 | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| 작업 증명은 중립적입니다. 시작할 때 ETH가 필요하지 않으며, 블록 보상을 통해 0ETH에서 긍정적인 잔고로 전환할 수 있습니다. [지분 증명](/developers/docs/consensus-mechanisms/pos/)을 사용하려면 시작하기 위해 ETH가 필요합니다. | 작업 증명은 너무 많은 에너지를 소모하여 환경에 해롭습니다. | +| 작업 증명은 오랜 시간 동안 비트코인과 이더리움을 안전하고 탈중앙화된 상태로 유지한 입증된 합의 메커니즘입니다. | 채굴을 하려면 매우 특수한 장비가 필요하므로 초기 비용이 많이 듭니다. | +| 지분증명과 비교했을 때 구현이 상대적으로 쉽습니다. | 필요한 계산량이 증가함에 따라, 채굴 풀들이 채굴 경쟁에서 우위를 점할 수 있으며, 이로 인해 중앙 집중화와 보안 위험이 발생할 수 있습니다. | + +## 지분 증명과의 비교 {#compared-to-pos} + +높은 수준에서 지분증명은 작업증명과 동일한 최종 목표를 가지고 있습니다: 분산 네트워크가 안전하게 합의에 도달하도록 돕는 것입니다. 그러나 프로세스와 참여자 측면에서 몇 가지 차이점이 있습니다: + +- 지분증명은 계산 능력의 중요성을 스테이킹된 ETH로 대체합니다. +- 지분증명은 채굴자를 검증자로 대체합니다. 검증자는 자신의 ETH를 스테이킹하여 새 블록을 생성할 수 있는 능력을 활성화합니다. +- 최종성은 더 명확해졌습니다: 특정 체크포인트에서 2/3의 검증자가 블록 상태에 동의하면 최종으로 간주됩니다. +- 검증자는 전액을 걸어야 하므로, 나중에 결탁하려고 하면 전액을 잃게 됩니다. 검증자는 전체 스테이크를 걸어야 하며, 만약 나중에 공모를 시도한다면 전체 스테이크를 잃게 됩니다. + +[지분 증명에 대한 자세한 정보](/developers/docs/consensus-mechanisms/pos/) + +## 시각 자료를 찾고 있나요? 시각적 학습자 + + + +## 추가 정보 {#further-reading} + +- [과반수 공격](https://en.bitcoin.it/wiki/Majority_attack) +- [정산 최종 승인에 관하여](https://blog.ethereum.org/2016/05/09/on-settlement-finality/) + +### 동영상 {#videos} + +- [작업 증명 프로토콜에 대한 기술적 설명](https://youtu.be/9V1bipPkCTU) + +## 관련 주제 {#related-topics} + +- [채굴](/developers/docs/consensus-mechanisms/pow/mining/) +- [지분 증명](/developers/docs/consensus-mechanisms/pos/) +- [권위 증명](/developers/docs/consensus-mechanisms/poa/) diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/mining/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/mining/index.md new file mode 100644 index 00000000000..733c7a01a5a --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/mining/index.md @@ -0,0 +1,86 @@ +--- +title: "마이닝" +description: "이더리움에서 채굴이 어떻게 작동했는지 설명합니다." +lang: ko +--- + + + + + +작업증명은 더 이상 이더리움의 합의 메커니즘의 기초가 아니며, 채굴이 중단되었습니다. 대신, 이더리움은 ETH를 스테이킹하는 검증자에 의해 보안이 유지됩니다. 오늘부터 ETH 스테이킹을 시작할 수 있습니다. 더 알아보려면
The Merge, 지분증명, 그리고 스테이킹에 대해 읽어보세요. 이 페이지는 역사적인 참고만을 위한 것입니다. + + + + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하려면 먼저 [트랜잭션](/developers/docs/transactions/), [블록](/developers/docs/blocks/) 및 [작업 증명](/developers/docs/consensus-mechanisms/pow/)에 대해 읽어보는 것을 권장합니다. + +## 이더리움 채굴이란 무엇인가요? {#what-is-ethereum-mining} + +채굴은 더 이상 이더리움의 작업증명 아키텍처에서 블록체인에 추가할 트랜잭션 블록을 생성하는 과정입니다. + +채굴이라는 단어는 암호화폐에 대한 금 비유에서 유래했습니다. 금이나 귀금속은 희소하듯이 디지털 토큰도 마찬가지이며, 작업증명 시스템에서는 채굴을 통해서만 총 발행량을 늘릴 수 있습니다. 작업증명 이더리움에서 유일한 발행 방법은 채굴을 통한 것이었습니다. 그러나 금이나 귀금속과 달리, 이더리움 채굴은 또한 블록체인에서 블록을 생성하고, 검증하고, 발표하며, 전파하는 방식으로 네트워크를 보안하는 방법이었습니다. + +이더 채굴은 네트워크 보안과 같습니다. + +채굴은 작업증명 블록체인의 핵심입니다. 이더리움 채굴자 - 소프트웨어를 실행하는 컴퓨터 - 는 이더리움이 지분증명으로 전환되기 전까지 트랜잭션을 처리하고 블록을 생성하기 위해 시간과 컴퓨팅 자원을 사용했습니다. + +## 채굴자는 왜 존재하나요? {#why-do-miners-exist} + +이더리움과 같은 분산 시스템에서는 모든 사람들이 트랜잭션 순서에 동의하는지 확인해야 합니다. 채굴자는 계산적으로 어려운 퍼즐을 풀어 블록을 생성함으로써 이 과정이 이루어지도록 돕고, 네트워크를 공격으로부터 보호했습니다. + +[작업 증명에 대해 더 알아보기](/developers/docs/consensus-mechanisms/pow/) + +이전에는 누구나 자신의 컴퓨터로 이더리움 네트워크에서 채굴을 할 수 있었습니다. 그러나 모든 사람들이 ETH(이더)를 수익성 있게 채굴할 수 있는 것은 아니었습니다. 대부분의 경우, 채굴자는 전용 컴퓨터 하드웨어를 구입하고, 저렴한 에너지원을 이용해야 했습니다. 일반적인 컴퓨터로는 채굴에 필요한 블록 보상을 얻어 채굴 비용을 충당하기 어렵습니다. + +### 채굴 비용 {#cost-of-mining} + +- 채굴 장비를 구축하고 유지하는 데 필요한 하드웨어의 잠재적 비용 +- 채굴 장비를 운영하는 데 필요한 전기 비용 +- 채굴 풀에서 채굴하는 경우, 이러한 풀은 일반적으로 생성된 블록의 일정 비율을 수수료로 부과했습니다. +- 채굴 장비를 지원하기 위한 장비 비용(환기 장치, 에너지 모니터링, 전기 배선 등) + +채굴 수익성을 더 자세히 알아보려면 [Etherscan](https://etherscan.io/ether-mining-calculator)에서 제공하는 채굴 계산기를 사용하세요. + +## 이더리움 트랜잭션 채굴 방법 {#how-ethereum-transactions-were-mined} + +다음은 이더리움 작업증명에서 트랜잭션이 어떻게 채굴되었는지에 대한 개요를 제공합니다. 이더리움 지분 증명 과정에 대한 유사한 설명은 [여기](/developers/docs/consensus-mechanisms/pos/#transaction-execution-ethereum-pos)에서 확인할 수 있습니다. + +1. 사용자는 일부 [계정](/developers/docs/accounts/)의 개인 키를 사용하여 [트랜잭션](/developers/docs/transactions/) 요청을 작성하고 서명합니다. +2. 사용자는 특정 [노드](/developers/docs/nodes-and-clients/)에서 전체 이더리움 네트워크로 트랜잭션 요청을 브로드캐스트합니다. +3. 이더리움 네트워크의 각 노드는 새로운 트랜잭션 요청에 대해 듣게 되면 해당 요청을 로컬 메모리 풀에 추가합니다. 이 목록은 아직 블록체인에 블록으로 기록되지 않은 모든 트랜잭션 요청을 포함합니다. +4. 어느 시점에서 채굴 노드는 블록 가스 한도 내에서 획득하는 [거래 수수료](/developers/docs/gas/)를 최대화하는 방식으로 수십 또는 수백 개의 트랜잭션 요청을 잠재적 [블록](/developers/docs/blocks/)으로 집계합니다. 그 다음 채굴 노드는: + 1. 각 트랜잭션 요청의 유효성을 검증합니다(예: 서명이 없는 계정에서 이더를 전송하려 하지 않음, 요청이 올바르지 않음 등). 그런 다음 요청의 코드를 실행하여 로컬 EVM 복사본의 상태를 변경합니다. 채굴자는 각 트랜잭션 요청에 대한 수수료를 자신의 계정에 부여합니다. + 2. 블록 내의 모든 트랜잭션 요청이 검증되고 로컬 EVM 복사본에서 실행되면 잠재적인 블록에 대한 작업 증명 "합법성 증명서"를 생성하는 과정을 시작합니다. +5. 결국, 채굴자는 특정 트랜잭션 요청을 포함하는 블록에 대한 증명서를 완성하게 됩니다. 그 다음 채굴자는 새로 주장된 EVM 상태의 증명서와 체크섬을 포함하는 완료된 블록을 브로드캐스트합니다. +6. 다른 노드들은 새로운 블록에 대해 듣게 됩니다. 그들은 인증서를 확인하고, 블록 내 모든 트랜잭션을 직접 실행하며(사용자가 원래 전송한 트랜잭션 포함), 모든 트랜잭션을 실행한 후 새 EVM 상태의 체크섬이 채굴자가 제시한 블록의 상태 체크섬과 일치하는지 확인합니다. 그런 다음 이 노드들은 이 블록을 블록체인의 마지막에 추가하고, 새로운 EVM 상태를 표준 상태로 받아들입니다. +7. 각 노드는 새 블록에 있는 모든 트랜잭션을 자신들의 미완료 트랜잭션 요청 메모리 풀에서 제거합니다. +8. 네트워크에 새로 참여하는 노드들은 모든 블록을 순차적으로 다운로드하며, 여기에는 우리가 관심을 가지는 트랜잭션이 포함된 블록도 있습니다. 그들은 로컬 EVM 사본을 초기화한 후(빈 상태의 EVM으로 시작), 로컬 EVM 사본에서 각 블록의 상태 체크섬을 확인하면서 모든 블록의 트랜잭션을 실행합니다. + +모든 트랜잭션은 한 번 채굴되지만(새 블록에 포함되고 처음 전파됨), 표준 EVM 상태를 갱신하는 과정에서 모든 참가자가 트랜잭션을 실행하고 검증합니다. 이는 블록체인의 핵심 원칙 중 하나인 '신뢰하지 말고 검증하라'를 강조합니다. + +## 옴머(엉클) 블록 {#ommer-blocks} + +작업 증명(Proof-of-Work)에서 블록 채굴은 확률적이었으며, 네트워크 지연으로 인해 때때로 두 개의 유효한 블록이 동시에 게시되었습니다. 이 경우, 프로토콜은 가장 긴(따라서 가장 "유효한") 체인을 결정해야 했으며, 포함되지 않은 유효한 블록을 제안한 채굴자에게 부분적으로 보상하여 공정성을 유지했습니다. 이는 지연 시간이 더 길어질 수 있는 소규모 채굴자들이 [옴머](/glossary/#ommer) 블록 보상을 통해 계속해서 수익을 창출할 수 있게 하여 네트워크의 탈중앙화를 더욱 촉진했습니다. + +"옴머"라는 용어는 부모 블록의 형제 블록에 대한 성 중립적인 용어로 선호되지만, 때때로 "uncle"로도 불립니다. **이더리움이 지분 증명으로 전환된 이후에는 각 슬롯에서 단 한 명의 제안자만 선출되므로 옴머 블록은 더 이상 채굴되지 않습니다.** 채굴된 옴머 블록의 [과거 차트](https://ycharts.com/indicators/ethereum_uncle_rate)를 보면 이러한 변화를 확인할 수 있습니다. + +## 시각적 데모 {#a-visual-demo} + +오스틴이 작업 증명 블록체인을 채굴하는 과정을 안내하는 영상을 시청하세요. + + + +## 채굴 알고리즘 {#mining-algorithm} + +이더리움 메인넷은 오직 하나의 채굴 알고리즘인 ['Ethash'](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/ethash/)만을 사용했습니다. Ethash는 ['Dagger-Hashimoto'](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto/)로 알려진 기존 R&D 알고리즘의 후속 버전이었습니다. + +[채굴 알고리즘에 대해 더 알아보기](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/). + +## 관련 주제 {#related-topics} + +- [가스](/developers/docs/gas/) +- [EVM](/developers/docs/evm/) +- [작업 증명](/developers/docs/consensus-mechanisms/pow/) diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto/index.md new file mode 100644 index 00000000000..5c942b519b3 --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto/index.md @@ -0,0 +1,329 @@ +--- +title: Dagger-Hashimoto +description: "Dagger-Hashimoto 알고리즘에 대한 상세 설명." +lang: ko +--- + +Dagger-Hashimoto는 이더리움의 채굴 알고리즘에 대한 최초의 연구 구현이자 사양이었습니다. Dagger-Hashimoto는 [Ethash](#ethash)로 대체되었습니다. 2022년 9월 15일 [병합](/roadmap/merge/)으로 채굴이 완전히 중단되었습니다. 그 이후로 이더리움은 대신 [지분 증명](/developers/docs/consensus-mechanisms/pos) 메커니즘을 사용하여 보호되고 있습니다. 이 페이지는 역사적 관심사를 위한 것으로, 여기에 있는 정보는 병합 이후 이더리움과 더 이상 관련이 없습니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하기 위해, 먼저 [작업 증명 합의](/developers/docs/consensus-mechanisms/pow), [채굴](/developers/docs/consensus-mechanisms/pow/mining), [채굴 알고리즘](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms)에 대해 읽어보시는 것을 권장합니다. + +## Dagger-Hashimoto {#dagger-hashimoto} + +Dagger-Hashimoto는 두 가지 목표를 만족시키는 것을 목표로 합니다. + +1. **ASIC 저항성**: 알고리즘을 위한 특수 하드웨어를 제작함으로써 얻는 이점은 가능한 한 작아야 합니다. +2. **라이트 클라이언트 검증 가능성**: 블록은 라이트 클라이언트에 의해 효율적으로 검증될 수 있어야 합니다. + +추가적인 수정을 통해, 원할 경우 세 번째 목표를 달성하는 방법도 명시하지만, 추가적인 복잡성을 대가로 합니다: + +**전체 체인 저장**: 채굴은 전체 블록체인 상태의 저장을 요구해야 합니다(이더리움 상태 트라이의 불규칙한 구조로 인해, 특히 자주 사용되는 일부 계약에 대한 일부 가지치기가 가능할 것으로 예상하지만, 이를 최소화하고자 합니다). + +## DAG 생성 {#dag-generation} + +알고리즘 코드는 아래 Python으로 정의됩니다. 먼저, 지정된 정밀도의 부호 없는 정수를 문자열로 마샬링하기 위한 `encode_int`를 제공합니다. 그것의 역함수도 다음과 같습니다: + +```python +NUM_BITS = 512 + +def encode_int(x): + "빅 엔디안 방식을 사용하여 정수 x를 64자 문자열로 인코딩합니다" + o = '' + for _ in range(NUM_BITS / 8): + o = chr(x % 256) + o + x //= 256 + return o + +def decode_int(s): + "빅 엔디안 방식을 사용하여 문자열에서 정수 x를 디코딩합니다" + x = 0 + for c in s: + x *= 256 + x += ord(c) + return x +``` + +다음으로, `sha3`는 정수를 입력받아 정수를 출력하는 함수이고, `dbl_sha3`는 double-sha3 함수라고 가정합니다. 이 참조 코드를 구현으로 변환하는 경우 다음을 사용하십시오. + +```python +from pyethereum import utils +def sha3(x): + if isinstance(x, (int, long)): + x = encode_int(x) + return decode_int(utils.sha3(x)) + +def dbl_sha3(x): + if isinstance(x, (int, long)): + x = encode_int(x) + return decode_int(utils.sha3(utils.sha3(x))) +``` + +### 파라미터 {#parameters} + +알고리즘에 사용되는 파라미터는 다음과 같습니다. + +```python +SAFE_PRIME_512 = 2**512 - 38117 # 2**512보다 작은 가장 큰 안전 소수 + +params = { + "n": 4000055296 * 8 // NUM_BITS, # 데이터세트 크기 (4기가바이트); 65536의 배수여야 함 + "n_inc": 65536, # 기간당 n 값의 증가량; 65536의 배수여야 함 + # epochtime=20000이면 연간 882MB 성장 + "cache_size": 2500, # 라이트 클라이언트의 캐시 크기 (라이트 클라이언트가 선택할 수 있음; 알고리즘 사양의 일부가 아님) + "diff": 2**14, # 난이도 (블록 평가 중 조정됨) + "epochtime": 100000, # 에폭의 길이(블록 단위) (데이터세트가 업데이트되는 빈도) + "k": 1, # 노드의 부모 수 + "w": w, # 모듈러 지수화 해싱에 사용됨 + "accesses": 200, # hashimoto 동안 데이터세트 접근 횟수 + "P": SAFE_PRIME_512 # 해싱 및 난수 생성을 위한 안전 소수 +} +``` + +이 경우 `P`는 `log₂(P)`가 512보다 약간 작게 선택된 소수이며, 이는 우리가 숫자를 나타내는 데 사용해 온 512비트에 해당합니다. 실제로 DAG의 후반부만 저장하면 되므로 사실상의 RAM 요구 사항은 1GB에서 시작하여 매년 441MB씩 증가합니다. + +### Dagger 그래프 구축 {#dagger-graph-building} + +Dagger 그래프 구축 기본 요소는 다음과 같이 정의됩니다. + +```python +def produce_dag(params, seed, length): + P = params["P"] + picker = init = pow(sha3(seed), params["w"], P) + o = [init] + for i in range(1, length): + x = picker = (picker * init) % P + for _ in range(params["k"]): + x ^= o[x % i] + o.append(pow(x, params["w"], P)) + return o +``` + +기본적으로, 그래프는 단일 노드인 `sha3(seed)`로 시작하며, 거기서부터 무작위 이전 노드를 기반으로 순차적으로 다른 노드를 추가하기 시작합니다. 새 노드가 생성될 때, 시드의 모듈러 거듭제곱이 계산되어 `i`보다 작은 일부 인덱스를 무작위로 선택하고(위의 `x % i` 사용), 해당 인덱스의 노드 값은 `x`에 대한 새로운 값을 생성하기 위한 계산에 사용됩니다. 그런 다음 이 값은 작은 작업 증명(PoW) 함수(XOR 기반)에 입력되어 궁극적으로 인덱스 `i`에서 그래프의 값을 생성합니다. 이 특정 설계의 근거는 DAG의 순차적 접근을 강제하는 것입니다. 접근할 다음 DAG의 값은 현재 값이 알려질 때까지 결정될 수 없습니다. 마지막으로, 모듈러 지수화는 결과를 추가로 해시합니다. + +이 알고리즘은 수론의 여러 결과에 의존합니다. 자세한 내용은 아래 부록을 참조하십시오. + +## 라이트 클라이언트 평가 {#light-client-evaluation} + +위의 그래프 구성은 그래프의 각 노드가 적은 수의 노드로 구성된 하위 트리를 계산하고 소량의 보조 메모리만 필요로 하여 재구성될 수 있도록 합니다. k=1일 때 하위 트리는 DAG의 첫 번째 요소까지 올라가는 값의 체인일 뿐이라는 점에 유의하십시오. + +DAG에 대한 라이트 클라이언트 계산 함수는 다음과 같이 작동합니다. + +```python +def quick_calc(params, seed, p): + w, P = params["w"], params["P"] + cache = {} + + def quick_calc_cached(p): + if p in cache: + pass + elif p == 0: + cache[p] = pow(sha3(seed), w, P) + else: + x = pow(sha3(seed), (p + 1) * w, P) + for _ in range(params["k"]): + x ^= quick_calc_cached(x % p) + cache[p] = pow(x, w, P) + return cache[p] + + return quick_calc_cached(p) +``` + +기본적으로 이것은 전체 DAG의 값을 계산하는 루프를 제거하고 이전 노드 조회를 재귀 호출 또는 캐시 조회로 대체하는 위 알고리즘의 재작성일 뿐입니다. `k=1`의 경우 캐시는 불필요하지만, 추가 최적화는 실제로 DAG의 처음 몇 천 개 값을 미리 계산하고 이를 계산을 위한 정적 캐시로 유지합니다. 이에 대한 코드 구현은 부록을 참조하십시오. + +## DAG의 이중 버퍼 {#double-buffer} + +풀 클라이언트에서는 위 공식에 의해 생성된 2개의 DAG로 구성된 [_이중 버퍼_](https://wikipedia.org/wiki/Multiple_buffering)가 사용됩니다. 아이디어는 위 파라미터에 따라 매 `epochtime` 수의 블록마다 DAG가 생성된다는 것입니다. 클라이언트는 가장 최근에 생성된 DAG를 사용하는 대신 이전 DAG를 사용합니다. 이것의 이점은 채굴자들이 갑자기 모든 데이터를 재계산해야 하는 단계를 통합할 필요 없이 시간이 지남에 따라 DAG를 교체할 수 있다는 것입니다. 그렇지 않으면, 일정한 간격으로 체인 처리 속도가 갑자기 일시적으로 느려지고 중앙화가 급격히 증가할 가능성이 있습니다. 따라서 모든 데이터가 재계산되기 전 몇 분 안에 51% 공격 위험이 있습니다. + +블록에 대한 작업을 계산하는 데 사용되는 DAG 세트를 생성하는 데 사용되는 알고리즘은 다음과 같습니다. + +```python +def get_prevhash(n): + from pyethereum.blocks import GENESIS_PREVHASH + from pyethereum import chain_manager + if n <= 0: + return hash_to_int(GENESIS_PREVHASH) + else: + prevhash = chain_manager.index.get_block_by_number(n - 1) + return decode_int(prevhash) + +def get_seedset(params, block): + seedset = {} + seedset["back_number"] = block.number - (block.number % params["epochtime"]) + seedset["back_hash"] = get_prevhash(seedset["back_number"]) + seedset["front_number"] = max(seedset["back_number"] - params["epochtime"], 0) + seedset["front_hash"] = get_prevhash(seedset["front_number"]) + return seedset + +def get_dagsize(params, block): + return params["n"] + (block.number // params["epochtime"]) * params["n_inc"] + +def get_daggerset(params, block): + dagsz = get_dagsize(params, block) + seedset = get_seedset(params, block) + if seedset["front_hash"] <= 0: + # 백 버퍼를 사용할 수 없으므로 프론트 버퍼만 만듭니다 + return {"front": {"dag": produce_dag(params, seedset["front_hash"], dagsz), + "block_number": 0}} + else: + return {"front": {"dag": produce_dag(params, seedset["front_hash"], dagsz), + "block_number": seedset["front_number"]}, + "back": {"dag": produce_dag(params, seedset["back_hash"], dagsz), + "block_number": seedset["back_number"]}} +``` + +## Hashimoto {#hashimoto} + +원래 Hashimoto의 아이디어는 블록체인을 데이터세트로 사용하여, 블록체인에서 N개의 인덱스를 선택하고, 해당 인덱스에서 트랜잭션을 수집하고, 이 데이터의 XOR을 수행한 다음 결과의 해시를 반환하는 계산을 수행하는 것입니다. 일관성을 위해 Python으로 번역된 Thaddeus Dryja의 원본 알고리즘은 다음과 같습니다. + +```python +def orig_hashimoto(prev_hash, merkle_root, list_of_transactions, nonce): + hash_output_A = sha256(prev_hash + merkle_root + nonce) + txid_mix = 0 + for i in range(64): + shifted_A = hash_output_A >> i + transaction = shifted_A % len(list_of_transactions) + txid_mix ^= list_of_transactions[transaction] << i + return txid_mix ^ (nonce << 192) +``` + +불행히도 Hashimoto는 RAM 하드로 간주되지만 256비트 산술에 의존하므로 상당한 계산 오버헤드가 발생합니다. 그러나 Dagger-Hashimoto는 이 문제를 해결하기 위해 데이터세트를 인덱싱할 때 최하위 64비트만 사용합니다. + +```python +def hashimoto(dag, dagsize, params, header, nonce): + m = dagsize / 2 + mix = sha3(encode_int(nonce) + header) + for _ in range(params["accesses"]): + mix ^= dag[m + (mix % 2**64) % m] + return dbl_sha3(mix) +``` + +이중 SHA3를 사용하면 제로 데이터, 거의 즉각적인 사전 검증이 가능하며, 올바른 중간값이 제공되었는지 여부만 확인합니다. 이 외부 작업 증명(PoW) 레이어는 ASIC 친화적이며 상당히 약하지만, 즉시 거부되지 않는 블록을 생성하기 위해 소량의 작업을 수행해야 하므로 DDoS 공격을 더욱 어렵게 만듭니다. 다음은 라이트 클라이언트 버전입니다. + +```python +def quick_hashimoto(seed, dagsize, params, header, nonce): + m = dagsize // 2 + mix = sha3(nonce + header) + for _ in range(params["accesses"]): + mix ^= quick_calc(params, seed, m + (mix % 2**64) % m) + return dbl_sha3(mix) +``` + +## 채굴 및 검증 {#mining-and-verifying} + +이제 이 모든 것을 채굴 알고리즘으로 종합해 보겠습니다. + +```python +def mine(daggerset, params, block): + from random import randint + nonce = randint(0, 2**64) + while 1: + result = hashimoto(daggerset, get_dagsize(params, block), + params, decode_int(block.prevhash), nonce) + if result * params["diff"] < 2**256: + break + nonce += 1 + if nonce >= 2**64: + nonce = 0 + return nonce +``` + +다음은 검증 알고리즘입니다. + +```python +def verify(daggerset, params, block, nonce): + result = hashimoto(daggerset, get_dagsize(params, block), + params, decode_int(block.prevhash), nonce) + return result * params["diff"] < 2**256 +``` + +라이트 클라이언트 친화적인 검증: + +```python +def light_verify(params, header, nonce): + seedset = get_seedset(params, block) + result = quick_hashimoto(seedset["front_hash"], get_dagsize(params, block), + params, decode_int(block.prevhash), nonce) + return result * params["diff"] < 2**256 +``` + +또한 Dagger-Hashimoto는 블록 헤더에 추가 요구 사항을 부과합니다. + +- 2계층 검증이 작동하려면 블록 헤더에 Nonce와 pre-sha3 중간값이 모두 있어야 합니다. +- 블록 헤더 어딘가에 현재 시드셋의 sha3을 저장해야 합니다. + +## 더 읽어보기 {#further-reading} + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 부록 {#appendix} + +위에서 언급했듯이 DAG 생성에 사용되는 RNG는 수론의 몇 가지 결과에 의존합니다. 첫째, `picker` 변수의 기초가 되는 Lehmer RNG가 넓은 주기를 가짐을 보장합니다. 둘째, `x ∈ [2,P-2]`에서 시작하는 경우 `pow(x,3,P)`가 `x`를 `1` 또는 `P-1`에 매핑하지 않음을 보여줍니다. 마지막으로, `pow(x,3,P)`가 해싱 함수로 취급될 때 충돌률이 낮다는 것을 보여줍니다. + +### 레머 난수 생성기 {#lehmer-random-number} + +`produce_dag` 함수는 편향되지 않은 난수를 생성할 필요는 없지만, `seed**i % P`가 소수의 값만 취한다는 잠재적인 위협이 있습니다. 이는 패턴을 인식하는 채굴자에게 그렇지 않은 채굴자보다 이점을 제공할 수 있습니다. + +이를 피하기 위해 수론의 결과를 이용합니다. [_안전 소수_](https://en.wikipedia.org/wiki/Safe_prime)는 `(P-1)/2`도 소수인 소수 `P`로 정의됩니다. [곱셈 그룹](https://en.wikipedia.org/wiki/Multiplicative_group_of_integers_modulo_n) `ℤ/nℤ`의 멤버 `x`의 위수
xᵐ mod P ≡ 1
인 최소 `m`으로 정의됩니다. +이러한 정의가 주어지면 다음과 같습니다. + +> 관찰 1. 안전 소수 `P`에 대해 `x`를 곱셈 그룹 `ℤ/Pℤ`의 멤버라고 합시다. 만약 `x mod P ≠ 1 mod P`이고 `x mod P ≠ P-1 mod P`이면, `x`의 위수는 `P-1` 또는 `(P-1)/2`입니다. + +_증명_. `P`가 안전 소수이므로 [라그랑주의 정리][lagrange]에 따라 `x`의 위수는 `1`, `2`, `(P-1)/2` 또는 `P-1` 중 하나입니다. + +`x`의 위수는 `1`이 될 수 없습니다. 페르마의 소정리에 따르면 다음과 같습니다. + +
xP-1 mod P ≡ 1
+ +따라서 `x`는 `ℤ/nℤ`의 곱셈 항등원이어야 하며, 이는 유일합니다. 가정에 따라 `x ≠ 1`이라고 가정했으므로 이는 불가능합니다. + +`x`의 위수는 `x = P-1`이 아닌 한 `2`가 될 수 없습니다. 이는 `P`가 소수라는 사실에 위배되기 때문입니다. + +위의 명제로부터 `(picker * init) % P`를 반복하면 최소 `(P-1)/2`의 주기 길이를 가질 것임을 알 수 있습니다. 이는 우리가 `P`를 2의 거듭제곱에 가까운 안전 소수로 선택했고, `init`이 `[2,2**256+1]` 구간에 있기 때문입니다. `P`의 크기를 고려할 때, 모듈러 지수화에서 주기가 발생할 것으로 예상해서는 안 됩니다. + +DAG의 첫 번째 셀(변수 `init`)을 할당할 때, `pow(sha3(seed) + 2, 3, P)`를 계산합니다. 언뜻 보기에 이것은 결과가 `1`도 아니고 `P-1`도 아니라는 것을 보장하지 않습니다. 그러나 `P-1`이 안전 소수이므로, 관찰 1의 따름정리인 다음과 같은 추가적인 보장을 얻을 수 있습니다. + +> 관찰 2. 안전 소수 `P`에 대해 `x`를 곱셈 그룹 `ℤ/Pℤ`의 멤버라고 하고, `w`를 자연수라고 합시다. 만약 `x mod P ≠ 1 mod P`이고 `x mod P ≠ P-1 mod P`이며, `w mod P ≠ P-1 mod P`이고 `w mod P ≠ 0 mod P`이면, `xʷ mod P ≠ 1 mod P`이고 `xʷ mod P ≠ P-1 mod P`입니다. + +### 해시 함수로서의 모듈러 지수화 {#modular-exponentiation} + +특정 `P`와 `w` 값에 대해, `pow(x, w, P)` 함수는 많은 충돌을 가질 수 있습니다. 예를 들어, `pow(x,9,19)`는 `{1,18}` 값만 가집니다. + +`P`가 소수라는 점을 감안할 때, 모듈러 지수 해싱 함수에 적합한 `w`는 다음 결과를 사용하여 선택할 수 있습니다. + +> 관찰 3. `P`를 소수라고 할 때, `w`와 `P-1`이 서로소인 것은, `ℤ/Pℤ`에 있는 모든 `a`와 `b`에 대해
`aʷ mod P ≡ bʷ mod P`인 것이 `a mod P ≡ b mod P`인 것과 동치
라는 것입니다. + +따라서 `P`가 소수이고 `w`가 `P-1`과 서로소일 때, `|{pow(x, w, P) : x ∈ ℤ}| = P`가 성립하며, 이는 해싱 함수가 가능한 최소 충돌률을 가짐을 의미합니다. + +우리가 선택한 것처럼 `P`가 안전 소수인 특수한 경우, `P-1`은 1, 2, `(P-1)/2`, `P-1`만을 인수로 가집니다. `P` > 7이므로, 3은 `P-1`과 서로소이며, 따라서 `w=3`은 위 명제를 만족합니다. + +## 보다 효율적인 캐시 기반 평가 알고리즘 {#cache-based-evaluation} + +```python +def quick_calc(params, seed, p): + cache = produce_dag(params, seed, params["cache_size"]) + return quick_calc_cached(cache, params, p) + +def quick_calc_cached(cache, params, p): + P = params["P"] + if p < len(cache): + return cache[p] + else: + x = pow(cache[0], p + 1, P) + for _ in range(params["k"]): + x ^= quick_calc_cached(cache, params, x % p) + return pow(x, params["w"], P) + +def quick_hashimoto(seed, dagsize, params, header, nonce): + cache = produce_dag(params, seed, params["cache_size"]) + return quick_hashimoto_cached(cache, dagsize, params, header, nonce) + +def quick_hashimoto_cached(cache, dagsize, params, header, nonce): + m = dagsize // 2 + mask = 2**64 - 1 + mix = sha3(encode_int(nonce) + header) + for _ in range(params["accesses"]): + mix ^= quick_calc_cached(cache, params, m + (mix & mask) % m) + return dbl_sha3(mix) +``` diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/ethash/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/ethash/index.md new file mode 100644 index 00000000000..726c6954af0 --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/ethash/index.md @@ -0,0 +1,1022 @@ +--- +title: Ethash +description: "이더해시 알고리즘 자세히 살펴보기." +lang: ko +--- + + + + + + Ethash는 이더리움의 작업 증명 채굴 알고리즘이었습니다. 이제 작업 증명은 완전히 중단되었으며, 대신 [지분 증명](/developers/docs/consensus-mechanisms/pos/)을 사용하여 이더리움을 보호합니다. [병합](/roadmap/merge/), [지분 증명](/developers/docs/consensus-mechanisms/pos/), [스테이킹](/staking/)에 대해 자세히 알아보세요. 이 페이지는 역사적 참고 자료로만 제공됩니다! + + + + +이더해시는 [Dagger-Hashimoto](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto) 알고리즘의 수정된 버전입니다. 이더해시 작업 증명은 [메모리 집약적](https://wikipedia.org/wiki/Memory-hard_function)이며, 이는 이 알고리즘을 ASIC 저항적으로 만든다고 여겨졌습니다. 결국 이더해시 ASIC가 개발되었지만, 작업 증명이 중단될 때까지 GPU 채굴은 여전히 실행 가능한 옵션이었습니다. 이더해시는 이더리움이 아닌 다른 작업 증명 네트워크에서 다른 코인을 채굴하는 데 여전히 사용됩니다. + +## 이더해시는 어떻게 작동하나요? {#how-does-ethash-work} + +메모리 집약성은 nonce 및 블록 헤더에 따라 고정된 리소스의 하위 집합을 선택해야 하는 작업 증명 알고리즘을 통해 달성됩니다. 이 리소스(크기는 수 기가바이트)를 DAG라고 합니다. DAG는 30,000 블록마다 변경되며, 에폭(약 5.2일)이라고 하는 약 125시간의 기간이며 생성하는 데 시간이 걸립니다. DAG는 블록 높이에만 의존하기 때문에 사전 생성이 가능하지만, 그렇지 않은 경우 클라이언트는 블록을 생성하기 위해 이 프로세스가 끝날 때까지 기다려야 합니다. 클라이언트가 미리 DAG를 생성하여 캐시하지 않으면 각 에폭 전환 시 네트워크에 엄청난 블록 지연이 발생할 수 있습니다. 작업 증명을 검증하기 위해 DAG를 생성할 필요가 없으므로 낮은 CPU와 적은 메모리로도 검증이 가능합니다. + +알고리즘이 따르는 일반적인 경로는 다음과 같습니다. + +1. 각 블록의 헤더를 해당 지점까지 스캔하여 계산할 수 있는 시드가 존재합니다. +2. 시드에서 16MB 의사 난수 캐시를 계산할 수 있습니다. 라이트 클라이언트는 캐시를 저장합니다. +3. 캐시에서 1GB 데이터세트를 생성할 수 있으며, 데이터세트의 각 항목은 캐시의 적은 수의 항목에만 종속된다는 속성이 있습니다. 풀 클라이언트와 채굴자는 데이터세트를 저장합니다. 데이터세트는 시간에 따라 선형적으로 증가합니다. +4. 채굴에는 데이터세트의 무작위 슬라이스를 가져와 함께 해싱하는 작업이 포함됩니다. 캐시를 사용하여 필요한 데이터세트의 특정 부분을 재생성하여 적은 메모리로 검증할 수 있으므로 캐시만 저장하면 됩니다. + +대용량 데이터세트는 30,000 블록마다 한 번씩 업데이트되므로, 채굴자 노력의 대부분은 데이터세트를 변경하는 것이 아니라 읽는 데 사용됩니다. + +## 정의 {#definitions} + +다음과 같은 정의를 사용합니다. + +``` +WORD_BYTES = 4 # 워드의 바이트 +DATASET_BYTES_INIT = 2**30 # 제네시스의 데이터세트 바이트 +DATASET_BYTES_GROWTH = 2**23 # 에폭당 데이터세트 증가량 +CACHE_BYTES_INIT = 2**24 # 제네시스의 캐시 바이트 +CACHE_BYTES_GROWTH = 2**17 # 에폭당 캐시 증가량 +CACHE_MULTIPLIER=1024 # 캐시에 대한 DAG의 크기 +EPOCH_LENGTH = 30000 # 에폭당 블록 수 +MIX_BYTES = 128 # 믹스 너비 +HASH_BYTES = 64 # 해시 길이(바이트) +DATASET_PARENTS = 256 # 각 데이터세트 요소의 부모 수 +CACHE_ROUNDS = 3 # 캐시 생성 라운드 수 +ACCESSES = 64 # 해시모토 루프의 액세스 수 +``` + +### 'SHA3'의 사용 {#sha3} + +이더리움 개발은 SHA3 표준 개발과 동시에 이루어졌으며, +표준화 과정에서 최종 해시 알고리즘의 패딩이 늦게 변경되어 이더리움의 +'sha3_256' 및 'sha3_512' 해시는 표준 sha3 해시가 아니라 다른 맥락에서 흔히 +'Keccak-256' 및 'Keccak-512'라고 불리는 변형입니다. 예를 들어 [여기](https://eips.ethereum.org/EIPS/eip-1803), [여기](http://ethereum.stackexchange.com/questions/550/which-cryptographic-hash-function-does-ethereum-use), 또는 [여기](http://bitcoin.stackexchange.com/questions/42055/what-is-the-approach-to-calculate-an-ethereum-address-from-a-256-bit-private-key/42057#42057)의 논의를 참조하세요. + +아래 알고리즘 설명에서 'sha3' 해시가 언급되므로 이 점을 유념해 주시기 바랍니다. + +## 파라미터 {#parameters} + +이더해시의 캐시 및 데이터세트 파라미터는 블록 번호에 따라 달라집니다. 캐시 크기와 데이터세트 크기는 모두 선형적으로 증가하지만, 주기적인 동작으로 이어지는 우발적인 규칙성의 위험을 줄이기 위해 선형적으로 증가하는 임계값보다 낮은 가장 높은 소수를 항상 사용합니다. + +```python +def get_cache_size(block_number): + sz = CACHE_BYTES_INIT + CACHE_BYTES_GROWTH * (block_number // EPOCH_LENGTH) + sz -= HASH_BYTES + while not isprime(sz / HASH_BYTES): + sz -= 2 * HASH_BYTES + return sz + +def get_full_size(block_number): + sz = DATASET_BYTES_INIT + DATASET_BYTES_GROWTH * (block_number // EPOCH_LENGTH) + sz -= MIX_BYTES + while not isprime(sz / MIX_BYTES): + sz -= 2 * MIX_BYTES + return sz +``` + +데이터세트 및 캐시 크기 값의 표는 부록에 제공됩니다. + +## 캐시 생성 {#cache-generation} + +이제 캐시를 생성하는 함수를 지정합니다. + +```python +def mkcache(cache_size, seed): + n = cache_size // HASH_BYTES + + # 초기 데이터세트를 순차적으로 생성 + o = [sha3_512(seed)] + for i in range(1, n): + o.append(sha3_512(o[-1])) + + # randmemohash의 낮은 라운드 버전을 사용 + for _ in range(CACHE_ROUNDS): + for i in range(n): + v = o[i][0] % n + o[i] = sha3_512(map(xor, o[(i-1+n) % n], o[v])) + + return o +``` + +캐시 생성 과정은 먼저 32MB의 메모리를 순차적으로 채운 다음, [_엄격한 메모리 집약적 해싱 함수(Strict Memory Hard Hashing Functions)_ (2014)](http://www.hashcash.org/papers/memohash.pdf)에서 Sergio Demian Lerner의 _RandMemoHash_ 알고리즘을 두 번 통과시키는 것을 포함합니다. 출력은 524288개의 64바이트 값 집합입니다. + +## 데이터 집계 함수 {#date-aggregation-function} + +경우에 따라 XOR의 비결합적 대체물로 [FNV 해시](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function)에서 영감을 받은 알고리즘을 사용합니다. 소수에 차례로 1바이트(옥텟)를 곱하는 FNV-1 사양과 달리, 전체 32비트 입력에 소수를 곱한다는 점에 유의하세요. + +```python +FNV_PRIME = 0x01000193 + +def fnv(v1, v2): + return ((v1 * FNV_PRIME) ^ v2) % 2**32 +``` + +옐로페이퍼에서는 fnv를 v1\*(FNV_PRIME ^ v2)로 지정하고 있지만, 현재 모든 구현에서는 일관되게 위의 정의를 사용하고 있습니다. + +## 전체 데이터세트 계산 {#full-dataset-calculation} + +전체 1GB 데이터세트의 각 64바이트 항목은 다음과 같이 계산됩니다. + +```python +def calc_dataset_item(cache, i): + n = len(cache) + r = HASH_BYTES // WORD_BYTES + # 믹스 초기화 + mix = copy.copy(cache[i % n]) + mix[0] ^= i + mix = sha3_512(mix) + # i를 기반으로 하는 많은 무작위 캐시 노드로 fnv 수행 + for j in range(DATASET_PARENTS): + cache_index = fnv(i ^ j, mix[j % r]) + mix = map(fnv, mix, cache[cache_index % n]) + return sha3_512(mix) +``` + +기본적으로 256개의 의사 난수적으로 선택된 캐시 노드의 데이터를 결합하고 이를 해싱하여 데이터세트 노드를 계산합니다. 그런 다음 전체 데이터세트는 다음에 의해 생성됩니다. + +```python +def calc_dataset(full_size, cache): + return [calc_dataset_item(cache, i) for i in range(full_size // HASH_BYTES)] +``` + +## 메인 루프 {#main-loop} + +이제 특정 헤더와 nonce에 대한 최종 값을 생성하기 위해 전체 데이터세트의 데이터를 집계하는 메인 '해시모토'와 유사한 루프를 지정합니다. 아래 코드에서 `header`는 **mixHash** 및 **nonce** 필드를 제외한 _잘린_ 블록 헤더, 즉 RLP 표현의 SHA3-256 해시를 나타냅니다. `nonce`는 빅 엔디안 순서의 64비트 부호 없는 정수의 8바이트입니다. 따라서 `nonce[::-1]`는 해당 값의 8바이트 리틀 엔디안 표현입니다. + +```python +def hashimoto(header, nonce, full_size, dataset_lookup): + n = full_size / HASH_BYTES + w = MIX_BYTES // WORD_BYTES + mixhashes = MIX_BYTES / HASH_BYTES + # 헤더+nonce를 64바이트 시드로 결합 + s = sha3_512(header + nonce[::-1]) + # 복제된 s로 믹스 시작 + mix = [] + for _ in range(MIX_BYTES / HASH_BYTES): + mix.extend(s) + # 무작위 데이터세트 노드에서 믹스 + for i in range(ACCESSES): + p = fnv(i ^ s[0], mix[i % w]) % (n // mixhashes) * mixhashes + newdata = [] + for j in range(MIX_BYTES / HASH_BYTES): + newdata.extend(dataset_lookup(p + j)) + mix = map(fnv, mix, newdata) + # 믹스 압축 + cmix = [] + for i in range(0, len(mix), 4): + cmix.append(fnv(fnv(fnv(mix[i], mix[i+1]), mix[i+2]), mix[i+3])) + return { + "mix digest": serialize_hash(cmix), + "result": serialize_hash(sha3_256(s+cmix)) + } + +def hashimoto_light(full_size, cache, header, nonce): + return hashimoto(header, nonce, full_size, lambda x: calc_dataset_item(cache, x)) + +def hashimoto_full(full_size, dataset, header, nonce): + return hashimoto(header, nonce, full_size, lambda x: dataset[x]) +``` + +기본적으로 128바이트 너비의 '믹스'를 유지하고 전체 데이터세트에서 128바이트를 반복적으로 순차적으로 가져와 `fnv` 함수를 사용하여 믹스와 결합합니다. 128바이트의 순차적 액세스는 알고리즘의 각 라운드가 항상 RAM에서 전체 페이지를 가져오도록 하여 이론적으로 ASIC이 피할 수 있는 변환 색인 버퍼(TLB) 누락을 최소화하는 데 사용됩니다. + +이 알고리즘의 출력이 원하는 대상보다 낮으면 nonce는 유효합니다. 마지막에 `sha3_256`을 추가로 적용하면 최소한의 작업이 수행되었음을 증명하기 위해 제공할 수 있는 중간 nonce가 존재하도록 보장합니다. 이 빠른 외부 PoW 검증은 안티-DDoS 목적으로 사용될 수 있습니다. 또한 결과가 편향되지 않은 256비트 숫자라는 통계적 보증을 제공하는 역할도 합니다. + +## 채굴 {#mining} + +채굴 알고리즘은 다음과 같이 정의됩니다. + +```python +def mine(full_size, dataset, header, difficulty): + # 동일한 숫자의 해시와 비교하기 위해 대상에 0을 채움 + target = zpad(encode_int(2**256 // difficulty), 64)[::-1] + from random import randint + nonce = randint(0, 2**64) + while hashimoto_full(full_size, dataset, header, nonce) > target: + nonce = (nonce + 1) % 2**64 + return nonce +``` + +## 시드 해시 정의 {#seed-hash} + +주어진 블록 위에 채굴하는 데 사용될 시드 해시를 계산하기 위해 다음 알고리즘을 사용합니다. + +```python + def get_seedhash(block): + s = '\x00' * 32 + for i in range(block.number // EPOCH_LENGTH): + s = serialize_hash(sha3_256(s)) + return s +``` + +원활한 채굴 및 검증을 위해 별도의 스레드에서 향후 시드해시 및 데이터세트를 미리 계산하는 것을 권장합니다. + +## 더 읽어보기 {#further-reading} + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 부록 {#appendix} + +위의 파이썬 사양을 코드로 실행하는 데 관심이 있다면 다음 코드를 앞에 추가해야 합니다. + +```python +import sha3, copy + +# 리틀 엔디안 비트 순서를 가정합니다 (인텔 아키텍처와 동일) +def decode_int(s): + return int(s[::-1].encode('hex'), 16) if s else 0 + +def encode_int(s): + a = "%x" % s + return '' if s == 0 else ('0' * (len(a) % 2) + a).decode('hex')[::-1] + +def zpad(s, length): + return s + '\x00' * max(0, length - len(s)) + +def serialize_hash(h): + return ''.join([zpad(encode_int(x), 4) for x in h]) + +def deserialize_hash(h): + return [decode_int(h[i:i+WORD_BYTES]) for i in range(0, len(h), WORD_BYTES)] + +def hash_words(h, sz, x): + if isinstance(x, list): + x = serialize_hash(x) + y = h(x) + return deserialize_hash(y) + +def serialize_cache(ds): + return ''.join([serialize_hash(h) for h in ds]) + +serialize_dataset = serialize_cache + +# sha3 해시 함수, 64바이트 출력 +def sha3_512(x): + return hash_words(lambda v: sha3.sha3_512(v).digest(), 64, x) + +def sha3_256(x): + return hash_words(lambda v: sha3.sha3_256(v).digest(), 32, x) + +def xor(a, b): + return a ^ b + +def isprime(x): + for i in range(2, int(x**0.5)): + if x % i == 0: + return False + return True +``` + +### 데이터 크기 {#data-sizes} + +다음 조회 테이블은 약 2048개의 표로 정리된 데이터 크기 및 캐시 크기의 에폭을 제공합니다. + +```python +def get_datasize(block_number): + return data_sizes[block_number // EPOCH_LENGTH] + +def get_cachesize(block_number): + return cache_sizes[block_number // EPOCH_LENGTH] + +data_sizes = [ +1073739904, 1082130304, 1090514816, 1098906752, 1107293056, +1115684224, 1124070016, 1132461952, 1140849536, 1149232768, +1157627776, 1166013824, 1174404736, 1182786944, 1191180416, +1199568512, 1207958912, 1216345216, 1224732032, 1233124736, +1241513344, 1249902464, 1258290304, 1266673792, 1275067264, +1283453312, 1291844992, 1300234112, 1308619904, 1317010048, +1325397376, 1333787776, 1342176128, 1350561664, 1358954368, +1367339392, 1375731584, 1384118144, 1392507008, 1400897408, +1409284736, 1417673344, 1426062464, 1434451072, 1442839168, +1451229056, 1459615616, 1468006016, 1476394112, 1484782976, +1493171584, 1501559168, 1509948032, 1518337664, 1526726528, +1535114624, 1543503488, 1551892096, 1560278656, 1568669056, +1577056384, 1585446272, 1593831296, 1602219392, 1610610304, +1619000192, 1627386752, 1635773824, 1644164224, 1652555648, +1660943488, 1669332608, 1677721216, 1686109312, 1694497664, +1702886272, 1711274624, 1719661184, 1728047744, 1736434816, +1744829056, 1753218944, 1761606272, 1769995904, 1778382464, +1786772864, 1795157888, 1803550592, 1811937664, 1820327552, +1828711552, 1837102976, 1845488768, 1853879936, 1862269312, +1870656896, 1879048064, 1887431552, 1895825024, 1904212096, +1912601216, 1920988544, 1929379456, 1937765504, 1946156672, +1954543232, 1962932096, 1971321728, 1979707264, 1988093056, +1996487552, 2004874624, 2013262208, 2021653888, 2030039936, +2038430848, 2046819968, 2055208576, 2063596672, 2071981952, +2080373632, 2088762752, 2097149056, 2105539712, 2113928576, +2122315136, 2130700672, 2139092608, 2147483264, 2155872128, +2164257664, 2172642176, 2181035392, 2189426048, 2197814912, +2206203008, 2214587264, 2222979712, 2231367808, 2239758208, +2248145024, 2256527744, 2264922752, 2273312128, 2281701248, +2290086272, 2298476672, 2306867072, 2315251072, 2323639168, +2332032128, 2340420224, 2348808064, 2357196416, 2365580416, +2373966976, 2382363008, 2390748544, 2399139968, 2407530368, +2415918976, 2424307328, 2432695424, 2441084288, 2449472384, +2457861248, 2466247808, 2474637184, 2483026816, 2491414144, +2499803776, 2508191872, 2516582272, 2524970368, 2533359232, +2541743488, 2550134144, 2558525056, 2566913408, 2575301504, +2583686528, 2592073856, 2600467328, 2608856192, 2617240448, +2625631616, 2634022016, 2642407552, 2650796416, 2659188352, +2667574912, 2675965312, 2684352896, 2692738688, 2701130624, +2709518464, 2717907328, 2726293376, 2734685056, 2743073152, +2751462016, 2759851648, 2768232832, 2776625536, 2785017728, +2793401984, 2801794432, 2810182016, 2818571648, 2826959488, +2835349376, 2843734144, 2852121472, 2860514432, 2868900992, +2877286784, 2885676928, 2894069632, 2902451584, 2910843008, +2919234688, 2927622784, 2936011648, 2944400768, 2952789376, +2961177728, 2969565568, 2977951616, 2986338944, 2994731392, +3003120256, 3011508352, 3019895936, 3028287104, 3036675968, +3045063808, 3053452928, 3061837696, 3070228352, 3078615424, +3087003776, 3095394944, 3103782272, 3112173184, 3120562048, +3128944768, 3137339264, 3145725056, 3154109312, 3162505088, +3170893184, 3179280256, 3187669376, 3196056704, 3204445568, +3212836736, 3221224064, 3229612928, 3238002304, 3246391168, +3254778496, 3263165824, 3271556224, 3279944576, 3288332416, +3296719232, 3305110912, 3313500032, 3321887104, 3330273152, +3338658944, 3347053184, 3355440512, 3363827072, 3372220288, +3380608384, 3388997504, 3397384576, 3405774208, 3414163072, +3422551936, 3430937984, 3439328384, 3447714176, 3456104576, +3464493952, 3472883584, 3481268864, 3489655168, 3498048896, +3506434432, 3514826368, 3523213952, 3531603584, 3539987072, +3548380288, 3556763264, 3565157248, 3573545344, 3581934464, +3590324096, 3598712704, 3607098752, 3615488384, 3623877248, +3632265856, 3640646528, 3649043584, 3657430144, 3665821568, +3674207872, 3682597504, 3690984832, 3699367808, 3707764352, +3716152448, 3724541056, 3732925568, 3741318016, 3749706368, +3758091136, 3766481536, 3774872704, 3783260032, 3791650432, +3800036224, 3808427648, 3816815488, 3825204608, 3833592704, +3841981568, 3850370432, 3858755968, 3867147904, 3875536256, +3883920512, 3892313728, 3900702592, 3909087872, 3917478784, +3925868416, 3934256512, 3942645376, 3951032192, 3959422336, +3967809152, 3976200064, 3984588416, 3992974976, 4001363584, +4009751168, 4018141312, 4026530432, 4034911616, 4043308928, +4051695488, 4060084352, 4068472448, 4076862848, 4085249408, +4093640576, 4102028416, 4110413696, 4118805632, 4127194496, +4135583104, 4143971968, 4152360832, 4160746112, 4169135744, +4177525888, 4185912704, 4194303616, 4202691968, 4211076736, +4219463552, 4227855488, 4236246656, 4244633728, 4253022848, +4261412224, 4269799808, 4278184832, 4286578048, 4294962304, +4303349632, 4311743104, 4320130432, 4328521088, 4336909184, +4345295488, 4353687424, 4362073472, 4370458496, 4378852736, +4387238528, 4395630208, 4404019072, 4412407424, 4420790656, +4429182848, 4437571456, 4445962112, 4454344064, 4462738048, +4471119232, 4479516544, 4487904128, 4496289664, 4504682368, +4513068416, 4521459584, 4529846144, 4538232704, 4546619776, +4555010176, 4563402112, 4571790208, 4580174464, 4588567936, +4596957056, 4605344896, 4613734016, 4622119808, 4630511488, +4638898816, 4647287936, 4655675264, 4664065664, 4672451968, +4680842624, 4689231488, 4697620352, 4706007424, 4714397056, +4722786176, 4731173248, 4739562368, 4747951744, 4756340608, +4764727936, 4773114496, 4781504384, 4789894784, 4798283648, +4806667648, 4815059584, 4823449472, 4831835776, 4840226176, +4848612224, 4857003392, 4865391488, 4873780096, 4882169728, +4890557312, 4898946944, 4907333248, 4915722368, 4924110976, +4932499328, 4940889728, 4949276032, 4957666432, 4966054784, +4974438016, 4982831488, 4991221376, 4999607168, 5007998848, +5016386432, 5024763776, 5033164672, 5041544576, 5049941888, +5058329728, 5066717056, 5075107456, 5083494272, 5091883904, +5100273536, 5108662144, 5117048192, 5125436032, 5133827456, +5142215296, 5150605184, 5158993024, 5167382144, 5175769472, +5184157568, 5192543872, 5200936064, 5209324928, 5217711232, +5226102656, 5234490496, 5242877312, 5251263872, 5259654016, +5268040832, 5276434304, 5284819328, 5293209728, 5301598592, +5309986688, 5318374784, 5326764416, 5335151488, 5343542144, +5351929472, 5360319872, 5368706944, 5377096576, 5385484928, +5393871232, 5402263424, 5410650496, 5419040384, 5427426944, +5435816576, 5444205952, 5452594816, 5460981376, 5469367936, +5477760896, 5486148736, 5494536832, 5502925952, 5511315328, +5519703424, 5528089984, 5536481152, 5544869504, 5553256064, +5561645696, 5570032768, 5578423936, 5586811264, 5595193216, +5603585408, 5611972736, 5620366208, 5628750464, 5637143936, +5645528192, 5653921408, 5662310272, 5670694784, 5679082624, +5687474048, 5695864448, 5704251008, 5712641408, 5721030272, +5729416832, 5737806208, 5746194304, 5754583936, 5762969984, +5771358592, 5779748224, 5788137856, 5796527488, 5804911232, +5813300608, 5821692544, 5830082176, 5838468992, 5846855552, +5855247488, 5863636096, 5872024448, 5880411008, 5888799872, +5897186432, 5905576832, 5913966976, 5922352768, 5930744704, +5939132288, 5947522432, 5955911296, 5964299392, 5972688256, +5981074304, 5989465472, 5997851008, 6006241408, 6014627968, +6023015552, 6031408256, 6039796096, 6048185216, 6056574848, +6064963456, 6073351808, 6081736064, 6090128768, 6098517632, +6106906496, 6115289216, 6123680896, 6132070016, 6140459648, +6148849024, 6157237376, 6165624704, 6174009728, 6182403712, +6190792064, 6199176064, 6207569792, 6215952256, 6224345216, +6232732544, 6241124224, 6249510272, 6257899136, 6266287744, +6274676864, 6283065728, 6291454336, 6299843456, 6308232064, +6316620928, 6325006208, 6333395584, 6341784704, 6350174848, +6358562176, 6366951296, 6375337856, 6383729536, 6392119168, +6400504192, 6408895616, 6417283456, 6425673344, 6434059136, +6442444672, 6450837376, 6459223424, 6467613056, 6476004224, +6484393088, 6492781952, 6501170048, 6509555072, 6517947008, +6526336384, 6534725504, 6543112832, 6551500672, 6559888768, +6568278656, 6576662912, 6585055616, 6593443456, 6601834112, +6610219648, 6618610304, 6626999168, 6635385472, 6643777408, +6652164224, 6660552832, 6668941952, 6677330048, 6685719424, +6694107776, 6702493568, 6710882176, 6719274112, 6727662976, +6736052096, 6744437632, 6752825984, 6761213824, 6769604224, +6777993856, 6786383488, 6794770816, 6803158144, 6811549312, +6819937664, 6828326528, 6836706176, 6845101696, 6853491328, +6861880448, 6870269312, 6878655104, 6887046272, 6895433344, +6903822208, 6912212864, 6920596864, 6928988288, 6937377152, +6945764992, 6954149248, 6962544256, 6970928768, 6979317376, +6987709312, 6996093824, 7004487296, 7012875392, 7021258624, +7029652352, 7038038912, 7046427776, 7054818944, 7063207808, +7071595136, 7079980928, 7088372608, 7096759424, 7105149824, +7113536896, 7121928064, 7130315392, 7138699648, 7147092352, +7155479168, 7163865728, 7172249984, 7180648064, 7189036672, +7197424768, 7205810816, 7214196608, 7222589824, 7230975104, +7239367552, 7247755904, 7256145536, 7264533376, 7272921472, +7281308032, 7289694848, 7298088832, 7306471808, 7314864512, +7323253888, 7331643008, 7340029568, 7348419712, 7356808832, +7365196672, 7373585792, 7381973888, 7390362752, 7398750592, +7407138944, 7415528576, 7423915648, 7432302208, 7440690304, +7449080192, 7457472128, 7465860992, 7474249088, 7482635648, +7491023744, 7499412608, 7507803008, 7516192384, 7524579968, +7532967296, 7541358464, 7549745792, 7558134656, 7566524032, +7574912896, 7583300992, 7591690112, 7600075136, 7608466816, +7616854912, 7625244544, 7633629824, 7642020992, 7650410368, +7658794112, 7667187328, 7675574912, 7683961984, 7692349568, +7700739712, 7709130368, 7717519232, 7725905536, 7734295424, +7742683264, 7751069056, 7759457408, 7767849088, 7776238208, +7784626816, 7793014912, 7801405312, 7809792128, 7818179968, +7826571136, 7834957184, 7843347328, 7851732352, 7860124544, +7868512384, 7876902016, 7885287808, 7893679744, 7902067072, +7910455936, 7918844288, 7927230848, 7935622784, 7944009344, +7952400256, 7960786048, 7969176704, 7977565312, 7985953408, +7994339968, 8002730368, 8011119488, 8019508096, 8027896192, +8036285056, 8044674688, 8053062272, 8061448832, 8069838464, +8078227328, 8086616704, 8095006592, 8103393664, 8111783552, +8120171392, 8128560256, 8136949376, 8145336704, 8153726848, +8162114944, 8170503296, 8178891904, 8187280768, 8195669632, +8204058496, 8212444544, 8220834176, 8229222272, 8237612672, +8246000768, 8254389376, 8262775168, 8271167104, 8279553664, +8287944064, 8296333184, 8304715136, 8313108352, 8321497984, +8329885568, 8338274432, 8346663296, 8355052928, 8363441536, +8371828352, 8380217984, 8388606592, 8396996224, 8405384576, +8413772672, 8422161536, 8430549376, 8438939008, 8447326592, +8455715456, 8464104832, 8472492928, 8480882048, 8489270656, +8497659776, 8506045312, 8514434944, 8522823808, 8531208832, +8539602304, 8547990656, 8556378752, 8564768384, 8573154176, +8581542784, 8589933952, 8598322816, 8606705024, 8615099264, +8623487872, 8631876992, 8640264064, 8648653952, 8657040256, +8665430656, 8673820544, 8682209152, 8690592128, 8698977152, +8707374464, 8715763328, 8724151424, 8732540032, 8740928384, +8749315712, 8757704576, 8766089344, 8774480768, 8782871936, +8791260032, 8799645824, 8808034432, 8816426368, 8824812928, +8833199488, 8841591424, 8849976448, 8858366336, 8866757248, +8875147136, 8883532928, 8891923328, 8900306816, 8908700288, +8917088384, 8925478784, 8933867392, 8942250368, 8950644608, +8959032704, 8967420544, 8975809664, 8984197504, 8992584064, +9000976256, 9009362048, 9017752448, 9026141312, 9034530688, +9042917504, 9051307904, 9059694208, 9068084864, 9076471424, +9084861824, 9093250688, 9101638528, 9110027648, 9118416512, +9126803584, 9135188096, 9143581312, 9151969664, 9160356224, +9168747136, 9177134464, 9185525632, 9193910144, 9202302848, +9210690688, 9219079552, 9227465344, 9235854464, 9244244864, +9252633472, 9261021824, 9269411456, 9277799296, 9286188928, +9294574208, 9302965888, 9311351936, 9319740032, 9328131968, +9336516736, 9344907392, 9353296768, 9361685888, 9370074752, +9378463616, 9386849408, 9395239808, 9403629184, 9412016512, +9420405376, 9428795008, 9437181568, 9445570688, 9453960832, +9462346624, 9470738048, 9479121536, 9487515008, 9495903616, +9504289664, 9512678528, 9521067904, 9529456256, 9537843584, +9546233728, 9554621312, 9563011456, 9571398784, 9579788672, +9588178304, 9596567168, 9604954496, 9613343104, 9621732992, +9630121856, 9638508416, 9646898816, 9655283584, 9663675776, +9672061312, 9680449664, 9688840064, 9697230464, 9705617536, +9714003584, 9722393984, 9730772608, 9739172224, 9747561088, +9755945344, 9764338816, 9772726144, 9781116544, 9789503872, +9797892992, 9806282624, 9814670464, 9823056512, 9831439232, +9839833984, 9848224384, 9856613504, 9865000576, 9873391232, +9881772416, 9890162816, 9898556288, 9906940544, 9915333248, +9923721088, 9932108672, 9940496512, 9948888448, 9957276544, +9965666176, 9974048384, 9982441088, 9990830464, 9999219584, +10007602816, 10015996544, 10024385152, 10032774016, 10041163648, +10049548928, 10057940096, 10066329472, 10074717824, 10083105152, +10091495296, 10099878784, 10108272256, 10116660608, 10125049216, +10133437312, 10141825664, 10150213504, 10158601088, 10166991232, +10175378816, 10183766144, 10192157312, 10200545408, 10208935552, +10217322112, 10225712768, 10234099328, 10242489472, 10250876032, +10259264896, 10267656064, 10276042624, 10284429184, 10292820352, +10301209472, 10309598848, 10317987712, 10326375296, 10334763392, +10343153536, 10351541632, 10359930752, 10368318592, 10376707456, +10385096576, 10393484672, 10401867136, 10410262144, 10418647424, +10427039104, 10435425664, 10443810176, 10452203648, 10460589952, +10468982144, 10477369472, 10485759104, 10494147712, 10502533504, +10510923392, 10519313536, 10527702656, 10536091264, 10544478592, +10552867712, 10561255808, 10569642368, 10578032768, 10586423168, +10594805632, 10603200128, 10611588992, 10619976064, 10628361344, +10636754048, 10645143424, 10653531776, 10661920384, 10670307968, +10678696832, 10687086464, 10695475072, 10703863168, 10712246144, +10720639616, 10729026688, 10737414784, 10745806208, 10754190976, +10762581376, 10770971264, 10779356288, 10787747456, 10796135552, +10804525184, 10812915584, 10821301888, 10829692288, 10838078336, +10846469248, 10854858368, 10863247232, 10871631488, 10880023424, +10888412032, 10896799616, 10905188992, 10913574016, 10921964672, +10930352768, 10938742912, 10947132544, 10955518592, 10963909504, +10972298368, 10980687488, 10989074816, 10997462912, 11005851776, +11014241152, 11022627712, 11031017344, 11039403904, 11047793024, +11056184704, 11064570752, 11072960896, 11081343872, 11089737856, +11098128256, 11106514816, 11114904448, 11123293568, 11131680128, +11140065152, 11148458368, 11156845696, 11165236864, 11173624192, +11182013824, 11190402688, 11198790784, 11207179136, 11215568768, +11223957376, 11232345728, 11240734592, 11249122688, 11257511296, +11265899648, 11274285952, 11282675584, 11291065472, 11299452544, +11307842432, 11316231296, 11324616832, 11333009024, 11341395584, +11349782656, 11358172288, 11366560384, 11374950016, 11383339648, +11391721856, 11400117376, 11408504192, 11416893568, 11425283456, +11433671552, 11442061184, 11450444672, 11458837888, 11467226752, +11475611776, 11484003968, 11492392064, 11500780672, 11509169024, +11517550976, 11525944448, 11534335616, 11542724224, 11551111808, +11559500672, 11567890304, 11576277376, 11584667008, 11593056128, +11601443456, 11609830016, 11618221952, 11626607488, 11634995072, +11643387776, 11651775104, 11660161664, 11668552576, 11676940928, +11685330304, 11693718656, 11702106496, 11710496128, 11718882688, +11727273088, 11735660416, 11744050048, 11752437376, 11760824704, +11769216128, 11777604736, 11785991296, 11794381952, 11802770048, +11811157888, 11819548544, 11827932544, 11836324736, 11844713344, +11853100928, 11861486464, 11869879936, 11878268032, 11886656896, +11895044992, 11903433088, 11911822976, 11920210816, 11928600448, +11936987264, 11945375872, 11953761152, 11962151296, 11970543488, +11978928512, 11987320448, 11995708288, 12004095104, 12012486272, +12020875136, 12029255552, 12037652096, 12046039168, 12054429568, +12062813824, 12071206528, 12079594624, 12087983744, 12096371072, +12104759936, 12113147264, 12121534592, 12129924992, 12138314624, +12146703232, 12155091584, 12163481216, 12171864704, 12180255872, +12188643968, 12197034112, 12205424512, 12213811328, 12222199424, +12230590336, 12238977664, 12247365248, 12255755392, 12264143488, +12272531584, 12280920448, 12289309568, 12297694592, 12306086528, +12314475392, 12322865024, 12331253632, 12339640448, 12348029312, +12356418944, 12364805248, 12373196672, 12381580928, 12389969024, +12398357632, 12406750592, 12415138432, 12423527552, 12431916416, +12440304512, 12448692352, 12457081216, 12465467776, 12473859968, +12482245504, 12490636672, 12499025536, 12507411584, 12515801728, +12524190592, 12532577152, 12540966272, 12549354368, 12557743232, +12566129536, 12574523264, 12582911872, 12591299456, 12599688064, +12608074624, 12616463488, 12624845696, 12633239936, 12641631616, +12650019968, 12658407296, 12666795136, 12675183232, 12683574656, +12691960192, 12700350592, 12708740224, 12717128576, 12725515904, +12733906816, 12742295168, 12750680192, 12759071872, 12767460736, +12775848832, 12784236928, 12792626816, 12801014656, 12809404288, +12817789312, 12826181504, 12834568832, 12842954624, 12851345792, +12859732352, 12868122496, 12876512128, 12884901248, 12893289088, +12901672832, 12910067584, 12918455168, 12926842496, 12935232896, +12943620736, 12952009856, 12960396928, 12968786816, 12977176192, +12985563776, 12993951104, 13002341504, 13010730368, 13019115392, +13027506304, 13035895168, 13044272512, 13052673152, 13061062528, +13069446272, 13077838976, 13086227072, 13094613632, 13103000192, +13111393664, 13119782528, 13128157568, 13136559232, 13144945024, +13153329536, 13161724288, 13170111872, 13178502784, 13186884736, +13195279744, 13203667072, 13212057472, 13220445824, 13228832128, +13237221248, 13245610624, 13254000512, 13262388352, 13270777472, +13279166336, 13287553408, 13295943296, 13304331904, 13312719488, +13321108096, 13329494656, 13337885824, 13346274944, 13354663808, +13363051136, 13371439232, 13379825024, 13388210816, 13396605056, +13404995456, 13413380224, 13421771392, 13430159744, 13438546048, +13446937216, 13455326848, 13463708288, 13472103808, 13480492672, +13488875648, 13497269888, 13505657728, 13514045312, 13522435712, +13530824576, 13539210112, 13547599232, 13555989376, 13564379008, +13572766336, 13581154432, 13589544832, 13597932928, 13606320512, +13614710656, 13623097472, 13631477632, 13639874944, 13648264064, +13656652928, 13665041792, 13673430656, 13681818496, 13690207616, +13698595712, 13706982272, 13715373184, 13723762048, 13732150144, +13740536704, 13748926592, 13757316224, 13765700992, 13774090112, +13782477952, 13790869376, 13799259008, 13807647872, 13816036736, +13824425344, 13832814208, 13841202304, 13849591424, 13857978752, +13866368896, 13874754688, 13883145344, 13891533184, 13899919232, +13908311168, 13916692096, 13925085056, 13933473152, 13941866368, +13950253696, 13958643584, 13967032192, 13975417216, 13983807616, +13992197504, 14000582272, 14008973696, 14017363072, 14025752192, +14034137984, 14042528384, 14050918016, 14059301504, 14067691648, +14076083584, 14084470144, 14092852352, 14101249664, 14109635968, +14118024832, 14126407552, 14134804352, 14143188608, 14151577984, +14159968384, 14168357248, 14176741504, 14185127296, 14193521024, +14201911424, 14210301824, 14218685056, 14227067264, 14235467392, +14243855488, 14252243072, 14260630144, 14269021568, 14277409408, +14285799296, 14294187904, 14302571392, 14310961792, 14319353728, +14327738752, 14336130944, 14344518784, 14352906368, 14361296512, +14369685376, 14378071424, 14386462592, 14394848128, 14403230848, +14411627392, 14420013952, 14428402304, 14436793472, 14445181568, +14453569664, 14461959808, 14470347904, 14478737024, 14487122816, +14495511424, 14503901824, 14512291712, 14520677504, 14529064832, +14537456768, 14545845632, 14554234496, 14562618496, 14571011456, +14579398784, 14587789184, 14596172672, 14604564608, 14612953984, +14621341312, 14629724288, 14638120832, 14646503296, 14654897536, +14663284864, 14671675264, 14680061056, 14688447616, 14696835968, +14705228416, 14713616768, 14722003328, 14730392192, 14738784128, +14747172736, 14755561088, 14763947648, 14772336512, 14780725376, +14789110144, 14797499776, 14805892736, 14814276992, 14822670208, +14831056256, 14839444352, 14847836032, 14856222848, 14864612992, +14872997504, 14881388672, 14889775744, 14898165376, 14906553472, +14914944896, 14923329664, 14931721856, 14940109696, 14948497024, +14956887424, 14965276544, 14973663616, 14982053248, 14990439808, +14998830976, 15007216768, 15015605888, 15023995264, 15032385152, +15040768384, 15049154944, 15057549184, 15065939072, 15074328448, +15082715008, 15091104128, 15099493504, 15107879296, 15116269184, +15124659584, 15133042304, 15141431936, 15149824384, 15158214272, +15166602368, 15174991232, 15183378304, 15191760512, 15200154496, +15208542592, 15216931712, 15225323392, 15233708416, 15242098048, +15250489216, 15258875264, 15267265408, 15275654528, 15284043136, +15292431488, 15300819584, 15309208192, 15317596544, 15325986176, +15334374784, 15342763648, 15351151744, 15359540608, 15367929728, +15376318336, 15384706432, 15393092992, 15401481856, 15409869952, +15418258816, 15426649984, 15435037568, 15443425664, 15451815296, +15460203392, 15468589184, 15476979328, 15485369216, 15493755776, +15502146944, 15510534272, 15518924416, 15527311232, 15535699072, +15544089472, 15552478336, 15560866688, 15569254528, 15577642624, +15586031488, 15594419072, 15602809472, 15611199104, 15619586432, +15627975296, 15636364928, 15644753792, 15653141888, 15661529216, +15669918848, 15678305152, 15686696576, 15695083136, 15703474048, +15711861632, 15720251264, 15728636288, 15737027456, 15745417088, +15753804928, 15762194048, 15770582656, 15778971008, 15787358336, +15795747712, 15804132224, 15812523392, 15820909696, 15829300096, +15837691264, 15846071936, 15854466944, 15862855808, 15871244672, +15879634816, 15888020608, 15896409728, 15904799104, 15913185152, +15921577088, 15929966464, 15938354816, 15946743424, 15955129472, +15963519872, 15971907968, 15980296064, 15988684928, 15997073024, +16005460864, 16013851264, 16022241152, 16030629248, 16039012736, +16047406976, 16055794816, 16064181376, 16072571264, 16080957824, +16089346688, 16097737856, 16106125184, 16114514816, 16122904192, +16131292544, 16139678848, 16148066944, 16156453504, 16164839552, +16173236096, 16181623424, 16190012032, 16198401152, 16206790528, +16215177344, 16223567744, 16231956352, 16240344704, 16248731008, +16257117824, 16265504384, 16273898624, 16282281856, 16290668672, +16299064192, 16307449216, 16315842176, 16324230016, 16332613504, +16341006464, 16349394304, 16357783168, 16366172288, 16374561664, +16382951296, 16391337856, 16399726208, 16408116352, 16416505472, +16424892032, 16433282176, 16441668224, 16450058624, 16458448768, +16466836864, 16475224448, 16483613056, 16492001408, 16500391808, +16508779648, 16517166976, 16525555328, 16533944192, 16542330752, +16550719616, 16559110528, 16567497088, 16575888512, 16584274816, +16592665472, 16601051008, 16609442944, 16617832064, 16626218624, +16634607488, 16642996096, 16651385728, 16659773824, 16668163712, +16676552576, 16684938112, 16693328768, 16701718144, 16710095488, +16718492288, 16726883968, 16735272832, 16743661184, 16752049792, +16760436608, 16768827008, 16777214336, 16785599104, 16793992832, +16802381696, 16810768768, 16819151744, 16827542656, 16835934848, +16844323712, 16852711552, 16861101952, 16869489536, 16877876864, +16886265728, 16894653056, 16903044736, 16911431296, 16919821696, +16928207488, 16936592768, 16944987776, 16953375616, 16961763968, +16970152832, 16978540928, 16986929536, 16995319168, 17003704448, +17012096896, 17020481152, 17028870784, 17037262208, 17045649536, +17054039936, 17062426496, 17070814336, 17079205504, 17087592064, +17095978112, 17104369024, 17112759424, 17121147776, 17129536384, +17137926016, 17146314368, 17154700928, 17163089792, 17171480192, +17179864192, 17188256896, 17196644992, 17205033856, 17213423488, +17221811072, 17230198912, 17238588032, 17246976896, 17255360384, +17263754624, 17272143232, 17280530048, 17288918912, 17297309312, +17305696384, 17314085504, 17322475136, 17330863744, 17339252096, +17347640192, 17356026496, 17364413824, 17372796544, 17381190016, +17389583488, 17397972608, 17406360704, 17414748544, 17423135872, +17431527296, 17439915904, 17448303232, 17456691584, 17465081728, +17473468288, 17481857408, 17490247552, 17498635904, 17507022464, +17515409024, 17523801728, 17532189824, 17540577664, 17548966016, +17557353344, 17565741184, 17574131584, 17582519168, 17590907008, +17599296128, 17607687808, 17616076672, 17624455808, 17632852352, +17641238656, 17649630848, 17658018944, 17666403968, 17674794112, +17683178368, 17691573376, 17699962496, 17708350592, 17716739968, +17725126528, 17733517184, 17741898112, 17750293888, 17758673024, +17767070336, 17775458432, 17783848832, 17792236928, 17800625536, +17809012352, 17817402752, 17825785984, 17834178944, 17842563968, +17850955648, 17859344512, 17867732864, 17876119424, 17884511872, +17892900224, 17901287296, 17909677696, 17918058112, 17926451072, +17934843776, 17943230848, 17951609216, 17960008576, 17968397696, +17976784256, 17985175424, 17993564032, 18001952128, 18010339712, +18018728576, 18027116672, 18035503232, 18043894144, 18052283264, +18060672128, 18069056384, 18077449856, 18085837184, 18094225792, +18102613376, 18111004544, 18119388544, 18127781248, 18136170368, +18144558976, 18152947328, 18161336192, 18169724288, 18178108544, +18186498944, 18194886784, 18203275648, 18211666048, 18220048768, +18228444544, 18236833408, 18245220736] + +cache_sizes = [ +16776896, 16907456, 17039296, 17170112, 17301056, 17432512, 17563072, +17693888, 17824192, 17955904, 18087488, 18218176, 18349504, 18481088, +18611392, 18742336, 18874304, 19004224, 19135936, 19267264, 19398208, +19529408, 19660096, 19791424, 19922752, 20053952, 20184896, 20315968, +20446912, 20576576, 20709184, 20840384, 20971072, 21102272, 21233216, +21364544, 21494848, 21626816, 21757376, 21887552, 22019392, 22151104, +22281536, 22412224, 22543936, 22675264, 22806464, 22935872, 23068096, +23198272, 23330752, 23459008, 23592512, 23723968, 23854912, 23986112, +24116672, 24247616, 24378688, 24509504, 24640832, 24772544, 24903488, +25034432, 25165376, 25296704, 25427392, 25558592, 25690048, 25820096, +25951936, 26081728, 26214208, 26345024, 26476096, 26606656, 26737472, +26869184, 26998208, 27131584, 27262528, 27393728, 27523904, 27655744, +27786688, 27917888, 28049344, 28179904, 28311488, 28441792, 28573504, +28700864, 28835648, 28966208, 29096768, 29228608, 29359808, 29490752, +29621824, 29752256, 29882816, 30014912, 30144448, 30273728, 30406976, +30538432, 30670784, 30799936, 30932672, 31063744, 31195072, 31325248, +31456192, 31588288, 31719232, 31850432, 31981504, 32110784, 32243392, +32372672, 32505664, 32636608, 32767808, 32897344, 33029824, 33160768, +33289664, 33423296, 33554368, 33683648, 33816512, 33947456, 34076992, +34208704, 34340032, 34471744, 34600256, 34734016, 34864576, 34993984, +35127104, 35258176, 35386688, 35518528, 35650624, 35782336, 35910976, +36044608, 36175808, 36305728, 36436672, 36568384, 36699968, 36830656, +36961984, 37093312, 37223488, 37355072, 37486528, 37617472, 37747904, +37879232, 38009792, 38141888, 38272448, 38403392, 38535104, 38660672, +38795584, 38925632, 39059264, 39190336, 39320768, 39452096, 39581632, +39713984, 39844928, 39974848, 40107968, 40238144, 40367168, 40500032, +40631744, 40762816, 40894144, 41023552, 41155904, 41286208, 41418304, +41547712, 41680448, 41811904, 41942848, 42073792, 42204992, 42334912, +42467008, 42597824, 42729152, 42860096, 42991552, 43122368, 43253696, +43382848, 43515712, 43646912, 43777088, 43907648, 44039104, 44170432, +44302144, 44433344, 44564288, 44694976, 44825152, 44956864, 45088448, +45219008, 45350464, 45481024, 45612608, 45744064, 45874496, 46006208, +46136768, 46267712, 46399424, 46529344, 46660672, 46791488, 46923328, +47053504, 47185856, 47316928, 47447872, 47579072, 47710144, 47839936, +47971648, 48103232, 48234176, 48365248, 48496192, 48627136, 48757312, +48889664, 49020736, 49149248, 49283008, 49413824, 49545152, 49675712, +49807168, 49938368, 50069056, 50200256, 50331584, 50462656, 50593472, +50724032, 50853952, 50986048, 51117632, 51248576, 51379904, 51510848, +51641792, 51773248, 51903296, 52035136, 52164032, 52297664, 52427968, +52557376, 52690112, 52821952, 52952896, 53081536, 53213504, 53344576, +53475776, 53608384, 53738816, 53870528, 54000832, 54131776, 54263744, +54394688, 54525248, 54655936, 54787904, 54918592, 55049152, 55181248, +55312064, 55442752, 55574336, 55705024, 55836224, 55967168, 56097856, +56228672, 56358592, 56490176, 56621888, 56753728, 56884928, 57015488, +57146816, 57278272, 57409216, 57540416, 57671104, 57802432, 57933632, +58064576, 58195264, 58326976, 58457408, 58588864, 58720192, 58849984, +58981696, 59113024, 59243456, 59375552, 59506624, 59637568, 59768512, +59897792, 60030016, 60161984, 60293056, 60423872, 60554432, 60683968, +60817216, 60948032, 61079488, 61209664, 61341376, 61471936, 61602752, +61733696, 61865792, 61996736, 62127808, 62259136, 62389568, 62520512, +62651584, 62781632, 62910784, 63045056, 63176128, 63307072, 63438656, +63569216, 63700928, 63831616, 63960896, 64093888, 64225088, 64355392, +64486976, 64617664, 64748608, 64879424, 65009216, 65142464, 65273792, +65402816, 65535424, 65666752, 65797696, 65927744, 66060224, 66191296, +66321344, 66453056, 66584384, 66715328, 66846656, 66977728, 67108672, +67239104, 67370432, 67501888, 67631296, 67763776, 67895104, 68026304, +68157248, 68287936, 68419264, 68548288, 68681408, 68811968, 68942912, +69074624, 69205568, 69337024, 69467584, 69599168, 69729472, 69861184, +69989824, 70122944, 70253888, 70385344, 70515904, 70647232, 70778816, +70907968, 71040832, 71171648, 71303104, 71432512, 71564992, 71695168, +71826368, 71958464, 72089536, 72219712, 72350144, 72482624, 72613568, +72744512, 72875584, 73006144, 73138112, 73268672, 73400128, 73530944, +73662272, 73793344, 73924544, 74055104, 74185792, 74316992, 74448832, +74579392, 74710976, 74841664, 74972864, 75102784, 75233344, 75364544, +75497024, 75627584, 75759296, 75890624, 76021696, 76152256, 76283072, +76414144, 76545856, 76676672, 76806976, 76937792, 77070016, 77200832, +77331392, 77462464, 77593664, 77725376, 77856448, 77987776, 78118336, +78249664, 78380992, 78511424, 78642496, 78773056, 78905152, 79033664, +79166656, 79297472, 79429568, 79560512, 79690816, 79822784, 79953472, +80084672, 80214208, 80346944, 80477632, 80608576, 80740288, 80870848, +81002048, 81133504, 81264448, 81395648, 81525952, 81657536, 81786304, +81919808, 82050112, 82181312, 82311616, 82443968, 82573376, 82705984, +82835776, 82967744, 83096768, 83230528, 83359552, 83491264, 83622464, +83753536, 83886016, 84015296, 84147776, 84277184, 84409792, 84540608, +84672064, 84803008, 84934336, 85065152, 85193792, 85326784, 85458496, +85589312, 85721024, 85851968, 85982656, 86112448, 86244416, 86370112, +86506688, 86637632, 86769344, 86900672, 87031744, 87162304, 87293632, +87424576, 87555392, 87687104, 87816896, 87947968, 88079168, 88211264, +88341824, 88473152, 88603712, 88735424, 88862912, 88996672, 89128384, +89259712, 89390272, 89521984, 89652544, 89783872, 89914816, 90045376, +90177088, 90307904, 90438848, 90569152, 90700096, 90832832, 90963776, +91093696, 91223744, 91356992, 91486784, 91618496, 91749824, 91880384, +92012224, 92143552, 92273344, 92405696, 92536768, 92666432, 92798912, +92926016, 93060544, 93192128, 93322816, 93453632, 93583936, 93715136, +93845056, 93977792, 94109504, 94240448, 94371776, 94501184, 94632896, +94764224, 94895552, 95023424, 95158208, 95287744, 95420224, 95550016, +95681216, 95811904, 95943872, 96075328, 96203584, 96337856, 96468544, +96599744, 96731072, 96860992, 96992576, 97124288, 97254848, 97385536, +97517248, 97647808, 97779392, 97910464, 98041408, 98172608, 98303168, +98434496, 98565568, 98696768, 98827328, 98958784, 99089728, 99220928, +99352384, 99482816, 99614272, 99745472, 99876416, 100007104, +100138048, 100267072, 100401088, 100529984, 100662592, 100791872, +100925248, 101056064, 101187392, 101317952, 101449408, 101580608, +101711296, 101841728, 101973824, 102104896, 102235712, 102366016, +102498112, 102628672, 102760384, 102890432, 103021888, 103153472, +103284032, 103415744, 103545152, 103677248, 103808576, 103939648, +104070976, 104201792, 104332736, 104462528, 104594752, 104725952, +104854592, 104988608, 105118912, 105247808, 105381184, 105511232, +105643072, 105774784, 105903296, 106037056, 106167872, 106298944, +106429504, 106561472, 106691392, 106822592, 106954304, 107085376, +107216576, 107346368, 107478464, 107609792, 107739712, 107872192, +108003136, 108131392, 108265408, 108396224, 108527168, 108657344, +108789568, 108920384, 109049792, 109182272, 109312576, 109444928, +109572928, 109706944, 109837888, 109969088, 110099648, 110230976, +110362432, 110492992, 110624704, 110755264, 110886208, 111017408, +111148864, 111279296, 111410752, 111541952, 111673024, 111803456, +111933632, 112066496, 112196416, 112328512, 112457792, 112590784, +112715968, 112852672, 112983616, 113114944, 113244224, 113376448, +113505472, 113639104, 113770304, 113901376, 114031552, 114163264, +114294592, 114425536, 114556864, 114687424, 114818624, 114948544, +115080512, 115212224, 115343296, 115473472, 115605184, 115736128, +115867072, 115997248, 116128576, 116260288, 116391488, 116522944, +116652992, 116784704, 116915648, 117046208, 117178304, 117308608, +117440192, 117569728, 117701824, 117833024, 117964096, 118094656, +118225984, 118357312, 118489024, 118617536, 118749632, 118882112, +119012416, 119144384, 119275328, 119406016, 119537344, 119668672, +119798464, 119928896, 120061376, 120192832, 120321728, 120454336, +120584512, 120716608, 120848192, 120979136, 121109056, 121241408, +121372352, 121502912, 121634752, 121764416, 121895744, 122027072, +122157632, 122289088, 122421184, 122550592, 122682944, 122813888, +122945344, 123075776, 123207488, 123338048, 123468736, 123600704, +123731264, 123861952, 123993664, 124124608, 124256192, 124386368, +124518208, 124649024, 124778048, 124911296, 125041088, 125173696, +125303744, 125432896, 125566912, 125696576, 125829056, 125958592, +126090304, 126221248, 126352832, 126483776, 126615232, 126746432, +126876608, 127008704, 127139392, 127270336, 127401152, 127532224, +127663552, 127794752, 127925696, 128055232, 128188096, 128319424, +128449856, 128581312, 128712256, 128843584, 128973632, 129103808, +129236288, 129365696, 129498944, 129629888, 129760832, 129892288, +130023104, 130154048, 130283968, 130416448, 130547008, 130678336, +130807616, 130939456, 131071552, 131202112, 131331776, 131464384, +131594048, 131727296, 131858368, 131987392, 132120256, 132250816, +132382528, 132513728, 132644672, 132774976, 132905792, 133038016, +133168832, 133299392, 133429312, 133562048, 133692992, 133823296, +133954624, 134086336, 134217152, 134348608, 134479808, 134607296, +134741056, 134872384, 135002944, 135134144, 135265472, 135396544, +135527872, 135659072, 135787712, 135921472, 136052416, 136182848, +136313792, 136444864, 136576448, 136707904, 136837952, 136970048, +137099584, 137232064, 137363392, 137494208, 137625536, 137755712, +137887424, 138018368, 138149824, 138280256, 138411584, 138539584, +138672832, 138804928, 138936128, 139066688, 139196864, 139328704, +139460032, 139590208, 139721024, 139852864, 139984576, 140115776, +140245696, 140376512, 140508352, 140640064, 140769856, 140902336, +141032768, 141162688, 141294016, 141426496, 141556544, 141687488, +141819584, 141949888, 142080448, 142212544, 142342336, 142474432, +142606144, 142736192, 142868288, 142997824, 143129408, 143258944, +143392448, 143523136, 143653696, 143785024, 143916992, 144045632, +144177856, 144309184, 144440768, 144570688, 144701888, 144832448, +144965056, 145096384, 145227584, 145358656, 145489856, 145620928, +145751488, 145883072, 146011456, 146144704, 146275264, 146407232, +146538176, 146668736, 146800448, 146931392, 147062336, 147193664, +147324224, 147455936, 147586624, 147717056, 147848768, 147979456, +148110784, 148242368, 148373312, 148503232, 148635584, 148766144, +148897088, 149028416, 149159488, 149290688, 149420224, 149551552, +149683136, 149814976, 149943616, 150076352, 150208064, 150338624, +150470464, 150600256, 150732224, 150862784, 150993088, 151125952, +151254976, 151388096, 151519168, 151649728, 151778752, 151911104, +152042944, 152174144, 152304704, 152435648, 152567488, 152698816, +152828992, 152960576, 153091648, 153222976, 153353792, 153484096, +153616192, 153747008, 153878336, 154008256, 154139968, 154270912, +154402624, 154533824, 154663616, 154795712, 154926272, 155057984, +155188928, 155319872, 155450816, 155580608, 155712064, 155843392, +155971136, 156106688, 156237376, 156367424, 156499264, 156630976, +156761536, 156892352, 157024064, 157155008, 157284416, 157415872, +157545536, 157677248, 157810496, 157938112, 158071744, 158203328, +158334656, 158464832, 158596288, 158727616, 158858048, 158988992, +159121216, 159252416, 159381568, 159513152, 159645632, 159776192, +159906496, 160038464, 160169536, 160300352, 160430656, 160563008, +160693952, 16082208, 160956352, 161086784, 161217344, 161349184, +161480512, 161611456, 161742272, 161873216, 162002752, 162135872, +162266432, 162397888, 162529216, 162660032, 162790976, 162922048, +163052096, 163184576, 163314752, 163446592, 163577408, 163707968, +163839296, 163969984, 164100928, 164233024, 164364224, 164494912, +164625856, 164756672, 164887616, 165019072, 165150016, 165280064, +165412672, 165543104, 165674944, 165805888, 165936832, 166067648, +166198336, 166330048, 166461248, 166591552, 166722496, 166854208, +166985408, 167116736, 167246656, 167378368, 167508416, 167641024, +167771584, 167903168, 168034112, 168164032, 168295744, 168427456, +168557632, 168688448, 168819136, 168951616, 169082176, 169213504, +169344832, 169475648, 169605952, 169738048, 169866304, 169999552, +170131264, 170262464, 170393536, 170524352, 170655424, 170782016, +170917696, 171048896, 171179072, 171310784, 171439936, 171573184, +171702976, 171835072, 171966272, 172097216, 172228288, 172359232, +172489664, 172621376, 172747712, 172883264, 173014208, 173144512, +173275072, 173407424, 173539136, 173669696, 173800768, 173931712, +174063424, 174193472, 174325696, 174455744, 174586816, 174718912, +174849728, 174977728, 175109696, 175242688, 175374272, 175504832, +175636288, 175765696, 175898432, 176028992, 176159936, 176291264, +176422592, 176552512, 176684864, 176815424, 176946496, 177076544, +177209152, 177340096, 177470528, 177600704, 177731648, 177864256, +177994816, 178126528, 178257472, 178387648, 178518464, 178650176, +178781888, 178912064, 179044288, 179174848, 179305024, 179436736, +179568448, 179698496, 179830208, 179960512, 180092608, 180223808, +180354752, 180485696, 180617152, 180748096, 180877504, 181009984, +181139264, 181272512, 181402688, 181532608, 181663168, 181795136, +181926592, 182057536, 182190016, 182320192, 182451904, 182582336, +182713792, 182843072, 182976064, 183107264, 183237056, 183368384, +183494848, 183631424, 183762752, 183893824, 184024768, 184154816, +184286656, 184417984, 184548928, 184680128, 184810816, 184941248, +185072704, 185203904, 185335616, 185465408, 185596352, 185727296, +185859904, 185989696, 186121664, 186252992, 186383552, 186514112, +186645952, 186777152, 186907328, 187037504, 187170112, 187301824, +187429184, 187562048, 187693504, 187825472, 187957184, 188087104, +188218304, 188349376, 188481344, 188609728, 188743616, 188874304, +189005248, 189136448, 189265088, 189396544, 189528128, 189660992, +189791936, 189923264, 190054208, 190182848, 190315072, 190447424, +190577984, 190709312, 190840768, 190971328, 191102656, 191233472, +191364032, 191495872, 191626816, 191758016, 191888192, 192020288, +192148928, 192282176, 192413504, 192542528, 192674752, 192805952, +192937792, 193068608, 193198912, 193330496, 193462208, 193592384, +193723456, 193854272, 193985984, 194116672, 194247232, 194379712, +194508352, 194641856, 194772544, 194900672, 195035072, 195166016, +195296704, 195428032, 195558592, 195690304, 195818176, 195952576, +196083392, 196214336, 196345792, 196476736, 196607552, 196739008, +196869952, 197000768, 197130688, 197262784, 197394368, 197523904, +197656384, 197787584, 197916608, 198049472, 198180544, 198310208, +198442432, 198573632, 198705088, 198834368, 198967232, 199097792, +199228352, 199360192, 199491392, 199621696, 199751744, 199883968, +200014016, 200146624, 200276672, 200408128, 200540096, 200671168, +200801984, 200933312, 201062464, 201194944, 201326144, 201457472, +201588544, 201719744, 201850816, 201981632, 202111552, 202244032, +202374464, 202505152, 202636352, 202767808, 202898368, 203030336, +203159872, 203292608, 203423296, 203553472, 203685824, 203816896, +203947712, 204078272, 204208192, 204341056, 204472256, 204603328, +204733888, 204864448, 204996544, 205125568, 205258304, 205388864, +205517632, 205650112, 205782208, 205913536, 206044736, 206176192, +206307008, 206434496, 206569024, 206700224, 206831168, 206961856, +207093056, 207223616, 207355328, 207486784, 207616832, 207749056, +207879104, 208010048, 208141888, 208273216, 208404032, 208534336, +208666048, 208796864, 208927424, 209059264, 209189824, 209321792, +209451584, 209582656, 209715136, 209845568, 209976896, 210106432, +210239296, 210370112, 210501568, 210630976, 210763712, 210894272, +211024832, 211156672, 211287616, 211418176, 211549376, 211679296, +211812032, 211942592, 212074432, 212204864, 212334016, 212467648, +212597824, 212727616, 212860352, 212991424, 213120832, 213253952, +213385024, 213515584, 213645632, 213777728, 213909184, 214040128, +214170688, 214302656, 214433728, 214564544, 214695232, 214826048, +214956992, 215089088, 215219776, 215350592, 215482304, 215613248, +215743552, 215874752, 216005312, 216137024, 216267328, 216399296, +216530752, 216661696, 216790592, 216923968, 217054528, 217183168, +217316672, 217448128, 217579072, 217709504, 217838912, 217972672, +218102848, 218233024, 218364736, 218496832, 218627776, 218759104, +218888896, 219021248, 219151936, 219281728, 219413056, 219545024, +219675968, 219807296, 219938624, 220069312, 220200128, 220331456, +220461632, 220592704, 220725184, 220855744, 220987072, 221117888, +221249216, 221378368, 221510336, 221642048, 221772736, 221904832, +222031808, 222166976, 222297536, 222428992, 222559936, 222690368, +222820672, 222953152, 223083968, 223213376, 223345984, 223476928, +223608512, 223738688, 223869376, 224001472, 224132672, 224262848, +224394944, 224524864, 224657344, 224788288, 224919488, 225050432, +225181504, 225312704, 225443776, 225574592, 225704768, 225834176, +225966784, 226097216, 226229824, 226360384, 226491712, 226623424, +226754368, 226885312, 227015104, 227147456, 227278528, 227409472, +227539904, 227669696, 227802944, 227932352, 228065216, 228196288, +228326464, 228457792, 228588736, 228720064, 228850112, 228981056, +229113152, 229243328, 229375936, 229505344, 229636928, 229769152, +229894976, 230030272, 230162368, 230292416, 230424512, 230553152, +230684864, 230816704, 230948416, 231079616, 231210944, 231342016, +231472448, 231603776, 231733952, 231866176, 231996736, 232127296, +232259392, 232388672, 232521664, 232652608, 232782272, 232914496, +233043904, 233175616, 233306816, 233438528, 233569984, 233699776, +233830592, 233962688, 234092224, 234221888, 234353984, 234485312, +234618304, 234749888, 234880832, 235011776, 235142464, 235274048, +235403456, 235535936, 235667392, 235797568, 235928768, 236057152, +236190272, 236322752, 236453312, 236583616, 236715712, 236846528, +236976448, 237108544, 237239104, 237371072, 237501632, 237630784, +237764416, 237895232, 238026688, 238157632, 238286912, 238419392, +238548032, 238681024, 238812608, 238941632, 239075008, 239206336, +239335232, 239466944, 239599168, 239730496, 239861312, 239992384, +240122816, 240254656, 240385856, 240516928, 240647872, 240779072, +240909632, 241040704, 241171904, 241302848, 241433408, 241565248, +241696192, 241825984, 241958848, 242088256, 242220224, 242352064, +242481856, 242611648, 242744896, 242876224, 243005632, 243138496, +243268672, 243400384, 243531712, 243662656, 243793856, 243924544, +244054592, 244187072, 244316608, 244448704, 244580032, 244710976, +244841536, 244972864, 245104448, 245233984, 245365312, 245497792, +245628736, 245759936, 245889856, 246021056, 246152512, 246284224, +246415168, 246545344, 246675904, 246808384, 246939584, 247070144, +247199552, 247331648, 247463872, 247593536, 247726016, 247857088, +247987648, 248116928, 248249536, 248380736, 248512064, 248643008, +248773312, 248901056, 249036608, 249167552, 249298624, 249429184, +249560512, 249692096, 249822784, 249954112, 250085312, 250215488, +250345792, 250478528, 250608704, 250739264, 250870976, 251002816, +251133632, 251263552, 251395136, 251523904, 251657792, 251789248, +251919424, 252051392, 252182464, 252313408, 252444224, 252575552, +252706624, 252836032, 252968512, 253099712, 253227584, 253361728, +253493056, 253623488, 253754432, 253885504, 254017216, 254148032, +254279488, 254410432, 254541376, 254672576, 254803264, 254933824, +255065792, 255196736, 255326528, 255458752, 255589952, 255721408, +255851072, 255983296, 256114624, 256244416, 256374208, 256507712, +256636096, 256768832, 256900544, 257031616, 257162176, 257294272, +257424448, 257555776, 257686976, 257818432, 257949632, 258079552, +258211136, 258342464, 258473408, 258603712, 258734656, 258867008, +258996544, 259127744, 259260224, 259391296, 259522112, 259651904, +259784384, 259915328, 260045888, 260175424, 260308544, 260438336, +260570944, 260700992, 260832448, 260963776, 261092672, 261226304, +261356864, 261487936, 261619648, 261750592, 261879872, 262011968, +262143424, 262274752, 262404416, 262537024, 262667968, 262799296, +262928704, 263061184, 263191744, 263322944, 263454656, 263585216, +263716672, 263847872, 263978944, 264108608, 264241088, 264371648, +264501184, 264632768, 264764096, 264895936, 265024576, 265158464, +265287488, 265418432, 265550528, 265681216, 265813312, 265943488, +266075968, 266206144, 266337728, 266468032, 266600384, 266731072, +266862272, 266993344, 267124288, 267255616, 267386432, 267516992, +267648704, 267777728, 267910592, 268040512, 268172096, 268302784, +268435264, 268566208, 268696256, 268828096, 268959296, 269090368, +269221312, 269352256, 269482688, 269614784, 269745856, 269876416, +270007616, 270139328, 270270272, 270401216, 270531904, 270663616, +270791744, 270924736, 271056832, 271186112, 271317184, 271449536, +271580992, 271711936, 271843136, 271973056, 272105408, 272236352, +272367296, 272498368, 272629568, 272759488, 272891456, 273022784, +273153856, 273284672, 273415616, 273547072, 273677632, 273808448, +273937088, 274071488, 274200896, 274332992, 274463296, 274595392, +274726208, 274857536, 274988992, 275118656, 275250496, 275382208, +275513024, 275643968, 275775296, 275906368, 276037184, 276167872, +276297664, 276429376, 276560576, 276692672, 276822976, 276955072, +277085632, 277216832, 277347008, 277478848, 277609664, 277740992, +277868608, 278002624, 278134336, 278265536, 278395328, 278526784, +278657728, 278789824, 278921152, 279052096, 279182912, 279313088, +279443776, 279576256, 279706048, 279838528, 279969728, 280099648, +280230976, 280361408, 280493632, 280622528, 280755392, 280887104, +281018176, 281147968, 281278912, 281411392, 281542592, 281673152, +281803712, 281935552, 282066496, 282197312, 282329024, 282458816, +282590272, 282720832, 282853184, 282983744, 283115072, 283246144, +283377344, 283508416, 283639744, 283770304, 283901504, 284032576, +284163136, 284294848, 284426176, 284556992, 284687296, 284819264, +284950208, 285081536] +``` diff --git a/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/index.md b/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/index.md new file mode 100644 index 00000000000..98a54930350 --- /dev/null +++ b/public/content/translations/ko/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/index.md @@ -0,0 +1,42 @@ +--- +title: "채굴 알고리즘" +description: "이더리움 채굴에 사용되는 알고리즘 자세히 살펴보기 " +lang: ko +--- + + + + + +작업증명은 더 이상 이더리움의 합의 메커니즘의 기초가 아니며, 채굴이 중단되었습니다. 대신, 이더리움은 ETH를 스테이킹하는 검증자에 의해 보안이 유지됩니다. 오늘부터 ETH 스테이킹을 시작할 수 있습니다. 더 알아보려면 The Merge, 지분증명, 그리고 스테이킹에 대해 읽어보세요. 이 페이지는 역사적인 참고만을 위한 것입니다. + + + + +이더리움 채굴은 Ethash라는 알고리즘을 사용했습니다. 이 알고리즘의 근본적 아이디어는 채굴자가 브루트 포스 계산-무작위 대입-을 통해 논스 입력값을 알아내려고 시도하여 그 결과 해쉬값이, 계산 난이도에 의해 결정된 임계값보다 작아지게 만드는 것입니다. 이 난이도는 동적으로 조절되어, 블록 생성이 일정한 주기로 이루어지도록 합니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하려면 먼저 [작업 증명 합의](/developers/docs/consensus-mechanisms/pow) 및 [채굴](/developers/docs/consensus-mechanisms/pow/mining)에 대해 읽어보는 것을 권장합니다. + +## 대거-해시모토 {#dagger-hashimoto} + +대거-하시모토 알고리즘은 이더리움 채굴에 있어서 Ethash가 대체한 선행적 검색 알고리즘이었습니다. 두 개의 서로 다른 알고리즘: 대거와 하시모토의 결합이었습니다. 그것은 단지 연구 구현이었고 이더리움 메인넷이 출시되었을 때는 Ethash로 대체되었습니다. + +[Dagger](http://www.hashcash.org/papers/dagger.html)는 [방향성 비순환 그래프(Directed Acyclic Graph)](https://en.wikipedia.org/wiki/Directed_acyclic_graph)를 생성하고, 이 그래프의 임의의 조각들을 함께 해시하는 과정을 포함합니다. 핵심 원칙은 각 논스값은 오직 거대한 전체 데이터 트리의 일부만 필요로 한다는 것입니다. 논스 값 각각에 대한 서브트리를 다시 계산하는 것은 채굴에 매우 부담이 되므로, 트리를 저장할 필요가 있습니다. 하지만 단일 논스 값에 대한 검증 작업으로는 재계산이 충분히 가능합니다. 대거 알고리즘은 메모리 집약적이지만 메모리 부담이 안전한 수준으로 증가하면 검증하기 어려운 기존의 Scrypt 알고리즘의 대안으로 설계되었습니다. 하지만 대거 알고리즘은 공유 메모리 하드웨어 가속에 취약하여 다른 연구 방향들이 선호됨에 따라 사용이 감소했습니다. + +[Hashimoto](http://diyhpl.us/%7Ebryan/papers2/bitcoin/meh/hashimoto.pdf)는 I/O 바운드(즉, 메모리 읽기가 채굴 과정의 제한 요소가 됨) 방식을 통해 ASIC 저항성을 추가하는 알고리즘입니다. 그 이론은 RAM이 계산보다 더 쉽게 이용 가능하다는 것입니다. 이미 수십억 달러 가치의 연구가 다양한 목적을 위해 RAM을 최적화하는 방법을 조사해왔으며, 이들 연구는 종종 거의 무작위 접근 패턴(따라서 ‘랜덤 액세스 메모리’)을 포함합니다. 그 결과로, 기존의 RAM은 알고리즘을 평가하는 데 있어 상당히 최적에 가까운 상태라고 할 수 있습니다. 하시모토 알고리즘은 블록체인을 데이터 소스로 사용하면서 위에 있는 (1)과 (3)을 동시에 만족합니다. + +대거 하시모토 알고리즘은 대거 및 하시모토의 변경된 버전을 사용했습니다. 대거-하시모토 알고리즘과 하시모토 알고리즘의 차이점은, 하시모토 알고리즘이 블록체인을 데이터 소스로 사용하는 반면에, 대거-하시모토 알고리즘은 맞춤형으로 생성된 데이터 세트를 사용한다는 점입니다. 이 맞춤형 데이터 세트는 매 N개의 블록이 쌓일 때마다 블록 데이터에 기반하여 업데이트됩니다. 이 데이터 세트는 대거 알고리즘을 활용해 생성되고, 라이트 클라이언트 검증 알고리즘 검증 시 모든 논스값의 특정한 서브셋을 효율적으로 계산합니다. 대거-해시모토와 대거의 차이점은 기존 대거와 달리, 블록을 쿼리하는 데 사용되는 데이터 세트가 반영구적이며 간헐적인 간격(예: 주 1회)으로만 업데이트된다는 것입니다. 이는 데이터 세트를 생성하는 데 들어가는 노력이 거의 없다는 것을 의미하며, 이에 따라 공유 메모리 속도 향상과 관련한 세르지오 레르너의 주장은 크게 약화됩니다. + +[대거-해시모토](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto)에 대해 더 알아보기. + +## Ethash {#ethash} + +Ethash는 현재는 더 이상 사용되지 않는 작업 증명-PoW- 방식 하에서, 실제 이더리움 메인넷에서 사용된 채굴 알고리즘이었습니다. Ethash는 이전 버전의 기본 원칙을 계승하면서도, 알고리즘이 상당히 업데이트된 후 대거-하시모토 알고리즘의 특정한 버전으로써 새로운 이름이 붙여졌습니다. 이더리움 메인넷은 Ethash만 사용했습니다. 대거-해시모토는 채굴 알고리즘의 R&D 버전이었으며, 이더리움 메인넷에서 채굴이 시작되기 전에 대체되었습니다. + +[Ethash에 대해 더 알아보기](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/ethash). + +## 더 읽어보기 {#further-reading} + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ diff --git a/public/content/translations/ko/developers/docs/dapps/index.md b/public/content/translations/ko/developers/docs/dapps/index.md new file mode 100644 index 00000000000..204cbff168a --- /dev/null +++ b/public/content/translations/ko/developers/docs/dapps/index.md @@ -0,0 +1,96 @@ +--- +title: "탈중앙화앱에 대한 기술적 소개" +description: +lang: ko +--- + +탈중앙화 애플리케이션(탈중앙화앱)은 [스마트 계약](/developers/docs/smart-contracts/)과 프런트엔드 사용자 인터페이스를 결합한 탈중앙화 네트워크상에 구축된 애플리케이션입니다. 이더리움에서 스마트 계약은 오픈 API처럼 접근하기 쉽고 투명합니다. 즉, 여러분의 디앱에는 다른 사람이 작성한 스마트 계약이 포함될 수 있습니다. + +## 필수 구성 요소 {#prerequisites} + +탈중앙화앱에 대해 배우기 전에 [블록체인 기초](/developers/docs/intro-to-ethereum/)를 다루고 이더리움 네트워크와 탈중앙화 방식에 대해 읽어보아야 합니다. + +## 탈중앙화앱의 정의 {#definition-of-a-dapp} + +디앱에는 분산형 피어-투-피어 네트워크 상에서 실행되는 백엔드 코드가 있습니다. 백엔드 코드가 중앙화된 서버에서 실행되는 앱과 이를 비교해보시기 바랍니다. + +디앱은 일반 앱처럼, 아떤 언어로 작성된 백엔드도 호출할 수 있는 프론트엔드 코드와 유저 인터페이스를 가지고 있다. 또한 프런트엔드는 [IPFS](https://ipfs.io/)와 같은 탈중앙화된 스토리지에서 호스팅될 수 있습니다. + +- **탈중앙화** - 탈중앙화앱은 어느 한 사람이나 그룹이 통제할 수 없는 개방형 공용 탈중앙화 플랫폼인 이더리움에서 작동합니다. +- **결정적** - 탈중앙화앱은 실행되는 환경에 관계없이 동일한 기능을 수행합니다. +- **튜링 완전** - 탈중앙화앱은 필요한 리소스가 주어지면 모든 작업을 수행할 수 있습니다. +- **격리됨** - 탈중앙화앱은 이더리움 가상 머신으로 알려진 가상 환경에서 실행되므로 스마트 계약에 버그가 있더라도 블록체인 네트워크의 정상적인 기능을 방해하지 않습니다. + +### 스마트 계약에 대하여 {#on-smart-contracts} + +디앱을 소개하려면, 디앱의 백엔드인 스마트 컨트랙트를 이해할 필요가 있다. 자세한 개요는 [스마트 계약](/developers/docs/smart-contracts/)에 대한 섹션을 참조하세요. + +스마트 컨트랙트는 이더리움 블록체인 상에서 살아있는 그리고 프로그램된대로 정확히 실행하는 코드이다. 스마트 계약이 네트워크에 배포되면, 변경할 수 없습니다. 디앱은 그들이 개인이나 회사가 아닌 컨트랙트에 적힌 로직에 의해 제어되기 때문에 탈중앙화될 수 있다. 이는 또한 스마트 계약를 매우 조심해서 설계하고, 철저히 테스트할 필요가 있음을 의미한다. + +## 탈중앙화앱 개발의 이점 {#benefits-of-dapp-development} + +- **무중단** – 스마트 계약이 블록체인에 배포되면, 전체 네트워크는 계약과 상호 작용하려는 클라이언트에게 항상 서비스를 제공할 수 있습니다. 따라서 악의적인 의도를 가진 사람들은 개별 디앱에 서비스 거부 공격을 할 수 없습니다. +- **개인정보보호** – 탈중앙화앱을 배포하거나 상호 작용하기 위해 실제 신원을 제공할 필요가 없습니다. +- **검열 저항성** – 네트워크상의 단일 개체는 사용자가 트랜잭션을 제출하거나, 탈중앙화앱을 배포하거나, 블록체인에서 데이터를 읽는 것을 차단할 수 없습니다. +- **완전한 데이터 무결성** – 블록체인에 저장된 데이터는 암호화 프리미티브 덕분에 불변하며 논쟁의 여지가 없습니다. 악의적인 행위자들은 이미 공개된 트랜잭션이나 다른 데이터를 위조할 수 없다. +- **무신뢰 계산/검증 가능한 동작** – 스마트 계약은 중앙 기관을 신뢰할 필요 없이 분석할 수 있으며 예측 가능한 방식으로 실행되도록 보장됩니다. 이는 전통적인 모델에서는 불가능하다. 예를 들어, 우리가 온라인 뱅킹 시스템을 사용할 때 우리는 금융 기관들이 우리의 금융 데이터를 오용하거나, 기록을 함부로 조작하거나 해킹 당하지 않을 것이라고 믿어야 한다. + +## 탈중앙화앱 개발의 단점 {#drawbacks-of-dapp-development} + +- **유지보수** – 블록체인에 게시된 코드와 데이터는 수정하기가 더 어렵기 때문에 탈중앙화앱은 유지보수가 더 어려울 수 있습니다. 이전 버전에서 버그나 보안 위험이 식별되더라도, 배포된 후에는 디앱(또는 디엡에 저장된 기본 데이터) 을 업데이트하기가 어렵습니다. +- **성능 오버헤드** – 상당한 성능 오버헤드가 있으며 확장이 정말 어렵습니다. 이더리움이 요구하는 보안성, 무결성, 투명성 그리고 신뢰성 레벨을 달성하기 위해서는 모든 노드가 실행하고, 모든 트랜잭션을 저장한다. 더욱이, 지분 증명 합의에도 시간이 걸립니다. +- **네트워크 혼잡** – 하나의 탈중앙화앱이 너무 많은 계산 리소스를 사용하면 전체 네트워크가 정체됩니다. 현재 네트워크는 초당 약 10\~15 트랜잭션만 처리 가능하다; 트랜잭션들이 이보다 빠르게 보내지면, 컨펌되지 않은 트랜잭션 풀이 빠르게 불어날 수 있다. +- **사용자 경험** – 평균적인 최종 사용자가 진정으로 안전한 방식으로 블록체인과 상호 작용하는 데 필요한 도구 스택을 설정하는 것이 너무 어렵다고 느낄 수 있으므로 사용자 친화적인 경험을 설계하는 것이 더 어려울 수 있습니다. +- **중앙화** – 이더리움의 베이스 레이어 위에 구축된 사용자 친화적이고 개발자 친화적인 솔루션은 어쨌든 중앙화된 서비스처럼 보일 수 있습니다. 예를 들어, 이러한 서비스는 키 또는 기타 민감한 정보를 서버 측에 저장하거나, 중앙 집중식 서버를 사용하여 프런트엔드를 제공하거나, 블록체인에 쓰기 전에 중앙 집중식 서버에서 중요한 비즈니스 로직을 실행할 수 있습니다. 중앙 집중화는 블록체인의 많은 이점을 제거합니다. + +## 시각 자료를 찾고 있나요? 시각적 학습자 + + + +## 탈중앙화앱 생성을 위한 도구 {#dapp-tools} + +**Scaffold-ETH _- 스마트 계약에 적응하는 프런트엔드를 사용하여 Solidity를 빠르게 실험합니다._** + +- [GitHub](https://github.com/scaffold-eth/scaffold-eth-2) +- [예시 탈중앙화앱](https://punkwallet.io/) + +**Create Eth App _- 한 가지 명령어로 이더리움 기반 앱을 만듭니다._** + +- [GitHub](https://github.com/paulrberg/create-eth-app) + +**One Click Dapp _- [ABI](/glossary/#abi)에서 탈중앙화앱 프런트엔드를 생성하기 위한 FOSS 도구._** + +- [oneclickdapp.com](https://oneclickdapp.com) +- [GitHub](https://github.com/oneclickdapp/oneclickdapp-v1) + +**Etherflow _- 이더리움 개발자가 노드를 테스트하고 브라우저에서 RPC 호출을 구성 및 디버그하기 위한 FOSS 도구입니다._** + +- [etherflow.quiknode.io](https://etherflow.quiknode.io/) +- [GitHub](https://github.com/abunsen/etherflow) + +**thirdweb _- 모든 언어의 SDK, 스마트 계약, 도구 및 web3 개발을 위한 인프라._** + +- [홈페이지](https://thirdweb.com/) +- [개발문서](https://portal.thirdweb.com/) +- [GitHub](https://github.com/thirdweb-dev/) + +**Crossmint _- 스마트 계약을 배포하고, 신용카드 및 교차 체인 결제를 활성화하고, API를 사용하여 NFT를 생성, 배포, 판매, 저장 및 편집할 수 있는 엔터프라이즈급 web3 개발 플랫폼입니다._** + +- [crossmint.com](https://www.crossmint.com) +- [개발문서](https://docs.crossmint.com) +- [Discord](https://discord.com/invite/crossmint) + +## 더 읽어보기 {#further-reading} + +- [탈중앙화앱 둘러보기](/apps) +- [웹 3.0 애플리케이션의 아키텍처](https://www.preethikasireddy.com/post/the-architecture-of-a-web-3-0-application) - _Preethi Kasireddy_ +- [탈중앙화 애플리케이션에 대한 2021년 가이드](https://limechain.tech/blog/what-are-dapps-the-2021-guide/) - _LimeChain_ +- [탈중앙화앱이란 무엇인가?](https://www.gemini.com/cryptopedia/decentralized-applications-defi-dapps) - _Gemini_ +- [인기 있는 탈중앙화앱](https://www.alchemy.com/dapps) - _Alchemy_ + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 관련 주제 {#related-topics} + +- [이더리움 스택 소개](/developers/docs/ethereum-stack/) +- [개발 프레임워크](/developers/docs/frameworks/) diff --git a/public/content/translations/ko/developers/docs/data-and-analytics/block-explorers/index.md b/public/content/translations/ko/developers/docs/data-and-analytics/block-explorers/index.md new file mode 100644 index 00000000000..3d3768a4419 --- /dev/null +++ b/public/content/translations/ko/developers/docs/data-and-analytics/block-explorers/index.md @@ -0,0 +1,254 @@ +--- +title: "블록 탐색기" +description: "트랜잭션, 계정, 계약 등에 대한 정보를 쿼리할 수 있는 블록체인 데이터 세계로 연결되는 포털인 블록 탐색기에 대한 소개" +lang: ko +sidebarDepth: 3 +--- + +블록 탐색기들은 이더리움 데이터로의 포털이다. 이를 사용하여 블록, 트랜잭션, 검증자, 계정 및 기타 온체인 활동에 대한 실시간 데이터를 볼 수 있습니다. + +## 필수 구성 요소 {#prerequisites} + +블록 탐색기의 데이터를 분석 할 수 있기 위해서는 이더리움에 대한 기본적인 개념을 이해해야 한다. [이더리움 소개](/developers/docs/intro-to-ethereum/)부터 시작해 보세요. + +## 서비스 {#services} + +- [Etherscan](https://etherscan.io/) -_중국어, 한국어, 러시아어, 일본어로도 제공_ +- [3xpl](https://3xpl.com/ethereum) +- [Beaconcha.in](https://beaconcha.in/) +- [Blockchair](https://blockchair.com/ethereum) -_스페인어, 프랑스어, 이탈리아어, 네덜란드어, 포르투갈어, 러시아어, 중국어, 페르시아어로도 제공_ +- [Blockscout](https://eth.blockscout.com/) +- [Chainlens](https://www.chainlens.com/) +- [DexGuru 블록 탐색기](https://ethereum.dex.guru/) +- [Etherchain](https://www.etherchain.org/) +- [Ethplorer](https://ethplorer.io/) -_중국어, 스페인어, 프랑스어, 터키어, 러시아어, 한국어, 베트남어로도 제공_ +- [EthVM](https://www.ethvm.com/) +- [OKLink](https://www.oklink.com/eth) +- [Ethseer](https://ethseer.io) + +## 오픈 소스 도구 {#open-source-tools} + +- [Otterscan](https://otterscan.io/) +- [lazy-etherscan](https://github.com/woxjro/lazy-etherscan) + +## 데이터 {#data} + +이더리움은 설계상 투명하기 때문에 모든 것이 검증 가능하다. 블록 탐색기는 이 정보를 가져올 수 있는 인터페이스를 제공한다. 그리고 만약 그 데이터가 필요하다면 이는 메인 이더리움 네트워크와 테스트넷 모두를 위한것이다. 데이터는 실행 데이터와 합의 데이터로 나뉩니다. 실행 데이터는 특정 블록에서 실행된 트랜잭션을 나타냅니다. 합의 데이터는 블록 자체와 이를 제안한 검증자를 나타냅니다. + +다음은 블록 탐색기에서 얻을 수 있는 데이터 유형 요약이다. + +### 실행 데이터 {#execution-data} + +새로운 블록은 12초마다 이더리움에 추가되므로(블록 제안자가 자신의 차례를 놓치지 않는 한), 거의 일정한 데이터 스트림이 블록 탐색기에 추가됩니다. 블록에는 다음과 같은 유용한 데이터가 많이 포함되어 있다: + +**표준 데이터** + +- 블록 높이 - 현재 블록 생성 시 블록체인의 블록 번호 및 길이(블록 단위) +- 타임스탬프 - 블록이 제안된 시간 +- 트랜잭션 - 블록에 포함된 트랜잭션의 수 +- 수수료 수령인 - 트랜잭션에서 가스 수수료 팁을 받은 주소 +- 블록 보상 - 블록을 제안한 검증자에게 수여된 ETH 금액 +- 크기 - 블록 내 데이터의 크기(바이트 단위로 측정) +- 사용된 가스 - 블록의 트랜잭션에서 사용된 총 가스 단위 +- 가스 한도 - 블록의 트랜잭션에 의해 설정된 총 가스 한도 +- 가스당 기본 수수료 - 트랜잭션이 블록에 포함되기 위해 필요한 최소 승수 +- 소각된 수수료 - 블록에서 소각된 ETH의 양 +- 추가 데이터 - 빌더가 블록에 포함한 모든 추가 데이터 + +**고급 데이터** + +- 해시 - 블록 헤더를 나타내는 암호화 해시(블록의 고유 식별자) +- 상위 해시 - 현재 블록 이전 블록의 해시 +- 상태 루트 - 시스템의 전체 상태를 저장하는 머클 트라이의 루트 해시 + +### 가스 {#gas} + +블록 탐색기는 트랜잭션 및 블록에서 가스 사용량에 대한 데이터를 제공할 뿐만 아니라 네트워크의 현재 가스 가격에 대한 정보도 제공한다. 이를 통해 네트워크 사용량을 파악하고, 안전한 트랜잭션을 제출하며, 가스 비용을 초과하지 않도록 할 수 있다. 프로덕트의 인터페이스로 이 정보를 가져오는 데 도움이 될 수 있는 API를 찾아보라. 가스 관련 데이터는 다음과 같다: + +- 안전하지만 느린 트랜잭션에 필요한 예상 가스 단위(+ 예상 가격 및 기간) +- 평균 트랜잭션에 필요한 예상 가스 단위(+ 예상 가격 및 기간) +- 빠른 트랜잭션에 필요한 예상 가스 단위(+ 예상 가격 및 기간) +- 가스 가격에 따른 평균 확인 시간 +- 가스를 소비하는 계약 - 즉, 네트워크에서 사용량이 많은 인기 있는 제품 +- 가스를 소비하는 계정 - 즉, 빈번한 네트워크 사용자 + +### 트랜잭션 {#transactions} + +블록 탐색기는 사람들이 트랜잭션의 진행 상태를 추적하는 일반적인 곳이 되었다. 이는 여러분이 얻을 수 있는 자세한 수준이 추가적인 확실성을 주기 때문이다. 트랜잭션 데이터는 다음을 포함한다. + +**표준 데이터** + +- 트랜잭션 해시 - 트랜잭션이 제출될 때 생성되는 해시 +- 상태 - 트랜잭션이 보류 중인지, 실패했는지 또는 성공했는지를 나타내는 표시 +- 블록 - 트랜잭션이 포함된 블록 +- 타임스탬프 - 트랜잭션이 검증자가 제안한 블록에 포함된 시간 +- 보낸 사람 - 트랜잭션을 제출한 계정의 주소 +- 받는 사람 - 트랜잭션이 상호 작용하는 수신자 또는 스마트 계약의 주소 +- 전송된 토큰 - 트랜잭션의 일부로 전송된 토큰 목록 +- 가치 - 전송되는 총 ETH 가치 +- 거래 수수료 - 트랜잭션을 처리하기 위해 검증자에게 지불된 금액(가스 가격\*사용된 가스로 계산) + +**고급 데이터** + +- 가스 한도 - 이 트랜잭션이 소비할 수 있는 최대 가스 단위 수 +- 사용된 가스 - 트랜잭션이 소비한 실제 가스 단위량 +- 가스 가격 - 가스 단위당 설정된 가격 +- 논스 - `from` 주소의 트랜잭션 번호(0부터 시작하므로 논스 `100`은 실제로는 이 계정에서 제출한 101번째 트랜잭션임) +- 입력 데이터 - 트랜잭션에 필요한 모든 추가 정보 + +### 계정 {#accounts} + +여러분이 계정에 관해 접근 가능한 수많은 데이터가 있다. 이것이 여러분의 자산과 가치가 쉽게 추적될 수 없도록 여러 계정을 사용할 것이 권장되는 이유이다. 트랜잭션과 계정 활동을 더 비밀스럽게 만들기 위해 여러 해결책이 또한 개발 중이다. 그러나 여기 계정에 이용 가능한 데이터가 있다. + +**사용자 계정** + +- 계정 주소 - 자금을 보낼 수 있는 공개 주소 +- ETH 잔액 - 해당 계정과 연결된 ETH 금액 +- 총 ETH 가치 - ETH의 가치 +- 토큰 - 계정과 관련된 토큰 및 그 가치 +- 거래 내역 - 이 계정이 발신자 또는 수신자였던 모든 거래 목록 + +**스마트 컨트랙트** + +스마트 컨트랙트 계정들은 사용자 계정이 가지는 모든 데이터를 갖지만, 어떤 블록 탐색기들은 코드 정보까지 보여준다. 예로 다음을 포함한다: + +- 계약 생성자 - 메인넷에 계약을 배포한 주소 +- 생성 트랜잭션 - 메인넷으로의 배포를 포함한 트랜잭션 +- 소스 코드 - 스마트 계약의 솔리디티 또는 바이퍼 코드 +- 계약 ABI - 계약의 애플리케이션 바이너리 인터페이스—계약이 수행하는 호출과 수신된 데이터 +- 계약 생성 코드 - 스마트 계약의 컴파일된 바이트코드—솔리디티나 Vyper 등으로 작성된 스마트 계약을 컴파일할 때 생성됩니다. +- 계약 이벤트 - 스마트 계약에서 호출된 메서드의 내역—기본적으로 계약이 어떻게, 얼마나 자주 사용되는지 확인할 수 있는 방법입니다. + +### 토큰 {#tokens} + +토큰은 계약의 한 종류이므로 스마트 계약과 유사한 데이터를 가집니다. 그러나 그들은 값을 갖고 거래될 수 있으므로, 그들은 추가 데이터 포인트를 갖는다: + +- 유형 - ERC-20, ERC-721 또는 다른 토큰 표준인지 여부 +- 가격 - ERC-20인 경우 현재 시장 가치를 가집니다. +- 시가 총액 - ERC-20인 경우 시가 총액을 가집니다(가격\*총 공급량으로 계산). +- 총 공급량 - 유통 중인 토큰의 수 +- 보유자 - 토큰을 보유하고 있는 주소의 수 +- 전송 - 계정 간에 토큰이 전송된 횟수 +- 거래 내역 - 토큰을 포함한 모든 거래의 내역 +- 계약 주소 - 메인넷에 배포된 토큰의 주소 +- 소수점 - ERC-20 토큰은 나눌 수 있으며 소수점을 가집니다. + +### 네트워크 {#network} + +일부 블록 데이터는 이더리움의 전반적인 상태와 관련이 있습니다. + +- 총 트랜잭션 - 이더리움이 생성된 이후의 트랜잭션 수 +- 초당 트랜잭션 - 1초 내에 처리할 수 있는 트랜잭션의 수 +- ETH 가격 - 1 ETH의 현재 가치 +- 총 ETH 공급량 - 유통 중인 ETH의 수—새로운 ETH는 블록 보상 형태로 모든 블록이 생성될 때 함께 생성된다는 점을 기억하세요. +- 시가 총액 - 가격\*공급량으로 계산 + +## 합의 레이어 데이터 {#consensus-layer-data} + +### 에포크 {#epoch} + +보안상의 이유로, 매 에포크(6.4분마다)가 끝날 때마다 무작위로 선정된 검증자 위원회가 생성됩니다. Epoch는 다음을 포함한다. + +- Epoch number +- 완결 상태 - 에포크가 완결되었는지 여부(예/아니오) +- 시간 - 에포크가 종료된 시간 +- 증명 - 에포크 내의 증명 수(슬롯 내 블록에 대한 투표) +- 입금 - 에포크에 포함된 ETH 입금 수(검증자는 검증자가 되기 위해 ETH를 스테이킹해야 함) +- 슬래싱 - 블록 제안자 또는 증명자에게 부과된 패널티 수 +- 투표 참여 - 블록을 증명하는 데 사용된 스테이킹된 ETH의 양 +- 검증자 - 해당 에포크에 활성화된 검증자 수 +- 평균 검증자 잔액 - 활성 검증자의 평균 잔액 +- 슬롯 - 에포크에 포함된 슬롯 수(슬롯은 하나의 유효한 블록을 포함) + +### 슬롯 {#slot} + +슬롯은 블록 생성을 위한 기회이며 각 슬롯에 사용할 수 있는 데이터는 다음과 같다. + +- 에포크 - 슬롯이 유효한 에포크 +- Slot number +- 상태 - 슬롯의 상태(제안됨/놓침) +- 시간 - 슬롯 타임스탬프 +- 제안자 - 슬롯에 대한 블록을 제안한 검증자 +- 블록 루트 - BeaconBlock의 해시 트리 루트 +- 상위 루트 - 이전에 온 블록의 해시 +- 상태 루트 - BeaconState의 해시 트리 루트 +- Signature +- Randao reveal +- 그래피티 - 블록 제안자는 블록 제안에 32바이트 길이의 메시지를 포함할 수 있습니다. +- 실행 데이터 + - Block hash + - Deposit count + - Deposit root +- 증명 - 이 슬롯에 있는 블록에 대한 증명 수 +- 입금 - 이 슬롯 동안의 입금 수 +- 자발적 퇴장 - 슬롯 동안 퇴장한 검증자 수 +- 슬래싱 - 블록 제안자 또는 증명자에게 부과된 패널티 수 +- 투표 - 이 슬롯의 블록에 투표한 검증자 + +### 블록 {#blocks-1} + +지분 증명은 시간을 슬롯과 에포크로 나눕니다. 즉, 새로운 데이터를 의미한다! + +- 제안자 - 새 블록을 제안하기 위해 알고리즘에 따라 선택된 검증자 +- 에포크 - 블록이 제안된 에포크 +- 슬롯 - 블록이 제안된 슬롯 +- 증명 - 슬롯에 포함된 증명 수—증명은 블록이 비콘 체인으로 갈 준비가 되었음을 나타내는 투표와 같습니다. + +### 검증자 {#validators} + +검증인은 블록을 제안하고 슬롯 내에서 이를 증명할 책임이 있다. + +- 검증자 번호 - 검증자를 나타내는 고유 번호 +- 현재 잔액 - 보상을 포함한 검증자의 잔액 +- 유효 잔액 - 스테이킹에 사용되는 검증자의 잔액 +- 수익 - 검증자가 받은 보상 또는 패널티 +- 상태 - 검증인이 현재 온라인 상태이고 활성 상태인지 여부 +- 증명 효율성 - 검증자의 증명이 체인에 포함되는 데 걸리는 평균 시간 +- 활성화 자격 - 검증자가 검증할 수 있게 된 날짜(및 에포크) +- 활성화 시작 시점 - 검증자가 활성화된 날짜(및 에포크) +- 제안된 블록 - 검증자가 제안한 블록 +- 증명 - 검증자가 제공한 증명 +- 입금 - 검증자가 수행한 스테이킹 입금의 `from` 주소, 트랜잭션 해시, 블록 번호, 타임스탬프, 금액 및 상태 + +### 증명 {#attestations} + +증명은 블록을 체인에 포함하기 위한 "동의" 투표이다. 그들의 데이터는 증명 기록, 그리고 증명한 검증인과 관련이 있다. + +- 슬롯 - 증명이 이루어진 슬롯 +- 위원회 인덱스 - 주어진 슬롯의 위원회 인덱스 +- 집계 비트 - 증명에 참여하는 모든 검증자의 집계된 증명을 나타냅니다. +- 검증자 - 증명을 제공한 검증자 +- 비콘 블록 루트 - 검증자가 증명하고 있는 블록을 가리킵니다. +- 소스 - 가장 최근에 정당화된 에포크를 가리킵니다. +- 타겟 - 가장 최근의 에포크 경계를 가리킵니다. +- Signature + +### 네트워크 {#network-1} + +합의 레이어의 최상위 데이터는 다음을 포함합니다. + +- Current epoch +- Current slot +- 활성 검증자 - 활성 검증자의 수 +- 대기 중인 검증자 - 활성화되기를 기다리는 검증자의 수 +- 스테이킹된 ETH - 네트워크에 스테이킹된 ETH의 양 +- 평균 잔액 - 검증자의 평균 ETH 잔액 + +## 블록 탐색기 {#block-explorers} + +- [Etherscan](https://etherscan.io/) - 이더리움 메인넷 및 테스트넷의 데이터를 가져오는 데 사용할 수 있는 블록 탐색기 +- [3xpl](https://3xpl.com/ethereum) - 데이터 세트 다운로드를 허용하는 광고 없는 오픈 소스 이더리움 탐색기 +- [Beaconcha.in](https://beaconcha.in/) - 이더리움 메인넷 및 테스트넷을 위한 오픈 소스 블록 탐색기 +- [Blockchair](https://blockchair.com/ethereum) - 가장 사적인 이더리움 탐색기입니다. (멤풀) 데이터 정렬 및 필터링에도 사용됩니다. +- [Etherchain](https://www.etherchain.org/) - 이더리움 메인넷을 위한 블록 탐색기 +- [Ethplorer](https://ethplorer.io/) - 이더리움 메인넷 및 Kovan 테스트넷의 토큰에 중점을 둔 블록 탐색기 + +## 더 읽어보기 {#further-reading} + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 관련 주제 {#related-topics} + +- [트랜잭션](/developers/docs/transactions/) +- [계정](/developers/docs/accounts/) +- [네트워크](/developers/docs/networks/) diff --git a/public/content/translations/ko/developers/docs/data-and-analytics/index.md b/public/content/translations/ko/developers/docs/data-and-analytics/index.md new file mode 100644 index 00000000000..0ffd93db9e7 --- /dev/null +++ b/public/content/translations/ko/developers/docs/data-and-analytics/index.md @@ -0,0 +1,72 @@ +--- +title: "데이터 및 분석" +description: "디앱에서 사용할 온체인 분석 및 데이터를 얻는 방법" +lang: ko +--- + +## 소개 {#Introduction} + +네트워크 사용량이 계속 증가함에 따라 온체인 데이터에 점점 더 많은 귀중한 정보가 존재하게 됩니다. 데이터 양이 급격히 증가함에 따라 이 정보를 계산하고 집계하여 보고하거나 디앱을 구동하는 것은 시간과 프로세스가 많이 소요되는 작업이 될 수 있습니다. + +기존 데이터 제공업체를 활용하면 개발 속도를 높이고, 더 정확한 결과를 산출하며, 지속적인 유지보수 노력을 줄일 수 있습니다. 이를 통해 팀은 프로젝트가 제공하려는 핵심 기능에 집중할 수 있습니다. + +## 필수 구성 요소 {#prerequisites} + +데이터 분석 컨텍스트에서 블록 탐색기를 사용하는 것을 더 잘 이해하려면 [블록 탐색기](/developers/docs/data-and-analytics/block-explorers/)의 기본 개념을 이해해야 합니다. 또한 시스템 설계에 추가되는 이점을 이해하려면 [인덱스](/glossary/#index) 개념에 익숙해져야 합니다. + +아키텍처 기본 측면에서 이론적으로라도 [API](https://www.wikipedia.org/wiki/API)와 [REST](https://www.wikipedia.org/wiki/Representational_state_transfer)가 무엇인지 이해해야 합니다. + +## 블록 탐색기 {#block-explorers} + +많은 [블록 탐색기](/developers/docs/data-and-analytics/block-explorers/)는 개발자에게 블록, 트랜잭션, 검증자, 계정 및 기타 온체인 활동에 대한 실시간 데이터를 제공하는 [RESTful](https://www.wikipedia.org/wiki/Representational_state_transfer) [API](https://www.wikipedia.org/wiki/API) 게이트웨이를 제공합니다. + +개발자는 이 데이터를 처리하고 변환하여 사용자에게 [블록체인](/glossary/#blockchain)에 대한 고유한 인사이트와 상호작용을 제공할 수 있습니다. 예를 들어, [Etherscan](https://etherscan.io)과 [Blockscout](https://eth.blockscout.com)은 매 12초 슬롯마다 실행 및 합의 데이터를 제공합니다. + +## The Graph {#the-graph} + +[The Graph](https://thegraph.com/)는 서브그래프라고 알려진 개방형 API를 통해 블록체인 데이터를 쉽게 쿼리할 수 있는 방법을 제공하는 인덱싱 프로토콜입니다. + +개발자는 The Graph를 통해 다음과 같은 이점을 얻을 수 있습니다. + +- 탈중앙화 인덱싱: 여러 인덱서를 통해 블록체인 데이터를 인덱싱할 수 있으므로 단일 실패 지점이 없습니다. +- GraphQL 쿼리: 인덱싱된 데이터를 쿼리하기 위한 강력한 GraphQL 인터페이스를 제공하여 데이터 검색을 매우 간단하게 만듭니다. +- 맞춤화: 블록체인 데이터를 변환하고 저장하기 위한 자체 로직을 정의하고 The Graph 네트워크에서 다른 개발자가 게시한 서브그래프를 재사용할 수 있습니다. + +이 [빠른 시작](https://thegraph.com/docs/en/quick-start/) 가이드를 따라 5분 이내에 서브그래프를 생성, 배포 및 쿼리하세요. + +## 클라이언트 다양성 {#client-diversity} + +[클라이언트 다양성](/developers/docs/nodes-and-clients/client-diversity/)은 버그 및 익스플로잇에 대한 복원력을 제공하기 때문에 이더리움 네트워크의 전반적인 상태에 중요합니다. 현재 [clientdiversity.org](https://clientdiversity.org/), [rated.network](https://www.rated.network), [supermajority.info](https://supermajority.info//) 및 [Ethernodes](https://ethernodes.org/)를 포함한 여러 클라이언트 다양성 대시보드가 있습니다. + +## Dune Analytics {#dune-analytics} + +[Dune Analytics](https://dune.com/)는 블록체인 데이터를 관계형 데이터베이스(DuneSQL) 테이블로 사전 처리하고, 사용자가 SQL을 사용하여 블록체인 데이터를 쿼리하고 쿼리 결과를 기반으로 대시보드를 구축할 수 있도록 합니다. 온체인 데이터는 `blocks`, `transactions`, (이벤트) `logs` 및 (호출) `traces`의 4가지 원시 테이블로 구성됩니다. 널리 사용되는 컨트랙트와 프로토콜은 디코딩되었으며, 각각 고유한 이벤트 및 호출 테이블 세트를 가지고 있습니다. 이러한 이벤트 및 호출 테이블은 프로토콜 유형(예: DEX, 대출, 스테이블코인 등)에 따라 추가로 처리되고 추상화 테이블로 구성됩니다. + +## SQD {#sqd} + +[SQD](https://sqd.dev/)는 대량의 데이터에 대한 효율적이고 무허가성 액세스를 제공하는 데 최적화된 탈중앙화된 초확장성 데이터 플랫폼입니다. 현재 이벤트 로그, 트랜잭션 영수증, 추적 및 트랜잭션별 상태 차이를 포함한 과거 온체인 데이터를 제공합니다. SQD는 맞춤형 데이터 추출 및 처리 파이프라인을 생성하기 위한 강력한 툴킷을 제공하며, 초당 최대 15만 블록의 인덱싱 속도를 달성합니다. + +시작하려면 [개발문서](https://docs.sqd.dev/)를 방문하거나 SQD로 구축할 수 있는 [EVM 예제](https://github.com/subsquid-labs/squid-evm-examples)를 참조하세요. + +## SubQuery 네트워크 {#subquery-network} + +[SubQuery](https://subquery.network/)는 개발자에게 웹3 프로젝트를 위한 빠르고, 신뢰할 수 있으며, 탈중앙화되고 맞춤화된 API를 제공하는 선도적인 데이터 인덱서입니다. SubQuery는 165개 이상의 생태계(이더리움 포함)의 개발자에게 풍부한 인덱싱된 데이터를 제공하여 사용자를 위한 직관적이고 몰입감 있는 경험을 구축할 수 있도록 지원합니다. SubQuery 네트워크는 복원력 있고 탈중앙화된 인프라 네트워크를 통해 멈출 수 없는 앱을 지원합니다. SubQuery의 블록체인 개발자 툴킷을 사용하여 데이터 처리 활동을 위한 맞춤형 백엔드를 구축하는 데 시간을 들이지 않고 미래의 웹3 애플리케이션을 구축하세요. + +시작하려면 [이더리움 빠른 시작 가이드](https://academy.subquery.network/quickstart/quickstart_chains/ethereum-gravatar.html)를 방문하여 [SubQuery의 관리 서비스](https://managedservice.subquery.network/) 또는 [SubQuery의 탈중앙화 네트워크](https://app.subquery.network/dashboard)에서 실시간으로 전환하기 전에 테스트를 위해 로컬 Docker 환경에서 몇 분 만에 이더리움 블록체인 데이터 인덱싱을 시작하세요. + +## EVM 쿼리 언어 {#evm-query-language} + +EVM 쿼리 언어(EQL)는 EVM(이더리움 가상 머신) 체인을 쿼리하도록 설계된 SQL과 유사한 언어입니다. EQL의 궁극적인 목표는 EVM 체인의 일급 시민(블록, 계정, 트랜잭션)에 대한 복잡한 관계형 쿼리를 지원하는 동시에 개발자와 연구원에게 일상적인 사용을 위한 인체공학적 구문을 제공하는 것입니다. EQL을 사용하면 개발자는 익숙한 SQL과 유사한 구문을 사용하여 블록체인 데이터를 가져올 수 있으며 복잡한 상용구 코드의 필요성을 없앨 수 있습니다. EQL은 표준 블록체인 데이터 요청(예: 이더리움에서 계정의 논스 및 잔액 검색 또는 현재 블록 크기 및 타임스탬프 가져오기)을 지원하며 더 복잡한 요청 및 기능 세트에 대한 지원을 지속적으로 추가하고 있습니다. + +## 추가 정보 {#further-reading} + +- [암호화폐 데이터 탐색 I: 데이터 흐름 아키텍처](https://web.archive.org/web/20250125012042/https://research.2077.xyz/exploring-crypto-data-1-data-flow-architectures) +- [Graph 네트워크 개요](https://thegraph.com/docs/en/about/) +- [Graph 쿼리 플레이그라운드](https://thegraph.com/explorer/subgraph/graphprotocol/graph-network-mainnet?version=current) +- [Etherscan의 API 코드 예제](https://etherscan.io/apis#contracts) +- [Blockscout의 API 개발문서](https://docs.blockscout.com/devs/apis) +- [Beaconcha.in 비콘 체인 탐색기](https://beaconcha.in) +- [Dune 기초](https://docs.dune.com/#dune-basics) +- [SubQuery 이더리움 빠른 시작 가이드](https://academy.subquery.network/indexer/quickstart/quickstart_chains/ethereum-gravatar.html) +- [SQD 네트워크 개요](https://docs.sqd.dev/) +- [EVM 쿼리 언어](https://eql.sh/blog/alpha-release-notes) diff --git a/public/content/translations/ko/developers/docs/data-availability/blockchain-data-storage-strategies/index.md b/public/content/translations/ko/developers/docs/data-availability/blockchain-data-storage-strategies/index.md new file mode 100644 index 00000000000..7bb23d3e34c --- /dev/null +++ b/public/content/translations/ko/developers/docs/data-availability/blockchain-data-storage-strategies/index.md @@ -0,0 +1,118 @@ +--- +title: "블록체인 데이터 저장 전략" +description: "블록체인을 사용하여 데이터를 저장하는 방법에는 여러 가지가 있습니다. 이 글에서는 다양한 전략, 비용 및 장단점, 그리고 안전한 사용을 위한 요구 사항을 비교합니다." +lang: ko +--- + +블록체인에 직접 정보를 저장하거나 블록체인에 의해 보호되는 방식으로 정보를 저장하는 방법에는 여러 가지가 있습니다. + +- EIP-4844 블롭 +- 콜데이터 +- L1 메커니즘을 사용한 오프체인 +- 계약 "코드" +- 이벤트 +- EVM 저장 공간 + +사용할 방법을 선택하는 기준은 다음과 같습니다. + +- 정보의 출처. 콜데이터의 정보는 블록체인 자체에서 직접 가져올 수 없습니다. +- 정보의 목적지. 콜데이터는 이를 포함하는 트랜잭션에서만 사용할 수 있습니다. 이벤트는 온체인에서 전혀 접근할 수 없습니다. +- 어느 정도의 번거로움이 허용됩니까? 전체 노드를 실행하는 컴퓨터는 브라우저에서 실행되는 애플리케이션의 라이트 클라이언트보다 더 많은 처리를 수행할 수 있습니다. +- 모든 노드에서 정보에 쉽게 접근할 수 있도록 해야 합니까? +- 보안 요구 사항. + +## 보안 요구 사항 {#security-requirements} + +일반적으로 정보 보안은 세 가지 속성으로 구성됩니다. + +- _기밀성_, 권한이 없는 주체는 정보를 읽을 수 없습니다. 이것은 많은 경우에 중요하지만 여기서는 그렇지 않습니다. _이더리움 상에 비공개 정보란 없습니다_. 블록체인은 누구나 상태 전환을 검증할 수 있기 때문에 작동하며, 따라서 비밀을 직접 저장하는 데 사용할 수 없습니다. 블록체인에 기밀 정보를 저장하는 방법이 있지만, 모두 키를 저장하기 위해 일부 오프체인 구성 요소에 의존합니다. + +- _무결성_, 정보는 정확하며, 권한 없는 주체에 의해 또는 권한 없는 방식(예: 'Transfer' 이벤트 없이 [ERC-20 토큰](https://eips.ethereum.org/EIPS/eip-20#events) 전송)으로 변경될 수 없습니다. 블록체인에서는 모든 노드가 모든 상태 변경을 검증하여 무결성을 보장합니다. + +- _가용성_, 정보는 모든 권한 있는 주체에게 제공됩니다. 블록체인에서는 일반적으로 모든 [전체 노드](https://ethereum.org/developers/docs/nodes-and-clients#full-node)에서 정보를 사용할 수 있도록 함으로써 이를 달성합니다. + +여기에 있는 다양한 솔루션은 모두 L1에 해시가 게시되므로 뛰어난 무결성을 가집니다. 그러나 가용성 보장은 서로 다릅니다. + +## 필수 구성 요소 {#prerequisites} + +[블록체인 기초](/developers/docs/intro-to-ethereum/)에 대한 충분한 이해가 있어야 합니다. 또한 이 페이지는 독자가 [블록](/developers/docs/blocks/), [트랜잭션](/developers/docs/transactions/) 및 기타 관련 주제에 익숙하다고 가정합니다. + +## EIP-4844 블롭 {#eip-4844-blobs} + +[Dencun 하드포크](https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/beacon-chain.md)를 시작으로 이더리움 블록체인에는 제한된 수명(초기 약 [18일](https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/p2p-interface.md#configuration))을 가진 데이터 블롭을 이더리움에 추가하는 [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844)가 포함됩니다. 이 블롭은 유사한 메커니즘을 사용하지만 [실행 가스](/developers/docs/gas)와는 별도로 가격이 책정됩니다. 임시 데이터를 게시하는 저렴한 방법입니다. + +EIP-4844 블롭의 주요 사용 사례는 롤업이 트랜잭션을 게시하는 것입니다. [낙관적 롤업](/developers/docs/scaling/optimistic-rollups)은 블록체인에 트랜잭션을 게시해야 합니다. 이러한 트랜잭션은 롤업의 [시퀀서](https://docs.optimism.io/connect/resources/glossary#sequencer)가 잘못된 상태 루트를 게시할 경우 [검증자](https://docs.optimism.io/connect/resources/glossary#validator)가 실수를 수정할 수 있도록 [챌린지 기간](https://docs.optimism.io/connect/resources/glossary#challenge-period) 동안 누구나 사용할 수 있어야 합니다. + +그러나 챌린지 기간이 지나고 상태 루트가 확정되면, 이러한 트랜잭션을 아는 것의 남은 목적은 체인의 현재 상태를 복제하는 것입니다. 이 상태는 체인 노드에서도 사용할 수 있으며, 처리 요구량이 훨씬 적습니다. 따라서 [블록 탐색기](/developers/docs/data-and-analytics/block-explorers)와 같은 몇 군데에는 트랜잭션 정보가 여전히 보존되어야 하지만, 이더리움이 제공하는 검열 저항성 수준에 대한 비용을 지불할 필요는 없습니다. + +[영지식 롤업](/developers/docs/scaling/zk-rollups/#data-availability)도 다른 노드가 기존 상태를 복제하고 유효성 증명을 검증할 수 있도록 트랜잭션 데이터를 게시하지만, 이 또한 단기적인 요구 사항입니다. + +작성 시점에 EIP-4844에 게시하는 비용은 바이트당 1wei(10-18 ETH)이며, 이는 블롭을 게시하는 트랜잭션을 포함한 모든 트랜잭션에 드는 [21,000 실행 가스](https://eth.blockscout.com/tx/0xf6cfaf0431c73dd1d96369a5e6707d64f463ccf477a4131265397f1d81466929?tab=index)와 비교하면 무시할 수 있는 수준입니다. 현재 EIP-4844 가격은 [blobscan.com](https://blobscan.com/blocks)에서 확인할 수 있습니다. + +다음은 유명 롤업이 게시한 블롭을 볼 수 있는 주소입니다. + +| 롤업 | 메일박스 주소 | +| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- | +| [Optimism](https://www.optimism.io/) | [`0xFF00000000000000000000000000000000000010`](https://blobscan.com/address/0xFF00000000000000000000000000000000000010) | +| [Arbitrum](https://arbitrum.io/) | [`0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6`](https://blobscan.com/address/0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6) | +| [Base](https://base.org/) | [`0xFF00000000000000000000000000000000008453`](https://blobscan.com/address/0xFF00000000000000000000000000000000008453) | + +## 콜데이터 {#calldata} + +콜데이터는 트랜잭션의 일부로 전송되는 바이트를 의미합니다. 이는 해당 트랜잭션을 포함하는 블록의 블록체인 영구 기록의 일부로 저장됩니다. + +이는 블록체인에 데이터를 영구적으로 저장하는 가장 저렴한 방법입니다. 바이트당 비용은 4 실행 가스(바이트가 0인 경우) 또는 16 가스(다른 값인 경우)입니다. 데이터가 압축되는 것이 일반적인 관행이라면 모든 바이트 값의 가능성이 동일하므로 평균 비용은 바이트당 약 15.95 가스입니다. + +작성 시점에서 가격은 12 gwei/가스 및 2300 $/ETH이며, 이는 킬로바이트당 약 45센트의 비용을 의미합니다. 이것이 EIP-4844 이전의 가장 저렴한 방법이었기 때문에, 롤업이 [오류 증명](https://docs.optimism.io/stack/protocol/overview#fault-proofs)을 위해 사용 가능한 트랜잭션 정보를 저장하는 데 사용한 방법이지만 온체인에서 직접 액세스할 필요는 없습니다. + +다음은 유명 롤업이 게시한 트랜잭션을 볼 수 있는 주소입니다. + +| 롤업 | 메일박스 주소 | +| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | +| [Optimism](https://www.optimism.io/) | [`0xFF00000000000000000000000000000000000010`](https://eth.blockscout.com/address/0xFF00000000000000000000000000000000000010) | +| [Arbitrum](https://arbitrum.io/) | [`0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6`](https://eth.blockscout.com/address/0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6) | +| [Base](https://base.org/) | [`0xFF00000000000000000000000000000000008453`](https://eth.blockscout.com/address/0xFF00000000000000000000000000000000008453) | + +## L1 메커니즘을 사용한 오프체인 {#offchain-with-l1-mechs} + +보안 장단점에 따라 정보를 다른 곳에 두고 필요할 때 데이터를 사용할 수 있도록 보장하는 메커니즘을 사용하는 것이 허용될 수 있습니다. 이것이 작동하기 위한 두 가지 요구 사항이 있습니다. + +1. 블록체인에 데이터의 [해시](https://en.wikipedia.org/wiki/Cryptographic_hash_function)를 게시하는 것을 입력 약정이라고 합니다. 이것은 단일 32바이트 단어일 수 있으므로 비싸지 않습니다. 입력 약정이 사용 가능한 한, 동일한 값으로 해시되는 다른 데이터를 찾는 것이 불가능하므로 무결성이 보장됩니다. 따라서 잘못된 데이터가 제공되면 감지할 수 있습니다. + +2. 가용성을 보장하는 메커니즘을 갖추십시오. 예를 들어, [Redstone](https://redstone.xyz/docs/what-is-redstone)에서는 모든 노드가 가용성 챌린지를 제출할 수 있습니다. 시퀀서가 마감일까지 온체인에서 응답하지 않으면 입력 약정은 폐기되므로 정보는 게시되지 않은 것으로 간주됩니다. + +상태 루트에 대해 최소 한 명의 정직한 검증자가 있다는 점에 이미 의존하고 있으므로 이는 낙관적 롤업에 허용됩니다. 이러한 정직한 검증자는 또한 블록을 처리할 데이터를 가지고 있는지 확인하고, 정보가 오프체인에서 사용 불가능한 경우 가용성 챌린지를 발행합니다. 이러한 유형의 낙관적 롤업은 [플라즈마](/developers/docs/scaling/plasma/)라고 합니다. + +## 계약 코드 {#contract-code} + +한 번만 작성하고 덮어쓰지 않으며 온체인에서 사용 가능해야 하는 정보는 계약 코드로 저장할 수 있습니다. 이는 데이터로 "스마트 계약"을 만들고 [`EXTCODECOPY`](https://www.evm.codes/#3c?fork=shanghai)를 사용하여 정보를 읽는 것을 의미합니다. 장점은 코드 복사 비용이 상대적으로 저렴하다는 것입니다. + +메모리 확장 비용 외에, `EXTCODECOPY`는 계약에 처음 액세스할 때(즉 "콜드" 상태일 때) 2,600 가스, 동일한 계약에서 후속 복사 시 100 가스, 그리고 32바이트 단어당 3 가스가 추가로 듭니다. 바이트당 15.95 가스가 드는 콜데이터와 비교할 때, 이는 약 200바이트부터 더 저렴합니다. [메모리 확장 비용 공식](https://www.evm.codes/about#memoryexpansion)에 따르면, 4MB 이상의 메모리가 필요하지 않는 한, 메모리 확장 비용은 콜데이터를 추가하는 비용보다 적습니다. + +물론 이것은 데이터를 _읽는_ 비용일 뿐입니다. 계약을 생성하는 데에는 약 32,000 가스 + 200 가스/바이트가 듭니다. 이 방법은 동일한 정보를 여러 다른 트랜잭션에서 여러 번 읽어야 할 때만 경제적입니다. + +`0xEF`로 시작하지 않는 한 계약 코드는 의미가 없을 수 있습니다. `0xEF`로 시작하는 계약은 훨씬 더 엄격한 요구 사항을 가진 [이더리움 객체 형식](https://notes.ethereum.org/@ipsilon/evm-object-format-overview)으로 해석됩니다. + +## 이벤트 {#events} + +[이벤트](https://docs.alchemy.com/docs/solidity-events)는 스마트 계약에서 방출되며 오프체인 소프트웨어에 의해 읽힙니다. +장점은 오프체인 코드가 이벤트를 수신할 수 있다는 것입니다. 비용은 [가스](https://www.evm.codes/#a0?fork=cancun)이며, 375에 데이터 바이트당 8 가스가 추가됩니다. 12 gwei/가스 및 2300 $/ETH에서, 이는 1센트에 킬로바이트당 22센트를 더한 값으로 환산됩니다. + +## 저장 공간 {#storage} + +스마트 계약은 [영구 저장 공간](https://docs.alchemy.com/docs/smart-contract-storage-layout#what-is-storage-memory)에 접근할 수 있습니다. 그러나 매우 비쌉니다. 이전에 비어 있던 저장 슬롯에 32바이트 단어를 쓰는 데 [22,100 가스가 들 수 있습니다](https://www.evm.codes/#55?fork=cancun). 12 gwei/가스 및 2300 $/ETH에서, 이는 쓰기 작업당 약 61센트, 또는 킬로바이트당 19.5달러입니다. + +이것은 이더리움에서 가장 비싼 형태의 저장 공간입니다. + +## 요약 {#summary} + +이 표는 다양한 옵션, 장점 및 단점을 요약합니다. + +| 저장 유형 | 데이터 소스 | 가용성 보장 | 온체인 가용성 | 추가 제한 사항 | +| ----------------- | ----------- | ----------------------------------------------------------------------------------------------------------------- | -------------------------------- | -------------------------------- | +| EIP-4844 블롭 | 오프체인 | [약 18일](https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/p2p-interface.md#configuration)간 이더리움 보장 | 해시만 사용 가능 | | +| 콜데이터 | 오프체인 | 이더리움 영구 보장(블록체인의 일부) | 계약에 기록된 경우, 그리고 해당 트랜잭션에서만 사용 가능 | | +| L1 메커니즘을 사용한 오프체인 | 오프체인 | 챌린지 기간 동안 "정직한 검증자 한 명" 보장 | 해시만 | 챌린지 기간 동안에만 챌린지 메커니즘에 의해 보장됨 | +| 계약 코드 | 온체인 또는 오프체인 | 이더리움 영구 보장(블록체인의 일부) | 네 | "임의의" 주소에 기록되며, `0xEF`로 시작할 수 없음 | +| 이벤트 | 온체인 | 이더리움 영구 보장(블록체인의 일부) | 아니오 | | +| 스토리지 | 온체인 | 이더리움 영구 보장(블록체인의 일부이며 덮어쓸 때까지 현재 상태 유지) | 네 | | diff --git a/public/content/translations/ko/developers/docs/data-availability/index.md b/public/content/translations/ko/developers/docs/data-availability/index.md new file mode 100644 index 00000000000..18fa3f223a4 --- /dev/null +++ b/public/content/translations/ko/developers/docs/data-availability/index.md @@ -0,0 +1,84 @@ +--- +title: "데이터 가용성" +description: "이더리움의 데이터 가용성과 관련된 문제 및 솔루션 개요" +lang: ko +--- + +"신뢰하지 말고, 검증하라"는 이더리움에서 흔히 사용되는 격언입니다. 이는 노드가 피어로부터 수신한 블록의 모든 트랜잭션을 실행하여 제안된 변경 사항이 노드에서 독립적으로 계산한 것과 정확히 일치하는지 확인함으로써 수신한 정보의 정확성을 독립적으로 확인할 수 있다는 생각에 기반합니다. 이는 노드가 블록 전송자의 정직성을 신뢰할 필요가 없다는 것을 의미합니다. 데이터가 누락된 경우에는 이것이 불가능합니다. + +데이터 가용성은 블록을 검증하는 데 필요한 데이터가 모든 네트워크 참여자에게 실제로 사용 가능하다는 것에 대해 사용자가 가질 수 있는 신뢰를 의미합니다. 이더리움 레이어 1의 풀 노드에게는 이것이 비교적 간단합니다. 풀 노드는 각 블록의 모든 데이터 사본을 다운로드하는데, 다운로드를 위해서는 데이터가 사용 _가능해야_ 합니다. 데이터가 누락된 블록은 블록체인에 추가되지 않고 폐기됩니다. 이것이 "온체인 데이터 가용성"이며 모놀리식 블록체인의 특징입니다. 풀 노드는 모든 트랜잭션을 직접 다운로드하고 실행하기 때문에 유효하지 않은 트랜잭션을 수락하도록 속일 수 없습니다. 그러나 모듈식 블록체인, 레이어 2 롤업 및 라이트 클라이언트의 경우 데이터 가용성 환경이 더 복잡하여 더 정교한 검증 절차가 필요합니다. + +## 필수 구성 요소 {#prerequisites} + +[블록체인 기본 사항](/developers/docs/intro-to-ethereum/)과 특히 [합의 메커니즘](/developers/docs/consensus-mechanisms/)에 대해 잘 이해하고 있어야 합니다. 또한 이 페이지에서는 독자가 [블록](/developers/docs/blocks/), [트랜잭션](/developers/docs/transactions/), [노드](/developers/docs/nodes-and-clients/), [확장 솔루션](/developers/docs/scaling/) 및 기타 관련 주제에 익숙하다고 가정합니다. + +## 데이터 가용성 문제 {#the-data-availability-problem} + +데이터 가용성 문제란 블록체인에 추가되는 트랜잭션 데이터의 요약된 형식이 실제로 유효한 트랜잭션 집합을 나타낸다는 것을 전체 네트워크에 증명해야 하지만 모든 노드가 모든 데이터를 다운로드할 필요는 없다는 것입니다. 전체 트랜잭션 데이터는 블록을 독립적으로 검증하는 데 필요하지만, 모든 노드에게 모든 트랜잭션 데이터를 다운로드하도록 요구하는 것은 확장성에 장벽이 됩니다. 데이터 가용성 문제에 대한 해결책은 데이터를 직접 다운로드하고 저장하지 않는 네트워크 참여자에게 검증을 위해 전체 트랜잭션 데이터를 사용할 수 있도록 했다는 충분한 보장을 제공하는 것을 목표로 합니다. + +[라이트 노드](/developers/docs/nodes-and-clients/light-clients) 및 [레이어 2 롤업](/developers/docs/scaling)은 강력한 데이터 가용성 보장이 필요하지만 트랜잭션 데이터를 직접 다운로드하고 처리할 수 없는 네트워크 참여자의 중요한 예입니다. 트랜잭션 데이터 다운로드를 피함으로써 라이트 노드를 가볍게 만들고 롤업이 효과적인 확장 솔루션이 될 수 있게 합니다. + +데이터 가용성은 블록 검증을 위해 상태 데이터를 다운로드하고 저장할 필요가 없는 미래의 ["상태 비저장"](/roadmap/statelessness) 이더리움 클라이언트에게도 중요한 문제입니다. 상태 비저장 클라이언트는 여전히 데이터가 _어딘가에서_ 사용 가능하고 올바르게 처리되었음을 확신해야 합니다. + +## 데이터 가용성 솔루션 {#data-availability-solutions} + +### 데이터 가용성 샘플링(DAS) {#data-availability-sampling} + +데이터 가용성 샘플링(DAS)은 개별 노드에 너무 많은 부담을 주지 않으면서 네트워크가 데이터의 가용성을 확인할 수 있는 방법입니다. 각 노드(스테이킹하지 않는 노드 포함)는 전체 데이터에서 무작위로 선택된 작은 하위 집합을 다운로드합니다. 샘플을 성공적으로 다운로드하면 모든 데이터를 사용할 수 있다는 것이 높은 신뢰도로 확인됩니다. 이는 데이터 소거 코딩에 의존하는데, 이는 주어진 데이터세트를 중복 정보로 확장하는 것입니다(이 작업은 데이터에 다항식으로 알려진 함수를 맞추고 추가 지점에서 해당 다항식을 평가하는 방식으로 수행됩니다). 이를 통해 필요할 때 중복 데이터에서 원본 데이터를 복구할 수 있습니다. 이 데이터 생성의 결과는 원본 데이터 중 _일부라도_ 사용할 수 없게 되면 확장된 데이터의 절반이 누락된다는 것입니다! 각 노드가 다운로드하는 데이터 샘플의 양을 조정하여 데이터의 절반 미만만 실제로 사용할 수 있는 _경우_ 각 클라이언트가 샘플링한 데이터 조각 중 하나 이상이 누락될 가능성이 _매우_ 높도록 할 수 있습니다. + +[전체 댕크샤딩](/roadmap/danksharding/#what-is-danksharding)이 구현된 후 DAS는 롤업 운영자가 트랜잭션 데이터를 사용할 수 있도록 보장하는 데 사용됩니다. 이더리움 노드는 위에서 설명한 중복 체계를 사용하여 블롭에 제공된 트랜잭션 데이터를 무작위로 샘플링하여 모든 데이터가 존재하는지 확인합니다. 라이트 클라이언트를 보호하기 위해 블록 생성자가 모든 데이터를 사용할 수 있도록 동일한 기술을 사용할 수도 있습니다. 마찬가지로 [제안자-빌더 분리](/roadmap/pbs) 하에서는 블록 빌더만 전체 블록을 처리해야 하며, 다른 검증자는 데이터 가용성 샘플링을 사용하여 검증하게 됩니다. + +### 데이터 가용성 위원회 {#data-availability-committees} + +데이터 가용성 위원회(DAC)는 데이터 가용성을 제공하거나 증명하는 신뢰할 수 있는 당사자입니다. DAC는 DAS 대신 사용되거나 [DAS와 함께](https://hackmd.io/@vbuterin/sharding_proposal#Why-not-use-just-committees-and-not-DAS) 사용될 수 있습니다. 위원회를 통해 제공되는 보안 보증은 특정 설정에 따라 다릅니다. 예를 들어, 이더리움은 무작위로 샘플링된 검증자 하위 집합을 사용하여 라이트 노드에 대한 데이터 가용성을 증명합니다. + +DAC는 일부 밸리디움에서도 사용됩니다. DAC는 데이터 사본을 오프라인으로 저장하는 신뢰할 수 있는 노드 집합입니다. 분쟁이 발생할 경우 DAC는 데이터를 사용할 수 있도록 해야 합니다. DAC의 구성원은 또한 해당 데이터가 실제로 사용 가능하다는 것을 증명하기 위해 온체인 증명을 게시합니다. 일부 밸리디움은 DAC를 지분 증명(PoS) 검증인 시스템으로 대체합니다. 여기서 누구나 검증자가 되어 데이터를 오프체인에 저장할 수 있습니다. 그러나 이들은 스마트 계약에 예치되는 '본드'를 제공해야 합니다. 검증자가 데이터를 보류하는 것과 같은 악의적인 행동이 발생할 경우, 본드가 삭감될 수 있습니다. 지분 증명 데이터 가용성 위원회는 정직한 행동을 직접적으로 장려하기 때문에 일반 DAC보다 훨씬 더 안전합니다. + +## 데이터 가용성 및 라이트 노드 {#data-availability-and-light-nodes} + +[라이트 노드](/developers/docs/nodes-and-clients/light-clients)는 블록 데이터를 다운로드하지 않고 수신하는 블록 헤더의 정확성을 검증해야 합니다. 이러한 가벼움의 대가는 풀 노드가 하는 것처럼 로컬에서 트랜잭션을 다시 실행하여 블록 헤더를 독립적으로 검증할 수 없다는 것입니다. + +이더리움 라이트 노드는 동기화 위원회에 할당된 512명의 검증자로 구성된 무작위 집합을 신뢰합니다. 동기화 위원회는 암호화 서명을 사용하여 헤더의 데이터가 정확하다는 신호를 라이트 클라이언트에 보내는 DAC 역할을 합니다. 매일 동기화 위원회는 새로 고쳐집니다. 각 블록 헤더는 라이트 노드에게 _다음_ 블록에 서명할 것으로 예상되는 검증자를 알려주므로 실제 동기화 위원회를 사칭하는 악의적인 그룹을 신뢰하도록 속일 수 없습니다. + +그러나 공격자가 어떻게든 악의적인 블록 헤더를 라이트 클라이언트에게 전달하고 정직한 동기화 위원회가 서명했다고 확신시킨다면 어떻게 될까요? 이 경우 공격자는 유효하지 않은 트랜잭션을 포함할 수 있으며, 라이트 클라이언트는 블록 헤더에 요약된 모든 상태 변경을 독립적으로 확인하지 않기 때문에 이를 맹목적으로 수락하게 됩니다. 이를 방지하기 위해 라이트 클라이언트는 사기 증명을 사용할 수 있습니다. + +이러한 사기 증명은 풀 노드가 네트워크를 통해 유효하지 않은 상태 전환이 전파되는 것을 보고 제안된 상태 전환이 주어진 트랜잭션 집합에서 발생할 수 없음을 보여주는 작은 데이터 조각을 신속하게 생성하여 해당 데이터를 피어에게 브로드캐스트하는 방식으로 작동합니다. 라이트 노드는 이러한 사기 증명을 포착하여 잘못된 블록 헤더를 폐기하고 풀 노드와 동일한 정직한 체인에 머무르도록 보장할 수 있습니다. + +이는 풀 노드가 전체 트랜잭션 데이터에 접근할 수 있어야 가능합니다. 잘못된 블록 헤더를 브로드캐스트하고 트랜잭션 데이터를 사용할 수 없게 만드는 공격자는 풀 노드가 사기 증명을 생성하는 것을 막을 수 있습니다. 풀 노드는 잘못된 블록에 대한 경고 신호를 보낼 수는 있지만, 증명을 생성할 데이터가 제공되지 않았기 때문에 증거로 경고를 뒷받침할 수는 없습니다! + +이 데이터 가용성 문제에 대한 해결책은 DAS입니다. 라이트 노드는 전체 상태 데이터의 아주 작은 무작위 청크를 다운로드하고 이 샘플을 사용하여 전체 데이터 세트가 사용 가능한지 확인합니다. N개의 무작위 청크를 다운로드한 후 전체 데이터 가용성을 잘못 가정할 실제 가능성을 계산할 수 있습니다([100개 청크의 경우 확률은 10^-30](https://dankradfeist.de/ethereum/2019/12/20/data-availability-checks.html)으로, 즉 믿을 수 없을 정도로 낮습니다). + +이 시나리오에서도 단 몇 바이트만 보류하는 공격은 무작위 데이터 요청을 하는 클라이언트에게 눈에 띄지 않을 수 있습니다. 소거 코딩은 제안된 상태 변경을 확인하는 데 사용할 수 있는 작은 누락 데이터 조각을 재구성하여 이 문제를 해결합니다. 그런 다음 재구성된 데이터를 사용하여 사기 증명을 구성하여 라이트 노드가 잘못된 헤더를 수락하는 것을 방지할 수 있습니다. + +**참고:** DAS 및 사기 증명은 아직 지분 증명 이더리움 라이트 클라이언트에 구현되지 않았지만, ZK-SNARK 기반 증명 형태일 가능성이 높은 로드맵에 포함되어 있습니다. 현재의 라이트 클라이언트는 DAC의 한 형태에 의존합니다. 즉, 동기화 위원회의 신원을 확인한 다음 수신한 서명된 블록 헤더를 신뢰합니다. + +## 데이터 가용성 및 레이어 2 롤업 {#data-availability-and-layer-2-rollups} + +[롤업](/glossary/#rollups)과 같은 [레이어 2 확장 솔루션](/layer-2/)은 트랜잭션을 오프체인으로 처리하여 트랜잭션 비용을 줄이고 이더리움의 처리량을 높입니다. 롤업 트랜잭션은 압축되어 이더리움에 일괄적으로 게시됩니다. 배치는 이더리움의 단일 트랜잭션에서 수천 개의 개별 오프체인 트랜잭션을 나타냅니다. 이를 통해 기본 레이어의 혼잡을 줄이고 사용자 수수료를 절감할 수 있습니다. + +그러나 이더리움에 게시된 '요약' 트랜잭션을 신뢰할 수 있으려면 제안된 상태 변경이 독립적으로 검증될 수 있고 모든 개별 오프체인 트랜잭션을 적용한 결과임이 확인되어야 합니다. 롤업 운영자가 이 검증을 위해 트랜잭션 데이터를 제공하지 않으면 이더리움에 잘못된 데이터를 전송할 수 있습니다. + +[낙관적 롤업](/developers/docs/scaling/optimistic-rollups/)은 압축된 트랜잭션 데이터를 이더리움에 게시하고 독립적인 검증자가 데이터를 확인할 수 있도록 일정 시간(보통 7일) 동안 기다립니다. 누군가 문제를 발견하면 사기 증명을 생성하여 롤업에 이의를 제기할 수 있습니다. 이렇게 하면 체인이 롤백되고 유효하지 않은 블록은 생략됩니다. 이는 데이터가 사용 가능한 경우에만 가능합니다. 현재 낙관적 롤업이 L1에 트랜잭션 데이터를 게시하는 방법에는 두 가지가 있습니다. 일부 롤업은 온체인에 영구적으로 존재하는 `CALLDATA`로 데이터를 영구적으로 사용할 수 있도록 합니다. EIP-4844가 구현되면서 일부 롤업은 트랜잭션 데이터를 더 저렴한 블롭 저장 공간에 게시합니다. 이것은 영구적인 저장 공간이 아닙니다. 독립 검증자는 이더리움 레이어 1에서 데이터가 삭제되기 전 약 18일 이내에 블롭을 쿼리하고 이의를 제기해야 합니다. 데이터 가용성은 이더리움 프로토콜에 의해 해당 짧은 고정 기간 동안만 보장됩니다. 그 이후에는 이더리움 생태계의 다른 주체들의 책임이 됩니다. 모든 노드는 블롭 데이터의 작은 무작위 샘플을 다운로드하여 DAS를 통해 데이터 가용성을 확인할 수 있습니다. + +[영지식(ZK) 롤업](/developers/docs/scaling/zk-rollups)은 [영지식 유효성 증명](/glossary/#zk-proof)이 상태 전환의 정확성을 보장하므로 트랜잭션 데이터를 게시할 필요가 없습니다. 그러나 상태 데이터에 접근하지 않으면 ZK 롤업의 기능(또는 상호작용)을 보장할 수 없기 때문에 데이터 가용성은 여전히 문제입니다. 예를 들어, 운영자가 롤업 상태에 대한 세부 정보를 보류하면 사용자는 자신의 잔액을 알 수 없습니다. 또한 새로 추가된 블록에 포함된 정보를 사용하여 상태 업데이트를 수행할 수 없습니다. + +## 데이터 가용성 대 데이터 검색 가능성 {#data-availability-vs-data-retrievability} + +데이터 가용성은 데이터 검색 가능성과 다릅니다. 데이터 가용성은 풀 노드가 특정 블록과 관련된 전체 트랜잭션 집합에 접근하고 이를 검증할 수 있다는 보장입니다. 그렇다고 해서 데이터에 영원히 접근할 수 있다는 의미는 아닙니다. + +데이터 검색 가능성은 노드가 블록체인에서 과거 정보를 검색하는 기능입니다. 이 과거 데이터는 새 블록을 검증하는 데 필요하지 않으며, 제네시스 블록에서 풀 노드를 동기화하거나 특정 과거 요청을 처리하는 데만 필요합니다. + +핵심 이더리움 프로토콜은 데이터 검색 가능성이 아닌 데이터 가용성에 주로 관심이 있습니다. 데이터 검색 가능성은 제3자가 운영하는 소수의 아카이브 노드를 통해 제공되거나 [포털 네트워크](https://www.ethportal.net/)와 같은 탈중앙화 파일 저장소를 사용하여 네트워크 전체에 분산될 수 있습니다. + +## 더 읽어보기 {#further-reading} + +- [데이터 가용성이란 무엇인가?](https://medium.com/blockchain-capital-blog/wtf-is-data-availability-80c2c95ded0f) +- [데이터 가용성이란 무엇인가?](https://coinmarketcap.com/academy/article/what-is-data-availability) +- [데이터 가용성 확인 입문](https://dankradfeist.de/ethereum/2019/12/20/data-availability-checks.html) +- [샤딩 + DAS 제안에 대한 설명](https://hackmd.io/@vbuterin/sharding_proposal#ELI5-data-availability-sampling) +- [데이터 가용성 및 소거 코딩에 대한 참고 사항](https://github.com/ethereum/research/wiki/A-note-on-data-availability-and-erasure-coding#can-an-attacker-not-circumvent-this-scheme-by-releasing-a-full-unavailable-block-but-then-only-releasing-individual-bits-of-data-as-clients-query-for-them) +- [데이터 가용성 위원회.](https://medium.com/starkware/data-availability-e5564c416424) +- [지분 증명 데이터 가용성 위원회.](https://blog.matter-labs.io/zkporter-a-breakthrough-in-l2-scaling-ed5e48842fbf) +- [데이터 검색 가능성 문제에 대한 해결책](https://notes.ethereum.org/@vbuterin/data_sharding_roadmap#Who-would-store-historical-data-under-sharding) +- [데이터 가용성: 또는 롤업이 어떻게 걱정을 멈추고 이더리움을 사랑하게 되었는가](https://web.archive.org/web/20250515194659/https://web.archive.org/web/20241108192208/https://research.2077.xyz/data-availability-or-how-rollups-learned-to-stop-worrying-and-love-ethereum) +- [EIP-7623: 콜데이터 비용 증가](https://web.archive.org/web/20250515194659/https://research.2077.xyz/eip-7623-increase-calldata-cost) diff --git a/public/content/translations/ko/developers/docs/data-structures-and-encoding/index.md b/public/content/translations/ko/developers/docs/data-structures-and-encoding/index.md new file mode 100644 index 00000000000..22362dde1b9 --- /dev/null +++ b/public/content/translations/ko/developers/docs/data-structures-and-encoding/index.md @@ -0,0 +1,32 @@ +--- +title: "데이터 구조 및 인코딩" +description: "기본적인 이더리움 데이터 구조에 대한 개요입니다." +lang: ko +sidebarDepth: 2 +--- + +이더리움은 대량의 데이터를 생성, 저장 및 전송합니다. 누구나 비교적 평범한 소비자 수준의 하드웨어에서 [노드를 실행](/run-a-node/)할 수 있도록 이 데이터는 표준화되고 메모리 효율적인 방식으로 형식화되어야 합니다. 이를 위해 이더리움 스택에서는 몇 가지 특정 데이터 구조가 사용됩니다. + +## 필수 구성 요소 {#prerequisites} + +이더리움의 기본 사항과 [클라이언트 소프트웨어](/developers/docs/nodes-and-clients/)를 이해해야 합니다. 네트워킹 레이어와 [이더리움 백서](/whitepaper/)에 익숙해지는 것을 권장합니다. + +## 데이터 구조 {#data-structures} + +### 패트리샤 머클 트라이 {#patricia-merkle-tries} + +패트리샤 머클 트라이는 키-값 쌍을 결정론적이고 암호학적으로 인증된 트라이로 인코딩하는 구조입니다. 이는 이더리움의 실행 레이어 전반에 걸쳐 광범위하게 사용됩니다. + +[패트리샤 머클 트라이에 대해 더 알아보기](/developers/docs/data-structures-and-encoding/patricia-merkle-trie) + +### 재귀 길이 접두어 {#recursive-length-prefix} + +재귀 길이 접두어(RLP)는 이더리움의 실행 레이어 전반에 걸쳐 광범위하게 사용되는 직렬화 방법입니다. + +[RLP에 대해 더 알아보기](/developers/docs/data-structures-and-encoding/rlp) + +### 단순 직렬화 {#simple-serialize} + +단순 직렬화(SSZ)는 머클화와의 호환성으로 인해 이더리움의 합의 레이어에서 주로 사용되는 직렬화 형식입니다. + +[SSZ에 대해 더 알아보기](/developers/docs/data-structures-and-encoding/ssz) diff --git a/public/content/translations/ko/developers/docs/data-structures-and-encoding/patricia-merkle-trie/index.md b/public/content/translations/ko/developers/docs/data-structures-and-encoding/patricia-merkle-trie/index.md new file mode 100644 index 00000000000..c4d5694a467 --- /dev/null +++ b/public/content/translations/ko/developers/docs/data-structures-and-encoding/patricia-merkle-trie/index.md @@ -0,0 +1,266 @@ +--- +title: "머클 패트리샤 트라이" +description: "머클 패트리샤 트라이 소개." +lang: ko +sidebarDepth: 2 +--- + +이더리움의 상태 (전체 계정, 잔액, 스마트 컨트랙트의 총합)는 일반적으로 컴퓨터 과학에서 머클 트리라고 알려진 데이터 구조의 특수한 버전에 인코딩됩니다. 이 구조는 트리에 얽혀있는 모든 개별 데이터 조각들 사이에 검증 가능한 관계를 생성하므로 암호학의 많은 응용 프로그램에 유용하며, 데이터에 대한 것들을 증명하는 데 사용할 수 있는 단일 **루트** 값을 생성합니다. + +이더리움의 데이터 구조는 '수정된 머클-패트리샤 트라이'입니다. 이는 PATRICIA(영숫자로 코딩된 정보 검색을 위한 실용적인 알고리즘)의 일부 기능을 차용했고, 이더리움 상태를 구성하는 항목들의 효율적인 데이터 re**trie**val(검색)을 위해 설계되었기 때문에 붙여진 이름입니다. + +머클-패트리샤 트라이는 결정론적이며 암호학적으로 검증 가능합니다. 상태 루트를 생성하는 유일한 방법은 상태의 각 개별 조각으로부터 계산하는 것이며, 동일한 두 상태는 루트 해시와 그에 이르는 해시(_머클 증명_)를 비교하여 쉽게 증명할 수 있습니다. 반대로, 서로 다른 상태가 같은 루트 해시를 가지는 일은 없으며, 상태 값이 조금이라도 바뀌면 루트 해시도 반드시 달라집니다. 이론적으로, 이 구조는 삽입, 조회 및 삭제에 대해 `O(log(n))` 효율성이라는 '성배'를 제공합니다. + +가까운 미래에 이더리움은 [버클 트리](/roadmap/verkle-trees) 구조로 마이그레이션할 계획이며, 이는 향후 프로토콜 개선을 위한 많은 새로운 가능성을 열 것입니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하려면 [해시](https://en.wikipedia.org/wiki/Hash_function), [머클 트리](https://en.wikipedia.org/wiki/Merkle_tree), [트라이](https://en.wikipedia.org/wiki/Trie), [직렬화](https://en.wikipedia.org/wiki/Serialization)에 대한 기본 지식이 있으면 도움이 됩니다. 이 문서는 기본 [래딕스 트리](https://en.wikipedia.org/wiki/Radix_tree)에 대한 설명으로 시작하여 이더리움의 더 최적화된 데이터 구조에 필요한 수정 사항을 점진적으로 소개합니다. + +## 기본 래딕스 트라이 {#basic-radix-tries} + +기본적인 radix trie에서 모든 노드는 다음과 같은 형태를 가집니다: + +``` + [i_0, i_1 ... i_n, value] +``` + +여기서 `i_0 ...` `i_n`은 알파벳의 기호(주로 이진 또는 16진수)를 나타내고, `value`는 노드의 터미널 값이며, `i_0, i_1 ...`에 있는 값은 `i_n` 슬롯은 `NULL`이거나 다른 노드에 대한 포인터(이 경우 해시)입니다. 이것은 기본적인 `(키, 값)` 저장소를 형성합니다. + +키-값 쌍 집합에 대한 순서를 유지하기 위해 래딕스 트리 데이터 구조를 사용한다고 가정해 보겠습니다. 트라이에서 `dog` 키에 현재 매핑된 값을 찾으려면 먼저 `dog`를 알파벳 문자로 변환(`64 6f 67`이 됨)한 다음 해당 경로를 따라 트라이를 내려가 값을 찾습니다. 즉, 플랫 키/값 DB에서 루트 해시를 조회하여 트라이의 루트 노드를 찾는 것으로 시작합니다. 이는 다른 노드를 가리키는 키의 배열로 표시됩니다. 인덱스 `6`의 값을 키로 사용하여 플랫 키/값 DB에서 조회하여 한 수준 아래의 노드를 가져옵니다. 그런 다음 인덱스 `4`를 선택하여 다음 값을 조회하고, 다음으로 인덱스 `6`을 선택하는 식으로 `root -> 6 -> 4 -> 6 -> 15 -> 6 -> 7` 경로를 따를 때까지 계속한 다음 노드의 값을 조회하고 결과를 반환합니다. + +'트라이'에서 무언가를 조회하는 것과 기본 플랫 키/값 'DB'에서 조회하는 것 사이에는 차이가 있습니다. 둘 다 키/값 배열을 정의하지만, 기본 DB는 키를 한 단계로 조회하는 전통적인 방식을 사용할 수 있습니다. 트라이에서 키를 조회하려면 위에서 설명한 최종 값에 도달하기 위해 여러 번의 기본 DB 조회가 필요합니다. 모호함을 없애기 위해 후자를 `path`라고 부르겠습니다. + +래딕스 트라이의 업데이트 및 삭제 작업은 다음과 같이 정의할 수 있습니다. + +```python + def update(node_hash, path, value): + curnode = db.get(node_hash) if node_hash else [NULL] * 17 + newnode = curnode.copy() + if path == "": + newnode[-1] = value + else: + newindex = update(curnode[path[0]], path[1:], value) + newnode[path[0]] = newindex + db.put(hash(newnode), newnode) + return hash(newnode) + + def delete(node_hash, path): + if node_hash is NULL: + return NULL + else: + curnode = db.get(node_hash) + newnode = curnode.copy() + if path == "": + newnode[-1] = NULL + else: + newindex = delete(curnode[path[0]], path[1:]) + newnode[path[0]] = newindex + + if all(x is NULL for x in newnode): + return NULL + else: + db.put(hash(newnode), newnode) + return hash(newnode) +``` + +'머클' 래딕스 트리는 결정론적으로 생성된 암호화 해시 다이제스트를 사용하여 노드를 연결하여 구축됩니다. 이 콘텐츠 주소 지정(키/값 DB에서 `key == keccak256(rlp(value))`)은 저장된 데이터의 암호화 무결성을 보장합니다. 주어진 트라이의 루트 해시가 공개적으로 알려진 경우, 기본 리프 데이터에 접근할 수 있는 사람은 누구나 특정 값을 트리 루트에 연결하는 각 노드의 해시를 제공하여 트라이가 특정 경로에 주어진 값을 포함한다는 증명을 구성할 수 있습니다. + +루트 해시는 궁극적으로 그 아래의 모든 해시를 기반으로 하므로 공격자가 존재하지 않는 `(path, value)` 쌍에 대한 증명을 제공하는 것은 불가능합니다. 기본적인 수정 사항이 있다면 루트 해시가 변경됩니다. 해시는 해싱 함수의 프리이미지 저항성에 의해 보호되는 데이터의 구조적 정보에 대한 압축된 표현이라고 생각할 수 있습니다. + +래딕스 트리의 원자 단위(예: 단일 16진수 문자 또는 4비트 이진수)를 '니블(nibble)'이라고 부릅니다. 위에서 설명한 대로 한 번에 한 니블씩 경로를 순회하는 동안 노드는 최대 16개의 자식을 참조할 수 있지만 `value` 요소를 포함합니다. 따라서 이를 길이 17의 배열로 표현합니다. 이 17개 요소 배열을 '브랜치 노드'라고 부릅니다. + +## 머클 패트리샤 트라이 {#merkle-patricia-trees} + +래딕스 트라이에는 한 가지 주요한 한계가 있습니다. 바로 비효율적이라는 점입니다. 이더리움에서처럼 경로가 64자 길이(`bytes32`의 니블 수)인 `(path, value)` 바인딩 하나를 저장하려면 문자당 한 레벨을 저장하기 위해 1킬로바이트 이상의 추가 공간이 필요하며, 각 조회 또는 삭제에는 전체 64단계가 소요됩니다. 다음에 소개되는 패트리샤 트라이는 이 문제를 해결합니다. + +### 최적화 {#optimization} + +머클 패트리샤 트라이의 노드는 다음 중 하나입니다. + +1. `NULL` (빈 문자열로 표시) +2. `branch` 17개 항목 노드 `[ v0 ...` v15, vt ]` +3. `leaf` 2개 항목 노드 `[ encodedPath, value ]` +4. `extension` 2개 항목 노드 `[ encodedPath, key ]` + +64자 경로를 사용하면 트라이의 처음 몇 개 레이어를 순회한 후, 적어도 일부 경로에서는 분기 경로가 존재하지 않는 노드에 도달하는 것이 불가피합니다. 경로를 따라 최대 15개의 희소한 `NULL` 노드를 생성하지 않도록 `[ encodedPath, key ]` 형식의 `extension` 노드를 설정하여 내려가는 과정을 단축합니다. 여기서 `encodedPath`는 건너뛸 '부분 경로'(아래 설명된 간결한 인코딩 사용)를 포함하고, `key`는 다음 DB 조회를 위한 것입니다. + +`encodedPath`의 첫 번째 니블에 있는 플래그로 표시될 수 있는 `leaf` 노드의 경우, 경로는 모든 이전 노드의 경로 조각을 인코딩하며 `value`를 직접 조회할 수 있습니다. + +그러나 위의 최적화는 모호성을 야기합니다. + +경로를 니블 단위로 순회할 때 순회할 니블의 수가 홀수가 될 수 있지만, 모든 데이터는 `bytes` 형식으로 저장됩니다. 예를 들어, 니블 `1`과 니블 `01`을 구별할 수 없습니다(둘 다 `<01>`로 저장되어야 함). 홀수 길이를 지정하기 위해 부분 경로에는 플래그가 접두사로 붙습니다. + +### 사양: 선택적 종결자가 있는 16진수 시퀀스의 간결한 인코딩 {#specification} + +위에서 설명한 _홀수 대 짝수 남은 부분 경로 길이_와 _리프 대 확장 노드_의 플래그 지정은 모두 2개 항목 노드의 부분 경로의 첫 번째 니블에 있습니다. 결과는 다음과 같습니다. + +| 16진수 문자 | 비트 | 노드 유형 | 경로 길이 | +| ------- | ---- | -------------------------- | ----- | +| 0 | 0000 | 확장 | 짝수 | +| 1 | 0001 | 확장 | 홀수 | +| 2 | 0010 | 종결 (리프) | 짝수 | +| 3 | 0011 | 종결 (리프) | 홀수 | + +남은 경로 길이가 짝수(`0` 또는 `2`)인 경우, 항상 다른 `0` '패딩' 니블이 뒤따릅니다. + +```python + def compact_encode(hexarray): + term = 1 if hexarray[-1] == 16 else 0 + if term: + hexarray = hexarray[:-1] + oddlen = len(hexarray) % 2 + flags = 2 * term + oddlen + if oddlen: + hexarray = [flags] + hexarray + else: + hexarray = [flags] + [0] + hexarray + # hexarray now has an even length whose first nibble is the flags. + o = "" + for i in range(0, len(hexarray), 2): + o += chr(16 * hexarray[i] + hexarray[i + 1]) + return o +``` + +예시: + +```python + > [1, 2, 3, 4, 5, ...] + '11 23 45' + > [0, 1, 2, 3, 4, 5, ...] + '00 01 23 45' + > [0, f, 1, c, b, 8, 10] + '20 0f 1c b8' + > [f, 1, c, b, 8, 10] + '3f 1c b8' +``` + +다음은 머클 패트리샤 트라이에서 노드를 가져오는 확장 코드입니다. + +```python + def get_helper(node_hash, path): + if path == []: + return node_hash + if node_hash == "": + return "" + curnode = rlp.decode(node_hash if len(node_hash) < 32 else db.get(node_hash)) + if len(curnode) == 2: + (k2, v2) = curnode + k2 = compact_decode(k2) + if k2 == path[: len(k2)]: + return get(v2, path[len(k2) :]) + else: + return "" + elif len(curnode) == 17: + return get_helper(curnode[path[0]], path[1:]) + + def get(node_hash, path): + path2 = [] + for i in range(len(path)): + path2.push(int(ord(path[i]) / 16)) + path2.push(ord(path[i]) % 16) + path2.push(16) + return get_helper(node_hash, path2) +``` + +### 트라이 예시 {#example-trie} + +네 개의 경로/값 쌍 `('do', 'verb')`, `('dog', 'puppy')`, `('doge', 'coins')`, `('horse', 'stallion')`을 포함하는 트라이를 원한다고 가정해 보겠습니다. + +먼저, 경로와 값을 모두 `bytes`로 변환합니다. 아래에서 _경로_의 실제 바이트 표현은 `<>`로 표시되지만, _값_은 이해를 돕기 위해 여전히 문자열로 표시되며 `''`로 표시됩니다(실제로는 이들도 `bytes`가 됩니다). + +``` + <64 6f> : 'verb' + <64 6f 67> : 'puppy' + <64 6f 67 65> : 'coins' + <68 6f 72 73 65> : 'stallion' +``` + +이제 기본 DB에서 다음 키/값 쌍으로 이러한 트라이를 구축합니다. + +``` + rootHash: [ <16>, hashA ] + hashA: [ <>, <>, <>, <>, hashB, <>, <>, <>, [ <20 6f 72 73 65>, 'stallion' ], <>, <>, <>, <>, <>, <>, <>, <> ] + hashB: [ <00 6f>, hashC ] + hashC: [ <>, <>, <>, <>, <>, <>, hashD, <>, <>, <>, <>, <>, <>, <>, <>, <>, 'verb' ] + hashD: [ <17>, [ <>, <>, <>, <>, <>, <>, [ <35>, 'coins' ], <>, <>, <>, <>, <>, <>, <>, <>, <>, 'puppy' ] ] +``` + +한 노드가 다른 노드 내에서 참조될 때 포함되는 것은 `len(rlp.encode(node)) >= 32`인 경우 `keccak256(rlp.encode(node))`이고, 그렇지 않으면 `node`입니다. 여기서 `rlp.encode`는 [RLP](/developers/docs/data-structures-and-encoding/rlp) 인코딩 함수입니다. + +트라이를 업데이트할 때, 새로 생성된 노드의 길이가 32보다 크거나 같은 경우 영구 조회 테이블에 키/값 쌍 `(keccak256(x), x)`를 저장해야 합니다. 그러나 노드가 그보다 짧으면 f(x) = x 함수는 가역적이므로 아무것도 저장할 필요가 없습니다. + +## 이더리움의 트라이 {#tries-in-ethereum} + +이더리움 실행 레이어의 모든 머클 트라이는 머클 패트리샤 트라이를 사용합니다. + +블록 헤더에는 이 트라이들 중 3개의 루트가 있습니다. + +1. stateRoot +2. transactionsRoot +3. receiptsRoot + +### 상태 트라이 {#state-trie} + +하나의 전역 상태 트라이가 있으며, 클라이언트가 블록을 처리할 때마다 업데이트됩니다. 여기서 `path`는 항상 `keccak256(ethereumAddress)`이고 `value`는 항상 `rlp(ethereumAccount)`입니다. 더 구체적으로, 이더리움 `account`는 `[nonce,balance,storageRoot,codeHash]`의 4개 항목 배열입니다. 이 시점에서 이 `storageRoot`는 다른 패트리샤 트라이의 루트라는 점을 주목할 가치가 있습니다. + +### 스토리지 트라이 {#storage-trie} + +스토리지 트라이는 _모든_ 컨트랙트 데이터가 있는 곳입니다. 각 계정마다 별도의 스토리지 트라이가 있습니다. 주어진 주소의 특정 스토리지 위치에서 값을 검색하려면 스토리지 주소, 스토리지에 저장된 데이터의 정수 위치 및 블록 ID가 필요합니다. 그런 다음 이를 JSON-RPC API에 정의된 `eth_getStorageAt`에 인수로 전달할 수 있습니다. 예를 들어, 주소 `0x295a70b2de5e3953354a6a8344e616ed314d7251`의 스토리지 슬롯 0에 있는 데이터를 검색하려면 다음과 같이 합니다. + +```bash +curl -X POST --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x0", "latest"], "id": 1}' localhost:8545 + +{"jsonrpc":"2.0","id":1,"result":"0x00000000000000000000000000000000000000000000000000000000000004d2"} + +``` + +스토리지의 다른 요소를 검색하는 것은 스토리지 트라이에서의 위치를 먼저 계산해야 하므로 약간 더 복잡합니다. 위치는 주소와 스토리지 위치의 `keccak256` 해시로 계산되며, 둘 다 32바이트 길이가 되도록 왼쪽에 0으로 채워집니다. 예를 들어, 주소 `0x391694e7e0b0cce554cb130d723a9d27458f9298`의 스토리지 슬롯 1에 있는 데이터의 위치는 다음과 같습니다. + +```python +keccak256(decodeHex("000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + "0000000000000000000000000000000000000000000000000000000000000001")) +``` + +Geth 콘솔에서는 다음과 같이 계산할 수 있습니다. + +``` +> var key = "000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + "0000000000000000000000000000000000000000000000000000000000000001" +undefined +> web3.sha3(key, {"encoding": "hex"}) +"0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9" +``` + +`path`는 따라서 `keccak256(<6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9>)`입니다. 이제 이것을 사용하여 이전과 같이 스토리지 트라이에서 데이터를 검색할 수 있습니다. + +```bash +curl -X POST --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9", "latest"], "id": 1}' localhost:8545 + +{"jsonrpc":"2.0","id":1,"result":"0x000000000000000000000000000000000000000000000000000000000000162e"} +``` + +참고: 이더리움 계정의 `storageRoot`는 컨트랙트 계정이 아닌 경우 기본적으로 비어 있습니다. + +### 트랜잭션 트라이 {#transaction-trie} + +모든 블록에는 별도의 트랜잭션 트라이가 있으며, 여기에도 `(키, 값)` 쌍이 저장됩니다. 여기서 경로는 `rlp(transactionIndex)`이며, 이는 다음에 의해 결정되는 값에 해당하는 키를 나타냅니다. + +```python +if legacyTx: + value = rlp(tx) +else: + value = TxType | encode(tx) +``` + +이에 대한 자세한 내용은 [EIP 2718](https://eips.ethereum.org/EIPS/eip-2718) 문서에서 찾을 수 있습니다. + +### 영수증 트라이 {#receipts-trie} + +모든 블록에는 자체 영수증 트라이가 있습니다. 여기서 `path`는 `rlp(transactionIndex)`입니다. `transactionIndex`는 포함된 블록 내에서의 인덱스입니다. 영수증 트라이는 절대 업데이트되지 않습니다. 트랜잭션 트라이와 유사하게 현재 및 레거시 영수증이 있습니다. 영수증 트라이에서 특정 영수증을 쿼리하려면 해당 블록 내 트랜잭션의 인덱스, 영수증 페이로드 및 트랜잭션 유형이 필요합니다. 반환된 영수증은 `TransactionType`과 `ReceiptPayload`의 연결로 정의되는 `Receipt` 유형이거나 `rlp([status, cumulativeGasUsed, logsBloom, logs])`로 정의되는 `LegacyReceipt` 유형일 수 있습니다. + +이에 대한 자세한 내용은 [EIP 2718](https://eips.ethereum.org/EIPS/eip-2718) 문서에서 찾을 수 있습니다. + +## 추가 정보 {#further-reading} + +- [수정된 머클 패트리샤 트라이 — 이더리움이 상태를 저장하는 방법](https://medium.com/codechain/modified-merkle-patricia-trie-how-ethereum-saves-a-state-e6d7555078dd) +- [이더리움의 머클링](https://blog.ethereum.org/2015/11/15/merkling-in-ethereum/) +- [이더리움 트라이 이해하기](https://easythereentropy.wordpress.com/2014/06/04/understanding-the-ethereum-trie/) diff --git a/public/content/translations/ko/developers/docs/data-structures-and-encoding/rlp/index.md b/public/content/translations/ko/developers/docs/data-structures-and-encoding/rlp/index.md new file mode 100644 index 00000000000..bd47f082432 --- /dev/null +++ b/public/content/translations/ko/developers/docs/data-structures-and-encoding/rlp/index.md @@ -0,0 +1,163 @@ +--- +title: "재귀 길이 접두어(RLP) 직렬화" +description: "이더리움 실행 레이어의 rlp 인코딩에 대한 정의입니다." +lang: ko +sidebarDepth: 2 +--- + +재귀 길이 접두어(RLP) 직렬화는 이더리움의 실행 클라이언트에서 광범위하게 사용됩니다. RLP는 공간 효율적인 형식으로 노드 간의 데이터 전송을 표준화합니다. RLP의 목적은 임의로 중첩된 바이너리 데이터 배열을 인코딩하는 것이며, 이더리움의 실행 레이어에서 객체를 직렬화하는 데 사용되는 기본 인코딩 방법입니다. RLP의 주요 목적은 구조를 인코딩하는 것입니다. 양의 정수를 제외하고 RLP는 특정 데이터 유형(예: 문자열, 부동 소수점)의 인코딩을 상위 수준 프로토콜에 위임합니다. 양의 정수는 선행 0이 없는 빅엔디언 바이너리 형식으로 표시되어야 합니다(따라서 정수 값 0은 빈 바이트 배열과 동일합니다). 선행 0이 있는 역직렬화된 양의 정수는 RLP를 사용하는 모든 상위 프로토콜에서 유효하지 않은 것으로 처리되어야 합니다. + +자세한 내용은 [이더리움 황서(부록 B)](https://ethereum.github.io/yellowpaper/paper.pdf#page=19)를 참조하세요. + +RLP를 사용하여 사전을 인코딩하려면 다음과 같은 두 가지 표준 형식을 사용할 수 있습니다. + +- 사전순으로 정렬된 키와 함께 `[[k1,v1],[k2,v2]...]` 사용 +- 이더리움에서처럼 상위 수준의 패트리샤 트리 인코딩 사용 + +## 정의 {#definition} + +RLP 인코딩 함수는 항목을 입력받습니다. 항목은 다음과 같이 정의됩니다: + +- 문자열(즉, 바이트 배열)은 항목입니다 +- 항목의 리스트는 항목입니다 +- 양의 정수는 항목입니다 + +예를 들어, 다음은 모두 항목입니다. + +- 빈 문자열; +- 'cat'이라는 단어를 포함하는 문자열; +- 임의의 개수의 문자열을 포함하는 리스트; +- 그리고 `["cat", ["puppy", "cow"], "horse", [[]], "pig", [""], "sheep"]`와 같은 더 복잡한 자료 구조. +- 숫자 `100` + +이 페이지의 나머지 컨텍스트에서 '문자열'은 "특정 바이트 수의 이진 데이터"를 의미합니다. 특별한 인코딩은 사용되지 않으며, 문자열의 내용에 대한 정보는 암시되지 않습니다(최소 크기가 아닌 양의 정수에 대한 규칙에서 요구하는 경우는 제외). + +RLP 인코딩은 다음과 같이 정의됩니다. + +- 양의 정수의 경우, 빅엔디언으로 해석했을 때 해당 정수가 되는 가장 짧은 바이트 배열로 변환된 다음, 아래 규칙에 따라 문자열로 인코딩됩니다. +- `[0x00, 0x7f]`(10진수 `[0, 127]`) 범위의 값을 갖는 단일 바이트의 경우, 해당 바이트 자체가 RLP 인코딩입니다. +- 그렇지 않고 문자열의 길이가 0-55바이트인 경우, RLP 인코딩은 **0x80**(10진수 128) 값에 문자열의 길이를 더한 단일 바이트와 그 뒤에 오는 문자열로 구성됩니다. 따라서 첫 번째 바이트의 범위는 `[0x80, 0xb7]`(10진수 `[128, 183]`)입니다. +- 문자열 길이가 55바이트보다 긴 경우, RLP 인코딩은 **0xb7**(10진수 183) 값에 문자열 길이를 이진 형식으로 나타낸 값의 바이트 수를 더한 단일 바이트와, 그 뒤에 오는 문자열의 길이, 그 뒤에 오는 문자열로 구성됩니다. 예를 들어, 1024바이트 길이의 문자열은 `\xb9\x04\x00`(10진수 `185, 4, 0`) 다음에 문자열이 오는 형태로 인코딩됩니다. 여기서 첫 번째 바이트는 `0xb9`(183 + 2 = 185)이고, 그 뒤에는 실제 문자열의 길이를 나타내는 2바이트 `0x0400`(10진수 1024)이 옵니다. 따라서 첫 번째 바이트의 범위는 `[0xb8, 0xbf]`(10진수 `[184, 191]`)입니다. +- 문자열 길이가 2^64바이트 이상이면 인코딩할 수 없습니다. +- 리스트의 총 페이로드(즉, RLP 인코딩된 모든 항목의 길이를 합한 길이)가 0-55바이트인 경우, RLP 인코딩은 **0xc0** 값에 페이로드의 길이를 더한 단일 바이트와 그 뒤에 오는 항목들의 RLP 인코딩 연결로 구성됩니다. 따라서 첫 번째 바이트의 범위는 `[0xc0, 0xf7]`(10진수 `[192, 247]`)입니다. +- 리스트의 총 페이로드가 55바이트보다 긴 경우, RLP 인코딩은 **0xf7** 값에 페이로드 길이를 이진 형식으로 나타낸 값의 바이트 수를 더한 단일 바이트와, 그 뒤에 오는 페이로드의 길이, 그 뒤에 오는 항목들의 RLP 인코딩 연결로 구성됩니다. 따라서 첫 번째 바이트의 범위는 `[0xf8, 0xff]`(10진수 `[248, 255]`)입니다. + +코드는 다음과 같습니다. + +```python +def rlp_encode(input): + if isinstance(input,str): + if len(input) == 1 and ord(input) < 0x80: + return input + return encode_length(len(input), 0x80) + input + elif isinstance(input, list): + output = '' + for item in input: + output += rlp_encode(item) + return encode_length(len(output), 0xc0) + output + +def encode_length(L, offset): + if L < 56: + return chr(L + offset) + elif L < 256**8: + BL = to_binary(L) + return chr(len(BL) + offset + 55) + BL + raise Exception("input too long") + +def to_binary(x): + if x == 0: + return '' + return to_binary(int(x / 256)) + chr(x % 256) +``` + +## 예시 {#examples} + +- 문자열 "dog" = [ 0x83, 'd', 'o', 'g' ] +- 리스트 [ "cat", "dog" ] = `[ 0xc8, 0x83, 'c', 'a', 't', 0x83, 'd', 'o', 'g' ]` +- 빈 문자열('null') = `[ 0x80 ]` +- 빈 리스트 = `[ 0xc0 ]` +- 정수 0 = `[ 0x80 ]` +- 바이트 '\\x00' = `[ 0x00 ]` +- 바이트 '\\x0f' = `[ 0x0f ]` +- 바이트 '\\x04\\x00' = `[ 0x82, 0x04, 0x00 ]` +- 3의 [집합론적 표현](http://en.wikipedia.org/wiki/Set-theoretic_definition_of_natural_numbers), `[ [], [[]], [ [], [[]] ] ] = [ 0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0 ]` +- 문자열 "Lorem ipsum dolor sit amet, consectetur adipisicing elit" = `[ 0xb8, 0x38, 'L', 'o', 'r', 'e', 'm', ' ', ...` , 'e', 'l', 'i', 't' ]` + +## RLP 디코딩 {#rlp-decoding} + +RLP 인코딩의 규칙과 프로세스에 따라, RLP 디코딩의 입력은 이진 데이터의 배열로 간주됩니다. RLP 디코딩 프로세스는 다음과 같습니다. + +1. 입력 데이터의 첫 바이트(즉, 접두사)에 따라 데이터 유형, 실제 데이터의 길이 및 오프셋을 디코딩합니다. + +2. 데이터의 유형과 오프셋에 따라 데이터를 그에 맞게 디코딩하며, 양의 정수에 대한 최소 인코딩 규칙을 준수합니다. + +3. 입력의 나머지 부분을 계속 디코딩합니다. + +그중에서 데이터 유형 및 오프셋 디코딩 규칙은 다음과 같습니다. + +1. 첫 바이트(즉, 접두사)의 범위가 [0x00, 0x7f]인 경우 데이터는 문자열이며, 문자열은 첫 바이트 그 자체입니다. + +2. 첫 바이트의 범위가 [0x80, 0xb7]인 경우 데이터는 문자열이며, 첫 바이트에서 0x80을 뺀 값과 길이가 같은 문자열이 첫 바이트 뒤에 옵니다. + +3. 첫 바이트의 범위가 [0xb8, 0xbf]인 경우 데이터는 문자열이며, 첫 바이트에서 0xb7을 뺀 값과 바이트 길이가 같은 문자열의 길이가 첫 바이트 뒤에 오고, 문자열은 문자열 길이 뒤에 옵니다. + +4. 첫 바이트의 범위가 [0xc0, 0xf7]인 경우 데이터는 리스트이며, 총 페이로드가 첫 바이트에서 0xc0을 뺀 값과 같은 리스트의 모든 항목에 대한 RLP 인코딩의 연결이 첫 바이트 뒤에 옵니다. + +5. 첫 바이트의 범위가 [0xf8, 0xff]인 경우 데이터는 리스트이며, 길이가 첫 바이트에서 0xf7을 뺀 값과 같은 리스트의 총 페이로드가 첫 바이트 뒤에 오고, 리스트의 모든 항목의 RLP 인코딩 연결이 리스트의 총 페이로드 뒤에 옵니다. + +코드는 다음과 같습니다. + +```python +def rlp_decode(input): + if len(input) == 0: + return + output = '' + (offset, dataLen, type) = decode_length(input) + if type is str: + output = instantiate_str(substr(input, offset, dataLen)) + elif type is list: + output = instantiate_list(substr(input, offset, dataLen)) + output += rlp_decode(substr(input, offset + dataLen)) + return output + +def decode_length(input): + length = len(input) + if length == 0: + raise Exception("input is null") + prefix = ord(input[0]) + if prefix <= 0x7f: + return (0, 1, str) + elif prefix <= 0xb7 and length > prefix - 0x80: + strLen = prefix - 0x80 + return (1, strLen, str) + elif prefix <= 0xbf and length > prefix - 0xb7 and length > prefix - 0xb7 + to_integer(substr(input, 1, prefix - 0xb7)): + lenOfStrLen = prefix - 0xb7 + strLen = to_integer(substr(input, 1, lenOfStrLen)) + return (1 + lenOfStrLen, strLen, str) + elif prefix <= 0xf7 and length > prefix - 0xc0: + listLen = prefix - 0xc0; + return (1, listLen, list) + elif prefix <= 0xff and length > prefix - 0xf7 and length > prefix - 0xf7 + to_integer(substr(input, 1, prefix - 0xf7)): + lenOfListLen = prefix - 0xf7 + listLen = to_integer(substr(input, 1, lenOfListLen)) + return (1 + lenOfListLen, listLen, list) + raise Exception("input does not conform to RLP encoding form") + +def to_integer(b): + length = len(b) + if length == 0: + raise Exception("input is null") + elif length == 1: + return ord(b[0]) + return ord(substr(b, -1)) + to_integer(substr(b, 0, -1)) * 256 +``` + +## 더 읽어보기 {#further-reading} + +- [이더리움의 RLP](https://medium.com/coinmonks/data-structure-in-ethereum-episode-1-recursive-length-prefix-rlp-encoding-decoding-d1016832f919) +- [이더리움 내부 구조: RLP](https://medium.com/coinmonks/ethereum-under-the-hood-part-3-rlp-decoding-df236dc13e58) +- Coglio, A. (2020). ACL2의 이더리움 재귀 길이 접두어. arXiv 사전 인쇄 arXiv:2009.13769.](https://arxiv.org/abs/2009.13769) + +## 관련 주제 {#related-topics} + +- [패트리샤 머클 트리](/developers/docs/data-structures-and-encoding/patricia-merkle-trie) diff --git a/public/content/translations/ko/developers/docs/data-structures-and-encoding/ssz/index.md b/public/content/translations/ko/developers/docs/data-structures-and-encoding/ssz/index.md new file mode 100644 index 00000000000..fd6f8f80788 --- /dev/null +++ b/public/content/translations/ko/developers/docs/data-structures-and-encoding/ssz/index.md @@ -0,0 +1,149 @@ +--- +title: "간단 직렬화" +description: "이더리움의 SSZ 형식에 대한 설명입니다." +lang: ko +sidebarDepth: 2 +--- + +간단 직렬화(SSZ)는 비콘 체인에서 사용되는 직렬화 방법입니다. 피어 검색 프로토콜을 제외하고 합의 레이어 전반의 실행 레이어에서 사용되는 RLP 직렬화를 대체합니다. RLP 직렬화에 대해 자세히 알아보려면 [재귀 길이 접두사(RLP)](/developers/docs/data-structures-and-encoding/rlp/)를 참조하세요. SSZ는 결정론적이며 효율적으로 머클화되도록 설계되었습니다. SSZ는 직렬화 방식과 직렬화된 데이터 구조와 효율적으로 작동하도록 설계된 머클화 방식의 두 가지 구성 요소를 갖는 것으로 생각할 수 있습니다. + +## SSZ는 어떻게 작동하나요? {#how-does-ssz-work} + +### 직렬화 {#serialization} + +SSZ는 자체 서술적이지 않은 직렬화 방식이며, 사전에 알려져야 하는 스키마에 의존합니다. SSZ 직렬화의 목표는 임의의 복잡성을 가진 객체를 바이트 문자열로 표현하는 것입니다. 이는 "기본 유형"에 대한 매우 간단한 프로세스입니다. 요소는 단순히 16진수 바이트로 변환됩니다. 기본 유형은 다음과 같습니다. + +- 부호 없는 정수 +- 불리언 + +복잡한 "복합" 유형의 경우, 복합 유형에 유형이나 크기가 다르거나 둘 다 다른 여러 요소가 포함되어 있으므로 직렬화가 더 복잡합니다. 이러한 객체가 모두 고정된 길이(즉, 요소의 크기가 실제 값에 관계없이 항상 일정함)를 갖는 경우 직렬화는 단순히 복합 유형의 각 요소를 리틀엔디언 바이트 문자열로 순서대로 변환하는 것입니다. 이러한 바이트 문자열은 함께 결합됩니다. 직렬화된 객체는 역직렬화된 객체에 나타나는 것과 동일한 순서로 고정 길이 요소의 바이트 목록 표현을 가집니다. + +가변 길이 유형의 경우, 실제 데이터는 직렬화된 객체의 해당 요소 위치에 있는 "오프셋" 값으로 대체됩니다. 실제 데이터는 직렬화된 객체의 끝에 있는 힙에 추가됩니다. 오프셋 값은 힙에 있는 실제 데이터의 시작 인덱스로, 관련 바이트에 대한 포인터 역할을 합니다. + +아래 예는 고정 및 가변 길이 요소를 모두 포함하는 컨테이너에 대한 오프셋 작동 방식을 보여줍니다. + +```Rust + + struct Dummy { + + number1: u64, + number2: u64, + vector: Vec, + number3: u64 + } + + dummy = Dummy{ + + number1: 37, + number2: 55, + vector: vec![1,2,3,4], + number3: 22, + } + + serialized = ssz.serialize(dummy) + +``` + +`serialized`는 다음과 같은 구조를 가집니다(여기서는 4비트로만 패딩되었지만 실제로는 32비트로 패딩되었으며, 명확성을 위해 `int` 표현을 유지합니다): + +``` +[37, 0, 0, 0, 55, 0, 0, 0, 16, 0, 0, 0, 22, 0, 0, 0, 1, 2, 3, 4] +------------ ----------- ----------- ----------- ---------- + | | | | | + number1 number2 vector의 number3 vector의 + 오프셋 값 + +``` + +명확성을 위해 여러 줄로 나눴습니다: + +``` +[ + 37, 0, 0, 0, # `number1`의 리틀엔디언 인코딩. + 55, 0, 0, 0, # `number2`의 리틀엔디언 인코딩. + 16, 0, 0, 0, # `vector` 값의 시작 위치를 나타내는 "오프셋"(리틀엔디언 16). + 22, 0, 0, 0, # `number3`의 리틀엔디언 인코딩. + 1, 2, 3, 4, # `vector`의 실제 값. +] +``` + +이것은 여전히 단순화된 것입니다. 위의 도식에 있는 정수와 0은 실제로는 다음과 같이 바이트 목록으로 저장됩니다. + +``` +[ + 10100101000000000000000000000000 # `number1`의 리틀엔디언 인코딩 + 10110111000000000000000000000000 # `number2`의 리틀엔디언 인코딩. + 10010000000000000000000000000000 # `vector` 값의 시작 위치를 나타내는 "오프셋"(리틀엔디언 16). + 10010110000000000000000000000000 # `number3`의 리틀엔디언 인코딩. + 10000001100000101000001110000100 # `bytes` 필드의 실제 값. +] +``` + +따라서 가변 길이 유형의 실제 값은 직렬화된 객체의 끝에 있는 힙에 저장되며, 오프셋은 정렬된 필드 목록의 올바른 위치에 저장됩니다. + +`BitList` 유형과 같이 직렬화 중에 길이 상한을 추가하고 역직렬화 중에 제거해야 하는 특정 처리가 필요한 몇 가지 특수한 경우도 있습니다. 전체 세부 정보는 [SSZ 사양](https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md)에서 확인할 수 있습니다. + +### 역직렬화 {#deserialization} + +이 객체를 역직렬화하려면 스키마가 필요합니다. 스키마는 직렬화된 데이터의 정확한 레이아웃을 정의하여 각 특정 요소를 바이트 블롭에서 올바른 유형, 값, 크기 및 위치를 갖는 의미 있는 객체로 역직렬화할 수 있도록 합니다. 어떤 값이 실제 값이고 어떤 값이 오프셋인지를 역직렬화 프로그램에 알려주는 것이 바로 스키마입니다. 모든 필드 이름은 객체가 직렬화될 때 사라지지만, 스키마에 따라 역직렬화될 때 다시 인스턴스화됩니다. + +이에 대한 대화형 설명은 [ssz.dev](https://www.ssz.dev/overview)를 참조하세요. + +## 머클화 {#merkleization} + +그런 다음 이 SSZ 직렬화된 객체를 머클화할 수 있습니다. 즉, 동일한 데이터의 머클 트리 표현으로 변환할 수 있습니다. 먼저, 직렬화된 객체에서 32바이트 청크의 수를 결정합니다. 이것이 트리의 "리프"입니다. 리프를 함께 해싱하여 최종적으로 단일 해시 트리 루트를 생성할 수 있도록 총 리프 수는 2의 거듭제곱이어야 합니다. 자연스럽게 그렇지 않은 경우, 32바이트의 0을 포함하는 추가 리프가 추가됩니다. 도식적으로: + +``` + 해시 트리 루트 + / \ + / \ + / \ + / \ + 리프 1과 2의 해시 리프 3과 4의 해시 + / \ / \ + / \ / \ + / \ / \ + 리프1 리프2 리프3 리프4 +``` + +위의 예에서와 같이 트리의 리프가 자연스럽게 고르게 분포되지 않는 경우도 있습니다. 예를 들어, 리프 4는 머클 트리에 추가적인 "깊이"를 추가해야 하는 여러 요소를 가진 컨테이너일 수 있으며, 이로 인해 불균일한 트리가 생성됩니다. + +이러한 트리 요소를 리프 X, 노드 X 등으로 지칭하는 대신, 루트 = 1에서 시작하여 각 레벨을 따라 왼쪽에서 오른쪽으로 계산하는 일반화된 인덱스를 부여할 수 있습니다. 이것이 위에서 설명한 일반화된 인덱스입니다. 직렬화된 목록의 각 요소는 `2**depth + idx`와 같은 일반화된 인덱스를 가집니다. 여기서 idx는 직렬화된 객체에서 0부터 시작하는 위치이고, 깊이는 머클 트리의 레벨 수이며, 요소(리프) 수의 밑이 2인 로그로 결정될 수 있습니다. + +## 일반화된 인덱스 {#generalized-indices} + +일반화된 인덱스는 이진 머클 트리의 노드를 나타내는 정수이며, 각 노드는 `2 ** depth + 행의 인덱스`라는 일반화된 인덱스를 가집니다. + +``` + 1 --깊이 = 0 2**0 + 0 = 1 + 2 3 --깊이 = 1 2**1 + 0 = 2, 2**1+1 = 3 + 4 5 6 7 --깊이 = 2 2**2 + 0 = 4, 2**2 + 1 = 5... + +``` + +이 표현은 머클 트리의 각 데이터 조각에 대한 노드 인덱스를 산출합니다. + +## 다중 증명 {#multiproofs} + +특정 요소를 나타내는 일반화된 인덱스 목록을 제공하면 해시 트리 루트와 비교하여 이를 확인할 수 있습니다. 이 루트는 우리가 수용한 현실 버전입니다. 제공된 모든 데이터는 머클 트리의 올바른 위치(일반화된 인덱스에 의해 결정됨)에 삽입하고 루트가 일정하게 유지되는지 관찰함으로써 그 현실에 대해 검증될 수 있습니다. 사양에는 특정 일반화된 인덱스 세트의 내용을 확인하는 데 필요한 최소 노드 세트를 계산하는 방법을 보여주는 함수가 [여기](https://github.com/ethereum/consensus-specs/blob/dev/ssz/merkle-proofs.md#merkle-multiproofs)에 있습니다. + +예를 들어, 아래 트리에서 인덱스 9의 데이터를 확인하려면 인덱스 8, 9, 5, 3, 1에 있는 데이터의 해시가 필요합니다. +(8,9)의 해시는 해시 (4)와 같아야 하며, 이는 5와 해싱되어 2를 생성하고, 이는 3과 해싱되어 트리 루트 1을 생성합니다. 9에 대해 잘못된 데이터가 제공되면 루트가 변경됩니다. 우리는 이를 감지하고 브랜치 확인에 실패할 것입니다. + +``` +* = 증명을 생성하는 데 필요한 데이터 + + 1* + 2 3* + 4 5* 6 7 +8* 9* 10 11 12 13 14 15 + +``` + +## 더 읽어보기 {#further-reading} + +- [이더리움 업그레이드: SSZ](https://eth2book.info/altair/part2/building_blocks/ssz) +- [이더리움 업그레이드: 머클화](https://eth2book.info/altair/part2/building_blocks/merkleization) +- [SSZ 구현](https://github.com/ethereum/consensus-specs/issues/2138) +- [SSZ 계산기](https://simpleserialize.com/) +- [SSZ.dev](https://www.ssz.dev/) diff --git a/public/content/translations/ko/developers/docs/data-structures-and-encoding/web3-secret-storage/index.md b/public/content/translations/ko/developers/docs/data-structures-and-encoding/web3-secret-storage/index.md new file mode 100644 index 00000000000..fea3a020bb8 --- /dev/null +++ b/public/content/translations/ko/developers/docs/data-structures-and-encoding/web3-secret-storage/index.md @@ -0,0 +1,195 @@ +--- +title: "Web3 비밀 저장소 정의" +description: "웹3 비밀 저장 공간에 대한 공식적인 정의" +lang: ko +sidebarDepth: 2 +--- + +앱이 이더리움에서 작동하도록 하려면 web3.js 라이브러리에서 제공하는 웹3 객체를 사용할 수 있습니다. 내부적으로 RPC 호출을 통해 로컬 노드와 통신합니다. [web3](https://github.com/ethereum/web3.js/)는 RPC 레이어를 노출하는 모든 이더리움 노드와 함께 작동합니다. + +`web3`는 `eth` 객체(web3.eth)를 포함합니다. + +```js +var fs = require("fs") +var recognizer = require("ethereum-keyfile-recognizer") + +fs.readFile("keyfile.json", (err, data) => { + var json = JSON.parse(data) + var result = recognizer(json) +}) + +/** result + * [ 'web3', 3 ] 웹3(v3) 키 파일 + * [ 'ethersale', undefined ] Ethersale 키 파일 + * null 잘못된 키 파일 + */ +``` + +이 문서는 웹3 비밀 저장 공간 정의의 버전 3에 대한 내용입니다. + +## 정의 {#definition} + +파일의 실제 인코딩 및 디코딩은 버전 1과 거의 동일하지만, 암호화 알고리즘이 더 이상 AES-128-CBC로 고정되지 않는다는 점이 다릅니다(현재는 AES-128-CTR이 최소 요구 사항임). 대부분의 의미/알고리즘은 버전 1과 유사하지만 `mac`은 예외입니다. `mac`은 파생된 키의 왼쪽에서 두 번째 16바이트와 전체 `ciphertext`를 연결한 것의 SHA3(keccak-256)으로 지정됩니다. + +비밀 키 파일은 `~/.web3/keystore`(유닉스 계열 시스템의 경우) 및 `~/AppData/Web3/keystore`(윈도우의 경우)에 직접 저장됩니다. 이름은 무엇이든 될 수 있지만, `.json`이 좋은 규칙입니다. 여기서 ``는 비밀 키에 부여된 128비트 UUID(비밀 키 주소에 대한 개인정보 보호 프록시)입니다. + +이러한 모든 파일에는 연결된 비밀번호가 있습니다. 주어진 `.json` 파일의 비밀 키를 파생시키려면 먼저 파일의 암호화 키를 파생시켜야 합니다. 이 작업은 파일의 비밀번호를 가져와 `kdf` 키에 설명된 대로 키 파생 함수를 통해 전달하여 수행됩니다. KDF 함수에 대한 KDF 종속 정적 및 동적 파라미터는 `kdfparams` 키에 설명되어 있습니다. + +최소 준수 구현은 모두 PBKDF2를 지원해야 하며, 다음과 같이 표시됩니다. + +- `kdf`: `pbkdf2` + +PBKDF2의 경우, kdfparams는 다음을 포함합니다. + +- `prf`: `hmac-sha256`이어야 합니다(향후 확장될 수 있음). +- `c`: 반복 횟수, +- `salt`: PBKDF에 전달된 솔트, +- `dklen`: 파생된 키의 길이. 32 이상이어야 합니다. + +파일의 키가 파생되면 MAC 파생을 통해 확인해야 합니다. MAC은 파생된 키의 왼쪽에서 두 번째 16바이트와 `ciphertext` 키의 내용을 연결하여 형성된 바이트 배열의 SHA3(keccak-256) 해시로 계산되어야 합니다. 즉, + +```js +KECCAK(DK[16..31] ++ ) +``` + +(여기서 `++`는 연결 연산자입니다) + +이 값은 `mac` 키의 내용과 비교해야 합니다. 만약 값이 다르면 다른 비밀번호를 요청하거나 작업을 취소해야 합니다. + +파일의 키가 확인된 후, `cipher` 키로 지정되고 `cipherparams` 키를 통해 매개변수화된 대칭 암호화 알고리즘을 사용하여 암호문(`ciphertext` 키)을 복호화할 수 있습니다. 파생된 키 크기와 알고리즘의 키 크기가 일치하지 않는 경우, 파생된 키의 0으로 채워진 가장 오른쪽 바이트가 알고리즘의 키로 사용되어야 합니다. + +모든 최소 준수 구현은 AES-128-CTR 알고리즘을 지원해야 하며, 다음과 같이 표시됩니다. + +- `cipher: aes-128-ctr` + +이 암호는 cipherparams 키에 대한 키로 지정된 다음 매개변수를 사용합니다. + +- `iv`: 암호에 대한 128비트 초기화 벡터. + +암호의 키는 파생된 키의 가장 왼쪽 16바이트입니다(예: `DK[0..15]`) + +비밀 키의 생성/암호화는 기본적으로 이러한 지침의 역순이어야 합니다. `uuid`, `salt` 및 `iv`가 실제로 무작위인지 확인하십시오. + +버전의 "하드" 식별자 역할을 해야 하는 `version` 필드 외에도, 구현은 형식에 대한 더 작고 호환성을 깨뜨리지 않는 변경 사항을 추적하기 위해 `minorversion`을 사용할 수도 있습니다. + +## 테스트 벡터 {#test-vectors} + +세부 정보: + +- `주소`: `008aeeda4d805471df9b2a5b0f38a0c3bcba786b` +- `ICAP`: `XE542A5PZHH8PYIZUBEJEO0MFWRAPPIL67` +- `UUID`: `3198bc9c-6672-5ab3-d9954942343ae5b6` +- `비밀번호`: `testpassword` +- `비밀`: `7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d` + +### PBKDF2-SHA-256 {#PBKDF2-SHA-256} + +`AES-128-CTR` 및 `PBKDF2-SHA-256`을 사용한 테스트 벡터: + +`~/.web3/keystore/3198bc9c-6672-5ab3-d9954942343ae5b6.json`의 파일 내용: + +```json +{ + "crypto": { + "cipher": "aes-128-ctr", + "cipherparams": { + "iv": "6087dab2f9fdbbfaddc31a909735c1e6" + }, + "ciphertext": "5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46", + "kdf": "pbkdf2", + "kdfparams": { + "c": 262144, + "dklen": 32, + "prf": "hmac-sha256", + "salt": "ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd" + }, + "mac": "517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2" + }, + "id": "3198bc9c-6672-5ab3-d995-4942343ae5b6", + "version": 3 +} +``` + +**중간값**: + +`파생된 키`: `f06d69cdc7da0faffb1008270bca38f5e31891a3a773950e6d0fea48a7188551` +`MAC 본문`: `e31891a3a773950e6d0fea48a71885515318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46` +`MAC`: `517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2` +`암호 키`: `f06d69cdc7da0faffb1008270bca38f5` + +### Scrypt {#scrypt} + +AES-128-CTR 및 Scrypt를 사용한 테스트 벡터: + +```json +{ + "crypto": { + "cipher": "aes-128-ctr", + "cipherparams": { + "iv": "740770fce12ce862af21264dab25f1da" + }, + "ciphertext": "dd8a1132cf57db67c038c6763afe2cbe6ea1949a86abc5843f8ca656ebbb1ea2", + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "n": 262144, + "p": 1, + "r": 8, + "salt": "25710c2ccd7c610b24d068af83b959b7a0e5f40641f0c82daeb1345766191034" + }, + "mac": "337aeb86505d2d0bb620effe57f18381377d67d76dac1090626aa5cd20886a7c" + }, + "id": "3198bc9c-6672-5ab3-d995-4942343ae5b6", + "version": 3 +} +``` + +**중간값**: + +`파생된 키`: `7446f59ecc301d2d79bc3302650d8a5cedc185ccbb4bf3ca1ebd2c163eaa6c2d` +`MAC 본문`: `edc185ccbb4bf3ca1ebd2c163eaa6c2ddd8a1132cf57db67c038c6763afe2cbe6ea1949a86abc5843f8ca656ebbb1ea2` +`MAC`: `337aeb86505d2d0bb620effe57f18381377d67d76dac1090626aa5cd20886a7c` +`암호 키`: `7446f59ecc301d2d79bc3302650d8a5c` + +## 버전 1의 변경 사항 {#alterations-from-v2} + +이 버전은 [여기](https://github.com/ethereum/homestead-guide/blob/master/old-docs-for-reference/go-ethereum-wiki.rst/Passphrase-protected-key-store-spec.rst)에 게시된 버전 1의 몇 가지 불일치를 수정합니다. 간단히 말해 다음과 같습니다. + +- 대소문자 사용이 부적절하고 일관성이 없습니다(scrypt는 소문자, Kdf는 혼합 대/소문자, MAC은 대문자). +- 주소는 불필요하며 개인 정보를 침해합니다. +- `Salt`는 본질적으로 키 파생 함수의 매개변수이므로 일반적인 암호화가 아닌 해당 함수와 연결되어야 합니다. +- SaltLen은 불필요합니다(Salt에서 파생하면 됨). +- 키 파생 함수는 주어지지만, 암호화 알고리즘은 하드코딩되어 있습니다. +- `Version`은 본질적으로 숫자이지만 문자열입니다(문자열로 구조화된 버전 관리가 가능하지만, 거의 변경되지 않는 구성 파일 형식의 범위를 벗어난 것으로 간주될 수 있습니다). +- `KDF`와 `cipher`는 개념적으로 형제 개념이지만 다르게 구성되어 있습니다. +- `MAC`은 공백에 영향을 받지 않는 데이터 조각을 통해 계산됩니다(!). + +이전에 링크된 페이지의 예시와 기능적으로 동일한 다음 파일을 제공하기 위해 형식이 변경되었습니다. + +```json +{ + "crypto": { + "cipher": "aes-128-cbc", + "ciphertext": "07533e172414bfa50e99dba4a0ce603f654ebfa1ff46277c3e0c577fdc87f6bb4e4fe16c5a94ce6ce14cfa069821ef9b", + "cipherparams": { + "iv": "16d67ba0ce5a339ff2f07951253e6ba8" + }, + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "n": 262144, + "p": 1, + "r": 8, + "salt": "06870e5e6a24e183a5c807bd1c43afd86d573f7db303ff4853d135cd0fd3fe91" + }, + "mac": "8ccded24da2e99a11d48cda146f9cc8213eb423e2ea0d8427f41c3be414424dd", + "version": 1 + }, + "id": "0498f19a-59db-4d54-ac95-33901b4f1870", + "version": 2 +} +``` + +## 버전 2의 변경 사항 {#alterations-from-v2} + +버전 2는 여러 버그가 있는 초기 C++ 구현이었습니다. 모든 필수 요소는 그대로 유지됩니다. diff --git a/public/content/translations/ko/developers/docs/design-and-ux/dex-design-best-practice/index.md b/public/content/translations/ko/developers/docs/design-and-ux/dex-design-best-practice/index.md new file mode 100644 index 00000000000..30ed7718dab --- /dev/null +++ b/public/content/translations/ko/developers/docs/design-and-ux/dex-design-best-practice/index.md @@ -0,0 +1,220 @@ +--- +title: "탈중앙화 거래소(DEX) 디자인 모범 사례" +description: "토큰 교환을 위한 UX/UI 결정 사항을 설명하는 가이드입니다." +lang: ko +--- + +2018년 Uniswap 출시 이후 수십 개의 다른 체인에 걸쳐 수백 개의 탈중앙화 거래소가 출시되었습니다. +이들 중 다수는 새로운 요소를 도입하거나 고유한 특징을 추가했지만 인터페이스는 대체로 동일하게 유지되었습니다. + +그 이유 중 하나는 [제이콥의 법칙](https://lawsofux.com/jakobs-law/)입니다. + +> 사용자는 대부분의 시간을 다른 사이트에서 보냅니다. 이는 사용자가 자신의 사이트가 이미 알고 있는 다른 모든 사이트와 동일한 방식으로 작동하기를 선호한다는 것을 의미합니다. + +Uniswap, Pancakeswap, Sushiswap과 같은 초기 혁신가들 덕분에 디파이(DeFi) 사용자들은 DEX가 어떤 모습인지에 대한 집단적인 아이디어를 갖게 되었습니다. +이러한 이유로 '모범 사례'와 같은 것이 이제 막 나타나고 있습니다. 점점 더 많은 디자인 결정이 사이트 전반에 걸쳐 표준화되고 있음을 알 수 있습니다. DEX의 진화를 실시간 테스트의 거대한 예로 볼 수 있습니다. 효과가 있었던 것은 남고, 그렇지 않은 것은 버려졌습니다. 여전히 개성을 발휘할 여지는 있지만 DEX가 따라야 할 특정 표준이 있습니다. + +이 글은 다음에 대한 요약입니다. + +- 포함해야 할 사항 +- 최대한 사용하기 쉽게 만드는 방법 +- 디자인을 사용자 정의하는 주요 방법 + +모든 예시 와이어프레임은 실제 프로젝트를 기반으로 하지만 이 글을 위해 특별히 제작되었습니다. + +Figma 키트도 하단에 포함되어 있습니다. 자유롭게 사용하여 자신만의 와이어프레임 작업 속도를 높여보세요! + +## DEX의 기본 구조 {#basic-anatomy-of-a-dex} + +UI는 일반적으로 세 가지 요소를 포함합니다. + +1. 기본 양식 +2. 버튼 +3. 세부 정보 패널 + +![세 가지 주요 요소를 보여주는 일반적인 DEX UI](./1.png) + +## 변형 {#variations} + +이는 이 글에서 공통적인 주제이지만, 이러한 요소들을 구성하는 방법에는 여러 가지가 있습니다. '세부 정보 패널'은 다음과 같을 수 있습니다. + +- 버튼 위 +- 버튼 아래 +- 아코디언 패널에 숨김 +- 그리고/또는 '미리보기' 모달에 표시 + +참고 '미리보기' 모달은 선택 사항이지만, 메인 UI에 아주 적은 세부 정보만 표시하는 경우 필수적입니다. + +## 메인 양식의 구조 {#structure-of-the-main-form} + +이 상자는 실제로 교환하려는 토큰을 선택하는 곳입니다. 이 컴포넌트는 한 줄에 입력 필드와 작은 버튼으로 구성됩니다. + +DEX는 일반적으로 위 한 줄과 아래 한 줄에 추가 세부 정보를 표시하지만, 이는 다르게 구성할 수 있습니다. + +![위아래에 세부 정보 행이 있는 입력 행](./2.png) + +## 변형 {#variations2} + +여기에는 두 가지 UI 변형이 표시됩니다. 하나는 테두리가 전혀 없어 매우 개방적인 디자인을 만들고, 다른 하나는 입력 행에 테두리가 있어 해당 요소에 초점을 맞춥니다. + +![메인 양식의 두 가지 UI 변형](./3.png) + +이 기본 구조를 통해 네 가지 핵심 정보를 디자인에 표시할 수 있습니다. 각 모서리에 하나씩입니다. 상단/하단 행이 하나만 있는 경우, 두 개의 지점만 있습니다. + +디파이(DeFi)의 진화 과정에서 여기에 많은 다양한 것들이 포함되었습니다. + +## 포함할 핵심 정보 {#key-info-to-include} + +- 지갑 내 잔액 +- 최대 버튼 +- 법정 화폐 등가액 +- '받는' 금액에 대한 가격 영향 + +디파이(DeFi) 초기에는 법정 화폐 등가액이 종종 누락되었습니다. 어떤 종류의 웹3 프로젝트를 구축하든 법정 화폐 등가액을 표시하는 것이 필수적입니다. 사용자는 여전히 현지 통화로 생각하므로 실제 세계의 정신 모델과 일치시키기 위해 이를 포함해야 합니다. + +두 번째 필드(교환할 토큰을 선택하는 필드)에서는 입력 금액과 예상 출력 금액의 차이를 계산하여 법정 화폐 금액 옆에 가격 영향을 포함할 수도 있습니다. 이것은 포함하기에 매우 유용한 세부 정보입니다. + +백분율 버튼(예: 25%, 50%, 75%)은 유용한 기능일 수 있지만 더 많은 공간을 차지하고 더 많은 행동 유도를 추가하며 더 많은 정신적 부담을 줍니다. 백분율 슬라이더도 마찬가지입니다. 이러한 UI 결정 중 일부는 브랜드와 사용자 유형에 따라 달라집니다. + +추가 세부 정보는 메인 양식 아래에 표시할 수 있습니다. 이러한 유형의 정보는 대부분 전문 사용자를 위한 것이므로 다음 중 하나를 수행하는 것이 좋습니다. + +- 최대한 최소한으로 유지하거나, +- 아코디언 패널에 숨기기 + +![메인 양식의 모서리에 표시되는 세부 정보](./4.png) + +## 포함할 추가 정보 {#extra-info-to-include} + +- 토큰 가격 +- 슬리피지 +- 최소 수령액 +- 예상 출력 +- 가격 영향 +- 가스 비용 추정치 +- 기타 수수료 +- 주문 라우팅 + +논란의 여지가 있지만, 이러한 세부 정보 중 일부는 선택 사항일 수 있습니다. + +주문 라우팅은 흥미롭지만 대부분의 사용자에게는 큰 차이가 없습니다. + +일부 다른 세부 정보는 단순히 같은 내용을 다른 방식으로 다시 설명하는 것입니다. 예를 들어 '최소 수령액'과 '슬리피지'는 동전의 양면과 같습니다. 슬리피지를 1%로 설정한 경우, 수령할 수 있는 최소 금액 = 예상 출력 - 1%입니다. 일부 UI는 예상 금액, 최소 금액 및 슬리피지를 표시합니다... 유용하지만 과할 수 있습니다. + +어차피 대부분의 사용자는 기본 슬리피지를 그대로 둡니다. + +'가격 영향'은 '받는' 필드의 법정 화폐 등가액 옆 괄호 안에 표시되는 경우가 많습니다. 이것은 추가하기에 훌륭한 UX 세부 정보이지만, 여기에 표시된다면 아래에 다시 표시할 필요가 있을까요? 그리고 미리보기 화면에 또다시? + +많은 사용자(특히 소액을 교환하는 사용자)는 이러한 세부 정보에 신경 쓰지 않을 것입니다. 그들은 단순히 숫자를 입력하고 교환을 누를 것입니다. + +![일부 세부 정보는 동일한 내용을 보여줍니다](./5.png) + +정확히 어떤 세부 정보를 표시할지는 잠재고객과 앱이 어떤 느낌을 주기를 원하는지에 따라 달라집니다. + +세부 정보 패널에 슬리피지 허용치를 포함하는 경우, 여기에서 직접 편집할 수 있도록 해야 합니다. 이것은 '단축키'의 좋은 예입니다. 앱의 일반적인 사용성에 영향을 주지 않으면서 숙련된 사용자의 흐름을 가속화할 수 있는 깔끔한 UX 트릭입니다. + +![세부 정보 패널에서 슬리피지를 제어할 수 있습니다](./6.png) + +한 화면의 특정 정보 하나뿐만 아니라 전체 흐름에 대해 신중하게 생각하는 것이 좋습니다. +메인 양식에 숫자 입력 → 세부 정보 스캔 → 미리보기 화면으로 클릭(미리보기 화면이 있는 경우). +세부 정보 패널을 항상 표시해야 할까요, 아니면 사용자가 확장하려면 클릭해야 할까요? +미리보기 화면을 추가하여 마찰을 만들어야 할까요? 이는 사용자가 속도를 늦추고 거래를 고려하도록 강제하는데, 이는 유용할 수 있습니다. 하지만 그들은 모든 동일한 정보를 다시 보고 싶어할까요? 이 시점에서 그들에게 가장 유용한 것은 무엇일까요? + +## 디자인 옵션 {#design-options} + +앞서 언급했듯이, 이 중 많은 부분이 개인 스타일에 달려 있습니다 +사용자는 누구입니까? +당신의 브랜드는 무엇입니까? +모든 세부 정보를 보여주는 '전문가용' 인터페이스를 원하십니까, 아니면 미니멀리스트를 원하십니까? +가능한 모든 정보를 원하는 전문 사용자를 목표로 하더라도 Alan Cooper의 현명한 말을 기억해야 합니다. + +> 인터페이스가 아무리 아름답고 멋지더라도, 적을수록 좋습니다. + +### 구조 {#structure} + +- 토큰을 왼쪽에, 또는 토큰을 오른쪽에 +- 2행 또는 3행 +- 버튼 위 또는 아래의 세부 정보 +- 세부 정보 확장, 최소화 또는 표시 안 함 + +### 구성 요소 스타일 {#component-style} + +- 비어 있음 +- 윤곽선 +- 채워짐 + +순수한 UX 관점에서 볼 때 UI 스타일은 생각보다 덜 중요합니다. 시각적 트렌드는 주기를 그리며 나타났다 사라지며, 선호도 중 상당 부분은 주관적입니다. + +이에 대한 감을 잡고 다양한 구성을 생각해 보는 가장 쉬운 방법은 몇 가지 예를 살펴본 다음 직접 실험해 보는 것입니다. + +포함된 Figma 키트에는 비어 있거나, 윤곽선이 있거나, 채워진 구성 요소가 포함되어 있습니다. + +아래 예시를 보고 모든 것을 종합할 수 있는 다양한 방법을 확인하세요. + +![채워진 스타일의 3행](./7.png) + +![윤곽선 스타일의 3행](./8.png) + +![빈 스타일의 2행](./9.png) + +![윤곽선 스타일의 3행, 세부 정보 패널 포함](./10.png) + +![윤곽선 스타일의 입력 행이 있는 3행](./11.png) + +![채워진 스타일의 2행](./12.png) + +## 하지만 토큰은 어느 쪽에 있어야 할까요? {#but-which-side-should-the-token-go-on} + +결론은 사용성에 큰 차이를 만들지 않을 것이라는 점입니다. 그러나 한쪽으로 기울게 할 수 있는 몇 가지 명심해야 할 사항이 있습니다. + +시간이 지남에 따라 유행이 변하는 것을 보는 것은 약간 흥미로웠습니다. Uniswap은 처음에 토큰을 왼쪽에 두었지만, 이후 오른쪽으로 옮겼습니다. Sushiswap도 디자인 업그레이드 중에 이 변경을 했습니다. 전부는 아니지만 대부분의 프로토콜이 그 뒤를 따랐습니다. + +금융 관례상 전통적으로 통화 기호를 숫자 앞에 둡니다(예: $50, €50, £50). 하지만 우리는 50달러, 50유로, 50파운드라고 _말합니다_. + +일반 사용자, 특히 왼쪽에서 오른쪽으로, 위에서 아래로 읽는 사람에게는 오른쪽에 있는 토큰이 아마도 더 자연스럽게 느껴질 것입니다. + +![토큰이 왼쪽에 있는 UI](./13.png) + +토큰을 왼쪽에, 모든 숫자를 오른쪽에 배치하면 보기 좋게 대칭을 이루어 장점이지만, 이 레이아웃에는 또 다른 단점이 있습니다. + +근접성의 법칙은 서로 가까이 있는 항목들이 관련 있는 것으로 인식된다는 것을 명시합니다. 따라서 관련 항목을 서로 옆에 배치하고자 합니다. 토큰 잔액은 토큰 자체와 직접 관련이 있으며, 새 토큰이 선택될 때마다 변경됩니다. 따라서 토큰 잔액이 토큰 선택 버튼 옆에 있는 것이 조금 더 합리적입니다. 토큰 아래로 옮길 수도 있지만, 그러면 레이아웃의 대칭이 깨집니다. + +궁극적으로 두 옵션 모두 장단점이 있지만, 추세가 오른쪽 토큰으로 기우는 것처럼 보이는 것은 흥미롭습니다. + +## 버튼 동작 {#button-behavior} + +승인을 위한 별도의 버튼을 만들지 마세요. 또한 승인을 위한 별도의 클릭을 만들지 마세요. 사용자는 교환을 원하므로 버튼에 '교환'이라고 표시하고 첫 번째 단계로 승인을 시작하세요. 모달은 스텝퍼 또는 간단한 '거래 1/2 - 승인 중' 알림으로 진행 상황을 표시할 수 있습니다. + +![승인과 교환을 위한 별도의 버튼이 있는 UI](./14.png) + +![승인이라고 표시된 버튼이 하나 있는 UI](./15.png) + +### 상황별 도움말로서의 버튼 {#button-as-contextual-help} + +버튼은 경고로서 이중 역할을 할 수 있습니다! + +이것은 사실 웹3 밖에서는 상당히 이례적인 디자인 패턴이지만, 그 안에서는 표준이 되었습니다. 이는 공간을 절약하고 주의를 집중시키는 좋은 혁신입니다. + +오류로 인해 주된 작업인 교환을 사용할 수 없는 경우, 버튼으로 그 이유를 설명할 수 있습니다. 예: + +- 네트워크 전환 +- 지갑 연결 +- 다양한 오류 + +버튼은 수행해야 할 작업에 매핑될 수도 있습니다. 예를 들어, 사용자가 잘못된 네트워크에 있어 교환할 수 없는 경우, 버튼에 'Ethereum으로 전환'이라고 표시되어야 하며, 사용자가 버튼을 클릭하면 네트워크를 Ethereum으로 전환해야 합니다. 이렇게 하면 사용자 흐름이 크게 빨라집니다. + +![메인 CTA에서 시작되는 핵심 작업](./16.png) + +![메인 CTA 내에 표시되는 오류 메시지](./17.png) + +## 이 Figma 파일로 직접 만들어 보세요 {#build-your-own-with-this-figma-file} + +여러 프로토콜의 노력 덕분에 DEX 디자인이 많이 개선되었습니다. 우리는 사용자가 어떤 정보를 필요로 하는지, 어떻게 보여줘야 하는지, 그리고 어떻게 흐름을 최대한 원활하게 만들 수 있는지 알고 있습니다. +이 글이 UX 원칙에 대한 확실한 개요를 제공하기를 바랍니다. + +실험해보고 싶으시다면 Figma 와이어프레임 키트를 자유롭게 사용해 주세요. 최대한 단순하게 유지되지만 다양한 방식으로 기본 구조를 구축할 수 있는 충분한 유연성을 갖추고 있습니다. + +[Figma 와이어프레임 키트](https://www.figma.com/community/file/1393606680816807382/dex-wireframes-kit) + +디파이(DeFi)는 계속해서 진화할 것이며, 항상 개선의 여지가 있습니다. + +행운을 빕니다! diff --git a/public/content/translations/ko/developers/docs/design-and-ux/heuristics-for-web3/index.md b/public/content/translations/ko/developers/docs/design-and-ux/heuristics-for-web3/index.md new file mode 100644 index 00000000000..21d647f1861 --- /dev/null +++ b/public/content/translations/ko/developers/docs/design-and-ux/heuristics-for-web3/index.md @@ -0,0 +1,138 @@ +--- +title: "웹3 인터페이스 디자인을 위한 7가지 휴리스틱" +description: "웹3의 사용성을 개선하기 위한 원칙" +lang: ko +--- + +사용성 휴리스틱은 사이트의 사용성을 측정하는 데 사용할 수 있는 광범위한 '경험 법칙'입니다. +여기에 소개된 7가지 휴리스틱은 웹3에 특화된 것으로, Jakob Nielsen의 [상호작용 설계를 위한 10가지 일반 원칙](https://www.nngroup.com/articles/ten-usability-heuristics/)과 함께 사용해야 합니다. + +## 웹3를 위한 7가지 사용성 휴리스틱 {#seven-usability-heuristics-for-web3} + +1. 피드백은 행동을 따른다 +2. 보안 및 신뢰 +3. 가장 중요한 정보는 명확하다 +4. 이해하기 쉬운 용어 +5. 행동은 가능한 한 짧게 +6. 네트워크 연결은 가시적이고 유연해야 한다 +7. 지갑이 아닌 앱에서 제어 + +## 정의 및 예시 {#definitions-and-examples} + +### 1. 피드백은 행동을 따른다 {#feedback-follows-action} + +**어떤 일이 발생했거나 발생하고 있을 때 명확하게 알 수 있어야 합니다.** + +사용자는 이전 단계의 결과를 바탕으로 다음 단계를 결정합니다. 따라서 시스템 상태에 대한 정보를 계속 제공받는 것이 중요합니다. 웹3에서는 트랜잭션이 블록체인에 커밋되기까지 시간이 걸릴 수 있으므로 특히 중요합니다. 기다리라는 피드백이 없으면 사용자는 어떤 일이 일어났는지 확신할 수 없습니다. + +**팁:** + +- 메시지, 알림 및 기타 경고를 통해 사용자에게 알립니다. +- 대기 시간을 명확하게 전달합니다. +- 작업이 몇 초 이상 걸리는 경우 타이머나 애니메이션으로 사용자에게 무언가 진행되고 있다는 느낌을 주어 안심시킵니다. +- 프로세스에 여러 단계가 있는 경우 각 단계를 보여줍니다. + +**예시:** +트랜잭션과 관련된 각 단계를 보여주면 사용자가 프로세스의 어느 단계에 있는지 알 수 있습니다. 적절한 아이콘을 통해 사용자는 자신의 행동 상태를 알 수 있습니다. + +![토큰 교환 시 각 단계에 대해 사용자에게 알림](./Image1.png) + +### 2. 보안 및 신뢰 내재화 {#security-and-trust-are-backed-in} + +보안을 우선시해야 하며, 이는 사용자에게 강조되어야 합니다. +사람들은 자신의 데이터를 매우 중요하게 생각합니다. 안전은 종종 사용자의 주된 관심사이므로 설계의 모든 수준에서 고려되어야 합니다. 항상 사용자의 신뢰를 얻기 위해 노력해야 하지만, 이를 수행하는 방법은 앱마다 다를 수 있습니다. 나중에 생각할 것이 아니라, 전반에 걸쳐 의식적으로 설계되어야 합니다. 최종 UI뿐만 아니라 소셜 채널과 개발문서를 포함한 사용자 경험 전반에 걸쳐 신뢰를 구축하십시오. 탈중앙화 수준, 재무 다중 서명 상태, 팀의 신상 공개 여부 등이 모두 사용자의 신뢰에 영향을 미칩니다. + +**팁:** + +- 감사 내역을 자신 있게 나열하십시오 +- 여러 감사를 받으십시오 +- 설계한 안전 기능을 홍보하십시오 +- 기본 통합을 포함한 잠재적 위험을 강조하십시오 +- 전략의 복잡성을 전달하십시오 +- 사용자의 안전 인식에 영향을 미칠 수 있는 비UI 문제를 고려하십시오 + +**예시:** +눈에 잘 띄는 크기로 바닥글에 감사 내역을 포함시키십시오. + +![웹사이트 바닥글에 참조된 감사 내역](./Image2.png) + +### 3. 가장 중요한 정보는 명확하다 {#the-most-important-info-is-obvious} + +복잡한 시스템의 경우 가장 관련성 높은 데이터만 표시합니다. 가장 중요한 것이 무엇인지 결정하고 표시의 우선순위를 정합니다. +너무 많은 정보는 부담스럽고 사용자는 일반적으로 의사 결정을 할 때 한 가지 정보에 의존합니다. 디파이에서는 수익 앱의 연이율(APR)과 대출 앱의 담보인정비율(LTV)이 될 것입니다. + +**팁:** + +- 사용자 조사를 통해 가장 중요한 지표를 발견할 수 있습니다 +- 핵심 정보는 크게, 다른 세부 정보는 작고 눈에 띄지 않게 만드십시오 +- 사람들은 읽지 않고 훑어봅니다. 디자인이 훑어보기 쉽도록 하십시오 + +**예시:** 풀 컬러의 큰 토큰은 훑어볼 때 쉽게 찾을 수 있습니다. 연이율(APR)은 크고 강조 색으로 강조 표시됩니다. + +![토큰과 연이율(APR)을 쉽게 찾을 수 있음](./Image3.png) + +### 4. 명확한 용어 {#clear-terminology} + +용어는 이해하기 쉽고 적절해야 합니다. +전문 용어는 완전히 새로운 정신 모델을 구축해야 하므로 큰 장애물이 될 수 있습니다. 사용자는 디자인을 이미 알고 있는 단어, 구문 및 개념과 연관시킬 수 없습니다. 모든 것이 혼란스럽고 낯설게 보이며, 사용을 시도하기 전에 가파른 학습 곡선이 있습니다. 사용자는 돈을 절약하려는 목적으로 디파이에 접근할 수 있지만, 마주하는 것은 채굴, 파밍, 스테이킹, 배출, 뇌물, 볼트, 락커, ve토큰, 베스팅, 에폭, 탈중앙화 알고리즘, 프로토콜 소유 유동성 등입니다… +가장 넓은 그룹의 사람들이 이해할 수 있는 간단한 용어를 사용하려고 노력하십시오. 프로젝트만을 위한 새로운 용어를 만들지 마십시오. + +**팁:** + +- 간단하고 일관된 용어를 사용하십시오 +- 기존 언어를 최대한 많이 사용하십시오 +- 자신만의 용어를 만들지 마십시오 +- 나타나는 대로 관례를 따르십시오 +- 사용자를 최대한 교육하십시오 + +**예시:** +'나의 보상'은 이 프로젝트를 위해 만들어진 새로운 단어가 아니라 널리 이해되는 중립적인 용어입니다. 보상 자체가 다른 토큰으로 지급되더라도 실제 세계의 정신 모델과 일치시키기 위해 보상은 미국 달러로 표시됩니다. + +![토큰 보상, 미국 달러로 표시됨](./Image4.png) + +### 5. 행동은 가능한 한 짧게 {#actions-are-as-short-as-possible} + +하위 작업을 그룹화하여 사용자의 상호작용 속도를 높입니다. +이는 UI뿐만 아니라 스마트 계약 수준에서도 수행될 수 있습니다. 사용자가 일반적인 작업을 완료하기 위해 시스템의 한 부분에서 다른 부분으로 이동하거나 시스템을 완전히 벗어날 필요가 없어야 합니다. + +**팁:** + +- 가능한 경우 "승인"을 다른 작업과 결합하십시오 +- 서명 단계를 최대한 가깝게 묶으십시오 + +**예시:** '유동성 추가'와 '스테이킹'을 결합하는 것은 사용자의 시간과 가스를 모두 절약하는 가속기의 간단한 예입니다. + +![입금 및 스테이킹 작업을 결합하는 스위치를 보여주는 모달](./Image5.png) + +### 6. 네트워크 연결은 가시적이고 유연해야 한다 {#network-connections-are-visible-and-flexible} + +사용자에게 연결된 네트워크를 알리고 네트워크를 변경할 수 있는 명확한 바로 가기를 제공합니다. +이는 멀티체인 앱에서 특히 중요합니다. 연결이 끊어졌거나 지원되지 않는 네트워크에 연결된 상태에서도 앱의 주요 기능은 계속 표시되어야 합니다. + +**팁:** + +- 연결이 끊긴 동안 가능한 한 많은 앱을 표시하십시오 +- 사용자가 현재 연결된 네트워크를 표시하십시오 +- 사용자가 네트워크를 변경하기 위해 지갑으로 이동하게 하지 마십시오 +- 앱에서 사용자가 네트워크를 전환해야 하는 경우 기본 콜투액션에서 해당 작업을 유도하십시오 +- 앱에 여러 네트워크에 대한 마켓이나 볼트가 포함된 경우 사용자가 현재 보고 있는 세트를 명확하게 명시하십시오 + +**예시:** 앱바에서 사용자가 연결된 네트워크를 표시하고 변경할 수 있도록 하십시오. + +![연결된 네트워크를 보여주는 드롭다운 버튼](./Image6.png) + +### 7. 지갑이 아닌 앱에서 제어 {#control-from-the-app-not-the-wallet} + +UI는 사용자에게 알아야 할 모든 것을 알려주고 해야 할 모든 것을 제어할 수 있도록 해야 합니다. +웹3에는 UI에서 수행하는 작업과 지갑에서 수행하는 작업이 있습니다. 일반적으로 UI에서 작업을 시작한 다음 지갑에서 확인합니다. 이 두 가닥이 신중하게 통합되지 않으면 사용자는 불편함을 느낄 수 있습니다. + +**팁:** + +- UI의 피드백을 통해 시스템 상태를 전달하십시오 +- 기록을 보관하십시오 +- 이전 거래에 대한 블록 탐색기 링크를 제공하십시오 +- 네트워크를 변경할 수 있는 바로 가기를 제공하십시오. + +미묘한 컨테이너는 사용자가 지갑에 어떤 관련 토큰을 가지고 있는지 보여주고, 주요 CTA는 네트워크를 변경할 수 있는 바로 가기를 제공합니다. + +![사용자에게 네트워크 전환을 유도하는 주요 CTA](./Image7.png) diff --git a/public/content/translations/ko/developers/docs/design-and-ux/index.md b/public/content/translations/ko/developers/docs/design-and-ux/index.md new file mode 100644 index 00000000000..f3953e71840 --- /dev/null +++ b/public/content/translations/ko/developers/docs/design-and-ux/index.md @@ -0,0 +1,86 @@ +--- +title: "Web3의 디자인과 UX" +description: "Web3 공간과 이더리움의 UX 디자인 및 연구 소개" +lang: ko +--- + +이더리움을 사용한 디자인이 처음이신가요? 잘 찾아오셨습니다. 이더리움 커뮤니티는 Web3 디자인 및 연구 기초를 소개하는 자료를 작성했습니다. 여러분에게 익숙한 다른 앱 디자인과 다를 수 있는 핵심 개념에 대해 배우게 될 것입니다. + +Web3에 대한 기본적인 이해가 먼저 필요하신가요? [**학습 허브**](/learn/)를 확인해 보세요. + +## 사용자 조사로 시작하기 {#start-with-user-research} + +효과적인 디자인은 시각적으로 매력적인 사용자 인터페이스를 만드는 것 이상을 의미합니다. 사용자의 요구, 목표, 동기를 깊이 이해하는 과정이 포함됩니다. 따라서 모든 디자이너가 의도적이고 신중한 작업을 보장하기 위해 [**더블 다이아몬드 프로세스**](https://en.wikipedia.org/wiki/Double_Diamond_\(design_process_model\))와 같은 디자인 프로세스를 채택할 것을 적극 권장합니다. + +- [Web3는 더 많은 UX 연구원과 디자이너가 필요합니다](https://blog.akasha.org/akasha-conversations-9-web3-needs-more-ux-researchers-and-designers) - 현재 디자인 성숙도에 대한 개요 +- [Web3 UX 연구에 대한 간단한 가이드](https://uxplanet.org/a-complete-guide-to-ux-research-for-web-3-0-products-d6bead20ebb1) - 연구 수행 방법에 대한 간단한 가이드 +- [Web3에서 UX 결정에 접근하는 방법](https://archive.devcon.org/archive/watch/6/data-empathy-how-to-approach-ux-decisions-in-web3/) - 정량적 연구와 정성적 연구에 대한 간략한 개요 및 둘의 차이점 (동영상, 6분) +- [Web3에서 UX 연구원으로 일하기](https://medium.com/@georgia.rakusen/what-its-like-being-a-user-researcher-in-web3-6a4bcc096849) - Web3에서 UX 연구원으로 일하는 것에 대한 개인적인 견해 + +## Web3 연구 사례 {#research-in-web3} + +이것은 Web3에서 수행된 사용자 연구를 선별한 목록으로, 디자인 및 제품 결정에 도움이 되거나 자체 연구를 수행하는 데 영감을 줄 수 있습니다. + +| 중점 분야 | 이름 | +| :--------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 암호화폐 온보딩 | [Reown Pulse 2024: 암호화폐 소비자 심리 및 사용 현황](https://reown.com/blog/unveiling-walletconnects-consumer-crypto-report) | +| 암호화폐 온보딩 | [CRADL: 암호화폐의 UX](https://docs.google.com/presentation/d/1s2OPSH5sMJzxRYaJSSRTe8W2iIoZx0PseIV-WeZWD1s/edit?usp=sharing) | +| 암호화폐 온보딩 | [CRADL: 암호화폐 온보딩](https://docs.google.com/presentation/d/1R9nFuzA-R6SxaGCKhoMbE4Vxe0JxQSTiHXind3LVq_w/edit?usp=sharing) | +| 암호화폐 온보딩 | [비트코인 UX 보고서](https://github.com/patestevao/BitcoinUX-report/blob/master/report.md) | +| 암호화폐 온보딩 | [Consensys: 2023년 전 세계 Web3 인식 현황](https://consensys.io/insight-report/web3-and-crypto-global-survey-2023) | +| 암호화폐 온보딩 | [NEAR: 채택을 향한 여정 가속화](https://drive.google.com/file/d/1VuaQP4QSaQxR5ddQKTMGI0b0rWdP7uGn/view) | +| 스테이킹 | [OpenUX: Rocket Pool 노드 운영자 UX](https://storage.googleapis.com/rocketpool/RocketPool-NodeOperator-UX-Report-Jan-2024.pdf) | +| 스테이킹 | [스테이킹: 주요 동향, 시사점 및 예측 - Eth Staker](https://lookerstudio.google.com/u/0/reporting/cafcee00-e1af-4148-bae8-442a88ac75fa/page/p_ja2srdhh2c?s=hmbTWDh9hJo) | +| 스테이킹 | [다중 앱 스테이킹](https://github.com/threshold-network/UX-User-Research/blob/main/Multi-App%20Staking%20\(MAS\)/iterative-user-study/MAS%20Iterative%20User%20Study.pdf) | +| DAO | [2022 DAO 연구 업데이트: DAO 빌더에게 무엇이 필요한가?](https://blog.aragon.org/2022-dao-research-update/) | +| 디파이 | [보장 풀](https://github.com/threshold-network/UX-User-Research/tree/main/Keep%20Coverage%20Pool) | +| 디파이 | [Consensys: 디파이 사용자 연구 보고서 2022](https://cdn2.hubspot.net/hubfs/4795067/ConsenSys%20Codefi-Defi%20User%20ResearchReport.pdf) | +| 메타버스 | [메타버스: 사용자 연구 보고서](https://www.politico.com/f/?id=00000187-7685-d820-a7e7-7e85d1420000) | +| 메타버스 | [사파리 가기: 메타버스에서 사용자 조사하기](https://archive.devcon.org/archive/watch/6/going-on-safari-researching-users-in-the-metaverse/?tab=YouTube) (동영상, 27분) | + +## Web3를 위한 디자인 {#design-for-web3} + +- [Web3 UX 디자인 핸드북](https://web3ux.design/) - Web3 앱 디자인 실용 가이드 +- [Web3 디자인 원칙](https://medium.com/@lyricalpolymath/web3-design-principles-f21db2f240c1) - 블록체인 기반 탈중앙화앱을 위한 UX 규칙 프레임워크 +- [블록체인 디자인 원칙](https://medium.com/design-ibm/blockchain-design-principles-599c5c067b6e) - IBM의 블록체인 디자인팀이 얻은 교훈 +- [Neueux.com](https://neueux.com/apps) - 다양한 필터링 옵션을 갖춘 사용자 플로우의 UI 라이브러리 +- [Web3의 사용성 위기: 꼭 알아야 할 것!](https://www.youtube.com/watch?v=oBSXT_6YDzg) - 개발자 중심 프로젝트 구축의 함정에 대한 패널 토론 (동영상, 34분) + +## 시작하기 {#getting-started} + +- [Web3를 위한 휴리스틱](/developers/docs/design-and-ux/heuristics-for-web3/) - Web3 인터페이스 디자인을 위한 7가지 휴리스틱 +- [DEX 디자인 모범 사례](/developers/docs/design-and-ux/dex-design-best-practice/) - 탈중앙화 거래소 디자인 가이드 + +## Web3 디자인 사례 연구 {#design-case-studies} + +- [Deep Work Studio](https://www.deepwork.studio/case-studies) +- [OpenSea에서 NFT 판매하기](https://builtformars.com/case-studies/opensea) +- [지갑 UX 분석: 지갑은 어떻게 변해야 하는가](https://www.youtube.com/watch?v=oTpuxYj8JWI&ab_channel=ETHDenver) (동영상, 20분) + +## 디자인 현상금 {#bounties} + +- [Dework](https://app.dework.xyz/bounties) +- [Buildbox 해커톤](https://app.buidlbox.io/) +- [ETHGlobal 해커톤](https://ethglobal.com/) + +## 디자인 DAO 및 커뮤니티 {#design-daos-and-communities} + +전문 커뮤니티 주도 조직에 참여하거나 디자인 그룹에 가입하여 다른 회원들과 디자인 및 연구 관련 주제와 동향에 대해 논의하세요. + +- [Vectordao.com](https://vectordao.com/) +- [Deepwork.studio](https://www.deepwork.studio/) +- [We3.co](https://we3.co/) +- [Openux.xyz](https://openux.xyz/) + +## 디자인 시스템 및 기타 디자인 자료 {#design-systems-and-resources} + +- [Optimism 디자인](https://www.figma.com/@optimism) (Figma) +- [Ethereum.org 디자인 시스템](https://www.figma.com/@ethdotorg) (Figma) +- [Finity, Polygon의 디자인 시스템](https://www.figma.com/community/file/1073921725197233598/finity-design-system) (Figma) +- [Kleros 디자인 시스템](https://www.figma.com/community/file/999852250110186964/kleros-design-system) (Figma) +- [Safe 디자인 시스템](https://www.figma.com/community/file/1337417127407098506/safe-design-system) (Figma) +- [ENS 디자인 시스템](https://thorin.ens.domains/) +- [Mirror 디자인 시스템](https://degen-xyz.vercel.app/) + +**이 페이지에 나열된 기사 및 프로젝트는 공식적인 보증이 아니며**, 정보 제공 목적으로만 제공됩니다. +저희는 [목록 정책](/contributing/design/adding-design-resources)의 기준에 따라 이 페이지에 링크를 추가합니다. 프로젝트/기사 추가를 원하시면 [GitHub](https://github.com/ethereum/ethereum-org-website/blob/dev/public/content/developers/docs/design-and-ux/index.md)에서 이 페이지를 편집하세요. diff --git a/public/content/translations/ko/developers/docs/development-networks/index.md b/public/content/translations/ko/developers/docs/development-networks/index.md new file mode 100644 index 00000000000..41650b6aba8 --- /dev/null +++ b/public/content/translations/ko/developers/docs/development-networks/index.md @@ -0,0 +1,71 @@ +--- +title: "개발 네트워크" +description: "개발 네트워크에 대한 개요 및 이더리움 애플리케이션 구축에 도움이 되는 도구에 대한 설명입니다." +lang: ko +--- + +스마트 계약을 사용하여 이더리움 애플리케이션을 구축할 때 배포하기 전에 로컬 네트워크에서 실행하여 어떻게 작동하는지 확인하는 것이 좋습니다. + +웹 개발을 위해 컴퓨터에서 로컬 서버를 실행하는 것과 유사하게, 개발 네트워크를 사용하여 로컬 블록체인 인스턴스를 생성하고 댑을 테스트할 수 있습니다. 이러한 이더리움 개발 네트워크는 공개 테스트넷보다 훨씬 빠른 반복 작업을 가능하게 하는 기능을 제공합니다(예: 테스트넷 수도꼭지에서 ETH를 얻을 필요가 없음). + +## 필수 구성 요소 {#prerequisites} + +[이더리움 스택의 기본 사항](/developers/docs/ethereum-stack/)과 [이더리움 네트워크](/developers/docs/networks/)를 이해한 후에 개발 네트워크에 대해 자세히 알아보는 것이 좋습니다. + +## 개발 네트워크란 무엇인가요? {#what-is-a-development-network} + +개발 네트워크는 기본적으로 로컬 개발을 위해 특별히 설계된 이더리움 클라이언트(이더리움 구현)입니다. + +**로컬에서 표준 이더리움 노드를 실행하면 안 되나요?** + +[노드를 실행](/developers/docs/nodes-and-clients/#running-your-own-node)할 수도 _있지만_, 개발 네트워크는 개발 목적으로 구축되었기 때문에 다음과 같은 편리한 기능이 포함된 경우가 많습니다. + +- 결정론적으로 로컬 블록체인에 데이터(예: ETH 잔액이 있는 계정)를 시딩합니다. +- 수신하는 각 트랜잭션에 대해 순서대로 지연 없이 즉시 블록을 생성합니다. +- 향상된 디버깅 및 로깅 기능 + +## 사용 가능한 도구 {#available-projects} + +**참고**: 대부분의 [개발 프레임워크](/developers/docs/frameworks/)에는 내장된 개발 네트워크가 포함되어 있습니다. 프레임워크로 시작하여 [로컬 개발 환경을 설정](/developers/local-environment/)하는 것을 추천합니다. + +### Hardhat 네트워크 {#hardhat-network} + +개발용으로 설계된 로컬 이더리움 네트워크입니다. 계약을 배포하고, 테스트를 실행하고, 코드를 디버그할 수 있습니다. + +Hardhat 네트워크는 전문가를 위한 이더리움 개발 환경인 Hardhat에 내장되어 있습니다. + +- [웹사이트](https://hardhat.org/) +- [GitHub](https://github.com/NomicFoundation/hardhat) + +### 로컬 비콘 체인 {#local-beacon-chains} + +일부 합의 클라이언트에는 테스트 목적으로 로컬 비콘 체인을 가동하기 위한 내장 도구가 있습니다. Lighthouse, Nimbus, Lodestar에 대한 지침은 다음과 같습니다. + +- [Lodestar를 사용한 로컬 테스트넷](https://chainsafe.github.io/lodestar/contribution/advanced-topics/setting-up-a-testnet#post-merge-local-testnet/) +- [Lighthouse를 사용한 로컬 테스트넷](https://lighthouse-book.sigmaprime.io/setup.html#local-testnets) + +### 공개 이더리움 테스트 체인 {#public-beacon-testchains} + +유지 관리되는 두 가지 공개 이더리움 테스트 구현인 Sepolia와 Hoodi도 있습니다. 장기적으로 지원되는 권장 테스트넷은 Hoodi이며 누구나 자유롭게 검증할 수 있습니다. Sepolia는 허가된 검증자 집합을 사용하므로, 이 테스트넷의 신규 검증자는 일반적으로 접근할 수 없습니다. + +- [Hoodi 스테이킹 런치패드](https://hoodi.launchpad.ethereum.org/) + +### Kurtosis 이더리움 패키지 {#kurtosis} + +Kurtosis는 개발자가 블록체인 네트워크의 재현 가능한 인스턴스를 로컬에서 가동할 수 있도록 하는 다중 컨테이너 테스트 환경용 빌드 시스템입니다. + +이더리움 Kurtosis 패키지를 사용하면 Docker 또는 Kubernetes를 통해 매개변수화 가능하고 확장성이 뛰어나며 비공개인 이더리움 테스트넷을 신속하게 인스턴스화할 수 있습니다. 이 패키지는 모든 주요 실행 레이어(EL) 및 합의 레이어(CL) 클라이언트를 지원합니다. Kurtosis는 이더리움 코어 인프라와 관련된 검증 및 테스트 워크플로에 사용될 대표 네트워크에 대한 모든 로컬 포트 매핑 및 서비스 연결을 원활하게 처리합니다. + +- [이더리움 네트워크 패키지](https://github.com/kurtosis-tech/ethereum-package) +- [웹사이트](https://www.kurtosis.com/) +- [GitHub](https://github.com/kurtosis-tech/kurtosis) +- [개발문서](https://docs.kurtosis.com/) + +## 더 읽어보기 {#further-reading} + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 관련 주제 {#related-topics} + +- [개발 프레임워크](/developers/docs/frameworks/) +- [로컬 개발 환경 설정](/developers/local-environment/) diff --git a/public/content/translations/ko/developers/docs/ethereum-stack/index.md b/public/content/translations/ko/developers/docs/ethereum-stack/index.md new file mode 100644 index 00000000000..0b7f7c194bf --- /dev/null +++ b/public/content/translations/ko/developers/docs/ethereum-stack/index.md @@ -0,0 +1,61 @@ +--- +title: "이더리움 스택 소개" +description: "이더리움 스택의 다양한 계층과 그들이 어떻게 결합되는지에 대한 설명." +lang: ko +--- + +여느 소프트웨어 스택과 마찬가지로 온전한 "이더리움스택"이란, 당신의 목표에 따라 프로젝트 마다 제각각일 것입니다. + +하지만 어떻게 응용프로그램과 이더리움 블록체인이 상호작용하는 지를 머리속에 그릴 수 있도록 돕는 핵심 컴퍼넌트들은 존재합니다. 이더리움 기술스택의 계층들을 이해하는 것은 이더리움이 소프트웨어 프로젝트에 통합되게끔 하는 서로 다른 방식들을 이해하는데 도움을 줍니다. + +## 레벨 1: 이더리움 가상 머신 {#ethereum-virtual-machine} + +[이더리움 가상 머신(EVM)](/developers/docs/evm/)은 이더리움에서 스마트 계약을 실행하는 런타임 환경입니다. 이더리움 블록체인의 모든 스마트 계약 및 상태 변경은 [트랜잭션](/developers/docs/transactions/)에 의해 실행됩니다. 이더리움 가상환경은 이더리움 네트워크상의 모든 트랜잭션 처리를 수행합니다. + +여느 가상머신과 마찬가지로 이더리움가상머신은 코드의 실행과 물리적인 장비(이더리움 노드) 사이에 추상화 계층을 만듭니다. 현재 EVM은 전 세계에 분산된 수천 개의 노드에서 실행되고 있습니다. + +이더리움 가상 머신은 내부적으로 특정한 작업 수행을 위해 일련의 opcode 명령어를 사용합니다. 이 (140개의 고유한) 연산 부호는 EVM이 [튜링 완전](https://en.wikipedia.org/wiki/Turing_completeness)하도록 하며, 이는 충분한 리소스가 주어진다면 EVM이 거의 모든 것을 계산할 수 있음을 의미합니다. + +dapp 개발자로서, EVM에 대해 많이 알 필요는 없으며, 단지 EVM이 존재하고 이더리움의 모든 애플리케이션을 중단 없이 안정적으로 구동한다는 사실만 알고 있으면 됩니다. + +## 레벨 2: 스마트 계약 {#smart-contracts} + +[스마트 계약](/developers/docs/smart-contracts/)은 이더리움 블록체인에서 실행되는 실행 가능한 프로그램입니다. + +스마트 계약은 EVM 바이트코드(연산 부호라고 불리는 저수준 기계 명령어)로 컴파일되는 특정 [프로그래밍 언어](/developers/docs/smart-contracts/languages/)를 사용하여 작성됩니다. + +스마트 계약은 오픈 소스 라이브러리 역할을 할 뿐만 아니라, 항상 실행 중이며 중단될 수 없는 공개 API 서비스이기도 합니다. 스마트 계약은 사용자와 애플리케이션([탈중앙화앱](/developers/docs/dapps/))이 허가 없이 상호 작용할 수 있는 공개 함수를 제공합니다. 모든 애플리케이션은 배포된 스마트 계약과 통합하여 [데이터 피드](/developers/docs/oracles/) 추가 또는 토큰 스왑 지원과 같은 기능을 구성할 수 있습니다. 또한, 누구나 새로운 스마트 계약을 이더리움에 배포하여 애플리케이션의 필요에 맞는 맞춤형 기능을 추가할 수 있습니다. + +dapp 개발자로서 이더리움 블록체인에 맞춤형 기능을 추가하고 싶을 때에만 스마트 계약을 작성해야 합니다. 프로젝트의 요구 사항을 대부분 또는 전부 기존 스마트 계약과의 통합으로 해결할 수 있을 것입니다. 예를 들어 스테이블코인 결제 지원이나 토큰의 분산형 교환 기능을 추가하는 경우입니다. + +## 레벨 3: 이더리움 노드 {#ethereum-nodes} + +애플리케이션이 이더리움 블록체인과 상호 작용하려면 [이더리움 노드](/developers/docs/nodes-and-clients/)에 연결해야 합니다. 노드에 연결하면 블록체인 데이터를 읽거나 네트워크에 트랜잭션을 전송할 수 있습니다. + +이더리움 노드는 소프트웨어를 실행하는 컴퓨터 - 즉, 이더리움 클라이언트입니다. 클라이언트는 각 블럭의 트랜잭션을 검증하여 네트워크를 안전하고 데이터가 무결하게 관리하는 이더리움의 구현체를 말합니다. **이더리움 노드가 이더리움 블록체인입니다**. 노드는 이더리움 블록체인의 상태를 집단적으로 저장하며, 블록체인 상태를 변경하기 위해 트랜잭션에 대한 합의를 이룹니다. + +애플리케이션을 이더리움 노드([JSON-RPC API](/developers/docs/apis/json-rpc/)를 통해)에 연결하면, 애플리케이션은 블록체인에서 데이터(예: 사용자 계정 잔액)를 읽을 수 있을 뿐만 아니라 네트워크에 새로운 트랜잭션(예: 사용자 계정 간 ETH 전송 또는 스마트 계약 함수 실행)을 브로드캐스트할 수 있습니다. + +## 레벨 4: 이더리움 클라이언트 API {#ethereum-client-apis} + +이더리움 오픈 소스 커뮤니티에서 제작하고 유지 관리하는 다양한 편리한 라이브러리가 애플리케이션이 이더리움 블록체인과 연결하고 통신할 수 있도록 도와줍니다. + +사용자 대상 애플리케이션이 웹 앱인 경우, 프런트엔드에 직접 [JavaScript API](/developers/docs/apis/javascript/)를 `npm install`할 수 있습니다. 또는 [Python](/developers/docs/programming-languages/python/)이나 [Java](/developers/docs/programming-languages/java/) API를 사용하여 서버 측에서 이 기능을 구현할 수도 있습니다. + +이 API는 스택에서 반드시 필요한 부분은 아니지만, 이더리움 노드와 직접 상호작용하는 복잡성을 대부분 추상화해줍니다. 또한 유틸리티 함수(예: ETH를 Gwei로 변환)를 제공하므로, 개발자는 이더리움 클라이언트의 복잡성을 다루는 데 시간을 덜 소비하고 애플리케이션의 특정 기능에 더 집중할 수 있습니다. + +## 레벨 5: 최종 사용자 애플리케이션 {#end-user-applications} + +스택의 최상위에는 사용자 대상 애플리케이션이 있습니다. 이들은 주로 웹 및 모바일 애플리케이션과 같은 여러분이 정기적으로 사용하고 개발하는 표준 애플리케이션입니다. + +이러한 사용자 인터페이스를 개발하는 방법은 본질적으로 변하지 않습니다. 대부분의 경우, 사용자는 그들이 사용하는 애플리케이션이 블록체인을 기반으로 구축되었는지 알 필요가 없습니다. + +## 스택을 선택할 준비가 되셨나요? {#ready-to-choose-your-stack} + +이더리움 애플리케이션을 위한 [로컬 개발 환경 설정](/developers/local-environment/) 가이드를 확인하세요. + +## 더 읽어보기 {#further-reading} + +- [웹 3.0 애플리케이션의 아키텍처](https://www.preethikasireddy.com/post/the-architecture-of-a-web-3-0-application) - _Preethi Kasireddy_ + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ diff --git a/public/content/translations/ko/developers/docs/evm/index.md b/public/content/translations/ko/developers/docs/evm/index.md new file mode 100644 index 00000000000..9c83d2e4b5e --- /dev/null +++ b/public/content/translations/ko/developers/docs/evm/index.md @@ -0,0 +1,88 @@ +--- +title: "이더리움 가상 머신(EVM)" +description: "이더리움 가상머신 소개 및 상태, 트랜잭션, 그리고 스마트 계약과의 관련성" +lang: ko +--- + +이더리움 가상머신(EVM)은 모든 이더리움 노드에서 코드를 일관되고 안전하게 실행하는 탈중앙화된 가상 환경입니다. 노드는 EVM을 실행하여 스마트 계약을 실행하고, "[가스](/developers/docs/gas/)"를 사용하여 [연산](/developers/docs/evm/opcodes/)에 필요한 연산량을 측정하며 효율적인 리소스 할당과 네트워크 보안을 보장합니다. + +## 필수 구성 요소 {#prerequisites} + +EVM을 이해하려면 [바이트](https://wikipedia.org/wiki/Byte), [메모리](https://wikipedia.org/wiki/Computer_memory), [스택](https://wikipedia.org/wiki/Stack_\(abstract_data_type\))과 같은 컴퓨터 과학의 일반적인 용어에 대한 기본적인 지식이 필요합니다. 또한 [해시 함수](https://wikipedia.org/wiki/Cryptographic_hash_function) 및 [머클 트리](https://wikipedia.org/wiki/Merkle_tree)와 같은 암호학/블록체인 개념에 익숙하면 도움이 됩니다. + +## 원장에서 상태 머신으로 {#from-ledger-to-state-machine} + +'분산 원장'의 유사함은 암호학의 기본 도구들을 사용해서 분산 화폐를 가능하게 하는 비트코인과 같은 블록체인을 설명하는데 자주 사용된다. 원장은 누군가가 원장을 수정하기 위해 할 수 있는 것과 할 수 없는 것을 지배하는 일련의 규칙을 준수해야 하는 활동 기록을 유지한다. 예를 들어 하나의 비트코인 주소는 그 주소가 이전에 받은 것보다 더 많은 비트코인을 쓸 수 없다. 이런 규칙은 비트코인과 다른 많은 블록체인 상의 모든 트랜잭션의 근간이다. + +이더리움은 거의 동일하고 직관적인 규칙을 따르는 자체 네이티브 암호화폐(이더)를 가지고 있지만, [스마트 계약](/developers/docs/smart-contracts/)이라는 훨씬 더 강력한 기능도 지원합니다. 이 더 복잡한 기능을 위해서, 더 정교한 설명이 필요하다. 이더리움은 분산 원장이 아니라 분산 [상태 머신](https://wikipedia.org/wiki/Finite-state_machine)입니다. 이더리움의 상태는 모든 계정과 잔고뿐만 아니라 사전 정의된 규칙에 따라 블록마다 변경될 수 있고, 임의의 머신 코드를 실행할 수 있는 머신 상태까지 포함하는 거대한 자료 구조입니다. 블록에서 블록으로의 상태 변화에 대한 자세한 규칙은 EVM에 의해 정의된다. + +![EVM의 구성을 보여주는 다이어그램](./evm.png) +_[Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)에서 발췌한 다이어그램_ + +## 이더리움 상태 전환 함수 {#the-ethereum-state-transition-function} + +EVM은 하나의 입력으로 하나의 결정된 출력을 생성하는 수학 함수처럼 동작한다. 따라서 이더리움을 상태 전환 함수를 갖는 것으로 보다 공식적으로 설명하는 것이 매우 유용합니다. + +``` +Y(S, T)= S' +``` + +이전 유효 상태 `(S)`와 새로운 유효 거래 집합 `(T)`이 주어지면 이더리움 상태 전환 함수 `Y(S, T)`는 새로운 유효 출력 상태 `S'`를 생성합니다. + +### 상태 {#state} + +이더리움의 맥락에서 상태는 [수정된 머클 패트리샤 트리](/developers/docs/data-structures-and-encoding/patricia-merkle-trie/)라고 불리는 거대한 자료 구조로, 이는 해시로 연결된 모든 [계정](/developers/docs/accounts/)을 유지하며 블록체인에 저장된 단일 루트 해시로 축소될 수 있습니다. + +### 트랜잭션 {#transactions} + +트랜잭션은 계정으로부터 암호학적으로 서명된 명령들이다. 트랜잭션은 두가지 종류가 있다. 메시지 콜을 만드는 것들, 그리고 컨트랙트를 생성하는 것들. + +계약 생성 시 컴파일된 [스마트 계약](/developers/docs/smart-contracts/anatomy/) 바이트코드가 포함된 새로운 계약 계정이 생성됩니다. 다른 게정이 그 컨트랙트로 메세지 콜을 보낼 때 마다, 그 바이트코드를 실행한다. + +## EVM 명령 {#evm-instructions} + +EVM은 1024개 항목의 깊이를 가진 [스택 머신](https://wikipedia.org/wiki/Stack_machine)으로 실행됩니다. 각 항목은 256비트 단어로 256비트 암호학(예: Keccak-256 해시 또는 secp256k1 서명)에서 사용하기 쉽도록 선택되었다. + +실행 중에 EVM은 트랜잭션 간에 유지되지 않는 일시적인 _메모리_(워드 주소 지정 바이트 배열)를 유지합니다. + +### 임시 저장 공간 + +임시 저장 공간은 `TSTORE` 및 `TLOAD` 연산 부호를 통해 액세스되는 트랜잭션별 키-값 저장소입니다. 동일한 트랜잭션 동안 모든 내부 호출에서 유지되지만, 트랜잭션이 끝나면 삭제됩니다. 메모리와 달리, 임시 저장 공간은 실행 프레임이 아닌 EVM 상태의 일부로 모델링되지만, 전역 상태에는 커밋되지 않습니다. 임시 저장 공간은 트랜잭션 중 내부 호출 간에 가스 효율적인 임시 상태 공유를 가능하게 합니다. + +### 스토리지 + +계약에는 해당 계정과 연결되어 있고 전역 상태의 일부인 머클 패트리샤 _저장 공간_ 트리(워드 주소 지정 워드 배열)가 포함됩니다. 이 영구 저장 공간은 단일 트랜잭션 기간 동안에만 사용할 수 있고 계정의 영구 저장 공간 트리의 일부를 구성하지 않는 임시 저장 공간과 다릅니다. + +### 연산 부호 + +컴파일된 스마트 계약 바이트코드는 `XOR`, `AND`, `ADD`, `SUB` 등과 같은 표준 스택 연산을 수행하는 다수의 EVM [연산 부호](/developers/docs/evm/opcodes)로 실행됩니다. EVM은 또한 `ADDRESS`, `BALANCE`, `BLOCKHASH` 등과 같은 여러 블록체인별 스택 연산도 구현합니다. 연산 부호 집합에는 임시 저장 공간에 대한 액세스를 제공하는 `TSTORE` 및 `TLOAD`도 포함됩니다. + +![EVM 연산에 가스가 필요한 위치를 보여주는 다이어그램](../gas/gas.png) +_[Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)에서 발췌한 다이어그램_ + +## EVM 구현 {#evm-implementations} + +EVM의 모든 구현은 이더리움 옐로우 페이퍼에 설명된 스펙을 준수해야한다. + +이더리움의 10년 역사 동안 EVM은 여러 차례 개정되었으며, 다양한 프로그래밍 언어로 된 여러 EVM 구현이 있습니다. + +[이더리움 실행 클라이언트](/developers/docs/nodes-and-clients/#execution-clients)에는 EVM 구현이 포함됩니다. 게다가 다음을 포함하는 여러 자체 구동 구현물이 있다. + +- [Py-EVM](https://github.com/ethereum/py-evm) - _Python_ +- [evmone](https://github.com/ethereum/evmone) - _C++_ +- [ethereumjs-vm](https://github.com/ethereumjs/ethereumjs-vm) - _JavaScript_ +- [revm](https://github.com/bluealloy/revm) - _Rust_ + +## 추가 정보 {#further-reading} + +- [이더리움 황서(Yellowpaper)](https://ethereum.github.io/yellowpaper/paper.pdf) +- [Jellopaper, 일명 KEVM: K의 EVM 시맨틱](https://jellopaper.org/) +- [Beigepaper](https://github.com/chronaeon/beigepaper) +- [이더리움 가상 머신 연산 부호](https://www.ethervm.io/) +- [이더리움 가상 머신 연산 부호 대화형 레퍼런스](https://www.evm.codes/) +- [Solidity 개발문서의 간단한 소개](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html#index-6) +- [마스터링 이더리움 - 이더리움 가상 머신](https://github.com/ethereumbook/ethereumbook/blob/openedition/13evm.asciidoc) + +## 관련 주제 {#related-topics} + +- [가스](/developers/docs/gas/) diff --git a/public/content/translations/ko/developers/docs/evm/opcodes/index.md b/public/content/translations/ko/developers/docs/evm/opcodes/index.md new file mode 100644 index 00000000000..11ff5d06b9c --- /dev/null +++ b/public/content/translations/ko/developers/docs/evm/opcodes/index.md @@ -0,0 +1,177 @@ +--- +title: "EVM용 연산 부호" +description: "이더리움 가상 머신에서 사용할 수 있는 모든 연산 부호 목록입니다." +lang: ko +--- + +## 개요 {#overview} + +[wolflo/evm-opcodes](https://github.com/wolflo/evm-opcodes)에 있는 EVM 참조 페이지의 업데이트된 버전입니다. +또한 [옐로페이퍼](https://ethereum.github.io/yellowpaper/paper.pdf), [젤로페이퍼](https://jellopaper.org/evm/), [geth](https://github.com/ethereum/go-ethereum) 구현을 참고했습니다. +이 문서는 이해하기 쉬운 참조 자료로 만들어졌지만, 특별히 엄격하지는 않습니다. +정확성을 확인하고 모든 에지 케이스를 인지하고 싶다면, 젤로페이퍼 또는 클라이언트 구현을 사용하는 것이 좋습니다. + +상호작용형 참조 자료를 찾고 계신가요? [evm.codes](https://www.evm.codes/)를 확인해 보세요. + +동적 가스 비용이 드는 연산에 대해서는 [gas.md](https://github.com/wolflo/evm-opcodes/blob/main/gas.md)를 참조하세요. + +💡 빠른 팁: 전체 라인을 보려면, 데스크톱에서 `[shift] + 스크롤`을 사용하여 가로로 스크롤하세요. + +| 스택 | 이름 | 가스 | 초기 스택 | 결과 스택 | 메모리 / 스토리지 | 참고사항 | | +| :---: | :------------- | :---------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | +| 00 | STOP | 0 | | | | 실행 중단 | | +| 01 | ADD | 3 | `a, b` | `a + b` | | (u)int256 덧셈(모듈로 2\*\*256) | | +| 02 | MUL | 5 | `a, b` | `a * b` | | (u)int256 곱셈(모듈로 2\*\*256) | | +| 03 | SUB | 3 | `a, b` | `a - b` | | (u)int256 뺄셈(모듈로 2\*\*256) | | +| 04 | DIV | 5 | `a, b` | `a // b` | | uint256 나눗셈 | | +| 05 | SDIV | 5 | `a, b` | `a // b` | | int256 나눗셈 | | +| 06 | MOD | 5 | `a, b` | `a % b` | | uint256 모듈로 | | +| 07 | SMOD | 5 | `a, b` | `a % b` | | int256 모듈로 | | +| 08 | ADDMOD | 8 | `a, b, N` | `(a + b) % N` | | (u)int256 덧셈(모듈로 N) | | +| 09 | MULMOD | 8 | `a, b, N` | `(a * b) % N` | | (u)int256 곱셈(모듈로 N) | | +| 0A | EXP | [A1](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a1-exp) | `a, b` | `a ** b` | | uint256 거듭제곱(모듈로 2\*\*256) | | +| 0B | SIGNEXTEND | 5 | `b, x` | `SIGNEXTEND(x, b)` | | `x`를 `(b+1)` 바이트에서 32바이트로 [부호 확장](https://wikipedia.org/wiki/Sign_extension) | | +| 0C-0F | _유효하지 않음_ | | | | | | | +| 10 | LT | 3 | `a, b` | `a < b` | | uint256 보다 작음 | | +| 11 | GT | 3 | `a, b` | `a > b` | | uint256 보다 큼 | | +| 12 | SLT | 3 | `a, b` | `a < b` | | int256 보다 작음 | | +| 13 | SGT | 3 | `a, b` | `a > b` | | int256 보다 큼 | | +| 14 | EQ | 3 | `a, b` | `a == b` | | (u)int256 같음 | | +| 15 | ISZERO | 3 | `a` | `a == 0` | | (u)int256이 0인지 확인 | | +| 16 | AND | 3 | `a, b` | `a && b` | | 비트 AND | | +| 17 | OR | 3 | `a, b` | `a \\|\\| b` | | 비트 OR | | +| 18 | XOR | 3 | `a, b` | `a ^ b` | | 비트 XOR | | +| 19 | NOT | 3 | `a` | `~a` | | 비트 NOT | | +| 1A | BYTE | 3 | `i, x` | `(x >> (248 - i * 8)) && 0xFF` | | 왼쪽부터 (u)int256 `x`의 `i`번째 바이트 | | +| 1B | SHL | 3 | `shift, val` | `val << shift` | | 왼쪽으로 시프트 | | +| 1C | SHR | 3 | `shift, val` | `val >> shift` | | 논리적 오른쪽 시프트 | | +| 1D | SAR | 3 | `shift, val` | `val >> shift` | | 산술적 오른쪽 시프트 | | +| 1E-1F | _유효하지 않음_ | | | | | | | +| 20 | KECCAK256 | [A2](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a2-sha3) | `ost, len` | `keccak256(mem[ost:ost+len-1])` | | keccak256 | | +| 21-2F | _유효하지 않음_ | | | | | | | +| 30 | ADDRESS | 2 | `.` | `address(this)` | | 실행 중인 컨트랙트의 주소 | | +| 31 | BALANCE | [A5](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a5-balance-extcodesize-extcodehash) | `addr` | `addr.balance` | | 잔액, wei 단위 | | +| 32 | ORIGIN | 2 | `.` | `tx.origin` | | 트랜잭션을 시작한 주소 | | +| 33 | CALLER | 2 | `.` | `msg.sender` | | 메시지 발신자의 주소 | | +| 34 | CALLVALUE | 2 | `.` | `msg.value` | | 메시지 값, wei 단위 | | +| 35 | CALLDATALOAD | 3 | `idx` | `msg.data[idx:idx+32]` | | 인덱스 `idx`에서 메시지 데이터 워드 읽기 | | +| 36 | CALLDATASIZE | 2 | `.` | `len(msg.data)` | | 메시지 데이터의 길이, 바이트 단위 | | +| 37 | CALLDATACOPY | [A3](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a3-copy-operations) | `dstOst, ost, len` | `.` | mem[dstOst:dstOst+len-1] := msg.data[ost:ost+len-1] | 메시지 데이터 복사 | | +| 38 | CODESIZE | 2 | `.` | `len(this.code)` | | 실행 중인 컨트랙트 코드의 길이, 바이트 단위 | | +| 39 | CODECOPY | [A3](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a3-copy-operations) | `dstOst, ost, len` | `.` | | mem[dstOst:dstOst+len-1] := this.code[ost:ost+len-1] | 실행 중인 컨트랙트의 바이트코드 복사 | +| 3A | GASPRICE | 2 | `.` | `tx.gasprice` | | 트랜잭션의 가스 가격, 가스 단위당 wei [\*\*](https://eips.ethereum.org/EIPS/eip-1559#gasprice) | | +| 3B | EXTCODESIZE | [A5](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a5-balance-extcodesize-extcodehash) | `addr` | `len(addr.code)` | | addr에 있는 코드 크기, 바이트 단위 | | +| 3C | EXTCODECOPY | [A4](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a4-extcodecopy) | `addr, dstOst, ost, len` | `.` | mem[dstOst:dstOst+len-1] := addr.code[ost:ost+len-1] | `addr`에서 코드 복사 | | +| 3D | RETURNDATASIZE | 2 | `.` | `size` | | 마지막 외부 호출에서 반환된 데이터의 크기, 바이트 단위 | | +| 3E | RETURNDATACOPY | [A3](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a3-copy-operations) | `dstOst, ost, len` | `.` | mem[dstOst:dstOst+len-1] := returndata[ost:ost+len-1] | 마지막 외부 호출에서 반환된 데이터 복사 | | +| 3F | EXTCODEHASH | [A5](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a5-balance-extcodesize-extcodehash) | `addr` | `hash` | | 해시 = addr이 존재하는 경우 ? keccak256(addr.code) : 0 | | +| 40 | BLOCKHASH | 20 | `blockNum` | `blockHash(blockNum)` | | | | +| 41 | COINBASE | 2 | `.` | `block.coinbase` | | 현재 블록 제안자의 주소 | | +| 42 | TIMESTAMP | 2 | `.` | `block.timestamp` | | 현재 블록의 타임스탬프 | | +| 43 | NUMBER | 2 | `.` | `block.number` | | 현재 블록의 번호 | | +| 44 | PREVRANDAO | 2 | `.` | `랜덤성 비콘` | | 랜덤성 비콘 | | +| 45 | GASLIMIT | 2 | `.` | `block.gaslimit` | | 현재 블록의 가스 한도 | | +| 46 | CHAINID | 2 | `.` | `chain_id` | | 현재 [체인 ID](https://eips.ethereum.org/EIPS/eip-155)를 스택에 푸시 | | +| 47 | SELFBALANCE | 5 | `.` | `address(this).balance` | | 실행 중인 컨트랙트의 잔액, wei 단위 | | +| 48 | BASEFEE | 2 | `.` | `block.basefee` | | 현재 블록의 기본 수수료 | | +| 49 | BLOBHASH | 3 | `idx` | `tx.blob_versioned_hashes[idx]` | | [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) | | +| 4A | BLOBBASEFEE | 2 | `.` | `block.blobbasefee` | | 현재 블록의 블롭 기본 수수료 ([EIP-7516](https://eips.ethereum.org/EIPS/eip-7516)) | | +| 4B-4F | _유효하지 않음_ | | | | | | | +| 50 | POP | 2 | `_anon` | `.` | | 스택 맨 위에서 항목을 제거하고 폐기 | | +| 51 | MLOAD | 3[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost` | `mem[ost:ost+32]` | | 오프셋 `ost`의 메모리에서 워드 읽기 | | +| 52 | MSTORE | 3[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost, val` | `.` | mem[ost:ost+32] := val | 메모리에 워드 쓰기 | | +| 53 | MSTORE8 | 3[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost, val` | `.` | mem[ost] := val && 0xFF | 메모리에 단일 바이트 쓰기 | | +| 54 | SLOAD | [A6](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a6-sload) | `key` | `storage[key]` | | 스토리지에서 워드 읽기 | | +| 55 | SSTORE | [A7](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a7-sstore) | `key, val` | `.` | storage[key] := val | 스토리지에 워드 쓰기 | | +| 56 | JUMP | 8 | `dst` | `.` | | `$pc := dst`는 `dst`가 유효한 점프 대상인 경우에만 `pc`가 할당됨을 표시 | | +| 57 | JUMPI | 10 | `dst, condition` | `.` | | `$pc := condition ?` dst : $pc + 1` | | +| 58 | PC | 2 | `.` | `$pc` | | 프로그램 카운터 | | +| 59 | MSIZE | 2 | `.` | `len(mem)` | | 현재 실행 컨텍스트의 메모리 크기, 바이트 단위 | | +| 5A | GAS | 2 | `.` | `gasRemaining` | | | | +| 5B | JUMPDEST | 1 | | | 유효한 점프 대상 표시 | 유효한 점프 대상(예: 푸시 데이터 내부에 있지 않은 점프 대상) | | +| 5C | TLOAD | 100 | `key` | `tstorage[key]` | | 임시 스토리지에서 워드 읽기 ([EIP-1153](https://eips.ethereum.org/EIPS/eip-1153)) | | +| 5D | TSTORE | 100 | `key, val` | `.` | tstorage[key] := val | 임시 스토리지에 워드 쓰기 ([EIP-1153](https://eips.ethereum.org/EIPS/eip-1153)) | | +| 5E | MCOPY | 3+3\*words+[A0](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `dstOst, ost, len` | `.` | mem[dstOst] := mem[ost:ost+len] | 한 영역에서 다른 영역으로 메모리 복사 ([EIP-5656](https://eips.ethereum.org/EIPS/eip-5656)) | | +| 5F | PUSH0 | 2 | `.` | `uint8` | | 상수 값 0을 스택에 푸시 | | +| 60 | PUSH1 | 3 | `.` | `uint8` | | 1바이트 값을 스택에 푸시 | | +| 61 | PUSH2 | 3 | `.` | `uint16` | | 2바이트 값을 스택에 푸시 | | +| 62 | PUSH3 | 3 | `.` | `uint24` | | 3바이트 값을 스택에 푸시 | | +| 63 | PUSH4 | 3 | `.` | `uint32` | | 4바이트 값을 스택에 푸시 | | +| 64 | PUSH5 | 3 | `.` | `uint40` | | 5바이트 값을 스택에 푸시 | | +| 65 | PUSH6 | 3 | `.` | `uint48` | | 6바이트 값을 스택에 푸시 | | +| 66 | PUSH7 | 3 | `.` | `uint56` | | 7바이트 값을 스택에 푸시 | | +| 67 | PUSH8 | 3 | `.` | `uint64` | | 8바이트 값을 스택에 푸시 | | +| 68 | PUSH9 | 3 | `.` | `uint72` | | 9바이트 값을 스택에 푸시 | | +| 69 | PUSH10 | 3 | `.` | `uint80` | | 10바이트 값을 스택에 푸시 | | +| 6A | PUSH11 | 3 | `.` | `uint88` | | 11바이트 값을 스택에 푸시 | | +| 6B | PUSH12 | 3 | `.` | `uint96` | | 12바이트 값을 스택에 푸시 | | +| 6C | PUSH13 | 3 | `.` | `uint104` | | 13바이트 값을 스택에 푸시 | | +| 6D | PUSH14 | 3 | `.` | `uint112` | | 14바이트 값을 스택에 푸시 | | +| 6E | PUSH15 | 3 | `.` | `uint120` | | 15바이트 값을 스택에 푸시 | | +| 6F | PUSH16 | 3 | `.` | `uint128` | | 16바이트 값을 스택에 푸시 | | +| 70 | PUSH17 | 3 | `.` | `uint136` | | 17바이트 값을 스택에 푸시 | | +| 71 | PUSH18 | 3 | `.` | `uint144` | | 18바이트 값을 스택에 푸시 | | +| 72 | PUSH19 | 3 | `.` | `uint152` | | 19바이트 값을 스택에 푸시 | | +| 73 | PUSH20 | 3 | `.` | `uint160` | | 20바이트 값을 스택에 푸시 | | +| 74 | PUSH21 | 3 | `.` | `uint168` | | 21바이트 값을 스택에 푸시 | | +| 75 | PUSH22 | 3 | `.` | `uint176` | | 22바이트 값을 스택에 푸시 | | +| 76 | PUSH23 | 3 | `.` | `uint184` | | 23바이트 값을 스택에 푸시 | | +| 77 | PUSH24 | 3 | `.` | `uint192` | | 24바이트 값을 스택에 푸시 | | +| 78 | PUSH25 | 3 | `.` | `uint200` | | 25바이트 값을 스택에 푸시 | | +| 79 | PUSH26 | 3 | `.` | `uint208` | | 26바이트 값을 스택에 푸시 | | +| 7A | PUSH27 | 3 | `.` | `uint216` | | 27바이트 값을 스택에 푸시 | | +| 7B | PUSH28 | 3 | `.` | `uint224` | | 28바이트 값을 스택에 푸시 | | +| 7C | PUSH29 | 3 | `.` | `uint232` | | 29바이트 값을 스택에 푸시 | | +| 7D | PUSH30 | 3 | `.` | `uint240` | | 30바이트 값을 스택에 푸시 | | +| 7E | PUSH31 | 3 | `.` | `uint248` | | 31바이트 값을 스택에 푸시 | | +| 7F | PUSH32 | 3 | `.` | `uint256` | | 32바이트 값을 스택에 푸시 | | +| 80 | DUP1 | 3 | `a` | `a, a` | | 스택의 첫 번째 값 복제 | | +| 81 | DUP2 | 3 | `_, a` | `a, _, a` | | 스택의 두 번째 값 복제 | | +| 82 | DUP3 | 3 | `_, _, a` | `a, _, _, a` | | 스택의 세 번째 값 복제 | | +| 83 | DUP4 | 3 | `_, _, _, a` | `a, _, _, _, a` | | 스택의 네 번째 값 복제 | | +| 84 | DUP5 | 3 | `..., a` | `a, ..., a` | | 스택의 다섯 번째 값 복제 | | +| 85 | DUP6 | 3 | `..., a` | `a, ..., a` | | 스택의 여섯 번째 값 복제 | | +| 86 | DUP7 | 3 | `..., a` | `a, ..., a` | | 스택의 일곱 번째 값 복제 | | +| 87 | DUP8 | 3 | `..., a` | `a, ..., a` | | 스택의 여덟 번째 값 복제 | | +| 88 | DUP9 | 3 | `..., a` | `a, ..., a` | | 스택의 아홉 번째 값 복제 | | +| 89 | DUP10 | 3 | `..., a` | `a, ..., a` | | 스택의 열 번째 값 복제 | | +| 8A | DUP11 | 3 | `..., a` | `a, ..., a` | | 스택의 열한 번째 값 복제 | | +| 8B | DUP12 | 3 | `..., a` | `a, ..., a` | | 스택의 열두 번째 값 복제 | | +| 8C | DUP13 | 3 | `..., a` | `a, ..., a` | | 스택의 열세 번째 값 복제 | | +| 8D | DUP14 | 3 | `..., a` | `a, ..., a` | | 스택의 열네 번째 값 복제 | | +| 8E | DUP15 | 3 | `..., a` | `a, ..., a` | | 스택의 열다섯 번째 값 복제 | | +| 8F | DUP16 | 3 | `..., a` | `a, ..., a` | | 스택의 열여섯 번째 값 복제 | | +| 90 | SWAP1 | 3 | `a, b` | `b, a` | | | | +| 91 | SWAP2 | 3 | `a, _, b` | `b, _, a` | | | | +| 92 | SWAP3 | 3 | `a, _, _, b` | `b, _, _, a` | | | | +| 93 | SWAP4 | 3 | `a, _, _, _, b` | `b, _, _, _, a` | | | | +| 94 | SWAP5 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 95 | SWAP6 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 96 | SWAP7 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 97 | SWAP8 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 98 | SWAP9 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 99 | SWAP10 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 9A | SWAP11 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 9B | SWAP12 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 9C | SWAP13 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 9D | SWAP14 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 9E | SWAP15 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 9F | SWAP16 | 3 | `a, ..., b` | `b, ..., a` | | | | +| A0 | LOG0 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len` | `.` | | LOG0(memory[ost:ost+len-1]) | | +| A1 | LOG1 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len, topic0` | `.` | | LOG1(memory[ost:ost+len-1], topic0) | | +| A2 | LOG2 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len, topic0, topic1` | `.` | | LOG2(memory[ost:ost+len-1], topic0, topic1) | | +| A3 | LOG3 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len, topic0, topic1, topic2` | `.` | | LOG3(memory[ost:ost+len-1], topic0, topic1, topic2) | | +| A4 | LOG4 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len, topic0, topic1, topic2, topic3` | `.` | | LOG4(memory[ost:ost+len-1], topic0, topic1, topic2, topic3) | | +| A5-EF | _유효하지 않음_ | | | | | | | +| F0 | CREATE | [A9](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a9-create-operations) | `val, ost, len` | `addr` | | addr = keccak256(rlp([주소(this), this.nonce])) | | +| F1 | CALL | [AA](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-call-operations) | gas, addr, val, argOst, argLen, retOst, retLen | `success` | mem[retOst:retOst+retLen-1] := returndata | | | +| F2 | CALLCODE | [AA](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-call-operations) | `gas, addr, val, argOst, argLen, retOst, retLen` | `success` | mem[retOst:retOst+retLen-1] = returndata | DELEGATECALL과 동일하지만, 원래의 msg.sender와 msg.value는 전파하지 않습니다. | | +| F3 | RETURN | 0[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost, len` | `.` | | mem[ost:ost+len-1] 반환 | | +| F4 | DELEGATECALL | [AA](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-call-operations) | `gas, addr, argOst, argLen, retOst, retLen` | `success` | mem[retOst:retOst+retLen-1] := returndata | | | +| F5 | CREATE2 | [A9](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a9-create-operations) | `val, ost, len, salt` | `addr` | | addr = keccak256(0xff ++ 주소(this) ++ salt ++ keccak256(mem[ost:ost+len-1]))[12:] | | +| F6-F9 | _유효하지 않음_ | | | | | | | +| FA | STATICCALL | [AA](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-call-operations) | `gas, addr, argOst, argLen, retOst, retLen` | `success` | mem[retOst:retOst+retLen-1] := returndata | | | +| FB-FC | _유효하지 않음_ | | | | | | | +| FD | REVERT | 0[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost, len` | `.` | | revert(mem[ost:ost+len-1]) | | +| FE | INVALID | [AF](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#af-invalid) | | | 지정된 유효하지 않은 연산 부호 - [EIP-141](https://eips.ethereum.org/EIPS/eip-141) | | | +| FF | SELFDESTRUCT | [AB](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#ab-selfdestruct) | `addr` | `.` | | 모든 ETH를 `addr`로 보냅니다. 컨트랙트가 생성된 것과 동일한 트랜잭션에서 실행되면 해당 컨트랙트를 파기합니다. | | diff --git a/public/content/translations/ko/developers/docs/frameworks/index.md b/public/content/translations/ko/developers/docs/frameworks/index.md new file mode 100644 index 00000000000..2a2f6e3d1c3 --- /dev/null +++ b/public/content/translations/ko/developers/docs/frameworks/index.md @@ -0,0 +1,149 @@ +--- +title: "디앱 개발 프레임워크" +description: "프레임워크 사용 시의 장점을 알아보고 가능한 옵션들을 비교해 봅니다." +lang: ko +--- + +## 프레임워크 소개 {#introduction-to-frameworks} + +온전한 형태의 디앱을 구축하려면 서로 다른 여러 기술들이 필요합니다. 소프트웨어 프레임워크는 필요한 기능을 많이 포함하거나 사용자가 원하는 도구를 찾도록 도와주는 다루기 쉬운 플러그인 시스템을 제공합니다. + +프레임워크에는 다음과 같이 추가 작업 없이 바로 사용할 수 있는 기능들이 있습니다. + +- 로컬 블록체인 인스턴스를 스핀업하기 위한 기능. +- 스마트 계약을 컴파일하고 테스트하기 위한 유틸리티. +- 동일한 프로젝트/리포지토리 내에서 사용자 대상 애플리케이션을 빌드하기 위한 클라이언트 개발 애드온. +- 로컬에서 실행되는 인스턴스 또는 이더리움 공개 네트워크 중 하나에 이더리움 네트워크를 연결하고 컨트랙트를 배포하기 위한 구성입니다. +- 탈중앙화 앱 배포 - IPFS와 같은 스토리지 옵션과의 통합. + +## 필수 구성 요소 {#prerequisites} + +프레임워크를 시작하기 전에 [탈중앙화앱](/developers/docs/dapps/)과 [이더리움 스택](/developers/docs/ethereum-stack/)에 대한 소개를 먼저 읽어보시는 것을 권장합니다. + +## 사용 가능한 프레임워크 {#available-frameworks} + +**Foundry** - **_Foundry는 이더리움 애플리케이션 개발을 위한 매우 빠르고, 이식성이 뛰어나며 모듈화된 툴킷입니다_** + +- [Foundry 설치](https://book.getfoundry.sh/) +- [Foundry 북](https://book.getfoundry.sh/) +- [텔레그램의 Foundry 커뮤니티 채팅](https://t.me/foundry_support) +- [Awesome Foundry](https://github.com/crisgarner/awesome-foundry) + +**Hardhat -** **_전문가를 위한 이더리움 개발 환경입니다._** + +- [hardhat.org](https://hardhat.org) +- [GitHub](https://github.com/nomiclabs/hardhat) + +**Ape -** **_Python 개발자, 데이터 과학자, 보안 전문가를 위한 스마트 컨트랙트 개발 도구입니다._** + +- [문서](https://docs.apeworx.io/ape/stable/) +- [GitHub](https://github.com/ApeWorX/ape) + +**Web3j -** **_JVM에서 블록체인 애플리케이션을 개발하기 위한 플랫폼입니다._** + +- [홈페이지](https://www.web3labs.com/web3j-sdk) +- [문서](https://docs.web3j.io) +- [GitHub](https://github.com/web3j/web3j) + +**ethers-kt -** **_EVM 기반 블록체인을 위한 비동기, 고성능 Kotlin/Java/Android 라이브러리입니다._** + +- [GitHub](https://github.com/Kr1ptal/ethers-kt) +- [예제](https://github.com/Kr1ptal/ethers-kt/tree/master/examples) +- [Discord](https://discord.gg/rx35NzQGSb) + +**Create Eth App -** **_명령어 하나로 이더리움 기반 앱을 만드세요. UI 프레임워크와 DeFi 템플릿의 다양한 선택지를 제공합니다._** + +- [GitHub](https://github.com/paulrberg/create-eth-app) +- [템플릿](https://github.com/PaulRBerg/create-eth-app/tree/develop/templates) + +**Scaffold-Eth -** **_Ethers.js + Hardhat + web3용 React 컴포넌트 및 후크: 스마트 컨트랙트로 구동되는 탈중앙화 애플리케이션 구축을 시작하는 데 필요한 모든 것을 제공합니다._** + +- [GitHub](https://github.com/scaffold-eth/scaffold-eth-2) + +**Tenderly -** **_블록체인 개발자가 스마트 컨트랙트를 빌드, 테스트, 디버그, 모니터링 및 운영하고 dapp UX를 개선할 수 있도록 지원하는 Web3 개발 플랫폼입니다._** + +- [웹사이트](https://tenderly.co/) +- [문서](https://docs.tenderly.co/) + +**The Graph -** **_블록체인 데이터를 효율적으로 쿼리하기 위한 The Graph입니다._** + +- [웹사이트](https://thegraph.com/) +- [튜토리얼](/developers/tutorials/the-graph-fixing-web3-data-querying/) + +**Alchemy -** **_이더리움 개발 플랫폼입니다._** + +- [alchemy.com](https://www.alchemy.com/) +- [GitHub](https://github.com/alchemyplatform) +- [Discord](https://discord.com/invite/alchemyplatform) + +**NodeReal -** **_이더리움 개발 플랫폼입니다._** + +- [Nodereal.io](https://nodereal.io/) +- [GitHub](https://github.com/node-real) +- [Discord](https://discord.gg/V5k5gsuE) + +**thirdweb SDK -** **_강력한 SDK와 CLI를 사용하여 스마트 컨트랙트와 상호 작용할 수 있는 web3 애플리케이션을 빌드하세요._** + +- [문서](https://portal.thirdweb.com/sdk/) +- [GitHub](https://github.com/thirdweb-dev/) + +**Chainstack -** **_Web3(이더리움 및 기타) 개발 플랫폼입니다._** + +- [chainstack.com](https://www.chainstack.com/) +- [GitHub](https://github.com/chainstack) +- [Discord](https://discord.gg/BSb5zfp9AT) + +**Crossmint -** **_모든 주요 EVM 체인(및 기타)에서 NFT 애플리케이션을 빌드할 수 있는 엔터프라이즈급 web3 개발 플랫폼입니다._** + +- [웹사이트](https://www.crossmint.com) +- [개발문서](https://docs.crossmint.com) +- [Discord](https://discord.com/invite/crossmint) + +**Brownie -** **_Python 기반 개발 환경 및 테스트 프레임워크입니다._** + +- [문서](https://eth-brownie.readthedocs.io/en/latest/) +- [GitHub](https://github.com/eth-brownie/brownie) +- **Brownie는 현재 유지보수되지 않습니다** + +**OpenZeppelin SDK -** **_궁극의 스마트 컨트랙트 툴킷: 스마트 컨트랙트를 개발, 컴파일, 업그레이드, 배포하고 상호작용하는 데 도움이 되는 도구 모음입니다._** + +- [OpenZeppelin Defender SDK](https://docs.openzeppelin.com/defender/sdk) +- [GitHub](https://github.com/OpenZeppelin/openzeppelin-sdk) +- [커뮤니티 포럼](https://forum.openzeppelin.com/c/support/17) +- **OpenZeppelin SDK 개발이 종료되었습니다** + +**Catapulta -** **_다중 체인 스마트 컨트랙트 배포 도구로, 블록 탐색기에서 검증을 자동화하고 배포된 스마트 컨트랙트를 추적하며 배포 보고서를 공유합니다. Foundry 및 Hardhat 프로젝트를 위한 플러그 앤 플레이 방식입니다._** + +- [웹사이트](https://catapulta.sh/) +- [문서](https://catapulta.sh/docs) +- [GitHub](https://github.com/catapulta-sh) + +**GoldRush(Covalent 제공) -** **_GoldRush는 개발자, 분석가, 기업을 위한 가장 포괄적인 블록체인 데이터 API 제품군을 제공합니다. 디파이 대시보드, 지갑, 트레이딩 봇, AI 에이전트 또는 규정 준수 플랫폼을 구축하는 경우, 데이터 API는 필요한 필수 온체인 데이터에 빠르고 정확하며 개발자 친화적인 액세스를 제공합니다_** + +- [웹사이트](https://goldrush.dev/) +- [문서](https://goldrush.dev/docs/chains/ethereum) +- [GitHub](https://github.com/covalenthq) +- [Discord](https://www.covalenthq.com/discord/) + +**Wake -** **_컨트랙트 테스트, 퍼징, 배포, 취약점 스캐닝, 코드 탐색을 위한 올인원 Python 프레임워크입니다._** + +- [홈페이지](https://getwake.io/) +- [문서](https://ackeeblockchain.com/wake/docs/latest/) +- [GitHub](https://github.com/Ackee-Blockchain/wake) +- [VS Code 확장 프로그램](https://marketplace.visualstudio.com/items?itemName=AckeeBlockchain.tools-for-solidity) + +**Veramo -** **_탈중앙화 애플리케이션 개발자가 자신의 애플리케이션에 탈중앙화 신원 및 검증 가능한 자격 증명을 쉽게 구축할 수 있도록 지원하는 오픈 소스, 모듈식, 독립 프레임워크입니다._** + +- [홈페이지](https://veramo.io/) +- [문서](https://veramo.io/docs/basics/introduction) +- [GitHub](https://github.com/uport-project/veramo) +- [Discord](https://discord.com/invite/FRRBdjemHV) +- [NPM 패키지](https://www.npmjs.com/package/@veramo/core) + +## 더 읽어보기 {#further-reading} + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 관련 주제 {#related-topics} + +- [로컬 개발 환경 설정](/developers/local-environment/) diff --git a/public/content/translations/ko/developers/docs/gas/index.md b/public/content/translations/ko/developers/docs/gas/index.md new file mode 100644 index 00000000000..0e281e627cc --- /dev/null +++ b/public/content/translations/ko/developers/docs/gas/index.md @@ -0,0 +1,151 @@ +--- +title: "가스와 수수료" +metaTitle: "이더리움 가스와 수수료: 기술적 개요" +description: "이더리움 가스 수수료, 계산 방법, 네트워크 보안 및 트랜잭션 처리에서 가스 수수료의 역할에 대해 알아보세요." +lang: ko +--- + +가스는 이더리움 네트워크의 필수적인 요소입니다. 자동차를 주행하기 위해 가솔린이 필요하듯이, 이더리움 네트워크의 연료와 같은 역할을 합니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하려면 먼저 [트랜잭션](/developers/docs/transactions/)과 [EVM](/developers/docs/evm/)에 대해 읽어보시는 것을 권장합니다. + +## 가스란 무엇인가요? {#what-is-gas} + +가스는 이더리움 네트워크에서 특정 동작을 실행하기 위해 요구되는 노력에 대한 양과 같습니다. + +각 이더리움 트랜잭션을 실행하려면 컴퓨팅 리소스가 필요하므로, 이더리움이 스팸에 취약하지 않고 무한한 계산 루프에 빠지지 않도록 하려면 이러한 리소스에 대한 비용을 지불해야 합니다. 연산에 대한 지불은 가스 수수료의 형태로 이루어집니다. + +가스 수수료는 특정 작업을 수행하는 데 사용된 가스의 양에 단위 가스당 비용을 곱한 값입니다. 수수료는 트랜잭션의 성공 여부와 관계없이 지불됩니다. + +![EVM 연산에 가스가 필요한 위치를 보여주는 다이어그램](./gas.png) +_[이더리움 EVM 일러스트](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)에서 발췌한 다이어그램_ + +가스 수수료는 이더리움의 고유 통화인 이더(ETH)로 지불해야 합니다. 가스 가격은 보통 ETH의 단위인 gwei로 표시됩니다. gwei는 1ETH의 10억분의 1(0.000000001 ETH or 10-9 ETH) 과 같습니다. + +예를 들어, 가스가 0.000000001 ETH라고 말하는 대신, 1 Gwei 라고 말할 수 있습니다. + +'gwei'라는 단어는 'giga-wei'의 축약어로, '10억 wei'를 의미합니다. 1 gwei는 10억 wei와 같습니다. Wei 자체([b-money](https://www.investopedia.com/terms/b/bmoney.asp)의 개발자인 [웨이 다이](https://wikipedia.org/wiki/Wei_Dai)의 이름을 따서 명명)는 ETH의 가장 작은 단위입니다. + +## 가스 수수료는 어떻게 계산되나요? {#how-are-gas-fees-calculated} + +트랜잭션을 제출할 때 지불하고자 하는 가스의 양을 설정할 수 있습니다. 특정 양의 가스를 제공함으로써 다음 블록에 트랜잭션이 포함되도록 입찰하는 것입니다. 너무 적은 금액을 제시하면 검증자가 트랜잭션을 포함하도록 선택할 가능성이 낮아지므로 트랜잭션이 늦게 실행되거나 전혀 실행되지 않을 수 있습니다. 너무 많이 제공하면 일부 ETH를 낭비할 수 있습니다. 그렇다면 얼마를 지불해야 하는지 어떻게 알 수 있을까요? + +총 가스 지불액은 `기본 수수료`와 `우선 수수료`(팁)의 두 가지 구성 요소로 나뉩니다. + +`기본 수수료`는 프로토콜에 의해 설정되며, 트랜잭션이 유효한 것으로 간주되려면 최소한 이 금액을 지불해야 합니다. `우선 수수료`는 기본 수수료에 추가하는 팁으로, 검증자가 다음 블록에 포함하도록 트랜잭션을 매력적으로 만드는 역할을 합니다. + +`기본 수수료`만 지불하는 트랜잭션은 기술적으로는 유효하지만, 검증자가 다른 트랜잭션보다 이를 선택할 인센티브가 없기 때문에 포함될 가능성이 낮습니다. '올바른' `우선` 수수료는 트랜잭션을 보낼 때의 네트워크 사용량에 따라 결정됩니다. 수요가 많으면 `우선` 수수료를 더 높게 설정해야 할 수도 있지만, 수요가 적을 때는 더 적게 지불할 수 있습니다. + +예를 들어, 조던이 테일러에게 1 ETH를 지불해야 한다고 가정해 봅시다. ETH 전송에는 21,000개의 가스 단위가 필요하며, 기본 요금은 10 gwei입니다. Jordan은 2gwei 만큼의 팁을 포함하고 있습니다. + +총 수수료는 다음과 같이 계산됩니다: + +`가스 사용 단위 * (기본 요금 + 우선 요금)` + +여기서 `기본 수수료`는 프로토콜에 의해 설정된 값이고, `우선 수수료`는 사용자가 검증자에게 팁으로 설정한 값입니다. + +예: `21,000 * (10 + 2) = 252,000 gwei` (0.000252 ETH). + +만약 Jordan이 1 ETH만큼의 돈을 보낸다면, 1.000252 이더만큼의 돈이 Jordan의 계좌에서 빠져나가게 됩니다. 그리고 Taylor는 1.0000ETH만큼의 돈을 얻게되죠. 검증자는 0.000042 ETH의 팁을 받습니다. 0.00021 ETH의 `기본 수수료`는 소각됩니다. + +### 기본 수수료 {#base-fee} + +모든 블록에는 예비 가격 역할을 하는 base fee이 있습니다. 블록에 포함될 자격이 있으려면 가스당 제시 가격이 최소한 base fee와 같아야 합니다. 기본 수수료는 현재 블록과 독립적으로 계산되며, 이전 블록에 의해 결정되므로 사용자가 거래 수수료를 더 쉽게 예측할 수 있습니다. 블록이 생성될 때 이 기본 수수료는 "소각"되어 유통에서 제거됩니다. + +기본 수수료는 이전 블록의 크기(모든 트랜잭션에 사용된 가스 양)를 목표 크기(가스 한도의 절반)와 비교하는 공식으로 계산됩니다. 목표 블록 크기가 목표보다 크거나 작을 경우, 기본 수수료는 블록당 최대 12.5%씩 증가하거나 감소합니다. 이러한 기하급수적인 성장은 블록 크기가 무한정 높게 유지되는 것을 경제적으로 불가능하게 만든다 + +| 블록 번호 | 포함된 가스 | 요금 상승률 | 현재 기본 요금 | +| ----- | -----: | --------------------: | -------------------------: | +| 1 | 18M | 0% | 100 gwei | +| 2 | 36M | 0% | 100 gwei | +| 3 | 36M | 12.5% | 112.5 gwei | +| 4 | 36M | 12.5% | 126.6 gwei | +| 5 | 36M | 12.5% | 142.4 gwei | +| 6 | 36M | 12.5% | 160.2 gwei | +| 7 | 36M | 12.5% | 180.2 gwei | +| 8 | 36M | 12.5% | 202.7 gwei | + +위 표에서는 가스 한도로 3,600만을 사용하여 예시를 보여줍니다. 이 예를 들어, 9번 블록에 트랜잭션을 생성하기 위해 지갑은 사용자에게 다음 블록에 추가될 최대 기본 수수료가 `현재 기본 수수료 * 112.5%` 또는 `202.7 gwei * 112.5% = 228.1 gwei`임을 확실하게 알려줍니다. + +기본 요금이 가득 찬 블록에 앞서 빠르게 증가하기 때문에 가득 찬 블록이 지속적으로 발생할 가능성은 낮습니다. + +| 블록 번호 | 포함된 가스 | 요금 상승률 | 현재 기본 요금 | +| --------------------------------------------------- | --------------------------------------------------: | --------------------: | --------------------------------------------------: | +| 30 | 36M | 12.5% | 2705.6 gwei | +| ... | ... | 12.5% | ... | +| 50 | 36M | 12.5% | 28531.3 gwei | +| ... | ... | 12.5% | ... | +| 100 | 36M | 12.5% | 10302608.6 gwei | + +### 우선 수수료(팁) {#priority-fee} + +우선 수수료(팁)는 검증자가 블록 가스 한도에 의해서만 제한된 블록의 트랜잭션 수를 최대화하도록 장려합니다. 팁이 없다면, 합리적인 검증자는 스테이킹 보상이 블록에 있는 트랜잭션 수와 무관하므로 직접적인 실행 레이어나 합의 레이어 페널티 없이 더 적은 수의 트랜잭션(또는 0개의 트랜잭션)을 포함할 수 있습니다. 또한 팁은 사용자가 동일한 블록 내에서 우선순위를 위해 다른 사람보다 높은 가격을 제시할 수 있게 하여 사실상 긴급성을 알립니다. + +### 최대 수수료 {#maxfee} + +네트워크에서 트랜잭션을 실행하기 위해 사용자는 실행할 트랜잭션에 대해 지불할 최대 한도를 지정할 수 있습니다. 이 선택적 매개변수는 `maxFeePerGas`로 알려져 있습니다. 거래가 실행되려면 최대 수수료가 기본 수수료와 팁의 합계를 초과해야 합니다. 거래 발송자는 최대 수수료와 기본 수수료 및 팁의 합계액의 차액을 환불받는다. + +### 블록 크기 {#block-size} + +각 블록의 목표 크기는 현재 가스 한도의 절반이지만, 블록 크기는 네트워크 수요에 따라 블록 한도(목표 블록 크기의 2배)에 도달할 때까지 증가하거나 감소합니다. 이 프로토콜은 _tâtonnement_ 프로세스를 통해 목표에서 평균 평형 블록 크기를 달성합니다. 이는 블록 크기가 목표 블록 크기보다 클 경우 프로토콜이 다음 블록에 대한 기본 요금을 증가시킨다는 것을 의미합니다. 마찬가지로, 블록 크기가 목표 블록 크기보다 작으면 프로토콜은 기본 요금을 감소시킵니다. + +Base fee를 조정하는 금액은 현재 블록 크기가 대상에서 얼마나 멀리 떨어져 있는지에 비례합니다. 이는 빈 블록의 경우 -12.5%, 목표 크기에서 0%, 가스 한도에 도달하는 블록의 경우 최대 +12.5%까지 선형으로 계산됩니다. 가스 한도는 검증자 신호와 네트워크 업그레이드를 통해 시간에 따라 변동될 수 있습니다. [여기에서 시간 경과에 따른 가스 한도의 변화를 볼 수 있습니다](https://eth.blockscout.com/stats/averageGasLimit?interval=threeMonths). + +[블록에 대해 더 알아보기](/developers/docs/blocks/) + +### 실제 가스 수수료 계산 {#calculating-fees-in-practice} + +거래를 실행하기 위해 지불할 금액을 명시적으로 설정할 수 있습니다. 그러나 대부분의 지갑 제공업체는 사용자 부담을 줄이기 위해 권장 거래 수수료(기본 요금 + 권장 우선 요금)를 자동으로 설정합니다. + +## 왜 가스 요금이 있는지? {#why-do-gas-fees-exist} + +간단히, 가스 요금은 이더리움 네트워크를 더 안전하게 유지하도록 돕습니다. 네트워크에서 실행되는 모든 계산에 대해 수수료를 요구함으로써, 우리는 나쁜 행위자들이 네트워크를 스팸하는 것을 방지한다. 우발적이거나 적대적인 무한 루프 또는 코드의 다른 계산 낭비를 피하기 위해, 각 트랜잭션은 코드 실행의 몇 가지 계산 단계를 사용할 수 있는지에 대한 제한을 설정해야 한다. 연산의 기본 단위가 "가스"입니다. + +트랜잭션에 한도가 포함되어 있지만, 트랜잭션에서 사용되지 않은 가스는 사용자에게 반환됩니다(예: `최대 수수료 - (기본 수수료 + 팁)`이 반환됨). + +![사용하지 않은 가스가 환불되는 방식을 보여주는 다이어그램](../transactions/gas-tx.png) +_[이더리움 EVM 일러스트](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)에서 발췌한 다이어그램_ + +## 가스 한도란 무엇입니까? {#what-is-gas-limit} + +가스 한도는 거래에 소비할 수 있는 최대 가스 양을 의미합니다. [스마트 계약](/developers/docs/smart-contracts/)과 관련된 더 복잡한 트랜잭션은 더 많은 계산 작업을 필요로 하므로, 단순한 결제보다 더 높은 가스 한도를 요구합니다. 표준 ETH 전송에는 21,000 단위의 가스 제한이 필요합니다. + +예를 들어, 단순 ETH 전송을 위해 가스 제한을 50,000으로 설정하면 EVM이 21,000을 소비하고 나머지 29,000을 돌려받게 됩니다. 하지만 가스를 너무 적게 지정하면(예: 단순 ETH 전송에 대한 가스 한도를 20,000으로 설정) 트랜잭션은 유효성 검사 단계에서 실패합니다. 블록에 포함되기 전에 거부되며 가스가 소모되지 않습니다. 반면에, 실행 중에 트랜잭션의 가스가 부족하면(예: 스마트 계약이 중간에 모든 가스를 소진) EVM은 모든 변경 사항을 되돌리지만, 제공된 모든 가스는 수행된 작업에 대해 계속 소모됩니다. + +## 가스 요금이 왜 이렇게 높은 건가요? {#why-can-gas-fees-get-so-high} + +높은 가스 요금은 이더리움의 인기 때문이다. 수요가 너무 많으면 사용자는 다른 사용자의 거래보다 높은 팁을 제공하여 경쟁할 수 있습니다. 팁이 높을수록 거래가 다음 블록으로 이동할 가능성이 높아집니다. 또한, 복잡한 스마트 계약 앱은 기능을 지원하기 위해 많은 작업을 수행할 수 있어 많은 가스를 소비할 수 있습니다. + +## 가스 비용 절감 이니셔티브 {#initiatives-to-reduce-gas-costs} + +이더리움 [확장성 업그레이드](/roadmap/)는 궁극적으로 일부 가스 수수료 문제를 해결하여 플랫폼이 초당 수천 건의 트랜잭션을 처리하고 전 세계적으로 확장할 수 있도록 해야 합니다. + +계층 2 스케일링은 가스 비용, 사용자 경험 및 확장성을 크게 개선하기 위한 주요 계획입니다. + +[레이어 2 확장에 대해 더 알아보기](/developers/docs/scaling/#layer-2-scaling) + +## 가스 수수료 모니터링 {#monitoring-gas-fees} + +가스 가격을 모니터링하여 ETH를 더 저렴하게 전송하려면 다음과 같은 다양한 도구를 사용할 수 있습니다. + +- [Etherscan](https://etherscan.io/gastracker) _트랜잭션 가스 가격 추정기_ +- [Blockscout](https://eth.blockscout.com/gas-tracker) _오픈 소스 트랜잭션 가스 가격 추정기_ +- [ETH 가스 추적기](https://www.ethgastracker.com/) _이더리움 및 L2 가스 가격을 모니터링하고 추적하여 거래 수수료를 줄이고 비용을 절약하세요_ +- [Blocknative ETH Gas Estimator](https://chrome.google.com/webstore/detail/blocknative-eth-gas-estim/ablbagjepecncofimgjmdpnhnfjiecfm) _유형 0 레거시 트랜잭션과 유형 2 EIP-1559 트랜잭션을 모두 지원하는 가스 추정 Chrome 확장 프로그램입니다._ +- [Cryptoneur 가스 수수료 계산기](https://www.cryptoneur.xyz/gas-fees-calculator) _메인넷, Arbitrum, Polygon에서 다양한 트랜잭션 유형에 대한 가스 수수료를 현지 통화로 계산합니다._ + +## 관련 도구 {#related-tools} + +- [Blocknative 가스 플랫폼](https://www.blocknative.com/gas) _Blocknative의 글로벌 멤풀 데이터 플랫폼으로 구동되는 가스 추정 API_ +- [가스 네트워크](https://gas.network) 온체인 가스 오라클. 35개 이상의 체인 지원. + +## 더 읽어보기 {#further-reading} + +- [이더리움 가스 설명](https://defiprime.com/gas) +- [스마트 계약의 가스 소비량 줄이기](https://medium.com/coinmonks/8-ways-of-reducing-the-gas-consumption-of-your-smart-contracts-9a506b339c0a) +- [개발자를 위한 가스 최적화 전략](https://www.alchemy.com/overviews/solidity-gas-optimization) +- [EIP-1559 문서](https://eips.ethereum.org/EIPS/eip-1559). +- [팀 베이코의 EIP-1559 관련 자료](https://hackmd.io/@timbeiko/1559-resources) +- [EIP-1559: 밈과 메커니즘 분리](https://web.archive.org/web/20241126205908/https://research.2077.xyz/eip-1559-separating-mechanisms-from-memes) diff --git a/public/content/translations/ko/developers/docs/ides/index.md b/public/content/translations/ko/developers/docs/ides/index.md new file mode 100644 index 00000000000..8297449dca6 --- /dev/null +++ b/public/content/translations/ko/developers/docs/ides/index.md @@ -0,0 +1,64 @@ +--- +title: "통합 개발 환경(IDE)" +description: "리믹스, VS Code 및 인기 플러그인을 비롯한 이더리움 개발용 웹 기반 및 데스크톱 IDE에 대해 알아보세요." +lang: ko +--- + +[통합 개발 환경(IDE)](https://wikipedia.org/wiki/Integrated_development_environment)을 설정할 때, 이더리움 애플리케이션을 프로그래밍하는 것은 다른 소프트웨어 프로젝트를 프로그래밍하는 것과 유사합니다. 선택할 수 있는 옵션이 많으므로, 최종적으로는 자신의 취향에 가장 적합한 IDE 또는 코드 편집기를 선택하세요. 이더리움 개발을 위한 가장 좋은 IDE 선택은 전통적인 소프트웨어 개발에 이미 사용 중인 IDE일 가능성이 큽니다. + +## 웹 기반 IDE {#web-based-ides} + +[로컬 개발 환경을 설정](/developers/local-environment/)하기 전에 코드를 만져보고 싶다면, 이 웹 앱들은 이더리움 스마트 계약 개발을 위해 맞춤 제작되었습니다. + +**[Remix](https://remix.ethereum.org/)** - **_정적 분석 기능 및 테스트 블록체인 가상 머신이 내장된 웹 기반 IDE_** + +- [문서](https://remix-ide.readthedocs.io/en/latest/#) +- [Gitter](https://gitter.im/ethereum/remix) + +**[ChainIDE](https://chainide.com/)** - **_클라우드 기반 멀티체인 IDE_** + +- [문서](https://chainide.gitbook.io/chainide-english-1/) +- [도움말 포럼](https://forum.chainide.com/) + +**[Replit (Solidity Starter - Beta)](https://replit.com/@replit/Solidity-starter-beta)** - **_핫 리로딩, 오류 검사 및 최고 수준의 테스트넷 지원을 갖춘 맞춤형 이더리움 개발 환경_** + +- [문서](https://docs.replit.com/) + +**[Tenderly Sandbox](https://sandbox.tenderly.co/)** - **_솔리디티(Solidity)와 자바스크립트(JavaScript)를 사용하여 브라우저에서 스마트 계약을 작성, 실행, 디버깅할 수 있는 빠른 프로토타이핑 환경_** + +**[EthFiddle](https://ethfiddle.com/)** - **_스마트 계약을 작성, 컴파일, 디버깅할 수 있는 웹 기반 IDE_** + +- [Gitter](https://gitter.im/loomnetwork/ethfiddle) + +## 데스크톱 IDE {#desktop-ides} + +가장 잘 알려진 IDE들은 이더리움 개발 경험을 향상시키기 위해 플러그인을 내장하고 있습니다. 최소한 [스마트 계약 언어](/developers/docs/smart-contracts/languages/)에 대한 구문 강조 기능을 제공합니다. + +**Visual Studio Code -** **_이더리움(Ethereum)을 공식 지원하는 전문 크로스플랫폼 IDE_** + +- [Visual Studio Code](https://code.visualstudio.com/) +- [코드 샘플](https://github.com/Azure-Samples/blockchain/blob/master/blockchain-workbench/application-and-smart-contract-samples/readme.md) +- [GitHub](https://github.com/microsoft/vscode) + +**JetBrains IDEs (IntelliJ IDEA 등)** -\*\* **_소프트웨어 개발자와 팀을 위한 필수 도구_** + +- [JetBrains](https://www.jetbrains.com/) +- [GitHub](https://github.com/JetBrains) +- [IntelliJ Solidity](https://github.com/intellij-solidity/intellij-solidity/) + +**Remix Desktop -** **_로컬 컴퓨터에서 Remix IDE를 경험해 보세요_** + +- [다운로드](https://github.com/ethereum/remix-desktop/releases) +- [GitHub](https://github.com/ethereum/remix-desktop) + +## 플러그인 및 확장 프로그램 {#plugins-extensions} + +- [solidity](https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity) - Visual Studio Code용 이더리움 솔리디티 언어 +- [Solidity + Hardhat for VS Code](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity) - Hardhat 팀의 솔리디티 및 Hardhat 지원 +- [Prettier Solidity](https://github.com/prettier-solidity/prettier-plugin-solidity) - Prettier를 사용하는 코드 포맷터 + +## 더 읽어보기 {#further-reading} + +- [Ethereum IDEs](https://www.alchemy.com/list-of/web3-ides-on-ethereum) _- Alchemy의 이더리움 IDE 목록_ + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ diff --git a/public/content/translations/ko/developers/docs/index.md b/public/content/translations/ko/developers/docs/index.md new file mode 100644 index 00000000000..ed6eb74d03e --- /dev/null +++ b/public/content/translations/ko/developers/docs/index.md @@ -0,0 +1,25 @@ +--- +title: "이더리움 개발 문서" +description: "ethereum.org 개발자 문서를 소개합니다." +lang: ko +--- + +이 문서는 이더리움 개발에 도움을 주기 위해 작성되었습니다. 이 문서는 이더리움의 개념, 이더리움 기술 스택에 대한 설명 그리고 더욱 복잡한 어플리케이션과 유스케이스를 위한 심화 주제를 다루고 있습니다. + +이 문서는 오픈소스 커뮤니티로 유지됩니다. 따라서 새로운 주제를 제안하거나, 새로운 내용을 추가하거나, 여러분이 생각하기에 도움이 될만한 예시를 추가하는데 주저하지 마시기 바랍니다. 모든 개발문서는 GitHub를 통해 수정할 수 있습니다. 방법을 잘 모르는 경우, [다음 지침을 따르세요](https://github.com/ethereum/ethereum-org-website/blob/dev/docs/editing-markdown.md). + +## 개발 모듈 {#development-modules} + +여러분이 처음으로 이더리움 개발에 처음이라면, 책으로 공부하는 것처럼 여러분만의 방식으로 시작하길 추천합니다. + +### 기본 주제 {#foundational-topics} + + + +### 이더리움 스택 {#ethereum-stack} + + + +### 고급 {#advanced} + + diff --git a/public/content/translations/ko/developers/docs/intro-to-ether/index.md b/public/content/translations/ko/developers/docs/intro-to-ether/index.md new file mode 100644 index 00000000000..5f7808d71b0 --- /dev/null +++ b/public/content/translations/ko/developers/docs/intro-to-ether/index.md @@ -0,0 +1,78 @@ +--- +title: "이더에 대한 기술적 소개" +description: "개발자를 위한 이더 암호화폐에 대한 소개" +lang: ko +--- + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하기 위해 [이더리움 소개](/developers/docs/intro-to-ethereum/)를 먼저 읽어보시는 것을 권장합니다. + +## 암호화폐란 무엇인가요? {#what-is-a-cryptocurrency} + +암호화폐는 블록체인 기반의 원장으로 보호되는 교환 매체입니다. + +교환 매체란 상품 및 서비스에 대한 지불 수단으로 인정되는 모든 것을 통칭하며, 원장은 거래를 추적하는 데이터 저장소를 의미합니다. 블록체인 기술을 통해, 사용자는 제 3자에게 원장을 믿고 맡길 필요 없이 원장에서의 트랜잭션을 수행할 수 있습니다. + +최초의 암호화폐는 사토시 나카모토가 만든 비트코인입니다. 2009년 비트코인이 ​​출시된 이후, 사람들은 다양한 블록체인에서 수천 개의 암호화폐를 만들었습니다. + +## 이더는 무엇인가? {#what-is-ether} + +이더(ETH)는 이더리움 네트워크의 여러 곳에서 사용되는 암호화폐입니다. 기본적으로 거래 수수료에 대해 허용되는 유일한 지불 형식이며, [머지](/roadmap/merge) 이후 메인넷에서 블록을 검증하고 제안하려면 이더가 필요합니다. 이더는 [DeFi](/defi) 대출 시장에서 기본 담보 형태로 사용되고, NFT 마켓플레이스에서 계산 단위로, 서비스 수행 또는 실물 상품 판매에 대한 대가로 사용되는 등 다양한 용도로 활용됩니다. + +이더리움을 통해 개발자는 모두가 컴퓨팅 파워 풀을 공유하는 [**탈중앙화 애플리케이션(탈중앙화앱)**](/developers/docs/dapps)을 만들 수 있습니다. 이 공유 풀은 유한하므로, 누가 그것을 사용할지 결정하는 메커니즘이 필요합니다. 그렇지 않으면 어느 디앱이 실수로 또는 악의적으로 모든 네트워크 리소스를 써버릴 수 있고, 이는 다른 앱들이 리소스를 사용할 수 없도록 방해합니다. + +이더 암호화폐는 이더리움의 컴퓨팅 파워에 대한 가격 책정 메커니즘을 지원합니다. 사용자가 트랜잭션을 발생시키고자 한다면, 이더를 지불해야 블록체인에서 해당 트랜재션이 인식됩니다. 이러한 사용 비용은 [가스비](/developers/docs/gas/)로 알려져 있으며, 가스비는 트랜잭션 실행에 필요한 컴퓨팅 파워의 양과 당시 네트워크 전체의 컴퓨팅 파워 수요에 따라 달라집니다. + +따라서 악의적인 디앱이 무한 루프를 돌며 트랜잭션을 발생시키더라도, 해당 트랜잭션이 이더를 모두 소모한 후엔 결국 종료하게 되고, 이러한 메커니즘은 이더리움 네트워크가 정상으로 돌아갈 수 있도록 합니다. + +이더리움과 이더를 [혼동하는 것이 일반적입니다](https://abcnews.go.com/Business/bitcoin-slumps-week-low-amid-renewed-worries-chinese/story?id=78399845). 사람들이 "이더리움의 가격"을 언급할 때, 그들은 이더의 가격을 말하는 것입니다. + +## 이더 민팅 {#minting-ether} + +발행은 이더리움 원장에 새로운 이더가 생성되는 과정을 말합니다. 이더리움 프로토콜이 새로운 이더를 생성하며, 사용자가 이더를 생성하는 것은 불가능합니다. + +이더는 제안된 각 블록과 합의에 도달하는 것과 관련된 다른 검증자 활동에 대한 모든 에포크 체크포인트에 대한 보상으로 주조된다. 발행된 총 금액은 검증자의 수와 그들이 얼마나 지분을 걸었는지에 따라 달라진다. 이 총 발행량은 모든 검증자가 정직하고 온라인인 이상적인 경우 검증자 간에 균등하게 분배되지만, 실제로는 검증자 성과에 따라 다르다. 전체 발행의 약 8분의 1은 블록 제안자에게 전달되고 나머지는 다른 검증자들에게 분배된다. 블록 제안자들은 거래 수수료와 MEV 관련 소득에서도 팁을 받지만, 이들은 신규 발행이 아닌 재활용 이더에서 나온다. + +## 이더 소각 {#burning-ether} + +블록 보상을 통해 이더를 생성하는 것 외에도 '소각'이라는 과정을 통해 이더를 소멸시킬 수 있습니다. 이더가 소각되면 네트워크에서 영구적으로 제거된다. + +이더 소각은 이더리움의 모든 트랜잭션에서 발생한다. 사용자가 트랜잭션에 대해 비용을 지불하면 기본 가스비가 소각되며, 이 기본 가스비는 네트워크상의 거래 수요에 따라 정해집니다. 여기에 블록 크기와 최대 가스비까지 연관되어, 이더리움상의 거래 수수료를 측정하는 것이 단순해집니다, 네트워크 수요가 높을 때, [블록](https://eth.blockscout.com/block/22580057)은 민팅하는 것보다 더 많은 이더를 소각할 수 있으며, 이는 효과적으로 이더 발행을 상쇄합니다. + +기본 수수료를 소각하면 블록 생성자가 트랜잭션을 조작하는 것을 방해합니다. 예를 들어, 블록 생산자들이 기본료를 받았다면, 그들은 그들 자신의 거래를 무료로 포함시킬 수 있고 다른 모든 사람들을 위한 기본료를 올릴 수 있다. 또는 일부 사용자에게 기본 수수료를 오프체인으로 환불하여 더 불투명하고 복잡한 거래 수수료 시장으로 이어질 수 있습니다. + +## 이더의 단위 {#denominations} + +이더리움의 많은 트랜잭션 가치는 작기 때문에, 이더는 더 작은 계산 단위로 참조될 수 있는 여러 단위를 가지고 있습니다. 그 중에서 Wei와 Gwei가 특히 중요하다. + +웨이는 가능한 가장 작은 이더 단위이며, 그 결과 [이더리움 옐로페이퍼](https://ethereum.github.io/yellowpaper/paper.pdf)와 같은 많은 기술적 구현은 모든 계산을 웨이 기준으로 합니다. + +Gwei는 giga-wei의 줄임말로 이더리움의 가스비를 설명하는 데 자주 사용된다. + +| 단위 | 이더 가치 | 목적 | +| ---- | ---------------- | ---------------- | +| Wei | 10-18 | 기술적 구현 | +| Gwei | 10-9 | 사람이 읽기 쉬운 가스비 단위 | + +## 이더 전송하기 {#transferring-ether} + +이더리움의 각 트랜잭션에는 `value` 필드가 포함되어 있으며, 이 필드는 보내는 사람의 주소에서 받는 사람의 주소로 전송될 이더의 양을 웨이 단위로 지정합니다. + +수신 주소가 [스마트 계약](/developers/docs/smart-contracts/)인 경우, 전송된 이더는 스마트 계약이 코드를 실행할 때 가스비를 지불하는 데 사용될 수 있습니다. + +[트랜잭션에 대해 더 알아보기](/developers/docs/transactions/) + +## 이더 조회하기 {#querying-ether} + +사용자는 계정의 `balance` 필드를 확인하여 모든 [계정](/developers/docs/accounts/)의 이더 잔액을 조회할 수 있으며, 이 필드는 웨이로 표시된 이더 보유량을 보여줍니다. + +[Etherscan](https://etherscan.io)과 [Blockscout](https://eth.blockscout.com)은 웹 기반 애플리케이션을 통해 주소 잔액을 확인할 수 있는 인기 있는 도구입니다. 예를 들어, [이 Blockscout 페이지](https://eth.blockscout.com/address/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe)는 이더리움 재단의 잔액을 보여줍니다. 계정 잔액은 지갑을 사용하거나 노드에 요청하여 직접 조회할 수도 있습니다. + +## 더 읽어보기 {#further-reading} + +- [이더와 이더리움 정의하기](https://www.cmegroup.com/education/courses/introduction-to-ether/defining-ether-and-ethereum.html) – _CME Group_ +- [이더리움 백서](/whitepaper/): 이더리움의 최초 제안서입니다. 이 문서는 이더에 대한 설명과 그 탄생 비화를 포함하고 있습니다. +- [Gwei 계산기](https://www.alchemy.com/gwei-calculator): 이 gwei 계산기를 사용하여 웨이, gwei, 이더를 쉽게 변환할 수 있습니다. wei, gwei 또는 ETH의 임의의 양을 입력만 하면 변환이 자동으로 계산됩니다. + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ diff --git a/public/content/translations/ko/developers/docs/intro-to-ethereum/index.md b/public/content/translations/ko/developers/docs/intro-to-ethereum/index.md new file mode 100644 index 00000000000..c96571e9fdf --- /dev/null +++ b/public/content/translations/ko/developers/docs/intro-to-ethereum/index.md @@ -0,0 +1,124 @@ +--- +title: "이더리움에 대한 기술적 소개" +description: "이더리움의 핵심 개념에 대한 디앱 개발자의 소개" +lang: ko +--- + +## 블록체인이란 무엇인가요? 블록체인이란 무엇인가요? + +블록체인은 네트워크 상의 많은 컴퓨터들에 업데이트되고 공유되는 공공의 데이터베이스입니다. + +"블록"은 "블록들"이라고 하는 연속된 그룹에 저장된 데이터와 상태를 말합니다. ETH를 다른 사람에게 보내는 경우, 트랜잭션 데이터를 블록에 추가해야 성공적으로 보낼 수 있습니다. + +"체인"은 각각의 블록이 암호화된 방식으로 자신의 부모를 참조한다는 것을 말한다. 다시 말해, 블록들은 서로 체인 형태로 연결됩니다. 블록의 데이터를 변경하려면 모든 후속 블록을 변경해야만 하며, 이러한 과정은 네트워크 전체가 합의해야만 이루어집니다. + +네트워크 안의 모든 컴퓨터는 새로 생성되는 블록과 전체 체인에 대해서 반드시 합의해야만 합니다. 이 컴퓨터들을 "노드"라고 합니다. 노드는 블록체인과 상호 작용하는 모든 사람이 동일한 데이터를 갖도록 합니다. 이렇게 분산된 합의를 이루기 위해, 블록체인은 합의 메커니즘이 필요합니다. + +이더리움은 [지분 증명 기반 합의 메커니즘](/developers/docs/consensus-mechanisms/pos/)을 사용합니다. 체인에 새로운 블록을 추가하려는 사람은 이더리움의 기축 통화인 ETH를 담보로 스테이킹하고 검증 소프트웨어를 실행해야 합니다. 이러한 "검증자"는 무작위로 선택되어 다른 검증자가 블록을 확인하고 블록체인에 추가할 블록을 제안할 수 있습니다. 참가자들이 온라인에서 최대한 정직하게 정보를 제공하도록 강력하게 장려하는 보상 및 패널티 시스템이 있습니다. + +블록체인 데이터가 어떻게 해시되고 이후 블록 참조 기록에 추가되는지 알고 싶다면 Anders Brownworth의 [이 데모](https://andersbrownworth.com/blockchain/blockchain)를 확인하고 아래에 첨부된 비디오를 시청하세요. + +블록체인의 해시에 대한 Anders의 설명 영상을 확인해보세요. + + + +## 이더리움이란? 이더리움이란 무엇인가요? + +이더리움은 컴퓨터가 내장된 블록체인입니다. 그것은 분산되고 허가 없이 검열에 저항하는 방식으로 앱과 조직을 구축하기 위한 기반입니다. + +이더리움 세상에는 이더리움 네트워크 상의 모두가 동의하는 상태를 가지는 (이더리움 가상 머신, 또는 EVM이라고 부르는) 하나의 정식 컴퓨터가 있습니다. 이더리움 네트워크에 참여하는 모두(모든 이더리움 노드)는 이 컴퓨터 상태의 복사본을 보관합니다. 또한, 모든 참여자는 이 컴퓨터에 대한 요청을 브로드캐스트하여 임의의 계산을 수행할 수 있습니다. 이러한 요청이 브로드캐스트 될 때마다, 네트워크상의 다른 참가자들은 이 연산을 확인, 검증 및 "실행"합니다. 이 실행은 네트워크 전체에 전파되고, EVM의 상태 변화를 일으킵니다. + +이렇게 연산을 위한 요청들을 트랜잭션 요청이라고 합니다. 모든 트랜잭션에 대한 기록과 EVM의 현재 상태가 블록체인에 저장되고, 결과적으로 이러한 내용은 모든 노드들에 의해 저장되고 합의됩니다. + +트랜잭션이 한번 검증되고 블록체인에 추가되면, 암호학적으로 더 이상 변경될 수 없음이 보장됩니다. 같은 방식으로, 적절한 "권한"이 있어야만 트랜잭션을 서명하고 실행할 수 있음이 보장됩니다. (Alice가 아닌 어떤 누구도 Alice의 계정에 있는 디지털 자산을 전송할 수 있어서는 안 됩니다.) + +## 이더는 무엇인가? {#what-is-ether} + +이더(ETH)는 이더리움의 네이티브 암호화폐입니다. ETH의 목적은 계산을 위한 시장을 허용하는 것이다. 시장에서는 참가자들이 네트워크에 컴퓨터 자원을 제공하고 트랜잭션을 검증/실행한 데에 대한 경제적 보상을 제공합니다. + +트랜잭션 요청을 브로드캐스트하는 참가자는 네트워크에 현상금으로서 이더를 제공해야합니다. 네트워크는 보상의 일부를 소각하고 트랜잭션을 검증, 실행, 블록체인에 커밋, 네트워크에 브로드캐스팅하는 작업을 최종적으로 수행하는 사람에게 나머지를 수여합니다. + +연산에 들어간 시간에 따라 지불하는 이더의 양이 정해집니다. 이는 또한 악의적인 참가자들이 무한 루프나 리소스가 많이 소모되는 스크립트의 실행을 요청함으로써 고의로 네트워크를 막히도록 하는 것을 이들 행위자에게 계속 지불되게 함으로써 예방한다. + +ETH는 또한 세 가지 주요 방식으로 네트워크에 암호경제학적 보안을 제공하는 데 사용됩니다. 1) 블록을 제안하거나 다른 검증자의 부정 행위를 지적하는 검증자에게 보상하는 수단으로 사용됩니다. 2) 부정 행위에 대한 담보 역할을 하도록 검증자에 의해 스테이킹됩니다. 만약 검증자가 부정하게 행동하려고 시도하면 해당 ETH는 소각될 수 있습니다. 3) 합의 메커니즘의 포크 선택 부분에 반영되어, 새로 제안된 블록에 대한 '투표'에 가중치를 부여하는 데 사용됩니다. + +## 스마트 계약이란 무엇입니까? 스마트 계약이란 무엇인가요? + +EVM상의 연산을 요청하기 위해서 참가자들이 새로운 코드를 실제로 쓰지는 않습니다. 어플리케이션 개발자들이 EVM 상태에 프로그램(재사용 가능한 코드조각)을 올려두고, 사용자들이 이 프로그램에 다양한 값을 입력해서 사용합니다. 네트워크에 업로드되어 실행되는 프로그램을 "스마트 계약"이라고 부릅니다. + +쉽게 말해서, 스마트 컨트랙트는 자판기로 볼 수 있습니다. 특정 값이 들어오면, 정해진 행동을 하거나 어떤 조건이 충족됐을 때 연산을 합니다. 예를 들어, 간단한 벤더 스마트 컨트랙트는 호출자가 특정 수신자에게 이더를 보내면 어떤 디지털 자산의 소유권을 생성하고 할당할 수 있습니다. + +아무 개발자나 스마트 컨트랙트를 만들어 네트워크에 공개할 수 있고, 사용료를 네트워크에 지불하고 블록체인을 자체 데이터 계층으로서 활용할 수 있습니다. 또, 아무 사용자나 네트워크에 사용료를 지불하면, 이 스마트 컨트랙트를 실행할 수 있습니다. + +즉, 개발자들은 마켓플레이스나 금융 서비스, 게임과 같은 복잡한 앱이나 서비스를 스마트 컨트랙트를 사용해서 개발하고 배포할 수 있습니다. + +## 용어 {#terminology} + +### 블록체인 {#blockchain} + +이더리움 네트워크가 시작된 이례로 이더리움 네트워크에 제출된 모든 블록들의 순서들. 각 블록들이 그 이전 블록을 참조를 포함하고 있어서 이렇게 이름 붙었습니다. 이러한 이전 블록에 대한 참조는 모든 블록의 순서를 (정확한 내역을) 관리할 수 있도록 합니다. + +### ETH {#eth} + +이더(ETH)는 이더리움의 네이티브 암호화폐입니다. 사용자는 다른 사용자들에게 그들의 코드를 실행해달라고 요청하기 위해서 이더를 지불합니다. + +[ETH에 대해 더 알아보기](/developers/docs/intro-to-ether/) + +### EVM {#evm} + +이더리움 가상 머신은 이더리움 네트워크의 모든 사용자가 상태를 저장하고 합의하는 가상의 글로벌 컴퓨터입니다. 어떤 참가자나 EVM 상의 임의의 코드를 실행 요청할 수 있습니다. 코드 실행은 EVM의 상태를 바꿉니다. + +[EVM에 대해 더 알아보기](/developers/docs/evm/) + +### 노드 {#nodes} + +EVM 상태를 저장하는 실제 머신. 노드들은 각자와 EVM 상태와 새로운 상태 변화에 대한 정보를 퍼뜨리기 위해서 통신합니다. 어느 사용자나 코드 노드로부터 실행 요청을 브로드캐스트해서 코드 실행을 요청할 수 있습니다. 이더리움 네트워크 그 자체는 모든 이더리움 노드들과 그들의 통신의 집합체를 말합니다. + +[노드에 대해 더 알아보기](/developers/docs/nodes-and-clients/) + +### 계정 {#accounts} + +이더가 저장되는 곳. 사용자는 계정을 초기화하고, 계정 안에 이더를 입금하고, 자신의 계정에서 다른 사용자에게 이더를 송금할 수 있습니다. 계정과 계정 잔고는 EVM 내의 큰 테이블에 저장됩니다. 계정과 계정 잔고는 전체 EVM 상태 중 일부입니다. + +[계정에 대해 더 알아보기](/developers/docs/accounts/) + +### 트랜잭션 {#transactions} + +"트랜잭션 요청"이란 EVM상의 코드 실행 요청을 가리키는 용어입니다. "트랜잭션"이란 수행된 트랜잭션 요청과, 그에 관련된 EVM 상태 변화를 의미합니다. 어떤 사용자든 노드로부터 네트워크로 트랜잭션 요청을 브로드캐스트 할 수 있습니다. 합의되어 있는 EVM 상태에 트랜잭션 요청이 실제 영향을 미치기 위해서, 그는 반드시 유효성이 검사되고, 실행되며 다른 노드들에 의해 “네트워크에 제출되어야” 한다. 어떤 코드의 실행은 EVM 내의 상태 변화를 일으킨다; 제출 시 이 상태 변화는 네트워크 내의 모든 노드로 브로드캐스트 된다. 트랜잭션의 예제: + +- 내 계정에서 앨리스의 계정으로 X 이더를 보냄 +- EVM 메모리내로 어떤 스마트 컨트랙트 코드를 발행 +- EVM 내의 주소 X에서 스마트 컨트랙트 코드를 Y 인자로 실행. + +[트랜잭션에 대해 더 알아보기](/developers/docs/transactions/) + +### 블록 {#blocks} + +트랜잭션의 양은 매우 많아서 트랜잭션들은 한번에 모아서 또는 블록으로 “제출된다”. 블록들은 일반적으로 수백개의 트랜잭션을 담는다. + +[블록에 대해 더 알아보기](/developers/docs/blocks/) + +### 스마트 계약 {#smart-contracts} + +개발자들이 EVM 메모리로 발행하는 재사용 가능한 코드 조각(프로그램). 누구나 트랜잭션 요청을 해서 실행될 스마트 컨트랙트 코드 실행을 요청할 수 있다. 개발자는 EVM에 임의로 실행 가능한 애플리케이션(게임, 마켓플레이스, 금융 상품 등)을 작성할 수 있기 때문에 스마트 계약을 게시함으로써, 이것들은 종종 [디앱(dapp) 또는 탈중앙화 앱](/developers/docs/dapps/)이라고도 불립니다. + +[스마트 계약에 대해 더 알아보기](/developers/docs/smart-contracts/) + +## 더 읽어보기 {#further-reading} + +- [이더리움 백서](/whitepaper/) +- [이더리움은 어떻게 작동하는가?](https://medium.com/@preethikasireddy/how-does-ethereum-work-anyway-22d1df506369) - _Preethi Kasireddy_ (**참고** 이 자료는 여전히 유용하지만 [병합](/roadmap/merge) 이전에 작성되어 이더리움의 작업 증명 메커니즘을 여전히 참조하고 있다는 점을 인지하시기 바랍니다. 이더리움은 현재 [지분 증명](/developers/docs/consensus-mechanisms/pos)을 사용하여 보안이 유지됩니다.) + +### 시각 자료를 찾고 있나요? 시각적 학습자 + +이 비디오 시리즈는 기초 주제에 대한 심층적인 탐구를 제공합니다. + + + +[이더리움 기초 플레이리스트](https://youtube.com/playlist?list=PLqgutSGloqiJyyoL0zvLVFPS-GMD2wKa5&si=kZTf5I7PKGTXDsOZ) + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 관련 튜토리얼 {#related-tutorials} + +- [이더리움 개발자 가이드, 1부](/developers/tutorials/a-developers-guide-to-ethereum-part-one/) _– Python과 web3.py를 사용해 이더리움을 탐구하는 아주 초보자 친화적인 자료_ diff --git a/public/content/translations/ko/developers/docs/mev/index.md b/public/content/translations/ko/developers/docs/mev/index.md new file mode 100644 index 00000000000..4361f3a1c2f --- /dev/null +++ b/public/content/translations/ko/developers/docs/mev/index.md @@ -0,0 +1,221 @@ +--- +title: "최대 추출 가능 값(MEV)" +description: "최대 추출 가능 값(MEV)에 대한 소개" +lang: ko +--- + +최대 추출 가능 가치(MEV)는 블록 내 트랜잭션의 포함, 제외 및 순서 변경을 통해 표준 블록 보상 및 가스 수수료를 초과하여 블록 생성에서 추출할 수 있는 최대 가치를 의미합니다. + +## 최대 추출 가능 가치 {#maximal-extractable-value} + +최대 추출 가능 가치는 [작업 증명](/developers/docs/consensus-mechanisms/pow/)의 맥락에서 처음 적용되었으며, 처음에는 "채굴자 추출 가능 가치"라고 불렸습니다. 작업 증명에서는 채굴자가 트랜잭션 포함, 제외, 순서를 제어하기 때문입니다. 하지만 [병합](/roadmap/merge)을 통한 지분 증명으로의 전환 이후, 검증자가 이러한 역할을 담당하게 되었으며 채굴은 더 이상 이더리움 프로토콜의 일부가 아닙니다. 그러나 가치 추출 방법은 여전히 존재하므로, 이제는 "최대 추출 가능 가치"라는 용어가 대신 사용됩니다. + +## 필수 구성 요소 {#prerequisites} + +[트랜잭션](/developers/docs/transactions/), [블록](/developers/docs/blocks/), [지분 증명](/developers/docs/consensus-mechanisms/pos), [가스](/developers/docs/gas/)에 대해 숙지하시기 바랍니다. [디앱스](/apps/)와 [디파이](/defi/)에 익숙하다면 도움이 될 것입니다. + +## MEV 추출 {#mev-extraction} + +이론적으로 수익성 있는 MEV 기회의 실행을 보장할 수 있는 유일한 주체는 검증자이므로 MEV는 전적으로 검증자에게 귀속됩니다. 하지만 실제로는 MEV의 상당 부분이 "검색자"라고 불리는 독립적인 네트워크 참여자에 의해 추출됩니다. 검색자는 블록체인 데이터에 복잡한 알고리즘을 실행하여 수익성 있는 MEV 기회를 감지하고, 해당 수익성 트랜잭션을 네트워크에 자동으로 제출하는 봇을 보유하고 있습니다. + +검색자는 수익성 있는 트랜잭션이 블록에 포함될 가능성을 높이는 대가로 높은 가스 수수료(검증자에게 지급됨)를 기꺼이 지불하기 때문에, 검증자는 어쨌든 전체 MEV 금액의 일부를 받게 됩니다. 검색자가 경제적으로 합리적이라고 가정하면, 검색자가 기꺼이 지불하려는 가스 수수료는 검색자 MEV의 최대 100%에 달하는 금액이 될 것입니다(가스 수수료가 더 높으면 검색자는 손해를 보기 때문입니다). + +따라서 [DEX 차익거래](#mev-examples-dex-arbitrage)와 같이 경쟁이 치열한 일부 MEV 기회의 경우, 많은 사람이 동일한 수익성 있는 차익거래를 실행하기를 원하기 때문에 검색자는 총 MEV 수익의 90% 이상을 검증자에게 가스 수수료로 지불해야 할 수도 있습니다. 자신의 차익거래 트랜잭션 실행을 보장할 수 있는 유일한 방법은 가장 높은 가스 가격으로 트랜잭션을 제출하는 것이기 때문입니다. + +### 가스 골핑 {#mev-extraction-gas-golfing} + +이러한 역학 관계는 "가스 골핑", 즉 트랜잭션을 프로그래밍하여 최소한의 가스를 사용하도록 하는 능력을 경쟁 우위로 만들었습니다. 이를 통해 검색자는 총 가스 수수료를 일정하게 유지하면서 더 높은 가스 가격을 설정할 수 있기 때문입니다(가스 수수료 = 가스 가격 \* 사용된 가스). + +잘 알려진 가스 골프 기술 몇 가지는 다음과 같습니다. 0으로 시작하는 긴 문자열의 주소([0x0000000000C521824EaFf97Eac7B73B084ef9306](https://eth.blockscout.com/address/0x0000000000C521824EaFf97Eac7B73B084ef9306) 등)를 사용하면 저장 공간(따라서 가스)이 덜 들기 때문에 이를 사용하고, 저장 공간 슬롯을 업데이트하는 것보다 초기화(잔액이 0인 경우)하는 데 더 많은 가스가 들기 때문에 계약에 소량의 [ERC-20](/developers/docs/standards/tokens/erc-20/) 토큰 잔액을 남겨두는 것 등이 있습니다. 가스 사용량을 줄이기 위한 더 많은 기술을 찾는 것은 검색자들 사이에서 활발한 연구 분야입니다. + +### 일반화된 프론트러너 {#mev-extraction-generalized-frontrunners} + +일부 검색자는 수익성 있는 MEV 기회를 감지하기 위해 복잡한 알고리즘을 프로그래밍하는 대신 일반화된 프론트러너를 실행합니다. 일반화된 프론트러너는 멤풀을 감시하여 수익성 있는 트랜잭션을 감지하는 봇입니다. 프론트러너는 잠재적으로 수익성이 있는 트랜잭션의 코드를 복사하고, 주소를 프론트러너의 주소로 교체한 다음, 트랜잭션을 로컬에서 실행하여 수정된 트랜잭션이 프론트러너의 주소에 이익을 가져다주는지 다시 한번 확인합니다. 트랜잭션이 실제로 수익성이 있는 경우, 프론트러너는 교체된 주소와 더 높은 가스 가격으로 수정된 트랜잭션을 제출하여 원래 트랜잭션을 "선행매매"하고 원래 검색자의 MEV를 획득합니다. + +### Flashbots {#mev-extraction-flashbots} + +Flashbots는 실행 클라이언트를 확장하여 검색자가 공개 멤풀에 노출하지 않고도 검증자에게 MEV 트랜잭션을 제출할 수 있는 서비스를 제공하는 독립 프로젝트입니다. 이를 통해 일반화된 프론트러너에 의한 트랜잭션 선행매매를 방지할 수 있습니다. + +## MEV 예시 {#mev-examples} + +MEV는 몇 가지 방식으로 블록체인에서 나타납니다. + +### DEX 차익거래 {#mev-examples-dex-arbitrage} + +[탈중앙화 거래소](/glossary/#dex)(DEX) 차익거래는 가장 간단하고 가장 잘 알려진 MEV 기회입니다. 결과적으로, 가장 경쟁이 치열하기도 합니다. + +작동 방식은 다음과 같습니다. 두 개의 DEX가 토큰을 서로 다른 가격으로 제공하는 경우, 누군가는 가격이 낮은 DEX에서 토큰을 구매하고 가격이 높은 DEX에서 단일 원자적 트랜잭션으로 판매할 수 있습니다. 블록체인의 메커니즘 덕분에 이것은 진정한 무위험 차익거래입니다. + +Uniswap과 Sushiswap에서 ETH/DAI 페어의 다른 가격 책정을 활용하여 검색자가 1,000 ETH를 1,045 ETH로 바꾼 수익성 있는 차익거래 트랜잭션의 [예시](https://eth.blockscout.com/tx/0x5e1657ef0e9be9bc72efefe59a2528d0d730d478cfc9e6cdd09af9f997bb3ef4)입니다. + +### 청산 {#mev-examples-liquidations} + +대출 프로토콜 청산은 또 다른 잘 알려진 MEV 기회를 제공합니다. + +Maker나 Aave와 같은 대출 프로토콜은 사용자가 담보(예: ETH)를 예치하도록 요구합니다. 이 예치된 담보는 다른 사용자에게 대출해 주는 데 사용됩니다. + +그런 다음 사용자는 예치된 담보의 특정 비율까지 필요한 것에 따라 다른 사람으로부터 자산과 토큰을 빌릴 수 있습니다(예: MakerDAO 거버넌스 제안에 투표하려면 MKR을 빌릴 수 있습니다). 예를 들어, 대출 금액이 최대 30%인 경우, 프로토콜에 100 DAI를 예치한 사용자는 다른 자산으로 최대 30 DAI 상당을 빌릴 수 있습니다. 프로토콜이 정확한 대출 능력 비율을 결정합니다. + +차용인의 담보 가치가 변동함에 따라 대출 능력도 변동합니다. 만약 시장 변동으로 인해 빌린 자산의 가치가 담보 가치의 30%(다시 말하지만, 정확한 비율은 프로토콜에 의해 결정됨)를 초과하면, 프로토콜은 일반적으로 누구나 담보를 청산하여 즉시 대출자에게 상환할 수 있도록 허용합니다(이는 전통적인 금융에서 [마진 콜](https://www.investopedia.com/terms/m/margincall.asp)이 작동하는 방식과 유사합니다). 청산될 경우, 차용인은 보통 막대한 청산 수수료를 지불해야 하며, 그 중 일부는 청산인에게 돌아갑니다. 바로 여기서 MEV 기회가 발생합니다. + +검색자들은 블록체인 데이터를 최대한 빨리 분석하여 어떤 차용인이 청산될 수 있는지 파악하고, 가장 먼저 청산 트랜잭션을 제출하여 청산 수수료를 챙기기 위해 경쟁합니다. + +### 샌드위치 거래 {#mev-examples-sandwich-trading} + +샌드위치 거래는 MEV 추출의 또 다른 일반적인 방법입니다. + +샌드위치 거래를 하기 위해, 검색자는 멤풀에서 대규모 DEX 거래를 주시합니다. 예를 들어, 누군가 Uniswap에서 DAI로 10,000 UNI를 구매하고 싶다고 가정해 봅시다. 이 정도 규모의 거래는 UNI/DAI 페어에 상당한 영향을 미쳐 DAI 대비 UNI의 가격을 크게 상승시킬 수 있습니다. + +검색자는 이 대규모 거래가 UNI/DAI 페어에 미치는 대략적인 가격 효과를 계산하고 대규모 거래 직전에 최적의 매수 주문을 실행하여 UNI를 저렴하게 구매한 다음, 대규모 거래 직후에 매도 주문을 실행하여 대규모 주문으로 인해 높아진 가격에 판매할 수 있습니다. + +그러나 샌드위치 거래는 (위에서 설명한 DEX 차익거래와 달리) 원자적이지 않고 [살모넬라 공격](https://github.com/Defi-Cartel/salmonella)에 취약하기 때문에 더 위험합니다. + +### NFT MEV {#mev-examples-nfts} + +NFT 분야의 MEV는 새로운 현상이며, 반드시 수익성이 있는 것은 아닙니다. + +하지만 NFT 트랜잭션은 다른 모든 이더리움 트랜잭션과 공유되는 동일한 블록체인에서 발생하므로, 검색자는 기존 MEV 기회에서 사용된 것과 유사한 기술을 NFT 시장에서도 사용할 수 있습니다. + +예를 들어, 인기 있는 NFT 드롭이 있고 검색자가 특정 NFT 또는 NFT 세트를 원하는 경우, NFT를 가장 먼저 구매하도록 트랜잭션을 프로그래밍하거나 단일 트랜잭션으로 전체 NFT 세트를 구매할 수 있습니다. 또는 NFT가 [실수로 낮은 가격에 등록](https://www.theblockcrypto.com/post/113546/mistake-sees-69000-cryptopunk-sold-for-less-than-a-cent)된 경우, 검색자는 다른 구매자를 선행매매하여 저렴하게 구매할 수 있습니다. + +NFT MEV의 한 가지 두드러진 예는 한 검색자가 700만 달러를 들여 모든 크립토펑크(Cryptopunk)를 최저가에 [구매](https://eth.blockscout.com/address/0x650dCdEB6ecF05aE3CAF30A70966E2F395d5E9E5?tab=txs)했을 때 발생했습니다. 한 블록체인 연구원은 [트위터에서](https://twitter.com/IvanBogatyy/status/1422232184493121538) 구매자가 MEV 제공업체와 협력하여 구매를 비밀로 유지한 방법을 설명했습니다. + +### 롱테일 {#mev-examples-long-tail} + +DEX 차익거래, 청산, 샌드위치 거래는 모두 매우 잘 알려진 MEV 기회이며 새로운 검색자에게는 수익성이 없을 가능성이 높습니다. 그러나 덜 알려진 MEV 기회의 롱테일이 있습니다(NFT MEV가 바로 그러한 기회 중 하나라고 할 수 있습니다). + +이제 막 시작하는 검색자들은 이 롱테일에서 MEV를 검색함으로써 더 많은 성공을 거둘 수 있습니다. Flashbot의 [MEV 채용 게시판](https://github.com/flashbots/mev-job-board)에는 몇 가지 새로운 기회가 나열되어 있습니다. + +## MEV의 효과 {#effects-of-mev} + +MEV가 모두 나쁜 것은 아닙니다. 이더리움의 MEV에는 긍정적인 결과와 부정적인 결과가 모두 있습니다. + +### 장점 {#effects-of-mev-the-good} + +많은 디파이 프로젝트는 프로토콜의 유용성과 안정성을 보장하기 위해 경제적으로 합리적인 행위자에게 의존합니다. 예를 들어, DEX 차익거래는 사용자가 자신의 토큰에 대해 가장 정확하고 최고의 가격을 받을 수 있도록 보장하고, 대출 프로토콜은 차용인이 담보 비율 아래로 떨어졌을 때 신속한 청산에 의존하여 대출자가 상환받을 수 있도록 보장합니다. + +경제적 비효율성을 찾아 수정하고 프로토콜의 경제적 인센티브를 활용하는 합리적인 검색자가 없다면, 디파이 프로토콜과 디앱스 전반이 오늘날처럼 견고하지 못할 수 있습니다. + +### 단점 {#effects-of-mev-the-bad} + +애플리케이션 레이어에서 샌드위치 거래와 같은 일부 MEV 형태는 사용자에게 명백히 더 나쁜 경험을 초래합니다. 샌드위치 공격을 당한 사용자는 거래에서 슬리피지 증가와 실행 악화에 직면하게 됩니다. + +네트워크 레이어에서 일반화된 프론트러너와 이들이 종종 참여하는 가스 가격 경매(둘 이상의 프론트러너가 다음 블록에 자신의 트랜잭션을 포함시키기 위해 점진적으로 자신의 트랜잭션 가스 가격을 올리며 경쟁하는 경우)는 네트워크 혼잡과 일반 트랜잭션을 실행하려는 다른 모든 사람들에게 높은 가스 가격을 초래합니다. + +블록 내부에서 일어나는 일 외에도, MEV는 블록 에 해로운 영향을 미칠 수 있습니다. 블록에서 사용 가능한 MEV가 표준 블록 보상을 크게 초과하면, 검증자는 블록을 재구성하여 MEV를 자신을 위해 캡처하도록 장려될 수 있으며, 이는 블록체인 재구성과 합의 불안정성을 유발합니다. + +이러한 블록체인 재구성 가능성은 [이전에 비트코인 블록체인에서 탐구된 바 있습니다](https://dl.acm.org/doi/10.1145/2976749.2978408). 비트코인의 블록 보상이 반감되고 거래 수수료가 블록 보상에서 차지하는 비중이 점점 더 커짐에 따라, 채굴자들이 다음 블록의 보상을 포기하고 대신 더 높은 수수료를 가진 과거 블록을 재채굴하는 것이 경제적으로 합리적인 상황이 발생합니다. MEV의 성장으로 이더리움에서도 동일한 종류의 상황이 발생하여 블록체인의 무결성을 위협할 수 있습니다. + +## MEV 현황 {#state-of-mev} + +MEV 추출은 2021년 초에 급증하여 연초 몇 달 동안 극도로 높은 가스 가격을 초래했습니다. Flashbots의 MEV 릴레이의 출현은 일반화된 프론트러너의 효율성을 감소시켰고 가스 가격 경매를 오프 체임으로 가져와 일반 사용자의 가스 가격을 낮췄습니다. + +많은 검색자가 여전히 MEV로 좋은 수익을 내고 있지만, 기회가 더 잘 알려지고 점점 더 많은 검색자가 동일한 기회를 놓고 경쟁함에 따라 검증자는 점점 더 많은 총 MEV 수익을 차지하게 될 것입니다(원래 설명된 것과 동일한 종류의 가스 경매가 Flashbots에서도 비공개로 발생하며, 검증자가 그에 따른 가스 수익을 차지하기 때문입니다). MEV는 이더리움에만 국한된 것이 아니며, 이더리움에서 기회 경쟁이 치열해짐에 따라 검색자들은 바이낸스 스마트 체인과 같은 대체 블록체인으로 이동하고 있습니다. 그곳에는 이더리움과 유사한 MEV 기회가 경쟁이 덜한 상태로 존재합니다. + +반면에 작업 증명에서 지분 증명으로의 전환과 롤업을 사용하여 이더리움을 확장하려는 지속적인 노력은 모두 아직 다소 불분명한 방식으로 MEV 환경을 변화시킵니다. 보장된 블록 제안자를 약간 미리 아는 것이 작업 증명의 확률적 모델에 비해 MEV 추출의 역학을 어떻게 변화시키는지, 또는 [단일 비밀 리더 선출](https://ethresear.ch/t/secret-non-single-leader-election/11789) 및 [분산 검증자 기술](/staking/dvt/)이 구현될 때 이것이 어떻게 중단될지는 아직 잘 알려져 있지 않습니다. 마찬가지로, 대부분의 사용자 활동이 이더리움에서 레이어 2 롤업 및 샤드로 이전될 때 어떤 MEV 기회가 존재하는지는 아직 지켜봐야 합니다. + +## 이더리움 지분 증명(PoS)에서의 MEV {#mev-in-ethereum-proof-of-stake} + +설명한 바와 같이, MEV는 전반적인 사용자 경험과 합의 레이어 보안에 부정적인 영향을 미칩니다. 그러나 이더리움의 지분 증명 합의로의 전환("병합"이라고 불림)은 잠재적으로 새로운 MEV 관련 위험을 초래합니다. + +### 검증자 중앙화 {#validator-centralization} + +병합 후 이더리움에서는 검증자(32 ETH의 보안 예치금을 예치한)가 비콘 체인에 추가된 블록의 유효성에 대해 합의에 도달합니다. 32 ETH는 많은 사람에게 부담스러운 금액일 수 있으므로 [스테이킹 풀에 참여](/staking/pools/)하는 것이 더 실현 가능한 옵션일 수 있습니다. 그럼에도 불구하고, [단독 스테이커](/staking/solo/)의 건전한 분포는 검증자의 중앙화를 완화하고 이더리움의 보안을 향상시키므로 이상적입니다. + +그러나 MEV 추출은 검증자 중앙화를 가속화할 수 있는 것으로 여겨집니다. 이는 부분적으로 검증자가 이전에 채굴자가 했던 것보다 [블록 제안에 대해 더 적은 수입을 얻게 되면서](/roadmap/merge/issuance/#how-the-merge-impacts-ETH-supply), [병합](/roadmap/merge/) 이후 MEV 추출이 [검증자 수입에 큰 영향](https://github.com/flashbots/eth2-research/blob/main/notebooks/mev-in-eth2/eth2-mev-calc.ipynb)을 미쳤기 때문입니다. + +더 큰 스테이킹 풀은 MEV 기회를 포착하기 위해 필요한 최적화에 투자할 더 많은 자원을 가질 가능성이 높습니다. 이러한 풀이 더 많은 MEV를 추출할수록 MEV 추출 능력을 향상시키고 전체 수익을 늘릴 수 있는 더 많은 자원을 갖게 되어 본질적으로 [규모의 경제](https://www.investopedia.com/terms/e/economiesofscale.asp#)를 창출합니다. + +가용 자원이 적은 단독 스테이커는 MEV 기회로부터 이익을 얻지 못할 수 있습니다. 이로 인해 독립 검증자들이 수입을 늘리기 위해 강력한 스테이킹 풀에 가입하라는 압력이 증가하여 이더리움의 탈중앙화를 감소시킬 수 있습니다. + +### 허가형 멤풀 {#permissioned-mempools} + +샌드위치 및 선행매매 공격에 대응하여 거래자들은 트랜잭션 개인 정보 보호를 위해 검증자와 오프 체임 거래를 시작할 수 있습니다. 잠재적인 MEV 트랜잭션을 공개 멤풀로 보내는 대신, 거래자는 이를 검증자에게 직접 보내고, 검증자는 이를 블록에 포함시키고 거래자와 이익을 나눕니다. + +"다크 풀"은 이러한 협의의 더 큰 버전이며 특정 수수료를 지불할 의사가 있는 사용자에게 개방된 허가형, 접근 전용 멤풀로 기능합니다. 이러한 추세는 이더리움의 무허가성과 무신뢰성을 감소시키고 잠재적으로 블록체인을 가장 높은 입찰자를 선호하는 "pay-to-play" 메커니즘으로 변형시킬 수 있습니다. + +허가형 멤풀은 또한 이전 섹션에서 설명한 중앙화 위험을 가속화할 것입니다. 여러 검증자를 운영하는 대규모 풀은 거래자와 사용자에게 트랜잭션 개인 정보 보호를 제공하여 MEV 수익을 늘리는 이점을 얻을 가능성이 높습니다. + +병합 후 이더리움에서 이러한 MEV 관련 문제를 해결하는 것은 핵심 연구 분야입니다. 현재까지, 병합 이후 이더리움의 탈중앙화 및 보안에 대한 MEV의 부정적인 영향을 줄이기 위해 제안된 두 가지 해결책은 [**제안자-빌더 분리(PBS)**](/roadmap/pbs/)와 [**빌더 API**](https://github.com/ethereum/builder-specs)입니다. + +### 제안자-빌더 분리 {#proposer-builder-separation} + +작업 증명과 지분 증명 모두에서, 블록을 생성하는 노드는 합의에 참여하는 다른 노드에게 체인에 추가할 것을 제안합니다. 새로운 블록은 다른 채굴자가 그 위에 빌드하거나(PoW에서) 또는 과반수의 검증자로부터 인증을 받은 후(지분 증명에서) 정식 체인의 일부가 됩니다. + +블록 생산자와 블록 제안자 역할의 조합이 이전에 설명한 대부분의 MEV 관련 문제를 야기합니다. 예를 들어, 합의 노드는 MEV 수익을 극대화하기 위해 [타임 밴딧 공격](https://www.mev.wiki/attack-examples/time-bandit-attack)에서 체인 재구성을 유발하도록 장려됩니다. + +[제안자-빌더 분리](https://ethresear.ch/t/proposer-block-builder-separation-friendly-fee-market-designs/9725)(PBS)는 특히 합의 레이어에서 MEV의 영향을 완화하도록 설계되었습니다. PBS의 주요 특징은 블록 생산자와 블록 제안자 역할의 분리입니다. 검증자는 여전히 블록을 제안하고 투표할 책임이 있지만, 블록 빌더라고 불리는 새로운 종류의 전문화된 주체가 트랜잭션을 정렬하고 블록을 생성하는 임무를 맡습니다. + +PBS 하에서, 블록 빌더는 트랜잭션 번들을 생성하고 비콘 체인 블록에 포함시키기 위한 입찰을 합니다("실행 페이로드"로서). 다음 블록을 제안하도록 선택된 검증자는 여러 입찰을 확인하고 가장 높은 수수료를 가진 번들을 선택합니다. PBS는 본질적으로 빌더가 블록 공간을 판매하는 검증자와 협상하는 경매 시장을 만듭니다. + +현재 PBS 설계는 빌더가 입찰과 함께 블록 내용물(블록 헤더)에 대한 암호화된 커밋먼트만 게시하는 [커밋-리빌 체계](https://gitcoin.co/blog/commit-reveal-scheme-on-ethereum/)를 사용합니다. 낙찰된 입찰을 수락한 후, 제안자는 블록 헤더를 포함하는 서명된 블록 제안을 생성합니다. 블록 빌더는 서명된 블록 제안을 본 후 전체 블록 본문을 게시해야 하며, 최종 확정되기 전에 검증자로부터 충분한 [인증](/glossary/#attestation)을 받아야 합니다. + +#### 제안자-빌더 분리는 MEV의 영향을 어떻게 완화합니까? {#how-does-pbs-curb-mev-impact} + +프로토콜 내 제안자-빌더 분리는 검증자의 권한에서 MEV 추출을 제거함으로써 합의에 대한 MEV의 영향을 줄입니다. 대신, 전문 하드웨어를 실행하는 블록 빌더가 앞으로 MEV 기회를 포착할 것입니다. + +그러나 빌더가 검증자에게 블록을 수락받기 위해 높은 가격으로 입찰해야 하므로, 이것이 검증자를 MEV 관련 수입에서 완전히 배제하는 것은 아닙니다. 그럼에도 불구하고, 검증자가 더 이상 MEV 수입 최적화에 직접적으로 집중하지 않게 됨에 따라 타임 밴딧 공격의 위협이 줄어듭니다. + +제안자-빌더 분리는 또한 MEV의 중앙화 위험을 줄입니다. 예를 들어, 커밋-리빌 체계를 사용하면 빌더가 검증자가 MEV 기회를 훔치거나 다른 빌더에게 노출하지 않을 것이라고 신뢰할 필요가 없어집니다. 이는 단독 스테이커가 MEV로부터 이익을 얻기 위한 장벽을 낮춥니다. 그렇지 않으면 빌더는 오프 체임 평판을 가진 대규모 풀을 선호하고 그들과 오프 체임 거래를 하는 경향이 있을 것입니다. + +마찬가지로, 지불이 무조건적이기 때문에 검증자는 빌더가 블록 본문을 보류하거나 유효하지 않은 블록을 게시하지 않을 것이라고 신뢰할 필요가 없습니다. 제안된 블록을 사용할 수 없거나 다른 검증자에 의해 유효하지 않다고 선언되더라도 검증자의 수수료는 여전히 처리됩니다. 후자의 경우, 블록은 단순히 폐기되어 블록 빌더가 모든 거래 수수료와 MEV 수익을 잃게 됩니다. + +### 빌더 API {#builder-api} + +제안자-빌더 분리는 MEV 추출의 영향을 줄일 것을 약속하지만, 이를 구현하려면 합의 프로토콜을 변경해야 합니다. 구체적으로, 비콘 체인의 [포크 선택](/developers/docs/consensus-mechanisms/pos/#fork-choice) 규칙을 업데이트해야 합니다. [빌더 API](https://github.com/ethereum/builder-specs)는 더 높은 신뢰 가정을 수반하지만, 제안자-빌더 분리의 작동 구현을 제공하기 위한 임시 해결책입니다. + +빌더 API는 합의 레이어 클라이언트가 실행 레이어 클라이언트로부터 실행 페이로드를 요청하는 데 사용되는 [엔진 API](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md)의 수정된 버전입니다. [정직한 검증자 사양](https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/validator.md)에 설명된 대로, 블록 제안 의무를 위해 선택된 검증자는 연결된 실행 클라이언트로부터 트랜잭션 번들을 요청하고, 이를 제안된 비콘 체인 블록에 포함시킵니다. + +빌더 API는 또한 검증자와 실행 레이어 클라이언트 간의 미들웨어 역할을 합니다. 그러나 비콘 체인의 검증자가 외부 주체로부터 블록을 소싱할 수 있도록 허용한다는 점에서 다릅니다(실행 클라이언트를 사용하여 로컬에서 블록을 생성하는 대신). + +다음은 빌더 API의 작동 방식에 대한 개요입니다. + +1. 빌더 API는 검증자를 실행 레이어 클라이언트를 실행하는 블록 빌더 네트워크에 연결합니다. PBS에서와 같이, 빌더는 자원 집약적인 블록 생성에 투자하고 MEV + 우선순위 팁에서 얻는 수익을 극대화하기 위해 다양한 전략을 사용하는 전문 주체입니다. + +2. 검증자(합의 레이어 클라이언트를 실행 중인)는 빌더 네트워크로부터 입찰과 함께 실행 페이로드를 요청합니다. 빌더의 입찰에는 실행 페이로드 헤더(페이로드 내용에 대한 암호화된 커밋먼트)와 검증자에게 지불할 수수료가 포함됩니다. + +3. 검증자는 들어오는 입찰을 검토하고 가장 높은 수수료를 가진 실행 페이로드를 선택합니다. 빌더 API를 사용하여 검증자는 자신의 서명과 실행 페이로드 헤더만 포함하는 "블라인드" 비콘 블록 제안을 생성하여 빌더에게 보냅니다. + +4. 빌더 API를 실행하는 빌더는 블라인드 블록 제안을 보면 전체 실행 페이로드로 응답해야 합니다. 이를 통해 검증자는 "서명된" 비콘 블록을 생성하여 네트워크 전체에 전파할 수 있습니다. + +5. 빌더 API를 사용하는 검증자는 블록 빌더가 신속하게 응답하지 않을 경우를 대비해 로컬에서 블록을 생성하여 블록 제안 보상을 놓치지 않도록 해야 합니다. 그러나 검증자는 이제 공개된 트랜잭션이나 다른 세트를 사용하여 또 다른 블록을 생성할 수 없습니다. 이는 _이중 서명_(동일한 슬롯 내에서 두 개의 블록에 서명하는 것)에 해당하며, 이는 슬래싱 대상 범죄입니다. + +빌더 API의 구현 예로는 이더리움에 대한 MEV의 부정적인 외부 효과를 억제하기 위해 설계된 [Flashbots 경매 메커니즘](https://docs.flashbots.net/Flashbots-auction/overview)의 개선 사항인 [MEV Boost](https://github.com/flashbots/mev-boost)가 있습니다. Flashbots 경매를 통해 지분 증명 검증자는 수익성 있는 블록을 구축하는 작업을 검색자라는 전문 당사자에게 아웃소싱할 수 있습니다. +![MEV 흐름을 자세히 보여주는 다이어그램](./mev.png) + +검색자는 수익성 있는 MEV 기회를 찾아 블록에 포함시키기 위해 [밀봉 가격 입찰](https://en.wikipedia.org/wiki/First-price_sealed-bid_auction)과 함께 트랜잭션 번들을 블록 제안자에게 보냅니다. go-ethereum(Geth) 클라이언트의 포크 버전인 mev-geth를 실행하는 검증자는 가장 수익성이 높은 번들을 선택하여 새 블록의 일부로 포함시키기만 하면 됩니다. 블록 제안자(검증자)를 스팸 및 유효하지 않은 트랜잭션으로부터 보호하기 위해 트랜잭션 번들은 제안자에게 도달하기 전에 검증을 위해 릴레이어를 통과합니다. + +MEV Boost는 이더리움의 지분 증명 전환을 위해 설계된 새로운 기능을 갖추고 있지만, 원래 Flashbots 경매의 동일한 작동 방식을 유지합니다. 검색자는 여전히 블록에 포함할 수익성 있는 MEV 트랜잭션을 찾지만, 빌더라고 불리는 새로운 종류의 전문 당사자가 트랜잭션과 번들을 블록으로 집계하는 책임을 집니다. 빌더는 검색자로부터 밀봉 가격 입찰을 수락하고 최적화를 실행하여 가장 수익성 있는 순서를 찾습니다. + +릴레이어는 여전히 트랜잭션 번들을 제안자에게 전달하기 전에 검증할 책임이 있습니다. 그러나 MEV Boost는 빌더가 보낸 블록 본문과 검증자가 보낸 블록 헤더를 저장하여 [데이터 가용성](/developers/docs/data-availability/)을 제공하는 에스크로를 도입합니다. 여기서 릴레이에 연결된 검증자는 사용 가능한 실행 페이로드를 요청하고 MEV Boost의 정렬 알고리즘을 사용하여 가장 높은 입찰가 + MEV 팁이 있는 페이로드 헤더를 선택합니다. + +#### 빌더 API는 MEV의 영향을 어떻게 완화합니까? {#how-does-builder-api-curb-mev-impact} + +빌더 API의 핵심 이점은 MEV 기회에 대한 접근을 민주화할 수 있는 잠재력입니다. 커밋-리빌 체계를 사용하면 신뢰 가정이 제거되고 MEV로부터 이익을 얻으려는 검증자의 진입 장벽이 낮아집니다. 이는 단독 스테이커가 MEV 이익을 늘리기 위해 대규모 스테이킹 풀과 통합해야 하는 압력을 줄여야 합니다. + +빌더 API의 광범위한 구현은 블록 빌더 간의 경쟁을 더욱 촉진하여 검열 저항성을 높일 것입니다. 검증자가 여러 빌더의 입찰을 검토함에 따라, 하나 이상의 사용자 트랜잭션을 검열하려는 빌더는 성공하기 위해 다른 모든 비검열 빌더보다 높은 가격을 제시해야 합니다. 이는 사용자를 검열하는 비용을 극적으로 증가시키고 그러한 행위를 억제합니다. + +MEV Boost와 같은 일부 프로젝트는 선행매매/샌드위치 공격을 피하려는 거래자와 같은 특정 당사자에게 트랜잭션 개인 정보 보호를 제공하도록 설계된 전체 구조의 일부로 빌더 API를 사용합니다. 이는 사용자와 블록 빌더 간의 비공개 통신 채널을 제공함으로써 달성됩니다. 앞서 설명한 허가형 멤풀과 달리 이 접근 방식은 다음과 같은 이유로 유익합니다. + +1. 시장에 여러 빌더가 존재하면 검열이 비현실적이 되어 사용자에게 이익이 됩니다. 대조적으로, 중앙화되고 신뢰 기반의 다크 풀이 존재하면 소수의 블록 빌더 손에 권력이 집중되고 검열 가능성이 높아질 것입니다. + +2. 빌더 API 소프트웨어는 오픈 소스이므로 누구나 블록 빌더 서비스를 제공할 수 있습니다. 이는 사용자가 특정 블록 빌더를 강제로 사용하지 않아도 되며 이더리움의 중립성과 무허가성을 향상시킵니다. 또한, MEV를 추구하는 거래자들은 비공개 거래 채널을 사용함으로써 의도치 않게 중앙화에 기여하지 않게 됩니다. + +## 관련 자료 {#related-resources} + +- [Flashbots 문서](https://docs.flashbots.net/) +- [Flashbots GitHub](https://github.com/flashbots/pm) +- [mevboost.org](https://www.mevboost.org/) - _MEV-Boost 릴레이 및 블록 빌더에 대한 실시간 통계 추적기_ + +## 더 읽어보기 {#further-reading} + +- [채굴자 추출 가능 가치(MEV)란 무엇인가?](https://blog.chain.link/what-is-miner-extractable-value-mev/) +- [MEV와 나](https://www.paradigm.xyz/2021/02/mev-and-me) +- [이더리움은 어두운 숲이다](https://www.paradigm.xyz/2020/08/ethereum-is-a-dark-forest/) +- [어두운 숲 탈출하기](https://samczsun.com/escaping-the-dark-forest/) +- [Flashbots: MEV 위기 선행매매](https://medium.com/flashbots/frontrunning-the-mev-crisis-40629a613752) +- [@bertcmiller의 MEV 스레드](https://twitter.com/bertcmiller/status/1402665992422047747) +- [MEV-Boost: 병합 준비가 된 Flashbots 아키텍처](https://ethresear.ch/t/mev-boost-merge-ready-flashbots-architecture/11177) +- [MEV Boost란 무엇인가](https://www.alchemy.com/overviews/mev-boost) +- [왜 mev-boost를 실행해야 하는가?](https://writings.flashbots.net/writings/why-run-mevboost/) +- [이더리움을 위한 히치하이커 안내서](https://members.delphidigital.io/reports/the-hitchhikers-guide-to-ethereum) diff --git a/public/content/translations/ko/developers/docs/networking-layer/index.md b/public/content/translations/ko/developers/docs/networking-layer/index.md new file mode 100644 index 00000000000..7bbbff13333 --- /dev/null +++ b/public/content/translations/ko/developers/docs/networking-layer/index.md @@ -0,0 +1,155 @@ +--- +title: "네트워킹 계층" +description: "이더리움의 네트워크 계층 소개." +lang: ko +sidebarDepth: 2 +--- + +이더리움은 표준화된 프로토콜을 기반으로 서로 통신할 수 있어야 하는, 수천 개의 노드로 구성된 P2P 네트워크입니다. 네트워크 계층은 이러한 노드가 서로를 찾고 정보를 교환할 수 있도록 하는 프로토콜의 스택입니다. 이는 네트워크 상에서 “가십” 정보(일대다 통신)를 전파하는 것뿐만 아니라, 특정 노드 간(일대일 통신) 요청과 응답을 교환하는 것도 포함합니다. 각 노드는 올바른 정보를 주고받고 있음을 보장하기 위해 특정한 네트워크 규칙을 반드시 준수해야 합니다. + +클라이언트 소프트웨어는 실행 클라이언트와 합의 클라이언트의 두 부분으로 나누어지며, 각 부분은 고유한 네트워크 스택을 가집니다. 다른 이더리움 노드와 통신하는 것뿐만 아니라, 실행 및 합의 클라이언트는 서로 간 통신을 해야 합니다. 이 페이지는 이러한 소통을 가능하게 해주는 프로토콜에 대한 소개 설명을 제공합니다. + +실행 클라이언트는 P2P 네트워크의 실행 계층을 통한 거래를 . 이는 인증된 피어들 간의 암호화된 통신을 필요로 합니다. 검증자가 블록을 제안하기 위해 선택될 때, 노드의 로컬 트랜잭션 풀로부터의 트랜잭션은 비콘 블록으로 패키징될 RPC 연결을 통해 합의 클라이언트를 통과시킬 것입니다.검증자가 블록을 제안하기 위해 선택될 때, 노드의 로컬 트랜잭션 풀로부터의 트랜잭션은 비콘 블록으로 패키징될 RPC 연결을 통해 합의 클라이언트를 통과시킬 것입니다. 그러면 합의 클라이언트는 이를 위해서는 두 개의 개별 P2P 네트워크가 필요합니다. 하나는 트랜잭션 가십을 위해 실행 클라이언트를 연결하고, 다른 하나는 블록 가십을 위해 합의 클라이언트를 연결하는 네트워크입니다. + +## 필수 구성 요소 {#prerequisites} + +이더리움 [노드 및 클라이언트](/developers/docs/nodes-and-clients/)에 대한 지식이 있으면 이 페이지를 이해하는 데 도움이 됩니다. + +## 실행 레이어 {#execution-layer} + +실행 레이어의 네트워킹 프로토콜은 두 개의 스택으로 나뉩니다: + +- 검색 스택: UDP 위에 구축되어 새로운 노드가 연결할 피어를 찾을 수 있도록 합니다. + +- DevP2P 스택: TCP 위에 위치하며 노드가 정보를 교환할 수 있도록 합니다. + +두 스택은 병렬로 작동합니다. 검색 스택은 새로운 네트워크 참여자를 네트워크에 공급하고 DevP2P 스택은 이들의 상호 작용을 가능하게 합니다. + +### 검색 {#discovery} + +검색은 네트워크에서 다른 노드를 찾는 프로세스입니다. 이는 소규모 부트노드 집합을 사용하여 부트스트랩됩니다(주소가 클라이언트에 [하드코딩](https://github.com/ethereum/go-ethereum/blob/master/params/bootnodes.go)되어 즉시 찾을 수 있고 클라이언트를 피어에 연결할 수 있는 노드). 이러한 부트노드는 새로운 노드를 피어 집합에 소개하기 위해서만 존재합니다. 이것이 유일한 목적이며, 체인 동기화와 같은 일반적인 클라이언트 작업에는 참여하지 않으며 클라이언트가 처음 시작될 때만 사용됩니다. + +노드-부트노드 상호작용에 사용되는 프로토콜은 노드 목록을 공유하기 위해 [분산 해시 테이블](https://en.wikipedia.org/wiki/Distributed_hash_table)을 사용하는 수정된 형태의 [Kademlia](https://medium.com/coinmonks/a-brief-overview-of-kademlia-and-its-use-in-various-decentralized-platforms-da08a7f72b8f)입니다. 각 노드는 가장 가까운 피어에 연결하는 데 필요한 정보를 포함하는 이 테이블의 버전을 가지고 있습니다. 이 '근접성'은 지리적인 것이 아니라 노드 ID의 유사성으로 거리가 정의됩니다. 각 노드의 테이블은 보안 기능으로 정기적으로 새로 고쳐집니다. 예를 들어, [Discv5](https://github.com/ethereum/devp2p/tree/master/discv5) 검색 프로토콜에서 노드는 클라이언트가 지원하는 하위 프로토콜을 표시하는 '광고'를 전송하여 피어가 서로 통신하는 데 사용할 수 있는 프로토콜에 대해 협상할 수 있도록 합니다. + +검색은 PING-PONG 게임으로 시작됩니다. 성공적인 PING-PONG은 새 노드를 부트노드에 "결속"시킵니다. 네트워크에 진입하는 새 노드의 존재를 부트노드에 알리는 초기 메시지는 `PING`입니다. 이 `PING`에는 새 노드, 부트노드 및 만료 타임스탬프에 대한 해시된 정보가 포함됩니다. 부트노드는 `PING`을 수신하고 `PING` 해시를 포함하는 `PONG`을 반환합니다. `PING`과 `PONG` 해시가 일치하면 새 노드와 부트노드 간의 연결이 확인되고 "결속"되었다고 합니다. + +일단 결속되면, 새 노드는 부트노드에 `FIND-NEIGHBOURS` 요청을 보낼 수 있습니다. 부트노드가 반환하는 데이터에는 새 노드가 연결할 수 있는 피어 목록이 포함됩니다. 노드가 결속되지 않으면 `FIND-NEIGHBOURS` 요청이 실패하므로 새 노드는 네트워크에 진입할 수 없습니다. + +새 노드가 부트노드로부터 이웃 목록을 받으면 각 이웃과 PING-PONG 교환을 시작합니다. 성공적인 PING-PONG은 새 노드를 이웃과 결속시켜 메시지 교환을 가능하게 합니다. + +``` +클라이언트 시작 --> 부트노드에 연결 --> 부트노드에 결속 --> 이웃 찾기 --> 이웃에 결속 +``` + +실행 클라이언트는 현재 [Discv4](https://github.com/ethereum/devp2p/blob/master/discv4.md) 검색 프로토콜을 사용하고 있으며, [Discv5](https://github.com/ethereum/devp2p/tree/master/discv5) 프로토콜로 마이그레이션하려는 노력이 활발히 이루어지고 있습니다. + +#### ENR: 이더리움 노드 레코드 {#enr} + +[이더리움 노드 레코드(ENR)](/developers/docs/networking-layer/network-addresses/)는 서명(합의된 ID 체계에 따라 만들어진 레코드 콘텐츠의 해시), 레코드 변경 사항을 추적하는 시퀀스 번호, 임의의 키:값 쌍 목록 등 세 가지 기본 요소를 포함하는 객체입니다. 이는 새로운 피어 간에 식별 정보를 더 쉽게 교환할 수 있도록 하는 미래 보장형 형식이며 이더리움 노드에 선호되는 [네트워크 주소](/developers/docs/networking-layer/network-addresses) 형식입니다. + +#### 검색이 UDP를 기반으로 구축된 이유는 무엇인가요? {#why-udp} + +UDP는 오류 검사, 실패한 패킷 재전송 또는 동적으로 연결을 열고 닫는 것을 지원하지 않습니다. 대신 성공적으로 수신되었는지 여부에 관계없이 대상에 지속적인 정보 스트림을 보냅니다. 이러한 최소한의 기능은 오버헤드도 최소화하여 이런 종류의 연결을 매우 빠르게 만듭니다. 노드가 피어와 공식적인 연결을 설정하기 위해 자신의 존재를 알리기만 하면 되는 검색의 경우 UDP로 충분합니다. 그러나 나머지 네트워킹 스택의 경우 UDP는 목적에 적합하지 않습니다. 노드 간의 정보 교환은 매우 복잡하므로 재전송, 오류 검사 등을 지원할 수 있는 더 완벽한 기능을 갖춘 프로토콜이 필요합니다. TCP와 관련된 추가 오버헤드는 추가 기능만큼의 가치가 있습니다. 따라서 P2P 스택의 대부분은 TCP를 통해 작동합니다. + +### DevP2P {#devp2p} + +DevP2P는 이더리움이 P2P 네트워크를 구축하고 유지하기 위해 구현하는 전체 프로토콜 스택입니다. 새 노드가 네트워크에 들어온 후, 이들의 상호 작용은 [DevP2P](https://github.com/ethereum/devp2p) 스택의 프로토콜에 의해 제어됩니다. 이들은 모두 TCP 위에 있으며 RLPx 전송 프로토콜, 와이어 프로토콜 및 여러 하위 프로토콜을 포함합니다. [RLPx](https://github.com/ethereum/devp2p/blob/master/rlpx.md)는 노드 간의 세션을 시작, 인증 및 유지 관리하는 프로토콜입니다. RLPx는 RLP(재귀 길이 접두사)를 사용하여 메시지를 인코딩하는데, 이는 노드 간 전송을 위해 데이터를 최소 구조로 인코딩하는 매우 공간 효율적인 방법입니다. + +두 노드 간의 RLPx 세션은 초기 암호화 핸드셰이크로 시작됩니다. 여기에는 노드가 인증 메시지를 보내고 피어가 이를 확인하는 과정이 포함됩니다. 확인에 성공하면 피어는 시작 노드로 반환할 인증-응답 메시지를 생성합니다. 이는 노드가 개인적으로 그리고 안전하게 통신할 수 있도록 하는 키 교환 프로세스입니다. 성공적인 암호화 핸드셰이크는 두 노드가 서로에게 "와이어상에서" "hello" 메시지를 보내도록 합니다. 와이어 프로토콜은 hello 메시지의 성공적인 교환으로 시작됩니다. + +hello 메시지에는 다음이 포함됩니다. + +- 프로토콜 버전 +- 클라이언트 ID +- 포트 +- 노드 ID +- 지원되는 하위 프로토콜 목록 + +이것은 두 노드 간에 공유되는 기능을 정의하고 통신을 구성하기 때문에 성공적인 상호 작용에 필요한 정보입니다. 각 노드에서 지원하는 하위 프로토콜 목록을 비교하고 두 노드에 공통적인 프로토콜을 세션에서 사용할 수 있는 하위 프로토콜 협상 프로세스가 있습니다. + +hello 메시지와 함께 와이어 프로토콜은 연결이 닫힐 것이라는 경고를 피어에게 제공하는 "연결 끊기" 메시지를 보낼 수도 있습니다. 와이어 프로토콜에는 세션을 열어두기 위해 주기적으로 전송되는 PING 및 PONG 메시지도 포함됩니다. 따라서 RLPx 및 와이어 프로토콜 교환은 노드 간 통신의 기반을 구축하여 특정 하위 프로토콜에 따라 유용한 정보를 교환하기 위한 발판을 제공합니다. + +### 하위 프로토콜 {#sub-protocols} + +#### 와이어 프로토콜 {#wire-protocol} + +피어가 연결되고 RLPx 세션이 시작되면 와이어 프로토콜은 피어가 통신하는 방법을 정의합니다. 처음에 와이어 프로토콜은 체인 동기화, 블록 전파, 트랜잭션 교환의 세 가지 주요 작업을 정의했습니다. 그러나 이더리움이 지분 증명으로 전환되면서 블록 전파와 체인 동기화는 합의 레이어의 일부가 되었습니다. 트랜잭션 교환은 여전히 실행 클라이언트의 권한 내에 있습니다. 트랜잭션 교환은 블록 빌더가 다음 블록에 포함할 일부 트랜잭션을 선택할 수 있도록 노드 간에 보류 중인 트랜잭션을 교환하는 것을 의미합니다. 이러한 작업에 대한 자세한 정보는 [여기](https://github.com/ethereum/devp2p/blob/master/caps/eth.md)에서 확인할 수 있습니다. 이러한 하위 프로토콜을 지원하는 클라이언트는 [JSON-RPC](/developers/docs/apis/json-rpc/)를 통해 이를 노출합니다. + +#### les (라이트 이더리움 하위 프로토콜) {#les} + +이것은 라이트 클라이언트를 동기화하기 위한 최소한의 프로토콜입니다. 전통적으로 이 프로토콜은 인센티브 없이 라이트 클라이언트에 데이터를 제공하기 위해 전체 노드가 필요하기 때문에 거의 사용되지 않았습니다. 실행 클라이언트의 기본 동작은 les를 통해 라이트 클라이언트 데이터를 제공하지 않는 것입니다. 자세한 정보는 les [사양](https://github.com/ethereum/devp2p/blob/master/caps/les.md)에서 확인할 수 있습니다. + +#### 스냅 {#snap} + +[스냅 프로토콜](https://github.com/ethereum/devp2p/blob/master/caps/snap.md#ethereum-snapshot-protocol-snap)은 피어가 최근 상태의 스냅샷을 교환할 수 있도록 하는 선택적 확장으로, 피어가 중간 머클 트라이 노드를 다운로드할 필요 없이 계정 및 저장 공간 데이터를 확인할 수 있도록 합니다. + +#### Wit (증인 프로토콜) {#wit} + +[증인 프로토콜](https://github.com/ethereum/devp2p/blob/master/caps/wit.md#ethereum-witness-protocol-wit)은 피어 간의 상태 증인 교환을 가능하게 하여 클라이언트를 체인의 끝으로 동기화하는 데 도움을 주는 선택적 확장입니다. + +#### 위스퍼 {#whisper} + +위스퍼는 블록체인에 정보를 쓰지 않고 피어 간에 보안 메시징을 제공하는 것을 목표로 하는 프로토콜이었습니다. DevP2P 와이어 프로토콜의 일부였지만 현재는 더 이상 사용되지 않습니다. 비슷한 목표를 가진 다른 [관련 프로젝트](https://wakunetwork.com/)가 있습니다. + +## 합의 레이어 {#consensus-layer} + +합의 클라이언트는 다른 사양을 가진 별도의 P2P 네트워크에 참여합니다. 합의 클라이언트는 블록 가십에 참여하여 피어로부터 새 블록을 수신하고 블록 제안자가 될 차례가 되면 이를 브로드캐스트해야 합니다. 실행 레이어와 유사하게, 이를 위해서는 먼저 노드가 피어를 찾고 블록, 인증 등을 교환하기 위한 보안 세션을 설정할 수 있도록 검색 프로토콜이 필요합니다. + +### 검색 {#consensus-discovery} + +실행 클라이언트와 마찬가지로 합의 클라이언트는 피어를 찾기 위해 UDP를 통해 [discv5](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#the-discovery-domain-discv5)를 사용합니다. 합의 레이어의 discv5 구현은 discv5를 [libP2P](https://libp2p.io/) 스택에 연결하는 어댑터를 포함하여 DevP2P를 더 이상 사용하지 않는다는 점에서만 실행 클라이언트의 구현과 다릅니다. 실행 레이어의 RLPx 세션은 libP2P의 노이즈 보안 채널 핸드셰이크를 위해 더 이상 사용되지 않습니다. + +### ENR {#consensus-enr} + +합의 노드를 위한 ENR에는 노드의 공개 키, IP 주소, UDP 및 TCP 포트, 그리고 인증 서브넷 비트필드와 `eth2` 키라는 두 가지 합의 관련 필드가 포함됩니다. 전자는 노드가 특정 인증 가십 하위 네트워크에 참여하는 피어를 더 쉽게 찾을 수 있도록 합니다. `eth2` 키에는 노드가 사용 중인 이더리움 포크 버전에 대한 정보가 포함되어 있어 피어가 올바른 이더리움에 연결되도록 보장합니다. + +### libP2P {#libp2p} + +libP2P 스택은 검색 후 모든 통신을 지원합니다. 클라이언트는 ENR에 정의된 대로 IPv4 및/또는 IPv6에서 다이얼하고 수신할 수 있습니다. libP2P 레이어의 프로토콜은 가십 및 요청/응답 도메인으로 세분화될 수 있습니다. + +### 가십 {#gossip} + +가십 도메인에는 네트워크 전체에 빠르게 퍼져야 하는 모든 정보가 포함됩니다. 여기에는 비콘 블록, 증명, 인증, 출금 및 슬래싱이 포함됩니다. 이는 libP2P gossipsub v1을 사용하여 전송되며 각 노드에 로컬로 저장된 다양한 메타데이터(수신 및 전송할 가십 페이로드의 최대 크기 포함)에 의존합니다. 가십 도메인에 대한 자세한 정보는 [여기](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#the-gossip-domain-gossipsub)에서 확인할 수 있습니다. + +### 요청-응답 {#request-response} + +요청-응답 도메인에는 클라이언트가 피어에게 특정 정보를 요청하기 위한 프로토콜이 포함됩니다. 예를 들어 특정 루트 해시와 일치하거나 특정 슬롯 범위 내에 있는 특정 비콘 블록을 요청하는 것이 있습니다. 응답은 항상 snappy로 압축된 SSZ 인코딩 바이트로 반환됩니다. + +## 합의 클라이언트는 왜 RLP보다 SSZ를 선호하나요? {#ssz-vs-rlp} + +SSZ는 simple serialization(단순 직렬화)의 약자입니다. 고정 오프셋을 사용하여 전체 구조를 디코딩할 필요 없이 인코딩된 메시지의 개별 부분을 쉽게 디코딩할 수 있으므로, 합의 클라이언트가 인코딩된 메시지에서 특정 정보를 효율적으로 가져올 수 있어 매우 유용합니다. 또한 머클 프로토콜과 통합되도록 특별히 설계되었으며, 머클화에 대한 관련 효율성 향상이 있습니다. 합의 레이어의 모든 해시는 머클 루트이므로 이는 상당한 개선으로 이어집니다. SSZ는 또한 값의 고유한 표현을 보장합니다. + +## 실행 및 합의 클라이언트 연결 {#connecting-clients} + +합의 클라이언트와 실행 클라이언트는 모두 병렬로 실행됩니다. 합의 클라이언트가 실행 클라이언트에 지침을 제공하고 실행 클라이언트가 비콘 블록에 포함할 트랜잭션 번들을 합의 클라이언트에 전달할 수 있도록 연결해야 합니다. 두 클라이언트 간의 통신은 로컬 RPC 연결을 사용하여 수행할 수 있습니다. ['Engine-API'](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md)로 알려진 API는 두 클라이언트 간에 전송되는 명령을 정의합니다. 두 클라이언트 모두 단일 네트워크 ID 뒤에 있으므로 각 클라이언트에 대한 별도의 키(eth1 키 및 eth2 키)를 포함하는 ENR(이더리움 노드 레코드)을 공유합니다. + +제어 흐름의 요약은 아래에 나와 있으며 관련 네트워킹 스택은 괄호 안에 있습니다. + +### 합의 클라이언트가 블록 생성자가 아닐 때: {#when-consensus-client-is-not-block-producer} + +- 합의 클라이언트는 블록 가십 프로토콜(합의 p2p)을 통해 블록을 수신합니다. +- 합의 클라이언트는 블록을 사전 검증합니다. 즉, 올바른 메타데이터를 가진 유효한 발신자로부터 도착했는지 확인합니다. +- 블록의 트랜잭션은 실행 페이로드로 실행 레이어에 전송됩니다(로컬 RPC 연결). +- 실행 레이어는 트랜잭션을 실행하고 블록 헤더의 상태를 검증합니다(즉, 해시 일치 여부 확인). +- 실행 레이어는 검증 데이터를 합의 레이어로 다시 전달하고, 이제 블록이 검증된 것으로 간주됩니다(로컬 RPC 연결). +- 합의 레이어는 블록을 자체 블록체인의 헤드에 추가하고 이를 인증하여 네트워크를 통해 인증을 브로드캐스트합니다(합의 p2p). + +### 합의 클라이언트가 블록 생성자일 때: {#when-consensus-client-is-block-producer} + +- 합의 클라이언트는 다음 블록 생성자라는 통지를 받습니다(합의 p2p). +- 합의 레이어는 실행 클라이언트에서 `create block` 메서드를 호출합니다(로컬 RPC). +- 실행 레이어는 트랜잭션 가십 프로토콜(실행 p2p)에 의해 채워진 트랜잭션 멤풀에 액세스합니다. +- 실행 클라이언트는 트랜잭션을 블록으로 묶고, 트랜잭션을 실행하고, 블록 해시를 생성합니다. +- 합의 클라이언트는 실행 클라이언트로부터 트랜잭션과 블록 해시를 가져와 비콘 블록에 추가합니다(로컬 RPC). +- 합의 클라이언트는 블록 가십 프로토콜(합의 p2p)을 통해 블록을 브로드캐스트합니다. +- 다른 클라이언트는 블록 가십 프로토콜을 통해 제안된 블록을 수신하고 위에서 설명한 대로 검증합니다(합의 p2p). + +블록이 충분한 검증자에 의해 인증되면 체인의 헤드에 추가되고, 정당화되며, 결국 최종 확정됩니다. + +![](cons_client_net_layer.png)\n![](exe_client_net_layer.png) + +[ethresear.ch](https://ethresear.ch/t/eth1-eth2-client-relationship/7248)에서 가져온 합의 및 실행 클라이언트를 위한 네트워크 레이어 개략도 + +## 추가 정보 {#further-reading} + +[DevP2P](https://github.com/ethereum/devp2p)\n[LibP2p](https://github.com/libp2p/specs)\n[합의 레이어 네트워크 사양](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#enr-structure)\n[kademlia에서 discv5로](https://vac.dev/kademlia-to-discv5)\n[kademlia 논문](https://pdos.csail.mit.edu/~petar/papers/maymounkov-kademlia-lncs.pdf)\n[이더리움 p2p 소개](https://p2p.paris/en/talks/intro-ethereum-networking/)\n[eth1/eth2 관계](http://ethresear.ch/t/eth1-eth2-client-relationship/7248)\n[병합 및 eth2 클라이언트 세부 정보 영상](https://www.youtube.com/watch?v=zNIrIninMgg) diff --git a/public/content/translations/ko/developers/docs/networking-layer/network-addresses/index.md b/public/content/translations/ko/developers/docs/networking-layer/network-addresses/index.md new file mode 100644 index 00000000000..a1a23192422 --- /dev/null +++ b/public/content/translations/ko/developers/docs/networking-layer/network-addresses/index.md @@ -0,0 +1,39 @@ +--- +title: "네트워크 주소" +description: "네트워크 주소에 대한 소개." +lang: ko +sidebarDepth: 2 +--- + +이더리움 노드는 피어에 연결하기 위해 몇 가지 기본 정보로 자신을 식별해야 합니다. 잠재적 피어가 이 정보를 해석할 수 있도록 이더리움 노드가 이해할 수 있는 세 가지 표준화된 형식(multiaddr, enode 또는 이더리움 노드 레코드(ENR)) 중 하나로 전달됩니다. ENR은 이더리움 네트워크 주소의 현재 표준입니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 이해하려면 이더리움의 [네트워킹 층](/developers/docs/networking-layer/)에 대한 약간의 이해가 필요합니다. + +## Multiaddr {#multiaddr} + +최초의 이더리움 노드 주소 형식은 'multiaddr'('multi-addresses'의 약자)였습니다. Multiaddr는 피어투피어 네트워크를 위해 설계된 보편적인 형식입니다. 주소는 키와 값을 슬래시로 구분한 키-값 쌍으로 표시됩니다. 예를 들어, IPv4 주소 `192.168.22.27`을 사용하고 TCP 포트 `33000`에서 수신 대기하는 노드의 multiaddr는 다음과 같습니다. + +/ip4/192.168.22.27/tcp/33000 + +이더리움 노드의 경우, multiaddr에는 노드 ID(공개 키의 해시)가 포함됩니다. + +/ip4/192.168.22.27/tcp/33000/p2p/5t7Nv7dG2d6ffbvAiewVsEwWweU3LdebSqX2y1bPrW8br + +## Enode {#enode} + +Enode는 URL 주소 형식을 사용하여 이더리움 노드를 식별하는 방법입니다. 16진수 노드 ID는 URL의 사용자 이름 부분에 인코딩되며 @ 기호를 사용하여 호스트와 구분됩니다. 호스트 이름은 IP 주소로만 지정할 수 있으며 DNS 이름은 허용되지 않습니다. 호스트 이름 섹션의 포트는 TCP 수신 대기 포트입니다. TCP와 UDP(검색) 포트가 다른 경우 UDP 포트는 쿼리 파라미터 "discport"로 지정됩니다. + +다음 예에서 노드 URL은 IP 주소가 `10.3.58.6`이고 TCP 포트가 `30303`이며 UDP 검색 포트가 `30301`인 노드를 설명합니다. + +enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@10.3.58.6:30303?discport=30301 + +## 이더리움 노드 레코드(ENR) {#enr} + +이더리움 노드 레코드(ENR)는 이더리움의 네트워크 주소에 대한 표준화된 형식입니다. 이것들은 multiaddr과 enode를 대체합니다. 이것들은 노드 간에 더 많은 정보 교환을 허용하기 때문에 특히 유용합니다. ENR에는 서명, 시퀀스 번호 및 서명을 생성하고 검증하는 데 사용되는 ID 체계를 자세히 설명하는 필드가 포함되어 있습니다. ENR은 키-값 쌍으로 구성된 임의의 데이터로 채워질 수도 있습니다. 이 키-값 쌍에는 노드의 IP 주소와 노드가 사용할 수 있는 하위 프로토콜에 대한 정보가 포함됩니다. 합의 클라이언트는 [특정 ENR 구조](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#enr-structure)를 사용하여 부트 노드를 식별하고 현재 이더리움 포크 및 인증 가십 서브넷(인증이 함께 집계되는 특정 피어 집합에 노드를 연결)에 대한 정보가 포함된 `eth2` 필드도 포함합니다. + +## 추가 정보 {#further-reading} + +- [EIP-778: 이더리움 노드 레코드(ENR)](https://eips.ethereum.org/EIPS/eip-778) +- [LibP2P: Multiaddr-Enode-ENR?!](https://consensys.net/diligence/blog/2020/09/libp2p-multiaddr-enode-enr/) diff --git a/public/content/translations/ko/developers/docs/networking-layer/portal-network/index.md b/public/content/translations/ko/developers/docs/networking-layer/portal-network/index.md new file mode 100644 index 00000000000..2998c3d1bac --- /dev/null +++ b/public/content/translations/ko/developers/docs/networking-layer/portal-network/index.md @@ -0,0 +1,89 @@ +--- +title: "포털 네트워크" +description: "포털 네트워크 개요 - 저사양 클라이언트를 지원하도록 설계된 개발 중인 네트워크입니다." +lang: ko +--- + +이더리움은 이더리움 클라이언트 소프트웨어를 실행하는 컴퓨터로 구성된 네트워크입니다. 이러한 각 컴퓨터를 '노드'라고 합니다. 클라이언트 소프트웨어를 통해 노드는 이더리움 네트워크에서 데이터를 보내고 받을 수 있으며, 이더리움 프로토콜 규칙에 따라 데이터를 검증합니다. 노드는 디스크 저장 공간에 많은 양의 기록 데이터를 보관하며 네트워크의 다른 노드로부터 블록이라고 하는 새로운 정보 패킷을 받을 때마다 이를 추가합니다. 이는 노드가 네트워크의 나머지 부분과 일치하는 정보를 가지고 있는지 항상 확인하는 데 필요합니다. 이는 노드를 실행하는 데 많은 디스크 공간이 필요할 수 있음을 의미합니다. 일부 노드 작업에는 많은 RAM이 필요할 수도 있습니다. + +이러한 디스크 저장 공간 문제를 해결하기 위해, 모든 정보를 직접 저장하는 대신 전체 노드에 정보를 요청하는 '라이트' 노드가 개발되었습니다. 하지만 이는 라이트 노드가 독립적으로 정보를 검증하지 않고 대신 다른 노드를 신뢰한다는 것을 의미합니다. 이는 또한 전체 노드가 해당 라이트 노드에 서비스를 제공하기 위해 추가 작업을 수행해야 함을 의미합니다. + +포털 네트워크는 필요한 데이터를 네트워크 전체에서 작은 조각으로 공유함으로써 전체 노드를 신뢰하거나 추가적인 부담을 주지 않고 "라이트" 노드의 데이터 가용성 문제를 해결하는 것을 목표로 하는 이더리움의 새로운 네트워킹 설계입니다. + +[노드 및 클라이언트](/developers/docs/nodes-and-clients/)에 대해 더 알아보기 + +## 포털 네트워크가 필요한 이유 {#why-do-we-need-portal-network} + +이더리움 노드는 이더리움 블록체인의 전체 또는 부분 사본을 자체적으로 저장합니다. 이 로컬 사본은 트랜잭션을 검증하고 노드가 올바른 체인을 따르고 있는지 확인하는 데 사용됩니다. 로컬에 저장된 이 데이터를 통해 노드는 다른 개체를 신뢰할 필요 없이 들어오는 데이터가 유효하고 올바른지 독립적으로 검증할 수 있습니다. + +이러한 블록체인의 로컬 사본과 관련 상태 및 영수증 데이터는 노드의 하드 디스크에서 많은 공간을 차지합니다. 예를 들어, [Geth](https://geth.ethereum.org)를 합의 클라이언트와 페어링하여 노드를 실행하려면 2TB 하드 디스크가 권장됩니다. 비교적 최근의 블록 세트에서 체인 데이터만 저장하는 스냅 동기화를 사용하면 Geth는 일반적으로 약 650GB의 디스크 공간을 차지하지만 주당 약 14GB씩 증가합니다(주기적으로 노드를 650GB로 다시 정리할 수 있습니다). + +이는 많은 양의 디스크 공간이 이더리움에 할당되어야 하므로 노드를 실행하는 데 비용이 많이 들 수 있음을 의미합니다. 이더리움 로드맵에는 [히스토리 만료](/roadmap/statelessness/#history-expiry), [상태 만료](/roadmap/statelessness/#state-expiry), [무상태성](/roadmap/statelessness/) 등 이 문제에 대한 몇 가지 해결책이 있습니다. 하지만, 이러한 기능이 구현되려면 몇 년이 걸릴 것으로 보입니다. 체인 데이터의 자체 사본을 저장하지 않고 전체 노드에서 필요한 데이터를 요청하는 [라이트 노드](/developers/docs/nodes-and-clients/light-clients/)도 있습니다. 하지만 이는 라이트 노드가 정직한 데이터를 제공하는 전체 노드를 신뢰해야 하며, 라이트 노드가 필요로 하는 데이터를 제공해야 하는 전체 노드에 부담을 준다는 것을 의미합니다. + +포털 네트워크는 라이트 노드가 전체 노드에서 수행해야 하는 작업에 대한 신뢰나 상당한 추가 작업 없이 데이터를 얻을 수 있는 대안적인 방법을 제공하는 것을 목표로 합니다. 이를 위해 이더리움 노드가 네트워크 전체에서 데이터를 공유할 수 있는 새로운 방법을 도입할 것입니다. + +## 포털 네트워크는 어떻게 작동하나요? {#how-does-portal-network-work} + +이더리움 노드에는 서로 통신하는 방법을 정의하는 엄격한 프로토콜이 있습니다. 실행 클라이언트는 [DevP2P](/developers/docs/networking-layer/#devp2p)로 알려진 하위 프로토콜 세트를 사용하여 통신하는 반면, 합의 클라이언트는 [libP2P](/developers/docs/networking-layer/#libp2p)라는 다른 하위 프로토콜 스택을 사용합니다. 이는 노드 간에 전달될 수 있는 데이터 유형을 정의합니다. + +![devP2P 및 libP2P](portal-network-devp2p-libp2p.png) + +노드는 [JSON-RPC API](/developers/docs/apis/json-rpc/)를 통해 특정 데이터를 제공할 수도 있으며, 이를 통해 앱과 지갑이 이더리움 노드와 정보를 교환합니다. 하지만 이들 중 어느 것도 라이트 클라이언트에 데이터를 제공하기에 이상적인 프로토콜은 아닙니다. + +라이트 클라이언트는 현재 DevP2P 또는 libP2p를 통해 특정 체인 데이터를 요청할 수 없습니다. 왜냐하면 이러한 프로토콜은 체인 동기화와 블록 및 트랜잭션의 가십(gossiping)을 가능하게 하도록 설계되었기 때문입니다. 라이트 클라이언트는 이 정보를 다운로드하고 싶어하지 않습니다. 그렇게 하면 "라이트"라는 특성을 잃게 되기 때문입니다. + +JSON-RPC API 또한 라이트 클라이언트 데이터 요청에 이상적인 선택이 아닙니다. 왜냐하면 데이터를 제공할 수 있는 특정 전체 노드 또는 중앙화된 RPC 제공자와의 연결에 의존하기 때문입니다. 이는 라이트 클라이언트가 특정 노드/제공자가 정직하다고 신뢰해야 하며, 전체 노드는 많은 라이트 클라이언트로부터 수많은 요청을 처리해야 하므로 대역폭 요구 사항이 추가될 수 있음을 의미합니다. + +포털 네트워크의 핵심은 기존 이더리움 클라이언트의 설계 제약에서 벗어나, 가벼움을 위해 특별히 구축하여 전체 설계를 재고하는 것입니다. + +포털 네트워크의 핵심 아이디어는 기록 데이터 및 현재 체인 헤드의 ID와 같이 라이트 클라이언트가 필요로 하는 정보를 [DHT](https://en.wikipedia.org/wiki/Distributed_hash_table)(비트토렌트와 유사)를 사용하는 경량 DevP2P 스타일의 P2P(peer-to-peer) 탈중앙화 네트워크를 통해 제공함으로써 현재 네트워킹 스택의 가장 좋은 부분을 취하는 것입니다. + +아이디어는 전체 이더리움 기록 데이터의 작은 부분과 일부 특정 노드 책임을 각 노드에 추가하는 것입니다. 그런 다음, 요청된 특정 데이터를 저장하는 노드를 찾아내고 그들로부터 데이터를 검색하여 요청을 처리합니다. + +이는 라이트 노드가 단일 노드를 찾아 대용량 데이터를 필터링하고 제공하도록 요청하는 일반적인 모델을 뒤집습니다. 대신, 각각 소량의 데이터를 처리하는 대규모 노드 네트워크를 신속하게 필터링합니다. + +목표는 경량 포털 클라이언트의 탈중앙화 네트워크가 다음을 수행할 수 있도록 하는 것입니다. + +- 체인 헤드 추적 +- 최신 및 과거 체인 데이터 동기화 +- 상태 데이터 검색 +- 트랜잭션 브로드캐스트 +- [EVM](/developers/docs/evm/)을 사용하여 트랜잭션 실행 + +이 네트워크 설계의 이점은 다음과 같습니다. + +- 중앙화된 제공자에 대한 의존도 감소 +- 인터넷 대역폭 사용량 감소 +- 최소화 또는 제로 동기화 +- 리소스가 제한된 장치에서 접근 가능(\<1GB RAM, \<100MB 디스크 공간, 1 CPU) + +아래 표는 포털 네트워크를 통해 제공될 수 있는 기존 클라이언트의 기능을 보여주며, 사용자는 매우 저사양 장치에서 이러한 기능에 접근할 수 있습니다. + +### 포털 네트워크 + +| 비콘 라이트 클라이언트 | 상태 네트워크 | 트랜잭션 가십 | 히스토리 네트워크 | +| ------------ | --------------- | ------- | --------- | +| 비콘 체인 라이트 | 계정 및 컨트랙트 저장 공간 | 경량 멤풀 | 헤더 | +| 프로토콜 데이터 | | | 블록 본문 | +| | | | 영수증 | + +## 기본적인 클라이언트 다양성 {#client-diversity-as-default} + +포털 네트워크 개발자들은 또한 처음부터 4개의 개별 포털 네트워크 클라이언트를 구축하기로 설계 결정을 내렸습니다. + +포털 네트워크 클라이언트는 다음과 같습니다. + +- [Trin](https://github.com/ethereum/trin): Rust로 작성됨 +- [Fluffy](https://fluffy.guide): Nim으로 작성됨 +- [Ultralight](https://github.com/ethereumjs/ultralight): Typescript로 작성됨 +- [Shisui](https://github.com/zen-eth/shisui): Go로 작성됨 + +여러 개의 독립적인 클라이언트 구현이 있으면 이더리움 네트워크의 복원력과 탈중앙화가 향상됩니다. + +한 클라이언트에 문제나 취약점이 발생하더라도 다른 클라이언트는 원활하게 계속 작동하여 단일 실패 지점을 방지할 수 있습니다. 또한, 다양한 클라이언트 구현은 혁신과 경쟁을 촉진하여 생태계 내 개선을 이끌고 단일 문화의 위험을 줄입니다. + +## 더 읽어보기 {#further-reading} + +- [포털 네트워크 (Devcon 보고타에서 Piper Merriam 발표)](https://www.youtube.com/watch?v=0stc9jnQLXA). +- [포털 네트워크 디스코드](https://discord.gg/CFFnmE7Hbs) +- [포털 네트워크 웹사이트](https://www.ethportal.net/) diff --git a/public/content/translations/ko/developers/docs/networks/index.md b/public/content/translations/ko/developers/docs/networks/index.md new file mode 100644 index 00000000000..db2d6fdeb4f --- /dev/null +++ b/public/content/translations/ko/developers/docs/networks/index.md @@ -0,0 +1,216 @@ +--- +title: "네트워크" +description: "이더리움 네트워크에 대한 설명서 및 테스트용 이더(ETH)를 획득하는 방법" +lang: ko +--- + +이더리움 네트워크는 이더리움 프로토콜을 사용하여 통신하는 연결된 컴퓨터 그룹입니다. 이더리움 메인넷은 하나뿐이지만, 테스트 및 개발 목적으로 동일한 프로토콜 규칙을 따르는 독립적인 네트워크를 생성할 수 있습니다. 서로 상호 작용하지 않으면서 프로토콜을 준수하는 독립적인 "네트워크"가 많이 있습니다. 스마트 계약과 웹3 앱을 테스트하기 위해 자신의 컴퓨터에서 로컬로 네트워크를 시작할 수도 있습니다. + +이더리움 주소 (Ethereum account) 는 서로 다른 네트워크에서 똑같이 이용될 수 있습니다. 하지만 주소의 잔액 (balance) 및 거래 내역 (transaction history) 는 네트워크마다 다를 수 있습니다. 테스트 작업을 위해 어떤 네트워크가 필요한지, 그리고 테스트넷 이더리움을 획득하는 방법을 알면 유용합니다. 일반적으로 보안상의 이유로 테스트넷에서 메인넷 계정을 재사용하거나 그 반대의 경우는 권장하지 않습니다. + +## 필수 구성 요소 {#prerequisites} + +테스트넷은 저렴하고 안전한 버전의 이더리움을 제공하므로 여러 네트워크에 대해 알아보기 전에 [이더리움의 기본 사항](/developers/docs/intro-to-ethereum/)을 이해해야 합니다. + +## 공개 네트워크 {#public-networks} + +공용 네트워크에는 인터넷에 연결할 수 있는 모든 사람이 접근할 수 있습니다. 누구나 공용 블록체인 상의 트랜잭션을 읽거나 만들고 트랜잭션이 실행되도록 승인할 수 있습니다. 개인간의 합의를 통해 거래의 승인 및 네트워크의 상태가 결정된다. + +### 이더리움 메인넷 {#ethereum-mainnet} + +메인넷이란 실제 거래가 분산 장부에 기록되는 이더리움 블록체인이다. + +코인 거래소에서 보여주는 ETH 가격이 바로 메인넷 이더리움 가격이다. + +### 이더리움 테스트넷 {#ethereum-testnets} + +메인넷 외에도 공용 테스트넷이 있습니다. 테스트넷은 프로토콜 개발자 또는 스마트계약 개발자들이 메인넷에 배포하기 전 실제 환경과 비슷한 가상의 환경에서 프로토콜 업그레이드 또는 스마트계약 테스트를 위해 활용된다. 비유를 들자면, 프로덕션 서버와 스테이징 서버의 관계와 비슷하다. + +사실 메인넷에 배포하기 전 모든 스마트계약 코드는 테스트넷에서 테스트를 거쳐야 한다. 이미 배포된 스마트계약에 통합되는 댑 dapp 들은 대부분 테스트넷에 배포 단계를 거쳤다. + +대부분의 테스트넷은 허가된 proof-of-authority 합의 메커니즘을 사용하여 시작되었습니다. 즉, 소수의 노드가 거래 검증 및 새 블록 형성에 사용되며 이 때 각 과정에서 신분확인이 이뤄집니다. 또는 일부 테스트넷은 이더리움 메인넷처럼 모든 사람이 벨리데이터 실행을 테스트할 수 있는 개방형 PoS 합의 메커니즘을 특징으로 합니다. + +테스트넷의 ETH는 실제 가치가 없는 것으로 간주되지만, 희소해지거나 구하기 어려워진 특정 유형의 테스트넷 ETH에 대한 시장이 형성되기도 했습니다. 이더리움과 상호작용하려면(테스트넷에서도) ETH가 필요하기 때문에, 대부분의 사람들은 포싯에서 테스트넷 ETH를 무료로 받습니다. faucet은 ETH를 받을 주소를 입력할 수 있는 웹앱인 경우가 많다. + +#### 어떤 동기화 방법을 사용해야 할까요? + +현재 클라이언트 개발자들이 유지 관리하는 두 개의 공개 테스트넷은 Sepolia와 Hoodi입니다. Sepolia는 컨트랙트와 어플리케이션 개발자들이 그들의 어플리케이션을 테스트하기 위해서 필요한 네트워크입니다. Hoodi 네트워크를 통해 프로토콜 개발자는 네트워크 업그레이드를 테스트하고, 스테이커는 검증자 실행을 테스트할 수 있습니다. + +#### Sepolia {#sepolia} + +**Sepolia는 어플리케이션 개발을 위한 디폴트 테스트넷으로 많이 쓰인다**. Sepolia 네트워크는 클라이언트 및 테스트 팀이 제어하는 허가된 검증자 세트를 사용합니다. + +##### 참고 자료 + +- [웹사이트](https://sepolia.dev/) +- [GitHub](https://github.com/eth-clients/sepolia) +- [Otterscan](https://sepolia.otterscan.io/) +- [Etherscan](https://sepolia.etherscan.io) +- [Blockscout](https://eth-sepolia.blockscout.com/) + +##### Faucets + +- [Alchemy Sepolia 포싯](https://www.alchemy.com/faucets/ethereum-sepolia) +- [Chain Platform Sepolia 포싯](https://faucet.chainplatform.co/faucets/ethereum-sepolia/) +- [Chainstack Sepolia 포싯](https://faucet.chainstack.com/sepolia-testnet-faucet) +- [Ethereum Ecosystem 포싯](https://www.ethereum-ecosystem.com/faucets/ethereum-sepolia) +- [ethfaucet.com Sepolia 포싯](https://ethfaucet.com/networks/ethereum) +- [Google Cloud Web3 Sepolia 포싯](https://cloud.google.com/application/web3/faucet/ethereum/sepolia) +- [Grabteeth](https://grabteeth.xyz/) +- [Infura Sepolia 포싯](https://www.infura.io/faucet) +- [PoW 포싯](https://sepolia-faucet.pk910.de/) +- [QuickNode Sepolia 포싯](https://faucet.quicknode.com/ethereum/sepolia) + +#### Hoodi {#hoodi} + +Hoodi는 검증 및 스테이킹을 테스트하기 위한 테스트넷입니다. Hoodi 네트워크는 테스트넷 검증자를 실행하려는 사용자에게 열려 있습니다. 따라서 메인넷에 배포되기 전에 프로토콜 업그레이드를 테스트하려는 스테이커는 Hoodi를 사용해야 합니다. + +- 개방형 검증자 세트, staker가 네트워크 업그레이드를 테스트할 수 있음 +- 복잡한 스마트 계약 상호 작용을 테스트하는 데 유용한 대규모 state +- 동기화 시간이 길어지고 노드를 실행하는 데 더 많은 스토리지 필요 + +##### 참고 자료 + +- [웹사이트](https://hoodi.ethpandaops.io/) +- [GitHub](https://github.com/eth-clients/hoodi) +- [익스플로러](https://explorer.hoodi.ethpandaops.io/) +- [체크포인트 동기화](https://checkpoint-sync.hoodi.ethpandaops.io/) +- [Otterscan](https://hoodi.otterscan.io/) +- [Etherscan](https://hoodi.etherscan.io/) + +##### Faucets + +- [Chain Platform Hoodi 포싯](https://faucet.chainplatform.co/faucets/ethereum-hoodi/) +- [Hoodi 포싯](https://hoodi.ethpandaops.io/) +- [PoW 포싯](https://hoodi-faucet.pk910.de/) + +#### Ephemery {#ephemery} + +Ephemery는 매달 완전히 재설정되는 독특한 종류의 테스트넷입니다. 실행 및 합의 상태는 28일마다 제네시스로 되돌아가는데, 이는 테스트넷에서 발생하는 모든 것이 일시적이라는 것을 의미합니다. 따라서 영속성이 필요 없는 단기 테스트, 빠른 노드 부트스트랩 및 '헬로 월드' 유형의 애플리케이션에 이상적입니다. + +- 항상 최신 상태, 검증자 및 앱의 단기 테스트 +- 기본 계약 세트만 포함합니다. +- 개방형 검증자 세트 및 대량의 자금에 대한 쉬운 접근성 +- 가장 작은 노드 요구 사항과 가장 빠른 동기화, 평균 5GB 미만 + +##### 참고 자료 + +- [웹사이트](https://ephemery.dev/) +- [Github](https://github.com/ephemery-testnet/ephemery-resources) +- [커뮤니티 채팅](https://matrix.to/#/#staker-testnet:matrix.org) +- [Blockscout](https://explorer.ephemery.dev/) +- [Otterscan](https://otter.bordel.wtf/) +- [비콘 익스플로러](https://beaconlight.ephemery.dev/) +- [체크포인트 동기화](https://checkpoint-sync.ephemery.ethpandaops.io) +- [런치패드](https://launchpad.ephemery.dev/) + +#### Faucets + +- [Bordel 포싯](https://faucet.bordel.wtf/) +- [Pk910 PoW 포싯](https://ephemery-faucet.pk910.de/) + +#### Holesky(지원 중단) {#holesky} + +Holesky 테스트넷은 2025년 9월부터 지원이 중단됩니다. 스테이킹 운영자와 인프라 제공업체는 대신 검증자 테스트에 Hoodi를 사용해야 합니다. + +- [Holesky 테스트넷 종료 발표](https://blog.ethereum.org/2025/09/01/holesky-shutdown-announcement) - _EF 블로그, 2025년 9월 1일_ +- [Holesky 및 Hoodi 테스트넷 업데이트](https://blog.ethereum.org/en/2025/03/18/hoodi-holesky) - _EF 블로그, 2025년 3월 18일_ + +### 레이어 2 테스트넷 {#layer-2-testnets} + +[레이어 2(L2)](/layer-2/)는 특정 이더리움 확장 솔루션 세트를 설명하는 총칭입니다. 레이어 2는 이더리움 블록체인을 확장하는 또다른 블록체인이며 이더리움의 보안성을 그대로 이어 받는다. 레이어 2에 속한 테스트넷은 주로 이더리움 테스트넷과 큰 연관성을 보인다. + +#### Arbitrum Sepolia {#arbitrum-sepolia} + +[Arbitrum](https://arbitrum.io/)을 위한 테스트넷입니다. + +##### 참고 자료 + +- [Etherscan](https://sepolia.arbiscan.io/) +- [Blockscout](https://sepolia-explorer.arbitrum.io/) + +##### Faucets + +- [Alchemy Arbitrum Sepolia 포싯](https://www.alchemy.com/faucets/arbitrum-sepolia) +- [Chainlink Arbitrum Sepolia 포싯](https://faucets.chain.link/arbitrum-sepolia) +- [ethfaucet.com Arbitrum Sepolia 포싯](https://ethfaucet.com/networks/arbitrum) +- [QuickNode Arbitrum Sepolia 포싯](https://faucet.quicknode.com/arbitrum/sepolia) + +#### Optimistic Sepolia {#optimistic-sepolia} + +[Optimism](https://www.optimism.io/)을 위한 테스트넷입니다. + +##### 참고 자료 + +- [Etherscan](https://sepolia-optimistic.etherscan.io/) +- [Blockscout](https://optimism-sepolia.blockscout.com/) + +##### Faucets + +- [Alchemy 포싯](https://www.alchemy.com/faucets/optimism-sepolia) +- [Chainlink 포싯](https://faucets.chain.link/optimism-sepolia) +- [ethfaucet.com Optimism Sepolia 포싯](https://ethfaucet.com/networks/optimism) +- [테스트넷 포싯](https://docs.optimism.io/builders/tools/build/faucets) + +#### Starknet Sepolia {#starknet-sepolia} + +[Starknet](https://www.starknet.io)을 위한 테스트넷입니다. + +##### 참고 자료 + +- [Starkscan](https://sepolia.starkscan.co/) + +##### Faucets + +- [Alchemy 포싯](https://www.alchemy.com/faucets/starknet-sepolia) +- [Blast Starknet Sepolia 포싯](https://blastapi.io/faucets/starknet-sepolia-eth) +- [Starknet 포싯](https://starknet-faucet.vercel.app/) + +## 프라이빗 네트워크 {#private-networks} + +이더리움 네트워크의 노드가 공개 네트워크(즉, 메인넷 또는 테스트넷)에 연결되지 않은 경우 해당 네트워크는 프라이빗 네트워크입니다. 여기서 개인 (private) 이란 독립적이란 뜻이며 (reserved, isolated) 안전 (protected, secure) 하다는 뜻은 아니다. + +### 개발 네트워크 {#development-networks} + +이더리움 애플리케이션을 개발하려면 이를 배포하기 전 개인 네트워크에 돌려보면서 확인하는 것을 선호할 수 있다. 웹 개발자들이 로컬 환경에서 서버를 생성하여 작업하는 방식처럼 블록체인도 로컬 환경에서 인스턴스를 생성하여 댑을 테스트 할 수 있다. 이는 공개 테스트넷보다 속도 면에서 더 빠르다는 장점이 있다. + +개발 네트워크에 유용한 프로젝트와 개발툴들이 있다. [개발 네트워크](/developers/docs/development-networks/)에 대해 자세히 알아보세요. + +### 컨소시엄 네트워크 {#consortium-networks} + +합의 프로세스는 사전에 설정되고 검증된 노드들에 의해 관리된다. 교육 기관들의 개인 네트워크가 각각 단일 노드를 운영하며 네트워크 내 서명자 기준으로 인해 블록이 검증되는 경우를 예로 들을 수 있다. + +공개 이더리움 네트워크가 인터넷과 비유할 수 있다면, 공동 네트워크는 인트라넷과 비슷하다고 볼 수 있다. + +## 왜 이더리움 테스트넷은 지하철역의 이름을 따서 명명되었을까요? {#why-naming} + +많은 이더리움 테스트넷은 실제 지하철이나 기차역의 이름을 따서 명명되었습니다. 이 명명 전통은 초기에 시작되었으며 기여자들이 거주하거나 일했던 전 세계 도시를 반영합니다. 상징적이고 기억하기 쉬우며 실용적입니다. 테스트넷이 이더리움 메인넷과 분리되어 있는 것처럼, 지하철 노선도 지상 교통과 별도로 운행됩니다. + +### 일반적으로 사용되는 레거시 테스트넷 {#common-and-legacy-testnets} + +- **Sepolia** - 그리스 아테네의 지하철과 연결된 지역입니다. 현재 스마트 계약 및 탈중앙화앱 테스트에 사용됩니다. +- **Hoodi** - 인도 벵갈루루에 있는 Hoodi 지하철역의 이름을 딴 것입니다. 검증자 및 프로토콜 업그레이드 테스트에 사용됩니다. +- **Goerli** _(지원 중단)_ - 독일 베를린의 Görlitzer Bahnhof의 이름을 딴 것입니다. +- **Rinkeby** _(지원 중단)_ - 지하철역이 있는 스톡홀름 교외 지역의 이름을 딴 것입니다. +- **Ropsten** _(지원 중단)_ - 스톡홀름의 한 지역이자 이전의 페리/지하철 터미널을 가리킵니다. +- **Kovan** _(지원 중단)_ - 싱가포르 MRT 역의 이름을 딴 것입니다. +- **Morden** _(지원 중단)_ - 런던 지하철역의 이름을 딴 것입니다. 이더리움 최초의 공개 테스트넷입니다. + +### 기타 특수 테스트넷 {#other-testnets} + +일부 테스트넷은 단기 또는 업그레이드별 테스트를 위해 만들어졌으며 반드시 지하철을 테마로 하지는 않습니다. + +- **Holesky** _(지원 중단)_ - 프라하의 Holešovice 역의 이름을 딴 것입니다. 검증자 테스트에 사용되었으며, 2025년에 지원이 중단되었습니다. +- **Kiln**, **Zhejiang**, **Shandong**, **Prater**, **Pyrmont**, **Olympic** _(모두 지원 중단)_ 및 **Ephemery** - 머지, 상하이 또는 검증자 실험과 같은 업그레이드 시뮬레이션을 위해 특수 제작되었습니다. 일부 이름은 지하철 기반이 아닌 지역적이거나 주제별 이름입니다. + +지하철역 이름을 사용하면 개발자가 숫자 체인 ID에 의존할 필요 없이 테스트넷을 신속하게 식별하고 기억하는 데 도움이 됩니다. 또한 실용적이고, 세계적이며, 인간 중심적인 이더리움의 문화를 반영합니다. + +## 관련 도구 {#related-tools} + +- [Chainlist](https://chainlist.org/) _지갑과 공급자를 적절한 체인 ID 및 네트워크 ID에 연결하기 위한 EVM 네트워크 목록_ +- [EVM 기반 체인](https://github.com/ethereum-lists/chains) _Chainlist를 구동하는 체인 메타데이터의 GitHub 리포지토리_ + +## 더 읽어보기 {#further-reading} + +- [제안: 예측 가능한 이더리움 테스트넷 수명 주기](https://ethereum-magicians.org/t/proposal-predictable-ethereum-testnet-lifecycle/11575/17) +- [이더리움 테스트넷의 진화](https://etherworld.co/2022/08/19/the-evolution-of-ethereum-testnet/) diff --git a/public/content/translations/ko/developers/docs/nodes-and-clients/archive-nodes/index.md b/public/content/translations/ko/developers/docs/nodes-and-clients/archive-nodes/index.md new file mode 100644 index 00000000000..ebb689c01b4 --- /dev/null +++ b/public/content/translations/ko/developers/docs/nodes-and-clients/archive-nodes/index.md @@ -0,0 +1,81 @@ +--- +title: "이더리움 아카이브 노드" +description: "아카이브 노드 개요" +lang: ko +sidebarDepth: 2 +--- + +아카이브 노드는 모든 기록 상태의 아카이브를 구축하기 위해 구성된 이더리움 클라이언트의 인스턴스입니다. 특정한 목적에는 유용한 기능이지만 풀 노드보다 실행하기가 더 까다로울 수 있습니다. + +## 필수 구성 요소 {#prerequisites} + +[이더리움 노드](/developers/docs/nodes-and-clients/), [아키텍처](/developers/docs/nodes-and-clients/node-architecture/), [동기화 전략](/developers/docs/nodes-and-clients/#sync-modes)의 개념과 노드를 [실행](/developers/docs/nodes-and-clients/run-a-node/)하고 [사용](/developers/docs/apis/json-rpc/)하는 방법을 이해해야 합니다. + +## 아카이브 노드란 + +아카이브 노드의 중요성을 이해하기 위해 "상태"의 개념을 명확히 해야 합니다. 이더리움은 트랜잭션 기반 상태 머신이라고 할 수 있습니다. 이는 상태를 변경하는 트랜잭션을 실행하는 계정과 애플리케이션으로 구성됩니다. 각 계정과 계약에 대한 정보가 포함된 글로벌 데이터는 상태라는 트라이 데이터베이스에 저장됩니다. 이는 실행 레이어(EL) 클라이언트에서 처리하며 다음을 포함합니다: + +- 계정 잔액 및 논스 +- 컨트랙트 코드 및 저장소 +- 합의 관련 데이터(예: 스테이킹 예치 계약) + +네트워크와 상호작용하고 새로운 블록 검증 및 생성을 위해서는 크더리움 클라이언트는 가장 최근의 변화(체인 마지막) 와 현재의 상태를 유지해야 합니다. 전체 노드로 구성된 실행 레이어 클라이언트는 네트워크의 최신 상태를 확인하고 따르지만, 체인 재구성을 처리하고 최근 데이터에 빠르게 액세스할 수 있도록 마지막 128개 블록과 관련된 상태와 같이 지난 몇 개의 상태만 캐시합니다. 최근 상태는 모든 클라이언트가 수신 트랜잭션을 검증하고 네트워크를 사용하기 위해 필요한 정보입니다. + +상태는 특정 블록의 순간적인 네트워크 스냅샷으로, 아카이브는 히스토리로 추측할 수 있습니다. + +과거 상태는 네트워크 작동에 필요하지 않으며 클라이언트가 모든 오래된 데이터를 보관하는 것은 불필요하게 중복되므로 안전하게 제거될 수 있습니다. 최근 블록(예: 헤드 이전 128개 블록) 이전에 존재했던 상태는 사실상 폐기됩니다. 전체 노드는 과거 블록체인 데이터(블록 및 트랜잭션)와 요청 시 이전 상태를 재생성하는 데 사용할 수 있는 간헐적인 과거 스냅샷만 보관합니다. 이는 EVM에서 과거 트랜잭션을 재실행하여 수행되는데, 원하는 상태가 가장 가까운 스냅샷에서 멀리 떨어져 있을 경우 계산 집약적일 수 있습니다. + +그러나 이는 전체 노드에서 과거 상태에 액세스하는 것이 많은 계산을 소모한다는 것을 의미합니다. 클라이언트는 모든 과거 트랜잭션을 실행하고 제네시스로부터 하나의 과거 상태를 계산해야 할 수도 있습니다. 아카이브 노드는 가장 최근 상태뿐만 아니라 각 블록 이후에 생성된 모든 과거 상태를 저장하여 이 문제를 해결합니다. 기본적으로 더 큰 디스크 공간 요구 사항과 절충합니다. + +네트워크가 모든 과거 데이터를 보관하고 제공하기 위해 아카이브 노드에 의존하지 않는다는 점에 유의하는 것이 중요합니다. 위에서 언급했듯이, 모든 과거 중간 상태는 전체 노드에서 파생될 수 있습니다. 트랜잭션은 모든 전체 노드에 저장되며(현재 400G 미만) 전체 아카이브를 구축하기 위해 재생될 수 있습니다. + +### 사용 사례 + +트랜잭션 전송, 계약 배포, 합의 확인 등과 같은 일반적인 이더리움 사용은 과거 상태에 대한 액세스를 필요로 하지 않습니다. 사용자는 네트워크와의 표준적인 상호작용을 위해 아카이브 노드를 필요로 하지 않습니다. + +상태 아카이브의 주요 이점은 과거 상태에 대한 쿼리에 빠르게 액세스할 수 있다는 것입니다. 예를 들어, 아카이브 노드는 다음과 같은 결과를 즉시 반환합니다. + +- _계정 0x1337...의 ETH 잔액은 얼마였습니까?_ 블록 15537393에서?_ +- _블록 1920000에서 계약 0x에 있는 토큰 0x의 잔액은 얼마입니까?_ + +위에서 설명한 대로, 전체 노드는 CPU를 사용하고 시간이 걸리는 EVM 실행을 통해 이 데이터를 생성해야 합니다. 아카이브 노드는 디스크에서 액세스하여 응답을 즉시 제공합니다. 이것은 인프라의 특정 부분에 유용한 기능입니다. 예를 들면 다음과 같습니다. + +- 블록 탐색기와 같은 서비스 제공자 +- 연구원 +- 보안 분석가 +- 탈중앙화앱 개발자 +- 감사 및 규정 준수 + +과거 데이터에 대한 액세스를 허용하는 다양한 무료 [서비스](/developers/docs/nodes-and-clients/nodes-as-a-service/)도 있습니다. 아카이브 노드를 실행하는 것이 더 까다롭기 때문에 이 액세스는 대부분 제한적이며 간헐적인 액세스에만 작동합니다. 프로젝트에 과거 데이터에 대한 지속적인 액세스가 필요한 경우 직접 하나를 실행하는 것을 고려해야 합니다. + +## 구현 및 사용법 + +이 맥락에서 아카이브 노드는 상태 데이터베이스를 처리하고 JSON-RPC 엔드포인트를 제공하는 사용자 대면 실행 레이어 클라이언트가 제공하는 데이터를 의미합니다. 구성 옵션, 동기화 시간 및 데이터베이스 크기는 클라이언트에 따라 다를 수 있습니다. 자세한 내용은 클라이언트에서 제공하는 개발문서를 참조하십시오. + +자신만의 아카이브 노드를 시작하기 전에 클라이언트 간의 차이점과 특히 다양한 [하드웨어 요구 사항](/developers/docs/nodes-and-clients/run-a-node/#requirements)에 대해 알아보십시오. 대부분의 클라이언트는 이 기능에 최적화되어 있지 않으며 해당 아카이브에는 12TB 이상의 공간이 필요합니다. 대조적으로, Erigon과 같은 구현은 동일한 데이터를 3TB 미만으로 저장할 수 있으므로 아카이브 노드를 실행하는 가장 효과적인 방법입니다. + +## 권장 사례 + +일반적인 [노드 실행 권장 사항](/developers/docs/nodes-and-clients/run-a-node/) 외에도 아카이브 노드는 하드웨어 및 유지 관리 측면에서 더 까다로울 수 있습니다. Erigon의 [주요 기능](https://github.com/ledgerwatch/erigon#key-features)을 고려할 때 가장 실용적인 접근 방식은 [Erigon](/developers/docs/nodes-and-clients/#erigon) 클라이언트 구현을 사용하는 것입니다. + +### 하드웨어 + +항상 클라이언트의 개발문서에서 특정 모드에 대한 하드웨어 요구 사항을 확인하십시오. +아카이브 노드의 가장 큰 요구 사항은 디스크 공간입니다. 클라이언트에 따라 3TB에서 12TB까지 다양합니다. HDD가 대용량 데이터에 더 나은 솔루션으로 간주될 수 있지만, 동기화하고 체인의 헤드를 지속적으로 업데이트하려면 SSD 드라이브가 필요합니다. [SATA](https://www.cleverfiles.com/help/sata-hard-drive.html) 드라이브로도 충분하지만, 최소한 [TLC](https://blog.synology.com/tlc-vs-qlc-ssds-what-are-the-differences) 이상의 신뢰할 수 있는 품질이어야 합니다. 디스크는 충분한 슬롯이 있는 데스크톱 컴퓨터나 서버에 장착할 수 있습니다. 이러한 전용 장치는 가동 시간이 긴 노드를 실행하는 데 이상적입니다. 노트북에서 실행하는 것도 전적으로 가능하지만 휴대성에는 추가 비용이 따릅니다. + +모든 데이터는 하나의 볼륨에 들어가야 하므로 디스크를 결합해야 합니다(예: [RAID0](https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_0) 또는 LVM). 데이터가 하위 수준 오류 없이 디스크에 올바르게 기록되도록 보장하는 "기록 중 복사(Copy-on-write)"를 지원하므로 [ZFS](https://en.wikipedia.org/wiki/ZFS) 사용도 고려해 볼 가치가 있습니다. + +우발적인 데이터베이스 손상을 방지하고 안정성과 보안을 높이기 위해, 특히 전문적인 환경에서는 시스템이 지원하는 경우 [ECC 메모리](https://en.wikipedia.org/wiki/ECC_memory) 사용을 고려하십시오. RAM 크기는 일반적으로 전체 노드와 동일하게 권장되지만, RAM이 많을수록 동기화 속도를 높이는 데 도움이 될 수 있습니다. + +초기 동기화 중에 아카이브 모드의 클라이언트는 제네시스 이후의 모든 트랜잭션을 실행합니다. 실행 속도는 대부분 CPU에 의해 제한되므로 더 빠른 CPU는 초기 동기화 시간을 단축하는 데 도움이 될 수 있습니다. 평균적인 소비자용 컴퓨터에서 초기 동기화는 최대 한 달이 걸릴 수 있습니다. + +## 더 읽어보기 {#further-reading} + +- [이더리움 전체 노드 vs 아카이브 노드](https://www.quicknode.com/guides/infrastructure/ethereum-full-node-vs-archive-node) - _QuickNode, 2022년 9월_ +- [나만의 이더리움 아카이브 노드 구축하기](https://tjayrush.medium.com/building-your-own-ethereum-archive-node-72c014affc09) - _Thomas Jay Rush, 2021년 8월_ +- [Erigon, Erigon RPC 및 TrueBlocks(스크레이프 및 API)를 서비스로 설정하는 방법](https://magnushansson.xyz/blog_posts/crypto_defi/2022-01-10-Erigon-Trueblocks) _– Magnus Hansson, 2022년 9월 업데이트됨_ + +## 관련 주제 {#related-topics} + +- [노드 및 클라이언트](/developers/docs/nodes-and-clients/) +- [노드 실행하기](/developers/docs/nodes-and-clients/run-a-node/) diff --git a/public/content/translations/ko/developers/docs/nodes-and-clients/bootnodes/index.md b/public/content/translations/ko/developers/docs/nodes-and-clients/bootnodes/index.md new file mode 100644 index 00000000000..fd37491c7cd --- /dev/null +++ b/public/content/translations/ko/developers/docs/nodes-and-clients/bootnodes/index.md @@ -0,0 +1,31 @@ +--- +title: "이더리움 부트노드 소개" +description: "부트노드를 이해하는 데 필요한 기본 정보" +lang: ko +--- + +새 노드가 이더리움 네트워크에 참여할 때 새로운 피어를 찾기 위해 네트워크에 이미 있는 노드에 연결해야 합니다. 이더리움 네트워크로 들어가는 이러한 진입점을 부트노드라고 합니다. 클라이언트에는 일반적으로 부트노드 목록이 하드코딩되어 있습니다. 이러한 부트노드는 일반적으로 이더리움 재단의 데브옵스 팀이나 클라이언트 팀 자체에서 운영합니다. 부트노드는 정적 노드와 같지 않다는 점에 유의하세요. 정적 노드는 반복적으로 호출되는 반면, 부트노드는 연결할 피어가 충분하지 않아 노드가 새로운 연결을 부트스트랩해야 하는 경우에만 호출됩니다. + +## 부트노드에 연결하기 {#connect-to-a-bootnode} + +대부분의 클라이언트에는 부트노드 목록이 내장되어 있지만, 직접 부트노드를 실행하거나 클라이언트의 하드코딩된 목록에 포함되지 않은 부트노드를 사용하고 싶을 수도 있습니다. 이 경우, 클라이언트를 시작할 때 다음과 같이 지정할 수 있습니다(예시는 Geth용이며, 사용 중인 클라이언트의 개발문서를 확인하시기 바랍니다): + +``` +geth --bootnodes "enode://<노드 ID>@:<포트>" +``` + +## 부트노드 실행하기 {#run-a-bootnode} + +부트노드는 NAT([네트워크 주소 변환](https://www.geeksforgeeks.org/network-address-translation-nat/)) 뒤에 있지 않은 풀노드입니다. 모든 풀노드는 공개적으로 사용 가능한 한 부트노드 역할을 할 수 있습니다. + +노드를 시작하면 다른 사용자가 노드에 연결하는 데 사용할 수 있는 공개 식별자인 [enode](/developers/docs/networking-layer/network-addresses/#enode)가 기록되어야 합니다. + +enode는 일반적으로 재시작할 때마다 재생성되므로, 부트노드에 대한 영구 enode를 생성하는 방법은 클라이언트 개발문서를 참조하세요. + +좋은 부트노드가 되려면 연결할 수 있는 최대 피어 수를 늘리는 것이 좋습니다. 많은 피어와 함께 부트노드를 실행하면 대역폭 요구 사항이 크게 증가합니다. + +## 사용 가능한 부트노드 {#available-bootnodes} + +go-ethereum에 내장된 부트노드 목록은 [여기](https://github.com/ethereum/go-ethereum/blob/master/params/bootnodes.go#L23)에서 확인할 수 있습니다. 이 부트노드들은 이더리움 재단과 go-ethereum 팀에 의해 유지 관리됩니다. + +자원봉사자들이 유지 관리하는 다른 부트노드 목록도 있습니다. 항상 하나 이상의 공식 부트노드를 포함하도록 하세요. 그렇지 않으면 이클립스 공격을 받을 수 있습니다. diff --git a/public/content/translations/ko/developers/docs/nodes-and-clients/client-diversity/index.md b/public/content/translations/ko/developers/docs/nodes-and-clients/client-diversity/index.md new file mode 100644 index 00000000000..886610ebb07 --- /dev/null +++ b/public/content/translations/ko/developers/docs/nodes-and-clients/client-diversity/index.md @@ -0,0 +1,132 @@ +--- +title: "클라이언트의 다양성" +description: "이더리움 클라이언트 다양성의 중요성에 대한 고급 설명" +lang: ko +sidebarDepth: 2 +--- + +이더리움 노드의 동작은 클라이언트 소프트웨어가 제어한다. 프로덕션 레벨의 이더리움 클라이언트는 다수 존재하는데 제각각 서로 다른 팀과 언어로 유지되고 있다. 클라이언트는 서로간의 원활한 통신을 보장하며 똑같은 기능과 UX를 가지는 공통 스펙이다. 하지만 노드 간 클라이언트 배포 시에는 해당 네트워크가 최대한으로 강해지게 할 만큼 충분하지는 않다. 이상적인 상황은 유저들이 서로다른 클라이언트들 사이로 엇비슷하게 나뉘어져서 네트워크에 클라이언트 다양성을 최대한으로 이끌어내는 것이다. + +## 필수 구성 요소 {#prerequisites} + +노드와 클라이언트가 무엇인지 아직 이해하지 못했다면 [노드와 클라이언트](/developers/docs/nodes-and-clients/)를 확인해 보세요. [실행](/glossary/#execution-layer) 레이어와 [합의](/glossary/#consensus-layer) 레이어는 용어집에 정의되어 있습니다. + +## 왜 클라이언트는 여러 개 있는가? {#why-multiple-clients} + +복수의 독립적으로 개발되고 유지되는 클라이언트는 클라이언트 다양성이 네트워크를 해킹과 버그에 더 내성이 강하기 때문에 존재한다. 복수의 클라이언트는 이더리움에 국한된 장점이다. - 다른 블록체인은 단일 클라이언트에 의존한다. 하지만 단순히 여러 클라이언트를 사용할 수 있는 것만으로는 충분하지 않으며, 커뮤니티에서 이를 채택하고 총 활성 노드가 여러 클라이언트에 걸쳐 비교적 고르게 분산되어야 합니다. + +## 클라이언트 다양성이 왜 중요한가요? {#client-diversity-importance} + +독립적으로 개발되고 유지되는 다수의 클라이언트는 탈중앙화 네트워크의 상태를 좌지우지 한다. 왜 그런지 알아본다. + +### 버그 {#bugs} + +이더리움 노드의 작은 부분만을 차지하는 개별 클라이언트 내 버그는 전체 네트워크에 미치는 영향이 보다 덜 위협적이다. 다수의 클라이언트에 균등하게 분배된 노드라면 대부분의 클라이언트들이 공통 이슈를 겪게 될 확률이 적다. 따라서 보다 더 안정적인 네트워크가 된다. + +### 공격에 대한 복원력 {#resilience} + +클라이언트 다양성은 해킹 방어에도 도움이 된다. 예를 들어, [특정 클라이언트를 속여](https://twitter.com/vdWijden/status/1437712249926393858) 특정 체인 분기로 유도하는 공격은 성공할 가능성이 낮습니다. 다른 클라이언트는 동일한 방식으로 악용될 가능성이 낮고 정식 체인은 손상되지 않은 상태로 유지되기 때문입니다. 클라이언드 다양성이 크지 않으면 몇몇 클라이언트가 해킹되면 다른 클라이언트들도 취약해진다. 클라이언트 다양성은 네트워크에 대한 악의적인 공격에 대한 중요한 방어 수단임이 이미 입증되었습니다. 예를 들어, 2016년 상하이 서비스 거부 공격은 공격자가 지배적인 클라이언트(Geth)를 속여 블록당 수만 번의 느린 디스크 I/O 작업을 실행하도록 할 수 있었기 때문에 가능했습니다. 반면 이더리움은 클라이언트들이 해당 해킹에 취약점을 보이지 않았기 때문에 피해를 받지 않았으며 Geth 취약점이 보완될 때까지 문제없이 작동하였다. + +### 지분증명 완결성 {#finality} + +이더리움 노드의 33% 이상을 차지하는 합의 클라이언트의 버그는 합의 레이어의 완결을 막을 수 있습니다. 이는 사용자가 어느 시점에서 트랜잭션이 되돌려지거나 변경되지 않을 것이라고 신뢰할 수 없음을 의미합니다. 이것은 이더리움 위에 구축된 많은 앱, 특히 DeFi에 매우 문제가 될 것이다. + + 설상가상으로, 3분의 2의 다수를 차지하는 클라이언트의 심각한 버그는 체인이 잘못 분할되고 완결되는 원인이 될 수 있으며, 이는 많은 검증자들이 유효하지 않은 체인에 갇히게 되는 결과로 이어질 수 있습니다. 만약 그들이 올바른 체인에 다시 가입하기를 원한다면, 이러한 검증자들은 쫒겨나거나 느리고 비용이 많이 드는 자발적인 탈퇴와 재활성화에 직면하게 된다. 슬래싱의 크기는 최대로 대폭 삭감(32 ETH)된 2/3 다수의 과실이 있는 노드의 수에 따라 확장된다. + +비록 발생 확률이 적은 시나리오이지만, 이더리움 에코 시스템은 활성 노드들 간 클라이언트 분산을 더 반반하게 함으로서 위험성을 줄일 수 있다. 이상적으로는 컨센서스 클라이언트가 전체 노드의 33% 이상의 지분을 갖지 않는 것이 좋다. + +### 공동 책임 {#responsibility} + +다수의 클라이언트를 소유하는 것은 인건비가 들지 않기도 하다. 그러나 소규모 개발팀에는 과중된 업무와 책임이 될 수 있다. 클라이언트 다양성이 작을수록 개발자들은 다수 클라이언트를 유지하기 위한 책임이 더 커진다는 의미이다. 이러한 책임을 여러 팀들에 분담하는 것이 이더리움 네트워크 노드와 이용자들에게 더 좋은 일이다. + +## 현재 클라이언트 다양성 {#current-client-diversity} + +### 실행 클라이언트 {#execution-clients-breakdown} + + + +### 합의 클라이언트 {#consensus-clients-breakdown} + + + +이 다이어그램은 오래된 정보일 수 있습니다. 최신 정보는 [ethernodes.org](https://ethernodes.org) 및 [clientdiversity.org](https://clientdiversity.org)를 참조하세요. + +위의 두 파이 차트는 실행 및 합의 레이어에 대한 현재 클라이언트 다양성의 스냅샷을 보여줍니다(2025년 10월 작성 시점 기준). 수년에 걸쳐 클라이언트 다양성이 개선되었으며, 실행 레이어에서는 [Geth](https://geth.ethereum.org/)의 지배력이 감소했습니다. [Nethermind](https://www.nethermind.io/nethermind-client)가 근소한 차이로 2위를, [Besu](https://besu.hyperledger.org/)가 3위, [Erigon](https://github.com/ledgerwatch/erigon)이 4위를 차지했으며, 다른 클라이언트들은 네트워크의 3% 미만을 구성합니다. 합의 레이어에서 가장 일반적으로 사용되는 클라이언트인 [Lighthouse](https://lighthouse.sigmaprime.io/)는 두 번째로 많이 사용되는 클라이언트와 점유율이 비슷합니다. [Prysm](https://prysmaticlabs.com/#projects)과 [Teku](https://consensys.net/knowledge-base/ethereum-2/teku/)가 각각 약 31%와 14%를 차지하며, 다른 클라이언트는 거의 사용되지 않습니다. + +실행 레이어 데이터는 2025년 10월 26일 [supermajority.info](https://supermajority.info/)에서 가져왔습니다. 합의 클라이언트 데이터는 [Michael Sproul](https://github.com/sigp/blockprint)에게서 얻었습니다. 합의 클라이언트 데이터는 합의 레이어 클라이언트가 항상 식별에 사용할 수 있는 명확한 흔적을 가지고 있는 것은 아니기 때문에 얻기가 더 어렵습니다. 데이터는 분류 알고리즘을 사용하여 생성되었으며, 이 알고리즘은 때때로 일부 소수 클라이언트를 혼동하기도 합니다(자세한 내용은 [여기](https://twitter.com/sproulM_/status/1440512518242197516) 참조). 위 다이어그램에서 이러한 모호한 분류는 '또는' 형식의 레이블(예: Nimbus/Teku)로 처리됩니다. 그럼에도 불구하고, 대다수의 네트워크가 Prysm을 운영하고 있는 것은 분명하다. 스냅샷에 불과하지만 다이어그램의 값은 클라이언트 다양성의 현재 상태에 대한 일반적인 느낌을 제공합니다. + +합의 레이어에 대한 최신 클라이언트 다양성 데이터는 이제 [clientdiversity.org](https://clientdiversity.org/)에서 확인할 수 있습니다. + +## 실행 레이어 {#execution-layer} + +지금까지, 클라이언트 다양성에 대한 대화는 주로 합의 계층에 초점을 맞추었다. 그러나 실행 클라이언트인 [Geth](https://geth.ethereum.org)는 현재 모든 노드의 약 85%를 차지합니다. 이 비율은 컨센서스 클라이언트과 같은 이유로 문제가 있습니다. 예를 들어, Geth의 버그가 트랜잭션 처리에 영향을 미치거나 실행 페이로드를 구성하면 합의된 클라이언트가 문제가 있거나 버그가 있는 트랜잭션을 finalizing할 수 있습니다. 따라서 이더리움은 네트워크의 33% 이상을 대표하는 클라이언트가 없는 것이 이상적이며 실행 클라이언트가 더 고르게 분포되어 있어 더 건강할 것이다. + +## 소수 클라이언트 사용하기 {#use-minority-client} + +클라이언트 다양성 문제를 해결하려면 개인 사용자가 소수 클라이언트를 선택하는 것 이상이 필요합니다. 주요 탈중앙화앱 및 거래소와 같은 검증자 풀 및 기관도 클라이언트를 전환해야 합니다. 그러나 모든 사용자는 현재의 불균형을 시정하고 사용 가능한 모든 이더리움 소프트웨어의 사용을 정상화하는 데 자신의 역할을 할 수 있다. The Merge 이후 모든 노드 운영자는 실행 클라이언트와 합의 클라이언트를 실행해야 합니다. 아래에서 제안된 클라이언트 조합을 선택하면 클라이언트의 다양성을 높이는 데 도움이 됩니다. + +### 실행 클라이언트 {#execution-clients} + +- [Besu](https://www.hyperledger.org/use/besu) +- [Nethermind](https://downloads.nethermind.io/) +- [Erigon](https://github.com/ledgerwatch/erigon) +- [Go-Ethereum](https://geth.ethereum.org/) +- [Reth](https://reth.rs/) + +### 합의 클라이언트 {#consensus-clients} + +- [Nimbus](https://nimbus.team/) +- [Lighthouse](https://github.com/sigp/lighthouse) +- [Teku](https://consensys.io/teku) +- [Lodestar](https://github.com/ChainSafe/lodestar) +- [Prysm](https://prysm.offchainlabs.com/docs/) +- [Grandine](https://docs.grandine.io/) + +기술 사용자는 소수 클라이언트를 위한 더 많은 튜토리얼과 문서를 작성하고 노드 운영 피어가 지배적인 클라이언트로부터 벗어나도록 권장함으로써 이 프로세스를 가속화할 수 있습니다. 소수 합의 클라이언트로 전환하기 위한 가이드는 [clientdiversity.org](https://clientdiversity.org/)에서 확인할 수 있습니다. + +## 클라이언트 다양성 대시보드 {#client-diversity-dashboards} + +여러 대시보드는 실행 및 합의 계층에 대한 실시간 클라이언트 다양성 통계를 제공합니다. + +**합의 계층:** + +- [Rated.network](https://www.rated.network/) +- [clientdiversity.org](https://clientdiversity.org/) + +**실행 계층:** + +- [supermajority.info](https://supermajority.info//) +- [Ethernodes](https://ethernodes.org/) + +## 더 읽어보기 {#further-reading} + +- [이더리움 합의 레이어의 클라이언트 다양성](https://mirror.xyz/jmcook.eth/S7ONEka_0RgtKTZ3-dakPmAHQNPvuj15nh0YGKPFriA) +- [이더리움 병합: 다수 클라이언트 실행의 위험성!](https://dankradfeist.de/ethereum/2022/03/24/run-the-majority-client-at-your-own-peril.html) – _Dankrad Fiest, 2022년 3월 24일_ +- [클라이언트 다양성의 중요성](https://our.status.im/the-importance-of-client-diversity/) +- [이더리움 노드 서비스 목록](https://ethereumnodes.com/) +- ["Five Whys"의 클라이언트 다양성 문제](https://notes.ethereum.org/@afhGjrKfTKmksTOtqhB9RQ/BJGj7uh08) +- [이더리움 다양성 및 해결 방법 (YouTube)](https://www.youtube.com/watch?v=1hZgCaiqwfU) +- [clientdiversity.org](https://clientdiversity.org/) + +## 관련 주제 {#related-topics} + +- [이더리움 노드 운영하기](/run-a-node/) +- [노드 및 클라이언트](/developers/docs/nodes-and-clients/) diff --git a/public/content/translations/ko/developers/docs/nodes-and-clients/index.md b/public/content/translations/ko/developers/docs/nodes-and-clients/index.md new file mode 100644 index 00000000000..ff25e490af5 --- /dev/null +++ b/public/content/translations/ko/developers/docs/nodes-and-clients/index.md @@ -0,0 +1,319 @@ +--- +title: Nodes and clients +description: "이더리움 노드와 클라이언트 소프트웨어에 대한 개요. 노드를 설정하는 방법과 이용해야하는 이유에 대한 추가적인 설명" +lang: ko +sidebarDepth: 2 +--- + +이더리움은 블럭 및 트랜잭션 데이터 검증 소프트웨어를 실행하는 컴퓨터 (노드) 들의 분산 네트워크입니다. 이 소프트웨어는 컴퓨터에서 실행되어 이더리움 노드로 변환되어야 함 노드를 구성하려면 두 개의 별도 소프트웨어(‘클라이언트’로 알려짐)가 필요함 + +## 필수 구성 요소 {#prerequisites} + +자신만의 이더리움 클라이언트를 실행하고 더 깊이 알아보기 전에, P2P(peer-to-peer) 네트워크 개념과 [EVM 기본 사항](/developers/docs/evm/)을 이해해야 합니다. [이더리움 소개](/developers/docs/intro-to-ethereum/)를 살펴보세요. + +노드라는 주제가 처음이시라면, 사용자 친화적인 소개 문서인 [이더리움 노드 실행하기](/run-a-node)를 먼저 확인해 보시는 것을 추천합니다. + +## 노드랑 클라이언트가 무엇인가요? {#what-are-nodes-and-clients} + +"노드"는 이더리움 클라이언트 소프트웨어를 실행하여 네트워크를 형성하는 다른 컴퓨터와 연결된 이더리움 클라이언트 소프트웨어의 인스턴스를 의미함 클라이언트는 이더리움 데이터를 프로토콜 규칙에 따라 검증하고 네트워크의 보안을 유지하는 역할을 함 노드는 두 개의 클라이언트를 실행해야 함: 합의 클라이언트와 실행 클라이언트 + +- 실행 클라이언트(실행 엔진, EL 클라이언트 또는 이전의 Eth1 클라이언트라고도 함)는 네트워크에서 브로드캐스트되는 새로운 트랜잭션을 청취하고 EVM에서 이를 실행하며 최신 상태 및 모든 현재 이더리움 데이터베이스를 보유함 +- 합의 클라이언트(비콘 노드, CL 클라이언트 또는 이전의 Eth2 클라이언트로도 알려짐)는 실행 클라이언트에서 검증된 데이터를 기반으로 네트워크가 합의에 도달할 수 있도록 하는 지분 증명 합의 알고리즘을 구현함 또한 합의 클라이언트에 추가할 수 있는 '검증자'라는 세 번째 소프트웨어가 있으며, 이를 통해 노드가 네트워크 보안에 참여할 수 있음 + +이러한 클라이언트는 함께 작동하여 이더리움 체인의 헤드를 추적하고 사용자가 이더리움 네트워크와 상호작용할 수 있도록 함 여러 소프트웨어가 함께 작동하는 모듈식 설계를 [캡슐화된 복잡성](https://vitalik.eth.limo/general/2022/02/28/complexity.html)이라고 합니다. 이 접근 방식 덕분에 [병합](/roadmap/merge)을 원활하게 실행할 수 있었으며, 클라이언트 소프트웨어의 유지보수 및 개발이 용이해졌고, 예를 들어 [레이어 2 생태계](/layer-2/)에서 개별 클라이언트를 재사용할 수 있게 되었습니다. + +![실행 및 합의 클라이언트 결합](./eth1eth2client.png) +결합된 실행 및 합의 클라이언트의 단순화된 다이어그램입니다. + +### 클라이언트 다양성 {#client-diversity} + +[실행 클라이언트](/developers/docs/nodes-and-clients/#execution-clients)와 [합의 클라이언트](/developers/docs/nodes-and-clients/#consensus-clients)는 모두 여러 팀에서 개발한 다양한 프로그래밍 언어로 존재합니다. + +다양한 클라이언트 구현은 단일 코드베이스에 대한 의존성을 줄여 네트워크를 더욱 강하게 만듭니다. 이상적인 목표는 어느 클라이언트도 네트워크를 지배하지 않으면서 다양성을 달성하여 잠재적인 단일 장애점을 제거하는 것입니다. +다양한 언어는 더 넓은 개발자 커뮤니티를 초대하고, 개발자가 선호하는 언어로 통합을 만들 수 있게 합니다. + +[클라이언트 다양성](/developers/docs/nodes-and-clients/client-diversity/)에 대해 자세히 알아보세요. + +이러한 구현들이 공통으로 가지고 있는 점은 모두 단일 사양을 따른다는 것입니다. 사양은 이더리움 네트워크와 블록체인이 작동하는 방식을 규정합니다. 모든 기술적 세부 사항이 정의되어 있으며, 사양은 다음에서 찾을 수 있습니다: + +- 원래는 [이더리움 옐로 페이퍼](https://ethereum.github.io/yellowpaper/paper.pdf) +- [실행 사양](https://github.com/ethereum/execution-specs/) +- [합의 사양](https://github.com/ethereum/consensus-specs) +- 다양한 [네트워크 업그레이드](/ethereum-forks/)에서 구현된 [EIP](https://eips.ethereum.org/) + +### 네트워크의 노드 추적 {#network-overview} + +여러 추적기는 이더리움 네트워크의 노드를 실시간으로 개요를 제공합니다. 탈중앙화 네트워크의 특성상 이러한 크롤러는 네트워크의 제한된 뷰만 제공할 수 있으며, 서로 다른 결과를 보고할 수 있음을 유의하십시오. + +- Etherscan의 [노드 맵](https://etherscan.io/nodetracker) +- Bitfly의 [Ethernodes](https://ethernodes.org/) +- Chainsafe의 [Nodewatch](https://www.nodewatch.io/), 합의 노드 크롤링 +- [Monitoreth](https://monitoreth.io/) - MigaLabs 제공, 분산 네트워크 모니터링 도구 +- [주간 네트워크 상태 보고서](https://probelab.io) - ProbeLab 제공, [Nebula 크롤러](https://github.com/dennis-tra/nebula) 및 기타 도구 사용 + +## 노드 유형 {#node-types} + +자신만의 [노드를 실행](/developers/docs/nodes-and-clients/run-a-node/)하려면, 데이터를 다르게 소비하는 다양한 유형의 노드가 있다는 것을 이해해야 합니다. 실제로 클라이언트는 세 가지 유형의 노드를 실행할 수 있습니다: 라이트, 풀, 아카이브. 또한 더 빠른 동기화를 가능하게 하는 다양한 동기화 전략이 있습니다. 동기화는 이더리움 상태에 대한 최신 정보를 얼마나 빨리 얻을 수 있는지와 관련이 있습니다. + +### 전체 노드 {#full-node} + +풀 노드는 블록체인의 블록별 검증을 수행하며, 각 블록의 블록 본문과 상태 데이터를 다운로드하고 검증합니다. 다양한 클래스의 풀 노드가 있으며, 일부는 최초 블록부터 시작하여 블록체인의 전체 기록을 검증합니다. 다른 노드들은 유효하다고 신뢰하는 더 최신 블록에서 검증을 시작합니다(예: Geth의 '스냅 동기화'). 검증이 어디에서 시작되든 풀 노드는 비교적 최근의 데이터(일반적으로 최신 128개 블록)를 로컬에 저장하며, 오래된 데이터는 디스크 공간을 절약하기 위해 삭제됩니다. 필요할 때 오래된 데이터는 다시 생성될 수 있습니다. + +- 풀 블록체인 데이터를 저장합니다(하지만 주기적으로 가지치기되므로 풀 노드는 모든 상태 데이터를 저장하지 않습니다). +- 블록 검증에 참여하며 모든 블록과 상태를 검증합니다. +- 모든 상태는 로컬 저장소에서 검색하거나 '스냅샷'에서 다시 생성할 수 있습니다. +- 네트워크에 데이터를 요청하면 제공합니다. + +### 아카이브 노드 {#archive-node} + +아카이브 노드는 모든 블록을 검증하고 다운로드한 데이터를 절대 삭제하지 않는 풀 노드입니다. + +- 풀 노드에 저장된 모든 것을 보관하고 역사적 상태의 아카이브를 작성합니다. 블록 #4,000,000에서 계정 잔액과 같은 것을 조회하거나, 추적을 사용하여 트랜잭션 세트를 검증하지 않고 간단하고 안정적으로 테스트하려는 경우에 필요합니다. +- 이 데이터는 테라바이트 단위로 나타나기 때문에 일반 사용자에게는 덜 매력적일 수 있지만, 블록 탐색기, 지갑 공급업체, 체인 분석 서비스와 같은 서비스에 유용할 수 있습니다. + +아카이브가 아닌 모드로 클라이언트를 동기화하면 가지치기된 블록체인 데이터가 발생합니다. 이는 모든 역사적 상태의 아카이브가 없다는 것을 의미하지만, 풀 노드는 필요할 때 이러한 상태를 구축할 수 있습니다. + +[아카이브 노드](/developers/docs/nodes-and-clients/archive-nodes)에 대해 자세히 알아보세요. + +### 라이트 노드 {#light-node} + +라이트 노드는 모든 블록을 다운로드하는 대신 블록 헤더만 다운로드합니다. 이 헤더는 블록 내용에 대한 요약 정보를 포함하고 있습니다. 라이트 노드가 필요한 다른 정보는 풀 노드에서 요청됩니다. 라이트 노드는 받은 데이터를 블록 헤더의 상태 루트와 대조하여 독립적으로 검증할 수 있습니다. 라이트 노드는 강력한 하드웨어나 높은 대역폭 없이도 이더리움 네트워크에 참여할 수 있게 합니다. 결국, 라이트 노드는 모바일 전화기나 임베디드 장치에서 실행될 수 있습니다. 라이트 노드는 합의에 참여하지 않지만(즉, 검증자가 될 수 없음), 전체 노드와 동일한 기능 및 보안 보장으로 이더리움 블록체인에 액세스할 수 있습니다. + +라이트 클라이언트는 이더리움의 활성 개발 분야이며, 조만간 합의 계층 및 실행 계층용 새로운 라이트 클라이언트를 볼 수 있을 것으로 기대됩니다. +[가십 네트워크](https://www.ethportal.net/)를 통해 라이트 클라이언트 데이터를 제공하는 잠재적 경로도 있습니다. 가십 네트워크가 전체 노드가 요청을 처리할 필요 없이 라이트 노드 네트워크를 지원할 수 있기 때문에 이점이 있습니다. + +이더리움은 아직 많은 수의 라이트 노드를 지원하지 않지만, 라이트 노드 지원은 가까운 미래에 빠르게 발전할 것으로 예상됩니다. 특히 [Nimbus](https://nimbus.team/), [Helios](https://github.com/a16z/helios), [LodeStar](https://lodestar.chainsafe.io/)와 같은 클라이언트는 현재 라이트 노드에 크게 집중하고 있습니다. + +## 왜 이더리움 노드를 실행해야 합니까? {#why-should-i-run-an-ethereum-node} + +노드를 실행하면 네트워크를 더 강력하고 분산화된 상태로 유지하는 데 도움을 주면서 이더리움을 직접, 신뢰 없이, 비공개로 사용할 수 있습니다. + +### 사용자에게 주는 이점 {#benefits-to-you} + +자신의 노드를 실행하면 이더리움을 비공개, 자급자족 방식으로 신뢰 없이 사용할 수 있습니다. 네트워크를 신뢰할 필요가 없으며, 자신의 클라이언트를 사용해 데이터를 직접 검증할 수 있습니다. "신뢰하지 말고, 검증하라"는 블록체인에서 인기 있는 모토입니다. + +- 귀하의 노드는 모든 거래와 블록을 합의 규칙에 따라 스스로 검증합니다. 즉, 네트워크 내 다른 노드를 신뢰할 필요가 없으며, 완전히 의존하지 않아도 됩니다. +- 자신의 노드와 함께 이더리움 지갑을 사용할 수 있습니다. 중개인에게 주소와 잔액을 유출하지 않고 더 안전하고 비공개로 dapp을 사용할 수 있습니다. 모든 것은 자신의 클라이언트로 확인할 수 있습니다. [MetaMask](https://metamask.io), [Frame](https://frame.sh/) 및 [기타 여러 지갑](/wallets/find-wallet/)은 사용자의 노드를 사용할 수 있도록 RPC 가져오기 기능을 제공합니다. +- 이더리움의 데이터를 필요로 하는 서비스(예: 비콘 체인 검증자, 레이어 2 소프트웨어, 블록 탐색기, 결제 처리기 등)를 실행하고 자체 호스팅할 수 있습니다. 이더리움의 데이터를 필요로 하는 서비스(예: 비콘 체인 검증자, 레이어 2 소프트웨어, 블록 탐색기, 결제 처리기 등)를 실행하고 자체 호스팅할 수 있습니다. +- 자신만의 맞춤형 [RPC 엔드포인트](/developers/docs/apis/json-rpc/)를 제공할 수 있습니다. 커뮤니티에 이러한 엔드포인트를 공개하여 대형 중앙 집중식 제공업체를 피하는 데 도움을 줄 수 있습니다. +- 프로세스 간 통신(IPC)을 사용하여 노드에 연결하거나 노드를 다시 작성하여 프로그램을 플러그인으로 로드할 수 있습니다. 이는 낮은 지연 시간을 보장하며, 예를 들어 web3 라이브러리를 사용하여 많은 양의 데이터를 처리하거나 가능한 한 빨리 트랜잭션을 교체해야 할 때(즉, 프론트러닝) 많은 도움이 됩니다. +- ETH를 직접 스테이킹하여 네트워크를 보호하고 보상을 받을 수 있습니다. 시작하려면 [단독 스테이킹](/staking/solo/)을 참조하세요. + +![애플리케이션과 노드를 통해 이더리움에 액세스하는 방법](./nodes.png) + +### 네트워크 이점 {#network-benefits} + +다양한 노드 세트는 이더리움의 건강, 보안 및 운영 복원력에 중요합니다. + +- 전체 노드는 합의 규칙을 시행하므로 규칙을 따르지 않는 블록을 받아들이지 않습니다. 이것은 네트워크의 추가 보안을 제공하는데, 만약 모든 노드가 전체 검증을 하지 않는 라이트 노드였다면 검증자들이 네트워크를 공격할 수 있었을 것입니다. +- [지분 증명](/developers/docs/consensus-mechanisms/pos/#what-is-pos)의 암호경제학적 방어를 극복하는 공격이 발생할 경우, 전체 노드가 정직한 체인을 따르기로 선택하여 사회적 복구를 수행할 수 있습니다. +- 네트워크의 노드가 많을수록 네트워크가 더 다양하고 강력해지며, 이는 검열에 저항하고 신뢰할 수 있는 시스템을 가능하게 하는 궁극적인 목표인 탈중앙화로 이어집니다. +- 전체 노드는 이더리움에 의존하는 경량 클라이언트에게 블록체인 데이터를 제공합니다. 라이트 노드는 전체 블록체인을 저장하지 않고, 대신 [블록 헤더의 상태 루트](/developers/docs/blocks/#block-anatomy)를 통해 데이터를 검증합니다. 필요한 경우 전체 노드에서 추가 정보를 요청할 수 있습니다. + +전체 노드를 실행하면, 검증자를 실행하지 않더라도 이더리움 네트워크 전체가 혜택을 받습니다. + +## 자신의 노드 실행 {#running-your-own-node} + +자신만의 이더리움 클라이언트를 실행해 보고 싶나요? + +초보자를 위한 소개는 [노드 실행하기](/run-a-node) 페이지에서 자세히 알아보세요. + +기술적인 사용자라면, [자신만의 노드를 가동하는 방법](/developers/docs/nodes-and-clients/run-a-node/)에 대한 자세한 내용과 옵션을 살펴보세요. + +## 대안 {#alternatives} + +자신만의 노드를 설정하는 데 시간과 자원이 소요될 수 있지만, 항상 자신의 인스턴스를 실행할 필요는 없습니다. 이 경우 제3자 API 제공업체를 사용할 수 있습니다. 이러한 서비스 사용에 대한 개요는 [서비스형 노드](/developers/docs/nodes-and-clients/nodes-as-a-service/)를 확인하세요. + +커뮤니티 내에서 공용 API를 사용하는 이더리움 노드를 실행하는 사람이 있다면, 커스텀 RPC를 통해 지갑을 커뮤니티 노드에 연결하고 무작위로 신뢰된 제3자보다 더 많은 개인 정보를 확보할 수 있습니다. + +반면에 클라이언트를 실행하면 필요할 때 친구들과 공유할 수 있습니다. + +## 실행 클라이언트 {#execution-clients} + +이더리움 커뮤니티는 여러 오픈 소스 실행 클라이언트(이전에는 'Eth1 클라이언트' 또는 '이더리움 클라이언트'로 알려짐)를 유지 관리하며, 다양한 프로그래밍 언어를 사용해 다양한 팀이 개발합니다. 이를 통해 네트워크는 더욱 강력해지고 [다양해집니다](/developers/docs/nodes-and-clients/client-diversity/). 궁극적인 목표는 어떤 클라이언트도 지배하지 않도록 다양성을 달성하여 단일 장애 지점을 줄이는 것입니다. + +이 표는 다양한 클라이언트를 요약합니다. 모든 클라이언트는 [클라이언트 테스트](https://github.com/ethereum/tests)를 통과하며 네트워크 업그레이드에 맞춰 최신 상태를 유지하기 위해 활발하게 유지 관리됩니다. + +| 클라이언트 | 언어 | 운영 체제 | 네트워크 | 동기화 전략 | 상태 가지치기 | +| ----------------------------------------------------------------------------------------- | ------------------------ | --------------------- | --------------------- | ----------------------------------------------------------------------- | ---------- | +| [Geth](https://geth.ethereum.org/) | Go | Linux, Windows, macOS | 메인넷, Sepolia, Holesky | [Snap](#snap-sync), [Full](#full-sync) | 아카이브, 가지치기 | +| [Nethermind](https://www.nethermind.io/) | C#, .NET | Linux, Windows, macOS | 메인넷, Sepolia, Holesky | [Snap](#snap-sync)(제공 안 함), Fast, [Full](#full-sync) | 아카이브, 가지치기 | +| [Besu](https://besu.hyperledger.org/en/stable/) | 자바 | Linux, Windows, macOS | 메인넷, Sepolia, Holesky | [Snap](#snap-sync), [Fast](#fast-sync), [Full](#full-sync) | 아카이브, 가지치기 | +| [Erigon](https://github.com/ledgerwatch/erigon) | Go | Linux, Windows, macOS | 메인넷, Sepolia, Holesky | [Full](#full-sync) | 아카이브, 가지치기 | +| [Reth](https://reth.rs/) | 러스트 | Linux, Windows, macOS | 메인넷, Sepolia, Holesky | [Full](#full-sync) | 아카이브, 가지치기 | +| [EthereumJS](https://github.com/ethereumjs/ethereumjs-monorepo) _(베타)_ | 타입스크립트 | Linux, Windows, macOS | Sepolia, Holesky | [Full](#full-sync) | 삭제된 데이터 | + +지원되는 네트워크에 대한 자세한 내용은 [이더리움 네트워크](/developers/docs/networks/)를 참조하세요. + +각 클라이언트는 고유한 사용 사례와 장점을 가지고 있으며, 개인의 선호에 따라 선택해야 합니다. 다양성은 서로 다른 기능과 사용자층에 집중할 수 있는 구현을 가능하게 합니다. 기능, 지원, 프로그래밍 언어 또는 라이선스를 기반으로 클라이언트를 선택할 수 있습니다. + +### Besu {#besu} + +Hyperledger Besu는 공개 및 허가된 네트워크를 위한 엔터프라이즈급 이더리움 클라이언트입니다. 이 클라이언트는 추적에서 GraphQL까지 이더리움 메인넷의 모든 기능을 실행하며, ConsenSys의 개방형 커뮤니티 채널 및 기업을 위한 상업적 SLA를 통해 지원됩니다. 자바로 작성되었으며, Apache 2.0 라이선스를 따릅니다. + +Besu의 광범위한 [문서](https://besu.hyperledger.org/en/stable/)는 기능 및 설정에 대한 모든 세부 정보를 안내합니다. + +### Erigon {#erigon} + +Erigon은 이전에는 Turbo-Geth로 알려졌으며, 디스크 공간 효율성과 속도를 중시하는 Go Ethereum의 포크로 시작되었습니다. Erigon은 완전히 재구성된 이더리움 구현체로, 현재는 Go로 작성되었지만 다른 언어로의 구현이 개발 중에 있습니다. Erigon의 목표는 더 빠르고 모듈화되고 최적화된 이더리움 구현을 제공하는 것입니다. 이 클라이언트는 약 2TB의 디스크 공간을 사용하여 3일 이내에 전체 아카이브 노드 동기화를 수행할 수 있습니다. + +### Go Ethereum {#geth} + +Go Ethereum(Geth로 약칭)은 이더리움 프로토콜의 최초 구현 중 하나입니다. 현재는 가장 널리 사용되는 클라이언트로, 가장 큰 사용자 기반과 다양한 도구를 제공합니다. Go로 작성되었으며, 완전한 오픈 소스이며, GNU LGPL v3 라이선스를 따릅니다. + +Geth에 대한 자세한 내용은 해당 [문서](https://geth.ethereum.org/docs/)를 참조하세요. + +### Nethermind {#nethermind} + +Nethermind는 C# .NET 기술 스택을 사용하여 개발된 이더리움 구현체로, LGPL-3.0 라이선스를 따르며 ARM을 포함한 주요 플랫폼에서 실행됩니다. 최고의 성능을 제공합니다: + +- 최적화된 가상 머신 +- 상태 접근 +- 최적화된 가상 머신과 상태 접근, 네트워킹, Prometheus/Grafana 대시보드, seq 엔터프라이즈 로깅 지원, JSON-RPC 추적 및 분석 플러그인과 같은 풍부한 기능을 제공합니다. + +Nethermind는 또한 [자세한 문서](https://docs.nethermind.io), 강력한 개발자 지원, 온라인 커뮤니티 및 프리미엄 사용자를 위한 연중무휴 지원을 제공합니다. + +### Reth {#reth} + +Reth(러스트 이더리움의 약칭)는 사용자 친화적이고 모듈화되며 빠르고 효율적인 이더리움 전체 노드 구현체입니다. Reth는 원래 Paradigm에 의해 개발되었으며, Apache와 MIT 라이선스를 따릅니다. + +Reth는 스테이킹이나 고가용성 서비스 같은 미션 크리티컬한 환경에서 사용할 수 있는 프로덕션 준비가 완료된 상태입니다. 높은 성능과 넓은 이익률이 요구되는 경우, 예를 들어 RPC, MEV, 인덱싱, 시뮬레이션 및 P2P 활동에서 뛰어난 성능을 발휘합니다. + +[Reth Book](https://reth.rs/) 또는 [Reth GitHub 저장소](https://github.com/paradigmxyz/reth?tab=readme-ov-file#reth)를 확인하여 자세히 알아보세요. + +### 개발 중 {#execution-in-development} + +이 클라이언트들은 아직 개발 초기 단계에 있으며, 프로덕션 사용에 권장되지 않습니다. + +#### EthereumJS {#ethereumjs} + +EthereumJS 실행 클라이언트(EthereumJS)는 TypeScript로 작성되었으며, 블록, 트랜잭션 및 머클-패트리샤 트리 클래스와 같은 핵심 이더리움 원시 패키지 및 이더리움 가상 머신(EVM) 구현, 블록체인 클래스, DevP2P 네트워킹 스택을 포함한 핵심 클라이언트 구성 요소로 구성되어 있습니다. + +[문서](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master)를 읽고 자세히 알아보세요. + +## 합의 클라이언트 {#consensus-clients} + +[합의 업그레이드](/roadmap/beacon-chain/)를 지원하는 여러 합의 클라이언트(이전에는 'Eth2' 클라이언트라고 알려짐)가 있습니다. 이들은 포크 선택 알고리즘, 증명 처리, [지분 증명](/developers/docs/consensus-mechanisms/pos) 보상 및 페널티 관리를 포함한 모든 합의 관련 로직을 담당합니다. + +| 클라이언트 | 언어 | 운영 체제 | 네트워크 | +| ------------------------------------------------------------- | ------ | --------------------- | ------------------------------------------ | +| [Lighthouse](https://lighthouse.sigmaprime.io/) | 러스트 | Linux, Windows, macOS | 비콘 체인, Holesky, Pyrmont, Sepolia 등 | +| [Lodestar](https://lodestar.chainsafe.io/) | 타입스크립트 | Linux, Windows, macOS | 비콘 체인, Holesky, Sepolia 등 | +| [Nimbus](https://nimbus.team/) | Nim | Linux, Windows, macOS | 비콘 체인, Holesky, Sepolia 등 | +| [Prysm](https://prysm.offchainlabs.com/docs/) | Go | Linux, Windows, macOS | 비콘 체인, Gnosis, Holesky, Pyrmont, Sepolia 등 | +| [Teku](https://consensys.net/knowledge-base/ethereum-2/teku/) | 자바 | Linux, Windows, macOS | 비콘 체인, Gnosis, Holesky, Sepolia 등 | +| [Grandine](https://docs.grandine.io/) | 러스트 | Linux, Windows, macOS | 비콘 체인, Holesky, Sepolia 등 | + +### Lighthouse {#lighthouse} + +Lighthouse는 Rust로 작성된 합의 클라이언트 구현체이며 Apache-2.0 라이선스 하에 있습니다. 이 클라이언트는 Sigma Prime에서 유지 관리되며 비콘 체인 시작 이후로 안정적이고 생산 준비가 완료된 상태입니다. 여러 기업, 스테이킹 풀, 개인 사용자들이 이 클라이언트를 신뢰하고 있습니다. 이 클라이언트는 보안성, 성능, 그리고 데스크탑 PC부터 정교한 자동 배포에 이르기까지 다양한 환경에서의 상호 운용성을 목표로 하고 있습니다. + +문서는 [Lighthouse Book](https://lighthouse-book.sigmaprime.io/)에서 찾을 수 있습니다. + +### Lodestar {#lodestar} + +Lodestar는 Typescript로 작성된 LGPL-3.0 라이선스 하의 생산 준비가 완료된 합의 클라이언트 구현체입니다. 이 클라이언트는 ChainSafe Systems에서 유지 관리되며 솔로 스테이커, 개발자 및 연구자를 위한 최신 합의 클라이언트 중 하나입니다. Lodestar는 이더리움 프로토콜의 JavaScript 구현을 바탕으로 비콘 노드와 검증자 클라이언트로 구성되어 있습니다. Lodestar는 라이트 클라이언트를 통해 이더리움 사용성을 개선하고 더 큰 개발자 그룹에 대한 접근성을 확장하며 생태계 다양성에 기여하는 것을 목표로 합니다. + +자세한 정보는 [Lodestar 웹사이트](https://lodestar.chainsafe.io/)에서 찾을 수 있습니다. + +### Nimbus {#nimbus} + +Nimbus는 Nim으로 작성된 Apache-2.0 라이선스 하의 합의 클라이언트 구현체입니다. 이 클라이언트는 솔로 스테이커와 스테이킹 풀에서 사용되는 생산 준비가 완료된 클라이언트입니다. Nimbus는 리소스 효율성을 위해 설계되어 리소스가 제한된 장치 및 기업 인프라에서 안정성이나 보상 성능을 저해하지 않으면서도 쉽게 실행할 수 있습니다. 가벼운 리소스 풋프린트는 네트워크가 스트레스를 받을 때 클라이언트의 안전 여유를 더 크게 만듭니다. + +[Nimbus 문서](https://nimbus.guide/)에서 자세히 알아보세요. + +### Prysm {#prysm} + +Prysm은 Go로 작성된 GPL-3.0 라이선스 하의 모든 기능을 갖춘 오픈 소스 합의 클라이언트입니다. 이 클라이언트는 선택적 웹앱 UI를 제공하며 사용자 경험, 문서화, 구성 가능성을 우선시합니다. 이는 가정 내 스테이킹 사용자와 기관 사용자를 위해 설계되었습니다. + +자세히 알아보려면 [Prysm 문서](https://prysm.offchainlabs.com/docs/)를 방문하세요. + +### Teku {#teku} + +Teku는 최초의 비콘 체인 제네시스 클라이언트 중 하나입니다. 보안성, 강건성, 안정성, 사용성, 성능 등의 일반적인 목표와 함께, Teku는 다양한 합의 클라이언트 표준을 완전히 준수하는 것을 목표로 합니다. + +Teku는 매우 유연한 배포 옵션을 제공합니다. 비콘 노드와 검증자 클라이언트는 단일 프로세스로 함께 실행될 수 있어 솔로 스테이커에게 매우 편리하며, 또는 더 정교한 스테이킹 작업을 위해 별도로 실행할 수 있습니다. 또한 Teku는 서명 키 보안 및 슬래싱 방지를 위해 [Web3Signer](https://github.com/ConsenSys/web3signer/)와 완벽하게 상호 운용됩니다. + +Teku는 Java로 작성되었으며 Apache 2.0 라이선스를 따릅니다. 이 클라이언트는 Besu와 Web3Signer를 책임지는 ConsenSys의 프로토콜 팀에서 개발되었습니다. [Teku 문서](https://docs.teku.consensys.net/en/latest/)에서 자세히 알아보세요. + +### Grandine {#grandine} + +Grandine은 Rust로 작성된 합의 클라이언트 구현체로, GPL-3.0 라이선스를 따릅니다. Grandine Core Team에 의해 유지되며, 빠르고 고성능이며 경량입니다. 이 클라이언트는 Raspberry Pi와 같은 저자원 장치에서 실행되는 솔로 스테이커부터 수만 개의 검증자를 실행하는 대규모 기관 스테이커에 이르기까지 다양한 스테이커에 적합합니다. + +문서는 [Grandine Book](https://docs.grandine.io/)에서 찾을 수 있습니다. + +## 동기화 모드 {#sync-modes} + +네트워크의 최신 데이터를 따르고 확인하기 위해 이더리움 클라이언트는 최신 네트워크 상태와 동기화되어야 합니다. 이것은 피어로부터 데이터를 다운로드하고 암호적으로 무결성을 확인하며 로컬 블록체인 데이터베이스를 구축하여 수행됩니다. + +동기화 모드는 이러한 과정을 다양한 트레이드 오프와 함께 나타냅니다. 클라이언트는 동기화 알고리즘 구현에서도 차이가 있습니다. 구체적인 구현에 대해서는 선택한 클라이언트의 공식 문서를 항상 참조하십시오. + +### 실행 레이어 동기화 모드 {#execution-layer-sync-modes} + +실행 레이어는 다양한 사용 사례에 맞게 블록체인의 세계 상태를 재실행하는 것부터 신뢰할 수 있는 체크포인트에서 체인의 팁과만 동기화하는 것까지 다양한 모드에서 실행될 수 있습니다. + +#### 전체 동기화 {#full-sync} + +전체 동기화는 모든 블록(헤더 및 블록 본문 포함)을 다운로드하고 제네시스부터 모든 블록을 실행하여 블록체인의 상태를 점진적으로 재생성합니다. + +- 모든 트랜잭션을 확인하여 신뢰를 최소화하고 최고 수준의 보안을 제공합니다. +- 트랜잭션 수가 증가함에 따라 모든 트랜잭션을 처리하는 데 며칠에서 몇 주가 걸릴 수 있습니다. + +[아카이브 노드](#archive-node)는 전체 동기화를 수행하여 모든 블록의 모든 트랜잭션에 의해 발생한 상태 변경의 전체 기록을 구축(및 유지)합니다. + +#### 빠른 동기화 {#fast-sync} + +전체 동기화와 마찬가지로, 빠른 동기화는 모든 블록(헤더, 트랜잭션 및 영수증 포함)을 다운로드합니다. 그러나 과거의 트랜잭션을 재처리하는 대신 빠른 동기화는 최근 헤드에 도달할 때까지 영수증을 신뢰하고, 그 후에는 블록을 가져오고 처리하여 전체 노드를 제공합니다. + +- 빠른 동기화 전략. +- 처리 수요를 줄이고 대역폭 사용을 선호합니다. + +#### 스냅 동기화 {#snap-sync} + +스냅 동기화도 체인을 블록별로 검증합니다. 하지만 스냅 동기화는 제네시스 블록에서 시작하지 않고, 진짜 블록체인의 일부로 확인된 '신뢰할 수 있는' 최신 체크포인트에서 시작합니다. 노드는 주기적으로 체크포인트를 저장하고 일정 연령 이상의 데이터를 삭제합니다. 이 스냅샷은 필요에 따라 상태 데이터를 재생성하는 데 사용되며, 데이터를 영구적으로 저장하지 않습니다. + +- 현재 이더리움 메인넷에서 기본 설정된 가장 빠른 동기화 전략. +- 보안성을 희생하지 않고 디스크 사용량과 네트워크 대역폭을 많이 절약합니다. + +[스냅 동기화에 대한 추가 정보](https://github.com/ethereum/devp2p/blob/master/caps/snap.md). + +#### 라이트 동기화 {#light-sync} + +경량 클라이언트 모드는 모든 블록 헤더, 블록 데이터를 다운로드하고 일부를 무작위로 검증합니다. 신뢰할 수 있는 체크포인트에서 체인의 팁만 동기화합니다. + +- 개발자와 합의 메커니즘에 대한 신뢰를 바탕으로 최신 상태만 가져옵니다. +- 몇 분 안에 현재 네트워크 상태로 클라이언트를 사용할 수 있습니다. + +**참고** 라이트 동기화는 아직 지분 증명 이더리움에서 작동하지 않습니다. 새로운 버전의 라이트 동기화가 곧 출시될 예정입니다! + +[라이트 클라이언트에 대한 추가 정보](/developers/docs/nodes-and-clients/light-clients/) + +### 합의 레이어 동기화 모드 {#consensus-layer-sync-modes} + +#### 낙관적 동기화 {#optimistic-sync} + +낙관적 동기화는 머지 이후의 동기화 전략으로, 선택적으로 사용할 수 있으며 이전 버전과 호환됩니다. 이를 통해 실행 노드가 기존 방법을 통해 동기화할 수 있습니다. 실행 엔진은 비콘 블록을 완전히 검증하지 않고 _낙관적으로_ 가져와 최신 헤드를 찾은 다음, 위 방법으로 체인 동기화를 시작할 수 있습니다. 그 후 실행 클라이언트가 최신 상태에 도달하면 비콘 체인의 트랜잭션 유효성을 합의 클라이언트에 알립니다. + +[낙관적 동기화에 대한 추가 정보](https://github.com/ethereum/consensus-specs/blob/dev/sync/optimistic.md) + +#### 체크포인트 동기화 {#checkpoint-sync} + +체크포인트 동기화, 즉 약한 주관성 동기화는 비콘 노드를 동기화하는 데 있어 우수한 사용자 경험을 제공합니다. 이는 [약한 주관성](/developers/docs/consensus-mechanisms/pos/weak-subjectivity/)의 가정을 기반으로 하며, 이를 통해 제네시스 대신 최근의 약한 주관성 체크포인트에서 비콘 체인을 동기화할 수 있습니다. 체크포인트 동기화는 [제네시스](/glossary/#genesis-block)에서 동기화하는 것과 유사한 신뢰 가정을 통해 초기 동기화 시간을 훨씬 더 빠르게 만듭니다. + +실제로 이는 노드가 원격 서비스를 연결하여 최근의 최종 상태를 다운로드한 후 그 시점부터 데이터를 검증하는 것을 의미합니다. 데이터를 제공하는 제3자에 대한 신뢰가 필요하며, 신중히 선택해야 합니다. + +[체크포인트 동기화](https://notes.ethereum.org/@djrtwo/ws-sync-in-practice)에 대한 추가 정보 + +## 더 읽어보기 {#further-reading} + +- [이더리움 101 - 2부 - 노드 이해하기](https://kauri.io/ethereum-101-part-2-understanding-nodes/48d5098292fd4f11b251d1b1814f0bba/a) _– Wil Barnes, 2019년 2월 13일_ +- [이더리움 전체 노드 실행하기: 동기 부여가 거의 없는 분들을 위한 안내서](https://medium.com/@JustinMLeroux/running-ethereum-full-nodes-a-guide-for-the-barely-motivated-a8a13e7a0d31) _– Justin Leroux, 2019년 11월 7일_ + +## 관련 주제 {#related-topics} + +- [블록](/developers/docs/blocks/) +- [네트워크](/developers/docs/networks/) + +## 관련 튜토리얼 {#related-tutorials} + +- [MicroSD 카드 플래싱만으로 Raspberry Pi 4를 검증자 노드로 전환하기 – 설치 가이드](/developers/tutorials/run-node-raspberry-pi/) _– Raspberry Pi 4를 플래시하고, 이더넷 케이블을 연결하고, SSD 디스크를 연결하고 장치에 전원을 공급하여 Raspberry Pi 4를 실행 레이어(메인넷) 및/또는 합의 레이어(비콘 체인/검증자)를 실행하는 전체 이더리움 노드로 전환합니다._ diff --git a/public/content/translations/ko/developers/docs/nodes-and-clients/light-clients/index.md b/public/content/translations/ko/developers/docs/nodes-and-clients/light-clients/index.md new file mode 100644 index 00000000000..488da0e169c --- /dev/null +++ b/public/content/translations/ko/developers/docs/nodes-and-clients/light-clients/index.md @@ -0,0 +1,61 @@ +--- +title: "라이트 클라이언트" +description: "이더리움 라이트 클라이언트 소개." +lang: ko +--- + +전체 노드를 실행하는 것은 이더리움과 상호작용하는 가장 신뢰가 필요 없고, 비공개적이며, 탈중앙화되고, 검열에 저항하는 방법입니다. 전체 노드를 사용하면 즉시 쿼리할 수 있는 블록체인의 자체 사본을 유지하고 이더리움의 P2P(peer-to-peer) 네트워크에 직접 액세스할 수 있습니다. 하지만 전체 노드를 실행하려면 상당한 양의 메모리, 저장 공간, CPU가 필요합니다. 이는 모든 사람이 자신의 노드를 실행하는 것이 실현 가능하지 않다는 것을 의미합니다. 이더리움 로드맵에는 무상태성을 포함하여 이에 대한 몇 가지 해결책이 있지만, 구현되기까지는 몇 년이 걸릴 것입니다. 단기적인 해결책은 전체 노드 실행의 이점 중 일부를 대폭적인 성능 향상과 맞바꾸어 매우 낮은 하드웨어 요구 사항으로 노드를 실행할 수 있도록 하는 것입니다. 이러한 트레이드오프를 하는 노드를 라이트 노드라고 합니다. + +## 라이트 클라이언트란 무엇인가요? {#what-is-a-light-client} + +라이트 노드는 라이트 클라이언트 소프트웨어를 실행하는 노드입니다. 블록체인 데이터의 로컬 사본을 보관하고 모든 변경 사항을 독립적으로 검증하는 대신, 일부 공급자에게 필요한 데이터를 요청합니다. 공급자는 전체 노드에 직접 연결하거나 일부 중앙화된 RPC 서버를 통해 연결될 수 있습니다. 그런 다음 데이터는 라이트 노드에 의해 검증되어 체인의 헤드를 따라갈 수 있습니다. 라이트 노드는 블록 헤더만 처리하며, 실제 블록 콘텐츠는 가끔씩만 다운로드합니다. 노드는 실행하는 라이트 및 전체 클라이언트 소프트웨어의 조합에 따라 경량성이 다를 수 있습니다. 예를 들어, 가장 가벼운 구성은 라이트 실행 클라이언트와 라이트 합의 클라이언트를 실행하는 것입니다. 또한 많은 노드가 라이트 합의 클라이언트를 전체 실행 클라이언트와 함께 실행하거나 그 반대로 실행하는 것을 선택할 가능성이 높습니다. + +## 라이트 클라이언트는 어떻게 작동하나요? {#how-do-light-clients-work} + +이더리움이 지분 증명 기반 합의 메커니즘을 사용하기 시작했을 때, 라이트 클라이언트를 특별히 지원하기 위한 새로운 인프라가 도입되었습니다. 작동 방식은 1.1일마다 512명의 검증자 중 일부를 무작위로 선택하여 동기화 위원회로 활동하게 하는 것입니다. 동기화 위원회는 최근 블록의 헤더에 서명합니다. 각 블록 헤더에는 동기화 위원회의 검증자들의 집계된 서명과 어떤 검증자가 서명했고 어떤 검증자가 서명하지 않았는지 보여주는 "비트필드"가 포함됩니다. 각 헤더에는 다음 블록 서명에 참여할 것으로 예상되는 검증자 목록도 포함됩니다. 이는 라이트 클라이언트가 동기화 위원회가 수신한 데이터에 서명했음을 신속하게 확인할 수 있으며, 이전 블록에서 예상하라고 전달받은 것과 수신한 것을 비교하여 동기화 위원회가 진짜인지 확인할 수도 있음을 의미합니다. 이러한 방식으로 라이트 클라이언트는 블록 자체를 실제로 다운로드하지 않고 요약 정보가 포함된 헤더만으로 최신 이더리움 블록에 대한 지식을 계속 업데이트할 수 있습니다. + +실행 레이어에는 라이트 실행 클라이언트에 대한 단일 사양이 없습니다. 라이트 실행 클라이언트의 범위는 전체 노드의 모든 EVM 및 네트워킹 기능을 갖추고 있지만 관련 데이터를 다운로드하지 않고 블록 헤더만 검증하는 전체 실행 클라이언트의 "라이트 모드"부터, 이더리움과 상호작용하기 위해 RPC 공급자에게 요청을 전달하는 데 크게 의존하는 더 간소화된 클라이언트에 이르기까지 다양할 수 있습니다. + +## 라이트 클라이언트가 왜 중요한가요? {#why-are-light-clients-important} + +라이트 클라이언트는 전체 노드의 아주 적은 계산 리소스만 사용하면서도 사용자가 데이터 제공업체가 정확하고 정직하다고 맹목적으로 신뢰하는 대신 들어오는 데이터를 직접 검증할 수 있게 해주기 때문에 중요합니다. 라이트 클라이언트가 수신하는 데이터는 무작위로 선정된 512명의 이더리움 검증자 중 최소 2/3가 서명한 것으로 알려진 블록 헤더와 대조하여 확인할 수 있습니다. 이는 데이터가 정확하다는 매우 강력한 증거입니다. + +라이트 클라이언트는 아주 적은 양의 컴퓨팅 파워, 메모리, 저장 공간만 사용하므로 휴대폰, 앱에 내장되거나 브라우저의 일부로 실행될 수 있습니다. 라이트 클라이언트는 신뢰를 최소화한 이더리움 액세스를 제3자 제공자를 신뢰하는 것만큼이나 원활하게 만드는 방법입니다. + +간단한 예를 들어보겠습니다. 계정 잔액을 확인하고 싶다고 상상해 보세요. 이를 위해서는 이더리움 노드에 요청을 해야 합니다. 해당 노드는 이더리움 상태의 로컬 사본에서 잔액을 확인하고 사용자에게 반환합니다. 노드에 직접 액세스할 수 없는 경우 이 데이터를 서비스로 제공하는 중앙화된 운영자가 있습니다. 그들에게 요청을 보내면 그들은 자신의 노드를 확인하고 결과를 다시 사용자에게 보냅니다. 이것의 문제점은 제공자가 올바른 정보를 제공하고 있다고 신뢰해야 한다는 것입니다. 스스로 확인할 수 없다면 정보가 정확한지 결코 알 수 없습니다. + +라이트 클라이언트는 이 문제를 해결합니다. 여전히 외부 공급자에게 데이터를 요청하지만, 데이터를 다시 받을 때 라이트 노드가 블록 헤더에서 받은 정보와 대조하여 확인할 수 있는 증명과 함께 제공됩니다. 이는 신뢰할 수 있는 일부 운영자 대신 이더리움이 데이터의 정확성을 검증하고 있음을 의미합니다. + +## 라이트 클라이언트는 어떤 혁신을 가능하게 하나요? {#what-innovations-do-light-clients-enable} + +라이트 클라이언트의 주요 이점은 더 많은 사람들이 무시할 수 있는 하드웨어 요구 사항과 제3자에 대한 최소한의 의존으로 독립적으로 이더리움에 액세스할 수 있도록 하는 것입니다. 이는 사용자가 자신의 데이터를 직접 검증할 수 있기 때문에 사용자에게 좋고, 체인을 검증하는 노드의 수와 다양성을 증가시키기 때문에 네트워크에도 좋습니다. + +매우 작은 저장 공간, 메모리, 처리 능력을 가진 장치에서 이더리움 노드를 실행할 수 있는 능력은 라이트 클라이언트에 의해 가능해진 주요 혁신 분야 중 하나입니다. 오늘날 이더리움 노드는 많은 컴퓨팅 리소스를 필요로 하지만, 라이트 클라이언트는 브라우저에 내장되거나, 휴대폰에서 실행되거나, 심지어 스마트 워치와 같은 더 작은 장치에서도 실행될 수 있습니다. 이는 내장된 클라이언트가 있는 이더리움 지갑이 휴대폰에서 실행될 수 있음을 의미합니다. 이는 모바일 지갑이 데이터에 대해 중앙화된 데이터 제공업체를 신뢰할 필요가 없으므로 훨씬 더 탈중앙화될 수 있음을 의미합니다. + +이것의 연장선상에서 **사물 인터넷(IoT)** 장치를 활성화할 수 있습니다. 라이트 클라이언트는 동기화 위원회가 제공하는 모든 보안 보증을 통해 일부 토큰 잔액 또는 NFT의 소유권을 신속하게 증명하고 IoT 네트워크에서 일부 작업을 트리거하는 데 사용될 수 있습니다. 내장된 라이트 클라이언트가 있는 앱을 사용하여 대여 서비스의 NFT를 소유하고 있는지 신속하게 확인하고, 그렇다면 자전거 잠금을 해제하여 타고 갈 수 있는 [자전거 대여 서비스](https://youtu.be/ZHNrAXf3RDE?t=929)를 상상해 보세요! + +이더리움 롤업 또한 라이트 클라이언트의 이점을 누릴 수 있습니다. 롤업의 큰 문제 중 하나는 이더리움 메인넷에서 롤업으로 자금을 이전할 수 있게 해주는 브리지를 대상으로 한 해킹이었습니다. 한 가지 취약점은 롤업이 사용자가 브리지에 입금했음을 감지하는 데 사용하는 오라클입니다. 오라클이 잘못된 데이터를 제공하면 롤업을 속여 브리지에 입금된 것으로 생각하게 하고 자금을 잘못 출금하게 할 수 있습니다. 롤업에 내장된 라이트 클라이언트는 손상된 오라클로부터 보호하는 데 사용될 수 있습니다. 왜냐하면 브리지에 대한 입금은 롤업이 토큰을 출금하기 전에 검증할 수 있는 증명과 함께 제공될 수 있기 때문입니다. 동일한 개념이 다른 인터체인 브리지에도 적용될 수 있습니다. + +라이트 클라이언트는 이더리움 지갑을 업그레이드하는 데에도 사용될 수 있습니다. RPC 공급자가 제공하는 데이터를 신뢰하는 대신, 지갑이 내장된 라이트 클라이언트를 사용하여 사용자에게 제시되는 데이터를 직접 검증할 수 있습니다. 이렇게 하면 지갑의 보안이 강화됩니다. RPC 공급자가 부정직하여 잘못된 데이터를 제공한 경우, 내장된 라이트 클라이언트가 이를 알려줄 수 있습니다! + +## 라이트 클라이언트 개발의 현재 상태는 어떤가요? {#current-state-of-development} + +실행, 합의 및 결합된 실행/합의 라이트 클라이언트를 포함하여 여러 라이트 클라이언트가 개발 중입니다. 이 페이지를 작성하는 시점에 우리가 알고 있는 라이트 클라이언트 구현은 다음과 같습니다: + +- [Lodestar](https://github.com/ChainSafe/lodestar/tree/unstable/packages/light-client): TypeScript로 작성된 합의 라이트 클라이언트 +- [Helios](https://github.com/a16z/helios): Rust로 작성된 결합된 실행 및 합의 라이트 클라이언트 +- [Geth](https://github.com/ethereum/go-ethereum/tree/master/beacon/light): Go로 작성된 실행 클라이언트용 라이트 모드(개발 중) +- [Nimbus](https://nimbus.guide/el-light-client.html): Nim으로 작성된 합의 라이트 클라이언트 + +우리가 알기로는 아직 이들 중 어느 것도 프로덕션 준비가 된 것으로 간주되지 않습니다. + +또한 라이트 클라이언트가 이더리움 데이터에 액세스하는 방식을 개선하기 위한 많은 작업이 진행되고 있습니다. 현재 라이트 클라이언트는 클라이언트/서버 모델을 사용하여 전체 노드에 대한 RPC 요청에 의존하지만, 미래에는 P2P(peer-to-peer) 가십 프로토콜을 사용하여 라이트 클라이언트에 데이터를 제공할 수 있는 [포털 네트워크](https://www.ethportal.net/)와 같은 전용 네트워크를 사용하여 더 탈중앙화된 방식으로 데이터를 요청할 수 있습니다. + +다른 [로드맵](/roadmap/) 항목인 [버클 트리](/roadmap/verkle-trees/) 및 [무상태성](/roadmap/statelessness/)은 결국 라이트 클라이언트의 보안 보증을 전체 클라이언트의 보안 보증과 동일한 수준으로 끌어올릴 것입니다. + +## 더 읽어보기 {#further-reading} + +- [Geth 라이트 클라이언트에 대한 Zsolt Felfodhi](https://www.youtube.com/watch?v=EPZeFXau-RE) +- [라이트 클라이언트 네트워킹에 대한 Etan Kissling](https://www.youtube.com/watch?v=85MeiMA4dD8) +- [병합 이후의 라이트 클라이언트에 대한 Etan Kissling](https://www.youtube.com/watch?v=ZHNrAXf3RDE) +- [Piper Merriam: 기능적인 라이트 클라이언트로 가는 구불구불한 길](https://snakecharmers.ethereum.org/the-winding-road-to-functional-light-clients/) diff --git a/public/content/translations/ko/developers/docs/nodes-and-clients/node-architecture/index.md b/public/content/translations/ko/developers/docs/nodes-and-clients/node-architecture/index.md new file mode 100644 index 00000000000..06a5daa4150 --- /dev/null +++ b/public/content/translations/ko/developers/docs/nodes-and-clients/node-architecture/index.md @@ -0,0 +1,59 @@ +--- +title: "노드 아키텍처" +description: "이더리움 노드가 어떻게 구성되는지에 대한 소개." +lang: ko +--- + +이더리움 노드는 [실행 클라이언트](/developers/docs/nodes-and-clients/#execution-clients)와 [합의 클라이언트](/developers/docs/nodes-and-clients/#consensus-clients)의 두 클라이언트로 구성됩니다. 노드가 새 블록을 제안하려면 [검증자 클라이언트](#validators)도 실행해야 합니다. + +이더리움이 [작업 증명](/developers/docs/consensus-mechanisms/pow/)을 사용했을 때에는 실행 클라이언트만으로도 전체 이더리움 노드를 실행하기에 충분했습니다. 그러나 [지분 증명](/developers/docs/consensus-mechanisms/pow/)이 구현된 이후에는 실행 클라이언트는 [합의 클라이언트](/developers/docs/nodes-and-clients/#consensus-clients)라는 다른 소프트웨어와 함께 사용되어야 합니다. + +아래 다이어그램은 두 이더리움 클라이언트 간의 관계를 보여줍니다. 두 클라이언트는 각자의 peer-to-peer (P2P) 네트워크에 연결됩니다. 실행 클라이언트는 P2P 네트워크를 통해 트랜잭션을 가십하여 로컬 트랜잭션 풀을 관리하고, 합의 클라이언트는 P2P 네트워크를 통해 블록을 가십하여 합의와 체인 성장을 가능하게 하므로 별도의 P2P 네트워크가 필요합니다. + +![](node-architecture-text-background.png) + +_실행 클라이언트에는 Erigon, Nethermind, Besu를 포함한 여러 옵션이 있습니다_. + +이 이중 클라이언트 구조가 작동하려면 합의 클라이언트는 트랜잭션 묶음을 실행 클라이언트에 전달해야 합니다. 실행 클라이언트는 트랜잭션을 로컬에서 실행하여 트랜잭션이 이더리움 규칙을 위반하지 않는지와 제안된 이더리움 상태 업데이트가 올바른지를 검증합니다. 노드가 블록 생성자로 선택되면 해당 합의 클라이언트 인스턴스는 실행 클라이언트로부터 트랜잭션 묶음을 요청하여 새 블록에 포함하고 이를 실행하여 전역 상태를 업데이트합니다. 합의 클라이언트는 [엔진 API](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md)를 사용하여 로컬 RPC 연결을 통해 실행 클라이언트를 구동합니다. + +## 실행 클라이언트는 어떤 역할을 하나요? {#execution-client} + +실행 클라이언트는 트랜잭션 검증, 처리, 가십뿐만 아니라 상태 관리와 이더리움 가상 머신([EVM](/developers/docs/evm/)) 지원을 담당합니다. 블록 생성, 블록 가십 또는 합의 로직 처리는 **담당하지 않습니다**. 이는 합의 클라이언트의 소관입니다. + +실행 클라이언트는 실행 페이로드, 즉 트랜잭션 목록, 업데이트된 상태 트라이, 기타 실행 관련 데이터를 생성합니다. 합의 클라이언트는 모든 블록에 실행 페이로드를 포함합니다. 실행 클라이언트는 새 블록의 트랜잭션을 재실행하여 유효성을 보장하는 역할도 합니다. 트랜잭션 실행은 [이더리움 가상 머신(EVM)](/developers/docs/evm)으로 알려진 실행 클라이언트의 내장 컴퓨터에서 수행됩니다. + +실행 클라이언트는 사용자가 이더리움 블록체인을 쿼리하고, 트랜잭션을 제출하고, 스마트 계약을 배포할 수 있도록 하는 [RPC 메서드](/developers/docs/apis/json-rpc)를 통해 이더리움에 대한 사용자 인터페이스를 제공합니다. RPC 호출은 일반적으로 [Web3js](https://docs.web3js.org/), [Web3py](https://web3py.readthedocs.io/en/v5/)와 같은 라이브러리나 브라우저 지갑과 같은 사용자 인터페이스에 의해 처리됩니다. + +요약하자면, 실행 클라이언트는 다음과 같습니다. + +- 이더리움으로 가는 사용자 게이트웨이 +- 이더리움 가상 머신, 이더리움의 상태 및 트랜잭션 풀의 홈 + +## 합의 클라이언트는 어떤 역할을 하나요? {#consensus-client} + +합의 클라이언트는 노드가 이더리움 네트워크와 동기화 상태를 유지할 수 있도록 하는 모든 로직을 처리합니다. 여기에는 피어로부터 블록을 수신하고 포크 선택 알고리즘을 실행하여 노드가 항상 가장 많은 인증(검증자 유효 잔고에 따라 가중치가 적용됨)이 축적된 체인을 따르도록 하는 것이 포함됩니다. 실행 클라이언트와 마찬가지로, 합의 클라이언트도 블록과 인증을 공유하는 자체 P2P 네트워크를 가집니다. + +합의 클라이언트는 블록을 인증하거나 제안하는 데 참여하지 않습니다. 이 작업은 합의 클라이언트의 선택적 애드온인 검증자에 의해 수행됩니다. 검증자가 없는 합의 클라이언트는 체인의 헤드만 따라가며 노드가 동기화 상태를 유지할 수 있도록 합니다. 이를 통해 사용자는 올바른 체인에 있다는 확신을 가지고 실행 클라이언트를 사용하여 이더리움과 거래할 수 있습니다. + +## 검증자 {#validators} + +스테이킹을 하고 검증자 소프트웨어를 실행하면 노드가 새 블록을 제안하도록 선택될 자격을 갖추게 됩니다. 노드 운영자는 예금 컨트랙트에 32 ETH를 예치하여 자신의 합의 클라이언트에 검증인을 추가할 수 있습니다. 검증자 클라이언트는 합의 클라이언트와 함께 번들로 제공되며 언제든지 노드에 추가할 수 있습니다. 검증인은 인증 및 블록 제안을 처리합니다. 또한 노드는 페널티나 슬래싱을 통해 보상을 받거나 ETH를 잃을 수 있습니다. + +[스테이킹에 대해 더 알아보기](/staking/). + +## 노드 구성 요소 비교 {#node-comparison} + +| 실행 클라이언트 | 합의 클라이언트 | 검증자 | +| ------------------------------- | --------------------------------------------------------------------------------- | -------------- | +| P2P 네트워크를 통해 트랜잭션을 가십합니다 | P2P 네트워크를 통해 블록 및 인증을 가십합니다 | 블록 제안 | +| 트랜잭션 실행/재실행 | 포크 선택 알고리즘 실행 | 보상/페널티 발생 | +| 수신 상태 변경 확인 | 체인 헤드 추적 | 인증 생성 | +| 상태 및 영수증 트라이 관리 | 비콘 상태 관리(합의 및 실행 정보 포함) | 32 ETH 스테이킹 필요 | +| 실행 페이로드 생성 | RANDAO(검증자 선택 및 기타 합의 작업에 검증 가능한 무작위성을 제공하는 알고리즘)의 누적된 무작위성 추적 | 슬래싱 가능 | +| 이더리움과 상호작용하기 위한 JSON-RPC API 노출 | 정당성 및 완결성 추적 | | + +## 더 읽어보기 {#further-reading} + +- [지분 증명](/developers/docs/consensus-mechanisms/pos) +- [블록 제안](/developers/docs/consensus-mechanisms/pos/block-proposal) +- [검증자 보상 및 페널티](/developers/docs/consensus-mechanisms/pos/rewards-and-penalties) diff --git a/public/content/translations/ko/developers/docs/nodes-and-clients/nodes-as-a-service/index.md b/public/content/translations/ko/developers/docs/nodes-and-clients/nodes-as-a-service/index.md new file mode 100644 index 00000000000..36d6fb4ac89 --- /dev/null +++ b/public/content/translations/ko/developers/docs/nodes-and-clients/nodes-as-a-service/index.md @@ -0,0 +1,418 @@ +--- +title: "노드 제공 서비스" +description: "노드 서비스에 대한 입문 단계 및 장단점 그리고 대표적인 서비스 제공" +lang: ko +sidebarDepth: 2 +--- + +## 소개 {#Introduction} + +자체 [이더리움 노드](/developers/docs/nodes-and-clients/#what-are-nodes-and-clients)를 실행하는 것은 특히 처음 시작하거나 빠르게 확장할 때 어려울 수 있습니다. 사용자를 위해 최적화된 노드 인프라를 실행하는 [여러 서비스](#popular-node-services)가 있으므로, 대신 애플리케이션이나 제품 개발에 집중할 수 있습니다. 본 장에서는 노드 서비스가 작동하는 방식과 장단점 그리고 서비스 제공업체 (provider)를 나열한다. + +## 필수 구성 요소 {#prerequisites} + +노드와 클라이언트가 무엇인지 아직 이해하지 못했다면 [노드 및 클라이언트](/developers/docs/nodes-and-clients/)를 확인하세요. + +## 스테이커 {#stakoooooooooooooors} + +개인 지분 소유자 (solo staker) 는 제3자를 통하지 않고 개인적으로 인프라를 구축하여야 한다. 즉 실행 클라이언트를 운영하는 것은 컨센서스 클라이언트와 매칭된다. [병합](/roadmap/merge) 이전에는 합의 클라이언트만 실행하고 중앙화된 제공자로부터 실행 데이터를 가져올 수 있었지만, 이제는 불가능하며 단독 스테이커는 두 클라이언트를 모두 실행해야 합니다. 그러나 몇몇 서비스가 이를 간단하게 해준다. + +[노드 실행에 대해 자세히 알아보기](/developers/docs/nodes-and-clients/run-a-node/). + +이 페이지에 설명된 서비스는 스테이킹이 아닌 노드용입니다. + +## 노드 서비스는 어떻게 작동하나요? {#how-do-node-services-work} + +노드 서비스 제공업체는 백그라운드에서 분산된 노드 클라이언트를 실행하므로 직접 할 필요가 없습니다. + +이 서비스들은 일반적으로 API 키를 제공하여 블록체인에 쓰거나 읽을 수 있습니다. 이러한 서비스는 보통 메인넷 외에도 [이더리움 테스트넷](/developers/docs/networks/#ethereum-testnets)에 대한 액세스를 포함합니다. + +일부 서비스는 자체적으로 관리하는 전용 노드를 제공하는 반면, 다른 서비스는 로드 밸런서를 사용하여 노드 간 활동을 분배합니다. + +대부분의 노드 서비스는 통합이 매우 쉬우며, 셀프 호스팅 노드를 교체하거나 서비스 간 전환하는 경우 코드에서 한 줄만 변경하면 됩니다. + +노드 서비스는 종종 다양한 [노드 클라이언트](/developers/docs/nodes-and-clients/#execution-clients) 및 [유형](/developers/docs/nodes-and-clients/#node-types)을 실행하여, 하나의 API에서 클라이언트 특정 메서드 외에 전체 및 아카이브 노드에 액세스할 수 있도록 합니다. + +노드 서비스가 개인 키나 정보를 저장하지 않으며 저장해서도 안 된다는 점을 유념해야 합니다. + +## 노드 서비스 사용의 장점은 무엇인가요? {#benefits-of-using-a-node-service} + +노드 서비스를 사용할 때의 주요 이점은 노드를 유지 관리하는 데 소요되는 엔지니어링 시간을 절약할 수 있다는 것입니다. 이는 인프라 유지 관리를 걱정하는 대신 제품 개발에 집중할 수 있도록 합니다. + +자체 노드를 실행하는 것은 스토리지에서 대역폭, 소중한 엔지니어링 시간에 이르기까지 매우 비용이 많이 들 수 있습니다. 확장 시 더 많은 노드를 시작하고, 최신 버전으로 노드를 업그레이드하고, 상태 일관성을 보장하는 것과 같은 작업은 웹3 제품 개발에 집중하는 데 방해가 될 수 있습니다. + +## 노드 서비스 사용의 단점은 무엇인가요? {#cons-of-using-a-node-service} + +노드 서비스를 사용하면 제품의 인프라 측면을 중앙 집중화하는 것입니다. 이러한 이유로 탈중앙화를 가장 중요하게 여기는 프로젝트는 3자에게 아웃소싱하는 대신 자체 노드를 호스팅하는 것을 선호할 수 있습니다. + +[자체 노드 실행의 이점](/developers/docs/nodes-and-clients/#benefits-to-you)에 대해 자세히 알아보세요. + +## 인기 있는 노드 서비스 {#popular-node-services} + +다음은 가장 인기 있는 이더리움 노드 제공업체 목록입니다. 누락된 항목이 있으면 자유롭게 추가하세요! 각 노드 서비스는 무료 또는 유료 계층 외에도 다양한 이점과 기능을 제공합니다. 결정을 내리기 전에 어떤 것이 가장 적합한지 조사해야 합니다. + +- [**Alchemy**](https://alchemy.com/) + - [문서](https://www.alchemy.com/docs/) + - 기능 + - 월 3억 컴퓨팅 유닛(약 3천만 getLatestBlock 요청)을 제공하는 가장 큰 무료 계층 + - Polygon, Starknet, Optimism, Arbitrum에 대한 멀티체인 지원 + - 최대 이더리움 dapp 및 DeFi 거래량의 약 70% 지원 + - 실시간 웹훅 알림 기능을 제공하는 Alchemy Notify + - 최고 수준의 지원 및 신뢰성/안정성 + - Alchemy의 NFT API + - Request Explorer, Mempool Watcher 및 Composer를 포함한 대시보드 + - 통합된 테스트넷 수도꼭지 접근 + - 18,000명의 사용자를 보유한 활성 Discord 빌더 커뮤니티 + +- [**Allnodes**](https://www.allnodes.com/) + - [문서](https://docs.allnodes.com/) + - 기능 + - Allnodes 포트폴리오 페이지에서 생성된 PublicNode 토큰 사용 시 속도 제한 없음. + - [PublicNode](https://www.publicnode.com)에서 개인 정보 보호에 중점을 둔 무료 RPC 엔드포인트(100개 이상의 블록체인) 제공 + - 90개 이상의 블록체인을 위한 속도 제한 없는 전용 노드 + - 30개 이상의 블록체인을 위한 전용 아카이브 노드 + - 3개 지역(미국, EU, 아시아)에서 사용 가능 + - [PublicNode](https://www.publicnode.com/snapshots)에서 100개 이상의 블록체인에 대한 스냅샷 제공 + - 연중무휴 기술 지원 및 99.90%-99.98% 가동 시간 SLA(플랜에 따라 다름). + - 시간당 결제 요금제 + - 신용카드, PayPal 또는 암호화폐로 결제 + +- [**All That Node**](https://allthatnode.com/) + - [문서](https://docs.allthatnode.com/) + - 기능 + - 무료 계층으로 하루에 50,000개의 요청 지원 + - 40개 이상의 프로토콜 지원 + - JSON-RPC(EVM, Tendermint), REST 및 Websocket API 지원 + - 아카이브 데이터 무제한 액세스 + - 24시간 기술 지원 및 99.9% 이상의 가동 시간 + - 멀티 체인에서 수도꼭지 이용 가능 + - 무제한 API 키로 무제한 엔드포인트 액세스 + - Trace/Debug API 지원 + - 자동 업데이트 + +- [**Amazon Managed Blockchain**](https://aws.amazon.com/managed-blockchain/) + - [문서](https://aws.amazon.com/managed-blockchain/resources/) + - 기능 + - 완전히 관리되는 이더리움 노드 + - 6개 지역에서 이용 가능 + - HTTP 및 안전한 WebSocket을 통한 JSON-RPC 지원 + - 3개의 체인 지원 + - SLA, AWS 24/7 지원 + - Go-ethereum 및 Lighthouse + +- [**Ankr**](https://www.ankr.com/) + - [문서](https://docs.ankr.com/) + - 기능 + - Ankr 프로토콜 - 8개 이상의 체인을 위한 공용 RPC API 엔드포인트에 대한 오픈 액세스 + - 가장 가까운 사용 가능한 노드로 빠르고 신뢰할 수 있는 게이트웨이를 제공하기 위한 로드 밸런싱 및 노드 상태 모니터링 + - 프리미엄 계층은 WSS 엔드포인트 및 무제한 속도 제한 활성화 + - 40개 이상의 체인을 위한 원클릭 풀 노드 및 검증자 노드 배포 + - 필요에 따라 확장 가능 + - 분석 도구 + - 대시보드 + - RPC, HTTPS 및 WSS 엔드포인트 + - 직접 지원 + +- [**Blast**](https://blastapi.io/) + - [문서](https://docs.blastapi.io/) + - 기능 + - RPC 및 WSS 지원 + - 멀티 리전 노드 호스팅 + - 탈중앙화 인프라 + - 공용 API + - 전용 무료 플랜 + - 다중 체인 지원 (17개 이상의 블록체인) + - 아카이브 노드 + - 24/7 디스코드 지원 + - 24/7 모니터링 및 알림 + - 99.9%의 전반적인 SLA + - 암호화폐로 결제 + +- [**BlockDaemon**](https://blockdaemon.com/) + - [문서](https://ubiquity.docs.blockdaemon.com/) + - 노드당 기준 + - 대시보드 + - 노드당 기준 + - 분석 + +- [**BlockPI**](https://blockpi.io/) + - [문서](https://docs.blockpi.io/) + - 기능 + - 견고하고 분산된 노드 구조 + - 최대 40개의 HTTPS 및 WSS 엔드포인트 + - 무료 가입 패키지 및 월간 패키지 + - 트레이스 메서드 + 아카이브 데이터 지원 + - 최대 90일 유효 기간 패키지 + - 맞춤형 플랜 및 사용량 기반 결제 + - 암호화폐로 결제 + - 직접 지원 및 기술 지원 + +- [**Chainbase**](https://www.chainbase.com/) + - [문서](https://docs.chainbase.com) + - 기능 + - 높은 가용성, 빠르고 확장 가능한 RPC 서비스 + - 다중 체인 지원 + - 무료 요금제 + - 사용자 친화적인 대시보드 + - RPC를 넘어서 블록체인 데이터 서비스를 제공 + +- [**Chainstack**](https://chainstack.com/) + - [문서](https://docs.chainstack.com/) + - 기능 + - 무료 공유 노드 + - 공유 아카이브 노드 + - GraphQL 지원 + - RPC 및 WSS 엔드포인트 + - 전용 풀 및 아카이브 노드 + - 전용 배포에 대한 빠른 동기화 시간 + - 사용자 클라우드 사용 + - 시간당 결제 요금제 + - 직접 24/7 지원 + +- [**dRPC**](https://drpc.org/) + - [문서](https://drpc.org/docs) + - NodeCloud: 10달러(USD)부터 시작하는 플러그 앤 플레이 RPC 인프라—최고 속도, 무제한 + - NodeCloud 기능: + - 185개 네트워크에 대한 API 지원 + - 40개 이상의 공급자로 구성된 분산 풀 + - 9개의 지리적 클러스터로 전 세계 서비스 제공 + - AI 기반 로드 밸런싱 시스템 + - 사용한 만큼 지불하는 정액 요금제—가격 인상, 만료, 약정 없음 + - 무제한 키, 세분화된 키 조정, 팀 역할, 프런트엔드 보호 + - 메서드당 20 컴퓨팅 유닛(CU)의 정액 요금 + - [퍼블릭 엔드포인트 체인리스트](https://drpc.org/chainlist) + - [가격 계산기](https://drpc.org/pricing#calculator) + - NodeCore: 완전한 제어를 원하는 조직을 위한 오픈소스 스택 + +- [**GetBlock**](https://getblock.io/) + - [문서](https://getblock.io/docs/get-started/authentication-with-api-key/) + - 기능 + - 40개 이상의 블록체인 노드 액세스 + - 하루 4만 건의 무료 요청 + - 무제한 API 키 수 + - 1GB/초의 높은 연결 속도 + - 추적+아카이브 + - 고급 분석 + - 자동 업데이트 + - 기술 지원 + +- [**InfStones**](https://infstones.com/) + - 기능 + - 무료 계층 옵션 + - 필요에 따라 확장 가능 + - 분석 + - 대시보드 + - 고유한 API 엔드포인트 + - 전용 풀 노드 + - 전용 배포에 대한 빠른 동기화 시간 + - 직접 24/7 지원 + - 50개 이상의 블록체인 노드 액세스 + +- [**Infura**](https://infura.io/) + - [문서](https://infura.io/docs) + - 기능 + - 무료 계층 옵션 + - 필요에 따라 확장 가능 + - 유료 아카이브 데이터 + - 직접 지원 + - 대시보드 + +- [**Kaleido**](https://kaleido.io/) + - [문서](https://docs.kaleido.io/) + - 기능 + - 무료 시작 계층 + - 원클릭 이더리움 노드 배포 + - 사용자 지정 가능한 클라이언트 및 알고리즘(Geth, Quorum & Besu || PoA, IBFT & Raft) + - 500개 이상의 관리 및 서비스 API + - 이더리움 트랜잭션 제출을 위한 RESTful 인터페이스 (Apache Kafka 지원) + - 이벤트 전송을 위한 아웃바운드 스트림 (Apache Kafka 지원) + - 방대한 "오프체인" 및 보조 서비스 컬렉션(예: 양방향 암호화 메시징 전송) + - 거버넌스 및 역할 기반 접근 제어를 통한 간단한 네트워크 온보딩 + - 관리자 및 최종 사용자를 위한 고급 사용자 관리 + - 매우 확장 가능하고 회복력이 강한 엔터프라이즈급 인프라 + - 클라우드 HSM 개인 키 관리 + - 이더리움 메인넷 연결 + - ISO 27k 및 SOC 2, 유형 2 인증 + - 동적 런타임 구성(예: 클라우드 통합 추가, 노드 인그레스 변경 등) + - 멀티 클라우드, 멀티 리전 및 하이브리드 배포 오케스트레이션 지원 + - 간단한 시간별 SaaS 기반 가격 책정 + - SLA 및 24x7 지원 + +- [**Lava Network**](https://www.lavanet.xyz/) + - [문서](https://docs.lavanet.xyz/) + - 기능 + - 무료 테스트넷 사용 + - 높은 가동률을 위한 탈중앙화 이중화 + - 오픈 소스 + - 완전히 탈중앙화된 SDK + - Ethers.js 통합 + - 직관적인 프로젝트 관리 인터페이스 + - 합의 기반 데이터 무결성 + - 멀티 체인 지원 + +- [**Moralis**](https://moralis.io/) + - [문서](https://docs.moralis.io/) + - 기능 + - 무료 공유 노드 + - 무료 공유 아카이브 노드 + - 개인정보 보호 중심 (로그 기록 정책 없음) + - 크로스 체인 지원 + - 필요에 따라 확장 가능 + - 대시보드 + - 고유한 이더리움 SDK + - 고유한 API 엔드포인트 + - 직접적인 기술 지원 + +- [**NodeReal MegaNode**](https://nodereal.io/) + - [문서](https://docs.nodereal.io/docs/introduction) + - 기능 + - 신뢰할 수 있고 빠르며 확장 가능한 RPC API 서비스 + - 웹3 개발자를 위한 향상된 API + - 다중 체인 지원 + - 무료로 시작하기 + +- [**NOWNodes**](https://nownodes.io/) + - [문서](https://documenter.getpostman.com/view/13630829/TVmFkLwy) + - 기능 + - 50개 이상의 블록체인 노드 액세스 + - 무료 API 키 + - 블록 탐색기 + - API 응답 시간 ⩽ 1초 + - 24/7 지원 팀 + - 개인 계정 관리자 + - 공유, 아카이브, 백업 및 전용 노드 + +- [**Pocket Network**](https://www.pokt.network/) + - [문서](https://docs.pokt.network/home/) + - 기능 + - 탈중앙화된 RPC 프로토콜 및 마켓플레이스 + - 일일 1백만 요청 무료 티어 (엔드포인트당, 최대 2개) + - [퍼블릭 엔드포인트](https://docs.pokt.network/developers/public-endpoints) + - Pre-Stake+ 프로그램 (일일 1백만 요청 이상 필요 시) + - 15개 이상의 블록체인 지원 + - 애플리케이션을 제공하며 POKT를 획득하는 6400개 이상의 노드 + - 아카이브 노드, 트레이싱 기능이 있는 아카이브 노드 및 테스트넷 노드 지원 + - 이더리움 메인넷 노드 클라이언트 다양성 + - 단일 장애점 없음 + - 제로 다운타임 + - 비용 효율적인 거의 제로 토크노믹스 (네트워크 대역폭을 위한 POKT 한 번 스테이킹) + - 월간 고정 비용 없음, 인프라를 자산으로 전환 + - 프로토콜에 내장된 로드 밸런싱 + - 요청 및 시간당 노드 수를 무한대로 확장 가능 + - 가장 개인적이고 검열 저항성이 높은 옵션 + - 실질적인 개발자 지원 + - [Pocket Portal](https://bit.ly/ETHorg_POKTportal) 대시보드 및 분석 + +- [**QuickNode**](https://www.quicknode.com) + - [문서](https://www.quicknode.com/docs/) + - 기능 + - 연중무휴 기술 지원 및 개발자 Discord 커뮤니티 + - 지리적 균형, 다중 클라우드/메탈, 저지연 네트워크 + - 다중 체인 지원 (Optimism, Arbitrum, Polygon + 11개 추가) + - 속도 및 안정성을 위한 중간 계층(호출 라우팅, 캐시, 인덱싱) + - 웹훅을 통한 스마트 계약 모니터링 + - 직관적인 대시보드, 분석 도구, RPC 컴포저 + - 고급 보안 기능 (JWT, 마스킹, 화이트리스트) + - NFT 데이터 및 분석 API + - [SOC2 인증](https://www.quicknode.com/security) + - 개발자부터 기업까지 적합 + +- [**Rivet**](https://rivet.cloud/) + - [문서](https://rivet.readthedocs.io/en/latest/) + - 기능 + - 무료 계층 옵션 + - 필요에 따라 확장 가능 + +- [**SenseiNode**](https://senseinode.com) + - [문서](https://docs.senseinode.com/) + - 기능 + - 전용 및 공유 노드 + - 대시보드 + - AWS 외 다양한 라틴 아메리카 지역에서 여러 호스팅 제공자 이용 + - Prysm 및 Lighthouse 클라이언트 + +- [**SettleMint**](https://console.settlemint.com/) + - [문서](https://docs.settlemint.com/) + - 기능 + - 무료 체험 + - 필요에 따라 확장 가능 + - GraphQL 지원 + - RPC 및 WSS 엔드포인트 + - 전용 풀 노드 + - 사용자 클라우드 사용 + - 분석 도구 + - 대시보드 + - 시간당 결제 요금제 + - 직접 지원 + +- [**Tenderly**](https://tenderly.co/web3-gateway) + - [문서](https://docs.tenderly.co/web3-gateway/web3-gateway) + - 기능 + - 월 2,500만 Tenderly 유닛을 포함한 무료 티어 + - 역사적 데이터 무료 접근 + - 최대 8배 빠른 읽기 집중 워크로드 + - 100% 일관된 읽기 액세스 + - JSON-RPC 엔드포인트 + - UI 기반의 RPC 요청 빌더 및 요청 미리보기 + - Tenderly의 개발, 디버깅 및 테스트 도구와 밀접하게 통합됨 + - 트랜잭션 시뮬레이션 + - 사용 분석 및 필터링 + - 간편한 액세스 키 관리 + - 채팅, 이메일, 디스코드를 통한 전용 엔지니어링 지원 + +- [**Tokenview**](https://services.tokenview.io/) + - [문서](https://services.tokenview.io/docs?type=nodeService) + - 기능 + - 연중무휴 기술 지원 및 개발자 텔레그램 커뮤니티 + - 멀티체인 지원 (비트코인, 이더리움, 트론, BNB 스마트 체인, 이더리움 클래식) + - RPC 및 WSS 엔드포인트 모두 사용 가능 + - 무제한 아카이브 데이터 API 액세스 + - 요청 탐색기 및 메인풀 감시기를 포함한 대시보드 + - NFT 데이터 API 및 Webhook 알림 + - 암호화폐로 결제 + - 추가 행동 요구 사항을 위한 외부 지원 + +- [**Watchdata**](https://watchdata.io/) + - [문서](https://docs.watchdata.io/) + - 기능 + - 데이터 신뢰성 + - 중단 없는 연결로 다운타임 없음 + - 프로세스 자동화 + - 무료 요금제 + - 모든 사용자에게 적합한 높은 제한 + - 다양한 노드 지원 + - 리소스 확장 + - 높은 처리 속도 + +- [**ZMOK**](https://zmok.io/) + - [문서](https://docs.zmok.io/) + - 기능 + - 서비스로서의 프론트러닝 + - 검색/필터링 방법을 갖춘 글로벌 트랜잭션 메인풀 + - 무제한 TX 수수료 및 무한 가스로 트랜잭션 전송 + - 새로운 블록을 가장 빠르게 가져오고 블록체인을 읽음 + - API 호출당 최고의 가격 보장 + +- [**Zeeve**](https://www.zeeve.io/) + - [문서](https://www.zeeve.io/docs/) + - 기능 + - 엔터프라이즈급 코드 없는 자동화 플랫폼으로 블록체인 노드 및 네트워크 배포, 모니터링 및 관리 제공 + - 30개 이상의 프로토콜 및 통합 지원, 계속 추가 중 + - 탈중앙화 스토리지, 탈중앙화 아이덴티티, 블록체인 원장 데이터 API와 같은 부가 웹3 인프라 서비스로 실제 사례에 사용 + - 24/7 지원 및 사전 모니터링으로 노드의 건강 상태를 항상 보장 + - RPC 엔드포인트는 인증된 API 액세스, 직관적인 대시보드 및 분석을 통한 손쉬운 관리 제공 + - 관리형 클라우드 및 사용자가 소유한 클라우드 옵션을 모두 제공하며 AWS, Azure, Google Cloud, Digital Ocean 및 온프레미스와 같은 모든 주요 클라우드 제공업체 지원 + - 지능형 라우팅을 사용하여 항상 사용자의 위치와 가장 가까운 노드를 타격함 + +## 더 읽어보기 {#further-reading} + +- [이더리움 노드 서비스 목록](https://ethereumnodes.com/) + +## 관련 주제 {#related-topics} + +- [노드 및 클라이언트](/developers/docs/nodes-and-clients/) + +## 관련 튜토리얼 {#related-tutorials} + +- [Alchemy를 사용한 이더리움 개발 시작하기](/developers/tutorials/getting-started-with-ethereum-development-using-alchemy/) +- [Web3 및 Alchemy를 사용하여 트랜잭션 보내기 가이드](/developers/tutorials/sending-transactions-using-web3-and-alchemy/) diff --git a/public/content/translations/ko/developers/docs/nodes-and-clients/run-a-node/index.md b/public/content/translations/ko/developers/docs/nodes-and-clients/run-a-node/index.md new file mode 100644 index 00000000000..2e7f6327f42 --- /dev/null +++ b/public/content/translations/ko/developers/docs/nodes-and-clients/run-a-node/index.md @@ -0,0 +1,484 @@ +--- +title: "자체 이더리움 노드 가동하기" +description: "자체 이더리움 클라이언트 인스턴스 실행에 대한 일반적인 소개입니다." +lang: ko +sidebarDepth: 2 +--- + +자체 노드를 실행하면 다양한 이점을 얻고 새로운 가능성을 열며 생태계를 지원하는 데 도움이 됩니다. 이 페이지에서는 자체 노드를 가동하고 이더리움 트랜잭션 검증에 참여하는 방법을 안내합니다. + +[병합(The Merge)](/roadmap/merge) 이후 이더리움 노드를 실행하려면 **실행 레이어(EL)** 클라이언트와 **합의 레이어(CL)** 클라이언트, 이렇게 두 개의 클라이언트가 필요하다는 점에 유의하세요. 이 페이지에서는 이 두 클라이언트를 설치, 구성 및 연결하여 이더리움 노드를 실행하는 방법을 보여줍니다. + +## 필수 구성 요소 {#prerequisites} + +이더리움 노드가 무엇인지, 그리고 왜 클라이언트를 실행해야 하는지 이해해야 합니다. 이 내용은 [노드와 클라이언트](/developers/docs/nodes-and-clients/)에서 다룹니다. + +노드 실행이라는 주제를 처음 접하시거나 기술적인 부담이 적은 방법을 찾고 계신다면, 먼저 [이더리움 노드 실행](/run-a-node)에 대한 사용자 친화적인 소개 자료를 확인하시는 것을 추천합니다. + +## 접근 방식 선택 {#choosing-approach} + +노드 가동의 첫 번째 단계는 접근 방식을 선택하는 것입니다. 요구사항과 다양한 가능성을 바탕으로 클라이언트 구현(실행 및 합의 클라이언트 모두), 환경(하드웨어, 시스템), 클라이언트 설정 매개변수를 선택해야 합니다. + +이 페이지에서는 이러한 결정을 내리는 데 도움을 드리고, 여러분의 이더리움 인스턴스를 실행하는 가장 적합한 방법을 찾는 데 도움을 드릴 것입니다. + +클라이언트 구현 중에서 선택하려면, 사용 가능한 모든 메인넷 지원 [실행 클라이언트](/developers/docs/nodes-and-clients/#execution-clients)와 [합의 클라이언트](/developers/docs/nodes-and-clients/#consensus-clients)를 살펴보고 [클라이언트 다양성](/developers/docs/nodes-and-clients/client-diversity)에 대해 알아보세요. + +클라이언트의 [요구사항](#requirements)을 고려하여 자체 [하드웨어에서 실행할지 또는 클라우드에서 실행할지](#local-vs-cloud) 결정하세요. + +환경을 준비한 후, [초보자 친화적인 인터페이스](#automatized-setup)를 사용하거나 고급 옵션이 있는 터미널을 사용하여 [수동으로](#manual-setup) 선택한 클라이언트를 설치하세요. + +노드가 실행되고 동기화되면 [사용할](#using-the-node) 준비가 된 것이지만, [유지 관리](#operating-the-node)에도 계속 신경 써야 합니다. + +![클라이언트 설정](./diagram.png) + +### 환경 및 하드웨어 {#environment-and-hardware} + +#### 로컬 또는 클라우드 {#local-vs-cloud} + +이더리움 클라이언트는 일반 소비자용 컴퓨터에서 실행할 수 있으며, 예를 들어 채굴기와 같은 특수 하드웨어가 필요하지 않습니다. 따라서 필요에 따라 노드를 배포하는 데 다양한 옵션이 있습니다. +간단하게 설명하기 위해 로컬 물리적 머신과 클라우드 서버 양쪽에서 노드를 실행하는 경우를 생각해 보겠습니다. + +- 클라우드 + - 공급자는 높은 서버 가동 시간과 고정 공인 IP 주소를 제공합니다. + - 전용 서버나 가상 서버를 이용하는 것이 직접 구축하는 것보다 더 편할 수 있습니다. + - 단점은 서버 제공업체라는 제3자를 신뢰해야 한다는 점입니다. + - 풀 노드에 필요한 저장 공간 크기 때문에, 대여 서버의 가격이 비싸질 수 있습니다. +- 자체 하드웨어 + - 더 신뢰가 필요 없고 자주적인 접근 방식 + - 일회성 투자 + - 사전 구성된 머신을 구매하는 옵션 + - 머신과 네트워킹을 물리적으로 준비, 유지 관리하고 잠재적인 문제를 해결해야 합니다. + +두 옵션 모두 위에서 요약한 바와 같이 서로 다른 장점을 가지고 있습니다. 클라우드 솔루션을 찾고 있다면, 많은 전통적인 클라우드 컴퓨팅 제공업체 외에도 노드 배포에 중점을 둔 서비스도 있습니다. 호스팅된 노드에 대한 더 많은 옵션을 보려면 [서비스형 노드](/developers/docs/nodes-and-clients/nodes-as-a-service/)를 확인하세요. + +#### 하드웨어 {#hardware} + +그러나 검열 저항적인 탈중앙화 네트워크는 클라우드 제공업체에 의존해서는 안 됩니다. 대신, 자체 로컬 하드웨어에서 노드를 실행하는 것이 생태계에 더 건강합니다. [추정치](https://www.ethernodes.org/networkType/cl/Hosting)에 따르면 상당수의 노드가 클라우드에서 실행되고 있으며, 이는 단일 장애점이 될 수 있습니다. + +이더리움 클라이언트는 컴퓨터, 노트북, 서버, 심지어 단일 보드 컴퓨터에서도 실행할 수 있습니다. 개인용 컴퓨터에서 클라이언트를 실행하는 것도 가능하지만, 노드 전용 머신을 사용하면 주 컴퓨터에 미치는 영향을 최소화하면서 성능과 보안을 크게 향상시킬 수 있습니다. + +자체 하드웨어를 사용하는 것은 매우 쉬울 수 있습니다. 기술적인 지식이 있는 사람들을 위한 고급 설정뿐만 아니라 많은 간단한 옵션이 있습니다. 그럼 여러분의 머신에서 이더리움 클라이언트를 실행하기 위한 요구사항과 수단을 살펴보겠습니다. + +#### 요구사항 {#requirements} + +하드웨어 요구사항은 클라이언트마다 다르지만, 노드는 동기화 상태만 유지하면 되므로 일반적으로 그렇게 높지 않습니다. 훨씬 더 많은 컴퓨팅 파워를 필요로 하는 채굴과 혼동하지 마세요. 하지만 더 강력한 하드웨어를 사용하면 동기화 시간과 성능이 향상됩니다. + +클라이언트를 설치하기 전에 컴퓨터에 실행할 수 있는 충분한 리소스가 있는지 확인하십시오. 최소 및 권장 요구사항은 아래에서 확인할 수 있습니다. + +하드웨어의 병목 현상은 대부분 디스크 공간입니다. 이더리움 블록체인을 동기화하는 것은 입출력이 매우 많고 많은 공간을 필요로 합니다. 동기화 후에도 수백 GB의 여유 공간이 있는 솔리드 스테이트 드라이브(SSD)를 사용하는 것이 가장 좋습니다. + +데이터베이스의 크기와 초기 동기화 속도는 선택한 클라이언트, 구성 및 [동기화 전략](/developers/docs/nodes-and-clients/#sync-modes)에 따라 다릅니다. + +또한 인터넷 연결이 [대역폭 상한](https://wikipedia.org/wiki/Data_cap)에 의해 제한되지 않는지 확인하세요. 초기 동기화 및 네트워크로 브로드캐스트되는 데이터가 제한을 초과할 수 있으므로 무제한 연결을 사용하는 것이 좋습니다. + +##### 운영 체제 + +모든 클라이언트는 주요 운영 체제(Linux, MacOS, Windows)를 지원합니다. 이는 자신에게 가장 적합한 운영 체제(OS)가 설치된 일반 데스크톱이나 서버 컴퓨터에서 노드를 실행할 수 있음을 의미합니다. 잠재적인 문제와 보안 취약점을 피하기 위해 OS를 최신 상태로 유지하십시오. + +##### 최소 요구사항 + +- 2코어 이상 CPU +- 8GB RAM +- 2TB SSD +- 10 MBit/s 이상 대역폭 + +##### 권장 사양 + +- 4코어 이상의 빠른 CPU +- 16GB 이상 RAM +- 2TB 이상의 빠른 SSD +- 25 MBit/s 이상 대역폭 + +선택한 동기화 모드와 클라이언트는 공간 요구사항에 영향을 미치지만, 아래에 각 클라이언트에 필요한 디스크 공간을 추정해 두었습니다. + +| 클라이언트 | 디스크 크기(스냅 동기화) | 디스크 크기(전체 아카이브) | +| ---------- | --------------------------------- | ---------------------------------- | +| Besu | 800GB+ | 12TB+ | +| Erigon | 해당 없음 | 2.5TB+ | +| Geth | 500GB+ | 12TB+ | +| Nethermind | 500GB+ | 12TB+ | +| Reth | 해당 없음 | 2.2TB+ | + +- 참고: Erigon과 Reth는 스냅 동기화를 제공하지 않지만, 전체 정리(Full Pruning)는 가능합니다(Erigon의 경우 약 2TB, Reth의 경우 약 1.2TB). + +합의 클라이언트의 경우, 공간 요구사항은 클라이언트 구현 및 활성화된 기능(예: 검증인 슬래셔)에 따라 다르지만, 일반적으로 비콘 데이터에 추가로 200GB가 필요하다고 생각하면 됩니다. 검증인 수가 많아지면 대역폭 부하도 증가합니다. [이 분석](https://mirror.xyz/0x934e6B4D7eee305F8C9C42b46D6EEA09CcFd5EDc/b69LBy8p5UhcGJqUAmT22dpvdkU-Pulg2inrhoS9Mbc)에서 합의 클라이언트 요구사항에 대한 자세한 내용을 확인할 수 있습니다. + +#### 플러그 앤 플레이 솔루션 {#plug-and-play} + +자체 하드웨어로 노드를 실행하는 가장 쉬운 방법은 플러그 앤 플레이 박스를 사용하는 것입니다. 공급업체의 사전 구성된 머신은 가장 간단한 경험을 제공합니다. 주문하고, 연결하고, 실행하면 됩니다. 소프트웨어를 모니터링하고 제어하기 위한 직관적인 가이드와 대시보드를 통해 모든 것이 사전 구성되어 자동으로 실행됩니다. + +- [DappNode](https://dappnode.io/) +- [Avado](https://ava.do/) + +#### 단일 보드 컴퓨터의 이더리움 {#ethereum-on-a-single-board-computer} + +이더리움 노드를 실행하는 쉽고 저렴한 방법은 라즈베리 파이(Raspberry Pi)와 같은 ARM 아키텍처를 가진 단일 보드 컴퓨터를 사용하는 것입니다. [ARM 기반 이더리움(Ethereum on ARM)](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/)은 라즈베리 파이 및 기타 ARM 보드를 위한 여러 실행 및 합의 클라이언트의 실행하기 쉬운 이미지를 제공합니다. + +이러한 작고 저렴하며 효율적인 장치는 집에서 노드를 실행하는 데 이상적이지만 성능이 제한적이라는 점을 명심하십시오. + +## 노드 가동하기 {#spinning-up-node} + +실제 클라이언트 설정은 자동화된 런처를 사용하거나 클라이언트 소프트웨어를 직접 설정하여 수동으로 수행할 수 있습니다. + +고급 사용자가 아닌 경우, 설치를 안내하고 클라이언트 설정 프로세스를 자동화하는 소프트웨어인 런처를 사용하는 것이 좋습니다. 하지만 터미널 사용 경험이 있다면 수동 설정 단계도 쉽게 따라 할 수 있을 것입니다. + +### 가이드 설정 {#automatized-setup} + +여러 사용자 친화적인 프로젝트는 클라이언트 설정 경험을 향상시키는 것을 목표로 합니다. 이러한 런처는 자동 클라이언트 설치 및 구성을 제공하며, 일부는 클라이언트의 가이드 설정 및 모니터링을 위한 그래픽 인터페이스를 제공하기도 합니다. + +다음은 몇 번의 클릭만으로 클라이언트를 설치하고 제어하는 데 도움이 되는 몇 가지 프로젝트입니다. + +- [DappNode](https://docs.dappnode.io/docs/user/getting-started/choose-your-path) - DappNode는 공급업체의 머신만 제공하는 것이 아닙니다. 소프트웨어, 실제 노드 런처 및 많은 기능을 갖춘 제어 센터는 임의의 하드웨어에서 사용할 수 있습니다. +- [EthPillar](https://www.coincashew.com/coins/overview-eth/ethpillar) - 풀 노드를 설정하는 가장 빠르고 쉬운 방법입니다. 원라이너 설정 도구 및 노드 관리 TUI. 무료입니다. 오픈 소스. 단독 스테이커에 의한 이더리움을 위한 공공재입니다. ARM64 및 AMD64 지원. +- [eth-docker](https://eth-docker.net/) - 쉽고 안전한 스테이킹에 중점을 둔 Docker를 사용한 자동 설정으로, 기본적인 터미널 및 Docker 지식이 필요하며, 약간 더 고급 사용자에게 권장됩니다. +- [Stereum](https://stereum-dev.github.io/ethereum-node-web-docs) - GUI 설정 가이드, 제어 센터 및 기타 여러 기능과 함께 SSH 연결을 통해 원격 서버에 클라이언트를 설치하기 위한 런처입니다. +- [NiceNode](https://www.nicenode.xyz/) - 컴퓨터에서 노드를 실행하기 위한 간단한 사용자 경험을 제공하는 런처입니다. 클라이언트를 선택하고 몇 번의 클릭만으로 시작하세요. 아직 개발 중입니다. +- [Sedge](https://docs.sedge.nethermind.io/docs/intro) - CLI 마법사를 사용하여 Docker 구성을 자동으로 생성하는 노드 설정 도구입니다. Nethermind에서 Go로 작성되었습니다. + +### 수동 클라이언트 설정 {#manual-setup} + +다른 옵션은 클라이언트 소프트웨어를 수동으로 다운로드, 확인 및 구성하는 것입니다. 일부 클라이언트는 그래픽 인터페이스를 제공하지만, 수동 설정은 여전히 터미널에 대한 기본적인 기술이 필요하지만 훨씬 더 많은 다용성을 제공합니다. + +앞서 설명했듯이, 자체 이더리움 노드를 설정하려면 합의 및 실행 클라이언트 쌍을 실행해야 합니다. 일부 클라이언트는 다른 종류의 라이트 클라이언트를 포함할 수 있으며 다른 소프트웨어 없이도 동기화할 수 있습니다. 하지만 완전한 무신뢰 검증을 위해서는 두 구현이 모두 필요합니다. + +#### 클라이언트 소프트웨어 받기 {#getting-the-client} + +먼저 선호하는 [실행 클라이언트](/developers/docs/nodes-and-clients/#execution-clients)와 [합의 클라이언트](/developers/docs/nodes-and-clients/#consensus-clients) 소프트웨어를 구해야 합니다. + +운영 체제와 아키텍처에 맞는 실행 가능한 애플리케이션이나 설치 패키지를 간단히 다운로드할 수 있습니다. 다운로드한 패키지의 서명과 체크섬을 항상 확인하십시오. 일부 클라이언트는 더 쉬운 설치 및 업데이트를 위해 리포지토리 또는 Docker 이미지를 제공하기도 합니다. 모든 클라이언트는 오픈 소스이므로 소스에서 직접 빌드할 수도 있습니다. 이것은 더 고급 방법이지만, 경우에 따라 필요할 수 있습니다. + +각 클라이언트 설치 지침은 위 클라이언트 목록에 링크된 문서에서 제공됩니다. + +다음은 사전 빌드된 바이너리 또는 설치 지침을 찾을 수 있는 클라이언트의 릴리스 페이지입니다. + +##### 실행 클라이언트 + +- [Besu](https://github.com/hyperledger/besu/releases) +- [Erigon](https://github.com/ledgerwatch/erigon/releases) +- [Geth](https://geth.ethereum.org/downloads/) +- [Nethermind](https://downloads.nethermind.io/) +- [Reth](https://reth.rs/installation/installation.html) + +클라이언트 다양성은 [실행 레이어의 문제](/developers/docs/nodes-and-clients/client-diversity/#execution-layer)라는 점도 주목할 가치가 있습니다. 독자들은 소수 실행 클라이언트를 실행하는 것을 고려하는 것이 좋습니다. + +##### 합의 클라이언트 + +- [Lighthouse](https://github.com/sigp/lighthouse/releases/latest) +- [Lodestar](https://chainsafe.github.io/lodestar/run/getting-started/installation#build-from-source) (사전 빌드된 바이너리를 제공하지 않으며, Docker 이미지 또는 소스에서 빌드해야 함) +- [Nimbus](https://github.com/status-im/nimbus-eth2/releases/latest) +- [Prysm](https://github.com/prysmaticlabs/prysm/releases/latest) +- [Teku](https://github.com/ConsenSys/teku/releases) + +[클라이언트 다양성](/developers/docs/nodes-and-clients/client-diversity/)은 검증인을 실행하는 합의 노드에 매우 중요합니다. 대부분의 검증인이 단일 클라이언트 구현을 실행하면 네트워크 보안이 위험에 처합니다. 따라서 소수 클라이언트를 선택하는 것을 고려하는 것이 좋습니다. + +[최신 네트워크 클라이언트 사용 현황 보기](https://clientdiversity.org/) 및 [클라이언트 다양성](/developers/docs/nodes-and-clients/client-diversity)에 대해 자세히 알아보세요. + +##### 소프트웨어 확인 + +인터넷에서 소프트웨어를 다운로드할 때는 무결성을 확인하는 것이 좋습니다. 이 단계는 선택 사항이지만, 특히 이더리움 클라이언트와 같은 중요한 인프라 구성 요소의 경우 잠재적인 공격 벡터를 인식하고 이를 피하는 것이 중요합니다. 사전 빌드된 바이너리를 다운로드했다면, 이를 신뢰해야 하며 공격자가 실행 파일을 악성 파일로 바꿀 수 있는 위험을 감수해야 합니다. + +개발자들은 릴리스된 바이너리를 PGP 키로 서명하므로, 여러분이 실행하는 소프트웨어가 정확히 그들이 만든 것임을 암호학적으로 확인할 수 있습니다. 개발자들이 사용하는 공개 키를 얻기만 하면 되며, 이는 클라이언트 릴리스 페이지나 문서에서 찾을 수 있습니다. 클라이언트 릴리스와 서명을 다운로드한 후, [GnuPG](https://gnupg.org/download/index.html)와 같은 PGP 구현을 사용하여 쉽게 확인할 수 있습니다. [Linux](https://www.tecmint.com/verify-pgp-signature-downloaded-software/) 또는 [Windows/MacOS](https://freedom.press/training/verifying-open-source-software/)에서 `gpg`를 사용하여 오픈 소스 소프트웨어를 확인하는 튜토리얼을 확인하십시오. + +또 다른 확인 방법은 다운로드한 소프트웨어의 해시(고유한 암호화 지문)가 개발자가 제공한 것과 일치하는지 확인하는 것입니다. 이것은 PGP를 사용하는 것보다 훨씬 쉬우며, 일부 클라이언트는 이 옵션만 제공합니다. 다운로드한 소프트웨어에서 해시 함수를 실행하고 릴리스 페이지의 것과 비교하기만 하면 됩니다. 예를 들어, + +```sh +sha256sum teku-22.6.1.tar.gz + +9b2f8c1f8d4dab0404ce70ea314ff4b3c77e9d27aff9d1e4c1933a5439767dde +``` + +#### 클라이언트 설정 {#client-setup} + +클라이언트 소프트웨어를 설치, 다운로드 또는 컴파일한 후에는 실행할 준비가 된 것입니다. 이는 적절한 구성으로 실행해야 함을 의미합니다. 클라이언트는 다양한 기능을 활성화할 수 있는 풍부한 구성 옵션을 제공합니다. + +클라이언트 성능과 데이터 사용량에 상당한 영향을 미칠 수 있는 옵션부터 시작하겠습니다. [동기화 모드](/developers/docs/nodes-and-clients/#sync-modes)는 블록체인 데이터를 다운로드하고 검증하는 다양한 방법을 나타냅니다. 노드를 시작하기 전에 사용할 네트워크와 동기화 모드를 결정해야 합니다. 가장 중요하게 고려해야 할 사항은 클라이언트에 필요한 디스크 공간과 동기화 시간입니다. 기본 동기화 모드가 무엇인지 확인하려면 클라이언트 문서를 주의 깊게 살펴보십시오. 그것이 마음에 들지 않으면 보안 수준, 사용 가능한 데이터 및 비용에 따라 다른 것을 선택하십시오. 동기화 알고리즘 외에도 다양한 종류의 오래된 데이터를 정리하도록 설정할 수도 있습니다. 정리를 사용하면 오래된 데이터를 삭제할 수 있습니다. 즉, 최근 블록에서 도달할 수 없는 상태 트리 노드를 제거합니다. + +다른 기본 구성 옵션으로는 네트워크(메인넷 또는 테스트넷) 선택, RPC 또는 웹소켓을 위한 HTTP 엔드포인트 활성화 등이 있습니다. 모든 기능과 옵션은 클라이언트 문서에서 찾을 수 있습니다. 다양한 클라이언트 구성은 CLI 또는 구성 파일에서 직접 해당 플래그로 클라이언트를 실행하여 설정할 수 있습니다. 각 클라이언트는 약간씩 다릅니다. 구성 옵션에 대한 자세한 내용은 항상 공식 문서나 도움말 페이지를 참조하십시오. + +테스트 목적으로, 테스트넷 네트워크 중 하나에서 클라이언트를 실행하는 것을 선호할 수 있습니다. [지원되는 네트워크 개요 보기](/developers/docs/nodes-and-clients/#execution-clients). + +기본 구성을 갖춘 실행 클라이언트 실행 예제는 다음 섹션에서 찾을 수 있습니다. + +#### 실행 클라이언트 시작하기 {#starting-the-execution-client} + +이더리움 클라이언트 소프트웨어를 시작하기 전에 환경이 준비되었는지 마지막으로 확인하십시오. 예를 들어, 다음을 확인하십시오. + +- 선택한 네트워크와 동기화 모드를 고려하여 충분한 디스크 공간이 있는지 확인합니다. +- 메모리와 CPU가 다른 프로그램에 의해 중단되지 않았는지 확인합니다. +- 운영 체제가 최신 버전으로 업데이트되었는지 확인합니다. +- 시스템의 시간과 날짜가 정확한지 확인합니다. +- 라우터와 방화벽이 수신 포트에서 연결을 허용하는지 확인합니다. 기본적으로 이더리움 클라이언트는 수신기(TCP) 포트와 검색(UDP) 포트를 사용하며, 둘 다 기본적으로 30303입니다. + +모든 것이 올바르게 작동하는지 확인하기 위해 먼저 테스트넷에서 클라이언트를 실행하십시오. + +기본값이 아닌 클라이언트 설정은 시작 시 선언해야 합니다. 플래그나 구성 파일을 사용하여 선호하는 구성을 선언할 수 있습니다. 각 클라이언트의 기능 집합과 구성 구문은 다릅니다. 자세한 내용은 클라이언트 문서를 확인하십시오. + +실행 및 합의 클라이언트는 [Engine API](https://github.com/ethereum/execution-apis/tree/main/src/engine)에 명시된 인증된 엔드포인트를 통해 통신합니다. 합의 클라이언트에 연결하려면 실행 클라이언트는 알려진 경로에 [`jwtsecret`](https://jwt.io/)을 생성해야 합니다. 보안 및 안정성상의 이유로 클라이언트는 동일한 머신에서 실행되어야 하며, 두 클라이언트 모두 로컬 RPC 연결을 인증하는 데 사용되므로 이 경로를 알아야 합니다. 실행 클라이언트는 또한 인증된 API에 대한 수신 포트를 정의해야 합니다. + +이 토큰은 클라이언트 소프트웨어에 의해 자동으로 생성되지만, 경우에 따라 직접 생성해야 할 수도 있습니다. [OpenSSL](https://www.openssl.org/)을 사용하여 생성할 수 있습니다. + +```sh +openssl rand -hex 32 > jwtsecret +``` + +#### 실행 클라이언트 실행하기 {#running-an-execution-client} + +이 섹션에서는 실행 클라이언트를 시작하는 방법을 안내합니다. 이는 다음과 같은 설정으로 클라이언트를 시작하는 기본 구성의 예시일 뿐입니다. + +- 연결할 네트워크를 지정합니다. 이 예제에서는 메인넷입니다. + - 설정의 예비 테스트를 위해 [테스트넷 중 하나](/developers/docs/networks/)를 대신 선택할 수 있습니다. +- 블록체인을 포함한 모든 데이터가 저장될 데이터 디렉터리를 정의합니다. + - 경로를 실제 경로로 대체해야 합니다. 예를 들어 외부 드라이브를 가리키도록 합니다. +- 클라이언트와 통신하기 위한 인터페이스를 활성화합니다. + - 합의 클라이언트와 통신하기 위한 JSON-RPC 및 Engine API 포함 +- 인증된 API를 위한 `jwtsecret` 경로를 정의합니다. + - 예제 경로를 클라이언트가 액세스할 수 있는 실제 경로로 대체해야 합니다. 예: `/tmp/jwtsecret` + +이것은 기본적인 예제일 뿐이며, 다른 모든 설정은 기본값으로 설정됩니다. 기본값, 설정 및 기능에 대해 자세히 알아보려면 각 클라이언트의 문서를 주의 깊게 살펴보십시오. 검증인 실행, 모니터링 등과 같은 더 많은 기능을 사용하려면 특정 클라이언트의 문서를 참조하십시오. + +> 예제의 백슬래시 ``는 서식 목적으로만 사용되며, 구성 플래그는 한 줄로 정의할 수 있습니다. + +##### Besu 실행 + +이 예제는 메인넷에서 Besu를 시작하고, 블록체인 데이터를 `/data/ethereum`에 기본 형식으로 저장하며, 합의 클라이언트 연결을 위해 JSON-RPC 및 Engine RPC를 활성화합니다. Engine API는 토큰 `jwtsecret`로 인증되며 `localhost`에서의 호출만 허용됩니다. + +```sh +besu --network=mainnet \ + --data-path=/data/ethereum \ + --rpc-http-enabled=true \ + --engine-rpc-enabled=true \ + --engine-host-allowlist="*" \ + --engine-jwt-enabled=true \ + --engine-jwt-secret=/path/to/jwtsecret +``` + +Besu는 또한 일련의 질문을 하고 구성 파일을 생성하는 런처 옵션도 함께 제공됩니다. 다음을 사용하여 대화형 런처를 실행합니다. + +```sh +besu --Xlauncher +``` + +[Besu 문서](https://besu.hyperledger.org/public-networks/get-started/start-node/)에는 추가 옵션과 구성 세부 정보가 포함되어 있습니다. + +##### Erigon 실행 + +이 예제는 메인넷에서 Erigon을 시작하고, `/data/ethereum`에 블록체인 데이터를 저장하며, JSON-RPC를 활성화하고, 허용되는 네임스페이스를 정의하며, `jwtsecret` 경로로 정의된 합의 클라이언트 연결을 위한 인증을 활성화합니다. + +```sh +erigon --chain mainnet \ + --datadir /data/ethereum \ + --http --http.api=engine,eth,web3,net \ + --authrpc.jwtsecret=/path/to/jwtsecret +``` + +Erigon은 기본적으로 8GB HDD로 전체 동기화를 수행하며, 이로 인해 2TB 이상의 아카이브 데이터가 생성됩니다. `datadir`이 충분한 여유 공간이 있는 디스크를 가리키는지 확인하거나, 다양한 종류의 데이터를 정리할 수 있는 `--prune` 플래그를 살펴보십시오. 자세한 내용은 Erigon의 `--help`를 확인하십시오. + +##### Geth 실행 + +이 예제는 메인넷에서 Geth를 시작하고, `/data/ethereum`에 블록체인 데이터를 저장하며, JSON-RPC를 활성화하고 허용되는 네임스페이스를 정의합니다. 또한 합의 클라이언트 연결을 위한 인증을 활성화하며, 이는 `jwtsecret` 경로와 허용되는 연결을 정의하는 옵션(이 예제에서는 `localhost`에서만)이 필요합니다. + +```sh +geth --mainnet \ + --datadir "/data/ethereum" \ + --http --authrpc.addr localhost \ + --authrpc.vhosts="localhost" \ + --authrpc.port 8551 + --authrpc.jwtsecret=/path/to/jwtsecret +``` + +모든 구성 옵션에 대한 [문서](https://geth.ethereum.org/docs/fundamentals/command-line-options)를 확인하고 [합의 클라이언트와 함께 Geth 실행](https://geth.ethereum.org/docs/getting-started/consensus-clients)에 대해 자세히 알아보십시오. + +##### Nethermind 실행 + +Nethermind는 다양한 [설치 옵션](https://docs.nethermind.io/get-started/installing-nethermind)을 제공합니다. 패키지에는 가이드 설정이 포함된 런처를 비롯한 다양한 바이너리가 포함되어 있어 대화형으로 구성을 생성하는 데 도움이 됩니다. 또는 실행 파일 자체인 Runner를 찾아 구성 플래그와 함께 실행할 수 있습니다. JSON-RPC는 기본적으로 활성화되어 있습니다. + +```sh +Nethermind.Runner --config mainnet \ + --datadir /data/ethereum \ + --JsonRpc.JwtSecretFile=/path/to/jwtsecret +``` + +Nethermind 문서는 합의 클라이언트와 함께 Nethermind를 실행하는 [완벽한 가이드](https://docs.nethermind.io/get-started/running-node/)를 제공합니다. + +실행 클라이언트는 핵심 기능, 선택된 엔드포인트를 초기화하고 피어를 찾기 시작합니다. 피어를 성공적으로 발견한 후 클라이언트는 동기화를 시작합니다. 실행 클라이언트는 합의 클라이언트로부터의 연결을 기다립니다. 클라이언트가 현재 상태로 성공적으로 동기화되면 현재 블록체인 데이터를 사용할 수 있습니다. + +##### Reth 실행 + +이 예제는 기본 데이터 위치를 사용하여 메인넷에서 Reth를 시작합니다. JSON-RPC 및 Engine RPC 인증을 활성화하여 `jwtsecret` 경로로 정의된 합의 클라이언트에 연결하며, `localhost`에서의 호출만 허용됩니다. + +```sh +reth node \ + --authrpc.jwtsecret /path/to/jwtsecret \ + --authrpc.addr 127.0.0.1 \ + --authrpc.port 8551 +``` + +기본 데이터 디렉터리에 대해 자세히 알아보려면 [Reth 구성](https://reth.rs/run/config.html?highlight=data%20directory#configuring-reth)을 참조하십시오. [Reth의 문서](https://reth.rs/run/mainnet.html)에는 추가 옵션과 구성 세부 정보가 포함되어 있습니다. + +#### 합의 클라이언트 시작하기 {#starting-the-consensus-client} + +합의 클라이언트는 실행 클라이언트와의 로컬 RPC 연결을 설정하기 위해 올바른 포트 구성으로 시작해야 합니다. 합의 클라이언트는 노출된 실행 클라이언트 포트를 구성 인수로 사용하여 실행해야 합니다. + +합의 클라이언트는 또한 둘 사이의 RPC 연결을 인증하기 위해 실행 클라이언트의 `jwt-secret` 경로가 필요합니다. 위의 실행 예제와 유사하게, 각 합의 클라이언트에는 jwt 토큰 파일 경로를 인수로 받는 구성 플래그가 있습니다. 이는 실행 클라이언트에 제공된 `jwtsecret` 경로와 일치해야 합니다. + +검증인을 실행할 계획이라면, 수수료 수령인의 이더리움 주소를 지정하는 구성 플래그를 추가해야 합니다. 이곳에 검증인에 대한 이더 보상이 누적됩니다. 각 합의 클라이언트에는 `--suggested-fee-recipient=0xabcd1`과 같은 옵션이 있으며, 이는 이더리움 주소를 인수로 받습니다. + +테스트넷에서 비콘 노드를 시작할 때, [체크포인트 동기화](https://notes.ethereum.org/@launchpad/checkpoint-sync)를 위한 공개 엔드포인트를 사용하여 동기화 시간을 크게 절약할 수 있습니다. + +#### 합의 클라이언트 실행하기 {#running-a-consensus-client} + +##### Lighthouse 실행 + +Lighthouse를 실행하기 전에 [Lighthouse Book](https://lighthouse-book.sigmaprime.io/installation.html)에서 설치 및 구성 방법을 자세히 알아보십시오. + +```sh +lighthouse beacon_node \ + --network mainnet \ + --datadir /data/ethereum \ + --http \ + --execution-endpoint http://127.0.0.1:8551 \ + --execution-jwt /path/to/jwtsecret +``` + +##### Lodestar 실행 + +Lodestar 소프트웨어를 컴파일하거나 Docker 이미지를 다운로드하여 설치하십시오. [문서](https://chainsafe.github.io/lodestar/)와 더 포괄적인 [설정 가이드](https://hackmd.io/@philknows/rk5cDvKmK)에서 자세히 알아보십시오. + +```sh +lodestar beacon \ + --dataDir="/data/ethereum" \ + --network=mainnet \ + --eth1.enabled=true \ + --execution.urls="http://127.0.0.1:8551" \ + --jwt-secret="/path/to/jwtsecret" +``` + +##### Nimbus 실행 + +Nimbus에는 합의 및 실행 클라이언트가 모두 포함되어 있습니다. 매우 낮은 컴퓨팅 파워를 가진 다양한 장치에서도 실행할 수 있습니다. +[의존성 및 Nimbus 자체를 설치](https://nimbus.guide/quick-start.html)한 후, 합의 클라이언트를 실행할 수 있습니다. + +```sh +nimbus_beacon_node \ + --network=mainnet \ + --web3-url=http://127.0.0.1:8551 \ + --rest \ + --jwt-secret="/path/to/jwtsecret" +``` + +##### Prysm 실행 + +Prysm은 쉬운 자동 설치를 허용하는 스크립트와 함께 제공됩니다. 자세한 내용은 [Prysm 문서](https://prysm.offchainlabs.com/docs/install-prysm/install-with-script/)에서 찾을 수 있습니다. + +```sh +./prysm.sh beacon-chain \ + --mainnet \ + --datadir /data/ethereum \ + --execution-endpoint=http://localhost:8551 \ + --jwt-secret=/path/to/jwtsecret +``` + +##### Teku 실행 + +```sh +teku --network mainnet \ + --data-path "/data/ethereum" \ + --ee-endpoint http://localhost:8551 \ + --ee-jwt-secret-file "/path/to/jwtsecret" +``` + +합의 클라이언트가 실행 클라이언트에 연결하여 예치 계약을 읽고 검증인을 식별하면, 다른 비콘 노드 피어에도 연결하여 제네시스로부터 합의 슬롯을 동기화하기 시작합니다. 비콘 노드가 현재 에포크에 도달하면, 비콘 API를 검증인에게 사용할 수 있게 됩니다. [비콘 노드 API](https://eth2docs.vercel.app/)에 대해 자세히 알아보세요. + +### 검증인 추가하기 {#adding-validators} + +합의 클라이언트는 검증인이 연결할 비콘 노드 역할을 합니다. 각 합의 클라이언트에는 해당 문서에 자세히 설명된 자체 검증인 소프트웨어가 있습니다. + +자체 검증인을 실행하면 이더리움 네트워크를 지원하는 가장 영향력 있고 신뢰가 필요 없는 방법인 [단독 스테이킹](/staking/solo/)이 가능합니다. 그러나 이를 위해서는 32 ETH의 예치금이 필요합니다. 더 적은 금액으로 자체 노드에서 검증인을 실행하려면 [Rocket Pool](https://rocketpool.net/node-operators)과 같은 무허가 노드 운영자를 갖춘 탈중앙화 풀에 관심이 있을 수 있습니다. + +스테이킹 및 검증인 키 생성을 시작하는 가장 쉬운 방법은 [Hoodi 테스트넷 스테이킹 런치패드](https://hoodi.launchpad.ethereum.org/)를 사용하는 것입니다. 이를 통해 [Hoodi에서 노드를 실행](https://notes.ethereum.org/@launchpad/hoodi)하여 설정을 테스트할 수 있습니다. 메인넷 준비가 되면 [메인넷 스테이킹 런치패드](https://launchpad.ethereum.org/)를 사용하여 이 단계를 반복할 수 있습니다. + +스테이킹 옵션에 대한 개요는 [스테이킹 페이지](/staking)를 참조하십시오. + +### 노드 사용하기 {#using-the-node} + +실행 클라이언트는 트랜잭션을 제출하고, 스마트 계약과 상호 작용하거나 이더리움 네트워크에 배포하는 등 다양한 방식으로 사용할 수 있는 [RPC API 엔드포인트](/developers/docs/apis/json-rpc/)를 제공합니다. + +- 적절한 프로토콜(예: `curl` 사용)로 수동 호출 +- 제공된 콘솔 연결(예: `geth attach`) +- web3 라이브러리(예: [web3.py](https://web3py.readthedocs.io/en/stable/overview.html#overview), [ethers](https://github.com/ethers-io/ethers.js/))를 사용하여 애플리케이션에 구현 + +클라이언트마다 RPC 엔드포인트 구현이 다릅니다. 하지만 모든 클라이언트에서 사용할 수 있는 표준 JSON-RPC가 있습니다. 개요는 [JSON-RPC 문서](/developers/docs/apis/json-rpc/)를 읽어보십시오. 이더리움 네트워크의 정보가 필요한 애플리케이션은 이 RPC를 사용할 수 있습니다. 예를 들어, 인기 있는 지갑인 MetaMask는 강력한 개인 정보 보호 및 보안 이점을 제공하는 [자체 RPC 엔드포인트에 연결](https://metamask.zendesk.com/hc/en-us/articles/360015290012-Using-a-Local-Node)할 수 있습니다. + +모든 합의 클라이언트는 [Curl](https://curl.se)과 같은 도구를 사용하여 요청을 보내 합의 클라이언트의 상태를 확인하거나 블록 및 합의 데이터를 다운로드하는 데 사용할 수 있는 [비콘 API](https://ethereum.github.io/beacon-APIs)를 노출합니다. 이에 대한 자세한 정보는 각 합의 클라이언트의 문서에서 찾을 수 있습니다. + +#### RPC 연결하기 {#reaching-rpc} + +실행 클라이언트 JSON-RPC의 기본 포트는 `8545`이지만, 구성에서 로컬 엔드포인트의 포트를 수정할 수 있습니다. 기본적으로 RPC 인터페이스는 컴퓨터의 localhost에서만 연결할 수 있습니다. 원격으로 액세스할 수 있도록 하려면 주소를 `0.0.0.0`으로 변경하여 공개적으로 노출할 수 있습니다. 이렇게 하면 로컬 네트워크 및 공용 IP 주소를 통해 연결할 수 있습니다. 대부분의 경우 라우터에서 포트 포워딩을 설정해야 합니다. + +인터넷에 포트를 노출하는 것은 인터넷상의 모든 사람이 노드를 제어할 수 있게 하므로 주의해서 접근하십시오. 클라이언트를 지갑으로 사용하는 경우, 악의적인 행위자가 노드에 액세스하여 시스템을 다운시키거나 자금을 훔칠 수 있습니다. + +이를 해결하는 방법은 잠재적으로 유해한 RPC 메서드가 수정되지 않도록 하는 것입니다. 예를 들어, Geth에서는 `--http.api web3,eth,txpool`과 같은 플래그로 수정 가능한 메서드를 선언할 수 있습니다. + +RPC 인터페이스에 대한 액세스는 엣지 레이어 API 또는 Nginx와 같은 웹 서버 애플리케이션을 개발하고 이를 클라이언트의 로컬 주소 및 포트에 연결하여 확장할 수 있습니다. 중간 계층을 활용하면 개발자는 RPC 인터페이스에 대한 보안 `https` 연결을 위해 인증서를 설정할 수도 있습니다. + +웹 서버, 프록시 또는 외부용 Rest API를 설정하는 것이 노드의 RPC 엔드포인트에 대한 액세스를 제공하는 유일한 방법은 아닙니다. 공개적으로 연결 가능한 엔드포인트를 설정하는 또 다른 개인 정보 보호 방법은 자체 [Tor](https://www.torproject.org/) 어니언 서비스에서 노드를 호스팅하는 것입니다. 이렇게 하면 고정 공용 IP 주소나 열린 포트 없이 로컬 네트워크 외부에서 RPC에 연결할 수 있습니다. 그러나 이 구성을 사용하면 모든 애플리케이션에서 지원되지 않는 Tor 네트워크를 통해서만 RPC 엔드포인트에 액세스할 수 있으며 연결 문제가 발생할 수 있습니다. + +이를 위해서는 자신만의 [어니언 서비스](https://community.torproject.org/onion-services/)를 만들어야 합니다. 자체 호스팅을 위해 어니언 서비스 설정에 대한 [문서](https://community.torproject.org/onion-services/setup/)를 확인하십시오. RPC 포트로 프록시하는 웹 서버를 가리키거나 그냥 RPC로 직접 가리킬 수 있습니다. + +마지막으로, 내부 네트워크에 대한 액세스를 제공하는 가장 인기 있는 방법 중 하나는 VPN 연결을 통하는 것입니다. 사용 사례와 노드에 액세스해야 하는 사용자 수에 따라 보안 VPN 연결이 옵션이 될 수 있습니다. [OpenVPN](https://openvpn.net/)은 업계 표준 SSL/TLS 프로토콜을 사용하여 OSI 레이어 2 또는 3 보안 네트워크 확장을 구현하는 모든 기능을 갖춘 SSL VPN으로, 인증서, 스마트카드 및/또는 사용자 이름/비밀번호 자격 증명을 기반으로 하는 유연한 클라이언트 인증 방법을 지원하며, VPN 가상 인터페이스에 적용되는 방화벽 규칙을 사용하여 사용자 또는 그룹별 액세스 제어 정책을 허용합니다. + +### 노드 운영하기 {#operating-the-node} + +노드가 제대로 실행되고 있는지 확인하기 위해 정기적으로 모니터링해야 합니다. 가끔 유지 관리를 해야 할 수도 있습니다. + +#### 노드를 온라인 상태로 유지하기 {#keeping-node-online} + +노드가 항상 온라인 상태일 필요는 없지만, 네트워크와 동기화 상태를 유지하기 위해 가능한 한 온라인 상태를 유지해야 합니다. 다시 시작하기 위해 종료할 수 있지만 다음 사항에 유의하십시오. + +- 최근 상태가 아직 디스크에 기록되는 중이면 종료하는 데 몇 분이 걸릴 수 있습니다. +- 강제 종료는 데이터베이스를 손상시켜 전체 노드를 다시 동기화해야 할 수 있습니다. +- 클라이언트가 네트워크와 동기화되지 않으며 다시 시작할 때 다시 동기화해야 합니다. 노드가 마지막으로 종료된 위치에서 동기화를 시작할 수 있지만, 오프라인 상태였던 기간에 따라 프로세스에 시간이 걸릴 수 있습니다. + +_이는 합의 레이어 검증인 노드에는 적용되지 않습니다._ 노드를 오프라인으로 전환하면 노드에 의존하는 모든 서비스에 영향을 미칩니다. _스테이킹_ 목적으로 노드를 실행하는 경우 가동 중지 시간을 최대한 최소화해야 합니다. + +#### 클라이언트 서비스 생성하기 {#creating-client-services} + +시작 시 클라이언트를 자동으로 실행하는 서비스를 만드는 것을 고려하십시오. 예를 들어, Linux 서버에서는 `systemd`와 같은 서비스로 클라이언트를 적절한 구성으로 실행하고, 제한된 권한을 가진 사용자 아래에서 실행하며 자동으로 다시 시작하는 것이 좋은 방법입니다. + +#### 클라이언트 업데이트하기 {#updating-clients} + +클라이언트 소프트웨어를 최신 보안 패치, 기능 및 [EIP](/eips/)로 최신 상태로 유지해야 합니다. 특히 [하드 포크](/ethereum-forks/) 전에는 올바른 클라이언트 버전을 실행하고 있는지 확인하십시오. + +> 중요한 네트워크 업데이트 전에 EF는 [블로그](https://blog.ethereum.org)에 게시물을 올립니다. 노드에 업데이트가 필요할 때 메일로 알림을 받으려면 [이러한 공지사항을 구독](https://blog.ethereum.org/category/protocol#subscribe)할 수 있습니다. + +클라이언트 업데이트는 매우 간단합니다. 각 클라이언트의 문서에는 구체적인 지침이 있지만, 일반적으로 최신 버전을 다운로드하고 새 실행 파일로 클라이언트를 다시 시작하는 과정입니다. 클라이언트는 업데이트가 적용된 상태에서 중단된 지점부터 다시 시작해야 합니다. + +각 클라이언트 구현에는 피어 투 피어 프로토콜에서 사용되지만 명령줄에서도 액세스할 수 있는 사람이 읽을 수 있는 버전 문자열이 있습니다. 이 버전 문자열을 통해 사용자는 올바른 버전을 실행하고 있는지 확인할 수 있으며, 블록 탐색기 및 기타 분석 도구는 네트워크를 통해 특정 클라이언트의 분포를 정량화하는 데 관심이 있습니다. 버전 문자열에 대한 자세한 정보는 개별 클라이언트 문서를 참조하십시오. + +#### 추가 서비스 실행하기 {#running-additional-services} + +자체 노드를 실행하면 이더리움 클라이언트 RPC에 직접 액세스해야 하는 서비스를 사용할 수 있습니다. 이들은 [레이어 2 솔루션](/developers/docs/scaling/#layer-2-scaling), 지갑용 백엔드, 블록 탐색기, 개발자 도구 및 기타 이더리움 인프라와 같이 이더리움 위에 구축된 서비스입니다. + +#### 노드 모니터링하기 {#monitoring-the-node} + +노드를 제대로 모니터링하려면 메트릭을 수집하는 것을 고려하십시오. 클라이언트는 노드에 대한 포괄적인 데이터를 얻을 수 있도록 메트릭 엔드포인트를 제공합니다. [InfluxDB](https://www.influxdata.com/get-influxdb/) 또는 [Prometheus](https://prometheus.io/)와 같은 도구를 사용하여 데이터베이스를 만들고, [Grafana](https://grafana.com/)와 같은 소프트웨어에서 시각화 및 차트로 변환할 수 있습니다. 이 소프트웨어를 사용하기 위한 많은 설정이 있으며, 노드와 네트워크 전체를 시각화할 수 있는 다양한 Grafana 대시보드가 있습니다. 예를 들어, [Geth 모니터링 튜토리얼](/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/)을 확인하십시오. + +모니터링의 일환으로 머신의 성능을 주시하십시오. 노드의 초기 동기화 중에 클라이언트 소프트웨어는 CPU와 RAM에 매우 부담을 줄 수 있습니다. Grafana 외에도 `htop` 또는 `uptime`과 같은 OS가 제공하는 도구를 사용하여 이를 수행할 수 있습니다. + +## 더 읽어보기 {#further-reading} + +- [이더리움 스테이킹 가이드](https://github.com/SomerEsat/ethereum-staking-guides) - _Somer Esat, 자주 업데이트됨_ +- [가이드 | 이더리움 스테이킹 메인넷에서 검증인을 설정하는 방법](https://www.coincashew.com/coins/overview-eth/guide-or-how-to-setup-a-validator-on-eth2-mainnet) _– CoinCashew, 자주 업데이트됨_ +- [테스트넷에서 검증인을 실행하는 ETHStaker 가이드](https://github.com/remyroy/ethstaker#guides) – _ETHStaker, 정기적으로 업데이트됨_ +- [이더리움 노드를 위한 샘플 AWS 블록체인 노드 러너 앱](https://aws-samples.github.io/aws-blockchain-node-runners/docs/Blueprints/Ethereum) - _AWS, 자주 업데이트됨_ +- [노드 운영자를 위한 병합 FAQ](https://notes.ethereum.org/@launchpad/node-faq-merge) - _2022년 7월_ +- [이더리움 풀 검증 노드가 되기 위한 하드웨어 요구사항 분석](https://medium.com/coinmonks/analyzing-the-hardware-requirements-to-be-an-ethereum-full-validated-node-dc064f167902) _– Albert Palau, 2018년 9월 24일_ +- [이더리움 전체 노드 실행하기: 동기 부여가 거의 없는 분들을 위한 안내서](https://medium.com/@JustinMLeroux/running-ethereum-full-nodes-a-guide-for-the-barely-motivated-a8a13e7a0d31) _– Justin Leroux, 2019년 11월 7일_ +- [이더리움 메인넷에서 Hyperledger Besu 노드 실행: 이점, 요구사항 및 설정](https://pegasys.tech/running-a-hyperledger-besu-node-on-the-ethereum-mainnet-benefits-requirements-and-setup/) _– Felipe Faraggi, 2020년 5월 7일_ +- [모니터링 스택으로 Nethermind 이더리움 클라이언트 배포](https://medium.com/nethermind-eth/deploying-nethermind-ethereum-client-with-monitoring-stack-55ce1622edbd) _– Nethermind.eth, 2020년 7월 8일_ + +## 관련 주제 {#related-topics} + +- [노드 및 클라이언트](/developers/docs/nodes-and-clients/) +- [블록](/developers/docs/blocks/) +- [네트워크](/developers/docs/networks/) diff --git a/public/content/translations/ko/developers/docs/oracles/index.md b/public/content/translations/ko/developers/docs/oracles/index.md new file mode 100644 index 00000000000..59422278341 --- /dev/null +++ b/public/content/translations/ko/developers/docs/oracles/index.md @@ -0,0 +1,433 @@ +--- +title: "오라클" +description: "오라클은 이더리움 스마트 계약에 실제 세계 데이터에 대한 액세스를 제공하여 사용자에게 더 많은 사용 사례와 더 큰 가치를 제공합니다." +lang: ko +--- + +오라클은 스마트 계약을 위해 오프체인 데이터 소스를 블록체인에서 사용할 수 있도록 하는 데이터 피드를 생성하는 애플리케이션입니다. 이는 이더리움 기반 스마트 계약이 기본적으로 블록체인 네트워크 외부에 저장된 정보에 액세스할 수 없기 때문에 필요합니다. + +스마트 계약에 오프체인 데이터를 사용하여 실행할 수 있는 기능을 제공하면 탈중앙화 애플리케이션의 유용성과 가치가 확장됩니다. 예를 들어, 온체인 예측 시장은 오라클에 의존하여 사용자 예측을 검증하는 데 사용하는 결과에 대한 정보를 제공합니다. Alice가 차기 미국 대통령이 될 사람에게 20 ETH를 걸었다고 가정해 보겠습니다. 대통령. 이 경우 예측 시장 탈중앙화앱은 선거 결과를 확인하고 Alice가 지불금을 받을 자격이 있는지 판단하기 위해 오라클이 필요합니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지에서는 독자가 [노드](/developers/docs/nodes-and-clients/), [합의 메커니즘](/developers/docs/consensus-mechanisms/), [EVM](/developers/docs/evm/)을 비롯한 이더리움의 기본 사항에 익숙하다고 가정합니다. [스마트 계약](/developers/docs/smart-contracts/) 및 [스마트 계약 구조](/developers/docs/smart-contracts/anatomy/), 특히 [이벤트](/glossary/#events)에 대해서도 잘 이해하고 있어야 합니다. + +## 블록체인 오라클이란 무엇인가요? {#what-is-a-blockchain-oracle} + +오라클은 외부 정보(즉, 오프체인에 저장된 정보)를 소싱, 확인 및 블록체인에서 실행되는 스마트 계약으로 전송하는 애플리케이션입니다. 오라클은 오프체인 데이터를 '가져와' 이더리움에 브로드캐스팅하는 것 외에도, 블록체인에서 외부 시스템으로 정보를 '푸시'할 수도 있습니다(예: 사용자가 이더리움 트랜잭션을 통해 수수료를 보내면 스마트 잠금을 해제하는 경우). + +오라클이 없다면 스마트 계약은 전적으로 온체인 데이터에만 국한될 것입니다. + +오라클은 데이터 소스(단일 또는 다중 소스), 신뢰 모델(중앙화 또는 탈중앙화), 시스템 아키텍처(즉시 읽기, 게시-구독 및 요청-응답)에 따라 다릅니다. 또한 오라클이 온체인 계약에서 사용할 외부 데이터를 검색하는지(입력 오라클), 블록체인에서 오프체인 애플리케이션으로 정보를 보내는지(출력 오라클), 오프체인에서 계산 작업을 수행하는지(계산 오라클)에 따라 오라클을 구별할 수도 있습니다. + +## 스마트 계약에 오라클이 필요한 이유는 무엇인가요? {#why-do-smart-contracts-need-oracles} + +많은 개발자는 스마트 계약을 블록체인의 특정 주소에서 실행되는 코드로 봅니다. 그러나 [스마트 계약에 대한 보다 일반적인 견해](/smart-contracts/)는 특정 조건이 충족되면 당사자 간의 계약을 시행할 수 있는 자체 실행 소프트웨어 프로그램이라는 것입니다. 따라서 '스마트 계약'이라는 용어가 사용됩니다. + +그러나 이더리움이 결정적이라는 점을 감안할 때 사람들 간의 계약을 시행하기 위해 스마트 계약을 사용하는 것은 간단하지 않습니다. [결정론적 시스템](https://en.wikipedia.org/wiki/Deterministic_algorithm)은 초기 상태와 특정 입력이 주어지면 항상 동일한 결과를 생성하는 시스템으로, 입력에서 출력을 계산하는 과정에 무작위성이나 변이가 없음을 의미합니다. + +결정론적 실행을 달성하기 위해 블록체인은 노드가 블록체인 자체에 저장된 데이터_만_을 사용하여 간단한 이진(참/거짓) 질문에 대한 합의에 도달하도록 제한합니다. 이러한 질문의 예는 다음과 같습니다. + +- “계정 소유자(공개 키로 식별)가 페어링된 개인 키로 이 트랜잭션에 서명했나요?” +- “이 계정에 트랜잭션을 처리할 충분한 자금이 있나요?” +- “이 트랜잭션은 이 스마트 계약의 맥락에서 유효한가요?” 등. + +블록체인이 외부 소스(즉, 현실 세계)로부터 정보를 받는다면 결정론을 달성하는 것이 불가능해져 노드가 블록체인 상태 변경의 유효성에 대해 합의하는 것을 막게 됩니다. 기존 가격 API에서 얻은 현재 ETH-USD 환율을 기반으로 트랜잭션을 실행하는 스마트 계약을 예로 들어 보겠습니다. 이 수치는 자주 변경될 가능성이 있으며(API가 더 이상 사용되지 않거나 해킹될 수 있다는 점은 말할 것도 없음), 이는 동일한 계약 코드를 실행하는 노드가 다른 결과에 도달한다는 것을 의미합니다. + +전 세계 수천 개의 노드가 트랜잭션을 처리하는 이더리움과 같은 퍼블릭 블록체인의 경우 결정론이 중요합니다. 진실의 원천 역할을 하는 중앙 권한이 없으면 노드는 동일한 트랜잭션을 적용한 후 동일한 상태에 도달하기 위한 메커니즘이 필요합니다. 노드 A가 스마트 계약 코드를 실행하여 결과로 '3'을 얻고, 노드 B가 동일한 트랜잭션을 실행한 후 '7'을 얻는 경우는 합의를 깨뜨리고 탈중앙화 컴퓨팅 플랫폼으로서의 이더리움의 가치를 없앨 것입니다. + +이 시나리오는 또한 외부 소스에서 정보를 가져오도록 블록체인을 설계할 때의 문제를 강조합니다. 그러나 오라클은 오프체인 소스에서 정보를 가져와 스마트 계약이 소비할 수 있도록 블록체인에 저장함으로써 이 문제를 해결합니다. 온체인에 저장된 정보는 변경할 수 없고 공개적으로 사용 가능하므로 이더리움 노드는 합의를 깨뜨리지 않고 오라클이 가져온 오프체인 데이터를 안전하게 사용하여 상태 변경을 계산할 수 있습니다. + +이를 위해 오라클은 일반적으로 온체인에서 실행되는 스마트 계약과 일부 오프체인 구성 요소로 구성됩니다. 온체인 계약은 다른 스마트 계약으로부터 데이터 요청을 받아 이를 오프체인 구성 요소(오라클 노드라고 함)에 전달합니다. 이 오라클 노드는 예를 들어 애플리케이션 프로그래밍 인터페이스(API)를 사용하여 데이터 소스를 쿼리하고 트랜잭션을 보내 요청된 데이터를 스마트 계약의 저장 공간에 저장할 수 있습니다. + +본질적으로 블록체인 오라클은 블록체인과 외부 환경 간의 정보 격차를 해소하여 '하이브리드 스마트 계약'을 만듭니다. 하이브리드 스마트 계약은 온체인 계약 코드와 오프체인 인프라의 조합을 기반으로 작동하는 계약입니다. 탈중앙화 예측 시장은 하이브리드 스마트 계약의 훌륭한 예입니다. 다른 예로는 오라클 집합이 특정 기상 현상이 발생했다고 판단할 때 지불하는 농작물 보험 스마트 계약이 있습니다. + +## 오라클 문제란 무엇인가요? {#the-oracle-problem} + +오라클은 중요한 문제를 해결하지만 다음과 같은 몇 가지 복잡한 문제도 야기합니다. + +- 주입된 정보가 올바른 소스에서 추출되었거나 조작되지 않았는지 어떻게 확인할 수 있나요? + +- 이 데이터가 항상 사용 가능하고 정기적으로 업데이트되도록 어떻게 보장할 수 있나요? + +소위 '오라클 문제'는 블록체인 오라클을 사용하여 스마트 계약에 입력을 보내는 데 따르는 문제를 보여줍니다. 스마트 계약이 올바르게 실행되려면 오라클의 데이터가 정확해야 합니다. 또한 정확한 정보를 제공하기 위해 오라클 운영자를 '신뢰'해야 한다는 것은 스마트 계약의 '무신뢰' 측면을 훼손합니다. + +서로 다른 오라클은 오라클 문제에 대해 서로 다른 솔루션을 제공하며, 이에 대해서는 나중에 살펴볼 것입니다. 오라클은 일반적으로 다음 과제를 얼마나 잘 처리하는지에 따라 평가됩니다. + +1. **정확성**: 오라클은 스마트 계약이 유효하지 않은 오프체인 데이터를 기반으로 상태 변경을 트리거하게 해서는 안 됩니다. 오라클은 데이터의 진위성무결성을 보장해야 합니다. 진위성은 데이터가 올바른 소스에서 가져왔음을 의미하며, 무결성은 데이터가 온체인으로 전송되기 전에 그대로 유지되었음(즉, 변경되지 않음)을 의미합니다. + +2. **가용성**: 오라클은 스마트 계약이 작업을 실행하고 상태 변경을 트리거하는 것을 지연시키거나 방해해서는 안 됩니다. 이는 오라클의 데이터가 중단 없이 요청 시 사용 가능해야 함을 의미합니다. + +3. **인센티브 호환성**: 오라클은 오프체인 데이터 제공자가 스마트 계약에 정확한 정보를 제출하도록 인센티브를 제공해야 합니다. 인센티브 호환성에는 기여 가능성책임성이 포함됩니다. 기여 가능성은 외부 정보 조각을 제공자와 연결할 수 있게 하는 반면, 책임성은 데이터 제공자를 제공하는 정보에 결부시켜 제공된 정보의 품질에 따라 보상을 받거나 불이익을 받을 수 있도록 합니다. + +## 블록체인 오라클 서비스는 어떻게 작동하나요? {#how-does-a-blockchain-oracle-service-work} + +### 사용자 {#users} + +사용자는 특정 작업을 완료하기 위해 블록체인 외부의 정보가 필요한 엔터티(즉, 스마트 계약)입니다. 오라클 서비스의 기본 워크플로는 사용자가 오라클 계약에 데이터 요청을 보내는 것으로 시작됩니다. 데이터 요청은 일반적으로 다음 질문 중 일부 또는 전부에 답합니다. + +1. 오프체인 노드가 요청된 정보에 대해 참조할 수 있는 소스는 무엇인가요? + +2. 보고자는 데이터 소스의 정보를 어떻게 처리하고 유용한 데이터 포인트를 추출하나요? + +3. 데이터 검색에 몇 개의 오라클 노드가 참여할 수 있나요? + +4. 오라클 보고서의 불일치는 어떻게 관리해야 하나요? + +5. 제출물을 필터링하고 보고서를 단일 값으로 집계하는 데 어떤 방법을 구현해야 하나요? + +### 오라클 계약 {#oracle-contract} + +오라클 계약은 오라클 서비스의 온체인 구성 요소입니다. 다른 계약의 데이터 요청을 수신하고 데이터 쿼리를 오라클 노드에 전달하며 반환된 데이터를 클라이언트 계약에 브로드캐스팅합니다. 이 계약은 또한 반환된 데이터 포인트에 대한 일부 계산을 수행하여 요청 계약에 보낼 집계 값을 생성할 수 있습니다. + +오라클 계약은 클라이언트 계약이 데이터 요청을 할 때 호출하는 일부 함수를 노출합니다. 새로운 쿼리를 수신하면 스마트 계약은 데이터 요청의 세부 정보와 함께 [로그 이벤트](/developers/docs/smart-contracts/anatomy/#events-and-logs)를 내보냅니다. 이는 로그를 구독하는 오프체인 노드(일반적으로 JSON-RPC `eth_subscribe` 명령과 같은 것을 사용)에 알리고, 노드는 로그 이벤트에 정의된 데이터를 검색합니다. + +아래는 Pedro Costa의 [오라클 계약 예시](https://medium.com/@pedrodc/implementing-a-blockchain-oracle-on-ethereum-cedc7e26b49e)입니다. 이것은 다른 스마트 계약의 요청에 따라 오프체인 API를 쿼리하고 요청된 정보를 블록체인에 저장할 수 있는 간단한 오라클 서비스입니다. + +```solidity +pragma solidity >=0.4.21 <0.6.0; + +contract Oracle { + Request[] requests; // 계약에 대한 요청 목록 + uint currentId = 0; // 증가하는 요청 ID + uint minQuorum = 2; // 최종 결과를 선언하기 전에 수신해야 하는 최소 응답 수 + uint totalOracleCount = 3; // 하드코딩된 오라클 수 + + // 일반적인 api 요청을 정의합니다 + struct Request { + uint id; // 요청 ID + string urlToQuery; // API URL + string attributeToFetch; // 응답에서 검색할 json 속성(키) + string agreedValue; // 키의 값 + mapping(uint => string) answers; // 오라클이 제공한 답변 + mapping(address => uint) quorum; // 답변을 쿼리할 오라클(1=오라클이 투표하지 않음, 2=오라클이 투표함) + } + + // 블록체인 외부에서 오라클을 트리거하는 이벤트 + event NewRequest ( + uint id, + string urlToQuery, + string attributeToFetch + ); + + // 최종 결과에 대한 합의가 있을 때 트리거됨 + event UpdatedRequest ( + uint id, + string urlToQuery, + string attributeToFetch, + string agreedValue + ); + + function createRequest ( + string memory _urlToQuery, + string memory _attributeToFetch + ) + public + { + uint length = requests.push(Request(currentId, _urlToQuery, _attributeToFetch, "")); + Request storage r = requests[length-1]; + + // 하드코딩된 오라클 주소 + r.quorum[address(0x6c2339b46F41a06f09CA0051ddAD54D1e582bA77)] = 1; + r.quorum[address(0xb5346CF224c02186606e5f89EACC21eC25398077)] = 1; + r.quorum[address(0xa2997F1CA363D11a0a35bB1Ac0Ff7849bc13e914)] = 1; + + // 블록체인 외부의 오라클이 감지할 이벤트를 발생시킴 + emit NewRequest ( + currentId, + _urlToQuery, + _attributeToFetch + ); + + // 요청 ID 증가 + currentId++; + } + + // 오라클이 답변을 기록하기 위해 호출함 + function updateRequest ( + uint _id, + string memory _valueRetrieved + ) public { + + Request storage currRequest = requests[_id]; + + // 오라클이 신뢰할 수 있는 오라클 목록에 있는지 확인 + // 그리고 오라클이 아직 투표하지 않았는지 확인 + if(currRequest.quorum[address(msg.sender)] == 1){ + + // 이 주소가 투표했음을 표시 + currRequest.quorum[msg.sender] = 2; + + // 위치가 비어 있을 때까지 답변 '배열'을 반복하고 검색된 값을 저장 + uint tmpI = 0; + bool found = false; + while(!found) { + // 첫 번째 빈 슬롯 찾기 + if(bytes(currRequest.answers[tmpI]).length == 0){ + found = true; + currRequest.answers[tmpI] = _valueRetrieved; + } + tmpI++; + } + + uint currentQuorum = 0; + + // 오라클 목록을 반복하고 충분한 오라클(최소 쿼럼)이 + // 현재 답변과 동일한 답변에 투표했는지 확인 + for(uint i = 0; i < totalOracleCount; i++){ + bytes memory a = bytes(currRequest.answers[i]); + bytes memory b = bytes(_valueRetrieved); + + if(keccak256(a) == keccak256(b)){ + currentQuorum++; + if(currentQuorum >= minQuorum){ + currRequest.agreedValue = _valueRetrieved; + emit UpdatedRequest ( + currRequest.id, + currRequest.urlToQuery, + currRequest.attributeToFetch, + currRequest.agreedValue + ); + } + } + } + } + } +} +``` + +### 오라클 노드 {#oracle-nodes} + +오라클 노드는 오라클 서비스의 오프체인 구성 요소입니다. 타사 서버에서 호스팅되는 API와 같은 외부 소스에서 정보를 추출하고 스마트 계약이 소비할 수 있도록 온체인에 배치합니다. 오라클 노드는 온체인 오라클 계약의 이벤트를 수신하고 로그에 설명된 작업을 완료합니다. + +오라클 노드의 일반적인 작업은 API 서비스에 [HTTP GET](https://www.w3schools.com/tags/ref_httpmethods.asp) 요청을 보내고, 응답을 구문 분석하여 관련 데이터를 추출하고, 블록체인에서 읽을 수 있는 출력으로 형식을 지정하고, 오라클 계약에 대한 트랜잭션에 포함하여 온체인으로 보내는 것입니다. 오라클 노드는 나중에 살펴볼 '진위성 증명'을 사용하여 제출된 정보의 유효성과 무결성을 증명해야 할 수도 있습니다. + +계산 오라클은 또한 가스 비용과 블록 크기 제한을 고려할 때 온체인에서 실행하기에는 비실용적인 계산 작업을 수행하기 위해 오프체인 노드에 의존합니다. 예를 들어, 오라클 노드는 검증 가능한 무작위 숫자(예: 블록체인 기반 게임용)를 생성하는 작업을 맡을 수 있습니다. + +## 오라클 디자인 패턴 {#oracle-design-patterns} + +오라클은 _즉시 읽기_, _게시-구독_, _요청-응답_ 등 다양한 유형이 있으며, 후자의 두 가지가 이더리움 스마트 계약에서 가장 많이 사용됩니다. 여기서는 게시-구독 및 요청-응답 모델에 대해 간략하게 설명합니다. + +### 게시-구독 오라클 {#publish-subscribe-oracles} + +이 유형의 오라클은 다른 계약이 정기적으로 정보를 읽을 수 있는 '데이터 피드'를 노출합니다. 이 경우 데이터는 자주 변경될 것으로 예상되므로 클라이언트 계약은 오라클의 저장 공간에 있는 데이터 업데이트를 수신해야 합니다. 예를 들어 사용자에게 최신 ETH-USD 가격 정보를 제공하는 오라클이 있습니다. + +### 요청-응답 오라클 {#request-response-oracles} + +요청-응답 설정을 통해 클라이언트 계약은 게시-구독 오라클에서 제공하는 것 이외의 임의의 데이터를 요청할 수 있습니다. 요청-응답 오라클은 데이터 세트가 너무 커서 스마트 계약의 저장 공간에 저장할 수 없거나 사용자가 특정 시점에 데이터의 일부만 필요할 경우에 이상적입니다. + +게시-구독 모델보다 더 복잡하지만 요청-응답 오라클은 기본적으로 이전 섹션에서 설명한 것입니다. 오라클에는 데이터 요청을 수신하고 이를 처리를 위해 오프체인 노드에 전달하는 온체인 구성 요소가 있습니다. + +데이터 쿼리를 시작하는 사용자는 오프체인 소스에서 정보를 검색하는 비용을 부담해야 합니다. 클라이언트 계약은 또한 요청에 지정된 콜백 함수를 통해 응답을 반환하는 데 오라클 계약이 발생시킨 가스 비용을 충당하기 위한 자금을 제공해야 합니다. + +## 중앙화 오라클 대 탈중앙화 오라클 {#types-of-oracles} + +### 중앙화 오라클 {#centralized-oracles} + +중앙화 오라클은 오프체인 정보를 집계하고 요청에 따라 오라클 계약의 데이터를 업데이트하는 단일 엔터티에 의해 제어됩니다. 중앙화 오라클은 단일 진실의 원천에 의존하기 때문에 효율적입니다. 독점 데이터 세트가 널리 인정된 서명과 함께 소유자에 의해 직접 게시되는 경우 더 잘 작동할 수 있습니다. 그러나 단점도 있습니다. + +#### 낮은 정확성 보장 {#low-correctness-guarantees} + +중앙화 오라클을 사용하면 제공된 정보가 정확한지 아닌지 확인할 방법이 없습니다. 심지어 '평판이 좋은' 제공업체도 악의적으로 변하거나 해킹당할 수 있습니다. 오라클이 손상되면 스마트 계약은 잘못된 데이터를 기반으로 실행됩니다. + +#### 낮은 가용성 {#poor-availability} + +중앙화 오라클은 다른 스마트 계약에 항상 오프체인 데이터를 제공한다고 보장하지 않습니다. 제공업체가 서비스를 중단하기로 결정하거나 해커가 오라클의 오프체인 구성 요소를 탈취하면 스마트 계약은 서비스 거부(DoS) 공격의 위험에 처하게 됩니다. + +#### 낮은 인센티브 호환성 {#poor-incentive-compatibility} + +중앙화 오라클은 종종 데이터 제공자가 정확하거나 변경되지 않은 정보를 보내도록 하는 인센티브가 잘못 설계되었거나 존재하지 않습니다. 정확성을 위해 오라클에 비용을 지불한다고 해서 정직성이 보장되는 것은 아닙니다. 이 문제는 스마트 계약이 제어하는 가치의 양이 증가함에 따라 더욱 커집니다. + +### 탈중앙화 오라클 {#decentralized-oracles} + +탈중앙화 오라클은 단일 장애 지점을 제거하여 중앙화 오라클의 한계를 극복하도록 설계되었습니다. 탈중앙화 오라클 서비스는 스마트 계약에 보내기 전에 오프체인 데이터에 대한 합의를 형성하는 피어투피어 네트워크의 여러 참가자로 구성됩니다. + +탈중앙화 오라클은 (이상적으로) 무허가성, 무신뢰성이어야 하며 중앙 기관의 관리에서 자유로워야 하지만, 실제로는 오라클 간의 탈중앙화는 스펙트럼 위에 있습니다. 누구나 참여할 수 있지만 과거 성과에 따라 노드를 승인하고 제거하는 '소유자'가 있는 반탈중앙화 오라클 네트워크가 있습니다. 완전히 탈중앙화된 오라클 네트워크도 존재합니다. 이들은 일반적으로 독립형 블록체인으로 실행되며 노드를 조정하고 잘못된 행동을 처벌하기 위한 정의된 합의 메커니즘을 가지고 있습니다. + +탈중앙화 오라클을 사용하면 다음과 같은 이점이 있습니다. + +### 높은 정확성 보장 {#high-correctness-guarantees} + +탈중앙화 오라클은 다양한 접근 방식을 사용하여 데이터의 정확성을 달성하려고 합니다. 여기에는 반환된 정보의 진위성과 무결성을 증명하는 증명을 사용하고 여러 엔터티가 오프체인 데이터의 유효성에 대해 집단적으로 동의하도록 요구하는 것이 포함됩니다. + +#### 진위성 증명 {#authenticity-proofs} + +진위성 증명은 외부 소스에서 검색한 정보의 독립적인 검증을 가능하게 하는 암호화 메커니즘입니다. 이 증명은 정보의 출처를 검증하고 검색 후 데이터에 대한 가능한 변경을 감지할 수 있습니다. + +진위성 증명의 예는 다음과 같습니다. + +**전송 계층 보안(TLS) 증명**: 오라클 노드는 종종 전송 계층 보안(TLS) 프로토콜을 기반으로 하는 보안 HTTP 연결을 사용하여 외부 소스에서 데이터를 검색합니다. 일부 탈중앙화 오라클은 진위성 증명을 사용하여 TLS 세션을 확인하고(즉, 노드와 특정 서버 간의 정보 교환을 확인) 세션 내용이 변경되지 않았음을 확인합니다. + +**신뢰 실행 환경(TEE) 증명**: [신뢰 실행 환경](https://en.wikipedia.org/wiki/Trusted_execution_environment)(TEE)은 호스트 시스템의 운영 프로세스로부터 격리된 샌드박스형 계산 환경입니다. TEE는 계산 환경에 저장/사용된 모든 애플리케이션 코드 또는 데이터가 무결성, 기밀성 및 불변성을 유지하도록 보장합니다. 사용자는 또한 신뢰 실행 환경 내에서 애플리케이션 인스턴스가 실행되고 있음을 증명하기 위해 증명을 생성할 수 있습니다. + +특정 클래스의 탈중앙화 오라클은 오라클 노드 운영자가 TEE 증명을 제공하도록 요구합니다. 이는 사용자에게 노드 운영자가 신뢰 실행 환경에서 오라클 클라이언트 인스턴스를 실행하고 있음을 확인시켜 줍니다. TEE는 외부 프로세스가 애플리케이션의 코드와 데이터를 변경하거나 읽는 것을 방지하므로 이러한 증명은 오라클 노드가 정보를 그대로 기밀로 유지했음을 증명합니다. + +#### 정보의 합의 기반 검증 {#consensus-based-validation-of-information} + +중앙화 오라클은 스마트 계약에 데이터를 제공할 때 단일 진실의 원천에 의존하므로 부정확한 정보를 게시할 가능성이 있습니다. 탈중앙화 오라클은 여러 오라클 노드에 의존하여 오프체인 정보를 쿼리함으로써 이 문제를 해결합니다. 여러 소스의 데이터를 비교함으로써 탈중앙화 오라클은 온체인 계약에 유효하지 않은 정보를 전달할 위험을 줄입니다. + +그러나 탈중앙화 오라클은 여러 오프체인 소스에서 검색된 정보의 불일치를 처리해야 합니다. 정보의 차이를 최소화하고 오라클 계약에 전달된 데이터가 오라클 노드의 집단적 의견을 반영하도록 보장하기 위해 탈중앙화 오라클은 다음 메커니즘을 사용합니다. + +##### 데이터 정확성에 대한 투표/스테이킹 + +일부 탈중앙화 오라클 네트워크는 참가자가 데이터 쿼리에 대한 답변의 정확성에 대해 투표하거나 스테이킹하도록 요구합니다(예: '2020년 미국 선거에서 누가 이겼나요?'). 네트워크의 기본 토큰을 사용합니다. 그런 다음 집계 프로토콜은 투표와 스테이킹을 집계하고 다수가 지지하는 답변을 유효한 것으로 간주합니다. + +다수결 답변에서 벗어난 노드는 더 정확한 값을 제공하는 다른 사람들에게 토큰을 분배받는 불이익을 받습니다. 노드가 데이터를 제공하기 전에 채권을 제공하도록 강제하는 것은 수익 극대화를 목표로 하는 합리적인 경제 주체로 가정되므로 정직한 응답을 유도합니다. + +스테이킹/투표는 또한 악의적인 행위자가 합의 시스템을 조작하기 위해 여러 신원을 생성하는 [시빌 공격](/glossary/#sybil-attack)으로부터 탈중앙화 오라클을 보호합니다. 그러나 스테이킹은 '프리라이딩'(오라클 노드가 다른 노드의 정보를 복사하는 것)과 '게으른 검증'(오라클 노드가 정보를 직접 확인하지 않고 다수를 따르는 것)을 방지할 수 없습니다. + +##### 셸링 포인트 메커니즘 + +[셸링 포인트](https://en.wikipedia.org/wiki/Focal_point_\(game_theory\))는 여러 엔터티가 통신이 없는 상태에서 문제에 대한 공통 해결책을 항상 기본으로 삼을 것이라고 가정하는 게임 이론 개념입니다. 셸링 포인트 메커니즘은 종종 탈중앙화 오라클 네트워크에서 노드가 데이터 요청에 대한 답변에 합의할 수 있도록 하는 데 사용됩니다. + +이에 대한 초기 아이디어는 [SchellingCoin](https://blog.ethereum.org/2014/03/28/schellingcoin-a-minimal-trust-universal-data-feed)으로, 참가자가 보증금과 함께 '스칼라' 질문(답이 크기로 설명되는 질문, 예: 'ETH 가격은 얼마입니까?')에 대한 응답을 제출하는 제안된 데이터 피드였습니다. 25번째와 75번째 [백분위수](https://en.wikipedia.org/wiki/Percentile) 사이의 값을 제공하는 사용자에게는 보상이 주어지지만, 중앙값에서 크게 벗어나는 값을 제공하는 사용자에게는 불이익이 주어집니다. + +오늘날 SchellingCoin은 존재하지 않지만, 특히 [Maker Protocol의 오라클](https://docs.makerdao.com/smart-contract-modules/oracle-module)과 같은 여러 탈중앙화 오라클은 오라클 데이터의 정확성을 향상시키기 위해 셸링 포인트 메커니즘을 사용합니다. 각 Maker Oracle은 담보 자산에 대한 시장 가격을 제출하는 오프체인 P2P 노드 네트워크('릴레이어' 및 '피드')와 제공된 모든 값의 중앙값을 계산하는 온체인 'Medianizer' 계약으로 구성됩니다. 지정된 지연 기간이 끝나면 이 중앙값은 관련 자산의 새로운 참조 가격이 됩니다. + +셸링 포인트 메커니즘을 사용하는 다른 오라클의 예로는 [Chainlink 오프체인 보고](https://docs.chain.link/architecture-overview/off-chain-reporting) 및 [Witnet](https://witnet.io/)이 있습니다. 두 시스템 모두에서 피어투피어 네트워크의 오라클 노드로부터의 응답은 평균 또는 중앙값과 같은 단일 집계 값으로 집계됩니다. 노드는 응답이 집계 값과 일치하거나 벗어나는 정도에 따라 보상을 받거나 처벌을 받습니다. + +셸링 포인트 메커니즘은 온체인 공간을 최소화하면서(하나의 트랜잭션만 보내면 됨) 탈중앙화를 보장하기 때문에 매력적입니다. 후자는 노드가 평균/중앙값을 생성하는 알고리즘에 공급되기 전에 제출된 응답 목록에 서명해야 하기 때문에 가능합니다. + +### 가용성 {#availability} + +탈중앙화 오라클 서비스는 스마트 계약에 오프체인 데이터의 높은 가용성을 보장합니다. 이는 오프체인 정보의 출처와 정보를 온체인으로 전송하는 책임이 있는 노드를 모두 탈중앙화함으로써 달성됩니다. + +이는 오라클 계약이 다른 계약의 쿼리를 실행하기 위해 여러 노드(또한 여러 데이터 소스에 의존)에 의존할 수 있으므로 내결함성을 보장합니다. 소스 _및_ 노드 운영자 수준에서의 탈중앙화는 매우 중요합니다. 동일한 소스에서 검색된 정보를 제공하는 오라클 노드 네트워크는 중앙화 오라클과 동일한 문제에 직면하게 됩니다. + +스테이킹 기반 오라클이 데이터 요청에 신속하게 응답하지 못하는 노드 운영자를 슬래싱하는 것도 가능합니다. 이는 오라클 노드가 내결함성 인프라에 투자하고 적시에 데이터를 제공하도록 크게 장려합니다. + +### 양호한 인센티브 호환성 {#good-incentive-compatibility} + +탈중앙화 오라클은 오라클 노드 간의 [비잔틴](https://en.wikipedia.org/wiki/Byzantine_fault) 행동을 방지하기 위해 다양한 인센티브 설계를 구현합니다. 구체적으로 기여 가능성책임성을 달성합니다. + +1. 탈중앙화 오라클 노드는 종종 데이터 요청에 대한 응답으로 제공하는 데이터에 서명해야 합니다. 이 정보는 오라클 노드의 과거 성과를 평가하는 데 도움이 되므로 사용자는 데이터 요청을 할 때 신뢰할 수 없는 오라클 노드를 필터링할 수 있습니다. Witnet의 [알고리즘 평판 시스템](https://docs.witnet.io/intro/about/architecture#algorithmic-reputation-system)이 그 예입니다. + +2. 앞서 설명했듯이 탈중앙화 오라클은 노드가 제출하는 데이터의 진실성에 대한 신뢰도에 스테이킹을 하도록 요구할 수 있습니다. 주장이 확인되면 이 스테이킹은 정직한 서비스에 대한 보상과 함께 반환될 수 있습니다. 그러나 정보가 부정확한 경우 슬래싱될 수도 있으며, 이는 어느 정도의 책임성을 제공합니다. + +## 스마트 계약에서의 오라클 애플리케이션 {#applications-of-oracles-in-smart-contracts} + +다음은 이더리움에서 오라클의 일반적인 사용 사례입니다. + +### 금융 데이터 검색 {#retrieving-financial-data} + +[탈중앙화 금융](/defi/)(디파이) 애플리케이션은 자산의 피어투피어 대출, 차입 및 거래를 허용합니다. 이를 위해서는 종종 환율 데이터(암호화폐의 법정화폐 가치를 계산하거나 토큰 가격을 비교하기 위해) 및 자본 시장 데이터(금 또는 미국 달러와 같은 토큰화된 자산의 가치를 계산하기 위해)를 포함한 다양한 금융 정보를 얻어야 합니다. + +예를 들어, 디파이 대출 프로토콜은 담보로 예치된 자산(예: ETH)의 현재 시장 가격을 쿼리해야 합니다. 이를 통해 계약은 담보 자산의 가치를 결정하고 시스템에서 얼마나 빌릴 수 있는지 결정할 수 있습니다. + +디파이에서 인기 있는 '가격 오라클'(흔히 이렇게 불림)에는 Chainlink 가격 피드, Compound Protocol의 [Open Price Feed](https://compound.finance/docs/prices), Uniswap의 [시간 가중 평균 가격(TWAP)](https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles) 및 [Maker Oracles](https://docs.makerdao.com/smart-contract-modules/oracle-module)이 있습니다. + +개발자는 프로젝트에 통합하기 전에 이러한 가격 오라클과 관련된 주의 사항을 이해해야 합니다. 이 [문서](https://blog.openzeppelin.com/secure-smart-contract-guidelines-the-dangers-of-price-oracles)는 언급된 가격 오라클 중 하나를 사용할 계획일 때 고려해야 할 사항에 대한 자세한 분석을 제공합니다. + +아래는 Chainlink 가격 피드를 사용하여 스마트 계약에서 최신 ETH 가격을 검색하는 방법의 예입니다. + +```solidity +pragma solidity ^0.6.7; + +import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol"; + +contract PriceConsumerV3 { + + AggregatorV3Interface internal priceFeed; + + /** + * 네트워크: Kovan + * 애그리게이터: ETH/USD + * 주소: 0x9326BFA02ADD2366b30bacB125260Af641031331 + */ + constructor() public { + priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331); + } + + /** + * 최신 가격을 반환합니다 + */ + function getLatestPrice() public view returns (int) { + ( + uint80 roundID, + int price, + uint startedAt, + uint timeStamp, + uint80 answeredInRound + ) = priceFeed.latestRoundData(); + return price; + } +} +``` + +### 검증 가능한 무작위성 생성 {#generating-verifiable-randomness} + +블록체인 기반 게임이나 복권 제도와 같은 특정 블록체인 애플리케이션은 효과적으로 작동하기 위해 높은 수준의 예측 불가능성과 무작위성이 필요합니다. 그러나 블록체인의 결정론적 실행은 무작위성을 제거합니다. + +원래 접근 방식은 `blockhash`와 같은 의사 난수 암호화 함수를 사용하는 것이었지만, 이는 작업 증명 알고리즘을 해결하는 [채굴자에 의해 조작될 수 있었습니다](https://ethereum.stackexchange.com/questions/3140/risk-of-using-blockhash-other-miners-preventing-attack#:~:text=So%20while%20the%20miners%20can,to%20one%20of%20the%20players.) 작업 증명 알고리즘을 해결합니다. 또한, 이더리움의 [지분 증명으로의 전환](/roadmap/merge/)은 개발자들이 더 이상 온체인 무작위성을 위해 `blockhash`에 의존할 수 없음을 의미합니다. 대신 비콘 체인의 [RANDAO 메커니즘](https://eth2book.info/altair/part2/building_blocks/randomness)이 무작위성의 대안 소스를 제공합니다. + +무작위 값을 오프체인으로 생성하여 온체인으로 보낼 수 있지만, 그렇게 하면 사용자에게 높은 신뢰 요구 사항이 부과됩니다. 그들은 값이 예측 불가능한 메커니즘을 통해 실제로 생성되었고 전송 중에 변경되지 않았다고 믿어야 합니다. + +오프체인 계산을 위해 설계된 오라클은 프로세스의 예측 불가능성을 증명하는 암호화 증명과 함께 온체인으로 브로드캐스팅하는 무작위 결과를 오프체인에서 안전하게 생성하여 이 문제를 해결합니다. 예를 들어, [Chainlink VRF](https://docs.chain.link/docs/chainlink-vrf/)(검증 가능한 랜덤 함수)는 예측 불가능한 결과에 의존하는 애플리케이션을 위한 신뢰할 수 있는 스마트 계약을 구축하는 데 유용한, 증명 가능하게 공정하고 변조 방지 기능이 있는 난수 생성기(RNG)입니다. + +### 이벤트 결과 얻기 {#getting-outcomes-for-events} + +오라클을 사용하면 실제 세계 이벤트에 응답하는 스마트 계약을 쉽게 만들 수 있습니다. 오라클 서비스는 계약이 오프체인 구성 요소를 통해 외부 API에 연결하고 해당 데이터 소스에서 정보를 소비할 수 있도록 하여 이를 가능하게 합니다. 예를 들어, 앞서 언급한 예측 탈중앙화앱은 신뢰할 수 있는 오프체인 소스(예: Associated Press)로부터 선거 결과를 반환하도록 오라클에 요청할 수 있습니다. + +실제 세계 결과를 기반으로 데이터를 검색하기 위해 오라클을 사용하면 다른 새로운 사용 사례가 가능해집니다. 예를 들어, 탈중앙화 보험 상품이 효과적으로 작동하려면 날씨, 재해 등에 대한 정확한 정보가 필요합니다. + +### 스마트 계약 자동화 {#automating-smart-contracts} + +스마트 계약은 자동으로 실행되지 않으며, 외부 소유 계정(EOA) 또는 다른 컨트랙트 계정이 계약 코드를 실행하기 위해 올바른 함수를 트리거해야 합니다. 대부분의 경우 계약의 기능 대부분은 공개되어 있으며 EOA 및 다른 계약에서 호출할 수 있습니다. + +그러나 계약 내에는 다른 사람이 액세스할 수 없지만 탈중앙화앱의 전반적인 기능에 중요한 비공개 함수도 있습니다. 예를 들어 사용자를 위해 주기적으로 새로운 NFT를 발행하는 `mintERC721Token()` 함수, 예측 시장에서 지불금을 수여하는 함수 또는 DEX에서 스테이킹된 토큰을 잠금 해제하는 함수가 있습니다. + +개발자는 애플리케이션이 원활하게 실행되도록 유지하기 위해 일정한 간격으로 이러한 함수를 트리거해야 합니다. 그러나 이는 개발자에게 평범한 작업에 더 많은 시간을 낭비하게 할 수 있으며, 이것이 스마트 계약 실행 자동화가 매력적인 이유입니다. + +일부 탈중앙화 오라클 네트워크는 자동화 서비스를 제공하여 오프체인 오라클 노드가 사용자가 정의한 매개 변수에 따라 스마트 계약 함수를 트리거할 수 있도록 합니다. 일반적으로 이를 위해서는 오라클 서비스에 대상 계약을 '등록'하고, 오라클 운영자에게 지불할 자금을 제공하고, 계약을 트리거할 조건이나 시간을 지정해야 합니다. + +Chainlink의 [Keeper 네트워크](https://chain.link/keepers)는 스마트 계약이 신뢰를 최소화하고 탈중앙화된 방식으로 정기적인 유지 관리 작업을 아웃소싱할 수 있는 옵션을 제공합니다. 계약을 Keeper와 호환되게 만들고 Upkeep 서비스를 사용하는 방법에 대한 정보는 공식 [Keeper 개발문서](https://docs.chain.link/docs/chainlink-keepers/introduction/)를 참조하세요. + +## 블록체인 오라클 사용 방법 {#use-blockchain-oracles} + +이더리움 탈중앙화앱에 통합할 수 있는 여러 오라클 애플리케이션이 있습니다. + +**[Chainlink](https://chain.link/)** - _Chainlink 탈중앙화 오라클 네트워크는 모든 블록체인에서 고급 스마트 계약을 지원하기 위해 변조 방지 입력, 출력 및 계산을 제공합니다._ + +**[RedStone Oracles](https://redstone.finance/)** - _RedStone은 가스 최적화 데이터 피드를 제공하는 탈중앙화 모듈형 오라클입니다. 유동성 스테이킹 토큰(LST), 유동성 리스테이킹 토큰(LRT), 비트코인 스테이킹 파생상품과 같은 신규 자산에 대한 가격 피드 제공을 전문으로 합니다._ + +**[Chronicle](https://chroniclelabs.org/)** - _Chronicle은 진정으로 확장 가능하고 비용 효율적이며 탈중앙화되고 검증 가능한 오라클을 개발하여 온체인 데이터 전송의 현재 한계를 극복합니다._ + +**[Witnet](https://witnet.io/)** - _Witnet은 강력한 암호 경제적 보장을 통해 스마트 계약이 실제 세계 이벤트에 반응하도록 돕는 무허가성, 탈중앙화 및 검열 저항성 오라클입니다._ + +**[UMA Oracle](https://uma.xyz)** - _UMA의 낙관적 오라클은 스마트 계약이 보험, 금융 파생 상품, 예측 시장을 포함한 다양한 애플리케이션을 위해 모든 종류의 데이터를 신속하게 수신할 수 있도록 합니다._ + +**[Tellor](https://tellor.io/)** - _Tellor는 스마트 계약이 필요할 때마다 모든 데이터를 쉽게 얻을 수 있는 투명하고 무허가성인 오라클 프로토콜입니다._ + +**[Band Protocol](https://bandprotocol.com/)** - _Band Protocol은 실제 세계 데이터와 API를 스마트 계약에 집계하고 연결하는 크로스 체인 데이터 오라클 플랫폼입니다._ + +**[Pyth Network](https://pyth.network/)** - _Pyth 네트워크는 변조 방지, 탈중앙화 및 자립 환경에서 연속적인 실제 세계 데이터를 온체인으로 게시하도록 설계된 1차 금융 오라클 네트워크입니다._ + +**[API3 DAO](https://www.api3.org/)** - _API3 DAO는 스마트 계약을 위한 탈중앙화 솔루션에서 더 큰 소스 투명성, 보안 및 확장성을 제공하는 1차 오라클 솔루션을 제공합니다._ + +**[Supra](https://supra.com/)** - 모든 블록체인(퍼블릭(L1 및 L2) 또는 프라이빗(기업))을 상호 연결하는 수직적으로 통합된 크로스 체인 솔루션 툴킷으로, 온체인 및 오프체인 사용 사례에 사용할 수 있는 탈중앙화 오라클 가격 피드를 제공합니다. + +**[Gas Network](https://gas.network/)** - 블록체인 전반에 걸쳐 실시간 가스 가격 데이터를 제공하는 분산형 오라클 플랫폼입니다. 선도적인 가스 가격 데이터 제공업체의 데이터를 온체인으로 가져옴으로써 Gas Network는 상호 운용성을 촉진하는 데 도움을 줍니다. Gas Network는 이더리움 메인넷 및 다수의 선도적인 L2를 포함하여 35개 이상의 체인에 대한 데이터를 지원합니다. + +## 더 읽어보기 {#further-reading} + +**문서** + +- [블록체인 오라클이란?](https://chain.link/education/blockchain-oracles) — _Chainlink_ +- [블록체인 오라클이란?](https://medium.com/better-programming/what-is-a-blockchain-oracle-f5ccab8dbd72) — _Patrick Collins_ +- [탈중앙화 오라클: 종합 개요](https://medium.com/fabric-ventures/decentralised-oracles-a-comprehensive-overview-d3168b9a8841) — _Julien Thevenard_ +- [이더리움에서 블록체인 오라클 구현하기](https://medium.com/@pedrodc/implementing-a-blockchain-oracle-on-ethereum-cedc7e26b49e) – _Pedro Costa_ +- [스마트 계약이 API를 호출할 수 없는 이유는 무엇인가요?](https://ethereum.stackexchange.com/questions/301/why-cant-contracts-make-api-calls) — _StackExchange_ +- [그래서 당신은 가격 오라클을 사용하고 싶군요](https://samczsun.com/so-you-want-to-use-a-price-oracle/) — _samczsun_ + +**영상** + +- [오라클과 블록체인 유틸리티의 확장](https://youtu.be/BVUZpWa8vpw) — _Real Vision Finance_ + +**튜토리얼** + +- [솔리디티에서 현재 이더리움 가격 가져오는 방법](https://blog.chain.link/fetch-current-crypto-price-data-solidity/) — _Chainlink_ +- [오라클 데이터 소비](https://docs.chroniclelabs.org/Developers/tutorials/Remix) — _Chronicle_ + +**예제 프로젝트** + +- [이더리움을 위한 전체 Chainlink 스타터 프로젝트(솔리디티)](https://github.com/hackbg/chainlink-fullstack) — _HackBG_ diff --git a/public/content/translations/ko/developers/docs/programming-languages/dart/index.md b/public/content/translations/ko/developers/docs/programming-languages/dart/index.md new file mode 100644 index 00000000000..1f149a1f603 --- /dev/null +++ b/public/content/translations/ko/developers/docs/programming-languages/dart/index.md @@ -0,0 +1,30 @@ +--- +title: "Dart 개발자를 위한 이더리움" +description: "Dart 언어를 사용한 이더리움 개발 방법 알아보기" +lang: ko +incomplete: true +--- + +## 스마트 계약 및 솔리디티 언어 시작하기 {#getting-started-with-smart-contracts-and-solidity} + +## 튜토리얼 {#tutorials} + +- [Flutter and Blockchain – Hello World Dapp](https://www.geeksforgeeks.org/flutter-and-blockchain-hello-world-dapp/)은 시작하는 데 필요한 모든 단계를 안내합니다. + 1. [Solidity](https://soliditylang.org/)로 스마트 계약 작성하기 + 2. 다트로 유저 인터페이스 짜기 +- [Building a Mobile dapp with Flutter](https://medium.com/dash-community/building-a-mobile-dapp-with-flutter-be945c80315a)는 분량이 훨씬 짧으므로, 이미 기초를 알고 있다면 더 나을 수 있습니다. +- 동영상으로 배우는 것을 선호한다면, 약 1시간 분량의 [Build Your First Blockchain Flutter App](https://www.youtube.com/watch?v=3Eeh3pJ6PeA)을 시청할 수 있습니다. +- 기다리기 힘들다면, 약 20분 분량의 [Building a Blockchain Decentralized-app with Flutter and Dart on Ethereum](https://www.youtube.com/watch?v=jaMFEOCq_1s)을 선호할 수도 있습니다. +- [Integrating MetaMask in Flutter application with Web3Modal by WalletConnect](https://www.youtube.com/watch?v=v_M2buHCpc4) - 이 짧은 동영상은 WalletConnect의 [Web3Modal](https://pub.dev/packages/web3modal_flutter) 라이브러리를 사용하여 MetaMask를 Flutter 애플리케이션에 통합하는 단계를 안내합니다. +- [Mobile Blockchain Developer Bootcamp Course With Solidity & Flutter](https://youtube.com/playlist?list=PL4V4Unlk5luhQ26ERO6hWEbcUwHDSSmVH) - 풀스택 모바일 블록체인 개발자 과정 재생 목록 + +## 이더리움 클라이언트 사용하기 {#working-with-ethereum-clients} + +이더리움을 사용하여 암호화폐와 블록체인 기술의 이점을 활용하는 탈중앙화 애플리케이션(또는 "탈중앙화앱")을 만들 수 있습니다. +현재 Dart에서 이더리움용 [JSON-RPC API](/developers/docs/apis/json-rpc/)를 사용하기 위해 유지 관리되는 라이브러리가 두 개 이상 있습니다. + +1. [pwa.ir의 Web3dart](https://pub.dev/packages/web3dart) +2. [darticulate.com의 Ethereum 5.0.0](https://pub.dev/packages/ethereum) + +특정 이더리움 주소를 조작하거나 다양한 암호화폐의 가격을 검색할 수 있는 추가 라이브러리도 있습니다. +[여기에서 전체 목록을 볼 수 있습니다](https://pub.dev/dart/packages?q=ethereum). diff --git a/public/content/translations/ko/developers/docs/programming-languages/delphi/index.md b/public/content/translations/ko/developers/docs/programming-languages/delphi/index.md new file mode 100644 index 00000000000..3fb5f840aae --- /dev/null +++ b/public/content/translations/ko/developers/docs/programming-languages/delphi/index.md @@ -0,0 +1,56 @@ +--- +title: "델파이 개발자를 위한 이더리움" +description: "Delphi 프로그래밍 언어를 사용하여 Ethereum을 개발하는 방법 배우기" +lang: ko +incomplete: true +--- + + + +Delphi 프로그래밍 언어를 사용하여 Ethereum을 개발하는 방법 배우기 + + + +이더리움 기반으로 개발된 탈중앙화 애플리케이션(또는 “디앱”)은 암호화폐와 블록체인 기술의 장점을 가지게 됩니다. 탈중앙화 애플리케이션은 일단 이더리움에 배포되면 항상 프로그래밍된 대로 동작하므로 완전히 신뢰할 수 있습니다. 그러므로 새로운 형태의 금융 애플리케이션을 제작하기 위해 디지털 자산을 제어하는 데 사용될 수 있습니다. 그뿐만 아니라 해당 금융 애플리케이션을 어떤 특정 단체나 개인이 제어할 수 없고 검열이 거의 불가능하도록 탈중앙화할 수 있습니다. + +Ethereum 위에서 분산 애플리케이션을 빌드하고 스마트 계약과 상호작용하기 + +## 스마트 계약과 솔리디티 언어 시작하기 {#getting-started-with-smart-contracts-and-the-solidity-language} + +**Delphi와 Ethereum을 통합하는 첫 단계** + +먼저 기본 지식이 더 필요하시나요? [ethereum.org/learn](/learn/) 또는 [ethereum.org/developers](/developers/)를 확인해 보세요. + +- [블록체인 설명](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) +- [스마트 계약 이해하기](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [첫 스마트 계약 작성하기](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [솔리디티 컴파일 및 배포 방법 알아보기](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) + +## 초보자를 위한 참고 자료 및 링크 {#beginner-references-and-links} + +**Delphereum 라이브러리 소개** + +- [Delphereum이란 무엇인가요?](https://github.com/svanas/delphereum/blob/master/README.md) +- [Delphi를 로컬(인메모리) 블록체인에 연결하기](https://medium.com/@svanas/connecting-delphi-to-a-local-in-memory-blockchain-9a1512d6c5b0) +- [Delphi를 이더리움 메인넷에 연결하기](https://medium.com/@svanas/connecting-delphi-to-the-ethereum-main-net-5faf1feffd83) +- [Delphi를 스마트 계약에 연결하기](https://medium.com/@svanas/connecting-delphi-to-smart-contracts-3146b12803a1) + +**설정을 건너뛰고 곧바로 샘플을 확인하고 싶으세요?** + +- [3분 완성 스마트 계약과 Delphi - 파트 1](https://medium.com/@svanas/a-3-minute-smart-contract-and-delphi-61d998571d) +- [3분 완성 스마트 계약과 Delphi - 파트 2](https://medium.com/@svanas/a-3-minute-smart-contract-and-delphi-part-2-446925faa47b) + +## 중급자용 아티클 {#intermediate-articles} + +- [Delphi에서 이더리움 서명 메시지 시그니처 생성하기](https://medium.com/@svanas/generating-an-ethereum-signed-message-signature-in-delphi-75661ce5031b) +- [Delphi로 이더 전송하기](https://medium.com/@svanas/transferring-ether-with-delphi-b5f24b1a98a4) +- [Delphi로 ERC-20 토큰 전송하기](https://medium.com/@svanas/transferring-erc-20-tokens-with-delphi-bb44c05b295d) + +## 고급 사용 패턴 {#advanced-use-patterns} + +- [Delphi와 이더리움 네임 서비스(ENS)](https://medium.com/@svanas/delphi-and-ethereum-name-service-ens-4443cd278af7) +- [QuikNode, 이더리움 및 Delphi](https://medium.com/@svanas/quiknode-ethereum-and-delphi-f7bfc9671c23) +- [Delphi와 이더리움 다크 포레스트](https://svanas.medium.com/delphi-and-the-ethereum-dark-forest-5b430da3ad93) +- [Delphi에서 토큰 교환하기](https://svanas.medium.com/swap-one-token-for-another-in-delphi-bcb999c47f7) + +더 많은 참고 자료를 확인하고 싶으신가요? [ethereum.org/developers](/developers/)를 확인해 보세요. diff --git a/public/content/translations/ko/developers/docs/programming-languages/dot-net/index.md b/public/content/translations/ko/developers/docs/programming-languages/dot-net/index.md new file mode 100644 index 00000000000..1883cdc90b4 --- /dev/null +++ b/public/content/translations/ko/developers/docs/programming-languages/dot-net/index.md @@ -0,0 +1,86 @@ +--- +title: ".NET 개발자를 위한 이더리움" +description: ".NET 기반 프로젝트 및 툴링을 사용하여 이더리움 개발 방법 알아보기" +lang: ko +incomplete: true +--- + +.NET 기반 프로젝트와 툴링을 사용하여 이더리움용으로 개발하는 방법을 알아보세요 + +이더리움 기반으로 개발된 탈중앙화 애플리케이션(또는 “디앱”)은 암호화폐와 블록체인 기술의 장점을 가지게 됩니다. 탈중앙화 애플리케이션은 일단 이더리움에 배포되면 항상 프로그래밍된 대로 동작하므로 완전히 신뢰할 수 있습니다. 그러므로 새로운 형태의 금융 애플리케이션을 제작하기 위해 디지털 자산을 제어하는 데 사용될 수 있습니다. 그뿐만 아니라 해당 금융 애플리케이션을 어떤 특정 단체나 개인이 제어할 수 없고 검열이 거의 불가능하도록 탈중앙화할 수 있습니다. + +이더리움 기반으로 개발된 탈중앙화 애플리케이션은 마이크로스프트(Microsoft) 기술 스택의 도구와 언어를 사용하여 스마트 계약과 상호 작용합니다. 지원되는 언어에는 C#, # Visual Basic .NET, F# 등이 있으며 .NET Framework/.NET Core/.NET Standard에서 VSCode 및 Visual Studio와 같은 도구를 통해 실행됩니다. 마이크로소프트 애저(Microsoft Azure) 블록체인을 사용하여 애저에서 수 분 이내에 이더리움 블록체인을 배포할 수 있습니다. 이더리움에서 .NET에 대한 열정을 표현해 보세요! + +## 스마트 계약과 솔리디티 언어 시작하기 {#getting-started-with-smart-contracts-and-the-solidity-language} + +**이더리움과 .NET을 통합하기 위한 첫걸음을 내딛으세요** + +먼저 기본 지식이 더 필요하시나요? [ethereum.org/learn](/learn/) 또는 [ethereum.org/developers](/developers/)를 확인해 보세요. + +- [블록체인 설명](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) +- [스마트 계약 이해하기](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [첫 스마트 계약 작성하기](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [솔리디티 컴파일 및 배포 방법 알아보기](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) + +## 초보자를 위한 참고 자료 및 링크 {#beginner-references-and-links} + +**네더리움 라이브러리(Nethereum library) 및 VS 코드 솔리디티(Code Solidity) 소개** + +- [Nethereum, 시작하기](https://docs.nethereum.com/en/latest/getting-started/) +- [VS Code 솔리디티 설치하기](https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity) +- [.NET 개발자의 이더리움 스마트 계약 생성 및 호출 워크플로](https://medium.com/coinmonks/a-net-developers-workflow-for-creating-and-calling-ethereum-smart-contracts-44714f191db2) +- [Nethereum을 이용한 스마트 계약 통합](https://kauri.io/#collections/Getting%20Started/smart-contracts-integration-with-nethereum/#smart-contracts-integration-with-nethereumm) +- [Nethereum으로 .NET 및 이더리움 블록체인 스마트 계약 연동하기](https://medium.com/my-blockchain-development-daily-journey/interfacing-net-and-ethereum-blockchain-smart-contracts-with-nethereum-2fa3729ac933), [중문판](https://medium.com/my-blockchain-development-daily-journey/%E4%BD%BF%E7%94%A8nethereum%E9%80%A3%E6%8E%A5-net%E5%92%8C%E4%BB%A5%E5%A4%AA%E7%B6%B2%E5%8D%80%E5%A1%8A%E9%8F%88%E6%99%BA%E8%83%BD%E5%90%88%E7%B4%84-4a96d35ad1e1)으로도 제공 +- [Nethereum - 블록체인을 위한 오픈 소스 .NET 통합 라이브러리](https://kauri.io/#collections/a%20hackathon%20survival%20guide/nethereum-an-open-source-.net-integration-library/) +- [Nethereum을 사용하여 이더리움 트랜잭션을 SQL 데이터베이스에 작성하기](https://medium.com/coinmonks/writing-ethereum-transactions-to-sql-database-using-nethereum-fd94e0e4fa36) +- [C#과 VisualStudio를 사용하여 이더리움 스마트 계약을 쉽게 배포하는 방법 알아보기](https://koukia.ca/deploy-ethereum-smart-contracts-using-c-and-visualstudio-5be188ae928c) + +**설정을 건너뛰고 곧바로 샘플을 확인하고 싶으세요?** + +- [Playground](http://playground.nethereum.com/) - 브라우저를 통해 이더리움과 상호작용하고 Nethereum 사용법을 알아보세요. + - 계정 잔액 조회하기 [C#](http://playground.nethereum.com/csharp/id/1001) [VB.NET](http://playground.nethereum.com/vb/id/2001) + - ERC20 스마트 계약 잔액 조회하기 [C#](http://playground.nethereum.com/csharp/id/1005) [VB.NET](http://playground.nethereum.com/vb/id/2004) + - 계정으로 이더 전송하기 [C#](http://playground.nethereum.com/csharp/id/1003) [VB.NET](http://playground.nethereum.com/vb/id/2003) + - ... 기타 + +## 중급자용 아티클 {#intermediate-articles} + +- [Nethereum 워크북/샘플 목록](http://docs.nethereum.com/en/latest/Nethereum.Workbooks/docs/) +- [자체 개발 테스트 체인 배포하기](https://github.com/Nethereum/Testchains) +- [솔리디티용 VSCode Codegen 플러그인](https://docs.nethereum.com/en/latest/nethereum-codegen-vscodesolidity/) +- [Unity와 이더리움: 왜, 그리고 어떻게](https://www.raywenderlich.com/5509-unity-and-ethereum-why-and-how) +- [이더리움 탈중앙화앱용 ASP.NET Core 웹 API 만들기](https://tech-mint.com/blockchain/create-asp-net-core-web-api-for-ethereum-dapps/) +- [Nethereum Web3를 사용하여 공급망 추적 시스템 구현하기](http://blog.pomiager.com/post/using-nethereum-web3-to-implement-a-supply-chain-traking-system4) +- [Nethereum 블록 처리](https://nethereum.readthedocs.io/en/latest/nethereum-block-processing-detail/), [C# Playground 샘플](http://playground.nethereum.com/csharp/id/1025) 포함 +- [Nethereum 웹소켓 스트리밍](https://nethereum.readthedocs.io/en/latest/nethereum-subscriptions-streaming/) +- [Kaleido와 Nethereum](https://kaleido.io/kaleido-and-nethereum/) +- [Quorum과 Nethereum](https://github.com/Nethereum/Nethereum/blob/master/src/Nethereum.Quorum/README.md) + +## 고급 사용 패턴 {#advanced-use-patterns} + +- [Azure Key Vault와 Nethereum](https://github.com/Azure-Samples/bc-community-samples/tree/master/akv-nethereum) +- [Nethereum.DappHybrid](https://github.com/Nethereum/Nethereum.DappHybrid) +- [Ujo Nethereum 백엔드 참조 아키텍처](https://docs.nethereum.com/en/latest/nethereum-ujo-backend-sample/) + +## .NET 프로젝트, 도구 및 기타 흥미로운 자료 {#dot-net-projects-tools-and-other-fun-stuff} + +- [Nethereum Playground](http://playground.nethereum.com/) - _브라우저에서 Nethereum 코드 스니펫 컴파일, 생성 및 실행_ +- [Nethereum Codegen Blazor](https://github.com/Nethereum/Nethereum.CodeGen.Blazor) - _Blazor의 UI를 사용한 Nethereum codegen_ +- [Nethereum Blazor](https://github.com/Nethereum/NethereumBlazor) - _.NET Wasm SPA 라이트 블록체인 익스플로러 및 간단한 지갑_ +- [Wonka 비즈니스 규칙 엔진](https://docs.nethereum.com/en/latest/wonka/) - _근본적으로 메타데이터 기반인 비즈니스 규칙 엔진(.NET 및 이더리움 플랫폼 모두 지원)_ +- [Nethermind](https://github.com/NethermindEth/nethermind) - _Linux, Windows, MacOS용 .NET Core 이더리움 클라이언트_ +- [eth-utils](https://github.com/ethereum/eth-utils/) - _이더리움 관련 코드베이스 작업을 위한 유틸리티 함수_ +- [TestChains](https://github.com/Nethereum/TestChains) - _빠른 응답을 위해 사전 구성된 .NET 개발 체인(PoA)_ + +더 많은 참고 자료를 확인하고 싶으신가요? [ethereum.org/developers](/developers/)를 확인해 보세요. + +## .NET 커뮤니티 기여자 {#dot-net-community-contributors} + +Nethereum에서는 주로 [Gitter](https://gitter.im/Nethereum/Nethereum)에서 활동하며, 누구나 자유롭게 질문과 답변을 하고, 도움을 받거나 편안하게 시간을 보낼 수 있습니다. [Nethereum GitHub 리포지토리](https://github.com/Nethereum)에서 자유롭게 PR을 보내거나 이슈를 열거나, 저희가 보유한 다양한 사이드/샘플 프로젝트를 둘러보세요. [Discord](https://discord.gg/jQPrR58FxX)에서도 저희를 만나보실 수 있습니다! + +Nethermind가 처음이고 시작하는 데 도움이 필요하시면, 저희 [Discord](http://discord.gg/PaCMRFdvWT)에 참여하세요. 저희 개발자들이 질문에 답변해 드립니다. [Nethermind GitHub 리포지토리](https://github.com/NethermindEth/nethermind)에서 주저하지 말고 PR을 열거나 이슈를 제기하세요. + +## 기타 수집된 목록 {#other-aggregated-lists} + +[Nethereum 공식 사이트](https://nethereum.com/) +[Nethermind 공식 사이트](https://nethermind.io/) diff --git a/public/content/translations/ko/developers/docs/programming-languages/elixir/index.md b/public/content/translations/ko/developers/docs/programming-languages/elixir/index.md new file mode 100644 index 00000000000..90edf40dc86 --- /dev/null +++ b/public/content/translations/ko/developers/docs/programming-languages/elixir/index.md @@ -0,0 +1,55 @@ +--- +title: "엘릭서 개발자를 위한 이더리움" +description: "엘릭서 기반 프로젝트와 툴링을 사용하여 이더리움 개발 방법을 알아보세요." +lang: ko +incomplete: false +--- + +엘릭서 기반 프로젝트와 툴링을 사용하여 이더리움 개발 방법을 알아보세요. + +이더리움 기반으로 개발된 탈중앙화 애플리케이션(또는 “디앱”)은 암호화폐와 블록체인 기술의 장점을 가지게 됩니다. 이러한 탈중앙화앱은 무신뢰성을 가질 수 있습니다. 즉, 이더리움에 배포되면 항상 프로그래밍된 대로 실행됩니다. 탈중앙화앱은 디지털 자산을 제어하여 새로운 종류의 금융 애플리케이션을 만들 수 있습니다. 그뿐만 아니라 해당 금융 애플리케이션을 어떤 특정 단체나 개인이 제어할 수 없고 검열이 거의 불가능하도록 탈중앙화할 수 있습니다. + +## 스마트 계약 및 솔리디티 언어 시작하기 {#getting-started-with-smart-contracts-and-solidity} + +**엘릭서와 이더리움 통합을 위한 첫 단계** + +먼저 기본 지식이 더 필요하시나요? [ethereum.org/learn](/learn/) 또는 [ethereum.org/developers](/developers/)를 확인해 보세요. + +- [블록체인 설명](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) +- [스마트 계약 이해하기](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [첫 스마트 계약 작성하기](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [솔리디티 컴파일 및 배포 방법 알아보기](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) + +## 초급자용 아티클 {#beginner-articles} + +- [드디어 이더리움 계정 이해하기](https://dev.to/q9/finally-understanding-ethereum-accounts-1kpe) +- [Ethers — 엘릭서를 위한 최고 수준의 이더리움 웹3 라이브러리](https://medium.com/@alisinabh/announcing-ethers-a-first-class-ethereum-web3-library-for-elixir-1d64e9409122) + +## 중급자용 아티클 {#intermediate-articles} + +- [엘릭서로 원시 이더리움 계약 트랜잭션에 서명하는 방법](https://kohlerjp.medium.com/how-to-sign-raw-ethereum-contract-transactions-with-elixir-f8822bcc813b) +- [이더리움 스마트 계약과 엘릭서](https://medium.com/agile-alpha/ethereum-smart-contracts-and-elixir-c7c4b239ddb4) + +## 엘릭서 프로젝트 및 도구 {#elixir-projects-and-tools} + +### 활성 {#active} + +- [block_keys](https://github.com/ExWeb3/block_keys) - _엘릭서의 BIP32 및 BIP44 구현 (결정적 지갑을 위한 다중 계정 계층 구조)_ +- [ethereumex](https://github.com/mana-ethereum/ethereumex) - _이더리움 블록체인을 위한 엘릭서 JSON-RPC 클라이언트_ +- [ethers](https://github.com/ExWeb3/elixir_ethers) - _엘릭서를 사용하여 이더리움의 스마트 계약과 상호 작용하기 위한 포괄적인 웹3 라이브러리_ +- [ethers_kms](https://github.com/ExWeb3/elixir_ethers_kms) - _Ethers를 위한 KMS 서명자 라이브러리 (AWS KMS로 트랜잭션 서명)_ +- [ex_abi](https://github.com/poanetwork/ex_abi) - _엘릭서의 이더리움 ABI 파서/디코더/인코더 구현_ +- [ex_keccak](https://github.com/ExWeb3/ex_keccak) - _tiny-keccak Rust 크레이트로 빌드된 NIF를 사용하여 Keccak SHA3-256 해시를 계산하기 위한 엘릭서 라이브러리_ +- [ex_rlp](https://github.com/mana-ethereum/ex_rlp) - _이더리움의 RLP(재귀 길이 접두사) 인코딩의 엘릭서 구현_ + +### 보관됨 / 더 이상 유지 관리되지 않음 {#archived--no-longer-maintained} + +- [eth](https://hex.pm/packages/eth) - _엘릭서용 이더리움 유틸리티_ +- [exw3](https://github.com/hswick/exw3) - _엘릭서를 위한 고급 이더리움 RPC 클라이언트_ +- [mana](https://github.com/mana-ethereum/mana) - _엘릭서로 작성된 이더리움 전체 노드 구현_ + +더 많은 참고 자료를 확인하고 싶으신가요? 저희 [개발자 홈](/developers/)을 확인해 보세요. + +## 엘릭서 커뮤니티 기여자 {#elixir-community-contributors} + +[엘릭서 Slack #ethereum 채널](https://elixir-lang.slack.com/archives/C5RPZ3RJL)은 빠르게 성장하는 커뮤니티가 활동하는 곳이며, 위에 언급된 프로젝트 및 관련 주제에 대한 논의를 위한 전용 공간입니다. diff --git a/public/content/translations/ko/developers/docs/programming-languages/golang/index.md b/public/content/translations/ko/developers/docs/programming-languages/golang/index.md new file mode 100644 index 00000000000..a313c43b5fc --- /dev/null +++ b/public/content/translations/ko/developers/docs/programming-languages/golang/index.md @@ -0,0 +1,84 @@ +--- +title: "Go 개발자를 위한 이더리움" +description: "Go 기반 프로젝트 및 툴링을 사용한 이더리움 개발 방법 알아보기" +lang: ko +incomplete: true +--- + +Go 기반 프로젝트와 툴링을 사용하여 이더리움용으로 개발하는 방법을 알아보세요. + +이더리움을 통한 탈중앙화 애플리케이션 (또는 디앱) 개발하기. 탈중앙화 애플리케이션은 일단 이더리움에 배포되면 항상 프로그래밍된 대로 동작하므로 완전히 신뢰할 수 있습니다. 탈중앙화되었다라는 것은 서비스가 중단되지 않는 다수의 노드가 연결된 네크워크 망에서의 동작을 의미합니다. 상태를 검열할 수 있는 어떤 단체나 개인도 없습니다. 새로운 유형의 애플리케이션을 제작하기 위해 디지털 자산을 사용할 수 있습니다. + +## 스마트 계약 및 솔리디티 언어 시작하기 {#getting-started-with-smart-contracts-and-solidity} + +**Go와 이더리움을 통합하기 위한 첫 단계** + +먼저 기본 지식이 더 필요하시나요? [ethereum.org/learn](/learn/) 또는 [ethereum.org/developers](/developers/)를 확인해 보세요. + +- [블록체인 설명](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) +- [스마트 계약 이해하기](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [첫 스마트 계약 작성하기](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [솔리디티 컴파일 및 배포 방법 알아보기](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) +- [계약 튜토리얼](https://github.com/ethereum/go-ethereum/wiki/Contract-Tutorial) + +## 초보자용 아티클 및 서적 {#beginner-articles-and-books} + +- [Geth 시작하기](https://medium.com/@tzhenghao/getting-started-with-geth-c1a30b8d6458) +- [Golang을 사용하여 이더리움에 연결하기](https://www.youtube.com/watch?v=-7uChuO_VzM) +- [Golang을 사용하여 이더리움 스마트 계약 배포하기](https://www.youtube.com/watch?v=pytGqQmDslE) +- [Go로 이더리움 스마트 계약을 테스트하고 배포하는 단계별 가이드](https://hackernoon.com/a-step-by-step-guide-to-testing-and-deploying-ethereum-smart-contracts-in-go-9fc34b178d78) +- [eBook: Go를 사용한 이더리움 개발](https://goethereumbook.org/) - _Go를 사용하여 이더리움 애플리케이션을 개발합니다_ + +## 중급자용 아티클 및 문서 {#intermediate-articles-and-docs} + +- [Go 이더리움 개발 문서](https://geth.ethereum.org/docs/) - _Go 언어를 사용한 공식 이더리움 개발 문서_ +- [Erigon 프로그래머 가이드](https://github.com/ledgerwatch/erigon/blob/devel/docs/programmers_guide/guide.md) - _상태 트리, 다중 증명 및 트랜잭션 처리를 포함한 그림 설명 가이드_ +- [Erigon과 무상태 이더리움](https://youtu.be/3-Mn7OckSus?t=394) - _2020 이더리움 커뮤니티 콘퍼런스(EthCC 3)_ +- [Erigon: 이더리움 클라이언트 최적화](https://www.youtube.com/watch?v=CSpc1vZQW2Q) - _2018 Devcon 4_ +- [Go 이더리움 GoDoc](https://godoc.org/github.com/ethereum/go-ethereum) +- [Geth와 Go로 디앱 만들기](https://kauri.io/#collections/A%20Hackathon%20Survival%20Guide/creating-a-dapp-in-go-with-geth/) +- [Golang 및 Geth를 사용하여 이더리움 프라이빗 네트워크와 작업하기](https://myhsts.org/tutorial-learn-how-to-work-with-ethereum-private-network-with-golang-with-geth.php) +- [Go를 사용하여 이더리움에서 솔리디티 계약 단위 테스트하기](https://medium.com/coinmonks/unit-testing-solidity-contracts-on-ethereum-with-go-3cc924091281) +- [Geth를 라이브러리로 사용하기 위한 빠른 참조](https://medium.com/coinmonks/web3-go-part-1-31c68c68e20e) + +## 고급 사용 패턴 {#advanced-use-patterns} + +- [GETH 시뮬레이션된 백엔드](https://kauri.io/#collections/An%20ethereum%20test%20toolkit%20in%20Go/the-geth-simulated-backend/#_top) +- [이더리움 및 Quorum을 사용한 서비스형 블록체인 앱](https://blockchain.dcwebmakers.com/blockchain-as-a-service-apps-using-ethereum-and-quorum.html) +- [이더리움 블록체인 애플리케이션의 분산 스토리지 IPFS 및 Swarm](https://blockchain.dcwebmakers.com/work-with-distributed-storage-ipfs-and-swarm-in-ethereum.html) +- [모바일 클라이언트: 라이브러리 및 Inproc 이더리움 노드](https://github.com/ethereum/go-ethereum/wiki/Mobile-Clients:-Libraries-and-Inproc-Ethereum-Nodes) +- [네이티브 디앱스: 이더리움 계약에 대한 Go 바인딩](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts) + +## Go 프로젝트 및 도구 {#go-projects-and-tools} + +- [Geth / Go 이더리움](https://github.com/ethereum/go-ethereum) - _이더리움 프로토콜의 공식 Go 구현체_ +- [Go 이더리움 코드 분석](https://github.com/ZtesoftCS/go-ethereum-code-analysis) - _Go 이더리움 소스 코드 검토 및 분석_ +- [Erigon](https://github.com/ledgerwatch/erigon) - _아카이브 노드에 중점을 둔 더 빠른 Go 이더리움 파생 클라이언트_ +- [Golem](https://github.com/golemfactory/golem) - _Golem은 컴퓨팅 파워를 위한 글로벌 시장을 만들고 있습니다_ +- [Quorum](https://github.com/jpmorganchase/quorum) - _데이터 개인 정보 보호를 지원하는 허가형 이더리움 구현체_ +- [Prysm](https://github.com/prysmaticlabs/prysm) - _이더리움 '세레니티' 2.0 Go 구현체_ +- [Eth Tweet](https://github.com/yep/eth-tweet) - _탈중앙화된 트위터: 이더리움 블록체인에서 실행되는 마이크로블로깅 서비스_ +- [Plasma MVP Golang](https://github.com/kyokan/plasma) — _최소 실행 가능 플라즈마(Minimum Viable Plasma) 사양의 Golang 구현 및 확장_ +- [오픈 이더리움 채굴 풀](https://github.com/sammy007/open-ethereum-pool) - _오픈 소스 이더리움 채굴 풀_ +- [이더리움 HD 지갑](https://github.com/miguelmota/go-ethereum-hdwallet) - _Go의 이더리움 HD 지갑 파생_ +- [Multi Geth](https://github.com/multi-geth/multi-geth) - _다양한 종류의 이더리움 네트워크 지원_ +- [Geth 라이트 클라이언트](https://github.com/zsfelfoldi/go-ethereum/wiki/Geth-Light-Client) - _라이트 이더리움 하위 프로토콜의 Geth 구현체_ +- [Ethereum Golang SDK](https://github.com/everFinance/goether) - _Golang의 간단한 이더리움 지갑 구현 및 유틸리티_ +- [Covalent Golang SDK](https://github.com/covalenthq/covalent-api-sdk-go) - _200개 이상의 블록체인을 위한 Go SDK를 통한 효율적인 블록체인 데이터 접근_ + +더 많은 참고 자료를 확인하고 싶으신가요? [ethereum.org/developers](/developers/)를 확인해 보세요 + +## Go 커뮤니티 기여자 {#go-community-contributors} + +- [Geth 디스코드](https://discordapp.com/invite/nthXNEv) +- [Geth Gist](https://gitter.im/ethereum/go-ethereum) +- [Gophers 슬랙](https://invite.slack.golangbridge.org/) - [#ethereum 채널](https://gophers.slack.com/messages/C9HP1S9V2) +- [StackExchange - 이더리움](https://ethereum.stackexchange.com/) +- [Multi Geth Gitter](https://gitter.im/ethoxy/multi-geth) +- [이더리움 Gitter](https://gitter.im/ethereum/home) +- [Geth 라이트 클라이언트 Gitter](https://gitter.im/ethereum/light-client) + +## 기타 수집된 목록 {#other-aggregated-lists} + +- [Awesome Ethereum](https://github.com/btomashvili/awesome-ethereum) +- [Consensys: 이더리움 개발자 도구 최종 목록](https://media.consensys.net/an-definitive-list-of-ethereum-developer-tools-2159ce865974) | [GitHub 소스](https://github.com/ConsenSys/ethereum-developer-tools-list) diff --git a/public/content/translations/ko/developers/docs/programming-languages/index.md b/public/content/translations/ko/developers/docs/programming-languages/index.md new file mode 100644 index 00000000000..af19b6d1fc9 --- /dev/null +++ b/public/content/translations/ko/developers/docs/programming-languages/index.md @@ -0,0 +1,32 @@ +--- +title: "프로그래밍 언어" +description: "JavaScript, Python, Go, Rust 등 다양한 프로그래밍 언어를 위한 이더리움 개발 참고 자료를 찾아보세요." +lang: ko +--- + +개발자들이 오해하고 있는 부분 중 하나는 이더리움 상에서 구축하려면 반드시 [스마트 계약](/developers/docs/smart-contracts/)을 작성해야 한다는 것입니다. 하지만 이는 사실이 아닙니다. +이더리움 네트워크와 커뮤니티의 장점 중 하나는 거의 모든 프로그래밍 언어로 [참여](/community/)할 수 있다는 것입니다. + +이더리움과 그 커뮤니티는 오픈 소스를 적극적으로 수용합니다. 여러분은 커뮤니티 프로젝트 - 클라이언트 구현, API, 개발 프레임워크, 테스팅 툴-을 매우 다양한 언어로 찾을 수 있다. + +## 언어 선택 {#data} + +프로젝트, 리소스 및 가상 커뮤니티를 찾기 위해 선택할 프로그래밍 언어를 선택하십시오. + +- [Dart 개발자를 위한 이더리움](/developers/docs/programming-languages/dart/) +- [Delphi 개발자를 위한 이더리움](/developers/docs/programming-languages/delphi/) +- [.NET 개발자를 위한 이더리움](/developers/docs/programming-languages/dot-net/) +- [Elixir 개발자를 위한 이더리움](/developers/docs/programming-languages/elixir/) +- [Go 개발자를 위한 이더리움](/developers/docs/programming-languages/golang/) +- [Java 개발자를 위한 이더리움](/developers/docs/programming-languages/java/) +- [JavaScript 개발자를 위한 이더리움](/developers/docs/programming-languages/javascript/) +- [Python 개발자를 위한 이더리움](/developers/docs/programming-languages/python/) +- [Ruby 개발자를 위한 이더리움](/developers/docs/programming-languages/ruby/) +- [Rust 개발자를 위한 이더리움](/developers/docs/programming-languages/rust/) + +### 사용하는 언어가 지원되지 않는다면 어떻게 해야 하나요? {#other-lang} + +추가적인 프로그래밍 언어에 대한 참고 자료를 링크하거나 가상 커뮤니티를 안내하고 싶다면 [이슈를 등록](https://github.com/ethereum/ethereum-org-website/issues/new/choose)하여 새 페이지를 요청할 수 있습니다. + +현재 지원되지 않는 언어를 사용하여 블록체인과 연동하는 코드를 작성하고 싶다면 +[JSON-RPC 인터페이스](/developers/docs/apis/json-rpc/)를 사용하여 이더리움 네트워크에 연결할 수 있습니다. TCP/IP를 사용할 수 있는 모든 프로그래밍 언어는 이 인터페이스를 사용할 수 있습니다. diff --git a/public/content/translations/ko/developers/docs/programming-languages/java/index.md b/public/content/translations/ko/developers/docs/programming-languages/java/index.md new file mode 100644 index 00000000000..3c65914a1b2 --- /dev/null +++ b/public/content/translations/ko/developers/docs/programming-languages/java/index.md @@ -0,0 +1,64 @@ +--- +title: "Java 개발자를 위한 이더리움" +description: "Java 기반 프로젝트 및 툴링을 사용한 이더리움 개발 방법 알아보기" +lang: ko +incomplete: true +--- + +Java 기반 프로젝트 및 툴링을 사용한 이더리움 개발 방법 알아보기 + +이더리움 기반으로 개발된 탈중앙화 애플리케이션(또는 “디앱”)은 암호화폐와 블록체인 기술의 장점을 가지게 됩니다. 탈중앙화 애플리케이션은 일단 이더리움에 배포되면 항상 프로그래밍된 대로 동작하므로 완전히 신뢰할 수 있습니다. 그러므로 새로운 형태의 금융 애플리케이션을 제작하기 위해 디지털 자산을 제어하는 데 사용될 수 있습니다. 그뿐만 아니라 해당 금융 애플리케이션을 어떤 특정 단체나 개인이 제어할 수 없고 검열이 거의 불가능하도록 탈중앙화할 수 있습니다. + +## 스마트 계약 및 솔리디티 언어 시작하기 {#getting-started-with-smart-contracts-and-solidity} + +**Java와 이더리움을 통합하기 위한 첫 단계** + +먼저 기본 지식이 더 필요하시나요? [ethereum.org/learn](/learn/) 또는 [ethereum.org/developers.](/developers/)를 확인해 보세요. + +- [블록체인 설명](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) +- [스마트 계약 이해하기](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [첫 스마트 계약 작성하기](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [솔리디티 컴파일 및 배포 방법 알아보기](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) + +## 이더리움 클라이언트 사용하기 {#working-with-ethereum-clients} + +두 개의 주요 Java 이더리움 클라이언트인 [Web3J](https://github.com/web3j/web3j)와 하이퍼레저 Besu 사용법을 알아보세요. + +- [Java, Eclipse, Web3J로 이더리움 클라이언트에 연결하기](https://kauri.io/article/b9eb647c47a546bc95693acc0be72546/connecting-to-an-ethereum-client-with-java-eclipse-and-web3j) +- [Java 및 Web3j로 이더리움 계정 관리하기](https://kauri.io/article/925d923e12c543da9a0a3e617be963b4/manage-an-ethereum-account-with-java-and-web3j) +- [스마트 계약에서 Java 래퍼 생성하기](https://kauri.io/article/84475132317d4d6a84a2c42eb9348e4b/generate-a-java-wrapper-from-your-smart-contract) +- [이더리움 스마트 계약과 상호 작용하기](https://kauri.io/article/14dc434d11ef4ee18bf7d57f079e246e/interacting-with-an-ethereum-smart-contract-in-java) +- [이더리움 스마트 계약 이벤트 수신하기](https://kauri.io/article/760f495423db42f988d17b8c145b0874/listening-for-ethereum-smart-contract-events-in-java) +- [Linux에서 Java 이더리움 클라이언트인 Besu(Pantheon) 사용하기](https://kauri.io/article/276dd27f1458443295eea58403fd6965/using-pantheon-the-java-ethereum-client-with-linux) +- [Java 통합 테스트에서 하이퍼레저 Besu(Pantheon) 노드 실행하기](https://kauri.io/article/7dc3ecc391e54f7b8cbf4e5fa0caf780/running-a-pantheon-node-in-java-integration-tests) +- [Web3j 치트 시트](https://kauri.io/web3j-cheat-sheet-\(java-ethereum\)/5dfa1ea941ac3d0001ce1d90/c) + +EVM 기반 블록체인과 상호 작용하기 위한 비동기, 고성능 Kotlin 라이브러리인 [ethers-kt](https://github.com/Kr1ptal/ethers-kt) 사용법을 알아보세요. JVM 및 Android 플랫폼 대상으로 합니다. + +- [ERC20 토큰 전송하기](https://github.com/Kr1ptal/ethers-kt/blob/master/examples/src/main/kotlin/io/ethers/examples/abi/TransferERC20.kt) +- [이벤트 수신을 포함한 UniswapV2 교환](https://github.com/Kr1ptal/ethers-kt/blob/master/examples/src/main/kotlin/io/ethers/examples/tokenswapwitheventlistening/TokenSwapWithEventListening.kt) +- [ETH / ERC20 잔액 추적기](https://github.com/Kr1ptal/ethers-kt/blob/master/examples/src/main/kotlin/io/ethers/examples/balancetracker/BalanceTracker.kt) + +## 중급자용 아티클 {#intermediate-articles} + +- [IPFS를 사용하여 Java 애플리케이션의 저장 공간 관리하기](https://kauri.io/article/3e8494f4f56f48c4bb77f1f925c6d926/managing-storage-in-a-java-application-with-ipfs) +- [Java에서 Web3j를 사용하여 ERC20 토큰 관리하기](https://kauri.io/article/d13e911bbf624108b1d5718175a5e0a0/manage-erc20-tokens-in-java-with-web3j) +- [Web3j 트랜잭션 관리자](https://kauri.io/article/4cb780bb4d0846438d11885a25b6d7e7/web3j-transaction-managers) + +## 고급 사용 패턴 {#advanced-use-patterns} + +- [Eventeum을 사용하여 Java 스마트 계약 데이터 캐시 구축하기](https://kauri.io/article/fe81ee9612eb4e5a9ab72790ef24283d/using-eventeum-to-build-a-java-smart-contract-data-cache) + +## Java 프로젝트 및 도구 {#java-projects-and-tools} + +- [Web3J(이더리움 클라이언트와 상호 작용하기 위한 라이브러리)](https://github.com/web3j/web3j) +- [ethers-kt(EVM 기반 블록체인을 위한 비동기, 고성능 Kotlin/Java/Android 라이브러리)](https://github.com/Kr1ptal/ethers-kt) +- [Eventeum(이벤트 리스너)](https://github.com/ConsenSys/eventeum) +- [Mahuta(IPFS 개발 도구)](https://github.com/ConsenSys/mahuta) + +더 많은 참고 자료를 확인하고 싶으신가요? [ethereum.org/developers.](/developers/)를 확인해 보세요. + +## Java 커뮤니티 기여자 {#java-community-contributors} + +- [IO Builders](https://io.builders) +- [Kauri](https://kauri.io) diff --git a/public/content/translations/ko/developers/docs/programming-languages/javascript/index.md b/public/content/translations/ko/developers/docs/programming-languages/javascript/index.md new file mode 100644 index 00000000000..7714ed3bc47 --- /dev/null +++ b/public/content/translations/ko/developers/docs/programming-languages/javascript/index.md @@ -0,0 +1,72 @@ +--- +title: "JavaScript 개발자를 위한 이더리움" +description: "JavaScript 기반 프로젝트 및 툴링을 사용한 이더리움 개발 방법 알아보기." +lang: ko +--- + +자바스크립트는 이더리움 생태계에서 가장 유명한 언어입니다. 실제로 가능한 많은 이더리움을 JavaScript로 가져오는 전담 [팀](https://github.com/ethereumjs)이 있습니다. + +JavaScript(또는 그와 유사한 언어)를 사용하여 [스택의 모든 레벨](/developers/docs/ethereum-stack/)에서 코드를 작성할 수 있습니다. + +## 이더리움과 상호작용하기 {#interact-with-ethereum} + +### JavaScript API 라이브러리 {#javascript-api-libraries} + +블록체인에 쿼리를 요청하고 트랜잭션을 전송하는 등 다양한 작업을 JavaScript로 작성하고 싶다면 [JavaScript API 라이브러리](/developers/docs/apis/javascript/)를 사용하는 것이 가장 편리한 방법입니다. 이러한 API를 통해 개발자는 [이더리움 네트워크의 노드](/developers/docs/nodes-and-clients/)와 쉽게 상호작용할 수 있습니다. + +라이브러리를 사용해 이더리움의 스마트 컨트랙트와 상호작용 할 수 있으므로 자바스크립트를 사용하여 기존의 계약과 상호작용 할 수 있는 디앱을 구죽할 수 있습니다. + +**자세히 알아보기** + +- [Web3.js](https://web3js.readthedocs.io) +- [Ethers.js](https://ethers.org) – _JavaScript 및 TypeScript의 이더리움 지갑 구현 및 유틸리티가 포함되어 있습니다._ +- [viem](https://viem.sh) – _이더리움과 상호작용하기 위한 저수준 무상태 프리미티브를 제공하는 TypeScript 인터페이스입니다._ +- [Drift](https://ryangoree.github.io/drift/) – _내장된 캐싱, 후크, 테스트 목(mock)을 사용하여 여러 웹3 라이브러리에서 이더리움 개발을 쉽게 할 수 있도록 지원하는 TypeScript 메타 라이브러리입니다._ + +### 스마트 계약 {#smart-contracts} + +JavaScript 개발자이고 직접 스마트 계약을 작성하고 싶다면, [Solidity](https://solidity.readthedocs.io)에 익숙해지는 것이 좋습니다. 이것은 가장 인기 있는 스마트 계약 언어이며, 구문이 JavaScript와 유사하여 배우기 쉬울 수 있습니다. + +[스마트 계약](/developers/docs/smart-contracts/)에 대해 더 알아보기. + +## 프로토콜 이해하기 {#understand-the-protocol} + +### 이더리움 가상 머신 {#the-ethereum-virtual-machine} + +[이더리움 가상 머신](/developers/docs/evm/)의 JavaScript 구현이 있습니다. 최신 포크 규칙을 지원합니다. 포크 규칙은 계획된 업그레이드의 결과로 EVM에 가해진 변경 사항을 의미합니다. + +다양한 JavaScript 패키지로 나뉘어 있으며, 이를 확인하여 더 잘 이해할 수 있습니다: + +- 계정 +- 블록 +- 블록체인 자체 +- 트랜잭션 +- 기타 등등... + +이것은 "계정의 데이터 구조가 무엇인가?"와 같은 것들을 이해하는 데 도움이 됩니다. + +코드를 읽는 것을 선호한다면, 이 JavaScript는 문서를 읽는 것에 대한 훌륭한 대안이 될 수 있습니다. + +**EVM 자세히 알아보기** +[`@ethereumjs/evm`](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/evm) + +### 노드 및 클라이언트 {#nodes-and-clients} + +이해할 수 있는 언어인 JavaScript로 이더리움 클라이언트가 어떻게 작동하는지 파악할 수 있는 Ethereumjs 클라이언트가 활발히 개발 중입니다. + +**클라이언트 자세히 알아보기** +[`@ethereumjs/client`](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/client) + +## 기타 프로젝트 {#other-projects} + +이더리움 JavaScript 분야에서는 다음과 같은 많은 일들이 일어나고 있습니다: + +- 지갑 유틸리티 라이브러리. +- 이더리움 키를 생성, 가져오기, 내보내기 위한 도구들. +- `merkle-patricia-tree`의 구현 – 이더리움 옐로우 페이퍼에 기술된 데이터 구조입니다. + +[EthereumJS 리포지토리](https://github.com/ethereumjs)에서 가장 관심 있는 것을 깊이 파고들어 보세요. + +## 더 읽어보기 {#further-reading} + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ diff --git a/public/content/translations/ko/developers/docs/programming-languages/python/index.md b/public/content/translations/ko/developers/docs/programming-languages/python/index.md new file mode 100644 index 00000000000..3e26f8fe47e --- /dev/null +++ b/public/content/translations/ko/developers/docs/programming-languages/python/index.md @@ -0,0 +1,99 @@ +--- +title: "Python 개발자를 위한 이더리움" +description: "Python 기반 프로젝트 및 툴링을 사용한 이더리움 개발 방법 알아보기" +lang: ko +incomplete: true +--- + +Python 기반 프로젝트 및 툴링을 사용한 이더리움 개발 방법 알아보기 + +이더리움 기반으로 개발된 탈중앙화 애플리케이션(또는 “디앱”)은 암호화폐와 블록체인 기술의 장점을 가지게 됩니다. 탈중앙화 애플리케이션은 일단 이더리움에 배포되면 항상 프로그래밍된 대로 동작하므로 완전히 신뢰할 수 있습니다. 그러므로 새로운 형태의 금융 애플리케이션을 제작하기 위해 디지털 자산을 제어하는 데 사용될 수 있습니다. 그뿐만 아니라 해당 금융 애플리케이션을 어떤 특정 단체나 개인이 제어할 수 없고 검열이 거의 불가능하도록 탈중앙화할 수 있습니다. + +## 스마트 계약 및 솔리디티 언어 시작하기 {#getting-started-with-smart-contracts-and-solidity} + +**Python과 이더리움을 통합하기 위한 첫 단계** + +먼저 기본 지식이 더 필요하시나요? [ethereum.org/learn](/learn/) 또는 [ethereum.org/developers](/developers/)를 확인해 보세요. + +- [블록체인 설명](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) +- [스마트 계약 이해하기](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [첫 스마트 계약 작성하기](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [솔리디티 컴파일 및 배포 방법 알아보기](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) +- [2023년 블록체인 파이썬 현황 보고서](https://tradingstrategy.ai/blog/the-state-of-python-in-blockchain-in-2023) + +## 초급자용 아티클 {#beginner-articles} + +- [web3.py 개요](https://web3py.readthedocs.io/en/latest/overview.html) +- [이더리움 파이썬 생태계 둘러보기](https://snakecharmers.ethereum.org/python-ecosystem/) +- [파이썬 개발자를 위한 이더리움 가이드](https://snakecharmers.ethereum.org/a-developers-guide-to-ethereum-pt-1/) +- [수상을 위한: 이더리움 파이썬 해커톤 가이드](https://snakecharmers.ethereum.org/prize-worthy/) +- [Vyper를 사용한 스마트 계약 소개](https://kauri.io/#collections/Getting%20Started/an-introduction-to-smart-contracts-with-vyper/) +- [Python Flask를 사용하여 이더리움 계약을 개발하는 방법](https://medium.com/coinmonks/how-to-develop-ethereum-contract-using-python-flask-9758fe65976e) +- [Web3.py 소개 · 파이썬 개발자를 위한 이더리움](https://www.dappuniversity.com/articles/web3-py-intro) +- [파이썬과 web3.py를 사용하여 스마트 계약 함수를 호출하는 방법](https://stackoverflow.com/questions/57580702/how-to-call-a-smart-contract-function-using-python-and-web3-py) + +## 중급자용 아티클 {#intermediate-articles} + +- [web3.py 관련 도구: Ape 소개](https://snakecharmers.ethereum.org/intro-to-ape/) +- [파이썬 프로그래머를 위한 탈중앙화앱 개발](https://levelup.gitconnected.com/dapps-development-for-python-developers-f52b32b54f28) +- [파이썬 이더리움 인터페이스 만들기: 1부](https://hackernoon.com/creating-a-python-ethereum-interface-part-1-4d2e47ea0f4d) +- [파이썬의 이더리움 스마트 계약: 종합에 가까운 가이드](https://hackernoon.com/ethereum-smart-contracts-in-python-a-comprehensive-ish-guide-771b03990988) + +## 고급 사용 패턴 {#advanced-use-patterns} + +- [web3.py 패턴: 실시간 이벤트 구독](https://snakecharmers.ethereum.org/subscriptions/) +- [web3.py 패턴: WebSocketProvider](https://snakecharmers.ethereum.org/websocketprovider/) +- [파이썬을 사용하여 이더리움 스마트 계약 컴파일, 배포 및 호출하기](https://yohanes.gultom.id/2018/11/28/compiling-deploying-and-calling-ethereum-smartcontract-using-python/) +- [Slither로 솔리디티 스마트 계약 분석하기](https://kauri.io/#collections/DevOps/analyze-solidity-smart-contracts-with-slither/#analyze-solidity-smart-contracts-with-slither) +- [블록체인 핀테크 튜토리얼: 파이썬으로 대출 및 차입 구현하기](https://blog.chain.link/blockchain-fintech-defi-tutorial-lending-borrowing-python/) + +## 보관된 아티클 + +- [파이썬과 브라우니로 나만의 ERC20 토큰 배포하기](https://betterprogramming.pub/python-blockchain-token-deployment-tutorial-create-an-erc20-77a5fd2e1a58) +- [브라우니와 파이썬을 사용하여 스마트 계약 배포하기](https://dev.to/patrickalphac/using-brownie-for-to-deploy-smart-contracts-1kkp) +- [브라우니로 OpenSea에서 NFT 만들기](https://www.freecodecamp.org/news/how-to-make-an-nft-and-render-on-opensea-marketplace/) + +## 파이썬 프로젝트 및 도구 {#python-projects-and-tools} + +### 활성: {#active} + +- [Web3.py](https://github.com/ethereum/web3.py) - _이더리움과 상호작용하기 위한 파이썬 라이브러리_ +- [Vyper](https://github.com/ethereum/vyper/) - _EVM을 위한 파이썬다운 스마트 계약 언어_ +- [Ape](https://github.com/ApeWorX/ape) - _Python 개발자, 데이터 과학자 및 보안 전문가를 위한 스마트 계약 개발 도구_ +- [py-evm](https://github.com/ethereum/py-evm) - _이더리움 가상 머신(EVM) 구현_ +- [eth-tester](https://github.com/ethereum/eth-tester) - _이더리움 기반 애플리케이션 테스트용 도구_ +- [eth-utils](https://github.com/ethereum/eth-utils/) - _이더리움 관련 코드베이스 작업을 위한 유틸리티 함수_ +- [py-solc-x](https://pypi.org/project/py-solc-x/) - _0.5.x 버전을 지원하는 solc 솔리디티 컴파일러용 파이썬 래퍼_ +- [pymaker](https://github.com/makerdao/pymaker) - _메이커 계약을 위한 파이썬 API_ +- [siwe](https://github.com/signinwithethereum/siwe-py) - _파이썬용 이더리움으로 로그인하기(siwe)_ +- [이더리움 통합을 위한 Web3 DeFi](https://github.com/tradingstrategy-ai/web3-ethereum-defi) - _ERC-20, Uniswap 및 기타 인기 프로젝트와 즉시 통합할 수 있는 파이썬 패키지_ +- [Wake](https://getwake.io) - _계약 테스트, 퍼징, 배포, 취약점 스캔 및 코드 탐색을 위한 올인원 파이썬 프레임워크(언어 서버 - [솔리디티용 도구](https://marketplace.visualstudio.com/items?itemName=AckeeBlockchain.tools-for-solidity))_ + +### 보관됨 / 더 이상 유지보수되지 않음: {#archived--no-longer-maintained} + +- [Trinity](https://github.com/ethereum/trinity) - _이더리움 파이썬 클라이언트_ +- [Mamba](https://github.com/arjunaskykok/mamba) - _Vyper 언어로 작성된 스마트 계약을 작성, 컴파일 및 배포하기 위한 프레임워크_ +- [Brownie](https://github.com/eth-brownie/brownie) - _이더리움 스마트 계약을 배포, 테스트 및 상호작용하기 위한 파이썬 프레임워크_ +- [pydevp2p](https://github.com/ethereum/pydevp2p) - _이더리움 P2P 스택 구현_ +- [py-wasm](https://github.com/ethereum/py-wasm) - _웹 어셈블리 인터프리터의 파이썬 구현_ + +더 많은 참고 자료를 확인하고 싶으신가요? [ethereum.org/developers](/developers/)를 확인해 보세요. + +## 파이썬 툴링을 사용하는 프로젝트 {#projects-using-python-tooling} + +아래 이더리움 기반 프로젝트들은 본 페이지에서 언급된 도구를 사용합니다. 모범 사례와 함께 링크된 오픈 소스 저장소에서 좋은 예제 코드를 참조할 수 있습니다. + +- [Yearn Finance](https://yearn.finance/) 및 [Yearn Vault 계약 저장소](https://github.com/yearn/yearn-vaults) +- [Curve](https://www.curve.finance/) 및 [Curve 스마트 계약 저장소](https://github.com/curvefi/curve-contract) +- [BadgerDAO](https://badger.com/) 및 [브라우니 툴체인을 사용하는 스마트 계약](https://github.com/Badger-Finance/badger-system) +- [Sushi](https://sushi.com/)는 [베스팅 계약을 관리하고 배포하는 데 파이썬을 사용합니다](https://github.com/sushiswap/sushi-vesting-protocols) +- Alpha Homora로 유명한 [Alpha Finance](https://alphafinance.io/)는 [스마트 계약을 테스트하고 배포하는 데 브라우니를 사용합니다](https://github.com/AlphaFinanceLab/alpha-staking-contract) + +## 파이썬 커뮤니티 토론 {#python-community-contributors} + +- Web3.py 및 기타 파이썬 프레임워크 토론을 위한 [이더리움 파이썬 커뮤니티 디스코드](https://discord.gg/9zk7snTfWe) +- Vyper 스마트 계약 프로그래밍 토론을 위한 [Vyper 디스코드](https://discord.gg/SdvKC79cJk) + +## 기타 수집된 목록 {#other-aggregated-lists} + +Vyper 위키에는 [Vyper를 위한 훌륭한 참고 자료 목록](https://github.com/vyperlang/vyper/wiki/Vyper-tools-and-resources)이 있습니다. \ No newline at end of file diff --git a/public/content/translations/ko/developers/docs/programming-languages/ruby/index.md b/public/content/translations/ko/developers/docs/programming-languages/ruby/index.md new file mode 100644 index 00000000000..56c0139362d --- /dev/null +++ b/public/content/translations/ko/developers/docs/programming-languages/ruby/index.md @@ -0,0 +1,60 @@ +--- +title: "루비 개발자를 위한 이더리움" +description: "루비 기반 프로젝트와 툴링을 사용해 이더리움용으로 개발하는 방법을 알아보세요." +lang: ko +incomplete: false +--- + +루비 기반 프로젝트와 툴링을 사용해 이더리움용으로 개발하는 방법을 알아보세요. + +이더리움 기반으로 개발된 탈중앙화 애플리케이션(또는 “디앱”)은 암호화폐와 블록체인 기술의 장점을 가지게 됩니다. 이러한 탈중앙화앱은 무신뢰성을 가질 수 있습니다. 즉, 이더리움에 배포되면 항상 프로그래밍된 대로 실행됩니다. 탈중앙화앱은 디지털 자산을 제어하여 새로운 종류의 금융 애플리케이션을 만들 수 있습니다. 그뿐만 아니라 해당 금융 애플리케이션을 어떤 특정 단체나 개인이 제어할 수 없고 검열이 거의 불가능하도록 탈중앙화할 수 있습니다. + +## 스마트 계약 및 솔리디티 언어 시작하기 {#getting-started-with-smart-contracts-and-solidity} + +**루비와 이더리움을 통합하기 위한 첫걸음을 내딛어 보세요** + +먼저 기본 지식이 더 필요하시나요? [ethereum.org/learn](/learn/) 또는 [ethereum.org/developers](/developers/)를 확인해 보세요. + +- [블록체인 설명](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) +- [스마트 계약 이해하기](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [첫 스마트 계약 작성하기](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [솔리디티 컴파일 및 배포 방법 알아보기](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) + +## 초급자용 아티클 {#beginner-articles} + +- [드디어 이더리움 계정 이해하기](https://dev.to/q9/finally-understanding-ethereum-accounts-1kpe) +- [드디어 MetaMask로 Rails 사용자 인증하기](https://dev.to/q9/finally-authenticating-rails-users-with-metamask-3fj) +- [루비를 사용하여 이더리움 네트워크에 연결하는 방법](https://www.quicknode.com/guides/web3-sdks/how-to-connect-to-the-ethereum-network-using-ruby) +- [루비에서 새로운 이더리움 주소를 생성하는 방법](https://www.quicknode.com/guides/web3-sdks/how-to-generate-a-new-ethereum-address-in-ruby) + +## 중급자용 아티클 {#intermediate-articles} + +- [루비를 사용한 블록체인 앱](https://www.nopio.com/blog/blockchain-app-ruby/) +- [이더리움에 연결된 루비를 사용하여 스마트 계약 실행하기](https://titanwolf.org/Network/Articles/Article?AID=87285822-9b25-49d5-ba2a-7ad95fff7ef9) + +## 루비 프로젝트 및 도구 {#ruby-projects-and-tools} + +### 활성 {#active} + +- [eth.rb](https://github.com/q9f/eth.rb) - _이더리움 계정, 메시지, 트랜잭션을 처리하기 위한 루비 라이브러리 및 RPC 클라이언트_ +- [keccak.rb](https://github.com/q9f/keccak.rb) - _이더리움에서 사용되는 Keccak(SHA3) 해시_ +- [siwe-ruby](https://github.com/signinwithethereum/siwe-ruby) - _이더리움으로 로그인(Sign-In with Ethereum)의 루비 구현_ +- [siwe-rails](https://github.com/signinwithethereum/siwe-rails) - _SIWE 로컬 로그인 라우트를 추가하는 Rails gem_ +- [siwe-rails-examples](https://github.com/signinwithethereum/siwe-rails-examples) - _커스텀 컨트롤러를 사용하여 Ruby on Rails를 이용한 SIWE 예제_ +- [omniauth-siwe](https://github.com/signinwithethereum/omniauth-siwe) - _이더리움으로 로그인(SIWE)을 위한 OmniAuth 전략_ +- [omniauth-nft](https://github.com/valthon/omniauth-nft) - _NFT 소유권을 통해 인증하기 위한 OmniAuth 전략_ +- [ethereum-on-rails](https://github.com/q9f/ethereum-on-rails) - _MetaMask를 Ruby on Rails에 연결할 수 있는 Ethereum on Rails 템플릿_ + +### 보관됨 / 더 이상 유지 관리되지 않음 {#archived--no-longer-maintained} + +- [web3-eth](https://github.com/spikewilliams/vtada-ethereum) - _루비를 사용하여 이더리움 노드의 RPC 메서드 호출_ +- [ethereum_tree](https://github.com/longhoangwkm/ethereum_tree) - _BIP32 표준에 따라 계층적 결정적 지갑에서 ETH 주소를 생성하기 위한 루비 라이브러리_ +- [etherlite](https://github.com/budacom/etherlite) - _Ruby on Rails를 위한 이더리움 통합_ +- [ethereum.rb](https://github.com/EthWorks/ethereum.rb) - _트랜잭션 전송, 계약 생성 및 상호 작용을 위해 JSON-RPC 인터페이스를 사용하는 루비 이더리움 클라이언트이자 이더리움 노드와 함께 작동하는 유용한 툴킷_ +- [omniauth-ethereum.rb](https://github.com/q9f/omniauth-ethereum.rb) - _OmniAuth를 위한 이더리움 공급자 전략 구현_ + +더 많은 참고 자료를 확인하고 싶으신가요? 저희 [개발자 홈](/developers/)을 확인해 보세요. + +## 루비 커뮤니티 기여자 {#ruby-community-contributors} + +[이더리움 루비 텔레그램 그룹](https://t.me/ruby_eth)은 빠르게 성장하는 커뮤니티의 장이며, 위에 언급된 모든 프로젝트 및 관련 주제에 대한 논의를 위한 전용 참고 자료입니다. diff --git a/public/content/translations/ko/developers/docs/programming-languages/rust/index.md b/public/content/translations/ko/developers/docs/programming-languages/rust/index.md new file mode 100644 index 00000000000..a266282c6b5 --- /dev/null +++ b/public/content/translations/ko/developers/docs/programming-languages/rust/index.md @@ -0,0 +1,65 @@ +--- +title: "Rust 개발자를 위한 이더리움" +description: "Rust 기반 프로젝트 및 툴링을 사용한 이더리움 개발 방법 알아보기" +lang: ko +incomplete: true +--- + +Rust 기반 프로젝트 및 툴링을 사용하여 이더리움을 개발하는 방법을 알아보세요 + +이더리움 기반으로 개발된 탈중앙화 애플리케이션(또는 “디앱”)은 암호화폐와 블록체인 기술의 장점을 가지게 됩니다. 탈중앙화 애플리케이션은 일단 이더리움에 배포되면 항상 프로그래밍된 대로 동작하므로 완전히 신뢰할 수 있습니다. 그러므로 새로운 형태의 금융 애플리케이션을 제작하기 위해 디지털 자산을 제어하는 데 사용될 수 있습니다. 그뿐만 아니라 해당 금융 애플리케이션을 어떤 특정 단체나 개인이 제어할 수 없고 검열이 거의 불가능하도록 탈중앙화할 수 있습니다. + +## 스마트 계약 및 솔리디티 언어 시작하기 {#getting-started-with-smart-contracts-and-solidity} + +**러스트와 이더리움을 통합하기 위한 첫 단계** + +먼저 기본 지식이 더 필요하시나요? [ethereum.org/learn](/learn/) 또는 [ethereum.org/developers](/developers/)를 확인해 보세요. + +- [블록체인 설명](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) +- [스마트 계약 이해하기](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [첫 스마트 계약 작성하기](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [솔리디티 컴파일 및 배포 방법 알아보기](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) + +## 초급자용 아티클 {#beginner-articles} + +- [Rust 이더리움 클라이언트](https://openethereum.github.io/) \* **참고: OpenEthereum은 [더 이상 사용되지 않으며](https://medium.com/openethereum/gnosis-joins-erigon-formerly-turbo-geth-to-release-next-gen-ethereum-client-c6708dd06dd) 더 이상 유지 관리되지 않습니다.** 주의하여 사용하고 가급적 다른 클라이언트 구현으로 전환하십시오. +- [Rust를 사용하여 이더리움으로 트랜잭션 보내기](https://kauri.io/#collections/A%20Hackathon%20Survival%20Guide/sending-ethereum-transactions-with-rust/) +- [Kovan용 rust Wasm으로 컨트랙트를 작성하는 방법에 대한 단계별 튜토리얼](https://github.com/paritytech/pwasm-tutorial) + +## 중급자용 아티클 {#intermediate-articles} + +## 고급 사용 패턴 {#advanced-use-patterns} + +- [이더리움과 유사한 네트워크와 상호작용하기 위한 pwasm_ethereum 외부 라이브러리](https://github.com/openethereum/pwasm-ethereum) + +- [JavaScript와 Rust를 사용하여 탈중앙화 채팅 구축하기](https://medium.com/perlin-network/build-a-decentralized-chat-using-javascript-rust-webassembly-c775f8484b52) + +- [Vue.js와 Rust를 사용하여 탈중앙화 Todo 앱 구축하기](https://medium.com/@jjmace01/build-a-decentralized-todo-app-using-vue-js-rust-webassembly-5381a1895beb) + +- [Rust로 블록체인 구축하기](https://blog.logrocket.com/how-to-build-a-blockchain-in-rust/) + +## Rust 프로젝트 및 도구 {#rust-projects-and-tools} + +- [pwasm-ethereum](https://github.com/paritytech/pwasm-ethereum) - _이더리움과 유사한 네트워크와 상호작용하기 위한 외부 모음_ +- [Lighthouse](https://github.com/sigp/lighthouse) - _빠른 이더리움 합의 레이어 클라이언트_ +- [Ethereum WebAssembly](https://ewasm.readthedocs.io/en/mkdocs/) - _결정론적 WebAssembly 하위 집합을 사용한 이더리움 스마트 계약 실행 레이어의 제안된 재설계_ +- [oasis_std](https://docs.rs/oasis-std/latest/oasis_std/index.html) - _OASIS API 레퍼런스_ +- [Solaris](https://github.com/paritytech/sol-rs) - _네이티브 Parity 클라이언트 EVM을 사용하는 Solidity 스마트 계약 단위 테스트 하네스._ +- [SputnikVM](https://github.com/rust-blockchain/evm) - _Rust 이더리움 가상 머신 구현_ +- [Wavelet](https://wavelet.perlin.net/docs/smart-contracts) - _Rust의 Wavelet 스마트 계약_ +- [Foundry](https://github.com/foundry-rs/foundry) - _이더리움 애플리케이션 개발을 위한 툴킷_ +- [Alloy](https://alloy.rs) - _이더리움 및 기타 EVM 기반 체인과 상호작용하기 위한 고성능의 잘 테스트되고 문서화된 라이브러리._ +- [Ethers_rs](https://github.com/gakonst/ethers-rs) - _이더리움 라이브러리 및 지갑 구현_ +- [SewUp](https://github.com/second-state/SewUp) - _일반적인 백엔드에서 개발하는 것처럼 Rust로 이더리움 웹어셈블리 계약을 구축하는 데 도움이 되는 라이브러리_ +- [Substreams](https://github.com/streamingfast/substreams) - _병렬화된 블록체인 데이터 인덱싱 기술_ +- [Reth](https://github.com/paradigmxyz/reth) Reth(Rust Ethereum의 줄임말)는 새로운 이더리움 전체 노드 구현입니다 +- [Awesome Ethereum Rust](https://github.com/Vid201/awesome-ethereum-rust) - _Rust로 작성된 이더리움 생태계의 프로젝트 큐레이션 모음_ + +더 많은 참고 자료를 확인하고 싶으신가요? [ethereum.org/developers.](/developers/)를 확인해 보세요. + +## Rust 커뮤니티 기여자 {#rust-community-contributors} + +- [Ethereum WebAssembly](https://gitter.im/ewasm/Lobby) +- [Oasis Gitter](https://gitter.im/Oasis-official/Lobby) +- [Parity Gitter](https://gitter.im/paritytech/parity) +- [Enigma](https://discord.gg/SJK32GY) diff --git a/public/content/translations/ko/developers/docs/scaling/index.md b/public/content/translations/ko/developers/docs/scaling/index.md new file mode 100644 index 00000000000..774bb3e56f9 --- /dev/null +++ b/public/content/translations/ko/developers/docs/scaling/index.md @@ -0,0 +1,113 @@ +--- +title: "확장" +description: "현재 Ethereum 커뮤니티에서 개발 중인 다양한 레이어 롤업 스케일링 솔루션에 대한 소개" +lang: ko +sidebarDepth: 3 +--- + +## 확장 개요 {#scaling-overview} + +이더리움을 사용하는 사람들이 증가함에 따라 블록체인은 여러 가지 용량 제한에 도달했습니다. 이 때문에 네트워크 사용 비용은 높아졌으며 "확장 솔루션"이 필요하게 되었습니다. 유사한 목표를 달성하기 위해 다양한 접근 방식을 취하는 여러 솔루션이 연구, 테스트 및 구현되고 있습니다. + +확장성의 주요 목표는 탈중앙성이나 보안을 희생하지 않으면서 트랜잭션 속도(더 빠른 완결성)와 트랜잭션 처리량(초당 더 많은 트랜잭션)을 높이는 것입니다. 레이어 1 이더리움 블록체인에서는 수요가 높으면 트랜잭션이 느려지고 [가스 가격](/developers/docs/gas/)이 비현실적으로 높아집니다. 속도와 처리량 측면에서 네트워크 용량을 늘리는 것은 이더리움의 의미 있는 대규모 채택을 위해 기본적입니다. + +속도와 처리량이 중요하지만, 이러한 목표를 가능하게 하는 확장 솔루션이 탈중앙화되고 안전하게 유지되는 것이 필수적입니다. 노드 운영자의 진입 장벽을 낮게 유지하는 것은 중앙집중화되고 안전하지 않은 컴퓨팅 파워로의 진행을 방지하는 데 중요합니다. + +개념적으로 우리는 먼저 확장을 온체인 또는 오프라인 확장으로 분류합니다. + +## 필수 구성 요소 {#prerequisites} + +모든 기초 주제에 대해 잘 이해하고 있어야 합니다. 확장 솔루션을 구현하는 것은 기술이 덜 검증되었고 지속적으로 연구 및 개발되고 있기 때문에 고급 단계입니다. + +## 온체인 확장 {#onchain-scaling} + +온체인 확장은 이더리움 프로토콜(레이어 1 [메인넷](/glossary/#mainnet))의 변경을 필요로 합니다. 오랫동안 블록체인 샤딩은 이더리움을 확장할 것으로 예상되었습니다. 이는 블록체인을 개별 조각(샤드)으로 분할하여 검증자 하위 집합에 의해 검증되도록 하는 것을 포함할 예정이었습니다. 그러나 레이어 2 롤업을 통한 확장이 주요 확장 기술로 자리잡았습니다. 이는 사용자에게 롤업을 저렴하게 만들기 위해 특별히 설계된 이더리움 블록에 첨부된 새로운 저렴한 형태의 데이터 추가로 지원됩니다. + +### 샤딩 {#sharding} + +샤딩은 데이터베이스를 분할하는 과정입니다. 검증자의 하위 집합이 이더리움 전체를 추적하는 대신 개별 샤드를 담당하게 됩니다. 샤딩은 오랫동안 이더리움 [로드맵](/roadmap/)에 있었으며, 한때 지분 증명으로 전환하는 더 머지 이전에 출시될 예정이었습니다. 하지만 [레이어 2 롤업](#layer-2-scaling)의 빠른 개발과 [댕크샤딩](/roadmap/danksharding)(검증자가 매우 효율적으로 검증할 수 있는 롤업 데이터 블롭을 이더리움 블록에 추가하는 것)의 발명으로 이더리움 커뮤니티는 샤딩을 통한 확장 대신 롤업 중심의 확장을 선호하게 되었습니다. 이는 또한 이더리움의 합의 로직을 더 단순하게 유지하는 데 도움이 될 것입니다. + +## 오프체인 확장 {#offchain-scaling} + +오프체인 솔루션은 레이어 1 메인넷과는 별도로 구현됩니다- 그들은 현재의 이더리움 프로토콜에 변화를 요구하지 않습니다. "레이어 2" 솔루션으로 알려진 일부 솔루션은 [낙관적 롤업](/developers/docs/scaling/optimistic-rollups/), [영지식 롤업](/developers/docs/scaling/zk-rollups/) 또는 [상태 채널](/developers/docs/scaling/state-channels/)과 같이 레이어 1 이더리움 합의에서 직접 보안을 확보합니다. 다른 솔루션들은 [사이드체인](#sidechains), [밸리디움](#validium), 또는 [플라즈마 체인](#plasma)과 같이 메인넷과 별개로 보안을 확보하는 다양한 형태의 새로운 체인 생성을 포함합니다. 이러한 솔루션들은 메인넷과 통신하지만 다양한 목표를 달성하기 위해 보안을 다르게 도출합니다. + +### 레이어 2 확장 {#layer-2-scaling} + +이러한 오프체인 해결책의 분류는. + +레이어 2는 당신의 어플리케이션을 확장시킬 수 있도록 하기 위해 Ethereum 메인넷 (레이어 1) 에서 트랜잭션을 처리하면서 메인넷의 탈중앙화된 강력한 보안 모델을 활용하도록 설계된 솔루션을 총칭합니다. 네트워크가 혼잡할 때는 트랜잭션 속도가 저하되어, 특정 유형의 dapp에서는 사용자 환경이 좋지 않습니다. 네트워크가 더 혼잡해지면, 트랜잭션 발신자들 서로가 가격을 비싸게 매기게 되면서 가스 가격이 상승합니다. 이러한 현상은 Ethereum을 더욱 비싸게 만듭니다. + +대부분의 레이어 2 솔루션은 서버 또는 서버 클러스터를 중심으로 구성되며, 각각을 노드, 검증자, 운영자, 시퀀서, 블록 프로듀서 또는 유사한 용어로 지칭할 수 있습니다. 구현에 따라 이러한 레이어 2 노드는 이를 사용하는 개인, 기업 또는 단체에 의해 운영되거나, 제3자 운영자에 의해 운영되거나, 많은 개인 그룹에 의해 운영될 수 있습니다(메인넷과 유사). 일반적으로 거래는 레이어 1(메인넷)에 직접 제출되는 대신 이러한 레이어 2 노드에 제출됩니다. 몇 가지 해결책으로, 레이어 2 인스턴스는 데이터를 그룹으로 일괄 배치하고 레이어 1 에 고정합니다. 그런 뒤 데이터는 레이어 1 에 의해 보호되고 변경할 수 없습니다. 이 작업이 수행되는 방식의 세부 사항은 다양한 레이어 2 기술 및 구현 간에 크게 다릅니다. + +특정 레이어 2 인스턴스는 많은 애플리케이션이 열어 공유할 수도 있고, 하나의 프로젝트에 의해 배포되어 해당 애플리케이션만 지원하도록 전용될 수도 있습니다. + +#### 레이어 2란 무엇인가요? {#why-is-layer-2-needed} + +- 초당 거래 수의 증가는 사용자 경험을 크게 향상시키고 메인넷 이더리움의 네트워크 혼잡을 줄입니다. +- 거래는 메인넷 이더리움으로 하나의 거래로 롤업되며, 이를 통해 사용자에게 가스 요금을 줄이고 이더리움을 모든 사람에게 더 포괄적이고 접근 가능하게 만듭니다. +- 확장성에 관한 어떤 업데이트도 분산 및 보안을 희생해서는 안됩니다 - Ethereum의 가장 위에 레이어 2가 세워집니다. +- 규모에 맞게 자산을 다룰 때 자체적인 효율성을 제공하는 애플리케이션 전용 레이어 2 네트워크가 있습니다. + +[레이어 2에 대해 더 알아보기](/layer-2/). + +#### 롤업 {#rollups} + +롤업은 트랜잭션 실행을 레이어 1 외부에서 수행한 다음 데이터를 레이어 1에 게시하여 합의가 이루어집니다. 트랜잭션 데이터가 레이어 1 블록에 포함되기 때문에 롤업은 이더리움 네이티브 보안에 의해 보호됩니다. + +다른 보안 모델을 가지는 두 가지 종류의 롤업이 있습니다: + +- **낙관적 롤업**: 트랜잭션이 기본적으로 유효하다고 가정하고, 이의가 제기될 경우에만 [**사기 증명**](/glossary/#fraud-proof)을 통해 연산을 실행합니다. [낙관적 롤업에 대해 더 알아보기](/developers/docs/scaling/optimistic-rollups/). +- **영지식 롤업**: 오프체인에서 연산을 실행하고 체인에 [**유효성 증명**](/glossary/#validity-proof)을 제출합니다. [영지식 롤업에 대해 더 알아보기](/developers/docs/scaling/zk-rollups/). + +#### 상태 채널 {#channels} + +상태 채널은 다중 계약을 사용해 참여자들이 오프체인에서 거래를 빠르고 자유롭게 거래한 뒤 메인넷에서 거래를 확정하게 합니다. 이것은 네트워크 혼잡, 수수료 그리고 딜레이를 최소화 합니다. 현재 두 가지 채널 유형은 State 채널과 Payment 채널입니다. + +[상태 채널에 대해 더 알아보기](/developers/docs/scaling/state-channels/). + +### 사이드체인 {#sidechains} + +사이드체인은 메인넷과 병렬로 실행되는 독립적인 EVM 호환 블록체인입니다. 이들은 이더리움과 양방향 브리지로 호환되며, 독자적인 합의 규칙과 블록 매개변수를 따릅니다. + +[사이드체인에 대해 더 알아보기](/developers/docs/scaling/sidechains/). + +### 플라즈마 {#plasma} + +플라즈마 체인은 메인 이더리움 체인에 고정된 별도의 블록체인으로, 분쟁 중재를 위해 ([낙관적 롤업](/developers/docs/scaling/optimistic-rollups/)처럼) 사기 증명을 사용합니다. + +[플라즈마에 대해 더 알아보기](/developers/docs/scaling/plasma/). + +### 밸리디움 {#validium} + +Validium 체인은 Zero-knowledge 롤업과 유사한 유효성 증명을 사용하지만 데이터는 메인 레이어 1 이더리움 체인에 저장되지 않습니다. 이로 인해 Validium 체인당 초당 10,000건의 트랜잭션이 가능하며, 여러 체인이 병렬로 실행될 수 있습니다. + +[밸리디움에 대해 더 알아보기](/developers/docs/scaling/validium/). + +## 왜 이렇게 많은 확장 솔루션이 필요한가요? {#why-do-we-need-these} + +- 여러 솔루션은 네트워크의 특정 부분에 대한 혼잡을 줄이고 단일 장애 지점을 방지할 수 있습니다. +- 전체는 각 부분의 합보다 큽니다. 다양한 솔루션이 공존하고 조화를 이루어 미래의 트랜잭션 속도와 처리량에 기하급수적인 영향을 미칠 수 있습니다. +- 모든 솔루션이 이더리움 합의 알고리즘을 직접 활용할 필요는 없으며, 대안은 얻기 어려운 이점을 제공할 수 있습니다. + +## 시각 자료를 찾고 있나요? 시각적 학습자 + + + +_해당 동영상에서는 "레이어 2"라는 용어를 모든 오프체인 확장 솔루션을 통칭하는 의미로 사용하지만, 우리는 "레이어 2"를 레이어 1 메인넷 합의를 통해 보안을 확보하는 오프체인 솔루션으로 정의합니다._ + + + +## 더 읽어보기 {#further-reading} + +- [롤업 중심의 이더리움 로드맵](https://ethereum-magicians.org/t/a-rollup-centric-ethereum-roadmap/4698) _Vitalik Buterin_ +- [이더리움을 위한 레이어 2 확장 솔루션에 대한 최신 분석](https://www.l2beat.com/) +- [이더리움 레이어 2 확장 솔루션 평가: 비교 프레임워크](https://medium.com/matter-labs/evaluating-ethereum-l2-scaling-solutions-a-comparison-framework-b6b2f410f955) +- [롤업에 대한 불완전한 가이드](https://vitalik.eth.limo/general/2021/01/05/rollup.html) +- [이더리움 기반 ZK-롤업: 세계 최고 수준](https://hackmd.io/@canti/rkUT0BD8K) +- [낙관적 롤업 대 ZK 롤업](https://limechain.tech/blog/optimistic-rollups-vs-zk-rollups/) +- [왜 롤업과 데이터 샤드가 높은 확장성을 위한 유일한 지속 가능한 해결책인가](https://polynya.medium.com/why-rollups-data-shards-are-the-only-sustainable-solution-for-high-scalability-c9aabd6fbb48) +- [어떤 종류의 레이어 3가 타당한가?](https://vitalik.eth.limo/general/2022/09/17/layer_3.html) +- [데이터 가용성: 또는 롤업이 어떻게 걱정을 멈추고 이더리움을 사랑하게 되었는가](https://web.archive.org/web/20250515194659/https://web.archive.org/web/20241108192208/https://research.2077.xyz/data-availability-or-how-rollups-learned-to-stop-worrying-and-love-ethereum) +- [이더리움 롤업에 대한 실용 가이드](https://web.archive.org/web/20241108192208/https://research.2077.xyz/the-practical-guide-to-ethereum-rollups) + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ diff --git a/public/content/translations/ko/developers/docs/scaling/optimistic-rollups/index.md b/public/content/translations/ko/developers/docs/scaling/optimistic-rollups/index.md new file mode 100644 index 00000000000..a7cc8e3d7ff --- /dev/null +++ b/public/content/translations/ko/developers/docs/scaling/optimistic-rollups/index.md @@ -0,0 +1,265 @@ +--- +title: "낙관적 롤업" +description: "낙관적 롤업 소개—이더리움 커뮤니티에서 사용하는 확장 솔루션입니다." +lang: ko +--- + +낙관적 롤업은 이더리움의 기본 레이어 처리량을 확장하기 위해 설계된 레이어 2(L2) 프로토콜입니다. 이들은 오프체인으로 트랜잭션을 처리하여 메인 이더리움 체인의 연산을 줄여주므로 처리 속도가 크게 향상됩니다. [사이드체인](/developers/docs/scaling/sidechains/)과 같은 다른 확장 솔루션이나, 이더리움에서 사기 증명으로 트랜잭션을 검증하지만 트랜잭션 데이터를 다른 곳에 저장하는 [플라즈마 체인](/developers/docs/scaling/plasma/)과 달리, 낙관적 롤업은 트랜잭션 결과를 온체인에 게시하여 메인넷으로부터 보안을 확보합니다. + +연산은 이더리움을 사용하는 데 있어 느리고 비용이 많이 드는 부분이므로, 낙관적 롤업은 확장성을 10\~100배 향상시킬 수 있습니다. 낙관적 롤업은 또한 이더리움에 트랜잭션을 `calldata` 또는 [블롭](/roadmap/danksharding/)으로 기록하여 사용자의 가스 비용을 줄입니다. + +## 필수 구성 요소 {#prerequisites} + +[이더리움 확장](/developers/docs/scaling/) 및 [레이어 2](/layer-2/)에 대한 페이지를 읽고 이해해야 합니다. + +## 낙관적 롤업이란 무엇인가요? {#what-is-an-optimistic-rollup} + +낙관적 롤업은 연산 및 상태 저장을 오프체인으로 이동하는 이더리움 확장 방식입니다. 낙관적 롤업은 이더리움 외부에서 트랜잭션을 실행하지만, 트랜잭션 데이터를 `calldata` 또는 [블롭](/roadmap/danksharding/)으로 메인넷에 게시합니다. + +낙관적 롤업 운영자는 이더리움에 제출하기 전에 여러 오프체인 트랜잭션을 대규모 배치로 묶습니다. 이 접근 방식을 사용하면 각 배치의 여러 트랜잭션에 고정 비용을 분산하여 최종 사용자의 수수료를 줄일 수 있습니다. 또한 낙관적 롤업은 압축 기술을 사용하여 이더리움에 게시되는 데이터의 양을 줄입니다. + +낙관적 롤업이 "낙관적"이라고 간주되는 이유는 오프체인 트랜잭션이 유효하다고 가정하고 온체인에 게시된 트랜잭션 배치에 대한 유효성 증명을 게시하지 않기 때문입니다. 이 점은 오프체인 트랜잭션에 대한 암호화된 [유효성 증명](/glossary/#validity-proof)을 게시하는 [영지식 롤업](/developers/docs/scaling/zk-rollups)과 낙관적 롤업을 구분합니다. + +대신 낙관적 롤업은 사기 증명 체계를 사용하여 트랜잭션이 올바르게 계산되지 않은 경우를 감지합니다. 롤업 배치가 이더리움에 제출된 후에는 누구나 [사기 증명](/glossary/#fraud-proof)을 계산하여 롤업 트랜잭션 결과에 이의를 제기할 수 있는 시간 창(챌린지 기간이라고 함)이 있습니다. + +사기 증명이 성공하면 롤업 프로토콜은 트랜잭션을 다시 실행하고 그에 따라 롤업의 상태를 업데이트합니다. 사기 증명이 성공할 경우 또 다른 효과는 잘못 실행된 트랜잭션을 블록에 포함시킨 시퀀서가 페널티를 받는다는 것입니다. + +챌린지 기간이 지난 후에도 롤업 배치에 이의가 제기되지 않으면(즉, 모든 트랜잭션이 올바르게 실행되면) 유효한 것으로 간주되어 이더리움에서 수락됩니다. 다른 사람들은 미확인 롤업 블록을 기반으로 계속 구축할 수 있지만, 이전에 게시된 잘못 실행된 트랜잭션을 기반으로 한 경우 트랜잭션 결과가 되돌려진다는 주의사항이 있습니다. + +## 낙관적 롤업은 이더리움과 어떻게 상호 작용하나요? {#optimistic-rollups-and-Ethereum} + +낙관적 롤업은 이더리움 위에서 작동하도록 구축된 [오프체인 확장 솔루션](/developers/docs/scaling/#offchain-scaling)입니다. 각 낙관적 롤업은 이더리움 네트워크에 배포된 스마트 계약 세트에 의해 관리됩니다. 낙관적 롤업은 메인 이더리움 체인 외부에서 트랜잭션을 처리하지만 오프체인 트랜잭션(배치 단위)을 온체인 롤업 계약에 게시합니다. 이더리움 블록체인과 마찬가지로 이 트랜잭션 기록은 변경할 수 없으며 "낙관적 롤업 체인"을 형성합니다. + +낙관적 롤업의 아키텍처는 다음 부분으로 구성됩니다. + +**온체인 계약**: 낙관적 롤업의 운영은 이더리움에서 실행되는 스마트 계약에 의해 제어됩니다. 여기에는 롤업 블록을 저장하고, 롤업의 상태 업데이트를 모니터링하며, 사용자 예금을 추적하는 계약이 포함됩니다. 이러한 의미에서 이더리움은 낙관적 롤업의 기본 레이어 또는 "레이어 1" 역할을 합니다. + +**오프체인 가상 머신(VM)**: 낙관적 롤업 프로토콜을 관리하는 계약은 이더리움에서 실행되지만, 롤업 프로토콜은 [이더리움 가상 머신](/developers/docs/evm/)과는 별개의 다른 가상 머신에서 연산 및 상태 저장을 수행합니다. 오프체인 VM은 애플리케이션이 존재하고 상태 변경이 실행되는 곳으로, 낙관적 롤업의 상위 레이어 또는 "레이어 2" 역할을 합니다. + +낙관적 롤업은 EVM용으로 작성되거나 컴파일된 프로그램을 실행하도록 설계되었으므로, 오프체인 VM은 많은 EVM 설계 사양을 통합합니다. 또한 온체인에서 계산된 사기 증명을 통해 이더리움 네트워크는 오프체인 VM에서 계산된 상태 변경의 유효성을 강제할 수 있습니다. + +낙관적 롤업은 별도의 프로토콜로 존재하지만 보안 속성은 이더리움에서 파생되므로 '하이브리드 확장 솔루션'으로 설명됩니다. 무엇보다도 이더리움은 롤업의 오프체인 연산의 정확성과 연산 이면의 데이터 가용성을 보장합니다. 이로 인해 낙관적 롤업은 보안을 위해 이더리움에 의존하지 않는 순수 오프체인 확장 프로토콜(예: [사이드체인](/developers/docs/scaling/sidechains/))보다 더 안전합니다. + +낙관적 롤업은 다음을 위해 메인 이더리움 프로토콜에 의존합니다. + +### 데이터 가용성 {#data-availability} + +언급했듯이, 낙관적 롤업은 트랜잭션 데이터를 `calldata` 또는 [블롭](/roadmap/danksharding/)으로 이더리움에 게시합니다. 롤업 체인의 실행은 제출된 트랜잭션을 기반으로 하므로, 누구나 이더리움의 기본 레이어에 고정된 이 정보를 사용하여 롤업의 상태를 실행하고 상태 전환의 정확성을 검증할 수 있습니다. + +[데이터 가용성](/developers/docs/data-availability/)은 상태 데이터에 액세스하지 않으면 챌린저가 유효하지 않은 롤업 작업에 이의를 제기하기 위해 사기 증명을 구성할 수 없기 때문에 매우 중요합니다. 이더리움이 데이터 가용성을 제공함으로써 롤업 운영자가 악의적인 행위(예: 유효하지 않은 블록 제출)를 저지르고도 무사히 넘어갈 위험이 줄어듭니다. + +### 검열 저항성 {#censorship-resistance} + +또한 낙관적 롤업은 검열 저항성을 위해 이더리움에 의존합니다. 낙관적 롤업에서는 중앙화된 주체(운영자)가 트랜잭션을 처리하고 롤업 블록을 이더리움에 제출하는 책임을 집니다. 여기에는 몇 가지 시사점이 있습니다. + +- 롤업 운영자는 완전히 오프라인 상태가 되거나 특정 트랜잭션을 포함하는 블록 생성을 거부함으로써 사용자를 검열할 수 있습니다. + +- 롤업 운영자는 소유권의 머클 증명에 필요한 상태 데이터를 보류함으로써 사용자가 롤업 계약에 예치된 자금을 인출하는 것을 막을 수 있습니다. 상태 데이터를 보류하면 사용자로부터 롤업의 상태를 숨기고 롤업과 상호 작용하는 것을 막을 수도 있습니다. + +낙관적 롤업은 운영자가 이더리움의 상태 업데이트와 관련된 데이터를 게시하도록 강제하여 이 문제를 해결합니다. 롤업 데이터를 온체인에 게시하면 다음과 같은 이점이 있습니다. + +- 낙관적 롤업 운영자가 오프라인 상태가 되거나 트랜잭션 배치 생성을 중단하면 다른 노드가 사용 가능한 데이터를 사용하여 롤업의 마지막 상태를 재현하고 블록 생성을 계속할 수 있습니다. + +- 사용자는 트랜잭션 데이터를 사용하여 자금 소유권을 증명하는 머클 증명을 생성하고 롤업에서 자산을 인출할 수 있습니다. + +- 사용자는 시퀀서 대신 L1에 트랜잭션을 제출할 수도 있으며, 이 경우 시퀀서는 유효한 블록을 계속 생성하기 위해 특정 시간 제한 내에 트랜잭션을 포함해야 합니다. + +### 정산 {#settlement} + +낙관적 롤업의 맥락에서 이더리움이 수행하는 또 다른 역할은 정산 레이어의 역할입니다. 정산 레이어는 전체 블록체인 생태계를 고정하고, 보안을 설정하며, 중재가 필요한 다른 체인(이 경우 낙관적 롤업)에서 분쟁이 발생할 경우 객관적인 최종성을 제공합니다. + +이더리움 메인넷은 낙관적 롤업이 사기 증명을 검증하고 분쟁을 해결할 수 있는 허브를 제공합니다. 또한 롤업에서 수행된 트랜잭션은 롤업 블록이 이더리움에서 수락된 _후에야_ 최종적으로 확정됩니다. 롤업 트랜잭션이 이더리움의 기본 레이어에 커밋되면 (체인 재구성과 같은 매우 드문 경우를 제외하고는) 롤백할 수 없습니다. + +## 낙관적 롤업은 어떻게 작동하나요? {#how-optimistic-rollups-work} + +### 트랜잭션 실행 및 집계 {#transaction-execution-and-aggregation} + +사용자는 낙관적 롤업에서 트랜잭션 처리를 담당하는 노드인 “운영자”에게 트랜잭션을 제출합니다. “검증자” 또는 “집계자”라고도 하는 운영자는 트랜잭션을 집계하고, 기본 데이터를 압축하며, 이더리움에 블록을 게시합니다. + +[지분 증명 시스템](/developers/docs/consensus-mechanisms/pos/)과 마찬가지로 누구나 검증자가 될 수 있지만, 낙관적 롤업 검증자는 블록을 생성하기 전에 본드를 제공해야 합니다. 검증자가 유효하지 않은 블록을 게시하거나 오래되었지만 유효하지 않은 블록을 기반으로 구축하는 경우(자신의 블록이 유효하더라도) 이 본드는 삭감될 수 있습니다. 이러한 방식으로 낙관적 롤업은 암호경제학적 인센티브를 활용하여 검증자가 정직하게 행동하도록 보장합니다. + +낙관적 롤업 체인의 다른 검증자들은 롤업 상태의 복사본을 사용하여 제출된 트랜잭션을 실행해야 합니다. 검증자의 최종 상태가 운영자가 제안한 상태와 다른 경우, 챌린지를 시작하고 사기 증명을 계산할 수 있습니다. + +일부 낙관적 롤업은 무허가형 검증자 시스템을 포기하고 단일 “시퀀서”를 사용하여 체인을 실행할 수 있습니다. 검증자와 마찬가지로 시퀀서는 트랜잭션을 처리하고, 롤업 블록을 생성하며, L1 체인(이더리움)에 롤업 트랜잭션을 제출합니다. + +시퀀서는 트랜잭션 순서에 대해 더 큰 통제권을 가지고 있기 때문에 일반 롤업 운영자와 다릅니다. 또한 시퀀서는 롤업 체인에 대한 우선 액세스 권한을 가지며 온체인 계약에 트랜잭션을 제출할 수 있는 유일한 주체입니다. 시퀀서가 아닌 노드나 일반 사용자의 트랜잭션은 시퀀서가 새 배치에 포함할 때까지 별도의 받은 편지함에 대기열로 간단히 저장됩니다. + +#### 이더리움에 롤업 블록 제출 {#submitting-blocks-to-ethereum} + +언급했듯이, 낙관적 롤업의 운영자는 오프체인 트랜잭션을 배치로 묶어 공증을 위해 이더리움으로 보냅니다. 이 과정에는 트랜잭션 관련 데이터를 압축하여 이더리움에 `calldata` 또는 블롭으로 게시하는 작업이 포함됩니다. + +`calldata`는 스마트 계약에서 수정할 수 없고 비영구적인 영역으로, 대부분 [메모리](/developers/docs/smart-contracts/anatomy/#memory)처럼 작동합니다. `calldata`는 블록체인의 [히스토리 로그](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html?highlight=memory#logs)의 일부로 온체인에 유지되지만, 이더리움 상태의 일부로 저장되지는 않습니다. `calldata`는 이더리움 상태의 어떤 부분도 건드리지 않기 때문에, 온체인에 데이터를 저장하는 데 상태보다 저렴합니다. + +`calldata` 키워드는 솔리디티에서 실행 시 스마트 계약 함수에 인수를 전달하는 데에도 사용됩니다. `calldata`는 트랜잭션 중에 호출되는 함수를 식별하고 임의의 바이트 시퀀스 형태로 함수에 대한 입력을 보유합니다. + +낙관적 롤업의 맥락에서 `calldata`는 압축된 트랜잭션 데이터를 온체인 계약으로 보내는 데 사용됩니다. 롤업 운영자는 롤업 계약에서 필요한 함수를 호출하고 압축된 데이터를 함수 인수로 전달하여 새 배치를 추가합니다. `calldata`를 사용하면 롤업이 발생하는 대부분의 비용이 온체인 데이터 저장에서 발생하므로 사용자 수수료가 절감됩니다. + +이 개념이 어떻게 작동하는지 보여주는 롤업 배치 제출의 [예시](https://eth.blockscout.com/tx/0x9102bfce17c58b5fc1c974c24b6bb7a924fb5fbd7c4cd2f675911c27422a5591)가 있습니다. 시퀀서는 `appendSequencerBatch()` 메서드를 호출하고 `calldata`를 사용하여 압축된 트랜잭션 데이터를 입력으로 전달했습니다. + +일부 롤업은 이제 블롭을 사용하여 이더리움에 트랜잭션 배치를 게시합니다. + +블롭은 (`calldata`와 마찬가지로) 수정할 수 없고 비영구적이지만 약 18일 후에 히스토리에서 제거됩니다. 블롭에 대한 자세한 내용은 [덴크샤딩](/roadmap/danksharding)을 참조하세요. + +### 상태 커밋먼트 {#state-commitments} + +어느 시점에서든 낙관적 롤업의 상태(계정, 잔액, 계약 코드 등) 는 "상태 트리"라고 불리는 [머클 트리](/whitepaper/#merkle-trees)로 구성됩니다. 롤업의 최신 상태를 참조하는 이 머클 트리의 루트(상태 루트)는 해시되어 롤업 계약에 저장됩니다. 체인에서의 모든 상태 전환은 새로운 롤업 상태를 생성하며, 운영자는 새로운 상태 루트를 계산하여 이를 커밋합니다. + +운영자는 배치를 게시할 때 이전 상태 루트와 새로운 상태 루트를 모두 제출해야 합니다. 이전 상태 루트가 온체인 계약의 기존 상태 루트와 일치하면, 후자는 폐기되고 새로운 상태 루트로 대체됩니다. + +롤업 운영자는 트랜잭션 배치 자체에 대한 머클 루트도 커밋해야 합니다. 이를 통해 누구나 [머클 증명](/developers/tutorials/merkle-proofs-for-offline-data-integrity/)을 제시하여 배치(L1에서)에 트랜잭션이 포함되었음을 증명할 수 있습니다. + +상태 커밋, 특히 상태 루트는 낙관적 롤업에서 상태 변경의 정확성을 증명하는 데 필요합니다. 롤업 계약은 운영자가 게시한 직후 새로운 상태 루트를 수락하지만, 나중에 유효하지 않은 상태 루트를 삭제하여 롤업을 올바른 상태로 복원할 수 있습니다. + +### 사기 증명 {#fraud-proving} + +설명했듯이, 낙관적 롤업은 누구나 유효성 증명을 제공하지 않고 블록을 게시할 수 있도록 합니다. 하지만 체인의 안전을 보장하기 위해, 낙관적 롤업은 누구나 상태 전환에 이의를 제기할 수 있는 시간 창을 지정합니다. 따라서 누구나 그 유효성에 이의를 제기할 수 있기 때문에 롤업 블록은 "어설션"이라고 불립니다. + +누군가 어설션에 이의를 제기하면, 롤업 프로토콜은 사기 증명 계산을 시작합니다. 모든 유형의 사기 증명은 상호작용적입니다. 즉, 다른 사람이 이의를 제기하기 전에 누군가가 어설션을 게시해야 합니다. 차이점은 사기 증명을 계산하는 데 필요한 상호작용 라운드의 수에 있습니다. + +단일 라운드 상호작용 증명 체계는 L1에서 분쟁이 발생한 트랜잭션을 재생하여 유효하지 않은 어설션을 감지합니다. 롤업 프로토콜은 검증자 계약을 사용하여 L1(이더리움)에서 분쟁이 발생한 트랜잭션의 재실행을 에뮬레이트하며, 계산된 상태 루트가 챌린지의 승자를 결정합니다. 롤업의 올바른 상태에 대한 챌린저의 주장이 맞으면, 운영자는 본드가 삭감되는 페널티를 받습니다. + +그러나 사기를 감지하기 위해 L1에서 트랜잭션을 재실행하려면 개별 트랜잭션에 대한 상태 커밋을 게시해야 하며, 롤업이 온체인에 게시해야 하는 데이터 양이 증가합니다. 트랜잭션을 재생하면 상당한 가스 비용도 발생합니다. 이러한 이유로, 낙관적 롤업은 다중 라운드 상호작용 증명으로 전환하고 있으며, 이는 동일한 목표(즉, 유효하지 않은 롤업 작업 감지)를 더 효율적으로 달성합니다. + +#### 다중 라운드 상호작용 증명 {#multi-round-interactive-proving} + +다중 라운드 상호작용 증명은 어설터와 챌린저 간의 상호 프로토콜을 포함하며, 이는 L1 검증자 계약에 의해 감독되고 궁극적으로 거짓말하는 당사자를 결정합니다. L2 노드가 어설션에 이의를 제기한 후, 어설터는 분쟁이 발생한 어설션을 두 개의 동일한 절반으로 나누어야 합니다. 이 경우 각 개별 어설션은 다른 어설션과 동일한 수의 연산 단계를 포함합니다. + +그러면 챌린저는 이의를 제기할 어설션을 선택합니다. 분할 과정("이분법 프로토콜"이라고 함)은 양 당사자가 실행의 _단일_ 단계에 대한 어설션에 대해 분쟁을 벌일 때까지 계속됩니다. 이 시점에서 L1 계약은 지침(및 그 결과)을 평가하여 분쟁을 해결하고 사기 당사자를 적발합니다. + +어설터는 분쟁이 발생한 단일 단계 연산의 유효성을 검증하는 “단일 단계 증명”을 제공해야 합니다. 어설터가 단일 단계 증명을 제공하지 못하거나 L1 검증자가 증명을 유효하지 않다고 판단하면 챌린지에서 패배합니다. + +이 유형의 사기 증명에 대한 몇 가지 참고 사항: + +1. 다중 라운드 상호작용 사기 증명은 분쟁 중재에서 L1 체인이 해야 할 작업을 최소화하기 때문에 효율적인 것으로 간주됩니다. 전체 트랜잭션을 재생하는 대신, L1 체인은 롤업 실행에서 한 단계만 다시 실행하면 됩니다. + +2. 이분법 프로토콜은 온체인에 게시되는 데이터의 양을 줄입니다(모든 트랜잭션에 대해 상태 커밋을 게시할 필요 없음). 또한, 낙관적 롤업 트랜잭션은 이더리움의 가스 한도에 의해 제한되지 않습니다. 반대로, 트랜잭션을 재실행하는 낙관적 롤업은 단일 이더리움 트랜잭션 내에서 실행을 에뮬레이트하기 위해 L2 트랜잭션의 가스 한도를 낮추어야 합니다. + +3. 악의적인 어설터의 본드 일부는 챌린저에게 수여되고, 나머지 일부는 소각됩니다. 소각은 검증자 간의 담합을 방지합니다. 만약 두 검증자가 담합하여 가짜 챌린지를 시작하면, 그들은 여전히 전체 스테이킹의 상당 부분을 잃게 됩니다. + +4. 다중 라운드 상호작용 증명은 양 당사자(어설터와 챌린저)가 지정된 시간 창 내에서 움직여야 합니다. 마감일 전에 조치를 취하지 않으면 불이행 당사자가 챌린지를 포기하게 됩니다. + +#### 낙관적 롤업에서 사기 증명이 중요한 이유 {#fraud-proof-benefits} + +사기 증명은 낙관적 롤업에서 무신뢰 최종성을 촉진하기 때문에 중요합니다. 무신뢰 최종성은 트랜잭션이 유효하기만 하다면 결국 확정될 것이라고 보장하는 낙관적 롤업의 품질입니다. + +악의적인 노드는 거짓 챌린지를 시작하여 유효한 롤업 블록의 확정을 지연시키려고 할 수 있습니다. 그러나 사기 증명은 결국 롤업 블록의 유효성을 증명하고 확정되도록 합니다. + +이는 또한 낙관적 롤업의 또 다른 보안 속성과 관련이 있습니다. 체인의 유효성은 _하나의_ 정직한 노드의 존재에 달려 있습니다. 정직한 노드는 유효한 어설션을 게시하거나 유효하지 않은 어설션에 이의를 제기함으로써 체인을 올바르게 진행시킬 수 있습니다. 어떤 경우든, 정직한 노드와 분쟁에 들어가는 악의적인 노드는 사기 증명 과정에서 자신의 스테이킹을 잃게 됩니다. + +### L1/L2 상호운용성 {#l1-l2-interoperability} + +낙관적 롤업은 이더리움 메인넷과의 상호운용성을 위해 설계되었으며, 사용자가 L1과 L2 간에 메시지와 임의의 데이터를 전달할 수 있도록 합니다. 또한 EVM과 호환되므로 기존 [탈중앙화앱](/developers/docs/dapps/)을 낙관적 롤업으로 포팅하거나 이더리움 개발 도구를 사용하여 새로운 탈중앙화앱을 만들 수 있습니다. + +#### 1. 자산 이동 {#asset-movement} + +##### 롤업 진입하기 + +낙관적 롤업을 사용하기 위해 사용자는 ETH, ERC-20 토큰 및 기타 허용된 자산을 L1의 롤업 [브리지](/developers/docs/bridges/) 계약에 예치합니다. 브리지 계약은 트랜잭션을 L2로 전달하며, 여기에서 동일한 양의 자산이 발행되어 낙관적 롤업에서 사용자가 선택한 주소로 전송됩니다. + +사용자가 생성한 트랜잭션(예: L1 > L2 예금)은 일반적으로 시퀀서가 롤업 계약에 다시 제출할 때까지 대기열에 들어갑니다. 그러나 검열 저항성을 유지하기 위해, 낙관적 롤업은 트랜잭션이 허용된 최대 시간을 초과하여 지연된 경우 사용자가 직접 온체인 롤업 계약에 트랜잭션을 제출할 수 있도록 허용합니다. + +일부 낙관적 롤업은 시퀀서가 사용자를 검열하는 것을 방지하기 위해 더 간단한 접근 방식을 채택합니다. 여기서 블록은 롤업 체인에서 처리된 트랜잭션 외에 이전 블록 이후 L1 계약에 제출된 모든 트랜잭션(예: 예금)으로 정의됩니다. 시퀀서가 L1 트랜잭션을 무시하면 (증명 가능하게) 잘못된 상태 루트를 게시하게 됩니다. 따라서 시퀀서는 L1에 게시된 사용자 생성 메시지를 지연시킬 수 없습니다. + +##### 롤업 나가기 + +낙관적 롤업에서 이더리움으로 인출하는 것은 사기 증명 체계 때문에 더 어렵습니다. 사용자가 L1에 에스크로된 자금을 인출하기 위해 L2 > L1 트랜잭션을 시작하는 경우, 약 7일 동안 지속되는 챌린지 기간이 끝날 때까지 기다려야 합니다. 그럼에도 불구하고 인출 과정 자체는 매우 간단합니다. + +L2 롤업에서 인출 요청이 시작되면 트랜잭션은 다음 배치에 포함되고, 롤업에 있는 사용자의 자산은 소각됩니다. 배치가 이더리움에 게시되면, 사용자는 블록에 자신의 출금 트랜잭션이 포함되었음을 확인하는 머클 증명을 계산할 수 있습니다. 그런 다음 지연 기간을 기다려 L1에서 트랜잭션을 최종 확정하고 메인넷으로 자금을 인출하기만 하면 됩니다. + +이더리움으로 자금을 인출하기 전에 일주일을 기다리는 것을 피하기 위해, 낙관적 롤업 사용자는 **유동성 공급자**(LP)를 이용할 수 있습니다. 유동성 공급자는 보류 중인 L2 인출의 소유권을 가정하고 L1에서 사용자에게 (수수료를 받고) 지불합니다. + +유동성 공급자는 자금을 지급하기 전에 사용자의 인출 요청의 유효성을 (직접 체인을 실행하여) 확인할 수 있습니다. 이런 식으로 그들은 트랜잭션이 결국 확정될 것이라는 보증(즉, 무신뢰 최종성)을 갖게 됩니다. + +#### 2. EVM 호환성 {#evm-compatibility} + +개발자에게 낙관적 롤업의 장점은 [이더리움 가상 머신(EVM)](/developers/docs/evm/)과의 호환성 또는 더 나아가 동등성입니다. EVM 호환 롤업은 [이더리움 옐로 페이퍼](https://ethereum.github.io/yellowpaper/paper.pdf)의 사양을 준수하며 바이트코드 수준에서 EVM을 지원합니다. + +낙관적 롤업의 EVM 호환성은 다음과 같은 이점을 가집니다. + +i. 개발자는 코드베이스를 광범위하게 수정할 필요 없이 이더리움의 기존 스마트 계약을 낙관적 롤업 체인으로 마이그레이션할 수 있습니다. 이를 통해 개발팀은 L2에 이더리움 스마트 계약을 배포할 때 시간을 절약할 수 있습니다. + +ii. 낙관적 롤업을 사용하는 개발자와 프로젝트 팀은 이더리움의 인프라를 활용할 수 있습니다. 여기에는 프로그래밍 언어, 코드 라이브러리, 테스트 도구, 클라이언트 소프트웨어, 배포 인프라 등이 포함됩니다. + +기존 도구를 사용하는 것은 이러한 도구들이 수년에 걸쳐 광범위하게 감사, 디버깅 및 개선되었기 때문에 중요합니다. 또한 이더리움 개발자가 완전히 새로운 개발 스택으로 구축하는 방법을 배울 필요가 없습니다. + +#### 3. 크로스체인 계약 호출 {#cross-chain-contract-calls} + +사용자(외부 소유 계정)는 롤업 계약에 트랜잭션을 제출하거나 시퀀서 또는 검증자가 대신 처리하도록 하여 L2 계약과 상호 작용합니다. 낙관적 롤업은 또한 이더리움의 계약 계정이 브리지 계약을 사용하여 L1과 L2 간에 메시지를 전달하고 데이터를 주고받음으로써 L2 계약과 상호 작용할 수 있도록 합니다. 이는 이더리움 메인넷의 L1 계약을 프로그래밍하여 L2 낙관적 롤업의 계약에 속한 함수를 호출할 수 있음을 의미합니다. + +크로스체인 계약 호출은 비동기적으로 발생합니다. 즉, 호출이 먼저 시작된 다음 나중에 실행됩니다. 이는 호출이 즉시 결과를 생성하는 이더리움의 두 계약 간 호출과는 다릅니다. + +크로스체인 계약 호출의 예로는 앞에서 설명한 토큰 예치가 있습니다. L1의 계약은 사용자의 토큰을 에스크로하고 페어링된 L2 계약에 메시지를 보내 롤업에서 동일한 양의 토큰을 발행합니다. + +크로스체인 메시지 호출은 계약 실행을 초래하므로, 발신자는 일반적으로 연산에 대한 [가스 비용](/developers/docs/gas/)을 부담해야 합니다. 대상 체인에서 트랜잭션이 실패하지 않도록 가스 한도를 높게 설정하는 것이 좋습니다. 토큰 브리징 시나리오가 좋은 예입니다. 트랜잭션의 L1 측(토큰 예치)은 작동하지만 L2 측(새 토큰 발행)이 낮은 가스로 인해 실패하면 예금은 복구할 수 없게 됩니다. + +마지막으로, 계약 간의 L2 > L1 메시지 호출은 지연을 고려해야 한다는 점에 유의해야 합니다(L1 > L2 호출은 일반적으로 몇 분 후에 실행됨). 이는 낙관적 롤업에서 메인넷으로 전송된 메시지는 챌린지 기간이 만료될 때까지 실행될 수 없기 때문입니다. + +## 낙관적 롤업 수수료는 어떻게 작동하나요? {#how-do-optimistic-rollup-fees-work} + +낙관적 롤업은 이더리움과 마찬가지로 가스 수수료 체계를 사용하여 사용자가 트랜잭션당 지불하는 금액을 나타냅니다. 낙관적 롤업에 부과되는 수수료는 다음 구성 요소에 따라 달라집니다. + +1. **상태 쓰기**: 낙관적 롤업은 트랜잭션 데이터와 블록 헤더(이전 블록 헤더 해시, 상태 루트, 배치 루트로 구성)를 이더리움에 `blob` 또는 "바이너리 대형 객체"로 게시합니다. [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844)는 온체인에 데이터를 포함하는 비용 효율적인 솔루션을 도입했습니다. `blob`은 롤업이 압축된 상태 전환 데이터를 이더리움 L1에 게시할 수 있도록 하는 새로운 트랜잭션 필드입니다. 영구적으로 온체인에 남아있는 `calldata`와 달리 블롭은 수명이 짧으며 [4096 에폭](https://github.com/ethereum/consensus-specs/blob/81f3ea8322aff6b9fb15132d050f8f98b16bdba4/configs/mainnet.yaml#L147)(약 18일) 후에 클라이언트에서 제거될 수 있습니다. 블롭을 사용하여 압축된 트랜잭션 배치를 게시함으로써 낙관적 롤업은 L1에 트랜잭션을 쓰는 비용을 크게 줄일 수 있습니다. + +2. **사용된 블롭 가스**: 블롭을 포함하는 트랜잭션은 [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)에 의해 도입된 것과 유사한 동적 수수료 메커니즘을 사용합니다. 유형 3 트랜잭션의 가스 수수료는 블롭에 대한 기본 수수료를 고려하며, 이는 블롭 공간 수요와 전송되는 트랜잭션의 블롭 공간 사용량에 따라 네트워크에 의해 결정됩니다. + +3. **L2 운영자 수수료**: 이는 이더리움의 가스 수수료와 마찬가지로 트랜잭션 처리에서 발생하는 연산 비용에 대한 보상으로 롤업 노드에 지불되는 금액입니다. L2는 처리 용량이 더 높고, 이더리움의 검증자가 더 높은 수수료의 트랜잭션을 우선적으로 처리하도록 강요하는 네트워크 혼잡에 직면하지 않기 때문에 롤업 노드는 더 낮은 거래 수수료를 부과합니다. + +낙관적 롤업은 트랜잭션 배치 및 `calldata` 압축을 포함한 여러 메커니즘을 적용하여 데이터 게시 비용을 줄이고 사용자의 수수료를 절감합니다. [L2 수수료 추적기](https://l2fees.info/)에서 이더리움 기반 낙관적 롤업 사용 비용에 대한 실시간 개요를 확인할 수 있습니다. + +## 낙관적 롤업은 어떻게 이더리움을 확장하나요? {#scaling-ethereum-with-optimistic-rollups} + +설명했듯이, 낙관적 롤업은 데이터 가용성을 보장하기 위해 압축된 트랜잭션 데이터를 이더리움에 게시합니다. 온체인에 게시된 데이터를 압축하는 능력은 낙관적 롤업으로 이더리움의 처리량을 확장하는 데 매우 중요합니다. + +메인 이더리움 체인은 블록이 보유할 수 있는 데이터의 양에 가스 단위로 제한을 둡니다([평균 블록 크기](/developers/docs/blocks/#block-size)는 1,500만 가스입니다). 이는 각 트랜잭션이 사용할 수 있는 가스의 양을 제한하지만, 트랜잭션 관련 데이터를 줄여 블록당 처리되는 트랜잭션을 늘릴 수 있다는 의미이기도 하며, 이는 확장성을 직접적으로 향상시킵니다. + +낙관적 롤업은 트랜잭션 데이터 압축을 달성하고 TPS 속도를 향상시키기 위해 여러 기술을 사용합니다. 예를 들어, 이 [기사](https://vitalik.eth.limo/general/2021/01/05/rollup.html)는 기본 사용자 트랜잭션(이더 전송)이 메인넷에서 생성하는 데이터와 동일한 트랜잭션이 롤업에서 생성하는 데이터의 양을 비교합니다. + +| 매개 변수 | 이더리움(L1) | 롤업(L2) | +| --------- | ---------------------------------------------------- | ------------------------------------ | +| Nonce | ~3 | 0 | +| 가스 가격 | ~8 | 0-0.5 | +| 가스 | 3 | 0-0.5 | +| 받는 주소 | 21 | 4 | +| 값 | 9 | ~3 | +| Signature | ~68 (2 + 33 + 33) | ~0.5 | +| 보내는 주소 | 0 (서명에서 복구) | 4 | +| **합계** | **\~112 바이트** | **\~12 바이트** | + +이 수치에 대한 대략적인 계산을 통해 낙관적 롤업이 제공하는 확장성 향상을 보여줄 수 있습니다. + +1. 모든 블록의 목표 크기는 1,500만 가스이며, 1바이트의 데이터를 검증하는 데 16가스가 소요됩니다. 평균 블록 크기를 16가스로 나누면(15,000,000/16), 평균 블록은 937,500바이트의 데이터를 담을 수 있음을 보여줍니다. +2. 기본 롤업 트랜잭션이 12바이트를 사용한다면, 평균 이더리움 블록은 **78,125개의 롤업 트랜잭션**(937,500/12) 또는 **39개의 롤업 배치**(각 배치가 평균 2,000개의 트랜잭션을 담는 경우)를 처리할 수 있습니다. +3. 이더리움에서 15초마다 새로운 블록이 생성된다면, 롤업의 처리 속도는 초당 약 5,208 트랜잭션에 달할 것입니다. 이는 이더리움 블록이 담을 수 있는 기본 롤업 트랜잭션 수(**78,125**)를 평균 블록 시간(**15초**)으로 나누어 계산합니다. + +낙관적 롤업 트랜잭션이 이더리움에서 전체 블록을 구성할 수는 없다는 점을 고려하면 이는 상당히 낙관적인 추정치입니다. 그러나 이는 낙관적 롤업이 이더리움 사용자에게 얼마나 많은 확장성 이득을 제공할 수 있는지에 대한 대략적인 아이디어를 제공할 수 있습니다(현재 구현은 최대 2,000 TPS를 제공함). + +[데이터 샤딩](/roadmap/danksharding/)이 이더리움에 도입되면 낙관적 롤업의 확장성이 향상될 것으로 예상됩니다. 롤업 트랜잭션은 다른 비롤업 트랜잭션과 블록 공간을 공유해야 하므로 처리 용량은 메인 이더리움 체인의 데이터 처리량에 의해 제한됩니다. 덴크샤딩은 비싸고 영구적인 `CALLDATA` 대신 저렴하고 비영구적인 "블롭" 저장소를 사용하여 L2 체인이 블록당 데이터를 게시하는 데 사용할 수 있는 공간을 늘릴 것입니다. + +### 낙관적 롤업의 장단점 {#optimistic-rollups-pros-and-cons} + +| 장점 | 단점 | +| -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | +| 보안이나 무신뢰성을 희생하지 않으면서 확장성을 크게 향상시킵니다. | 잠재적인 사기 챌린지로 인한 트랜잭션 최종성 지연. | +| 트랜잭션 데이터는 레이어 1 체인에 저장되어 투명성, 보안, 검열 저항성 및 탈중앙화를 향상시킵니다. | 중앙화된 롤업 운영자(시퀀서)가 트랜잭션 순서에 영향을 미칠 수 있습니다. | +| 사기 증명은 무신뢰 최종성을 보장하고 정직한 소수 그룹이 체인을 보호할 수 있도록 합니다. | 정직한 노드가 없는 경우 악의적인 운영자가 유효하지 않은 블록과 상태 커밋을 게시하여 자금을 훔칠 수 있습니다. | +| 사기 증명 계산은 특별한 하드웨어가 필요한 유효성 증명(ZK 롤업에서 사용)과 달리 일반 L2 노드에 개방되어 있습니다. | 보안 모델은 롤업 트랜잭션을 실행하고 유효하지 않은 상태 전환에 이의를 제기하기 위해 사기 증명을 제출하는 최소 한 개의 정직한 노드에 의존합니다. | +| 롤업은 "무신뢰 활성"("누구나 트랜잭션을 실행하고 어설션을 게시하여 체인을 강제로 진행시킬 수 있음)의 이점을 누립니다. | 사용자는 이더리움으로 자금을 인출하기 전에 일주일의 챌린지 기간이 만료될 때까지 기다려야 합니다. | +| 낙관적 롤업은 체인의 보안을 강화하기 위해 잘 설계된 암호경제학적 인센티브에 의존합니다. | 롤업은 모든 트랜잭션 데이터를 온체인에 게시해야 하므로 비용이 증가할 수 있습니다. | +| EVM 및 솔리디티와의 호환성을 통해 개발자는 이더리움 네이티브 스마트 계약을 롤업으로 포팅하거나 기존 도구를 사용하여 새로운 탈중앙화앱을 만들 수 있습니다. | | + +### 낙관적 롤업에 대한 시각적 설명 {#optimistic-video} + +시각 자료를 찾고 있나요? Finematics에서 옵티미스틱 롤업을 설명하는 것을 살펴보세요. + + + +## 낙관적 롤업에 대한 추가 자료 + +- [낙관적 롤업은 어떻게 작동하는가 (완벽 가이드)](https://www.alchemy.com/overviews/optimistic-rollups) +- [블록체인 롤업이란 무엇인가? 기술적 소개](https://www.ethereum-ecosystem.com/blog/what-is-a-blockchain-rollup-a-technical-introduction) +- [아비트럼 필수 가이드](https://www.bankless.com/the-essential-guide-to-arbitrum) +- [이더리움 롤업 실용 가이드](https://web.archive.org/web/20241108192208/https://research.2077.xyz/the-practical-guide-to-ethereum-rollups) +- [이더리움 L2의 사기 증명 현황](https://web.archive.org/web/20241124154627/https://research.2077.xyz/the-state-of-fraud-proofs-in-ethereum-l2s) +- [옵티미즘의 롤업은 실제로 어떻게 작동하는가?](https://www.paradigm.xyz/2021/01/how-does-optimism-s-rollup-really-work) +- [OVM 심층 분석](https://medium.com/ethereum-optimism/ovm-deep-dive-a300d1085f52) +- [낙관적 가상 머신이란 무엇인가?](https://www.alchemy.com/overviews/optimistic-virtual-machine) diff --git a/public/content/translations/ko/developers/docs/scaling/plasma/index.md b/public/content/translations/ko/developers/docs/scaling/plasma/index.md new file mode 100644 index 00000000000..d1ebbcae9d9 --- /dev/null +++ b/public/content/translations/ko/developers/docs/scaling/plasma/index.md @@ -0,0 +1,176 @@ +--- +title: "플라즈마 체인" +description: "현재 이더리움 커뮤니티에서 확장 솔루션으로 활용되고 있는 플라즈마 체인에 대한 소개입니다." +lang: ko +incomplete: true +sidebarDepth: 3 +--- + +플라즈마 체인은 이더리움 메인넷에 고정된 별도의 블록체인이지만, 자체적인 블록 검증 메커니즘을 통해 오프체인에서 트랜잭션을 실행합니다. 플라즈마 체인은 본질적으로 이더리움 메인넷의 작은 복사본인 "자식" 체인이라고도 불립니다. 플라즈마 체인은 [낙관적 롤업](/developers/docs/scaling/optimistic-rollups/)처럼 [사기 증명](/glossary/#fraud-proof)을 사용하여 분쟁을 중재합니다. + +머클 트리를 사용하면 이러한 체인을 무한히 쌓을 수 있으며, 이는 부모 체인(이더리움 메인넷 포함)의 대역폭 부담을 덜어줍니다. 그러나 이러한 체인은 이더리움으로부터 어느 정도의 보안성(사기 증명을 통해)을 얻지만, 여러 설계상의 한계로 인해 보안 및 효율성에 영향을 받습니다. + +## 필수 구성 요소 {#prerequisites} + +모든 기초 주제를 잘 이해하고 [이더리움 확장](/developers/docs/scaling/)에 대해 높은 수준으로 이해하고 있어야 합니다. + +## 플라즈마란 무엇인가요? + +플라즈마는 이더리움과 같은 퍼블릭 블록체인의 확장성을 개선하기 위한 프레임워크입니다. 오리지널 [플라즈마 백서](http://plasma.io/plasma.pdf)에 설명된 바와 같이, 플라즈마 체인은 다른 블록체인("루트 체인"이라고 함) 위에 구축됩니다. 각 "자식 체인"은 루트 체인에서 확장되며 일반적으로 부모 체인에 배포된 스마트 계약에 의해 관리됩니다. + +플라즈마 계약은 여러 기능 중에서도 사용자가 이더리움 메인넷과 플라즈마 체인 간에 자산을 이동할 수 있도록 하는 [브리지](/developers/docs/bridges/) 역할을 합니다. 이 점은 [사이드체인](/developers/docs/scaling/sidechains/)과 유사하지만, 플라즈마 체인은 적어도 어느 정도는 이더리움 메인넷의 보안성의 이점을 누립니다. 이는 자체 보안에 전적으로 책임이 있는 사이드체인과 다릅니다. + +## 플라즈마는 어떻게 작동하나요? + +플라즈마 프레임워크의 기본 구성 요소는 다음과 같습니다. + +### 오프체인 계산 {#offchain-computation} + +이더리움의 현재 처리 속도는 초당 약 15\~20개의 트랜잭션으로 제한되어 있어, 더 많은 사용자를 처리하기 위한 단기적인 확장 가능성을 줄입니다. 이 문제는 주로 이더리움의 [합의 메커니즘](/developers/docs/consensus-mechanisms/)이 블록체인 상태에 대한 모든 업데이트를 검증하기 위해 많은 P2P 노드를 요구하기 때문에 발생합니다. + +이더리움의 합의 메커니즘은 보안에 필수적이지만, 모든 사용 사례에 적용되는 것은 아닐 수 있습니다. 예를 들어, 앨리스가 밥에게 커피 한 잔 값을 매일 지불하는 경우, 양 당사자 간에 어느 정도 신뢰가 존재하므로 전체 이더리움 네트워크의 검증이 필요하지 않을 수 있습니다. + +플라즈마는 이더리움 메인넷이 모든 트랜잭션을 검증할 필요가 없다고 가정합니다. 대신, 메인넷 외부에서 트랜잭션을 처리하여 노드가 모든 트랜잭션을 검증해야 하는 부담을 덜 수 있습니다. + +플라즈마 체인은 속도와 비용을 최적화할 수 있으므로 오프체인 계산이 필요합니다. 예를 들어, 플라즈마 체인은 트랜잭션의 순서 지정 및 실행을 관리하기 위해 단일 "운영자"를 사용할 수 있으며, 대부분의 경우 실제로 그렇게 합니다. 단 하나의 개체만이 트랜잭션을 검증하므로, 플라즈마 체인의 처리 시간은 이더리움 메인넷보다 빠릅니다. + +### 상태 커밋먼트 {#state-commitments} + +플라즈마는 트랜잭션을 오프체인에서 실행하지만, 메인 이더리움 실행 레이어에서 정산됩니다. 그렇지 않으면 플라즈마 체인은 이더리움의 보안 보장을 받을 수 없습니다. 그러나 플라즈마 체인의 상태를 알지 못한 채 오프체인 트랜잭션을 확정하는 것은 보안 모델을 깨뜨리고 유효하지 않은 트랜잭션의 확산을 허용할 것입니다. 이것이 플라즈마 체인에서 블록을 생성하는 책임이 있는 개체인 운영자가 이더리움에 주기적으로 "상태 커밋먼트"를 게시해야 하는 이유입니다. + +[커밋먼트 스킴](https://en.wikipedia.org/wiki/Commitment_scheme)은 다른 당사자에게 가치나 진술을 공개하지 않고 이에 커밋하는 암호화 기술입니다. 커밋먼트는 한번 커밋하면 그 가치나 진술을 변경할 수 없다는 의미에서 "구속력"이 있습니다. 플라즈마의 상태 커밋먼트는 "머클 루트"([머클 트리](/whitepaper/#merkle-trees)에서 파생됨)의 형태를 취하며, 운영자는 이를 이더리움 체인의 플라즈마 계약에 주기적으로 보냅니다. + +머클 루트는 대량의 정보를 압축할 수 있게 해주는 암호화 기본 요소입니다. 머클 루트(이 경우 "블록 루트"라고도 함)는 블록 내의 모든 트랜잭션을 나타낼 수 있습니다. 머클 루트는 또한 작은 데이터 조각이 더 큰 데이터 세트의 일부임을 더 쉽게 검증할 수 있도록 합니다. 예를 들어, 사용자는 특정 블록에 트랜잭션이 포함되었음을 증명하기 위해 [머클 증명](/developers/tutorials/merkle-proofs-for-offline-data-integrity/#main-content)을 생성할 수 있습니다. + +머클 루트는 이더리움에 오프체인 상태에 대한 정보를 제공하는 데 중요합니다. 머클 루트를 "저장 지점"으로 생각할 수 있습니다. 운영자는 "이것은 x 시점의 플라즈마 체인 상태이며, 이것이 그 증거인 머클 루트입니다."라고 말하는 것과 같습니다. 운영자는 머클 루트를 사용하여 플라즈마 체인의 현재 상태에 커밋하며, 이것이 "상태 커밋먼트"라고 불리는 이유입니다. + +### 진입 및 탈출 {#entries-and-exits} + +이더리움 사용자가 플라즈마를 활용하려면 메인넷과 플라즈마 체인 간에 자금을 이동하는 메커니즘이 필요합니다. 그러나 플라즈마 체인의 주소로 이더를 임의로 보낼 수는 없습니다. 이들 체인은 호환되지 않으므로 트랜잭션이 실패하거나 자금 손실로 이어질 수 있습니다. + +플라즈마는 이더리움에서 실행되는 마스터 계약을 사용하여 사용자의 진입과 탈출을 처리합니다. 이 마스터 계약은 또한 상태 커밋먼트(앞서 설명)를 추적하고 사기 증명을 통해 부정직한 행위를 처벌하는 역할도 합니다(이에 대해서는 나중에 자세히 설명). + +#### 플라즈마 체인 진입하기 {#entering-the-plasma-chain} + +플라즈마 체인에 진입하려면 앨리스(사용자)는 플라즈마 계약에 ETH 또는 ERC-20 토큰을 예치해야 합니다. 계약 예치를 감시하는 플라즈마 운영자는 앨리스의 초기 예치금과 동일한 금액을 재생성하여 플라즈마 체인의 그녀의 주소로 지급합니다. 앨리스는 자식 체인에서 자금을 수령했음을 증명해야 하며, 그 후 이 자금을 트랜잭션에 사용할 수 있습니다. + +#### 플라즈마 체인 탈출하기 {#exiting-the-plasma-chain} + +플라즈마 체인을 탈출하는 것은 여러 가지 이유로 진입하는 것보다 더 복잡합니다. 가장 큰 이유는 이더리움이 플라즈마 체인의 상태에 대한 정보를 가지고 있지만, 그 정보가 사실인지 아닌지를 검증할 수 없다는 것입니다. 악의적인 사용자가 잘못된 주장("나는 1000 ETH를 가지고 있다")을 하고 주장을 뒷받침하기 위해 가짜 증거를 제공하여 빠져나갈 수 있습니다. + +악의적인 출금을 방지하기 위해 "챌린지 기간"이 도입됩니다. 챌린지 기간(보통 일주일) 동안 누구나 사기 증명을 사용하여 출금 요청에 이의를 제기할 수 있습니다. 챌린지가 성공하면 출금 요청은 거부됩니다. + +그러나 일반적으로 사용자는 정직하며 자신이 소유한 자금에 대해 올바른 주장을 합니다. 이 시나리오에서 앨리스는 플라즈마 계약에 트랜잭션을 제출하여 루트 체인(이더리움)에서 출금 요청을 시작합니다. + +그녀는 또한 플라즈마 체인에서 자신의 자금을 생성한 트랜잭션이 블록에 포함되었음을 검증하는 머클 증명을 제공해야 합니다. [미사용 트랜잭션 출력(UTXO)](https://en.wikipedia.org/wiki/Unspent_transaction_output) 모델을 사용하는 [플라즈마 MVP](https://www.learnplasma.org/en/learn/mvp.html)와 같은 플라즈마의 반복 버전에 필요합니다. + +[플라즈마 캐시](https://www.learnplasma.org/en/learn/cash.html)와 같은 다른 것들은 자금을 UTXO 대신 [대체 불가능한 토큰](/developers/docs/standards/tokens/erc-721/)으로 나타냅니다. 이 경우 출금하려면 플라즈마 체인의 토큰 소유권을 증명해야 합니다. 이는 토큰과 관련된 최근 두 개의 트랜잭션을 제출하고 해당 트랜잭션이 블록에 포함되었음을 검증하는 머클 증명을 제공함으로써 이루어집니다. + +사용자는 정직한 행동을 보장하기 위해 출금 요청에 증거금을 추가해야 합니다. 챌린저가 앨리스의 출금 요청이 유효하지 않음을 증명하면 그녀의 증거금은 슬래싱되고, 그 중 일부는 챌린저에게 보상으로 지급됩니다. + +챌린지 기간 동안 아무도 사기 증명을 제공하지 않으면 앨리스의 출금 요청은 유효한 것으로 간주되어 이더리움의 플라즈마 계약에서 예치금을 회수할 수 있게 됩니다. + +### 분쟁 중재 {#dispute-arbitration} + +모든 블록체인과 마찬가지로, 플라즈마 체인은 참여자가 악의적으로 행동할 경우(예: 자금 이중 사용) 트랜잭션의 무결성을 강제하는 메커니즘이 필요합니다. 이를 위해 플라즈마 체인은 사기 증명을 사용하여 상태 전환의 유효성에 관한 분쟁을 중재하고 나쁜 행동을 처벌합니다. 사기 증명은 플라즈마 자식 체인이 부모 체인이나 루트 체인에 불만을 제기하는 메커니즘으로 사용됩니다. + +사기 증명은 특정 상태 전환이 유효하지 않다는 주장일 뿐입니다. 한 예로 사용자(앨리스)가 동일한 자금을 두 번 사용하려고 하는 경우입니다. 아마도 그녀는 밥과의 트랜잭션에서 UTXO를 사용했고, 이제 밥의 소유가 된 동일한 UTXO를 다른 트랜잭션에서 사용하고 싶어할 수 있습니다. + +출금을 막기 위해 밥은 앨리스가 이전 트랜잭션에서 해당 UTXO를 사용했다는 증거와 해당 트랜잭션이 블록에 포함되었다는 머클 증명을 제공하여 사기 증명을 구성할 것입니다. 플라즈마 캐시에서도 동일한 과정이 작동합니다. 밥은 앨리스가 출금하려는 토큰을 이전에 전송했다는 증거를 제공해야 합니다. + +밥의 챌린지가 성공하면 앨리스의 출금 요청은 취소됩니다. 그러나 이 접근 방식은 밥이 체인에서 출금 요청을 감시할 수 있는 능력에 의존합니다. 만약 밥이 오프라인 상태라면, 앨리스는 챌린지 기간이 지나면 악의적인 출금을 처리할 수 있습니다. + +## 플라즈마의 대량 탈출 문제 {#the-mass-exit-problem-in-plasma} + +대량 탈출 문제는 많은 수의 사용자가 동시에 플라즈마 체인에서 출금하려고 할 때 발생합니다. 이 문제가 존재하는 이유는 플라즈마의 가장 큰 문제 중 하나인 데이터 비가용성과 관련이 있습니다. + +데이터 가용성이란 제안된 블록에 대한 정보가 실제로 블록체인 네트워크에 게시되었는지 검증할 수 있는 능력입니다. 생성자가 블록 자체는 게시하지만 블록을 생성하는 데 사용된 데이터를 보류하면 블록은 "사용 불가능" 상태가 됩니다. + +노드가 블록을 다운로드하고 트랜잭션의 유효성을 검증하려면 블록이 사용 가능해야 합니다. 블록체인은 블록 생성자가 모든 트랜잭션 데이터를 온체인에 게시하도록 강제하여 데이터 가용성을 보장합니다. + +데이터 가용성은 또한 이더리움의 베이스 레이어 위에 구축되는 오프체인 확장 프로토콜을 보호하는 데 도움이 됩니다. 이러한 체인의 운영자가 이더리움에 트랜잭션 데이터를 게시하도록 강제함으로써, 누구나 체인의 올바른 상태를 참조하는 사기 증명을 구성하여 유효하지 않은 블록에 이의를 제기할 수 있습니다. + +플라즈마 체인은 주로 운영자와 함께 트랜잭션 데이터를 저장하며 **메인넷에는 어떠한 데이터도 게시하지 않습니다**(즉, 주기적인 상태 커밋먼트 외에는). 이는 사용자가 유효하지 않은 트랜잭션에 이의를 제기하는 사기 증명을 생성해야 할 경우, 블록 데이터를 제공하기 위해 운영자에게 의존해야 함을 의미합니다. 이 시스템이 작동한다면, 사용자는 항상 사기 증명을 사용하여 자금을 보호할 수 있습니다. + +문제는 단순한 사용자가 아닌 운영자가 악의적으로 행동하는 당사자일 때 시작됩니다. 운영자는 블록체인을 단독으로 통제하기 때문에, 플라즈마 체인에 있는 사용자의 자금을 훔치는 것과 같이 더 큰 규모로 유효하지 않은 상태 전환을 진행할 동기가 더 큽니다. + +이 경우, 고전적인 사기 증명 시스템은 작동하지 않습니다. 운영자는 앨리스와 밥의 자금을 자신의 지갑으로 이체하는 유효하지 않은 트랜잭션을 쉽게 만들고, 사기 증명을 생성하는 데 필요한 데이터를 숨길 수 있습니다. 이는 운영자가 사용자나 메인넷에 데이터를 제공할 의무가 없기 때문에 가능합니다. + +따라서 가장 낙관적인 해결책은 플라즈마 체인에서 사용자의 "대량 탈출"을 시도하는 것입니다. 대량 탈출은 악의적인 운영자의 자금 탈취 계획을 늦추고 사용자에게 어느 정도의 보호를 제공합니다. 출금 요청은 각 UTXO(또는 토큰)가 생성된 시점을 기준으로 정렬되므로 악의적인 운영자가 정직한 사용자를 선행 매매하는 것을 방지합니다. + +그럼에도 불구하고, 기회주의적인 개인이 혼란을 틈타 유효하지 않은 탈출을 처리하여 이익을 취하는 것을 방지하기 위해 대량 탈출 중에 출금 요청의 유효성을 검증할 방법이 여전히 필요합니다. 해결책은 간단합니다. 사용자가 돈을 인출하기 위해 체인의 마지막 유효한 상태를 게시하도록 요구하는 것입니다. + +그러나 이 접근 방식에는 여전히 문제가 있습니다. 예를 들어, 플라즈마 체인의 모든 사용자가 탈출해야 하는 경우(악의적인 운영자의 경우 가능), 플라즈마 체인의 전체 유효한 상태가 한 번에 이더리움의 베이스 레이어에 덤프되어야 합니다. 플라즈마 체인의 임의의 크기(높은 처리량 = 더 많은 데이터)와 이더리움의 처리 속도에 대한 제약을 고려할 때, 이것은 이상적인 해결책이 아닙니다. + +탈출 게임은 이론적으로는 멋지게 들리지만, 실제 대량 탈출은 이더리움 자체에 네트워크 전체의 혼잡을 유발할 가능성이 높습니다. 이더리움의 기능을 해치는 것 외에도, 제대로 조정되지 않은 대량 탈출은 운영자가 플라즈마 체인의 모든 계정을 비우기 전에 사용자가 자금을 인출하지 못할 수 있음을 의미합니다. + +## 플라즈마의 장단점 {#pros-and-cons-of-plasma} + +| 장점 | 단점 | +| ----------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| 높은 처리량과 낮은 트랜잭션당 비용을 제공합니다. | 일반 계산을 지원하지 않습니다(스마트 계약을 실행할 수 없음). 기본적인 토큰 전송, 스왑 및 기타 몇 가지 트랜잭션 유형만 술어 논리를 통해 지원됩니다. | +| 임의의 사용자 간 트랜잭션에 적합합니다(두 사용자 모두 플라즈마 체인에 설정된 경우 사용자 쌍당 오버헤드 없음). | 자금의 보안을 보장하기 위해 주기적으로 네트워크를 감시하거나(활성 요구 사항) 이 책임을 다른 사람에게 위임해야 합니다. | +| 플라즈마 체인은 메인 체인과 관련 없는 특정 사용 사례에 맞게 조정될 수 있습니다. 기업을 포함한 누구나 플라즈마 스마트 계약을 맞춤화하여 다양한 컨텍스트에서 작동하는 확장 가능한 인프라를 제공할 수 있습니다. | 하나 이상의 운영자에 의존하여 데이터를 저장하고 요청 시 제공합니다. | +| 계산 및 저장소를 오프체인으로 이동하여 이더리움 메인넷의 부하를 줄입니다. | 챌린지를 허용하기 위해 출금이 며칠 지연됩니다. 대체 가능한 자산의 경우, 유동성 공급자에 의해 완화될 수 있지만, 관련 자본 비용이 발생합니다. | +| | 너무 많은 사용자가 동시에 탈출하려고 하면 이더리움 메인넷이 혼잡해질 수 있습니다. | + +## 플라즈마 대 레이어 2 확장 프로토콜 {#plasma-vs-layer-2} + +플라즈마는 한때 이더리움에 유용한 확장 솔루션으로 여겨졌지만, 그 이후 [레이어 2(L2) 확장 프로토콜](/layer-2/)을 위해 채택되지 않았습니다. L2 확장 솔루션은 플라즈마의 여러 문제를 해결합니다. + +### 효율성 {#efficiency} + +[영지식 롤업](/developers/docs/scaling/zk-rollups)은 오프체인에서 처리된 각 트랜잭션 배치의 유효성에 대한 암호화 증명을 생성합니다. 이는 사용자(및 운영자)가 유효하지 않은 상태 전환을 진행하는 것을 방지하여 챌린지 기간과 탈출 게임의 필요성을 없애줍니다. 이는 또한 사용자가 자금을 보호하기 위해 주기적으로 체인을 감시할 필요가 없다는 것을 의미합니다. + +### 스마트 계약 지원 {#support-for-smart-contracts} + +플라즈마 프레임워크의 또 다른 문제는 [이더리움 스마트 계약의 실행을 지원할 수 없다는 것](https://ethresear.ch/t/why-smart-contracts-are-not-feasible-on-plasma/2598/4)이었습니다. 결과적으로, 대부분의 플라즈마 구현은 주로 간단한 결제나 ERC-20 토큰 교환을 위해 구축되었습니다. + +반대로, 낙관적 롤업은 [이더리움 가상 머신](/developers/docs/evm/)과 호환되며 이더리움 네이티브 [스마트 계약](/developers/docs/smart-contracts/)을 실행할 수 있어 [탈중앙화 애플리케이션](/developers/docs/dapps/) 확장을 위한 유용하고 _안전한_ 솔루션이 됩니다. 마찬가지로, ZK-롤업이 임의의 로직을 처리하고 스마트 계약을 실행할 수 있도록 하는 [EVM의 영지식 구현(zkEVM)을 생성](https://ethresear.ch/t/a-zk-evm-specification/11549)하려는 계획이 진행 중입니다. + +### 데이터 비가용성 {#data-unavailability} + +앞서 설명했듯이, 플라즈마는 데이터 가용성 문제를 겪고 있습니다. 악의적인 운영자가 플라즈마 체인에서 유효하지 않은 전환을 진행하면, 운영자가 사기 증명을 생성하는 데 필요한 데이터를 보류할 수 있으므로 사용자는 이에 이의를 제기할 수 없습니다. 롤업은 운영자가 이더리움에 트랜잭션 데이터를 게시하도록 강제하여 누구나 체인의 상태를 검증하고 필요한 경우 사기 증명을 생성할 수 있도록 함으로써 이 문제를 해결합니다. + +### 대량 탈출 문제 {#mass-exit-problem} + +ZK-롤업과 낙관적 롤업은 모두 다양한 방식으로 플라즈마의 대량 탈출 문제를 해결합니다. 예를 들어, ZK-롤업은 어떤 시나리오에서도 운영자가 사용자 자금을 훔칠 수 없도록 보장하는 암호화 메커니즘에 의존합니다. + +마찬가지로, 낙관적 롤업은 출금에 지연 기간을 부과하여, 그 동안 누구나 챌린지를 시작하고 악의적인 출금 요청을 방지할 수 있습니다. 이것이 플라즈마와 유사하지만, 차이점은 검증자가 사기 증명을 생성하는 데 필요한 데이터에 접근할 수 있다는 것입니다. 따라서 롤업 사용자는 이더리움 메인넷으로의 광란적인 "먼저 탈출하기" 이주에 참여할 필요가 없습니다. + +## 플라즈마는 사이드체인 및 샤딩과 어떻게 다른가요? {#plasma-sidechains-sharding} + +플라즈마, 사이드체인, 샤딩은 모두 어떤 방식으로든 이더리움 메인넷에 연결되기 때문에 상당히 유사합니다. 그러나 이러한 연결의 수준과 강도는 다양하며, 이는 각 확장 솔루션의 보안 속성에 영향을 미칩니다. + +### 플라즈마 대 사이드체인 {#plasma-vs-sidechains} + +[사이드체인](/developers/docs/scaling/sidechains/)은 양방향 브리지를 통해 이더리움 메인넷에 연결된 독립적으로 운영되는 블록체인입니다. [브리지](/bridges/)는 사용자가 두 블록체인 간에 토큰을 교환하여 사이드체인에서 거래할 수 있도록 하여 이더리움 메인넷의 혼잡을 줄이고 확장성을 향상시킵니다. +사이드체인은 별도의 합의 메커니즘을 사용하며 일반적으로 이더리움 메인넷보다 훨씬 작습니다. 결과적으로, 이러한 체인으로 자산을 브리징하는 것은 더 큰 위험을 수반합니다. 사이드체인 모델에서는 이더리움 메인넷에서 상속된 보안 보장이 없기 때문에 사용자는 사이드체인 공격 시 자금 손실 위험을 감수해야 합니다. + +반대로, 플라즈마 체인은 메인넷으로부터 보안성을 얻습니다. 이는 사이드체인보다 측정 가능할 정도로 더 안전하게 만듭니다. 사이드체인과 플라즈마 체인 모두 다른 합의 프로토콜을 가질 수 있지만, 차이점은 플라즈마 체인이 각 블록에 대한 머클 루트를 이더리움 메인넷에 게시한다는 것입니다. 블록 루트는 플라즈마 체인에서 발생하는 트랜잭션에 대한 정보를 검증하는 데 사용할 수 있는 작은 정보 조각입니다. 플라즈마 체인에서 공격이 발생하면 사용자는 적절한 증명을 사용하여 메인넷으로 자금을 안전하게 인출할 수 있습니다. + +### 플라즈마 대 샤딩 {#plasma-vs-sharding} + +플라즈마 체인과 샤드 체인 모두 주기적으로 암호화 증명을 이더리움 메인넷에 게시합니다. 그러나 둘 다 다른 보안 속성을 가지고 있습니다. + +샤드 체인은 각 데이터 샤드에 대한 자세한 정보가 포함된 "콜레이션 헤더"를 메인넷에 커밋합니다. 메인넷의 노드는 데이터 샤드의 유효성을 검증하고 강제하여 유효하지 않은 샤드 전환 가능성을 줄이고 악의적인 활동으로부터 네트워크를 보호합니다. + +플라즈마는 메인넷이 자식 체인의 상태에 대한 최소한의 정보만 받기 때문에 다릅니다. 이는 메인넷이 자식 체인에서 수행된 트랜잭션을 효과적으로 검증할 수 없어 보안성이 떨어진다는 것을 의미합니다. + +**참고** 이더리움 블록체인 샤딩은 더 이상 로드맵에 없습니다. 이는 롤업을 통한 확장과 [댕크샤딩](/roadmap/danksharding)으로 대체되었습니다. + +### 플라즈마 사용하기 {#use-plasma} + +여러 프로젝트에서 여러분의 탈중앙화앱에 통합할 수 있는 플라즈마 구현을 제공합니다: + +- [Polygon](https://polygon.technology/) (이전 Matic Network) + +## 더 읽어보기 {#further-reading} + +- [플라즈마 알아보기](https://www.learnplasma.org/en/) +- ["공유 보안"의 의미와 그것이 왜 그렇게 중요한지에 대한 간단한 리마인더](https://old.reddit.com/r/ethereum/comments/sgd3zt/a_quick_reminder_of_what_shared_security_means/) +- [사이드체인 대 플라즈마 대 샤딩](https://vitalik.eth.limo/general/2019/06/12/plasma_vs_sharding.html) +- [플라즈마 이해하기, 1부: 기본](https://www.theblockcrypto.com/amp/post/10793/understanding-plasma-part-1-the-basics) +- [플라즈마의 삶과 죽음](https://medium.com/dragonfly-research/the-life-and-death-of-plasma-b72c6a59c5ad#) + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ diff --git a/public/content/translations/ko/developers/docs/scaling/sidechains/index.md b/public/content/translations/ko/developers/docs/scaling/sidechains/index.md new file mode 100644 index 00000000000..51eb6acfc49 --- /dev/null +++ b/public/content/translations/ko/developers/docs/scaling/sidechains/index.md @@ -0,0 +1,73 @@ +--- +title: "사이드체인" +description: "이더리움 커뮤니티에서 사용되는 확장 솔루션인 사이드체인에 대한 소개" +lang: ko +sidebarDepth: 3 +--- + +사이드체인은 이더리움과는 별도로 실행되는 블록체인이며 양방향 브리지를 통해 이더리움 메인넷과 연결되어 있습니다. 사이드체인에는 트랜잭션을 신속하게 처리할 수 있도록 설계된 별도의 블록 매개변수나 [합의 알고리즘](/developers/docs/consensus-mechanisms/)이 있기도 합니다. 그러나 사이드체인은 이더리움의 보안 속성을 상속하지 않으므로 사용 시 절충이 필요합니다. [레이어 2 확장 솔루션](/layer-2/)과 달리 사이드체인은 상태 변경 및 트랜잭션 데이터를 이더리움 메인넷에 다시 게시하지 않습니다. + +사이드체인은 또한 높은 처리량을 달성하기 위해 어느 정도의 탈중앙화나 보안을 희생합니다([확장성 트릴레마](https://vitalik.eth.limo/general/2021/05/23/scaling.html)). 그러나 이더리움은 탈중앙화와 보안을 저해하지 않으면서 확장하는 데 전념하고 있습니다. + +## 사이드체인은 어떻게 작동하나요? {#how-do-sidechains-work} + +사이드체인은 서로 다른 역사, 개발 로드맵 및 설계 고려사항을 가진 독립적인 블록체인입니다. 사이드체인은 이더리움과 표면적으로 몇 가지 유사점을 공유할 수 있지만, 몇 가지 독특한 특징을 가지고 있습니다. + +### 합의 알고리즘 {#consensus-algorithms} + +사이드체인을 고유하게(즉, 이더리움과 다르게) 만드는 특징 중 하나는 사용되는 합의 알고리즘입니다. 사이드체인은 합의를 위해 이더리움에 의존하지 않으며 필요에 맞는 대체 합의 프로토콜을 선택할 수 있습니다. 사이드체인에서 사용되는 합의 알고리즘의 몇 가지 예는 다음과 같습니다. + +- [권위 증명](/developers/docs/consensus-mechanisms/poa/) +- [위임 지분 증명(Delegated proof-of-stake)](https://en.bitcoin.it/wiki/Delegated_proof_of_stake) +- [비잔틴 장애 허용(Byzantine fault tolerance)](https://decrypt.co/resources/byzantine-fault-tolerance-what-is-it-explained). + +이더리움과 마찬가지로 사이드체인에는 트랜잭션을 확인 및 처리하고, 블록을 생성하며, 블록체인 상태를 저장하는 검증 노드가 있습니다. 검증자는 또한 네트워크 전반에 걸쳐 합의를 유지하고 악의적인 공격으로부터 네트워크를 보호할 책임이 있습니다. + +#### 블록 매개변수 {#block-parameters} + +이더리움은 [블록 시간](/developers/docs/blocks/#block-time)(즉, 새 블록을 생성하는 데 걸리는 시간) 및 [블록 크기](/developers/docs/blocks/#block-size)(즉, 가스로 표시되는 블록당 포함된 데이터의 양)에 제한을 둡니다. 반대로, 사이드체인은 높은 처리량, 빠른 트랜잭션, 낮은 수수료를 달성하기 위해 더 빠른 블록 시간 및 더 높은 가스 한도와 같은 다른 매개변수를 채택하는 경우가 많습니다. + +이것은 몇 가지 이점이 있지만 네트워크 탈중앙화 및 보안에 중대한 영향을 미칩니다. 빠른 블록 시간 및 큰 블록 크기와 같은 블록 매개변수는 전체 노드 실행의 난이도를 높여 소수의 "슈퍼노드"가 체인 보안을 책임지게 만듭니다. 이러한 시나리오에서는 검증자 담합 또는 악의적인 체인 탈취 가능성이 증가합니다. + +블록체인이 탈중앙화를 해치지 않으면서 확장하려면, 반드시 전문 하드웨어를 가진 당사자가 아니더라도 모든 사람이 노드를 실행할 수 있어야 합니다. 이것이 바로 모든 사람이 이더리움 네트워크에서 [전체 노드를 실행할 수 있도록](/developers/docs/nodes-and-clients/#why-should-i-run-an-ethereum-node) 하기 위한 노력이 진행 중인 이유입니다. + +### EVM 호환성 {#evm-compatibility} + +일부 사이드체인은 EVM과 호환되며 [이더리움 가상 머신(EVM)](/developers/docs/evm/)용으로 개발된 계약을 실행할 수 있습니다. EVM 호환 사이드체인은 [솔리디티(Solidity)로 작성된](/developers/docs/smart-contracts/languages/) 스마트 계약 및 기타 EVM 스마트 계약 언어를 지원합니다. 즉, 이더리움 메인넷용으로 작성된 스마트 계약은 EVM 호환 사이드체인에서도 작동합니다. + +즉, [디앱](/developers/docs/dapps/)을 사이드체인에서 사용하려면 해당 사이드체인에 [스마트 계약](/developers/docs/smart-contracts/)을 배포하기만 하면 됩니다. 솔리디티 언어로 계약을 작성하고, 사이드체인 RPC를 통해 체인과 상호작용하는 것은 이더리움 메인넷과 별로 다르지 않습니다. + +사이드체인은 EVM과 호환되기 때문에 이더리움 네이티브 디앱을 위한 유용한 [확장 솔루션](/developers/docs/scaling/)으로 간주됩니다. 사이드체인에 배포한 디앱 덕분에 사용자들은 저렴한 가스 비용과 보다 빠른 트랜잭션을 경험할 수 있으며, 메인넷이 혼잡한 경우 효과는 더 두드러지게 나타납니다. + +그러나 이전에 설명했듯이 사이드체인을 사용하는 데는 상당한 절충이 필요합니다. 각 사이드체인은 보안을 유지할 책임이 있으며 이더리움의 보안 속성을 따르지 않습니다. 이는 사용자에게 영향을 미치거나 자금을 위험에 빠뜨릴 수 있는 악의적인 행위의 가능성을 높입니다. + +### 자산 이동 {#asset-movement} + +별도의 블록체인이 이더리움 메인넷의 사이드체인이 되려면 이더리움 메인넷과의 자산 전송을 용이하게 하는 기능이 필요합니다. 이더리움과의 이러한 상호 운용성은 블록체인 브리지를 사용하여 달성됩니다. [브리지](/bridges/)는 이더리움 메인넷과 사이드체인에 배포된 스마트 계약을 사용하여 둘 사이의 자금 브리징을 제어합니다. + +브리지는 사용자가 이더리움과 사이드체인 간에 자금을 이동하는 데 도움이 되지만, 자산이 실제로 두 체인 간에 물리적으로 이동하는 것은 아닙니다. 대신, 일반적으로 민팅(minting) 및 소각(burning)과 관련된 메커니즘이 체인 간 가치 전송에 사용됩니다. [브리지 작동 방식](/developers/docs/bridges/#how-do-bridges-work)에 대해 자세히 알아보세요. + +## 사이드체인의 장단점 {#pros-and-cons-of-sidechains} + +| 장점 | 단점 | +| ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| 사이드체인을 뒷받침하는 기술은 잘 확립되어 있으며 광범위한 연구와 설계 개선의 이점을 누리고 있습니다. | 사이드체인은 확장성을 위해 어느 정도의 탈중앙화와 무신뢰성을 절충합니다. | +| 사이드체인은 일반적인 계산을 지원하고 EVM 호환성을 제공합니다(이더리움 네이티브 디앱을 실행할 수 있음). | 사이드체인은 별도의 합의 메커니즘을 사용하며 이더리움의 보안 보장의 이점을 얻지 못합니다. | +| 사이드체인은 다양한 합의 모델을 사용하여 트랜잭션을 효율적으로 처리하고 사용자의 거래 수수료를 낮춥니다. | 사이드체인은 더 높은 신뢰 가정을 요구합니다(예: 악의적인 사이드체인 검증자 정족수가 사기를 저지를 수 있음). | +| EVM 호환 사이드체인을 통해 디앱은 생태계를 확장할 수 있습니다. | | + +### 사이드체인 사용하기 {#use-sidechains} + +여러 프로젝트에서 디앱에 통합할 수 있는 사이드체인 구현을 제공합니다. + +- [Polygon PoS](https://polygon.technology/solutions/polygon-pos) +- [Skale](https://skale.network/) +- [Gnosis Chain(이전 xDai)](https://www.gnosischain.com/) +- [Loom Network](https://loomx.io/) +- [Metis Andromeda](https://www.metis.io/) + +## 더 읽어보기 {#further-reading} + +- [사이드체인을 통한 이더리움 디앱 확장](https://medium.com/loom-network/dappchains-scaling-ethereum-dapps-through-sidechains-f99e51fff447) _2018년 2월 8일 - Georgios Konstantopoulos_ + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ diff --git a/public/content/translations/ko/developers/docs/scaling/state-channels/index.md b/public/content/translations/ko/developers/docs/scaling/state-channels/index.md new file mode 100644 index 00000000000..da9e39db116 --- /dev/null +++ b/public/content/translations/ko/developers/docs/scaling/state-channels/index.md @@ -0,0 +1,261 @@ +--- +title: "상태 채널" +description: "현재 이더리움 커뮤니티에서 사용되는 확장 솔루션인 상태 채널 및 지불 채널에 대한 소개입니다." +lang: ko +sidebarDepth: 3 +--- + +상태 채널을 통해 참여자들은 이더리움 메인넷과의 상호작용을 최소화하면서 오프체인에서 안전하게 거래할 수 있습니다. 채널 피어는 채널을 열고 닫기 위해 온체인 트랜잭션을 두 번만 제출하면서 임의의 수의 오프체인 트랜잭션을 수행할 수 있습니다. 이를 통해 매우 높은 트랜잭션 처리량을 달성하고 사용자 비용을 절감할 수 있습니다. + +## 필수 구성 요소 {#prerequisites} + +[이더리움 확장](/developers/docs/scaling/) 및 [레이어 2](/layer-2/)에 대한 페이지를 읽고 이해해야 합니다. + +## 채널이란 무엇인가요? {#what-are-channels} + +이더리움과 같은 퍼블릭 블록체인은 분산된 아키텍처로 인해 확장성 문제에 직면합니다. 온체인 트랜잭션은 모든 노드에서 실행되어야 합니다. 노드는 네트워크의 탈중앙성을 유지하기 위해 평범한 하드웨어를 사용하여 블록의 트랜잭션 양을 처리할 수 있어야 하므로 트랜잭션 처리량에 제한이 있습니다. 블록체인 채널은 사용자가 최종 정산을 위해 메인 체인의 보안에 의존하면서 오프체인에서 상호작용할 수 있도록 함으로써 이 문제를 해결합니다. + +채널은 두 당사자가 서로 많은 트랜잭션을 수행한 다음 최종 결과만 블록체인에 게시할 수 있도록 하는 간단한 P2P 프로토콜입니다. 채널은 암호학을 사용하여 생성된 요약 데이터가 실제로 유효한 중간 트랜잭션 집합의 결과임을 증명합니다. ["다중서명"](/developers/docs/smart-contracts/#multisig) 스마트 계약은 트랜잭션이 올바른 당사자에 의해 서명되었는지 확인합니다. + +채널을 사용하면 관련 당사자가 상태 변경을 실행하고 검증하여 이더리움의 실행 레이어에서 계산을 최소화할 수 있습니다. 이는 이더리움의 혼잡을 줄이고 사용자의 트랜잭션 처리 속도를 높입니다. + +각 채널은 이더리움에서 실행되는 [다중서명 스마트 계약](/developers/docs/smart-contracts/#multisig)에 의해 관리됩니다. 채널을 열려면 참여자가 온체인에 채널 계약을 배포하고 자금을 예치해야 합니다. 양 당사자는 채널의 상태를 초기화하기 위해 상태 업데이트에 공동으로 서명한 후, 오프체인에서 빠르고 자유롭게 거래할 수 있습니다. + +채널을 닫으려면 참여자들은 마지막으로 합의된 채널 상태를 온체인에 제출해야 합니다. 이후 스마트 계약은 채널의 최종 상태에서 각 참여자의 잔액에 따라 잠긴 자금을 분배합니다. + +P2P 채널은 사전 정의된 일부 참여자가 눈에 띄는 오버헤드 없이 높은 빈도로 거래하고자 하는 상황에 특히 유용합니다. 블록체인 채널은 지불 채널상태 채널의 두 가지 범주로 나뉩니다. + +## 지불 채널 {#payment-channels} + +지불 채널은 두 명의 사용자가 공동으로 유지 관리하는 "양방향 원장"으로 가장 잘 설명할 수 있습니다. 원장의 초기 잔액은 채널 개설 단계에서 온체인 계약에 예치된 예금의 합계입니다. 지불 채널 전송은 초기에 한 번 온체인에서 생성하고 최종적으로 채널을 닫는 경우를 제외하고 실제 블록체인 자체의 개입 없이 즉시 수행될 수 있습니다. + +원장 잔액(즉, 지불 채널의 상태)에 대한 업데이트는 채널의 모든 당사자의 승인이 필요합니다. 모든 채널 참여자가 서명한 채널 업데이트는 이더리움의 트랜잭션과 마찬가지로 확정된 것으로 간주됩니다. + +지불 채널은 간단한 사용자 상호 작용(예: ETH 전송, 아토믹 스왑, 소액 결제)의 비용이 많이 드는 온체인 활동을 최소화하기 위해 설계된 최초의 확장 솔루션 중 하나였습니다. 채널 참여자는 전송의 순 합계가 예치된 토큰을 초과하지 않는 한 서로 간에 무제한의 즉각적이고 수수료 없는 트랜잭션을 수행할 수 있습니다. + +## 상태 채널 {#state-channels} + +오프체인 지불을 지원하는 것 외에 지불 채널은 일반적인 상태 전환 로직을 처리하는 데 유용하다는 것이 입증되지 않았습니다. 상태 채널은 이 문제를 해결하고 채널을 범용 계산 확장에 유용하게 만들기 위해 만들어졌습니다. + +상태 채널은 여전히 지불 채널과 많은 공통점을 가지고 있습니다. 예를 들어, 사용자는 암호화 서명된 메시지(트랜잭션)를 교환하여 상호 작용하며, 다른 채널 참여자도 이에 서명해야 합니다. 제안된 상태 업데이트가 모든 참여자에 의해 서명되지 않으면 유효하지 않은 것으로 간주됩니다. + +그러나 채널은 사용자의 잔액을 보유하는 것 외에도 계약 스토리지의 현재 상태(즉, 계약 변수 값)도 추적합니다. + +이를 통해 두 사용자 간에 오프체인으로 스마트 계약을 실행할 수 있습니다. 이 시나리오에서 스마트 계약의 내부 상태에 대한 업데이트는 채널을 만든 피어의 승인만 필요합니다. + +이는 앞에서 설명한 확장성 문제를 해결하지만 보안에 영향을 미칩니다. 이더리움에서 상태 전환의 유효성은 네트워크의 합의 프로토콜에 의해 시행됩니다. 이로 인해 스마트 계약의 상태에 대한 잘못된 업데이트를 제안하거나 스마트 계약 실행을 변경하는 것이 불가능합니다. + +상태 채널은 동일한 보안 보장을 제공하지 않습니다. 어느 정도 상태 채널은 메인넷의 축소판입니다. 제한된 수의 참여자가 규칙을 시행하므로 악의적인 행동(예: 유효하지 않은 상태 업데이트 제안)의 가능성이 증가합니다. 상태 채널은 [사기 증명](/glossary/#fraud-proof)에 기반한 분쟁 중재 시스템에서 보안을 얻습니다. + +## 상태 채널의 작동 방식 {#how-state-channels-work} + +기본적으로 상태 채널에서의 활동은 사용자와 블록체인 시스템이 관련된 상호 작용의 세션입니다. 사용자는 대부분 오프체인에서 서로 통신하며, 채널을 열거나 닫거나 참여자 간의 잠재적인 분쟁을 해결하기 위해서만 기본 블록체인과 상호 작용합니다. + +다음 섹션에서는 상태 채널의 기본 워크플로를 간략하게 설명합니다. + +### 채널 열기 {#opening-the-channel} + +채널을 열려면 참여자가 메인넷의 스마트 계약에 자금을 예치해야 합니다. 예치금은 가상 탭 역할도 하므로 참여 행위자는 즉시 결제를 정산할 필요 없이 자유롭게 거래할 수 있습니다. 채널이 온체인에서 확정되어야만 당사자들이 서로 정산하고 탭에 남은 금액을 인출할 수 있습니다. + +이 예치금은 각 참여자의 정직한 행동을 보장하는 보증금 역할도 합니다. 예금자가 분쟁 해결 단계에서 악의적인 행위를 한 것으로 밝혀지면 계약은 예금자의 예금을 삭감합니다. + +채널 피어는 모두가 동의하는 초기 상태에 서명해야 합니다. 이는 상태 채널의 제네시스 역할을 하며, 이후 사용자는 거래를 시작할 수 있습니다. + +### 채널 사용하기 {#using-the-channel} + +채널의 상태를 초기화한 후 피어는 트랜잭션에 서명하고 승인을 위해 서로에게 전송하여 상호 작용합니다. 참여자는 이러한 트랜잭션으로 상태 업데이트를 시작하고 다른 사람의 상태 업데이트에 서명합니다. 각 트랜잭션은 다음으로 구성됩니다. + +- 논스(nonce)는 트랜잭션의 고유 ID 역할을 하며 재전송 공격을 방지합니다. 또한 상태 업데이트가 발생한 순서를 식별합니다(분쟁 해결에 중요). + +- 채널의 이전 상태 + +- 채널의 새로운 상태 + +- 상태 전환을 유발하는 트랜잭션 (예: 앨리스가 밥에게 5 ETH를 보냄) + +채널의 상태 업데이트는 일반적으로 사용자가 메인넷에서 상호 작용할 때와 같이 온체인에서 브로드캐스트되지 않으며, 이는 온체인 공간을 최소화하려는 상태 채널의 목표와 일치합니다. 참여자들이 상태 업데이트에 동의하는 한, 이는 이더리움 트랜잭션만큼 최종적입니다. 참여자는 분쟁이 발생할 경우에만 메인넷의 합의에 의존하면 됩니다. + +### 채널 닫기 {#closing-the-channel} + +상태 채널을 닫으려면 채널의 최종 합의된 상태를 온체인 스마트 계약에 제출해야 합니다. 상태 업데이트에서 참조되는 세부 정보에는 각 참가자의 이동 횟수와 승인된 트랜잭션 목록이 포함됩니다. + +상태 업데이트가 유효한지(즉, 모든 당사자가 서명했는지) 확인한 후 스마트 계약은 채널을 확정하고 채널의 결과에 따라 잠긴 자금을 분배합니다. 오프체인에서 이루어진 지불은 이더리움의 상태에 적용되며 각 참여자는 잠긴 자금의 남은 부분을 받습니다. + +위에 설명된 시나리오는 성공적인 경우에 발생하는 상황을 나타냅니다. 때로는 사용자가 합의에 도달하지 못하고 채널을 확정하지 못할 수도 있습니다(실패한 경우). 다음 중 어느 하나라도 해당될 수 있습니다. + +- 참여자가 오프라인 상태가 되어 상태 전환을 제안하지 못합니다 + +- 참여자가 유효한 상태 업데이트에 공동 서명하기를 거부합니다 + +- 참여자가 온체인 계약에 오래된 상태 업데이트를 제안하여 채널을 확정하려고 시도합니다. + +- 참여자가 다른 사람이 서명하도록 유효하지 않은 상태 전환을 제안합니다. + +채널의 참여 행위자 간에 합의가 깨지면, 마지막 옵션은 메인넷의 합의에 의존하여 채널의 최종 유효 상태를 강제하는 것입니다. 이 경우 상태 채널을 닫으려면 온체인에서 분쟁을 해결해야 합니다. + +### 분쟁 해결 {#settling-disputes} + +일반적으로 채널의 당사자들은 사전에 채널을 닫는 데 동의하고 마지막 상태 전환에 공동 서명하여 스마트 계약에 제출합니다. 업데이트가 온체인에서 승인되면 오프체인 스마트 계약의 실행이 종료되고 참여자는 자신의 돈을 가지고 채널을 나옵니다. + +그러나 한쪽 당사자는 상대방의 승인을 기다리지 않고 스마트 계약의 실행을 종료하고 채널을 확정하기 위해 온체인 요청을 제출할 수 있습니다. 앞서 설명한 합의 파기 상황 중 하나라도 발생하면 어느 쪽이든 온체인 계약을 트리거하여 채널을 닫고 자금을 분배할 수 있습니다. 이것은 무신뢰성을 제공하여 정직한 당사자가 다른 당사자의 행동에 관계없이 언제든지 예치금을 인출할 수 있도록 보장합니다. + +채널 종료를 처리하려면 사용자는 애플리케이션의 마지막 유효한 상태 업데이트를 온체인 계약에 제출해야 합니다. 이것이 확인되면(즉, 모든 당사자의 서명이 있는 경우) 자금은 그들에게 유리하게 재분배됩니다. + +하지만 단일 사용자 종료 요청을 실행하는 데는 지연이 있습니다. 채널을 종료하라는 요청이 만장일치로 승인되면 온체인 종료 트랜잭션이 즉시 실행됩니다. + +사기 행위의 가능성으로 인해 단일 사용자 종료 시 지연이 발생합니다. 예를 들어, 채널 참여자는 오래된 상태 업데이트를 온체인에 제출하여 이더리움에서 채널을 확정하려고 시도할 수 있습니다. + +이에 대한 대응책으로, 상태 채널은 정직한 사용자가 채널의 최신 유효 상태를 온체인에 제출하여 유효하지 않은 상태 업데이트에 이의를 제기할 수 있도록 합니다. 상태 채널은 더 새롭고 합의된 상태 업데이트가 더 오래된 상태 업데이트를 무효화하도록 설계되었습니다. + +피어가 온체인 분쟁 해결 시스템을 트리거하면 상대방은 시간 제한(챌린지 기간이라고 함) 내에 응답해야 합니다. 이를 통해 사용자는 특히 상대방이 오래된 업데이트를 적용하는 경우 종료 트랜잭션에 이의를 제기할 수 있습니다. + +어떤 경우이든 채널 사용자는 항상 강력한 최종성 보장을 받습니다. 즉, 자신이 소유한 상태 전환이 모든 구성원에 의해 서명되었고 가장 최근의 업데이트인 경우 일반적인 온체인 트랜잭션과 동일한 최종성을 가집니다. 그들은 여전히 온체인에서 상대방에게 이의를 제기해야 하지만, 유일한 가능한 결과는 그들이 보유한 마지막 유효한 상태를 확정하는 것입니다. + +### 상태 채널은 이더리움과 어떻게 상호 작용하나요? {#how-do-state-channels-interact-with-ethereum} + +상태 채널은 오프체인 프로토콜로 존재하지만 온체인 구성 요소를 가지고 있습니다. 바로 채널을 열 때 이더리움에 배포되는 스마트 계약입니다. 이 계약은 채널에 예치된 자산을 제어하고, 상태 업데이트를 검증하며, 참여자 간의 분쟁을 중재합니다. + +상태 채널은 [레이어 2](/layer-2/) 확장 솔루션과 달리 트랜잭션 데이터나 상태 약정을 메인넷에 게시하지 않습니다. 그러나 [사이드체인](/developers/docs/scaling/sidechains/)보다 메인넷에 더 많이 연결되어 있어 어느 정도 더 안전합니다. + +상태 채널은 다음을 위해 메인 이더리움 프로토콜에 의존합니다. + +#### 1. 활성 {#liveness} + +채널을 열 때 배포된 온체인 계약은 채널의 기능을 담당합니다. 계약이 이더리움에서 실행 중이면 채널은 항상 사용 가능합니다. 반대로, 사이드체인은 메인넷이 작동하더라도 항상 실패할 수 있어 사용자 자금을 위험에 빠뜨릴 수 있습니다. + +#### 2. 보안 {#security} + +어느 정도 상태 채널은 보안을 제공하고 악의적인 피어로부터 사용자를 보호하기 위해 이더리움에 의존합니다. 이후 섹션에서 논의했듯이, 채널은 사용자가 유효하지 않거나 오래된 업데이트로 채널을 확정하려는 시도에 이의를 제기할 수 있도록 하는 사기 증명 메커니즘을 사용합니다. + +이 경우, 정직한 당사자는 채널의 최신 유효 상태를 사기 증명으로 온체인 계약에 제공하여 검증을 받습니다. 사기 증명을 통해 서로 신뢰하지 않는 당사자들이 자금을 위험에 빠뜨리지 않고 오프체인 트랜잭션을 수행할 수 있습니다. + +#### 3. 최종 승인 {#finality} + +채널 사용자가 공동으로 서명한 상태 업데이트는 온체인 트랜잭션과 동일하게 간주됩니다. 하지만, 모든 채널 내 활동은 채널이 이더리움에서 닫힐 때만 진정한 최종성을 달성합니다. + +낙관적인 경우, 양 당사자는 협력하여 최종 상태 업데이트에 서명하고 온체인에 제출하여 채널을 닫을 수 있으며, 그 후 채널의 최종 상태에 따라 자금이 분배됩니다. 비관적인 경우, 누군가 온체인에 잘못된 상태 업데이트를 게시하여 속이려고 할 때, 그들의 트랜잭션은 챌린지 기간이 경과할 때까지 확정되지 않습니다. + +## 가상 상태 채널 {#virtual-state-channels} + +상태 채널의 단순한 구현은 두 명의 사용자가 오프체인에서 애플리케이션을 실행하고자 할 때 새로운 계약을 배포하는 것입니다. 이는 실현 불가능할 뿐만 아니라 상태 채널의 비용 효율성을 떨어뜨립니다(온체인 트랜잭션 비용이 빠르게 증가할 수 있음). + +이 문제를 해결하기 위해 "가상 채널"이 만들어졌습니다. 열고 종료하기 위해 온체인 트랜잭션이 필요한 일반 채널과 달리, 가상 채널은 메인 체인과 상호 작용하지 않고도 열고, 실행하고, 확정할 수 있습니다. 이 방법을 사용하여 오프체인에서 분쟁을 해결하는 것도 가능합니다. + +이 시스템은 온체인에서 자금을 조달한 소위 "원장 채널"의 존재에 의존합니다. 두 당사자 간의 가상 채널은 기존 원장 채널 위에 구축될 수 있으며, 원장 채널의 소유자가 중개자 역할을 합니다. + +각 가상 채널의 사용자는 새로운 계약 인스턴스를 통해 상호 작용하며, 원장 채널은 여러 계약 인스턴스를 지원할 수 있습니다. 원장 채널의 상태에는 둘 이상의 계약 스토리지 상태도 포함되어 있어 여러 사용자 간에 오프체인에서 애플리케이션을 병렬로 실행할 수 있습니다. + +일반 채널과 마찬가지로 사용자는 상태 업데이트를 교환하여 상태 머신을 진행합니다. 분쟁이 발생하지 않는 한, 중개자는 채널을 열거나 종료할 때만 연락하면 됩니다. + +### 가상 지불 채널 {#virtual-payment-channels} + +가상 지불 채널은 가상 상태 채널과 동일한 아이디어로 작동합니다. 동일한 네트워크에 연결된 참여자는 온체인에서 새로운 채널을 열 필요 없이 메시지를 전달할 수 있습니다. 가상 지불 채널에서 가치 전송은 하나 이상의 중개자를 통해 라우팅되며, 의도된 수신자만 전송된 자금을 받을 수 있도록 보장됩니다. + +## 상태 채널의 애플리케이션 {#applications-of-state-channels} + +### 지불 {#payments} + +초기 블록체인 채널은 두 명의 참여자가 메인넷에서 높은 트랜잭션 수수료를 지불할 필요 없이 오프체인에서 신속하고 저렴한 수수료로 전송을 수행할 수 있도록 하는 간단한 프로토콜이었습니다. 오늘날에도 지불 채널은 이더와 토큰의 교환 및 예치를 위해 설계된 애플리케이션에 여전히 유용합니다. + +채널 기반 지불에는 다음과 같은 장점이 있습니다. + +1. **처리량**: 채널당 오프체인 트랜잭션의 양은 이더리움의 처리량과 관련이 없으며, 이더리움의 처리량은 블록 크기 및 블록 시간과 같은 다양한 요인의 영향을 받습니다. 오프체인에서 트랜잭션을 실행함으로써 블록체인 채널은 더 높은 처리량을 달성할 수 있습니다. + +2. **개인 정보 보호**: 채널은 오프체인에 존재하기 때문에 참여자 간의 상호 작용 세부 정보는 이더리움의 공개 블록체인에 기록되지 않습니다. 채널 사용자는 채널에 자금을 지원하고 닫거나 분쟁을 해결할 때만 온체인에서 상호 작용하면 됩니다. 따라서 채널은 더 사적인 거래를 원하는 개인에게 유용합니다. + +3. **지연 시간**: 채널 참여자 간에 수행되는 오프체인 트랜잭션은 양 당사자가 협력하면 즉시 정산되어 지연을 줄일 수 있습니다. 반면, 메인넷에서 트랜잭션을 보내려면 노드가 트랜잭션을 처리하고, 트랜잭션이 포함된 새 블록을 생성하고, 합의에 도달할 때까지 기다려야 합니다. 사용자는 또한 트랜잭션을 확정된 것으로 간주하기 전에 더 많은 블록 확인을 기다려야 할 수도 있습니다. + +4. **비용**: 상태 채널은 특정 참여자 그룹이 장기간에 걸쳐 많은 상태 업데이트를 교환하는 상황에 특히 유용합니다. 발생하는 유일한 비용은 상태 채널 스마트 계약을 열고 닫는 것입니다. 채널을 열고 닫는 사이의 모든 상태 변경은 정산 비용이 그에 따라 분배되므로 마지막보다 저렴해집니다. + +[롤업](/developers/docs/scaling/#rollups)과 같은 레이어 2 솔루션에 상태 채널을 구현하면 지불에 더욱 매력적으로 만들 수 있습니다. 채널은 저렴한 지불을 제공하지만, 개설 단계에서 메인넷에 온체인 계약을 설정하는 비용은 특히 가스 수수료가 급등할 때 비싸질 수 있습니다. 이더리움 기반 롤업은 [더 낮은 트랜잭션 수수료](https://l2fees.info/)를 제공하며 설정 수수료를 낮춰 채널 참여자의 오버헤드를 줄일 수 있습니다. + +### 소액 결제 {#microtransactions} + +소액 결제는 기업이 손실을 입지 않고는 처리할 수 없는 소액 지불(예: 1달러 미만)입니다. 이러한 법인은 지불 서비스 제공업체에 비용을 지불해야 하는데, 고객 지불에 대한 마진이 너무 낮아 이익을 낼 수 없다면 이를 수행할 수 없습니다. + +지불 채널은 소액 결제와 관련된 오버헤드를 줄여 이 문제를 해결합니다. 예를 들어, 인터넷 서비스 제공업체(ISP)는 고객과 지불 채널을 열어 서비스를 사용할 때마다 소액 결제를 스트리밍할 수 있습니다. + +채널을 열고 닫는 비용 외에 참여자는 소액 결제에 대한 추가 비용(가스 수수료 없음)을 부담하지 않습니다. 이는 고객이 서비스에 대해 지불하는 금액에 대해 더 많은 유연성을 갖게 되고 기업은 수익성 있는 소액 결제를 놓치지 않으므로 상호 이익이 되는 상황입니다. + +### 탈중앙화 애플리케이션 {#decentralized-applications} + +지불 채널과 마찬가지로 상태 채널은 상태 머신의 최종 상태에 따라 조건부 지불을 할 수 있습니다. 상태 채널은 임의의 상태 전환 로직도 지원할 수 있어 오프체인에서 일반 앱을 실행하는 데 유용합니다. + +상태 채널은 온체인 계약에 예치된 자금을 관리하기 쉽기 때문에 간단한 턴제 애플리케이션으로 제한되는 경우가 많습니다. 또한, 제한된 수의 당사자가 오프체인 애플리케이션의 상태를 간헐적으로 업데이트하므로 부정직한 행동을 처벌하는 것이 비교적 간단합니다. + +상태 채널 애플리케이션의 효율성은 디자인에 따라 달라집니다. 예를 들어, 개발자는 앱 채널 계약을 한 번 온체인에 배포하고 다른 플레이어가 온체인에 가지 않고도 앱을 재사용할 수 있도록 할 수 있습니다. 이 경우, 초기 앱 채널은 여러 가상 채널을 지원하는 원장 채널 역할을 하며, 각 가상 채널은 오프체인에서 앱의 스마트 계약의 새로운 인스턴스를 실행합니다. + +상태 채널 애플리케이션의 잠재적인 사용 사례는 게임 결과에 따라 자금이 분배되는 간단한 2인용 게임입니다. 여기서의 이점은 플레이어가 서로를 신뢰할 필요가 없고(무신뢰성), 플레이어가 아닌 온체인 계약이 자금 배분과 분쟁 해결을 제어한다는 것입니다(탈중앙화). + +상태 채널 앱의 다른 가능한 사용 사례로는 ENS 이름 소유권, NFT 원장 등이 있습니다. + +### 아토믹 전송 {#atomic-transfers} + +초기 지불 채널은 두 당사자 간의 전송으로 제한되어 사용성이 제한되었습니다. 그러나 가상 채널의 도입으로 개인은 온체인에서 새로운 채널을 열 필요 없이 중개자(즉, 여러 P2P 채널)를 통해 전송을 라우팅할 수 있게 되었습니다. + +"다중 홉 전송"이라고 흔히 설명되는 라우팅된 지불은 원자적입니다(즉, 트랜잭션의 모든 부분이 성공하거나 전체가 실패합니다). 아토믹 전송은 [해시 타임락 계약(HTLC)](https://en.bitcoin.it/wiki/Hash_Time_Locked_Contracts)을 사용하여 특정 조건이 충족되는 경우에만 지불이 해제되도록 하여 거래 상대방 위험을 줄입니다. + +## 상태 채널 사용의 단점 {#drawbacks-of-state-channels} + +### 활성 가정 {#liveness-assumptions} + +효율성을 보장하기 위해 상태 채널은 채널 참여자가 분쟁에 대응할 수 있는 능력에 시간 제한을 둡니다. 이 규칙은 피어가 항상 온라인 상태로 채널 활동을 모니터링하고 필요할 때 챌린지에 이의를 제기할 것이라고 가정합니다. + +실제로 사용자는 통제할 수 없는 이유(예: 열악한 인터넷 연결, 기계적 고장 등)로 오프라인 상태가 될 수 있습니다. 정직한 사용자가 오프라인 상태가 되면 악의적인 피어는 중재자 계약에 오래된 중간 상태를 제시하고 예치된 자금을 훔쳐 상황을 악용할 수 있습니다. + +일부 채널은 "감시탑"을 사용합니다. 이는 다른 사람을 대신하여 온체인 분쟁 이벤트를 감시하고 관련 당사자에게 알리는 것과 같은 필요한 조치를 취하는 주체입니다. 하지만 이는 상태 채널 사용 비용을 증가시킬 수 있습니다. + +### 데이터 비가용성 {#data-unavailability} + +앞서 설명했듯이, 유효하지 않은 분쟁에 이의를 제기하려면 상태 채널의 최신 유효 상태를 제시해야 합니다. 이것은 사용자가 채널의 최신 상태에 액세스할 수 있다는 가정에 기반한 또 다른 규칙입니다. + +채널 사용자가 오프체인 애플리케이션 상태의 사본을 저장할 것으로 기대하는 것은 합리적이지만, 이 데이터는 오류나 기계적 고장으로 인해 손실될 수 있습니다. 사용자가 데이터를 백업하지 않은 경우, 상대방이 소유하고 있는 오래된 상태 전환을 사용하여 유효하지 않은 종료 요청을 확정하지 않기를 바랄 뿐입니다. + +이더리움 사용자는 네트워크가 데이터 가용성에 대한 규칙을 시행하므로 이 문제를 처리할 필요가 없습니다. 트랜잭션 데이터는 모든 노드에 의해 저장 및 전파되며, 사용자가 필요할 때 다운로드할 수 있습니다. + +### 유동성 문제 {#liquidity-issues} + +블록체인 채널을 설정하려면 참여자는 채널의 수명 주기 동안 온체인 스마트 계약에 자금을 예치해야 합니다. 이는 채널 사용자의 유동성을 감소시키고, 메인넷에 자금을 예치할 여유가 있는 사람들로 채널을 제한합니다. + +하지만 오프체인 서비스 제공업체(OSP)가 운영하는 원장 채널은 사용자의 유동성 문제를 줄일 수 있습니다. 원장 채널에 연결된 두 피어는 가상 채널을 생성할 수 있으며, 원할 때 언제든지 오프체인에서 완전히 열고 확정할 수 있습니다. + +오프체인 서비스 제공업체는 여러 피어와 채널을 열어 지불 라우팅에 유용하게 만들 수도 있습니다. 물론 사용자는 OSP의 서비스에 대한 수수료를 지불해야 하며, 이는 일부에게는 바람직하지 않을 수 있습니다. + +### 그리핑 공격 {#griefing-attacks} + +그리핑 공격은 사기 증명 기반 시스템의 일반적인 특징입니다. 그리핑 공격은 공격자에게 직접적인 이익을 주지 않고 피해자에게 슬픔(즉, 해악)을 주기 때문에 붙여진 이름입니다. + +사기 증명은 정직한 당사자가 모든 분쟁(유효하지 않은 분쟁 포함)에 대응해야 하거나 자금을 잃을 위험이 있기 때문에 그리핑 공격에 취약합니다. 악의적인 참여자는 오래된 상태 전환을 온체인에 반복적으로 게시하여 정직한 당사자가 유효한 상태로 응답하도록 강요할 수 있습니다. 이러한 온체인 트랜잭션 비용은 빠르게 증가하여 정직한 당사자들이 그 과정에서 손해를 볼 수 있습니다. + +### 사전 정의된 참여자 집합 {#predefined-participant-sets} + +설계상 상태 채널을 구성하는 참여자 수는 수명 주기 동안 고정됩니다. 이는 참여자 집합을 업데이트하면 채널 자금 조달이나 분쟁 해결 시 채널 운영을 복잡하게 만들기 때문입니다. 참여자를 추가하거나 제거하려면 추가적인 온체인 활동이 필요하며, 이는 사용자에게 오버헤드를 증가시킵니다. + +이는 상태 채널을 더 쉽게 이해할 수 있게 하지만, 애플리케이션 개발자에게 채널 디자인의 유용성을 제한합니다. 이는 부분적으로 상태 채널이 롤업과 같은 다른 확장 솔루션을 위해 폐기된 이유를 설명합니다. + +### 병렬 트랜잭션 처리 {#parallel-transaction-processing} + +상태 채널의 참여자는 순서대로 상태 업데이트를 보내므로 "턴제 애플리케이션"(예: 2인용 체스 게임)에 가장 적합합니다. 이는 동시 상태 업데이트를 처리할 필요를 없애고 온체인 계약이 오래된 업데이트 게시자를 처벌하기 위해 해야 할 작업을 줄여줍니다. 그러나 이 디자인의 부작용은 트랜잭션이 서로 의존적이어서 지연 시간을 늘리고 전반적인 사용자 경험을 저하시킨다는 것입니다. + +일부 상태 채널은 오프체인 상태를 두 개의 단방향 "단순" 상태로 분리하는 "전이중" 설계를 사용하여 이 문제를 해결하며, 이를 통해 동시 상태 업데이트가 가능합니다. 이러한 설계는 오프체인 처리량을 향상시키고 트랜잭션 지연을 줄입니다. + +## 상태 채널 사용하기 {#use-state-channels} + +여러 프로젝트에서 탈중앙화앱에 통합할 수 있는 상태 채널 구현을 제공합니다: + +- [Connext](https://connext.network/) +- [Kchannels](https://www.kchannels.io/) +- [Perun](https://perun.network/) +- [Raiden](https://raiden.network/) +- [Statechannels.org](https://statechannels.org/) + +## 더 읽어보기 {#further-reading} + +**상태 채널** + +- [이더리움의 레이어 2 확장 솔루션 이해하기: 상태 채널, 플라즈마, 트루빗](https://medium.com/l4-media/making-sense-of-ethereums-layer-2-scaling-solutions-state-channels-plasma-and-truebit-22cb40dcc2f4) _– 조쉬 스타크, 2018년 2월 12일_ +- [상태 채널 - 설명](https://www.jeffcoleman.ca/state-channels/) _2015년 11월 6일 - 제프 콜먼_ +- [상태 채널의 기초](https://education.district0x.io/general-topics/understanding-ethereum/basics-state-channels/) _District0x_ +- [블록체인 상태 채널: 최신 기술](https://ieeexplore.ieee.org/document/9627997) + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ diff --git a/public/content/translations/ko/developers/docs/scaling/validium/index.md b/public/content/translations/ko/developers/docs/scaling/validium/index.md new file mode 100644 index 00000000000..fdc4374b1e7 --- /dev/null +++ b/public/content/translations/ko/developers/docs/scaling/validium/index.md @@ -0,0 +1,166 @@ +--- +title: Validium +description: "현재 이더리움 커뮤니티에서 활용되는 확장 솔루션인 Validium에 대한 소개입니다." +lang: ko +sidebarDepth: 3 +--- + +Validium은 [영지식 롤업](/developers/docs/scaling/zk-rollups/)과 같은 유효성 증명을 사용하여 트랜잭션의 무결성을 강화하지만 이더리움 메인넷에는 트랜잭션 데이터를 저장하지 않는 [확장 솔루션](/developers/docs/scaling/)입니다. 오프체인 데이터 가용성은 장단점이 있지만, 확장성을 크게 개선할 수 있습니다(Validium은 [초당 약 9,000개 이상의 트랜잭션을 처리](https://blog.matter-labs.io/zkrollup-vs-validium-starkex-5614e38bc263)할 수 있습니다). + +## 필수 구성 요소 {#prerequisites} + +[이더리움 확장](/developers/docs/scaling/) 및 [레이어 2](/layer-2)에 대한 페이지를 읽고 이해해야 합니다. + +## Validium이란 무엇인가요? {#what-is-validium} + +Validium은 이더리움 메인넷 외부에서 트랜잭션을 처리하여 처리량을 개선하도록 설계된 오프체인 데이터 가용성 및 연산을 사용하는 확장 솔루션입니다. 영지식 롤업(ZK-롤업)과 마찬가지로 Validium은 이더리움에서 오프체인 트랜잭션을 검증하기 위해 [영지식 증명](/glossary/#zk-proof)을 게시합니다. 이를 통해 유효하지 않은 상태 전환을 방지하고 validium 체인의 보안 보장을 강화합니다. + +이러한 "유효성 증명"은 ZK-SNARK(Zero-Knowledge Succinct Non-Interactive Argument of Knowledge) 또는 ZK-STARK(Zero-Knowledge Scalable Transparent ARgument of Knowledge)의 형태로 제공될 수 있습니다. [영지식 증명](https://consensys.net/blog/blockchain-explained/zero-knowledge-proofs-starks-vs-snarks/)에 대해 자세히 알아보기 + +Validium 사용자의 자금은 이더리움의 스마트 계약에 의해 제어됩니다. Validium은 ZK-롤업과 마찬가지로 거의 즉각적인 출금을 제공합니다. 메인넷에서 출금 요청에 대한 유효성 증명이 검증되면 사용자는 [머클 증명](/developers/tutorials/merkle-proofs-for-offline-data-integrity/)을 제공하여 자금을 출금할 수 있습니다. 머클 증명은 사용자의 출금 트랜잭션이 검증된 트랜잭션 배치에 포함되었음을 검증하여 온체인 계약이 출금을 처리할 수 있도록 합니다. + +하지만 validium 사용자는 자금이 동결되고 출금이 제한될 수 있습니다. 이 문제는 validium 체인의 데이터 가용성 관리자가 사용자에게 오프체인 상태 데이터를 제공하지 않는 경우 발생할 수 있습니다. 트랜잭션 데이터에 액세스할 수 없는 사용자는 자금 소유권을 증명하고 출금을 실행하는 데 필요한 머클 증명을 계산할 수 없습니다. + +이것이 데이터 가용성 스펙트럼에서의 위치라는 점에서 validium과 ZK-롤업의 주요 차이점입니다. 두 솔루션은 데이터 저장에 다르게 접근하며, 이는 보안과 무신뢰성에 영향을 미칩니다. + +## Validium은 이더리움과 어떻게 상호 작용하나요? {#how-do-validiums-interact-with-ethereum} + +Validium은 기존 이더리움 체인 위에 구축된 확장 프로토콜입니다. 오프체인에서 트랜잭션을 실행하지만, validium 체인은 다음을 포함하여 메인넷에 배포된 스마트 계약 모음에 의해 관리됩니다. + +1. **검증자 계약**: 검증자 계약은 validium 운영자가 상태를 업데이트할 때 제출한 증명의 유효성을 검증합니다. 여기에는 오프체인 트랜잭션의 정확성을 증명하는 유효성 증명과 오프체인 트랜잭션 데이터의 존재를 확인하는 데이터 가용성 증명이 포함됩니다. + +2. **메인 계약**: 메인 계약은 블록 생성자가 제출한 상태 커밋(머클 루트)을 저장하고 유효성 증명이 온체인에서 검증되면 validium의 상태를 업데이트합니다. 이 계약은 또한 validium 체인으로의 입금 및 출금을 처리합니다. + +Validium은 또한 다음을 위해 메인 이더리움 체인에 의존합니다. + +### 정산 {#settlement} + +Validium에서 실행된 트랜잭션은 상위 체인에서 유효성을 확인할 때까지 완전히 확인될 수 없습니다. Validium에서 수행되는 모든 비즈니스는 궁극적으로 메인넷에서 정산되어야 합니다. 이더리움 블록체인은 또한 validium 사용자에게 "정산 보장"을 제공합니다. 즉, 오프체인 트랜잭션은 온체인에 커밋되면 되돌리거나 변경할 수 없습니다. + +### 보안 {#security} + +정산 레이어 역할을 하는 이더리움은 validium의 상태 전환 유효성도 보장합니다. Validium 체인에서 실행되는 오프체인 트랜잭션은 기본 이더리움 레이어의 스마트 계약을 통해 검증됩니다. + +온체인 검증자 계약이 증명이 유효하지 않다고 판단하면 트랜잭션이 거부됩니다. 이는 운영자가 validium의 상태를 업데이트하기 전에 이더리움 프로토콜에 의해 시행되는 유효성 조건을 충족해야 함을 의미합니다. + +## Validium은 어떻게 작동하나요? {#how-does-validium-work} + +### 트랜잭션 {#transactions} + +사용자는 validium 체인에서 트랜잭션을 실행하는 노드인 운영자에게 트랜잭션을 제출합니다. 일부 validium은 단일 운영자를 사용하여 체인을 실행하거나 운영자 순환을 위해 [지분 증명(PoS)](/developers/docs/consensus-mechanisms/pos/) 메커니즘에 의존할 수 있습니다. + +운영자는 트랜잭션을 배치로 집계하여 증명을 위해 증명 회로로 보냅니다. 증명 회로는 트랜잭션 배치(및 기타 관련 데이터)를 입력으로 받아 작업이 올바르게 수행되었음을 확인하는 유효성 증명을 출력합니다. + +### 상태 커밋먼트 {#state-commitments} + +Validium의 상태는 머클 트리로 해시되며 루트는 이더리움의 메인 계약에 저장됩니다. 상태 루트라고도 하는 머클 루트는 validium의 현재 계정 및 잔액 상태에 대한 암호화 커밋 역할을 합니다. + +상태 업데이트를 수행하려면 운영자는 새로운 상태 루트(트랜잭션 실행 후)를 계산하여 온체인 계약에 제출해야 합니다. 유효성 증명이 확인되면 제안된 상태가 수락되고 validium은 새로운 상태 루트로 전환됩니다. + +### 입금 및 출금 {#deposits-and-withdrawals} + +사용자는 온체인 계약에 ETH(또는 모든 ERC 호환 토큰)를 예치하여 이더리움에서 validium으로 자금을 이동합니다. 계약은 입금 이벤트를 validium 오프체인으로 전달하며, 여기서 사용자의 주소에는 입금액과 동일한 금액이 입금됩니다. 운영자는 또한 이 입금 트랜잭션을 새로운 배치에 포함시킵니다. + +자금을 메인넷으로 다시 옮기려면 validium 사용자는 출금 트랜잭션을 시작하여 운영자에게 제출하고, 운영자는 출금 요청을 검증하고 배치에 포함합니다. validium 체인에 있는 사용자의 자산은 시스템을 나가기 전에 소멸됩니다. 배치와 관련된 유효성 증명이 검증되면 사용자는 메인 계약을 호출하여 초기 예치금의 잔액을 인출할 수 있습니다. + +검열 방지 메커니즘으로서 validium 프로토콜은 사용자가 운영자를 거치지 않고 validium 계약에서 직접 인출할 수 있도록 합니다. 이 경우 사용자는 계정이 상태 루트에 포함되어 있음을 보여주는 머클 증명을 검증자 계약에 제공해야 합니다. 증명이 수락되면 사용자는 메인 계약의 출금 기능을 호출하여 validium에서 자금을 인출할 수 있습니다. + +### 배치 제출 {#batch-submission} + +트랜잭션 배치를 실행한 후 운영자는 관련 유효성 증명을 검증자 계약에 제출하고 새로운 상태 루트를 메인 계약에 제안합니다. 증명이 유효하면 메인 계약은 validium의 상태를 업데이트하고 배치에 있는 트랜잭션의 결과를 최종화합니다. + +ZK-롤업과 달리 validium의 블록 생성자는 트랜잭션 배치에 대한 트랜잭션 데이터(블록 헤더만)를 게시할 필요가 없습니다. 이로 인해 validium은 블롭 데이터, `calldata` 또는 이 둘의 조합을 사용하여 메인 이더리움 체인에 상태 데이터를 게시하는 "하이브리드" 확장 프로토콜(예: [레이어 2](/layer-2/))과 달리 순수 오프체인 확장 프로토콜이 됩니다. + +### 데이터 가용성 {#data-availability} + +앞서 언급했듯이, validium은 운영자가 모든 트랜잭션 데이터를 이더리움 메인넷 외부(off)에 저장하는 오프체인 데이터 가용성 모델을 활용합니다. Validium의 낮은 온체인 데이터 사용량은 확장성을 향상시키고(처리량이 이더리움의 데이터 처리 용량에 의해 제한되지 않음) 사용자 수수료를 줄입니다(온체인에 데이터를 게시하는 비용이 더 낮음). + +그러나 오프체인 데이터 가용성은 머클 증명을 생성하거나 확인하는 데 필요한 데이터를 사용할 수 없는 문제를 야기합니다. 이는 운영자가 악의적으로 행동할 경우 사용자가 온체인 계약에서 자금을 인출하지 못할 수 있음을 의미합니다. + +다양한 validium 솔루션은 상태 데이터의 저장을 분산화하여 이 문제를 해결하려고 시도합니다. 여기에는 블록 생성자가 기본 데이터를 오프체인 데이터를 저장하고 요청 시 사용자에게 제공할 책임이 있는 "데이터 가용성 관리자"에게 보내도록 강제하는 것이 포함됩니다. + +Validium의 데이터 가용성 관리자는 모든 validium 배치에 서명함으로써 오프체인 트랜잭션 데이터의 가용성을 증명합니다. 이 서명은 온체인 검증자 계약이 상태 업데이트를 승인하기 전에 확인하는 "가용성 증명"의 한 형태를 구성합니다. + +Validium은 데이터 가용성 관리에 대한 접근 방식이 다릅니다. 일부는 신뢰할 수 있는 당사자에 의존하여 상태 데이터를 저장하는 반면, 다른 일부는 이 작업을 위해 무작위로 할당된 검증자를 사용합니다. + +#### 데이터 가용성 위원회(DAC) {#data-availability-committee} + +오프체인 데이터의 가용성을 보장하기 위해 일부 validium 솔루션은 데이터 가용성 위원회(DAC)로 알려진 신뢰할 수 있는 법인 그룹을 지정하여 상태 사본을 저장하고 데이터 가용성 증명을 제공합니다. DAC는 구성원 수가 적기 때문에 구현하기가 더 쉽고 조정이 덜 필요합니다. + +그러나 사용자는 필요할 때(예: 머클 증명 생성) 데이터를 사용할 수 있도록 DAC를 신뢰해야 합니다. 데이터 가용성 위원회의 구성원이 [악의적인 행위자에 의해 손상되어](https://notes.ethereum.org/DD7GyItYQ02d0ax_X-UbWg?view) 오프체인 데이터를 보류할 가능성이 있습니다. + +[validium의 데이터 가용성 위원회에 대해 더 알아보기](https://medium.com/starkware/data-availability-e5564c416424). + +#### 보증된 데이터 가용성 {#bonded-data-availability} + +다른 validium은 오프라인 데이터를 저장하는 참여자가 역할을 맡기 전에 스마트 계약에 토큰을 스테이킹(즉, 락업)하도록 요구합니다. 이 스테이크는 데이터 가용성 관리자 간의 정직한 행동을 보장하는 “보증” 역할을 하며 신뢰 가정을 줄입니다. 이 참가자들이 데이터 가용성을 증명하지 못하면 보증금은 삭감됩니다. + +보증된 데이터 가용성 체계에서는 필요한 스테이크를 제공하면 누구나 오프체인 데이터를 보유하도록 할당받을 수 있습니다. 이를 통해 자격을 갖춘 데이터 가용성 관리자 풀을 확장하여 데이터 가용성 위원회(DAC)에 영향을 미치는 중앙 집중화를 줄입니다. 더 중요한 것은 이 접근 방식이 악의적인 활동을 방지하기 위해 암호 경제적 인센티브에 의존한다는 것입니다. 이는 validium에서 오프라인 데이터를 보호하기 위해 신뢰할 수 있는 당사자를 지정하는 것보다 훨씬 더 안전합니다. + +[validium의 보증된 데이터 가용성에 대해 더 알아보기](https://blog.matter-labs.io/zkporter-a-breakthrough-in-l2-scaling-ed5e48842fbf). + +## Volition과 Validium {#volitions-and-validium} + +Validium은 많은 이점을 제공하지만 장단점(특히 데이터 가용성)이 있습니다. 하지만 많은 확장 솔루션과 마찬가지로 validium은 특정 사용 사례에 적합하며 이것이 volition이 만들어진 이유입니다. + +Volition은 ZK-롤업과 validium 체인을 결합하고 사용자가 두 확장 솔루션 간에 전환할 수 있도록 합니다. Volition을 통해 사용자는 특정 트랜잭션에 대해 validium의 오프체인 데이터 가용성을 활용하면서 필요한 경우 온체인 데이터 가용성 솔루션(ZK-롤업)으로 전환할 수 있는 자유를 유지할 수 있습니다. 이것은 본질적으로 사용자에게 고유한 상황에 따라 장단점을 선택할 수 있는 자유를 줍니다. + +탈중앙화 거래소(DEX)는 고가 거래에 대해 validium의 확장 가능하고 사적인 인프라를 사용하는 것을 선호할 수 있습니다. 또한 ZK-롤업의 더 높은 보안 보장과 무신뢰성을 원하는 사용자를 위해 ZK-롤업을 사용할 수도 있습니다. + +## Validium과 EVM 호환성 {#validiums-and-evm-compatibility} + +ZK-롤업과 마찬가지로 validium은 대부분 토큰 교환 및 결제와 같은 간단한 애플리케이션에 적합합니다. 영지식 증명 회로에서 [EVM](/developers/docs/evm/) 명령을 증명하는 데 상당한 오버헤드가 발생하기 때문에 validium 간의 일반 연산 및 스마트 계약 실행을 지원하는 것은 구현하기 어렵습니다. + +일부 validium 프로젝트는 EVM 호환 언어(예: Solidity, Vyper)를 효율적인 증명에 최적화된 사용자 지정 바이트코드를 생성하도록 컴파일하여 이 문제를 해결하려고 시도합니다. 이 접근 방식의 단점은 새로운 영지식 증명 친화적인 VM이 중요한 EVM 연산 부호를 지원하지 않을 수 있고, 개발자는 최적의 경험을 위해 고급 언어로 직접 작성해야 한다는 것입니다. 이는 개발자가 완전히 새로운 개발 스택으로 탈중앙화앱을 구축하도록 강제하고 현재 이더리움 인프라와의 호환성을 깨뜨리는 등 더 많은 문제를 야기합니다. + +그러나 일부 팀은 ZK 증명 회로에 대해 기존 EVM 연산 부호를 최적화하려고 시도하고 있습니다. 이것은 프로그램 실행의 정확성을 검증하기 위한 증명을 생성하는 EVM 호환 VM인 영지식 이더리움 가상 머신(zkEVM)의 개발로 이어질 것입니다. zkEVM을 사용하면 validium 체인은 스마트 계약을 오프체인에서 실행하고 이더리움에서 오프체인 계산을 검증하기 위해 유효성 증명을 제출할 수 있습니다(다시 실행할 필요 없이). + +[zkEVM에 대해 더 알아보기](https://www.alchemy.com/overviews/zkevm). + +## Validium은 이더리움을 어떻게 확장하나요? {#scaling-ethereum-with-validiums} + +### 1. 오프체인 데이터 저장 {#offchain-data-storage} + +낙관적 롤업 및 ZK-롤업과 같은 레이어 2 확장 프로젝트는 L1에 일부 트랜잭션 데이터를 게시하여 보안을 위해 순수 오프체인 확장 프로토콜(예: [플라즈마](/developers/docs/scaling/plasma/))의 무한한 확장성을 절충합니다. 그러나 이는 롤업의 확장성 속성이 이더리움 메인넷의 데이터 대역폭에 의해 제한됨을 의미합니다([데이터 샤딩](/roadmap/danksharding/)은 이러한 이유로 이더리움의 데이터 저장 용량을 개선할 것을 제안합니다). + +Validium은 모든 트랜잭션 데이터를 오프체인에 유지하고 상태 업데이트를 메인 이더리움 체인으로 중계할 때 상태 커밋(및 유효성 증명)만 게시하여 확장성을 달성합니다. 그러나 유효성 증명의 존재는 플라즈마 및 [사이드체인](/developers/docs/scaling/sidechains/)을 포함한 다른 순수 오프체인 확장 솔루션보다 validium에 더 높은 보안 보장을 제공합니다. Validium 설계는 이더리움이 오프체인 트랜잭션을 검증하기 전에 처리해야 하는 데이터 양을 줄임으로써 메인넷의 처리량을 크게 확장합니다. + +### 2. 재귀적 증명 {#recursive-proofs} + +재귀적 증명은 다른 증명의 유효성을 검증하는 유효성 증명입니다. 이러한 "증명의 증명"은 이전의 모든 증명을 검증하는 하나의 최종 증명이 생성될 때까지 여러 증명을 재귀적으로 집계하여 생성됩니다. 재귀적 증명은 유효성 증명당 검증할 수 있는 트랜잭션 수를 늘려 블록체인 처리 속도를 확장합니다. + +일반적으로 validium 운영자가 검증을 위해 이더리움에 제출하는 각 유효성 증명은 단일 블록의 무결성을 검증합니다. 반면 단일 재귀적 증명은 여러 validium 블록의 유효성을 동시에 확인하는 데 사용할 수 있습니다. 이는 증명 회로가 여러 블록 증명을 하나의 최종 증명으로 재귀적으로 집계할 수 있기 때문에 가능합니다. 온체인 검증자 계약이 재귀적 증명을 수락하면 모든 기본 블록이 즉시 최종화됩니다. + +## Validium의 장단점 {#pros-and-cons-of-validium} + +| 장점 | 단점 | +| ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| 유효성 증명은 오프체인 트랜잭션의 무결성을 강화하고 운영자가 유효하지 않은 상태 업데이트를 마무리하는 것을 방지합니다. | 유효성 증명을 생성하려면 특수 하드웨어가 필요하며 이는 중앙 집중화 위험을 야기합니다. | +| 사용자의 자본 효율성 증가(이더리움으로 자금을 다시 인출하는 데 지연 없음) | 일반 연산/스마트 계약에 대한 지원이 제한적이며, 개발에 특화된 언어가 필요합니다. | +| 고가치 애플리케이션에서 사기 증명 기반 시스템이 직면하는 특정 경제적 공격에 취약하지 않습니다. | ZK 증명을 생성하는 데 높은 연산 능력이 필요하며, 처리량이 낮은 애플리케이션에는 비용 효율적이지 않습니다. | +| 이더리움 메인넷에 calldata를 게시하지 않음으로써 사용자의 가스 수수료를 줄입니다. | 주관적인 완결 시간은 더 느리지만(ZK 증명을 생성하는 데 10\~30분 소요), 분쟁 시간 지연이 없기 때문에 완전한 완결까지는 더 빠릅니다. | +| 거래 프라이버시와 확장성을 우선시하는 거래 또는 블록체인 게임과 같은 특정 사용 사례에 적합합니다. | 소유권의 머클 증명을 생성하려면 오프체인 데이터를 항상 사용할 수 있어야 하므로 사용자가 자금을 인출하지 못할 수 있습니다. | +| 오프체인 데이터 가용성은 더 높은 수준의 처리량을 제공하고 확장성을 높입니다. | 보안 모델은 순전히 암호화 보안 메커니즘에 의존하는 ZK-롤업과 달리 신뢰 가정 및 암호 경제적 인센티브에 의존합니다. | + +### Validium/Volition 사용 {#use-validium-and-volitions} + +여러 프로젝트에서 탈중앙화앱에 통합할 수 있는 Validium 및 volition 구현을 제공합니다. + +**StarkWare StarkEx** - _StarkEx는 유효성 증명을 기반으로 하는 이더리움 레이어 2(L2) 확장 솔루션입니다. ZK-롤업 또는 Validium 데이터 가용성 모드에서 작동할 수 있습니다._ + +- [문서](https://docs.starkware.co/starkex-v4/starkex-deep-dive/data-availability-modes#validium) +- [웹사이트](https://starkware.co/starkex/) + +**Matter Labs zkPorter**- _zkPorter는 zkRollup과 샤딩의 아이디어를 결합한 하이브리드 접근 방식으로 데이터 가용성을 해결하는 레이어 2 확장 프로토콜입니다. 각각 자체 데이터 가용성 정책을 가진 임의의 수의 샤드를 지원할 수 있습니다._ + +- [블로그](https://blog.matter-labs.io/zkporter-a-breakthrough-in-l2-scaling-ed5e48842fbf) +- [문서](https://docs.zksync.io/zksync-protocol/rollup/data-availability) +- [웹사이트](https://zksync.io/) + +## 더 읽어보기 {#further-reading} + +- [Validium과 레이어 2 2x2 매트릭스 — 99호](https://www.buildblockchain.tech/newsletter/issues/no-99-validium-and-the-layer-2-two-by-two) +- [ZK-롤업 vs Validium](https://blog.matter-labs.io/zkrollup-vs-validium-starkex-5614e38bc263) +- [Volition과 새로운 데이터 가용성 스펙트럼](https://medium.com/starkware/volition-and-the-emerging-data-availability-spectrum-87e8bfa09bb) +- [롤업, Validium 및 Volition: 가장 인기 있는 이더리움 확장 솔루션에 대해 알아보기](https://www.defipulse.com/blog/rollups-validiums-and-volitions-learn-about-the-hottest-ethereum-scaling-solutions) +- [이더리움 롤업에 대한 실용 가이드](https://web.archive.org/web/20241108192208/https://research.2077.xyz/the-practical-guide-to-ethereum-rollups) diff --git a/public/content/translations/ko/developers/docs/scaling/zk-rollups/index.md b/public/content/translations/ko/developers/docs/scaling/zk-rollups/index.md new file mode 100644 index 00000000000..43ea628d3c3 --- /dev/null +++ b/public/content/translations/ko/developers/docs/scaling/zk-rollups/index.md @@ -0,0 +1,257 @@ +--- +title: "영지식 롤업" +description: "영지식 롤업 소개 - 이더리움 커뮤니티에서 사용하는 확장성 솔루션" +lang: ko +--- + +영지식 롤업(ZK-롤업)은 연산과 상태 저장을 오프체인으로 이동시켜 이더리움 메인넷에서 처리량을 높이는 레이어 2 [확장 솔루션](/developers/docs/scaling/)입니다. 영지식 롤업은 수천 개의 트랜잭션을 일괄적으로 처리한 다음 최소한의 요약 데이터만 메인넷에 올린다. 요약 데이터는 이더리움 상태에 적용해야하는 변경 사항과 변경 사항이 옳다는 암호학적 증거를 정의합니다. + +## 필수 구성 요소 {#prerequisites} + +[이더리움 확장](/developers/docs/scaling/) 및 [레이어 2](/layer-2)에 대한 페이지를 읽고 이해해야 합니다. + +## 영지식 롤업이란? {#what-are-zk-rollups} + +영지식 롤업(ZK-롤업)은 오프체인에서 실행되는 배치로 트랜잭션을 묶습니다(또는 '롤업'합니다). 오프체인 연산은 블록체인에 게시해야 하는 데이터의 양을 줄입니다. 영지식 롤업 운영자(operator)는 각 트랜잭션을 개별적으로 보내는 대신 모든 트랜잭션 묶음을 나타내는 데 필요한 변경사항의 요약을 제출합니다. 또한 변경 사항의 정확성을 증명하기 위해 [유효성 증명](/glossary/#validity-proof)을 생성합니다. + +영지식 롤업의 상태는 이더리움 네트워크에 배포된 스마트 컨트랙트에 의해 유지됩니다. 이 상태를 업데이트 하기 위해서는 영지식 롤업 노드가 검증을 위한 유효성 증명을 제출해야합니다. 언급했듯이, 유효성 증명은 롤업에 의해 제안된 상태 변화가 주어진 트랜잭션 묶음을 실제로 실행한 결과라는 암호화된 보증입니다. 이는 ZK-롤업이 [낙관적 롤업](/developers/docs/scaling/optimistic-rollups/)처럼 모든 트랜잭션 데이터를 온체인에 게시하는 대신, 이더리움에서 트랜잭션을 확정하기 위해 유효성 증명만 제공하면 된다는 것을 의미합니다. + +영지식 롤업 계약이 유효성 증명을 확인하면 출금 트랜잭션(exit transaction)이 실행되기때문에 이더리움으로 자금을 이동시킬 때 지연이 없습니다. 반대로, 낙관적 롤업에서 자금을 인출하는 경우 누구나 [사기 증명](/glossary/#fraud-proof)으로 출금 트랜잭션에 이의를 제기할 수 있도록 지연이 발생합니다. + +ZK-롤업은 트랜잭션을 `calldata`로 이더리움에 기록합니다. `calldata`는 스마트 계약 함수에 대한 외부 호출에 포함된 데이터가 저장되는 위치입니다. `calldata`의 정보는 블록체인에 게시되므로 누구나 독립적으로 롤업의 상태를 재구성할 수 있습니다. 영지식 롤업은 압축기술을 사용하여 트랜잭션 데이터를 줄입니다. 예를들어, 계정은 주소가 아닌 인덱스로 표시되어 28바이트의 데이터로 저장합니다. 온체인 데이터 게시는 롤업에 상당한 비용이 들기 때문에, 데이터 압축을 통해 사용자 수수료를 줄일 수 있습니다. + +## 영지식 롤업은 이더리움과 어떻게 상호 작용하나요? {#zk-rollups-and-ethereum} + +ZK-롤업 체인은 이더리움 블록체인 위에서 작동하는 오프체인 프로토콜이며 온체인 이더리움 스마트 계약에 의해 관리됩니다. ZK-롤업은 메인넷 외부에서 트랜잭션을 실행하지만, 주기적으로 오프체인 트랜잭션 배치를 온체인 롤업 계약에 커밋합니다. 이 거래 기록은 이더리움 블록체인과 마찬가지로 불변이며, 영지식 롤업 체인을 형성합니다. + +영지식 롤업의 핵심 아키텍처 구성은 다음과 같습니다. + +1. **온체인 계약**: 앞서 언급했듯이, ZK-롤업 프로토콜은 이더리움에서 실행되는 스마트 계약에 의해 제어됩니다. 여기에는 롤업 블록을 저장하고 예금을 추적하며 상태 업데이트를 모니터링하는 메인 스마트 컨트랙트가 포함됩니다. 또 다른 온체인 계약(검증자 계약)은 블록 생산자가 제출한 영지식 증명을 검증합니다. 따라서 이더리움은 영지식 롤업의 기본 계층 또는 "레이어 1" 역할을 합니다. + +2. **오프체인 가상 머신(VM)**: ZK-롤업 프로토콜은 이더리움에 있지만, 트랜잭션 실행 및 상태 저장은 [EVM](/developers/docs/evm/)과 독립적인 별도의 가상 머신에서 이루어집니다. 이 오프체인 VM은 ZK-롤업에서 트랜잭션을 실행하기 위한 환경이며 ZK-롤업 프로토콜의 보조 레이어 또는 "레이어 2" 역할을 합니다. 이더리움 메인넷에서 검증된 유효성 증명은 오프체인 VM의 상태 전환에 대한 정확성을 보장합니다. + +ZK-롤업은 "하이브리드 확장 솔루션"으로, 독립적으로 작동하지만 이더리움으로부터 보안을 파생하는 오프체인 프로토콜입니다. 특히 이더리움 네트워크는 영지식 롤업에 대한 상태 업데이트의 유효성을 강화하고 롤업 상태에 대한 모든 업데이트 뒤에 있는 데이터의 가용성을 보장합니다. 결과적으로, ZK-롤업은 자체 보안 속성을 책임지는 [사이드체인](/developers/docs/scaling/sidechains/)이나, 유효성 증명을 통해 이더리움에서 트랜잭션을 검증하지만 트랜잭션 데이터는 다른 곳에 저장하는 [밸리디움](/developers/docs/scaling/validium/)과 같은 순수 오프체인 확장 솔루션보다 훨씬 더 안전합니다. + +영지식 롤업은 다음을 위해 메인 이더리움 프로토콜에 의존합니다. + +### 데이터 가용성 {#data-availability} + +ZK-롤업은 오프체인에서 처리된 모든 트랜잭션의 상태 데이터를 이더리움에 게시합니다. 이 데이터를 사용해 개인이나 기업에서 롤업의 상태를 재생산하고 스스로 체인의 유효성을 검증할 수 있습니다. 이더리움은 이 데이터를 `calldata`로 네트워크의 모든 참여자가 사용할 수 있도록 합니다. + +유효성 증명이 이미 상태 전환의 진위 여부를 검증하기 때문에, ZK-롤업은 많은 트랜잭션 데이터를 온체인에 게시할 필요가 없습니다. 그럼에도 불구하고 온체인에 데이터를 저장하는 것은 중요합니다. L2 체인의 상태를 무허가적이고 독립적으로 검증할 수 있게 해주기 때문입니다. 이는 결국 누구나 트랜잭션 배치를 제출할 수 있게 하여 악의적인 운영자가 체인을 검열하거나 동결하는 것을 방지합니다. + +사용자가 롤업과 상호 작용하려면 온체인이 필요합니다. 상태 데이터 접근 없이 유저는 그들의 잔고나 상태 정보에 의존하는 트랜잭션 (예, 출금) 을 실행할 수 없습니다. + +### 트랜잭션 완결성 {#transaction-finality} + +이더리움은 ZK-롤업의 정산 레이어 역할을 합니다. L2 트랜잭션은 L1 계약이 유효성 증명을 수락해야만 완결됩니다. 모든 트랜잭션이 메인넷에서 승인되어야 하므로, 악의적인 운영자가 체인을 손상시키는(예: 롤업 자금 탈취) 위험을 제거합니다. 또한 이더리움은 사용자 작업이 L1에서 완결되면 되돌릴 수 없음을 보장합니다. + +### 검열 저항성 {#censorship-resistance} + +대부분의 ZK-롤업은 "슈퍼노드"(운영자)를 사용하여 트랜잭션을 실행하고, 배치를 생성하며, 블록을 L1에 제출합니다. 이는 효율성을 보장하지만 검열의 위험을 증가시킵니다. 악의적인 ZK-롤업 운영자는 사용자의 트랜잭션을 배치에 포함시키기를 거부함으로써 사용자를 검열할 수 있습니다. + +보안 조치로서, ZK-롤업은 사용자가 운영자에 의해 검열되고 있다고 생각하는 경우, 메인넷의 롤업 계약에 직접 트랜잭션을 제출할 수 있도록 합니다. 이를 통해 사용자는 운영자의 허가에 의존하지 않고 ZK-롤업에서 이더리움으로 강제 출금을 할 수 있습니다. + +## ZK-롤업은 어떻게 작동하나요? {#how-do-zk-rollups-work} + +### 트랜잭션 {#transactions} + +ZK-롤업의 사용자는 트랜잭션에 서명하고 다음 배치에 포함되도록 처리를 위해 L2 운영자에게 제출합니다. 어떤 경우에는 운영자가 시퀀서라고 불리는 중앙화된 주체이며, 트랜잭션을 실행하고, 배치로 집계하여 L1에 제출합니다. 이 시스템의 시퀀서는 L2 블록을 생성하고 ZK-롤업 계약에 롤업 트랜잭션을 추가할 수 있는 유일한 주체입니다. + +다른 ZK-롤업은 [지분 증명](/developers/docs/consensus-mechanisms/pos/) 검증자 세트를 사용하여 운영자 역할을 순환시킬 수 있습니다. 예비 운영자는 롤업 계약에 자금을 예치하며, 각 스테이킹의 크기는 스테이커가 다음 롤업 배치를 생성하도록 선택될 확률에 영향을 미칩니다. 운영자가 악의적으로 행동하면 스테이킹이 삭감될 수 있으며, 이는 유효한 블록을 게시하도록 장려합니다. + +#### ZK-롤업이 이더리움에 트랜잭션 데이터를 게시하는 방법 {#how-zk-rollups-publish-transaction-data-on-ethereum} + +설명한 바와 같이, 트랜잭션 데이터는 `calldata`로 이더리움에 게시됩니다. `calldata`는 함수에 인수를 전달하는 데 사용되는 스마트 계약의 데이터 영역이며 [메모리](/developers/docs/smart-contracts/anatomy/#memory)와 유사하게 동작합니다. `calldata`는 이더리움의 상태의 일부로 저장되지는 않지만, 이더리움 체인의 [기록 로그](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html?highlight=memory#logs)의 일부로 온체인에 유지됩니다. `calldata`는 이더리움의 상태에 영향을 미치지 않으므로 온체인에 데이터를 저렴하게 저장하는 방법입니다. + +`calldata` 키워드는 종종 트랜잭션에 의해 호출되는 스마트 계약 메서드를 식별하고 임의의 바이트 시퀀스 형태로 메서드에 대한 입력을 보유합니다. ZK-롤업은 `calldata`를 사용하여 압축된 트랜잭션 데이터를 온체인에 게시합니다. 롤업 운영자는 롤업 계약에서 필요한 함수를 호출하여 새 배치를 추가하고 압축된 데이터를 함수 인수로 전달하기만 하면 됩니다. 롤업 수수료의 상당 부분이 온체인에 트랜잭션 데이터를 저장하는 데 사용되므로 이는 사용자 비용을 줄이는 데 도움이 됩니다. + +### 상태 커밋먼트 {#state-commitments} + +L2 계정 및 잔액을 포함하는 ZK-롤업의 상태는 [머클 트리](/whitepaper/#merkle-trees)로 표시됩니다. 머클 트리의 루트(머클 루트)에 대한 암호화 해시는 온체인 계약에 저장되어 롤업 프로토콜이 ZK-롤업 상태의 변경 사항을 추적할 수 있도록 합니다. + +롤업은 새로운 트랜잭션 세트가 실행된 후 새로운 상태로 전환됩니다. 상태 전환을 시작한 운영자는 새로운 상태 루트를 계산하여 온체인 계약에 제출해야 합니다. 배치와 관련된 유효성 증명이 검증자 계약에 의해 인증되면 새로운 머클 루트는 ZK-롤업의 정식 상태 루트가 됩니다. + +상태 루트를 계산하는 것 외에도 ZK-롤업 운영자는 배치 루트, 즉 배치의 모든 트랜잭션으로 구성된 머클 트리의 루트도 생성합니다. 새 배치가 제출되면 롤업 계약은 배치 루트를 저장하여 사용자가 트랜잭션(예: 인출 요청)이 배치에 포함되었음을 증명할 수 있도록 합니다. 사용자는 트랜잭션 세부 정보, 배치 루트 및 포함 경로를 보여주는 [머클 증명](/developers/tutorials/merkle-proofs-for-offline-data-integrity/)을 제공해야 합니다. + +### 유효성 증명 {#validity-proofs} + +ZK-롤업 운영자가 L1 계약에 제출하는 새로운 상태 루트는 롤업 상태 업데이트의 결과입니다. 예를 들어 앨리스가 밥에게 10개의 토큰을 보내면 운영자는 앨리스의 잔액을 10만큼 줄이고 밥의 잔액을 10만큼 늘립니다. 그런 다음 운영자는 업데이트된 계정 데이터를 해시하고 롤업의 머클 트리를 다시 빌드한 다음 새 머클 루트를 온체인 계약에 제출합니다. + +그러나 롤업 계약은 운영자가 새 머클 루트가 롤업 상태에 대한 올바른 업데이트의 결과임을 증명할 때까지 제안된 상태 약정을 자동으로 수락하지 않습니다. ZK-롤업 운영자는 배치된 트랜잭션의 정확성을 검증하는 간결한 암호화 약정인 유효성 증명을 생성하여 이를 수행합니다. + +유효성 증명을 사용하면 당사자가 진술 자체를 공개하지 않고도 진술의 정확성을 증명할 수 있으므로 영지식 증명이라고도 합니다. ZK-롤업은 유효성 증명을 사용하여 이더리움에서 트랜잭션을 다시 실행하지 않고도 오프체인 상태 전환의 정확성을 확인합니다. 이러한 증명은 [ZK-SNARK](https://arxiv.org/abs/2202.06877)(영지식 간결 비대화형 지식 논증) 또는 [ZK-STARK](https://eprint.iacr.org/2018/046)(영지식 확장형 투명 지식 논증)의 형태를 띨 수 있습니다. + +SNARK와 STARK는 각각 독특한 특징을 가지고 있지만 ZK-롤업에서 오프체인 계산의 무결성을 증명하는 데 도움이 됩니다. + +**ZK-SNARK** + +ZK-SNARK 프로토콜이 작동하려면 공통 참조 문자열(CRS)을 생성해야 합니다. CRS는 유효성 증명을 증명하고 검증하기 위한 공개 매개변수를 제공합니다. 증명 시스템의 보안은 CRS 설정에 따라 달라집니다. 공개 매개변수를 생성하는 데 사용된 정보가 악의적인 행위자의 손에 들어가면 거짓 유효성 증명을 생성할 수 있습니다. + +일부 ZK-롤업은 신뢰할 수 있는 개인을 포함하는 [다자간 계산(MPC) 행사](https://zkproof.org/2021/06/30/setup-ceremonies/amp/)를 사용하여 ZK-SNARK 회로에 대한 공개 매개변수를 생성함으로써 이 문제를 해결하려고 시도합니다. 각 당사자는 CRS를 구성하기 위해 약간의 무작위성("독성 폐기물"이라고 함)을 제공하며, 이를 즉시 파기해야 합니다. + +신뢰 기반 설정은 CRS 설정의 보안을 높이기 때문에 사용됩니다. 한 명의 정직한 참가자가 자신의 입력을 파기하는 한 ZK-SNARK 시스템의 보안은 보장됩니다. 하지만 이 접근 방식은 관련된 사람들이 샘플링된 무작위성을 삭제하고 시스템의 보안 보장을 훼손하지 않을 것이라고 신뢰해야 합니다. + +신뢰 가정을 제외하고, ZK-SNARK는 작은 증명 크기와 상수 시간 검증으로 인기가 있습니다. L1에서의 증명 검증은 ZK-롤업 운영 비용의 더 큰 부분을 차지하므로 L2는 ZK-SNARK를 사용하여 메인넷에서 빠르고 저렴하게 검증할 수 있는 증명을 생성합니다. + +**ZK-STARK** + +ZK-SNARK와 마찬가지로 ZK-STARK는 입력을 공개하지 않고 오프체인 계산의 유효성을 증명합니다. 그러나 ZK-STARK는 확장성과 투명성 때문에 ZK-SNARK보다 개선된 것으로 간주됩니다. + +ZK-STARK는 공통 참조 문자열(CRS)의 신뢰 기반 설정 없이도 작동할 수 있으므로 '투명'합니다. 대신 ZK-STARK는 공개적으로 검증 가능한 무작위성에 의존하여 증명을 생성하고 검증하기 위한 매개변수를 설정합니다. + +ZK-STARK는 또한 유효성 증명을 증명하고 검증하는 데 필요한 시간이 기본 계산의 복잡성과 관련하여 _준선형적으로_ 증가하기 때문에 더 많은 확장성을 제공합니다. ZK-SNARK의 경우 증명 및 검증 시간은 기본 계산의 크기에 비례하여 _선형적으로_ 확장됩니다. 이는 대규모 데이터세트가 관련될 때 ZK-STARK가 증명 및 검증에 ZK-SNARK보다 시간이 덜 걸린다는 것을 의미하며, 따라서 대용량 애플리케이션에 유용합니다. + +ZK-STARK는 양자 컴퓨터에 대해서도 안전하지만, ZK-SNARK에 사용되는 타원 곡선 암호화(ECC)는 양자 컴퓨팅 공격에 취약한 것으로 널리 알려져 있습니다. ZK-STARK의 단점은 더 큰 증명 크기를 생성하여 이더리움에서 검증하는 데 더 많은 비용이 든다는 것입니다. + +#### ZK-롤업에서 유효성 증명은 어떻게 작동하나요? {#validity-proofs-in-zk-rollups} + +##### 증명 생성 + +트랜잭션을 수락하기 전에 운영자는 일반적인 검사를 수행합니다. 여기에는 다음 확인 사항이 포함됩니다. + +- 송금인과 수취인 계정이 상태 트리의 일부입니다. +- 송금인이 트랜잭션을 처리하기에 충분한 자금을 가지고 있습니다. +- 트랜잭션이 정확하고 롤업의 송금인 공개 키와 일치합니다. +- 송금인의 논스가 정확합니다. + +ZK-롤업 노드에 충분한 트랜잭션이 있으면 이를 배치로 집계하고 증명 회로가 간결한 ZK-증명으로 컴파일할 수 있도록 입력을 컴파일합니다. 여기에는 다음이 포함됩니다. + +- 배치의 모든 트랜잭션으로 구성된 머클 트리 루트. +- 배치 포함을 증명하기 위한 트랜잭션에 대한 머클 증명. +- 해당 계정이 롤업 상태 트리의 일부임을 증명하기 위해 트랜잭션의 각 송금인-수취인 쌍에 대한 머클 증명. +- 각 트랜잭션에 대한 상태 업데이트를 적용한 후 상태 루트를 업데이트하여 파생된 중간 상태 루트 세트(즉, 송금인 계정 감소 및 수취인 계정 증가). + +증명 회로는 각 트랜잭션을 "반복"하고 운영자가 트랜잭션을 처리하기 전에 완료한 것과 동일한 검사를 수행하여 유효성 증명을 계산합니다. 먼저 제공된 머클 증명을 사용하여 송금인의 계정이 기존 상태 루트의 일부인지 확인합니다. 그런 다음 송금인의 잔액을 줄이고, 논스를 증가시키고, 업데이트된 계정 데이터를 해시한 다음 머클 증명과 결합하여 새로운 머클 루트를 생성합니다. + +이 머클 루트는 ZK-롤업 상태의 유일한 변경 사항인 송금인의 잔액과 논스 변경을 반영합니다. 계정의 존재를 증명하는 데 사용되는 머클 증명이 새로운 상태 루트를 도출하는 데 사용되기 때문에 이것이 가능합니다. + +증명 회로는 수취인의 계정에서 동일한 프로세스를 수행합니다. 중간 상태 루트 아래에 수취인의 계정이 있는지 확인하고(머클 증명 사용), 잔액을 늘리고, 계정 데이터를 다시 해시한 다음 머클 증명과 결합하여 새로운 상태 루트를 생성합니다. + +이 프로세스는 모든 트랜잭션에 대해 반복됩니다. 각 "루프"는 송금인의 계정을 업데이트하여 새로운 상태 루트를 생성하고 수취인의 계정을 업데이트하여 후속 새로운 루트를 생성합니다. 설명한 바와 같이 상태 루트에 대한 모든 업데이트는 롤업 상태 트리의 한 부분이 변경되었음을 나타냅니다. + +ZK 증명 회로는 전체 트랜잭션 배치를 반복하여 마지막 트랜잭션이 실행된 후 최종 상태 루트가 되는 업데이트 순서를 확인합니다. 계산된 마지막 머클 루트는 ZK-롤업의 최신 정식 상태 루트가 됩니다. + +##### 증명 검증 + +증명 회로가 상태 업데이트의 정확성을 확인한 후 L2 운영자는 계산된 유효성 증명을 L1의 검증자 계약에 제출합니다. 계약의 검증 회로는 증명의 유효성을 확인하고 증명의 일부를 구성하는 공개 입력도 확인합니다. + +- **이전 상태 루트**: ZK-롤업의 이전 상태 루트(즉, 일괄 처리된 트랜잭션이 실행되기 전)로, L2 체인의 마지막으로 알려진 유효한 상태를 반영합니다. + +- **이후 상태 루트**: ZK-롤업의 새로운 상태 루트(즉, 일괄 처리된 트랜잭션이 실행된 후)로, L2 체인의 최신 상태를 반영합니다. 이후 상태 루트는 증명 회로에서 상태 업데이트를 적용한 후 파생된 최종 루트입니다. + +- **배치 루트**: 배치의 머클 루트로, 배치의 트랜잭션을 머클화하고 트리의 루트를 해시화하여 파생됩니다. + +- **트랜잭션 입력**: 제출된 배치의 일부로 실행된 트랜잭션과 관련된 데이터. + +증명이 회로를 만족시키는 경우(즉, 유효한 경우) 이전 상태(이전 상태 루트로 암호화 지문 채취)에서 새로운 상태(이후 상태 루트로 암호화 지문 채취)로 롤업을 전환하는 유효한 트랜잭션 시퀀스가 존재함을 의미합니다. 이전 상태 루트가 롤업 계약에 저장된 루트와 일치하고 증명이 유효하면 롤업 계약은 증명에서 이후 상태 루트를 가져와 롤업의 변경된 상태를 반영하도록 상태 트리를 업데이트합니다. + +### 진입 및 탈출 {#entries-and-exits} + +사용자는 L1 체인에 배포된 롤업 계약에 토큰을 예치하여 ZK-롤업에 참여합니다. 운영자만 롤업 계약에 트랜잭션을 제출할 수 있으므로 이 트랜잭션은 대기열에 추가됩니다. + +보류 중인 예금 대기열이 채워지기 시작하면 ZK-롤업 운영자는 예금 트랜잭션을 가져와 롤업 계약에 제출합니다. 사용자의 자금이 롤업에 있으면 처리를 위해 운영자에게 트랜잭션을 전송하여 거래를 시작할 수 있습니다. 사용자는 계정 데이터를 해시하고 해시를 롤업 계약에 보낸 다음 머클 증명을 제공하여 현재 상태 루트에 대해 확인하여 롤업의 잔액을 확인할 수 있습니다. + +ZK-롤업에서 L1으로 인출하는 것은 간단합니다. 사용자는 롤업의 자산을 소각을 위해 지정된 계정으로 보내 출금 트랜잭션을 시작합니다. 운영자가 다음 배치에 트랜잭션을 포함하면 사용자는 온체인 계약에 인출 요청을 제출할 수 있습니다. 이 인출 요청에는 다음이 포함됩니다. + +- 사용자의 트랜잭션이 소각 계정으로 전송되었음을 증명하는 머클 증명 + +- 트랜잭션 데이터 + +- 배치 루트 + +- 예치된 자금을 받을 L1 주소 + +롤업 계약은 트랜잭션 데이터를 해시하고 배치 루트가 있는지 확인한 다음 머클 증명을 사용하여 트랜잭션 해시가 배치 루트의 일부인지 확인합니다. 그 후 계약은 출금 트랜잭션을 실행하고 L1에서 사용자가 선택한 주소로 자금을 보냅니다. + +## ZK-롤업 및 EVM 호환성 {#zk-rollups-and-evm-compatibility} + +낙관적 롤업과 달리 ZK-롤업은 [이더리움 가상 머신(EVM)](/developers/docs/evm/)과 쉽게 호환되지 않습니다. 회로에서 범용 EVM 계산을 증명하는 것은 이전에 설명한 토큰 전송과 같은 간단한 계산을 증명하는 것보다 더 어렵고 리소스 집약적입니다. + +그러나 [영지식 기술의 발전](https://hackmd.io/@yezhang/S1_KMMbGt#Why-possible-now)으로 인해 EVM 계산을 영지식 증명으로 래핑하는 것에 대한 관심이 다시 불붙고 있습니다. 이러한 노력은 프로그램 실행의 정확성을 효율적으로 검증할 수 있는 영지식 EVM(zkEVM) 구현을 만드는 것을 목표로 합니다. zkEVM은 회로에서 증명/검증을 위해 기존 EVM 옵코드를 재생성하여 스마트 계약을 실행할 수 있도록 합니다. + +EVM과 마찬가지로 zkEVM은 일부 입력에 대한 계산이 수행된 후 상태 간에 전환됩니다. 차이점은 zkEVM이 프로그램 실행의 모든 단계의 정확성을 검증하기 위해 영지식 증명을 생성한다는 것입니다. 유효성 증명은 VM의 상태(메모리, 스택, 스토리지)에 영향을 미치는 작업의 정확성과 계산 자체(즉, 작업이 올바른 옵코드를 호출하고 올바르게 실행했는지 여부)를 확인할 수 있습니다. + +EVM 호환 ZK-롤업의 도입은 개발자가 영지식 증명의 확장성과 보안 보장을 활용하는 데 도움이 될 것으로 예상됩니다. 더 중요한 것은 네이티브 이더리움 인프라와의 호환성은 개발자가 익숙하고 검증된 툴링과 언어를 사용하여 ZK 친화적인 탈중앙화앱을 구축할 수 있음을 의미합니다. + +## ZK-롤업 수수료는 어떻게 작동하나요? {#how-do-zk-rollup-fees-work} + +ZK-롤업에서 사용자가 트랜잭션에 대해 지불하는 금액은 이더리움 메인넷과 마찬가지로 가스 수수료에 따라 다릅니다. 그러나 가스 수수료는 L2에서 다르게 작동하며 다음 비용의 영향을 받습니다. + +1. **상태 쓰기**: 이더리움 상태에 쓰는 데(즉, 이더리움 블록체인에 트랜잭션을 제출하는 것) 고정 비용이 있습니다. ZK-롤업은 트랜잭션을 일괄 처리하고 여러 사용자에게 고정 비용을 분산시켜 이 비용을 줄입니다. + +2. **데이터 게시**: ZK-롤업은 모든 트랜잭션의 상태 데이터를 `calldata`로 이더리움에 게시합니다. `calldata` 비용은 현재 [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)에 의해 관리되며, 이는 0이 아닌 바이트에 대해 16 가스, `calldata`의 0바이트에 대해 각각 4 가스의 비용을 규정합니다. 각 트랜잭션에 대해 지불하는 비용은 온체인에 게시해야 하는 `calldata`의 양에 따라 영향을 받습니다. + +3. **L2 운영자 수수료**: 이더리움 메인넷의 [트랜잭션 "우선 수수료(팁)"](/developers/docs/gas/#how-are-gas-fees-calculated)와 마찬가지로 트랜잭션 처리 시 발생하는 계산 비용에 대한 보상으로 롤업 운영자에게 지불되는 금액입니다. + +4. **증명 생성 및 검증**: ZK-롤업 운영자는 트랜잭션 배치에 대한 유효성 증명을 생성해야 하며, 이는 리소스 집약적입니다. 메인넷에서 영지식 증명을 검증하는 데에도 가스(\~500,000 가스)가 소요됩니다. + +트랜잭션을 일괄 처리하는 것 외에도 ZK-롤업은 트랜잭션 데이터를 압축하여 사용자 수수료를 줄입니다. 이더리움 ZK-롤업 사용 비용에 대한 [실시간 개요](https://l2fees.info/)를 볼 수 있습니다. + +## ZK-롤업은 이더리움을 어떻게 확장하나요? {#scaling-ethereum-with-zk-rollups} + +### 트랜잭션 데이터 압축 {#transaction-data-compression} + +ZK-롤업은 계산을 오프체인으로 가져와 이더리움의 기본 레이어에서 처리량을 확장하지만, 확장을 위한 진정한 이점은 트랜잭션 데이터를 압축하는 데 있습니다. 이더리움의 [블록 크기](/developers/docs/blocks/#block-size)는 각 블록이 보유할 수 있는 데이터의 양과 나아가 블록당 처리되는 트랜잭션 수를 제한합니다. 트랜잭션 관련 데이터를 압축함으로써 ZK-롤업은 블록당 처리되는 트랜잭션 수를 크게 늘립니다. + +ZK-롤업은 각 트랜잭션을 검증하는 데 필요한 모든 데이터를 게시할 필요가 없으므로 낙관적 롤업보다 트랜잭션 데이터를 더 잘 압축할 수 있습니다. 롤업에서 계정 및 잔액의 최신 상태를 재구성하는 데 필요한 최소한의 데이터만 게시하면 됩니다. + +### 재귀적 증명 {#recursive-proofs} + +영지식 증명의 장점은 증명이 다른 증명을 검증할 수 있다는 것입니다. 예를 들어, 단일 ZK-SNARK는 다른 ZK-SNARK를 검증할 수 있습니다. 이러한 "증명의 증명"은 재귀적 증명이라고 하며 ZK-롤업의 처리량을 극적으로 증가시킵니다. + +현재 유효성 증명은 블록 단위로 생성되어 검증을 위해 L1 계약에 제출됩니다. 그러나 운영자가 증명을 제출할 때 하나의 블록만 완결될 수 있으므로 단일 블록 증명을 검증하면 ZK-롤업이 달성할 수 있는 처리량이 제한됩니다. + +그러나 재귀적 증명을 사용하면 하나의 유효성 증명으로 여러 블록을 완결할 수 있습니다. 이는 증명 회로가 최종 증명이 하나 생성될 때까지 여러 블록 증명을 재귀적으로 집계하기 때문입니다. L2 운영자는 이 재귀적 증명을 제출하며, 계약이 이를 수락하면 모든 관련 블록이 즉시 완결됩니다. 재귀적 증명을 사용하면 일정 간격으로 이더리움에서 완결될 수 있는 ZK-롤업 트랜잭션의 수가 증가합니다. + +### ZK-롤업의 장단점 {#zk-rollups-pros-and-cons} + +| 장점 | 단점 | +| ------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | +| 유효성 증명은 오프체인 트랜잭션의 정확성을 보장하고 운영자가 잘못된 상태 전환을 실행하는 것을 방지합니다. | 유효성 증명을 계산하고 검증하는 데 드는 비용이 상당하며 롤업 사용자의 수수료를 증가시킬 수 있습니다. | +| L1에서 유효성 증명이 검증되면 상태 업데이트가 승인되므로 더 빠른 트랜잭션 완결성을 제공합니다. | 영지식 기술의 복잡성으로 인해 EVM 호환 ZK-롤업을 구축하는 것은 어렵습니다. | +| [낙관적 롤업](/developers/docs/scaling/optimistic-rollups/#optimistic-pros-and-cons)과 같이 인센티브를 받는 행위자의 정직성이 아니라 보안을 위해 무신뢰 암호화 메커니즘에 의존합니다. | 유효성 증명을 생성하려면 특수 하드웨어가 필요하며, 이는 소수 당사자에 의한 체인의 중앙 집중식 제어를 조장할 수 있습니다. | +| L1에서 오프체인 상태를 복구하는 데 필요한 데이터를 저장하여 보안, 검열 저항성 및 탈중앙화를 보장합니다. | 중앙화된 운영자(시퀀서)는 트랜잭션 순서에 영향을 미칠 수 있습니다. | +| 사용자는 더 큰 자본 효율성의 이점을 누리고 지연 없이 L2에서 자금을 인출할 수 있습니다. | 하드웨어 요구 사항으로 인해 체인을 강제로 진행시킬 수 있는 참여자 수가 줄어들어 악의적인 운영자가 롤업 상태를 동결하고 사용자를 검열할 위험이 증가할 수 있습니다. | +| 활성 가정에 의존하지 않으며 사용자는 자금을 보호하기 위해 체인을 검증할 필요가 없습니다. | 일부 증명 시스템(예: ZK-SNARK)은 신뢰 기반 설정을 필요로 하며, 이를 잘못 처리하면 ZK-롤업의 보안 모델이 손상될 수 있습니다. | +| 더 나은 데이터 압축은 이더리움에서 `calldata`를 게시하는 비용을 줄이고 사용자의 롤업 수수료를 최소화하는 데 도움이 될 수 있습니다. | | + +### ZK-롤업에 대한 시각적 설명 {#zk-video} + +Finematics에서 영지식 증명에 대해 설명합니다. + + + +## zkEVM을 개발하는 곳은 어디인가요? {#zkevm-projects} + +zkEVM을 개발하는 프로젝트는 다음과 같습니다. + +- **[zkEVM](https://github.com/privacy-scaling-explorations/zkevm-specs)** - _zkEVM은 이더리움 재단이 EVM 호환 ZK-롤업과 이더리움 블록에 대한 유효성 증명 생성 메커니즘을 개발하기 위해 자금을 지원하는 프로젝트입니다._ + +- **[Polygon zkEVM](https://polygon.technology/solutions/polygon-zkevm)** - _이더리움 메인넷의 탈중앙화된 ZK 롤업으로, 영지식 증명 검증을 통해 스마트 계약을 포함한 이더리움 트랜잭션을 투명하게 실행하는 영지식 이더리움 가상 머신(zkEVM)을 개발하고 있습니다._ + +- **[Scroll](https://scroll.io/blog/zkEVM)** - _Scroll은 이더리움을 위한 네이티브 zkEVM 레이어 2 솔루션을 구축하는 기술 중심 회사입니다._ + +- **[Taiko](https://taiko.xyz)** - _Taiko는 탈중앙화된 이더리움 동등 ZK-롤업([유형 1 ZK-EVM](https://vitalik.eth.limo/general/2022/08/04/zkevm.html))입니다._ + +- **[ZKsync](https://docs.zksync.io/)** - _ZKsync Era는 Matter Labs가 구축한 EVM 호환 ZK 롤업으로, 자체 zkEVM으로 구동됩니다._ + +- **[Starknet](https://starkware.co/starknet/)** - _StarkNet은 StarkWare가 구축한 EVM 호환 레이어 2 확장 솔루션입니다._ + +- **[Morph](https://www.morphl2.io/)** - _Morph는 zk-증명을 활용하여 레이어 2 상태 문제 문제를 해결하는 하이브리드 롤업 확장 솔루션입니다._ + +- **[Linea](https://linea.build)** - _Linea는 Consensys가 구축한 이더리움 동등 zkEVM 레이어 2로, 이더리움 생태계와 완벽하게 일치합니다._ + +## ZK-롤업에 대한 추가 자료 {#further-reading-on-zk-rollups} + +- [영지식 롤업이란?](https://coinmarketcap.com/alexandria/glossary/zero-knowledge-rollups) +- [영지식 롤업이란?](https://alchemy.com/blog/zero-knowledge-rollups) +- [이더리움 롤업 실용 가이드](https://web.archive.org/web/20241108192208/https://research.2077.xyz/the-practical-guide-to-ethereum-rollups) +- [STARK 대 SNARK](https://consensys.net/blog/blockchain-explained/zero-knowledge-proofs-starks-vs-snarks/) +- [zkEVM이란?](https://www.alchemy.com/overviews/zkevm) +- [ZK-EVM 유형: 이더리움 동등, EVM 동등, 유형 1, 유형 4 및 기타 암호화된 유행어](https://taiko.mirror.xyz/j6KgY8zbGTlTnHRFGW6ZLVPuT0IV0_KmgowgStpA0K4) +- [zkEVM 소개](https://hackmd.io/@yezhang/S1_KMMbGt) +- [ZK-EVM L2란?](https://linea.mirror.xyz/qD18IaQ4BROn_Y40EBMTUTdJHYghUtdECscSWyMvm8M) +- [Awesome-zkEVM 리소스](https://github.com/LuozhuZhang/awesome-zkevm) +- [ZK-SNARK 내부 구조](https://vitalik.eth.limo/general/2017/02/01/zk_snarks.html) +- [SNARK는 어떻게 가능한가?](https://vitalik.eth.limo/general/2021/01/26/snarks.html) diff --git a/public/content/translations/ko/developers/docs/smart-contracts/anatomy/index.md b/public/content/translations/ko/developers/docs/smart-contracts/anatomy/index.md new file mode 100644 index 00000000000..fab057e51df --- /dev/null +++ b/public/content/translations/ko/developers/docs/smart-contracts/anatomy/index.md @@ -0,0 +1,658 @@ +--- +title: "스마트 계약의 구조" +description: "스마트 컨트랙트 구성 요소에 대해 자세히 알아보기 - 함수, 데이터, 변수" +lang: ko +--- + +스마트 컨트랙트는 이더리움 주소 체계 상에서 실행되는 프로그램이며, 거래가 발생할 때 실행되는 데이터와 함수로 구성되어 있습니다. 지금부터 그 구성 요소에 대해 전반적으로 살펴보도록 하겠습니다. + +## 필수 구성 요소 {#prerequisites} + +[스마트 계약](/developers/docs/smart-contracts/)에 대해 먼저 읽어보시기 바랍니다. 자바 스크립트나 파이썬과 같은 프로그래밍 언어에 상당히 익숙하다는 것을 전제합니다. + +## 데이터 {#data} + +모든 계약 데이터는 `storage` 또는 `memory` 위치에 할당되어야 합니다. 이 중 스토리지 사용은 비용이 더 발생하므로 여러분은 어떤 것을 활용할 지 미리 고려해야 합니다. + +### 저장 공간 {#storage} + +영구적인 데이터는 스토리지로 간주되며 상태 변수 형태로 표현됩니다. 이런 값은 블록체인 상에 영구히 남게 되므로, 컨트랙트 컴파일 시에 스토리지 형태로 사용할 변수를 명확히 구분할 필요가 있습니다. + +```solidity +// Solidity 예시 +contract SimpleStorage { + uint storedData; // 상태 변수 + // ... +} +``` + +```python +# Vyper 예시 +storedData: int128 +``` + +여러분이 객체 지향적인 언어를 사용해 보았다면 대부분의 변수 타입에는 익숙할 것입니다. 하지만 이더리움 개발이 처음이라면 `address`는 생소할 수 있습니다. + +`address` 유형은 이더리움 주소를 저장할 수 있으며, 이는 20바이트 또는 160비트와 같습니다. 또한 16진수로 표기되며 0x로 시작합니다. + +기타 유형에는 다음이 포함됩니다: + +- 불리언 +- 정수 +- 고정 소수점 숫자 +- 고정 크기 바이트 배열 +- 동적 크기 바이트 배열 +- 유리수 및 정수 리터럴 +- 문자열 리터럴 +- 16진수 리터럴 +- 열거형 + +더 많은 설명은 문서를 참고하십시오: + +- [Vyper 유형 보기](https://docs.vyperlang.org/en/v0.1.0-beta.6/types.html#value-types) +- [Solidity 유형 보기](https://docs.soliditylang.org/en/latest/types.html#value-types) + +### 메모리 {#memory} + +메모리 변수는 컨트랙스 함수가 실행되는 시간에만 사용이 가능하기 때문에, 블록체인에는 저장되지 않고 비용도 저렴합니다. + +[Solidity 문서](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html#storage-memory-and-the-stack)에서 EVM이 데이터(저장 공간, 메모리, 스택)를 저장하는 방법에 대해 자세히 알아보세요. + +### 환경 변수 {#environment-variables} + +여러분이 컨트랙트에 정의한 변수 외에도 특별하게 사용할 수 있는 전역 변수가 있습니다. 그것을 통해 주로 블록체인과 현재 트랜잭션에 대한 정보를 알 수 있습니다. + +예시: + +| **속성** | **상태 변수** | **설명** | +| ----------------- | --------- | ---------------------------------- | +| `block.timestamp` | uint256 | 현재 블록 에포크 타임스탬프 | +| `msg.sender` | 주소 | 메시지의 발신자(현재 호출) | + +## 함수 {#functions} + +함수는 거래에 대한 정보를 간단한 방법으로 가져오거나 설정할 수 있습니다. + +함수 호출에는 두 가지 방법이 있습니다. + +- `internal` – EVM 호출을 생성하지 않습니다 + - 내부 함수와 상태 변수는 내부에서만 (즉, 현재 계약 또는 그로부터 파생된 계약 내에서만) 접근할 수 있습니다 +- `external` – EVM 호출을 생성합니다 + - 외부 함수는 계약 인터페이스의 일부로, 다른 계약 및 트랜잭션을 통해 호출할 수 있습니다. 외부 함수 `f`는 내부에서 호출할 수 없습니다(예: `f()`는 작동하지 않지만 `this.f()`는 작동합니다). + +`public` 또는 `private`일 수도 있습니다 + +- `public` 함수는 계약 내에서 내부적으로 또는 메시지를 통해 외부에서 호출할 수 있습니다 +- `private` 함수는 정의된 계약에서만 볼 수 있으며 파생된 계약에서는 볼 수 없습니다 + +함수와 상태 변수 모두 public 또는 private 설정이 가능합니다. + +계약의 상태 변수를 업데이트하는 함수 예제입니다: + +```solidity +// Solidity 예시 +function update_name(string value) public { + dapp_name = value; +} +``` + +- `string` 유형의 매개변수 `value`가 `update_name` 함수에 전달됩니다 +- `public`으로 선언되어 누구나 접근할 수 있습니다 +- `view`로 선언되지 않았으므로 계약 상태를 수정할 수 있습니다 + +### View 함수 {#view-functions} + +이 함수들은 컨트랙트 데이터를 변경하지 않습니다. 흔히 "getter" 함수라고도 하며 사용자의 지갑의 잔액을 얻을 때 사용될 때의 예시입니다. + +```solidity +// Solidity 예시 +function balanceOf(address _owner) public view returns (uint256 _balance) { + return ownerPizzaCount[_owner]; +} +``` + +```python +dappName: public(string) + +@view +@public +def readName() -> string: + return dappName +``` + +상태를 수정하는 것으로 간주되는 것: + +1. 상태 변수에 쓰기 +2. [이벤트 발생시키기](https://docs.soliditylang.org/en/v0.7.0/contracts.html#events). +3. [다른 계약 생성하기](https://docs.soliditylang.org/en/v0.7.0/control-structures.html#creating-contracts). +4. `selfdestruct` 사용하기. +5. 호출을 통해 이더 전송 +6. `view` 또는 `pure`로 표시되지 않은 함수 호출하기. +7. 저수준 호출 사용 +8. 특정 오프코드를 포함하는 인라인 어셈블리 사용 + +### 생성자 함수 {#constructor-functions} + +`constructor` 함수는 계약이 처음 배포될 때 한 번만 실행됩니다. 많은 클래스 기반 프로그래밍 언어의 `constructor`와 마찬가지로, 이 함수는 종종 상태 변수를 지정된 값으로 초기화합니다. + +```solidity +// Solidity 예시 +// 계약의 데이터를 초기화하고, `owner`를 +// 계약 생성자의 주소로 설정합니다. +constructor() public { + // 모든 스마트 계약은 외부 트랜잭션에 의존하여 함수를 실행합니다. + // `msg`는 보낸 사람의 주소 및 트랜잭션에 포함된 ETH 값과 같은 + // 주어진 트랜잭션의 관련 데이터를 포함하는 전역 변수입니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties + owner = msg.sender; +} +``` + +```python +# Vyper 예시 + +@external +def __init__(_beneficiary: address, _bidding_time: uint256): + self.beneficiary = _beneficiary + self.auctionStart = block.timestamp + self.auctionEnd = self.auctionStart + _bidding_time +``` + +### 내장 함수 {#built-in-functions} + +컨트랙트를 작성할 때 정의하는 변수와 함수 외에 추가적으로 사용할 수 있는 특별한 내장 함수가 있습니다. 대표적인 함수에는 아래가 있으며, + +- `address.send()` – 솔리디티 +- `send(address)` – Vyper + +다른 계정으로 ETH를 송금할 때 사용할 수 있습니다. + +## 함수 작성하기 {#writing-functions} + +당신의 함수에는 다음이 필요합니다: + +- 매개변수 변수 및 타입(매개변수를 받는 경우) +- 내부/외부 선언 +- 순수(pure)/뷰(view)/지급(payable) 선언 +- 반환 타입(값을 반환하는 경우) + +```solidity +pragma solidity >=0.4.0 <=0.6.0; + +contract ExampleDapp { + string dapp_name; // 상태 변수 + + // 계약이 배포될 때 호출되어 값을 초기화합니다 + constructor() public { + dapp_name = "My Example dapp"; + } + + // Get 함수 + function read_name() public view returns(string) { + return dapp_name; + } + + // Set 함수 + function update_name(string value) public { + dapp_name = value; + } +} +``` + +완전한 계약은 다음과 같을 수 있습니다. 여기서 `constructor` 함수는 `dapp_name` 변수에 대한 초기값을 제공합니다. + +## 이벤트와 로그 {#events-and-logs} + +이벤트는 스마트 계약이 프론트엔드나 다른 구독 애플리케이션과 통신할 수 있게 합니다. 트랜잭션이 검증되어 블록에 추가되면, 스마트 계약은 이벤트를 방출하고 정보를 로그로 기록할 수 있으며, 프론트엔드는 이를 처리하고 활용할 수 있습니다. + +## 주석이 달린 예시 {#annotated-examples} + +이것들은 Solidity로 작성된 몇 가지 예시입니다. 코드를 사용해보고 싶다면 [Remix](http://remix.ethereum.org)에서 상호작용할 수 있습니다. + +### Hello world {#hello-world} + +```solidity +// 시맨틱 버저닝을 사용하여 Solidity 버전을 지정합니다. +// 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma +pragma solidity ^0.5.10; + +// `HelloWorld`라는 이름의 계약을 정의합니다. +// 계약은 함수와 데이터(상태)의 모음입니다. +// 배포된 계약은 이더리움 블록체인의 특정 주소에 존재합니다. +// 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html +contract HelloWorld { + + // `string` 유형의 상태 변수 `message`를 선언합니다. + // 상태 변수는 계약 저장 공간에 영구적으로 저장되는 변수입니다. + // `public` 키워드를 사용하면 계약 외부에서 변수에 접근할 수 있으며 + // 다른 계약이나 클라이언트가 값을 접근하기 위해 호출할 수 있는 함수를 생성합니다. + string public message; + + // 많은 클래스 기반 객체 지향 언어와 마찬가지로, 생성자는 + // 계약 생성 시에만 실행되는 특별한 함수입니다. + // 생성자는 계약의 데이터를 초기화하는 데 사용됩니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors + constructor(string memory initMessage) public { + // 문자열 인수 `initMessage`를 받아 계약의 `message` 저장 공간 변수에 + // 값을 설정합니다. + message = initMessage; + } + + // 문자열 인수를 받아 + // `message` 저장 공간 변수를 업데이트하는 public 함수입니다. + function update(string memory newMessage) public { + message = newMessage; + } +} +``` + +### 토큰 {#token} + +```solidity +pragma solidity ^0.5.10; + +contract Token { + // `address`는 이메일 주소와 비슷하며, 이더리움에서 계정을 식별하는 데 사용됩니다. + // 주소는 스마트 계약 또는 외부(사용자) 계정을 나타낼 수 있습니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/types.html#address + address public owner; + + // `mapping`은 기본적으로 해시 테이블 데이터 구조입니다. + // 이 `mapping`은 부호 없는 정수(토큰 잔액)를 주소(토큰 보유자)에 할당합니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/types.html#mapping-types + mapping (address => uint) public balances; + + // 이벤트를 통해 블록체인 활동을 기록할 수 있습니다. + // 이더리움 클라이언트는 계약 상태 변경에 반응하기 위해 이벤트를 수신할 수 있습니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#events + event Transfer(address from, address to, uint amount); + + // 계약 데이터를 초기화하고, `owner`를 + // 계약 생성자의 주소로 설정합니다. + constructor() public { + // 모든 스마트 계약은 외부 트랜잭션에 의존하여 함수를 실행합니다. + // `msg`는 보낸 사람의 주소 및 트랜잭션에 포함된 ETH 값과 같은 + // 주어진 트랜잭션의 관련 데이터를 포함하는 전역 변수입니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties + owner = msg.sender; + } + + // 새로운 토큰을 생성하여 주소로 보냅니다. + function mint(address receiver, uint amount) public { + // `require`는 특정 조건을 강제하는 데 사용되는 제어 구조입니다. + // `require`문이 `false`로 평가되면 예외가 발생하며, + // 현재 호출 동안 상태에 적용된 모든 변경 사항이 되돌려집니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions + + // 계약 소유자만 이 함수를 호출할 수 있습니다 + require(msg.sender == owner, "당신은 소유자가 아닙니다."); + + // 토큰의 최대량을 강제합니다 + require(amount < 1e60, "최대 발행량을 초과했습니다"); + + // `receiver`의 잔액을 `amount`만큼 증가시킵니다 + balances[receiver] += amount; + } + + // 호출자로부터 주소로 기존 토큰을 보냅니다. + function transfer(address receiver, uint amount) public { + // 보내는 사람은 보낼 만큼의 충분한 토큰을 가지고 있어야 합니다 + require(amount <= balances[msg.sender], "잔액이 부족합니다."); + + // 두 주소의 토큰 잔액을 조정합니다 + balances[msg.sender] -= amount; + balances[receiver] += amount; + + // 이전에 정의된 이벤트를 발생시킵니다 + emit Transfer(msg.sender, receiver, amount); + } +} +``` + +### 고유 디지털 자산 {#unique-digital-asset} + +```solidity +pragma solidity ^0.5.10; + +// 다른 파일의 심볼을 현재 계약으로 가져옵니다. +// 이 경우 OpenZeppelin의 일련의 헬퍼 계약입니다. +// 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#importing-other-source-files + +import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; +import "../node_modules/@openzeppelin/contracts/introspection/ERC165.sol"; +import "../node_modules/@openzeppelin/contracts/math/SafeMath.sol"; + +// `is` 키워드는 외부 계약에서 함수와 키워드를 상속받는 데 사용됩니다. +// 이 경우, `CryptoPizza`는 `IERC721` 및 `ERC165` 계약에서 상속받습니다. +// 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#inheritance +contract CryptoPizza is IERC721, ERC165 { + // OpenZeppelin의 SafeMath 라이브러리를 사용하여 산술 연산을 안전하게 수행합니다. + // 자세히 알아보기: https://docs.openzeppelin.com/contracts/2.x/api/math#SafeMath + using SafeMath for uint256; + + // Solidity의 상수 상태 변수는 다른 언어와 유사하지만 + // 컴파일 시에 상수인 표현식에서 할당해야 합니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constant-state-variables + uint256 constant dnaDigits = 10; + uint256 constant dnaModulus = 10 ** dnaDigits; + bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; + + // Struct 유형을 사용하면 자신만의 유형을 정의할 수 있습니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs + struct Pizza { + string name; + uint256 dna; + } + + // Pizza 구조체의 빈 배열을 생성합니다. + Pizza[] public pizzas; + + // 피자 ID에서 소유자 주소로의 매핑 + mapping(uint256 => address) public pizzaToOwner; + + // 소유자 주소에서 소유한 토큰 수로의 매핑 + mapping(address => uint256) public ownerPizzaCount; + + // 토큰 ID에서 승인된 주소로의 매핑 + mapping(uint256 => address) pizzaApprovals; + + // 매핑을 중첩할 수 있습니다. 이 예는 소유자를 운영자 승인에 매핑합니다. + mapping(address => mapping(address => bool)) private operatorApprovals; + + // 문자열(이름)과 DNA로부터 임의의 피자를 생성하는 내부 함수 + function _createPizza(string memory _name, uint256 _dna) + // `internal` 키워드는 이 함수가 이 계약과 + // 이 계약을 파생하는 계약 내에서만 보인다는 것을 의미합니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters + internal + // `isUnique`는 피자가 이미 존재하는지 확인하는 함수 제어자입니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers + isUnique(_name, _dna) + { + // 피자 배열에 피자를 추가하고 id를 얻습니다. + uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1); + + // 피자 소유자가 현재 사용자와 동일한지 확인합니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions + + // note that address(0)은 제로 주소이며, + // pizza[id]가 아직 특정 사용자에게 할당되지 않았음을 나타냅니다. + + assert(pizzaToOwner[id] == address(0)); + + // 피자를 소유자에게 매핑합니다. + pizzaToOwner[id] = msg.sender; + ownerPizzaCount[msg.sender] = SafeMath.add( + ownerPizzaCount[msg.sender], + 1 + ); + } + + // 문자열(이름)로부터 임의의 피자를 생성합니다. + function createRandomPizza(string memory _name) public { + uint256 randDna = generateRandomDna(_name, msg.sender); + _createPizza(_name, randDna); + } + + // 문자열(이름)과 소유자 주소(생성자)로부터 임의의 DNA를 생성합니다. + function generateRandomDna(string memory _str, address _owner) + public + // `pure`로 표시된 함수는 상태를 읽거나 수정하지 않을 것을 약속합니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions + pure + returns (uint256) + { + // 문자열(이름) + 주소(소유자)로부터 임의의 uint를 생성합니다. + uint256 rand = uint256(keccak256(abi.encodePacked(_str))) + + uint256(_owner); + rand = rand % dnaModulus; + return rand; + } + + // 소유자가 찾은 피자 배열을 반환합니다. + function getPizzasByOwner(address _owner) + public + // `view`로 표시된 함수는 상태를 수정하지 않을 것을 약속합니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions + view + returns (uint256[] memory) + { + // `memory` 저장 위치를 사용하여 이 함수 호출의 + // 수명 주기 동안만 값을 저장합니다. + // 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/introduction-to-smart-contracts.html#storage-memory-and-the-stack + uint256[] memory result = new uint256[](ownerPizzaCount[_owner]); + uint256 counter = 0; + for (uint256 i = 0; i < pizzas.length; i++) { + if (pizzaToOwner[i] == _owner) { + result[counter] = i; + counter++; + } + } + return result; + } + + // 피자와 소유권을 다른 주소로 이전합니다. + function transferFrom(address _from, address _to, uint256 _pizzaId) public { + require(_from != address(0) && _to != address(0), "유효하지 않은 주소입니다."); + require(_exists(_pizzaId), "피자가 존재하지 않습니다."); + require(_from != _to, "같은 주소로 전송할 수 없습니다."); + require(_isApprovedOrOwner(msg.sender, _pizzaId), "주소가 승인되지 않았습니다."); + + ownerPizzaCount[_to] = SafeMath.add(ownerPizzaCount[_to], 1); + ownerPizzaCount[_from] = SafeMath.sub(ownerPizzaCount[_from], 1); + pizzaToOwner[_pizzaId] = _to; + + // 가져온 IERC721 계약에 정의된 이벤트를 발생시킵니다. + emit Transfer(_from, _to, _pizzaId); + _clearApproval(_to, _pizzaId); + } + + /** + * 주어진 토큰 ID의 소유권을 다른 주소로 안전하게 이전합니다. + * 대상 주소가 계약인 경우, `onERC721Received`를 구현해야 하며, + * 이는 안전한 전송 시 호출되고 매직 값 + * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`을 반환해야 합니다. + * 그렇지 않으면 전송이 되돌려집니다. + */ + function safeTransferFrom(address from, address to, uint256 pizzaId) + public + { + // solium-disable-next-line arg-overflow + this.safeTransferFrom(from, to, pizzaId, ""); + } + + /** + * 주어진 토큰 ID의 소유권을 다른 주소로 안전하게 이전합니다. + * 대상 주소가 계약인 경우, `onERC721Received`를 구현해야 하며, + * 이는 안전한 전송 시 호출되고 매직 값 + * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`을 반환해야 합니다. + * 그렇지 않으면 전송이 되돌려집니다. + */ + function safeTransferFrom( + address from, + address to, + uint256 pizzaId, + bytes memory _data + ) public { + this.transferFrom(from, to, pizzaId); + require(_checkOnERC721Received(from, to, pizzaId, _data), "onERC721Received를 구현해야 합니다."); + } + + /** + * 대상 주소에서 `onERC721Received`를 호출하는 내부 함수 + * 대상 주소가 계약이 아닌 경우 호출이 실행되지 않습니다. + */ + function _checkOnERC721Received( + address from, + address to, + uint256 pizzaId, + bytes memory _data + ) internal returns (bool) { + if (!isContract(to)) { + return true; + } + + bytes4 retval = IERC721Receiver(to).onERC721Received( + msg.sender, + from, + pizzaId, + _data + ); + return (retval == _ERC721_RECEIVED); + } + + // 피자를 소각합니다 - 토큰을 완전히 파괴합니다. + // `external` 함수 제어자는 이 함수가 + // 계약 인터페이스의 일부이며 다른 계약이 호출할 수 있음을 의미합니다. + function burn(uint256 _pizzaId) external { + require(msg.sender != address(0), "유효하지 않은 주소입니다."); + require(_exists(_pizzaId), "피자가 존재하지 않습니다."); + require(_isApprovedOrOwner(msg.sender, _pizzaId), "주소가 승인되지 않았습니다."); + + ownerPizzaCount[msg.sender] = SafeMath.sub( + ownerPizzaCount[msg.sender], + 1 + ); + pizzaToOwner[_pizzaId] = address(0); + } + + // 주소별 피자 수를 반환합니다. + function balanceOf(address _owner) public view returns (uint256 _balance) { + return ownerPizzaCount[_owner]; + } + + // id로 찾은 피자의 소유자를 반환합니다. + function ownerOf(uint256 _pizzaId) public view returns (address _owner) { + address owner = pizzaToOwner[_pizzaId]; + require(owner != address(0), "유효하지 않은 피자 ID입니다."); + return owner; + } + + // 다른 주소가 피자의 소유권을 이전하도록 승인합니다. + function approve(address _to, uint256 _pizzaId) public { + require(msg.sender == pizzaToOwner[_pizzaId], "피자 소유자여야 합니다."); + pizzaApprovals[_pizzaId] = _to; + emit Approval(msg.sender, _to, _pizzaId); + } + + // 특정 피자에 대해 승인된 주소를 반환합니다. + function getApproved(uint256 _pizzaId) + public + view + returns (address operator) + { + require(_exists(_pizzaId), "피자가 존재하지 않습니다."); + return pizzaApprovals[_pizzaId]; + } + + /** + * 주어진 토큰 ID의 현재 승인을 지우는 비공개 함수 + * 주어진 주소가 토큰의 소유자가 아닌 경우 되돌립니다. + */ + function _clearApproval(address owner, uint256 _pizzaId) private { + require(pizzaToOwner[_pizzaId] == owner, "피자 소유자여야 합니다."); + require(_exists(_pizzaId), "피자가 존재하지 않습니다."); + if (pizzaApprovals[_pizzaId] != address(0)) { + pizzaApprovals[_pizzaId] = address(0); + } + } + + /* + * 주어진 운영자의 승인을 설정하거나 해제합니다. + * 운영자는 보낸 사람을 대신하여 모든 토큰을 이전할 수 있습니다. + */ + function setApprovalForAll(address to, bool approved) public { + require(to != msg.sender, "자신의 주소를 승인할 수 없습니다."); + operatorApprovals[msg.sender][to] = approved; + emit ApprovalForAll(msg.sender, to, approved); + } + + // 주어진 소유자가 운영자를 승인했는지 여부를 알려줍니다. + function isApprovedForAll(address owner, address operator) + public + view + returns (bool) + { + return operatorApprovals[owner][operator]; + } + + // 피자 소유권을 가져옵니다 - 승인된 사용자만 가능합니다. + function takeOwnership(uint256 _pizzaId) public { + require(_isApprovedOrOwner(msg.sender, _pizzaId), "주소가 승인되지 않았습니다."); + address owner = this.ownerOf(_pizzaId); + this.transferFrom(owner, msg.sender, _pizzaId); + } + + // 피자가 존재하는지 확인합니다. + function _exists(uint256 pizzaId) internal view returns (bool) { + address owner = pizzaToOwner[pizzaId]; + return owner != address(0); + } + + // 주소가 소유자인지 또는 피자를 이전하도록 승인되었는지 확인합니다. + function _isApprovedOrOwner(address spender, uint256 pizzaId) + internal + view + returns (bool) + { + address owner = pizzaToOwner[pizzaId]; + // 다음으로 인해 solium 검사를 비활성화합니다. + // https://github.com/duaraghav8/Solium/issues/175 + // solium-disable-next-line operator-whitespace + return (spender == owner || + this.getApproved(pizzaId) == spender || + this.isApprovedForAll(owner, spender)); + } + + // 피자가 고유하고 아직 존재하지 않는지 확인합니다. + modifier isUnique(string memory _name, uint256 _dna) { + bool result = true; + for (uint256 i = 0; i < pizzas.length; i++) { + if ( + keccak256(abi.encodePacked(pizzas[i].name)) == + keccak256(abi.encodePacked(_name)) && + pizzas[i].dna == _dna + ) { + result = false; + } + } + require(result, "같은 이름의 피자가 이미 존재합니다."); + _; + } + + // 대상 주소가 계약인지 여부를 반환합니다. + function isContract(address account) internal view returns (bool) { + uint256 size; + // 현재 주소에 계약이 있는지 확인하는 더 좋은 방법은 없습니다. + // 해당 주소의 코드 크기를 확인하는 것보다. + // 이것이 어떻게 작동하는지에 대한 자세한 내용은 https://ethereum.stackexchange.com/a/14016/36603을 + // 참조하세요. + // TODO Serenity 릴리스 전에 이것을 다시 확인하세요. 모든 주소가 + // 계약이 될 것이기 때문입니다. + // solium-disable-next-line security/no-inline-assembly + assembly { + size := extcodesize(account) + } + return size > 0; + } +} +``` + +## 더 읽어보기 {#further-reading} + +스마트 계약에 대한 더 완전한 개요를 원한다면 Solidity와 Vyper의 문서를 확인하세요: + +- [솔리디티](https://docs.soliditylang.org/) +- [Vyper](https://docs.vyperlang.org/en/stable/) + +## 관련 주제 {#related-topics} + +- [스마트 계약](/developers/docs/smart-contracts/) +- [이더리움 가상 머신](/developers/docs/evm/) + +## 관련 튜토리얼 {#related-tutorials} + +- [계약 크기 제한에 대응하기 위한 계약 축소](/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/) _– 스마트 계약의 크기를 줄이기 위한 몇 가지 실용적인 팁입니다._ +- [이벤트를 사용하여 스마트 계약에서 데이터 기록하기](/developers/tutorials/logging-events-smart-contracts/) _– 스마트 계약 이벤트에 대한 소개와 이를 사용하여 데이터를 기록하는 방법입니다._ +- [Solidity에서 다른 계약과 상호작용하기](/developers/tutorials/interact-with-other-contracts-from-solidity/) _– 기존 계약에서 스마트 계약을 배포하고 상호작용하는 방법입니다._ diff --git a/public/content/translations/ko/developers/docs/smart-contracts/compiling/index.md b/public/content/translations/ko/developers/docs/smart-contracts/compiling/index.md new file mode 100644 index 00000000000..4a42e91d264 --- /dev/null +++ b/public/content/translations/ko/developers/docs/smart-contracts/compiling/index.md @@ -0,0 +1,282 @@ +--- +title: "스마트 계약 컴파일" +description: "스마트 계약을 컴파일해야 하는 이유와 컴파일이 실제로 무엇을 하는지에 대한 설명입니다." +lang: ko +incomplete: true +--- + +웹 앱과 이더리움 가상 머신(EVM)이 스마트 계약을 이해할 수 있도록 하기 위해 계약을 컴파일해야 합니다. + +## 필수 구성 요소 {#prerequisites} + +컴파일에 대해 읽기 전에 [스마트 계약](/developers/docs/smart-contracts/)과 [이더리움 가상 머신](/developers/docs/evm/)에 대한 소개를 읽어보시면 도움이 될 수 있습니다. + +## EVM {#the-evm} + +[EVM](/developers/docs/evm/)이 계약을 실행하려면 바이트코드여야 합니다. 컴파일이 이 작업을 수행합니다. + +```solidity +pragma solidity 0.4.24; + +contract Greeter { + + function greet() public view returns (string memory) { + return "Hello"; + } + +} +``` + +**다음과 같이** + +``` +PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x41 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0xCFAE3217 EQ PUSH2 0x46 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x52 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x5B PUSH2 0xD6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x9B JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x80 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xC8 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x40 DUP1 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x48656C6C6F000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 POP SWAP1 JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 SLT 0xec 0xe 0xf5 0xf8 SLT 0xc7 0x2d STATICCALL ADDRESS SHR 0xdb COINBASE 0xb1 BALANCE 0xe8 0xf8 DUP14 0xda 0xad DUP13 LOG1 0x4c 0xb4 0x26 0xc2 DELEGATECALL PUSH7 0x8994D3E002900 +``` + +이를 연산 부호라고 합니다. EVM 옵코드는 이더리움 가상 머신(EVM)이 실행할 수 있는 저수준 명령어입니다. 각 옵코드는 산술 연산, 논리 연산, 데이터 조작, 제어 흐름 등을 나타냅니다. + +[연산 부호에 대해 더 알아보기](/developers/docs/evm/opcodes/) + +## 웹 애플리케이션 {#web-applications} + +컴파일러는 애플리케이션이 계약을 이해하고 계약의 함수를 호출하는 데 필요한 애플리케이션 바이너리 인터페이스(ABI)도 생성합니다. + +ABI는 배포된 계약과 스마트 계약 기능을 설명하는 JSON 파일입니다. 이는 웹2와 웹3 간의 격차를 좁히는 데 도움이 됩니다. + +[JavaScript 클라이언트 라이브러리](/developers/docs/apis/javascript/)는 웹 앱 인터페이스에서 스마트 계약을 호출할 수 있도록 ABI를 읽습니다. + +아래는 ERC-20 토큰 계약에 대한 ABI입니다. ERC-20은 이더리움에서 거래할 수 있는 토큰입니다. + +```json +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + } +] +``` + +## 더 읽어보기 {#further-reading} + +- [ABI 사양](https://solidity.readthedocs.io/en/v0.7.0/abi-spec.html) _– Solidity_ + +## 관련 주제 {#related-topics} + +- [JavaScript 클라이언트 라이브러리](/developers/docs/apis/javascript/) +- [이더리움 가상 머신](/developers/docs/evm/) diff --git a/public/content/translations/ko/developers/docs/smart-contracts/composability/index.md b/public/content/translations/ko/developers/docs/smart-contracts/composability/index.md new file mode 100644 index 00000000000..562f20c0765 --- /dev/null +++ b/public/content/translations/ko/developers/docs/smart-contracts/composability/index.md @@ -0,0 +1,76 @@ +--- +title: "스마트 계약 구성 가능성" +description: "스마트 계약이 레고 블록처럼 결합되어 기존 구성 요소를 재사용하여 복잡한 탈중앙화앱을 구축하는 방법을 알아보세요." +lang: ko +incomplete: true +--- + +## 간단한 소개 {#a-brief-introduction} + +스마트 컨트랙트는 이더리움 상에서 공개되어 오픈 API처럼 생각할 수 있습니다. dapp 개발자가 되기 위해서는 직접 스마트 계약을 작성할 필요가 없습니다. 계약과 상호작용하는 방법만 알면 됩니다. 예를 들어, 탈중앙화 거래소인 [Uniswap](https://uniswap.exchange/swap)의 기존 스마트 계약을 사용하여 앱의 모든 토큰 스왑 로직을 처리할 수 있습니다. 처음부터 시작할 필요가 없습니다. [v2](https://github.com/Uniswap/uniswap-v2-core/tree/master/contracts) 및 [v3](https://github.com/Uniswap/uniswap-v3-core/tree/main/contracts) 계약 중 일부를 확인해 보세요. + +## 구성 가능성이란? {#what-is-composability} + +구성 가능성이란 별개의 구성 요소를 결합하여 새로운 시스템이나 출력을 생성하는 것입니다. 소프트웨어 개발에서 구성 가능성은 개발자가 기존 소프트웨어 구성 요소를 재사용하여 새로운 애플리케이션을 구축할 수 있음을 의미합니다. 구성 가능성을 이해하는 좋은 방법은 구성 요소를 레고 블록으로 생각하는 것입니다. 각 레고 블록은 다른 블록과 결합될 수 있으며, 서로 다른 레고 블록을 결합하여 복잡한 구조를 만들 수 있습니다. + +이더리움에서는 모든 스마트 계약이 일종의 레고입니다. 다른 프로젝트의 스마트 계약을 사용하여 프로젝트의 구성 요소로 사용할 수 있습니다. 이는 기본 기능을 처음부터 다시 만들 필요가 없다는 것을 의미합니다. + +## 구성 가능성은 어떻게 작동합니까? {#how-does-composability-work} + +이더리움 스마트 계약은 공개 API와 같아서 누구나 계약과 상호작용하거나 이를 dapp에 통합하여 기능을 추가할 수 있습니다. 스마트 계약 구성 가능성은 주로 세 가지 원칙에 따라 작동합니다: 모듈성, 자율성, 검색 가능성: + +**1.** **모듈성**: 개별 구성 요소가 특정 작업을 수행할 수 있는 능력입니다. 이더리움에서는 모든 스마트 계약이 특정 사용 사례를 가지고 있습니다(유니스왑 예시에서 보여준 것처럼). + +**2.** **자율성**: 구성 가능한 구성 요소는 독립적으로 작동할 수 있어야 합니다. 이더리움의 각 스마트 계약은 스스로 실행되며 시스템의 다른 부분에 의존하지 않고도 작동할 수 있습니다. + +**3.** **검색 가능성**: 외부 계약이나 소프트웨어 라이브러리가 공개적으로 사용 가능하지 않은 경우 개발자가 이를 호출하거나 애플리케이션에 통합할 수 없습니다. 스마트 계약은 기본적으로 오픈소스입니다. 누구나 스마트 계약을 호출하거나 코드베이스를 포크할 수 있습니다. + +## 구성 가능성의 이점 {#benefits-of-composability} + +### 개발 주기 단축 {#shorter-development-cycle} + +구성 가능성은 개발자가 [탈중앙화앱](/apps/#what-are-dapps)을 만들 때 해야 할 작업을 줄여줍니다. [Naval Ravikant가 말했듯이:](https://twitter.com/naval/status/1444366754650656770) "오픈 소스는 모든 문제를 한 번만 해결하면 된다는 것을 의미합니다." + +어떤 문제를 해결하는 스마트 계약이 있다면, 다른 개발자들은 그것을 재사용할 수 있으므로 같은 문제를 다시 해결할 필요가 없습니다. 이 방법으로 개발자는 기존 소프트웨어 라이브러리를 사용하여 새로운 dapp을 만들기 위해 추가 기능을 추가할 수 있습니다. + +### 혁신 증대 {#greater-innovation} + +구성 가능성은 개발자가 오픈소스 코드를 자유롭게 재사용, 수정, 복제 또는 통합하여 원하는 결과를 만들 수 있기 때문에 혁신과 실험을 장려합니다. 결과적으로 개발 팀은 기본 기능에 더 적은 시간을 할애하고 새로운 기능을 실험하는 데 더 많은 시간을 할애할 수 있습니다. + +### 더 나은 사용자 경험 {#better-user-experience} + +이더리움 생태계의 구성 요소 간 상호 운용성은 사용자 경험을 향상시킵니다. dapp이 외부 스마트 계약을 통합하면 사용자들은 더 큰 기능을 사용할 수 있습니다. + +우리는 상호 운용성의 이점을 설명하기 위해 차익 거래의 예를 사용할 것입니다: + +`exchange A`에서 토큰이 `exchange B`보다 더 높은 가격으로 거래된다면, 가격 차이를 이용해 수익을 낼 수 있습니다. 하지만 거래에 자금을 댈 충분한 자본이 있는 경우에만 가능합니다(즉, `exchange B`에서 토큰을 구매하여 `exchange A`에 판매하는 것). + +거래 자금을 충분히 확보하지 못한 경우, 플래시 론이 적합할 수 있습니다. [플래시 론](/defi/#flash-loans)은 고도로 기술적이지만, 기본 개념은 (담보 없이) 자산을 빌리고 _하나의_ 거래 내에서 동일한 자산을 반환할 수 있다는 것입니다. + +처음의 예시로 돌아가서, 차익 거래자는 대규모 플래시 론을 받아 `exchange B`에서 토큰을 구매하고 `exchange A`에서 판매한 후, 동일한 거래 내에서 원금과 이자를 상환하고 수익을 챙길 수 있습니다. 이러한 복잡한 로직은 여러 계약에 대한 호출을 결합해야 하며, 이는 스마트 계약이 상호운용성이 부족할 경우 불가능할 것입니다. + +## 이더리움의 구성 가능성 예시 {#composability-in-ethereum} + +### 토큰 스왑 {#token-swaps} + +ETH로 거래 비용을 지불해야 하는 Dapp을 생성하는 경우, 토큰 교환 로직을 통합하여 사용자가 다른 ERC-20 토큰으로 지불할 수 있도록 할 수 있습니다. 코드는 사용자의 토큰을 ETH로 자동 변환한 후 계약이 호출된 기능을 실행할 수 있습니다. + +### 거버넌스 {#governance} + +[DAO](/dao/)를 위한 맞춤형 거버넌스 시스템을 구축하는 것은 비용과 시간이 많이 소요될 수 있습니다. 대신 [Aragon Client](https://client.aragon.org/)와 같은 오픈소스 거버넌스 툴킷을 사용하여 DAO를 부트스트랩하고 거버넌스 프레임워크를 신속하게 만들 수 있습니다. + +### 신원 관리 {#identity-management} + +맞춤 인증 시스템을 구축하거나 중앙 집중식 제공자에 의존하는 대신, 분산된 신원 (DID) 도구를 통합하여 사용자 인증을 관리할 수 있습니다. 예를 들어 [SpruceID](https://www.spruceid.com/)는 사용자가 이더리움 지갑으로 신원을 인증할 수 있도록 하는 "이더리움으로 로그인" 기능을 제공하는 오픈소스 툴킷입니다. + +## 관련 튜토리얼 {#related-tutorials} + +- [create-eth-app으로 탈중앙화앱 프론트엔드 개발 시작하기](/developers/tutorials/kickstart-your-dapp-frontend-development-with-create-eth-app/) _– create-eth-app을 사용하여 인기 있는 스마트 계약이 포함된 앱을 바로 만드는 방법에 대한 개요입니다._ + +## 더 읽어보기 {#further-reading} + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +- [구성 가능성은 혁신이다](https://a16zcrypto.com/posts/article/how-composability-unlocks-crypto-and-everything-else/) +- [웹3에서 구성 가능성이 중요한 이유](https://hackernoon.com/why-composability-matters-for-web3) +- [구성 가능성이란 무엇인가?](https://blog.aragon.org/what-is-composability/#:~:text=Aragon,connect%20to%20every%20other%20piece.) diff --git a/public/content/translations/ko/developers/docs/smart-contracts/deploying/index.md b/public/content/translations/ko/developers/docs/smart-contracts/deploying/index.md new file mode 100644 index 00000000000..0b24afc72f4 --- /dev/null +++ b/public/content/translations/ko/developers/docs/smart-contracts/deploying/index.md @@ -0,0 +1,81 @@ +--- +title: "스마트 컨트랙트 배포" +description: "필수 구성 요소, 도구, 배포 단계를 포함하여 이더리움 네트워크에 스마트 계약을 배포하는 방법을 알아보세요." +lang: ko +--- + +이더리움 네트워크 유저들이 스마트 계약을 이용할 수 있으려면 스마트계약 배포를 마쳐야 합니다. + +스마트 계약 배포는 컴파일된 코드를 포함하는 이더리움 거래를 받는 이를 지정하지 않고 보내는 식으로 이루어 집니다. + +## 필수 구성 요소 {#prerequisites} + +스마트 계약을 배포하기 전에 [이더리움 네트워크](/developers/docs/networks/), [거래](/developers/docs/transactions/) 및 [스마트 계약의 구조](/developers/docs/smart-contracts/anatomy/)를 이해해야 합니다. + +계약은 블록체인에 저장되므로 배포 시 이더(ETH)가 필요합니다. 따라서 이더리움의 [가스 및 수수료](/developers/docs/gas/)에 대해 잘 알고 있어야 합니다. + +마지막으로, 계약을 배포하기 전에 컴파일해야 하므로 [스마트 계약 컴파일](/developers/docs/smart-contracts/compiling/)에 대해 읽어보시기 바랍니다. + +## 스마트 계약 배포 방법 {#how-to-deploy-a-smart-contract} + +### 필요한 것 {#what-youll-need} + +- 계약의 바이트코드 – [컴파일](/developers/docs/smart-contracts/compiling/)을 통해 생성됩니다. +- 가스비(이더) - 일반 거래처럼 가스 한도를 설정이 필요합니다. 그러나 일반 거래보다는 계약 배포가 더 많은 가스 한도를 설정하십시오. +- 배포 스크립트 또는 플러그인 +- 자체 노드 실행, 공용 노드 연결, 또는 [노드 서비스](/developers/docs/nodes-and-clients/nodes-as-a-service/)의 API 키를 통한 [이더리움 노드](/developers/docs/nodes-and-clients/) 액세스 + +### 스마트 계약 배포 단계 {#steps-to-deploy} + +구체적인 단계는 개발 프레임워크에 따라 다릅니다. 예를 들어, [계약 배포에 관한 Hardhat 문서](https://hardhat.org/docs/tutorial/deploying) 또는 [스마트 계약 배포 및 검증에 관한 Foundry 문서](https://book.getfoundry.sh/forge/deploying)를 확인할 수 있습니다. 배포되면 계약은 다른 [계정](/developers/docs/accounts/)과 마찬가지로 이더리움 주소를 갖게 되며, [소스 코드 검증 도구](/developers/docs/smart-contracts/verifying/#source-code-verification-tools)를 사용하여 확인할 수 있습니다. + +## 관련 도구 {#related-tools} + +**Remix - _Remix IDE는 이더리움과 같은 블록체인을 위한 스마트 계약을 개발, 배포 및 관리할 수 있도록 지원합니다_** + +- [Remix](https://remix.ethereum.org) + +**Tenderly - _스마트 계약을 개발, 테스트, 모니터링, 운영하기 위한 디버깅, 관찰 가능성 및 인프라 구성 요소를 제공하는 Web3 개발 플랫폼_** + +- [tenderly.co](https://tenderly.co/) +- [문서](https://docs.tenderly.co/) +- [GitHub](https://github.com/Tenderly) +- [Discord](https://discord.gg/eCWjuvt) + +**Hardhat - _이더리움 소프트웨어를 컴파일, 배포, 테스트 및 디버그할 수 있는 개발 환경_** + +- [hardhat.org](https://hardhat.org/getting-started/) +- [계약 배포에 관한 문서](https://hardhat.org/docs/tutorial/deploying) +- [GitHub](https://github.com/nomiclabs/hardhat) +- [Discord](https://discord.com/invite/TETZs2KK4k) + +**thirdweb - _단일 명령어로 모든 EVM 호환 체인에 계약을 쉽게 배포하세요_** + +- [문서](https://portal.thirdweb.com/deploy/) + +**Crossmint - _엔터프라이즈급 웹3 개발 플랫폼으로 스마트 계약을 배포하고, 신용카드 및 크로스체인 결제를 활성화하며, API를 사용하여 NFT를 생성, 배포, 판매, 저장 및 편집할 수 있습니다._** + +- [crossmint.com](https://www.crossmint.com) +- [개발문서](https://docs.crossmint.com) +- [Discord](https://discord.com/invite/crossmint) +- [블로그](https://blog.crossmint.com) + +## 관련 튜토리얼 {#related-tutorials} + +- [첫 번째 스마트 계약 배포하기](/developers/tutorials/deploying-your-first-smart-contract/) _– 이더리움 테스트넷에 첫 번째 스마트 계약을 배포하는 방법을 소개합니다._ +- [Hello World | 스마트 계약 튜토리얼](/developers/tutorials/hello-world-smart-contract/) _– 이더리움에 기본적인 스마트 계약을 생성 및 배포하는, 따라하기 쉬운 튜토리얼입니다._ +- [Solidity에서 다른 계약과 상호작용하기](/developers/tutorials/interact-with-other-contracts-from-solidity/) _– 기존 계약에서 스마트 계약을 배포하고 상호작용하는 방법입니다._ +- [계약 크기 줄이는 방법](/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/) _- 계약 크기를 제한 아래로 줄여 가스를 절약하는 방법_ + +## 더 읽어보기 {#further-reading} + +- [https://docs.openzeppelin.com/learn/deploying-and-interacting](https://docs.openzeppelin.com/learn/deploying-and-interacting) - _OpenZeppelin_ +- [Hardhat으로 계약 배포하기](https://hardhat.org/docs/tutorial/deploying) - _Nomic Labs_ + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 관련 주제 {#related-topics} + +- [개발 프레임워크](/developers/docs/frameworks/) +- [이더리움 노드 실행하기](/developers/docs/nodes-and-clients/run-a-node/) +- [서비스형 노드](/developers/docs/nodes-and-clients/nodes-as-a-service) diff --git a/public/content/translations/ko/developers/docs/smart-contracts/formal-verification/index.md b/public/content/translations/ko/developers/docs/smart-contracts/formal-verification/index.md new file mode 100644 index 00000000000..6fb738e6963 --- /dev/null +++ b/public/content/translations/ko/developers/docs/smart-contracts/formal-verification/index.md @@ -0,0 +1,284 @@ +--- +title: "스마트 계약의 형식 검증" +description: "이더리움 스마트 계약을 위한 형식 검증 개요" +lang: ko +--- + +[스마트 계약](/developers/docs/smart-contracts/)은 새로운 사용 사례를 제시하고 사용자에게 가치를 창출하는 탈중앙화되고 신뢰가 필요 없으며 견고한 애플리케이션을 만들 수 있도록 합니다. 스마트 계약은 막대한 가치를 다루기 때문에 보안은 개발자에게 매우 중요한 고려 사항입니다. + +형식 검증은 [스마트 계약 보안](/developers/docs/smart-contracts/security/)을 향상시키기 위해 권장되는 기술 중 하나입니다. 프로그램을 명시하고, 설계하고, 검증하기 위해 [형식적 방법](https://www.brookings.edu/techstream/formal-methods-as-a-path-toward-better-cybersecurity/)을 사용하는 형식 검증은 수년 동안 중요한 하드웨어 및 소프트웨어 시스템의 정확성을 보장하는 데 사용되어 왔습니다. + +스마트 계약에 구현될 때, 형식 검증은 계약의 비즈니스 로직이 사전에 정의된 사양을 충족함을 증명할 수 있습니다. 테스트와 같이 계약 코드의 정확성을 평가하는 다른 방법에 비해 형식 검증은 스마트 계약이 기능적으로 올바르다는 것을 더 강력하게 보장합니다. + +## 형식 검증이란 무엇인가요? {#what-is-formal-verification} + +형식 검증은 형식 사양에 대한 시스템의 정확성을 평가하는 과정을 의미합니다. 간단히 말해 형식 검증을 통해 시스템의 동작이 일부 요구 사항을 충족하는지(즉, 원하는 대로 작동하는지) 확인할 수 있습니다. + +시스템(이 경우 스마트 계약)의 예상 동작은 형식 모델링을 사용하여 설명되는 반면, 사양 언어는 형식적 속성을 생성할 수 있도록 합니다. 형식 검증 기술은 계약의 구현이 해당 사양을 준수하는지 검증하고 전자의 정확성에 대한 수학적 증명을 도출할 수 있습니다. 계약이 사양을 충족하면 '기능적으로 올바름', '설계에 따라 올바름' 또는 '구성에 따라 올바름'으로 설명됩니다. + +### 형식 모델이란 무엇인가요? {#what-is-a-formal-model} + +컴퓨터 과학에서 [형식 모델](https://en.wikipedia.org/wiki/Model_of_computation)은 계산 과정에 대한 수학적 설명입니다. 프로그램은 수학적 함수(방정식)로 추상화되며, 모델은 입력이 주어졌을 때 함수에 대한 출력이 어떻게 계산되는지를 설명합니다. + +형식 모델은 프로그램의 동작 분석을 평가할 수 있는 추상화 수준을 제공합니다. 형식 모델의 존재는 해당 모델의 바람직한 속성을 설명하는 형식 사양을 생성할 수 있게 합니다. + +형식 검증을 위해 스마트 계약을 모델링하는 데는 여러 기술이 사용됩니다. 예를 들어, 일부 모델은 스마트 계약의 상위 수준 동작에 대해 추론하는 데 사용됩니다. 이러한 모델링 기술은 스마트 계약에 블랙박스 관점을 적용하여, 입력을 수락하고 해당 입력을 기반으로 계산을 실행하는 시스템으로 봅니다. + +상위 수준 모델은 스마트 계약과 외부 소유 계정(EOA), 계약 계정, 블록체인 환경과 같은 외부 에이전트 간의 관계에 중점을 둡니다. 이러한 모델은 특정 사용자 상호 작용에 대한 계약의 동작 방식을 지정하는 속성을 정의하는 데 유용합니다. + +반대로, 다른 형식 모델은 스마트 계약의 하위 수준 동작에 중점을 둡니다. 상위 수준 모델은 계약의 기능에 대한 추론에 도움이 될 수 있지만, 구현의 내부 작동에 대한 세부 정보를 포착하지 못할 수 있습니다. 하위 수준 모델은 프로그램 분석에 화이트박스 관점을 적용하고 프로그램 추적 및 [제어 흐름 그래프](https://en.wikipedia.org/wiki/Control-flow_graph)와 같은 스마트 계약 애플리케이션의 하위 수준 표현에 의존하여 계약 실행과 관련된 속성을 추론합니다. + +하위 수준 모델은 이더리움의 실행 환경(즉, [EVM](/developers/docs/evm/))에서 스마트 계약의 실제 실행을 나타내므로 이상적인 것으로 간주됩니다. 하위 수준 모델링 기술은 스마트 계약에서 중요한 안전 속성을 설정하고 잠재적인 취약점을 감지하는 데 특히 유용합니다. + +### 형식 사양이란 무엇인가요? {#what-is-a-formal-specification} + +사양은 특정 시스템이 충족해야 하는 기술적 요구 사항입니다. 프로그래밍에서 사양은 프로그램 실행에 대한 일반적인 아이디어(즉, 프로그램이 무엇을 해야 하는지)를 나타냅니다. + +스마트 계약의 맥락에서 형식 사양은 계약이 충족해야 하는 요구 사항에 대한 형식적 설명인 속성을 의미합니다. 이러한 속성은 '불변성'으로 설명되며 예외 없이 모든 가능한 상황에서 참으로 유지되어야 하는 계약 실행에 대한 논리적 주장을 나타냅니다. + +따라서 형식 사양을 스마트 계약의 의도된 실행을 설명하는 형식 언어로 작성된 문장의 모음으로 생각할 수 있습니다. 사양은 계약의 속성을 다루고 다양한 상황에서 계약이 어떻게 작동해야 하는지 정의합니다. 형식 검증의 목적은 스마트 계약이 이러한 속성(불변성)을 소유하고 있는지, 그리고 이러한 속성이 실행 중에 위반되지 않는지를 확인하는 것입니다. + +형식 사양은 스마트 계약의 보안 구현을 개발하는 데 중요합니다. 불변성을 구현하지 못하거나 실행 중에 속성이 위반된 계약은 기능을 손상시키거나 악의적인 익스플로잇을 유발할 수 있는 취약점에 노출되기 쉽습니다. + +## 스마트 계약의 형식 사양 유형 {#formal-specifications-for-smart-contracts} + +형식 사양을 통해 프로그램 실행의 정확성에 대한 수학적 추론이 가능합니다. 형식 모델과 마찬가지로 형식 사양은 계약 구현의 상위 수준 속성이나 하위 수준 동작을 포착할 수 있습니다. + +형식 사양은 프로그램의 속성에 대한 형식적 추론을 허용하는 [프로그램 논리](https://en.wikipedia.org/wiki/Logic_programming)의 요소를 사용하여 파생됩니다. 프로그램 논리에는 프로그램의 예상 동작을 (수학적 언어로) 표현하는 형식 규칙이 있습니다. [도달 가능성 논리](https://en.wikipedia.org/wiki/Reachability_problem), [시간 논리](https://en.wikipedia.org/wiki/Temporal_logic), [호어 논리](https://en.wikipedia.org/wiki/Hoare_logic)를 포함하여 형식 사양을 만드는 데 다양한 프로그램 논리가 사용됩니다. + +스마트 계약에 대한 형식 사양은 크게 **상위 수준** 또는 **하위 수준** 사양으로 분류할 수 있습니다. 사양이 속한 범주에 관계없이 분석 중인 시스템의 속성을 적절하고 명확하게 설명해야 합니다. + +### 상위 수준 사양 {#high-level-specifications} + +이름에서 알 수 있듯이 상위 수준 사양('모델 지향 사양'이라고도 함)은 프로그램의 상위 수준 동작을 설명합니다. 상위 수준 사양은 스마트 계약을 작업을 수행하여 상태 간에 전환할 수 있는 [유한 상태 머신](https://en.wikipedia.org/wiki/Finite-state_machine)(FSM)으로 모델링하며, 시간 논리를 사용하여 FSM 모델의 형식적 속성을 정의합니다. + +[시간 논리](https://en.wikipedia.org/wiki/Temporal_logic)는 '시간의 관점에서 한정된 명제에 대해 추론하기 위한 규칙(예: '나는 _항상_ 배고프다' 또는 '나는 _결국_ 배고플 것이다')'입니다. 형식 검증에 적용될 때, 시간 논리는 상태 머신으로 모델링된 시스템의 올바른 동작에 대한 주장을 진술하는 데 사용됩니다. 특히, 시간 논리는 스마트 계약이 있을 수 있는 미래 상태와 상태 간 전환 방법을 설명합니다. + +상위 수준 사양은 일반적으로 스마트 계약에 대한 두 가지 중요한 시간적 속성인 안전성활성을 포착합니다. 안전성 속성은 '나쁜 일은 절대 일어나지 않는다'는 아이디어를 나타내며 일반적으로 불변성을 표현합니다. 안전성 속성은 [교착 상태](https://www.techtarget.com/whatis/definition/deadlock)로부터의 자유와 같은 일반적인 소프트웨어 요구 사항을 정의하거나 계약에 대한 도메인별 속성(예: 함수에 대한 접근 제어의 불변성, 상태 변수의 허용 값 또는 토큰 전송 조건)을 표현할 수 있습니다. + +예를 들어, ERC-20 토큰 계약에서 `transfer()` 또는 `transferFrom()` 사용 조건을 다루는 다음과 같은 안전성 요구 사항을 살펴보겠습니다. _'전송자의 잔액은 전송 요청된 토큰의 양보다 결코 낮아서는 안 된다.'_ 계약 불변성에 대한 이 자연어 설명은 형식(수학적) 사양으로 변환될 수 있으며, 그 후 유효성을 엄격하게 확인할 수 있습니다. + +활성 속성은 '결국 좋은 일이 일어난다'고 주장하며, 계약이 여러 상태를 거쳐 진행할 수 있는 능력과 관련이 있습니다. 활성 속성의 예로는 '유동성'이 있으며, 이는 요청 시 사용자에게 잔액을 전송하는 계약의 능력을 의미합니다. [Parity 지갑 사건](https://www.cnbc.com/2017/11/08/accidental-bug-may-have-frozen-280-worth-of-ether-on-parity-wallet.html)에서 발생했던 것처럼 이 속성이 위반되면 사용자는 계약에 저장된 자산을 인출할 수 없게 됩니다. + +### 하위 수준 사양 {#low-level-specifications} + +상위 수준 사양은 계약의 유한 상태 모델을 시작점으로 삼고 이 모델의 바람직한 속성을 정의합니다. 이와 대조적으로 하위 수준 사양('속성 지향 사양'이라고도 함)은 종종 프로그램(스마트 계약)을 수학적 함수 모음으로 구성된 시스템으로 모델링하고 이러한 시스템의 올바른 동작을 설명합니다. + +간단히 말해, 하위 수준 사양은 프로그램 추적을 분석하고 이러한 추적을 통해 스마트 계약의 속성을 정의하려고 시도합니다. 추적은 스마트 계약의 상태를 변경하는 함수 실행 시퀀스를 의미합니다. 따라서 하위 수준 사양은 계약의 내부 실행에 대한 요구 사항을 지정하는 데 도움이 됩니다. + +하위 수준 형식 사양은 호어 스타일 속성 또는 실행 경로에 대한 불변성으로 주어질 수 있습니다. + +### 호어 스타일 속성 {#hoare-style-properties} + +[호어 논리](https://en.wikipedia.org/wiki/Hoare_logic)는 스마트 계약을 포함한 프로그램의 정확성에 대해 추론하기 위한 일련의 형식 규칙을 제공합니다. 호어 스타일 속성은 호어 삼중항 `{P}c{Q}`로 표시됩니다. 여기서 `c`는 프로그램이고 `P`와 `Q`는 `c`의 상태(즉, 프로그램)에 대한 술어이며, 각각 공식적으로 사전 조건사후 조건으로 설명됩니다. + +사전 조건은 함수의 올바른 실행에 필요한 조건을 설명하는 술어입니다. 계약을 호출하는 사용자는 이 요구 사항을 충족해야 합니다. 사후 조건은 함수가 올바르게 실행될 경우 함수가 설정하는 조건을 설명하는 술어입니다. 사용자는 함수를 호출한 후 이 조건이 참일 것으로 기대할 수 있습니다. 호어 논리에서 불변성은 함수 실행에 의해 보존되는(즉, 변경되지 않는) 술어입니다. + +호어 스타일 사양은 _부분적 정확성_ 또는 전체 정확성을 보장할 수 있습니다. 계약 함수의 구현은 함수가 실행되기 전에 사전 조건이 참이고 실행이 종료되면 사후 조건도 참인 경우 '부분적으로 올바름'입니다. 함수가 실행되기 전에 사전 조건이 참이고, 실행이 종료되는 것이 보장되며, 종료될 때 사후 조건이 참이면 전체 정확성의 증명이 얻어집니다. + +일부 실행은 종료되기 전에 지연되거나 전혀 종료되지 않을 수 있으므로 전체 정확성의 증명을 얻는 것은 어렵습니다. 즉, 이더리움의 가스 메커니즘이 무한 프로그램 루프를 방지하므로(실행이 성공적으로 종료되거나 '가스 부족' 오류로 인해 종료됨) 실행이 종료되는지 여부는 논란의 여지가 있는 문제입니다. + +호어 논리를 사용하여 생성된 스마트 계약 사양에는 계약의 함수 및 루프 실행에 대해 정의된 사전 조건, 사후 조건 및 불변성이 포함됩니다. 사전 조건에는 종종 함수에 대한 잘못된 입력 가능성이 포함되며, 사후 조건은 이러한 입력에 대한 예상 응답(예: 특정 예외 발생)을 설명합니다. 이러한 방식으로 호어 스타일 속성은 계약 구현의 정확성을 보장하는 데 효과적입니다. + +많은 형식 검증 프레임워크는 함수의 의미론적 정확성을 증명하기 위해 호어 스타일 사양을 사용합니다. 또한 솔리디티의 `require` 및 `assert` 문을 사용하여 호어 스타일 속성(어설션으로)을 계약 코드에 직접 추가할 수도 있습니다. + +`require` 문은 사전 조건 또는 불변성을 표현하며 종종 사용자 입력을 검증하는 데 사용되는 반면, `assert`는 안전에 필요한 사후 조건을 포착합니다. 예를 들어, 호출하는 계정의 ID에 대한 사전 조건 확인으로 `require`를 사용하여 함수에 대한 적절한 접근 제어(안전성 속성의 예)를 달성할 수 있습니다. 마찬가지로, 계약의 상태 변수 허용 값에 대한 불변성(예: 유통 중인 총 토큰 수)은 함수 실행 후 계약의 상태를 확인하기 위해 `assert`를 사용하여 위반으로부터 보호될 수 있습니다. + +### 추적 수준 속성 {#trace-level-properties} + +추적 기반 사양은 계약을 여러 상태 간에 전환하는 작업과 이러한 작업 간의 관계를 설명합니다. 앞서 설명했듯이 추적은 특정 방식으로 계약의 상태를 변경하는 작업의 시퀀스입니다. + +이 접근 방식은 미리 정의된 전환 집합(계약 함수에 의해 설명됨)과 함께 일부 미리 정의된 상태(상태 변수에 의해 설명됨)를 가진 상태 전환 시스템으로서의 스마트 계약 모델에 의존합니다. 또한, 프로그램의 실행 흐름을 그래픽으로 표현한 [제어 흐름 그래프](https://www.geeksforgeeks.org/software-engineering-control-flow-graph-cfg/)(CFG)가 계약의 운영 의미론을 설명하는 데 자주 사용됩니다. 여기서 각 추적은 제어 흐름 그래프의 경로로 표시됩니다. + +주로 추적 수준 사양은 스마트 계약의 내부 실행 패턴에 대해 추론하는 데 사용됩니다. 추적 수준 사양을 생성함으로써 스마트 계약에 대한 허용 가능한 실행 경로(즉, 상태 전환)를 주장합니다. 기호 실행과 같은 기술을 사용하여 형식 모델에 정의되지 않은 경로를 실행이 따르지 않음을 형식적으로 검증할 수 있습니다. + +[DAO](/dao/) 계약의 예를 사용하여 추적 수준 속성을 설명해 보겠습니다. 이 계약에는 공개적으로 접근 가능한 몇 가지 기능이 있습니다. 여기서는 DAO 계약이 사용자가 다음 작업을 수행할 수 있도록 허용한다고 가정합니다. + +- 자금 예치 + +- 자금 예치 후 제안에 투표 + +- 제안에 투표하지 않으면 환불 요청 + +추적 수준 속성의 예로는 _'자금을 예치하지 않은 사용자는 제안에 투표할 수 없음'_ 또는 '제안에 투표하지 않은 사용자는 항상 환불을 요청할 수 있어야 함'이 있습니다. 두 속성 모두 선호되는 실행 순서를 주장합니다(투표는 자금을 예치하기 에 발생할 수 없으며 환불 요청은 제안에 투표한 에 발생할 수 없습니다). + +## 스마트 계약의 형식 검증 기술 {#formal-verification-techniques} + +### 모델 체킹 {#model-checking} + +모델 체킹은 알고리즘이 스마트 계약의 형식 모델을 해당 사양과 대조하여 확인하는 형식 검증 기술입니다. 모델 체킹에서 스마트 계약은 종종 상태 전환 시스템으로 표현되며, 허용 가능한 계약 상태에 대한 속성은 시간 논리를 사용하여 정의됩니다. + +모델 체킹은 시스템(즉, 계약)의 추상적인 수학적 표현을 생성하고 [명제 논리](https://www.baeldung.com/cs/propositional-logic)에 기반한 공식을 사용하여 이 시스템의 속성을 표현해야 합니다. 이는 모델 체킹 알고리즘의 작업, 즉 수학적 모델이 주어진 논리 공식을 만족함을 증명하는 작업을 단순화합니다. + +형식 검증에서의 모델 체킹은 주로 시간 경과에 따른 계약의 동작을 설명하는 시간적 속성을 평가하는 데 사용됩니다. 스마트 계약의 시간적 속성에는 이전에 설명한 안전성활성이 포함됩니다. + +예를 들어, 접근 제어와 관련된 보안 속성(예: _계약 소유자만 `selfdestruct`를 호출할 수 있음_)은 형식 논리로 작성할 수 있습니다. 그 후, 모델 체킹 알고리즘은 계약이 이 형식 사양을 만족하는지 검증할 수 있습니다. + +모델 체킹은 상태 공간 탐색을 사용하며, 이는 스마트 계약의 모든 가능한 상태를 구성하고 속성 위반을 초래하는 도달 가능한 상태를 찾으려고 시도하는 것을 포함합니다. 그러나 이는 무한한 수의 상태( '상태 폭발 문제'로 알려짐)로 이어질 수 있으므로, 모델 체커는 스마트 계약의 효율적인 분석을 가능하게 하기 위해 추상화 기술에 의존합니다. + +### 정리 증명 {#theorem-proving} + +정리 증명은 스마트 계약을 포함한 프로그램의 정확성에 대해 수학적으로 추론하는 방법입니다. 계약 시스템의 모델과 해당 사양을 수학 공식(논리 문)으로 변환하는 과정이 포함됩니다. + +정리 증명의 목표는 이러한 문장 간의 논리적 동등성을 검증하는 것입니다. '논리적 동등성'('논리적 쌍방함의'라고도 함)은 첫 번째 문장이 참일 _경우에만_ 두 번째 문장이 참이 되는 두 문장 사이의 관계 유형입니다. + +계약 모델과 그 속성에 대한 문장 간의 필요한 관계(논리적 동등성)는 증명 가능한 문장(정리라고 함)으로 공식화됩니다. 형식적 추론 시스템을 사용하여 자동 정리 증명기는 정리의 유효성을 검증할 수 있습니다. 즉, 정리 증명기는 스마트 계약의 모델이 해당 사양과 정확히 일치함을 결정적으로 증명할 수 있습니다. + +모델 체킹은 계약을 유한 상태를 가진 전환 시스템으로 모델링하는 반면, 정리 증명은 무한 상태 시스템의 분석을 처리할 수 있습니다. 그러나 이는 자동 정리 증명기가 논리 문제가 '결정 가능'한지 여부를 항상 알 수 없다는 것을 의미합니다. + +결과적으로, 정리 증명기가 정확성 증명을 도출하도록 안내하기 위해 종종 인간의 도움이 필요합니다. 정리 증명에 인간의 노력을 사용하는 것은 완전히 자동화된 모델 체킹보다 사용 비용이 더 비쌉니다. + +### 기호 실행 {#symbolic-execution} + +기호 실행은 _구체적인 값_(예: `x == 5`) 대신 _기호 값_(예: `x > 5`)을 사용하여 함수를 실행함으로써 스마트 계약을 분석하는 방법입니다. 형식 검증 기술로서 기호 실행은 계약 코드의 추적 수준 속성에 대해 형식적으로 추론하는 데 사용됩니다. + +기호 실행은 실행 추적을 기호 입력 값에 대한 수학 공식으로 나타내며, 이를 경로 술어라고도 합니다. [SMT 솔버](https://en.wikipedia.org/wiki/Satisfiability_modulo_theories)는 경로 술어가 '만족 가능'한지(즉, 공식을 만족할 수 있는 값이 존재하는지) 확인하는 데 사용됩니다. 취약한 경로가 만족 가능하면, SMT 솔버는 실행을 해당 경로로 유도하는 구체적인 값을 생성합니다. + +스마트 계약의 함수가 `uint` 값(`x`)을 입력으로 받고 `x`가 `5`보다 크고 `10`보다 작을 때 되돌린다고 가정해 보겠습니다. 일반적인 테스트 절차를 사용하여 오류를 유발하는 `x` 값을 찾는 것은 오류를 유발하는 입력을 실제로 찾을 수 있다는 보장 없이 수십 개(또는 그 이상)의 테스트 사례를 실행해야 합니다. + +반대로, 기호 실행 도구는 기호 값 `X > 5 ∧ X < 10` (즉, `x`가 5보다 크고 10보다 작음)으로 함수를 실행합니다. 연관된 경로 술어 `x = X > 5 ∧ X < 10`은 해결을 위해 SMT 솔버에 주어집니다. 특정 값이 `x = X > 5 ∧ X < 10` 공식을 만족하면 SMT 솔버가 이를 계산합니다. 예를 들어, 솔버는 `x`의 값으로 `7`을 생성할 수 있습니다. + +기호 실행은 프로그램에 대한 입력에 의존하고, 도달 가능한 모든 상태를 탐색하기 위한 입력 집합은 잠재적으로 무한하므로 여전히 테스트의 한 형태입니다. 그러나 예에서 보듯이, 기호 실행은 속성 위반을 유발하는 입력을 찾는 데 있어 일반적인 테스트보다 더 효율적입니다. + +또한, 기호 실행은 함수에 대한 입력을 무작위로 생성하는 다른 속성 기반 기술(예: 퍼징)보다 거짓 양성이 적습니다. 기호 실행 중에 오류 상태가 트리거되면, 오류를 트리거하는 구체적인 값을 생성하고 문제를 재현하는 것이 가능합니다. + +기호 실행은 또한 어느 정도의 수학적 정확성 증명을 제공할 수 있습니다. 오버플로 방지 기능이 있는 계약 함수의 다음 예를 고려해 보십시오. + +``` +function safe_add(uint x, uint y) returns(uint z){ + + z = x + y; + require(z>=x); + require(z>=y); + + return z; +} +``` + +정수 오버플로를 초래하는 실행 추적은 `z = x + y AND (z >= x) AND (z >= y) AND (z < x OR z < y)` 공식을 만족해야 합니다. 이러한 공식은 해결될 가능성이 거의 없으므로, `safe_add` 함수가 절대 오버플로되지 않는다는 수학적 증거 역할을 합니다. + +### 스마트 계약에 형식 검증을 사용하는 이유는 무엇인가요? {#benefits-of-formal-verification} + +#### 신뢰성의 필요성 {#need-for-reliability} + +형식 검증은 실패 시 사망, 부상 또는 재정적 파탄과 같은 파괴적인 결과를 초래할 수 있는 안전이 중요한 시스템의 정확성을 평가하는 데 사용됩니다. 스마트 계약은 막대한 가치를 제어하는 고부가가치 애플리케이션이며, 설계상의 사소한 오류는 [사용자에게 복구 불가능한 손실](https://www.freecodecamp.org/news/a-hacker-stole-31m-of-ether-how-it-happened-and-what-it-means-for-ethereum-9e5dc29e33ce/amp/)을 초래할 수 있습니다. 그러나 배포 전에 계약을 형식적으로 검증하면 블록체인에서 실행될 때 예상대로 작동할 것이라는 보장을 높일 수 있습니다. + +신뢰성은 모든 스마트 계약에서 매우 바람직한 품질이며, 특히 이더리움 가상 머신(EVM)에 배포된 코드는 일반적으로 불변이기 때문입니다. 출시 후 업그레이드에 쉽게 접근할 수 없기 때문에 계약의 신뢰성을 보장해야 하므로 형식 검증이 필요합니다. 형식 검증은 감사자 및 테스터가 놓칠 수 있는 정수 언더플로 및 오버플로, 재진입성, 부실한 가스 최적화와 같은 까다로운 문제를 감지할 수 있습니다. + +#### 기능적 정확성 증명 {#prove-functional-correctness} + +프로그램 테스트는 스마트 계약이 일부 요구 사항을 충족함을 증명하는 가장 일반적인 방법입니다. 이는 계약이 처리할 것으로 예상되는 데이터 샘플로 계약을 실행하고 그 동작을 분석하는 것을 포함합니다. 계약이 샘플 데이터에 대해 예상 결과를 반환하면 개발자는 그 정확성에 대한 객관적인 증거를 갖게 됩니다. + +그러나 이 접근 방식은 샘플에 포함되지 않은 입력 값에 대한 올바른 실행을 증명할 수 없습니다. 따라서 계약을 테스트하면 버그를 감지하는 데 도움이 될 수 있지만(즉, 일부 코드 경로가 실행 중에 원하는 결과를 반환하지 못하는 경우), **버그가 없음을 결정적으로 증명할 수는 없습니다**. + +반대로 형식 검증은 계약을 전혀 실행하지 _않고도_ 스마트 계약이 무한한 실행 범위에 대한 요구 사항을 만족함을 형식적으로 증명할 수 있습니다. 이를 위해서는 올바른 계약 동작을 정확하게 설명하는 형식 사양을 만들고 계약 시스템의 형식(수학적) 모델을 개발해야 합니다. 그런 다음 형식 증명 절차에 따라 계약 모델과 해당 사양 간의 일관성을 확인할 수 있습니다. + +형식 검증을 통해 계약의 비즈니스 로직이 요구 사항을 만족하는지 검증하는 문제는 증명되거나 반증될 수 있는 수학적 명제입니다. 명제를 형식적으로 증명함으로써 유한한 단계로 무한한 수의 테스트 사례를 검증할 수 있습니다. 이러한 방식으로 형식 검증은 계약이 사양에 대해 기능적으로 올바르다는 것을 증명할 더 나은 가능성을 가집니다. + +#### 이상적인 검증 대상 {#ideal-verification-targets} + +검증 대상은 형식적으로 검증될 시스템을 설명합니다. 형식 검증은 '임베디드 시스템'(더 큰 시스템의 일부를 형성하는 작고 간단한 소프트웨어 조각)에 가장 잘 사용됩니다. 또한 규칙이 거의 없는 전문화된 도메인에도 이상적입니다. 이는 도메인별 속성을 검증하기 위한 도구를 수정하기 쉽게 만들기 때문입니다. + +스마트 계약은 어느 정도까지는 두 요구 사항을 모두 충족합니다. 예를 들어, 이더리움 계약의 작은 크기는 형식 검증에 적합하게 만듭니다. 마찬가지로, EVM은 간단한 규칙을 따르므로 EVM에서 실행되는 프로그램의 의미론적 속성을 지정하고 검증하기가 더 쉽습니다. + +### 더 빠른 개발 주기 {#faster-development-cycle} + +모델 체킹 및 기호 실행과 같은 형식 검증 기술은 일반적으로 스마트 계약 코드의 일반적인 분석(테스트 또는 감사 중에 수행됨)보다 더 효율적입니다. 이는 형식 검증이 주장을 테스트하기 위해 기호 값에 의존하기 때문입니다('사용자가 _n_ 이더를 인출하려고 하면 어떻게 될까?') 구체적인 값을 사용하는 테스트와는 다릅니다('사용자가 5 이더를 인출하려고 하면 어떻게 될까?'). + +기호 입력 변수는 여러 클래스의 구체적인 값을 포함할 수 있으므로, 형식 검증 접근 방식은 더 짧은 시간 내에 더 많은 코드 범위를 약속합니다. 효과적으로 사용하면 형식 검증은 개발자의 개발 주기를 가속화할 수 있습니다. + +형식 검증은 또한 비용이 많이 드는 설계 오류를 줄여 탈중앙화 애플리케이션(탈중앙화앱) 구축 과정을 개선합니다. 취약점을 수정하기 위해 (가능한 경우) 계약을 업그레이드하려면 코드베이스를 광범위하게 다시 작성하고 개발에 더 많은 노력을 기울여야 합니다. 형식 검증은 테스터와 감사자가 놓칠 수 있는 계약 구현의 많은 오류를 감지하고 계약을 배포하기 전에 이러한 문제를 해결할 충분한 기회를 제공합니다. + +## 형식 검증의 단점 {#drawbacks-of-formal-verification} + +### 수작업 비용 {#cost-of-manual-labor} + +형식 검증, 특히 인간이 증명기가 정확성 증명을 도출하도록 안내하는 반자동 검증은 상당한 수작업을 필요로 합니다. 또한, 형식 사양을 만드는 것은 높은 수준의 기술을 요구하는 복잡한 활동입니다. + +이러한 요인(노력과 기술)은 형식 검증을 테스트 및 감사와 같은 계약의 정확성을 평가하는 일반적인 방법에 비해 더 까다롭고 비용이 많이 들게 만듭니다. 그럼에도 불구하고, 스마트 계약 구현의 오류 비용을 감안할 때 전체 검증 감사 비용을 지불하는 것은 실용적입니다. + +### 거짓 음성 {#false-negatives} + +형식 검증은 스마트 계약의 실행이 형식 사양과 일치하는지 여부만 확인할 수 있습니다. 따라서 사양이 스마트 계약의 예상 동작을 올바르게 설명하는지 확인하는 것이 중요합니다. + +사양이 잘못 작성되면, 속성 위반(취약한 실행을 가리킴)이 형식 검증 감사에 의해 감지될 수 없습니다. 이 경우 개발자는 계약에 버그가 없다고 잘못 가정할 수 있습니다. + +### 성능 문제 {#performance-issues} + +형식 검증은 여러 성능 문제에 부딪힙니다. 예를 들어, 모델 체킹 및 기호 체킹 중에 각각 발생하는 상태 및 경로 폭발 문제는 검증 절차에 영향을 미칠 수 있습니다. 또한 형식 검증 도구는 종종 기본 레이어에서 SMT 솔버 및 기타 제약 조건 솔버를 사용하며, 이러한 솔버는 계산 집약적인 절차에 의존합니다. + +또한 프로그램이 절대 종료되지 않을 수 있기 때문에 프로그램 검증기가 속성(논리 공식으로 설명됨)이 만족될 수 있는지 여부를 항상 결정할 수 있는 것은 아닙니다('[결정 문제](https://en.wikipedia.org/wiki/Decision_problem)'). 따라서 잘 명시되어 있더라도 계약에 대한 일부 속성을 증명하는 것이 불가능할 수 있습니다. + +## 이더리움 스마트 계약을 위한 형식 검증 도구 {#formal-verification-tools} + +### 형식 사양 생성을 위한 사양 언어 {#specification-languages} + +**Act**: __Act는 저장소 업데이트, 사전/사후 조건 및 계약 불변성의 사양을 허용합니다. 해당 도구 제품군에는 Coq, SMT 솔버 또는 hevm을 통해 많은 속성을 증명할 수 있는 증명 백엔드도 있습니다.__ + +- [GitHub](https://github.com/ethereum/act) +- [개발문서](https://github.com/argotorg/act) + +**Scribble** - __Scribble은 Scribble 사양 언어의 코드 주석을 사양을 확인하는 구체적인 주장으로 변환합니다.__ + +- [개발문서](https://docs.scribble.codes/) + +**Dafny** - __Dafny는 코드의 정확성을 추론하고 증명하기 위해 상위 수준 주석에 의존하는 검증 준비 프로그래밍 언어입니다.__ + +- [GitHub](https://github.com/dafny-lang/dafny) + +### 정확성 확인을 위한 프로그램 검증기 {#program-verifiers} + +**Certora Prover** - _Certora Prover는 스마트 계약의 코드 정확성을 확인하기 위한 자동 형식 검증 도구입니다. 사양은 CVL(Certora Verification Language)로 작성되며, 속성 위반은 정적 분석과 제약 조건 해결의 조합을 사용하여 감지됩니다._ + +- [웹사이트](https://www.certora.com/) +- [개발문서](https://docs.certora.com/en/latest/index.html) + +**Solidity SMTChecker** - __Solidity의 SMTChecker는 SMT(Satisfiability Modulo Theories) 및 Horn 해결을 기반으로 하는 내장 모델 체커입니다. 컴파일 중에 계약의 소스 코드가 사양과 일치하는지 확인하고 안전 속성 위반을 정적으로 확인합니다.__ + +- [GitHub](https://github.com/ethereum/solidity) + +**solc-verify** - __solc-verify는 주석 및 모듈식 프로그램 검증을 사용하여 Solidity 코드에 대한 자동 형식 검증을 수행할 수 있는 Solidity 컴파일러의 확장 버전입니다.__ + +- [GitHub](https://github.com/SRI-CSL/solidity) + +**KEVM** - __KEVM은 K 프레임워크로 작성된 이더리움 가상 머신(EVM)의 형식 의미론입니다. KEVM은 실행 가능하며 도달 가능성 논리를 사용하여 특정 속성 관련 주장을 증명할 수 있습니다.__ + +- [GitHub](https://github.com/runtimeverification/evm-semantics) +- [개발문서](https://jellopaper.org/) + +### 정리 증명을 위한 논리적 프레임워크 {#theorem-provers} + +**Isabelle** - _Isabelle/HOL은 수학 공식을 형식 언어로 표현하고 해당 공식을 증명하기 위한 도구를 제공하는 증명 보조 도구입니다. 주요 애플리케이션은 수학적 증명의 형식화, 특히 컴퓨터 하드웨어 또는 소프트웨어의 정확성을 증명하고 컴퓨터 언어 및 프로토콜의 속성을 증명하는 것을 포함하는 형식 검증입니다._ + +- [GitHub](https://github.com/isabelle-prover) +- [개발문서](https://isabelle.in.tum.de/documentation.html) + +**Rocq** - _Rocq는 정리를 사용하여 프로그램을 정의하고 기계 검사된 정확성 증명을 대화형으로 생성할 수 있는 대화형 정리 증명기입니다._ + +- [GitHub](https://github.com/rocq-prover/rocq) +- [개발문서](https://rocq-prover.org/docs) + +### 스마트 계약의 취약한 패턴을 감지하기 위한 기호 실행 기반 도구 {#symbolic-execution-tools} + +**Manticore** - __기호 실행을 기반으로 하는 EVM 바이트코드 분석 도구_._ + +- [GitHub](https://github.com/trailofbits/manticore) +- [개발문서](https://github.com/trailofbits/manticore/wiki) + +**hevm** - __hevm은 EVM 바이트코드에 대한 기호 실행 엔진 및 등가성 검사기입니다.__ + +- [GitHub](https://github.com/dapphub/dapptools/tree/master/src/hevm) + +**Mythril** - _이더리움 스마트 계약의 취약점을 감지하기 위한 기호 실행 도구_ + +- [GitHub](https://github.com/ConsenSys/mythril-classic) +- [개발문서](https://mythril-classic.readthedocs.io/en/develop/) + +## 더 읽어보기 {#further-reading} + +- [스마트 계약의 형식 검증 작동 방식](https://runtimeverification.com/blog/how-formal-verification-of-smart-contracts-works/) +- [형식 검증이 완벽한 스마트 계약을 보장하는 방법](https://media.consensys.net/how-formal-verification-can-ensure-flawless-smart-contracts-cbda8ad99bd1) +- [이더리움 생태계의 형식 검증 프로젝트 개요](https://github.com/leonardoalt/ethereum_formal_verification_overview) +- [이더리움 2.0 예치 스마트 계약의 종단 간 형식 검증](https://runtimeverification.com/blog/end-to-end-formal-verification-of-ethereum-2-0-deposit-smart-contract/) +- [세계에서 가장 인기 있는 스마트 계약 형식 검증하기](https://www.zellic.io/blog/formal-verification-weth) +- [SMTChecker 및 형식 검증](https://docs.soliditylang.org/en/v0.8.15/smtchecker.html) diff --git a/public/content/translations/ko/developers/docs/smart-contracts/index.md b/public/content/translations/ko/developers/docs/smart-contracts/index.md new file mode 100644 index 00000000000..6a69ad8df35 --- /dev/null +++ b/public/content/translations/ko/developers/docs/smart-contracts/index.md @@ -0,0 +1,112 @@ +--- +title: "스마트 계약 소개" +description: "스마트 컨트랙트의 개요, 고유한 특징과 한계에 집중하여" +lang: ko +--- + +## 스마트 컨트랙트란 무엇인가요? 스마트 계약이란 무엇인가요? {#what-is-a-smart-contract} + +"스마트 컨트랙트"란 간단히 말해서 이더리움 블록체인 상에서 작동하는 프로그램입니다. 이것은 이더리움 블록체인 상에서 특정한 주소에 살고 있는 코드(함수들) 와 데이터(상태) 의 모음입니다. + +스마트 계약은 [이더리움 계정](/developers/docs/accounts/)의 한 유형입니다. 이는 잔액을 가지고 있으며 트랜잭션의 대상이 될 수 있음을 의미합니다. 그러나 사용자에 의해 조작되지 않고, 대신에 네트워크에 의해 배포되고 프로그램된 대로 작동합니다. 그렇기에 사용자 계정은 스마트 컨트랙트에 정의된 함수를 실행하는 트랜잭션을 제출함으로써 스마트 컨트랙트와 상호 작용할 수 있습니다. 스마트 컨트랙트는 일반적인 계약처럼 규칙을 정의할 수 있고, 코드를 통해 자동으로 규칙을 시행하기도 합니다. 스마트 계약은 기본적으로 삭제할 수 없으며, 스마트 계약과의 상호작용은 되돌릴 수 없습니다. + +## 필수 구성 요소 {#prerequisites} + +이제 막 시작하셨거나 덜 기술적인 소개를 찾고 계신다면, 저희의 [스마트 계약 소개](/smart-contracts/)를 추천합니다. + +스마트 계약의 세계로 뛰어들기 전에 [계정](/developers/docs/accounts/), [트랜잭션](/developers/docs/transactions/), 그리고 [이더리움 가상 머신](/developers/docs/evm/)에 대해 충분히 숙지하시기 바랍니다. + +## 디지털 자판기 {#a-digital-vending-machine} + +스마트 계약에 대한 가장 좋은 비유는 [Nick Szabo](https://unenumerated.blogspot.com/)가 설명한 자판기일 것입니다. 올바른 입력으로, 확실한 결과가 보장됩니다. + +자판기에서 snack을 사려면: + +``` +돈 + 간식 선택 = 간식 제공 +``` + +이 로직은 자판기 안에 프로그램되었습니다. + +자판기처럼 스마트 컨트랙트는 내부에 프로그램된 로직을 갖고 있습니다. 이 자판기가 솔리디티로 작성된 스마트 계약이라면 다음과 같이 보일 것입니다. + +```solidity +pragma solidity 0.8.7; + +contract VendingMachine { + + // 계약의 상태 변수 선언 + address public owner; + mapping (address => uint) public cupcakeBalances; + + // 'VendingMachine' 계약이 배포될 때: + // 1. 배포하는 주소를 계약의 소유자로 설정 + // 2. 배포된 스마트 계약의 컵케이크 잔액을 100으로 설정 + constructor() { + owner = msg.sender; + cupcakeBalances[address(this)] = 100; + } + + // 소유자가 스마트 계약의 컵케이크 잔액을 늘릴 수 있도록 허용 + function refill(uint amount) public { + require(msg.sender == owner, "소유자만 리필할 수 있습니다."); + cupcakeBalances[address(this)] += amount; + } + + // 누구나 컵케이크를 구매할 수 있도록 허용 + function purchase(uint amount) public payable { + require(msg.value >= amount * 1 ether, "컵케이크당 최소 1 ETH를 지불해야 합니다."); + require(cupcakeBalances[address(this)] >= amount, "이 구매를 완료하기에 재고가 충분하지 않습니다."); + cupcakeBalances[address(this)] -= amount; + cupcakeBalances[msg.sender] += amount; + } +} +``` + +자판기가 종업원에 대한 필요성을 없앤 것처럼, 스마트 컨트랙트는 많은 산업에서 중재자를 대체할 수 있습니다. + +## 무허가성 {#permissionless} + +누구나 스마트 컨트랙트를 작성할 수 있고 네트워크에 배포할 수 있습니다. 그저 [스마트 계약 언어](/developers/docs/smart-contracts/languages/)로 코딩하는 법을 배우고, 계약을 배포하기에 충분한 ETH만 있으면 됩니다. 스마트 계약 배포는 기술적으로 트랜잭션이므로, 간단한 ETH 전송에 가스를 지불해야 하는 것과 같은 방식으로 [가스](/developers/docs/gas/)를 지불해야 합니다. 그러나 계약 배포의 가스 비용은 훨씬 높습니다. + +이더리움은 스마트 컨트랙트 작성을 위한 개발자-친화적인 언어들을 갖고 있습니다. + +- 솔리디티 +- Vyper + +[언어에 대해 더 알아보기](/developers/docs/smart-contracts/languages/) + +그러나, 이더리움 가상 머신이 컨트랙트를 해석하고 저장하기 위해서 이 언어들은 배포되기 전에 컴파일 되어야 합니다. [컴파일에 대해 더 알아보기](/developers/docs/smart-contracts/compiling/) + +## 구성 가능성 {#composability} + +스마트 컨트랙트는 이더리움 상에서 공개되어 오픈 API처럼 생각할 수 있습니다. 이는 스마트 계약에서 다른 스마트 계약을 호출하여 가능성을 크게 확장할 수 있음을 의미합니다. 심지어 컨트랙트는 다른 컨트랙트를 배포하기도 가능합니다. + +[스마트 계약 구성 가능성](/developers/docs/smart-contracts/composability/)에 대해 더 알아보세요. + +## 한계 {#limitations} + +스마트 계약만으로는 오프체인 소스에서 데이터를 가져올 수 없기 때문에 "현실 세계" 이벤트에 대한 정보를 얻을 수 없습니다. 이들은 현실 세계의 사건에 반응할 수 없습니다. 이는 설계된 것입니다. 외부 정보에 의존하는 것은 합의를 위협할 수 있고, 이는 보안과 탈중앙화에 중요합니다. + +그러나 블록체인 애플리케이션이 오프체인 데이터를 사용할 수 있는 것이 중요합니다. 해결책은 오프체인 데이터를 가져와 스마트 계약에서 사용할 수 있도록 하는 도구인 [오라클](/developers/docs/oracles/)입니다. + +스마트 컨트랙트의 다른 한계는 컨트랙트 최대 사이즈입니다. 스마트 컨트랙트는 최대 24KB까지 가능하거나 가스를 다 써버릴 수도 있습니다. [다이아몬드 패턴(The Diamond Pattern)](https://eips.ethereum.org/EIPS/eip-2535)을 사용하여 이 문제를 해결할 수 있습니다. + +## 멀티시그 계약 {#multisig} + +멀티시그(다중 서명) 계약은 거래를 실행하기 위해 여러 유효한 서명을 필요로 하는 스마트 계약 계정입니다. 이는 상당한 양의 이더 또는 기타 토큰을 보유한 계약에서 단일 실패 지점을 방지하는 데 매우 유용합니다. 멀티시그는 또한 계약 실행 및 키 관리를 여러 당사자로 분산시키며, 단일 프라이빗 키의 손실로 인해 자금을 영구적으로 잃지 않도록 합니다. 이러한 이유로 멀티시그 계약은 간단한 DAO 거버넌스에도 사용할 수 있습니다. 멀티시그는 실행을 위해 M개의 허용 가능한 서명 중 N개의 서명을 필요로 합니다(N ≤ M, 그리고 M > 1). `N = 3, M = 5`와 `N = 4, M = 7`이 일반적으로 사용됩니다. 4/7 멀티시그는 7개의 가능한 서명 중 4개가 유효한 서명임을 요구합니다. 이는 3개의 서명을 잃어도 자금을 여전히 복구할 수 있다는 의미입니다. 이 경우 또한 계약을 실행하려면 다수의 키 보유자가 동의하고 서명해야 한다는 것을 의미합니다. + +## 스마트 계약 참고 자료 {#smart-contract-resources} + +**OpenZeppelin Contracts -** **_안전한 스마트 계약 개발을 위한 라이브러리._** + +- [openzeppelin.com/contracts/](https://openzeppelin.com/contracts/) +- [GitHub](https://github.com/OpenZeppelin/openzeppelin-contracts) +- [커뮤니티 포럼](https://forum.openzeppelin.com/c/general/16) + +## 더 읽어보기 {#further-reading} + +- [Coinbase: 스마트 계약이란 무엇인가요?](https://www.coinbase.com/learn/crypto-basics/what-is-a-smart-contract) +- [Chainlink: 스마트 계약이란 무엇인가요?](https://chain.link/education/smart-contracts) +- [영상: 간단한 설명 - 스마트 계약](https://youtu.be/ZE2HxTmxfrI) +- [Cyfrin Updraft: 웹3 학습 및 감사 플랫폼](https://updraft.cyfrin.io) diff --git a/public/content/translations/ko/developers/docs/smart-contracts/languages/index.md b/public/content/translations/ko/developers/docs/smart-contracts/languages/index.md new file mode 100644 index 00000000000..339709fd401 --- /dev/null +++ b/public/content/translations/ko/developers/docs/smart-contracts/languages/index.md @@ -0,0 +1,343 @@ +--- +title: "스마트 컨트랙트 언어" +description: "두 종류의 주요 smart contract 언어에 대한 요약과 비교 - Solidity 와 Vyper" +lang: ko +--- + +이더리움의 가장 좋은 점은 smart contract을 개발자 친화적인 언어로 프로그래밍 할 수 있다는 점이다. Python 또는 [중괄호 언어](https://wikipedia.org/wiki/List_of_programming_languages_by_type#Curly-bracket_languages)에 익숙하다면 친숙한 구문을 가진 언어를 찾을 수 있습니다. + +가장 활발하고 유지되는 언어들은 다음과 같다: + +- 솔리디티 +- Vyper + +Remix IDE는 Solidity 및 Vyper에서 계약을 생성하고 테스트하기 위한 종합 개발 환경을 제공합니다. [브라우저 내 Remix IDE](https://remix.ethereum.org)에서 코딩을 시작하세요. + +더 숙련된 개발자들은 [이더리움 가상 머신](/developers/docs/evm/)을 위한 중간 언어인 Yul 또는 Yul의 확장판인 Yul+를 사용할 수도 있습니다. + +만약 당신이 궁금하고 아직 힘들게 개발중인 새로운 언어 테스트를 도와주고 싶다면, smart contract 언어로 떠오르고 있지만 아직은 초창기 단계인 Fe 언어를 시도해볼 수 있다. + +## 필수 구성 요소 {#prerequisites} + +특히 Javascript나 Python에 대해 미리 알고 있다면, smart contract 언어의 차이를 이해하는데 도움을 줄 수 있다. 언어에 대한 차이를 너무 깊게 파고들기 전에 smart contract 개념을 먼저 이해하는 것을 추천한다. [스마트 계약 소개](/developers/docs/smart-contracts/). + +## 솔리디티 {#solidity} + +- Smart contract를 구현하기 위한 객체지향의 고급 언어 (high-level language). +- C++로부터 영향을 가장 많이 받은 Curly-bracket 언어. +- 정적 프로그래밍 언어 (자료형이 컴파일 시 결정되는 언어). +- 지원: + - 상속 (다른 contract으로 확장할 수 있음). + - 라이브러리 (객체지향 프로그래밍 언어에서 정적(static) 클래스에 있는 정적 함수처럼 서로 다른 contract에서 부를 수 있는 재사용이 가능한 코드를 만들 수 있음). + - Complex user-defined types. + +### 중요 링크 {#important-links} + +- [개발문서](https://docs.soliditylang.org/en/latest/) +- [솔리디티 언어 포털](https://soliditylang.org/) +- [솔리디티 예제](https://docs.soliditylang.org/en/latest/solidity-by-example.html) +- [GitHub](https://github.com/ethereum/solidity/) +- [Solidity Gitter 채팅방](https://gitter.im/ethereum/solidity), [Solidity Matrix 채팅방](https://matrix.to/#/#ethereum_solidity:gitter.im)과 브리지됨 +- [치트 시트](https://reference.auditless.com/cheatsheet) +- [솔리디티 블로그](https://blog.soliditylang.org/) +- [솔리디티 트위터](https://twitter.com/solidity_lang) + +### 예제 계약 {#example-contract} + +```solidity +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >= 0.7.0; + +contract Coin { + // "public" 키워드는 변수를 + // 다른 계약에서 접근할 수 있도록 합니다 + address public minter; + mapping (address => uint) public balances; + + // 이벤트는 클라이언트가 선언한 특정 + // 계약 변경에 반응할 수 있도록 합니다 + event Sent(address from, address to, uint amount); + + // 생성자 코드는 계약이 + // 생성될 때만 실행됩니다 + constructor() { + minter = msg.sender; + } + + // 새로 생성된 코인을 주소로 전송합니다 + // 계약 생성자만 호출할 수 있습니다 + function mint(address receiver, uint amount) public { + require(msg.sender == minter); + require(amount < 1e60); + balances[receiver] += amount; + } + + // 기존 코인을 + // 모든 호출자로부터 주소로 전송합니다 + function send(address receiver, uint amount) public { + require(amount <= balances[msg.sender], "잔액이 부족합니다."); + balances[msg.sender] -= amount; + balances[receiver] += amount; + emit Sent(msg.sender, receiver, amount); + } +} +``` + +이 예제를 통해 Solidity contract 문법이 어떤지 감을 찾을 수 있다. 함수와 변수에 대한 더 자세한 설명은 [문서를 참조하세요](https://docs.soliditylang.org/en/latest/contracts.html). + +## Vyper {#vyper} + +- Pythonic 프로그래밍 언어 +- 강한 타입 +- 작고 이해하기 쉬운 컴파일러 코드 +- 효율적인 바이트코드 생성 +- Contract을 더 안전하고 검사하기 쉽게 일부러 Solidity보다 기능이 적음. Vyper는 아래를 지원하지 않음: + - 제어자 (Modifiers) + - 상속 + - 인라인 어셈블리 (Inline assembly) + - 함수 오버로드 + - 연산자 오버로드 + - 재귀 호출 + - 무한 루프 + - 이진 고정점 (Binary fixed points) + +자세한 내용은 [Vyper의 기본 원칙을 읽어보세요](https://vyper.readthedocs.io/en/latest/index.html). + +### 중요 링크 {#important-links-1} + +- [개발문서](https://vyper.readthedocs.io) +- [예제로 배우는 Vyper](https://vyper.readthedocs.io/en/latest/vyper-by-example.html) +- [예제로 배우는 Vyper 더 보기](https://vyper-by-example.org/) +- [GitHub](https://github.com/vyperlang/vyper) +- [Vyper 커뮤니티 Discord 채팅](https://discord.gg/SdvKC79cJk) +- [치트 시트](https://reference.auditless.com/cheatsheet) +- [Vyper를 위한 스마트 계약 개발 프레임워크 및 도구](/developers/docs/programming-languages/python/) +- [VyperPunk - Vyper 스마트 계약을 보호하고 해킹하는 방법 배우기](https://github.com/SupremacyTeam/VyperPunk) +- [개발을 위한 Vyper 허브](https://github.com/zcor/vyper-dev) +- [Vyper 인기 스마트 계약 예제](https://github.com/pynchmeister/vyper-greatest-hits/tree/main/contracts) +- [엄선된 Vyper 참고 자료 모음](https://github.com/spadebuilders/awesome-vyper) + +### 예제 {#example} + +```python +# 공개 경매 + +# 경매 매개변수 + +# 수익자는 최고 입찰자로부터 금액을 받습니다 + +beneficiary: public(address) +auctionStart: public(uint256) +auctionEnd: public(uint256) + +# 경매의 현재 상태 + +highestBidder: public(address) +highestBid: public(uint256) + +# 종료 시 true로 설정, 모든 변경을 금지합니다 + +ended: public(bool) + +# 출금 패턴을 따를 수 있도록 환불된 입찰을 추적합니다 + +pendingReturns: public(HashMap[address, uint256]) + +# `_bidding_time`을 사용하여 간단한 경매를 생성합니다 + +# `_beneficiary` 주소를 대신하여 + +# 초 단위 입찰 시간을 지정합니다. + +@external +def __init__(_beneficiary: address, _bidding_time: uint256): + self.beneficiary = _beneficiary + self.auctionStart = block.timestamp + self.auctionEnd = self.auctionStart + _bidding_time + +# 이 트랜잭션과 함께 전송된 금액으로 경매에 + +# 입찰합니다. + +# 이 금액은 경매에서 이기지 못할 경우에만 + +# 환불됩니다. + +@external +@payable +def bid(): + # 입찰 기간이 끝났는지 확인합니다. + assert block.timestamp < self.auctionEnd + # 입찰가가 충분히 높은지 확인합니다. + assert msg.value > self.highestBid + # 이전 최고 입찰자에 대한 환불을 추적합니다. + self.pendingReturns[self.highestBidder] += self.highestBid + # 새로운 최고 입찰가를 추적합니다. + self.highestBidder = msg.sender + self.highestBid = msg.value + +# 이전에 환불된 입찰을 출금합니다. 출금 패턴은 + +# 보안 문제를 피하기 위해 여기서 사용됩니다. 만약 환불이 + +# bid()의 일부로 직접 전송된다면, 악의적인 입찰 계약이 + +# 해당 환불을 막고, 따라서 더 높은 새로운 입찰이 들어오는 것을 + +# 막을 수 있습니다. + +@external +def withdraw(): + pending_amount: uint256 = self.pendingReturns[msg.sender] + self.pendingReturns[msg.sender] = 0 + send(msg.sender, pending_amount) + +# 경매를 종료하고 최고 입찰가를 + +# 수익자에게 전송합니다. + +@external +def endAuction(): + # 다른 계약과 상호 작용하는(즉, 함수를 호출하거나 이더를 보내는) + # 함수를 세 단계로 구성하는 것이 좋은 지침입니다. + # 1. 조건 확인 + # 2. 작업 수행(조건을 변경할 수 있음) + # 3. 다른 계약과 상호 작용 + # 이러한 단계가 혼합되면 다른 계약이 + # 현재 계약으로 다시 호출하여 상태를 수정하거나 + # 효과(이더 지급)가 여러 번 수행되도록 할 수 있습니다. + # 내부적으로 호출된 함수가 외부 계약과의 + # 상호 작용을 포함하는 경우, 이들도 외부 계약과의 + # 상호 작용으로 간주되어야 합니다. + + # 1. 조건 + # 경매 종료 시간에 도달했는지 확인합니다. + assert block.timestamp >= self.auctionEnd + # 이 함수가 이미 호출되었는지 확인합니다. + assert not self.ended + + # 2. 효과 + self.ended = True + + # 3. 상호 작용 + send(self.beneficiary, self.highestBid) +``` + +이 예제를 통해 Vyper contract 문법이 어떤지 감을 찾을 수 있다. 함수와 변수에 대한 더 자세한 설명은 [문서를 참조하세요](https://vyper.readthedocs.io/en/latest/vyper-by-example.html#simple-open-auction). + +## Yul 및 Yul+ {#yul} + +이더리움을 처음 접하고 아직 스마트 계약 언어로 코딩해본 적이 없다면, Solidity 또는 Vyper로 시작하는 것이 좋습니다. 스마트 계약 보안 모범 사례와 EVM 작업의 구체적인 사항에 익숙해진 후에 Yul 또는 Yul+를 탐색하세요. + +**Yul** + +- 이더리움을 위한 중간 언어입니다. +- [EVM](/developers/docs/evm)과 이더리움 기반의 웹어셈블리인 [Ewasm](https://github.com/ewasm)을 지원하며, 두 플랫폼 모두에서 사용할 수 있는 공통 분모로 설계되었습니다. +- EVM과 Ewasm 플랫폼 모두에 유리한 고급 최적화 단계를 위한 좋은 목표입니다. + +**Yul+** + +- Yul의 저수준 및 고효율 확장입니다. +- 처음에는 [낙관적 롤업](/developers/docs/scaling/optimistic-rollups/) 계약을 위해 설계되었습니다. +- Yul+는 Yul의 새로운 기능을 추가하는 실험적 업그레이드 제안으로 볼 수 있습니다. + +### 중요 링크 {#important-links-2} + +- [Yul 개발문서](https://docs.soliditylang.org/en/latest/yul.html) +- [Yul+ 개발문서](https://github.com/fuellabs/yulp) +- [Yul+ 소개 게시물](https://medium.com/@fuellabs/introducing-yul-a-new-low-level-language-for-ethereum-aa64ce89512f) + +### 예제 계약 {#example-contract-2} + +다음의 간단한 예는 제곱 함수(power function)를 구현합니다. `solc --strict-assembly --bin input.yul`을 사용하여 컴파일할 수 있습니다. 이 예시는 input.yul 파일에 저장해야 합니다. + +``` +{ + function power(base, exponent) -> result + { + switch exponent + case 0 { result := 1 } + case 1 { result := base } + default + { + result := power(mul(base, base), div(exponent, 2)) + if mod(exponent, 2) { result := mul(base, result) } + } + } + let res := power(calldataload(0), calldataload(32)) + mstore(0, res) + return(0, 32) +} +``` + +스마트 계약에 이미 매우 익숙하다면 Yul로 구현된 전체 ERC20을 [여기](https://solidity.readthedocs.io/en/latest/yul.html#complete-erc20-example)에서 찾을 수 있습니다. + +## Fe {#fe} + +- 이더리움 가상 머신(EVM)을 위한 정적 타입 언어입니다. +- Python과 Rust에서 영감을 받았습니다. +- 이더리움 생태계에 처음인 개발자도 쉽게 배울 수 있도록 설계되었습니다. +- Fe 개발은 아직 초기 단계이며, 2021년 1월에 알파 버전이 출시되었습니다. + +### 중요 링크 {#important-links-3} + +- [GitHub](https://github.com/ethereum/fe) +- [Fe 발표](https://snakecharmers.ethereum.org/fe-a-new-language-for-the-ethereum-ecosystem/) +- [Fe 2021 로드맵](https://notes.ethereum.org/LVhaTF30SJOpkbG1iVw1jg) +- [Fe Discord 채팅](https://discord.com/invite/ywpkAXFjZH) +- [Fe 트위터](https://twitter.com/official_fe) + +### 예제 계약 {#example-contract-3} + +다음은 Fe로 구현된 간단한 계약입니다. + +``` +type BookMsg = bytes[100] + +contract GuestBook: + pub guest_book: map + + event Signed: + book_msg: BookMsg + + pub def sign(book_msg: BookMsg): + self.guest_book[msg.sender] = book_msg + + emit Signed(book_msg=book_msg) + + pub def get_msg(addr: address) -> BookMsg: + return self.guest_book[addr].to_mem() + +``` + +## 선택 방법 {#how-to-choose} + +다른 프로그래밍 언어와 마찬가지로 작업에 적합한 도구를 선택하는 것이 중요하며, 개인적인 선호도도 고려해야 합니다. + +솔리디티의 장점은 무엇인가요? + +### 초보자에게는 다양한 튜토리얼과 학습 도구가 있습니다. {#solidity-advantages} + +- 코딩으로 배우기 섹션에서 더 알아볼 수 있습니다. 자세한 내용은 [코딩으로 배우기](/developers/learning-tools/) 섹션을 참조하세요. +- 좋은 개발자 툴링을 사용할 수 있습니다. +- 솔리디티는 큰 개발자 커뮤니티가 있어 질문에 대한 답변을 쉽게 찾을 수 있습니다. + +### Vyper의 장점은 무엇인가요? {#vyper-advatages} + +- 스마트 계약을 작성하고자 하는 Python 개발자에게 훌륭한 출발점입니다. +- 기능 수가 적어 아이디어를 빠르게 프로토타입하는 데 적합합니다. +- Vyper는 감사하기 쉽고 가독성이 뛰어납니다. + +### Yul과 Yul+의 장점은 무엇인가요? {#yul-advantages} + +- 간단하고 기능적인 저수준 언어입니다. +- 계약의 가스 사용량 최적화에 도움이 되는 원시 EVM에 더 가깝게 접근할 수 있습니다. + +## 언어 비교 {#language-comparisons} + +기본 구문, 계약 수명 주기, 인터페이스, 연산자, 데이터 구조, 함수, 제어 흐름 등을 비교하려면 Auditless의 [치트 시트](https://reference.auditless.com/cheatsheet/)를 확인하세요. + +## 더 읽어보기 {#further-reading} + +- [OpenZeppelin의 솔리디티 계약 라이브러리](https://docs.openzeppelin.com/contracts/5.x/) +- [예제로 배우는 솔리디티](https://solidity-by-example.org) diff --git a/public/content/translations/ko/developers/docs/smart-contracts/libraries/index.md b/public/content/translations/ko/developers/docs/smart-contracts/libraries/index.md new file mode 100644 index 00000000000..fb9c6f499c5 --- /dev/null +++ b/public/content/translations/ko/developers/docs/smart-contracts/libraries/index.md @@ -0,0 +1,117 @@ +--- +title: "스마트 계약 라이브러리" +description: "재사용 가능한 스마트 계약 라이브러리 및 구성 요소를 찾아 이더리움 개발 프로젝트를 가속화하세요." +lang: ko +--- + +프로젝트에서 모든 스마트 계약을 처음부터 작성할 필요가 없습니다. 프로젝트에 재사용 가능한 빌딩 블록을 제공하는 많은 오픈 소스 스마트 계약 라이브러리가 있어, 처음부터 모든 것을 다시 만들 필요 없이 시간을 절약할 수 있습니다. + +## 필수 구성 요소 {#prerequisites} + +스마트 계약 라이브러리에 뛰어들기 전에, 스마트 계약의 구조를 잘 이해하는 것이 좋습니다. 아직 확인하지 않았다면 [스마트 계약 구조](/developers/docs/smart-contracts/anatomy/)로 이동하세요. + +## 라이브러리 구성 {#whats-in-a-library} + +스마트 계약 라이브러리에서는 보통 두 가지 유형의 빌딩 블록을 찾을 수 있습니다: 계약에 추가할 수 있는 재사용 가능한 동작과 다양한 표준의 구현입니다. + +### 동작 {#behaviors} + +스마트 계약을 작성할 때, 계약에서 보호된 작업을 수행하기 위해 _admin_ 주소를 할당하거나 예기치 않은 문제가 발생했을 때 긴급 _pause_ 버튼을 추가하는 것처럼, 유사한 패턴을 여러 번 작성하게 될 가능성이 큽니다. + +스마트 계약 라이브러리는 일반적으로 솔리디티(Solidity)에서 [라이브러리](https://solidity.readthedocs.io/en/v0.7.2/contracts.html#libraries) 또는 [상속](https://solidity.readthedocs.io/en/v0.7.2/contracts.html#inheritance)을 통해 이러한 동작의 재사용 가능한 구현을 제공합니다. + +예를 들어, 다음은 [OpenZeppelin Contracts 라이브러리](https://github.com/OpenZeppelin/openzeppelin-contracts)의 [`Ownable` 계약](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.2.0/contracts/access/Ownable.sol)의 간소화된 버전입니다. 이 계약은 주소를 계약의 소유자로 지정하고 해당 소유자에게만 메서드에 대한 접근을 제한하는 제어자를 제공합니다. + +```solidity +contract Ownable { + address public owner; + + constructor() internal { + owner = msg.sender; + } + + modifier onlyOwner() { + require(owner == msg.sender, "Ownable: 호출자가 소유자가 아닙니다"); + _; + } +} +``` + +이러한 빌딩 블록을 계약에 사용하려면 먼저 이를 가져와 계약에서 확장해야 합니다. 이를 통해 기본 `Ownable` 계약에서 제공하는 제어자를 사용하여 자신의 함수를 보호할 수 있습니다. + +```solidity +import ".../Ownable.sol"; // 가져온 라이브러리의 경로 + +contract MyContract is Ownable { + // 다음 함수는 소유자만 호출할 수 있습니다 + function secured() onlyOwner public { + msg.sender.transfer(1 ether); + } +} +``` + +또 다른 인기 있는 예는 [SafeMath](https://docs.openzeppelin.com/contracts/3.x/utilities#math) 또는 [DsMath](https://dappsys.readthedocs.io/en/latest/ds_math.html)입니다. 이들은 언어에서 제공되지 않는 오버플로우 검사를 포함한 산술 기능을 제공하는 라이브러리입니다. 계약을 오버플로우로부터 보호하기 위해 기본 산술 연산 대신 이러한 라이브러리 중 하나를 사용하는 것이 좋은 관행입니다. + +### 표준 {#standards} + +[구성 가능성 및 상호 운용성](/developers/docs/smart-contracts/composability/)을 촉진하기 위해 이더리움 커뮤니티는 **ERC** 형식으로 여러 표준을 정의했습니다. 자세한 내용은 [표준](/developers/docs/standards/) 섹션에서 확인할 수 있습니다. + +계약의 일부로 ERC를 포함할 때는, 직접 구현하는 대신 표준 구현을 찾는 것이 좋습니다. 많은 스마트 계약 라이브러리에는 가장 인기 있는 ERC의 구현이 포함되어 있습니다. 예를 들어, 널리 사용되는 [ERC20 대체 가능 토큰 표준](/developers/tutorials/understand-the-erc-20-token-smart-contract/)은 [HQ20](https://github.com/HQ20/contracts/blob/master/contracts/token/README.md), [DappSys](https://github.com/dapphub/ds-token/), [OpenZeppelin](https://docs.openzeppelin.com/contracts/3.x/erc20)에서 찾아볼 수 있습니다. 또한, 일부 ERC는 ERC 자체의 일부로 표준 구현을 제공합니다. + +몇몇 ERC는 독립적인 것이 아니라 다른 ERC에 추가로 제공되는 경우도 있습니다. 예를 들어, [ERC2612](https://eips.ethereum.org/EIPS/eip-2612)는 ERC20의 사용성 개선을 위한 확장 기능을 추가합니다. + +## 라이브러리 추가 방법 {#how-to} + +프로젝트에 라이브러리를 포함하는 구체적인 방법에 대해서는 항상 라이브러리의 문서를 참조하세요. 일부 솔리디티(Solidity) 계약 라이브러리는 `npm`을 사용하여 패키지로 제공되므로 `npm install`을 사용하여 간단히 설치할 수 있습니다. 계약 [컴파일](/developers/docs/smart-contracts/compiling/)을 위한 대부분의 도구는 스마트 계약 라이브러리를 `node_modules`에서 찾으므로 다음과 같이 할 수 있습니다. + +```solidity +// node_modules에서 @openzeppelin/contracts 라이브러리를 로드합니다 +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; + +contract MyNFT is ERC721 { + constructor() ERC721("MyNFT", "MNFT") public { } +} +``` + +사용하는 방법에 관계없이 라이브러리를 포함할 때는 항상 [언어](/developers/docs/smart-contracts/languages/) 버전을 주시해야 합니다. 예를 들면 솔리디티 0.5에서 계약을 작성하고 있는 경우 솔리디티 0.6 라이브러리를 사용할 수 없습니다. + +## 사용 시점 {#when-to-use} + +프로젝트에서 스마트 계약 라이브러리를 사용하는 것은 여러 가지 장점이 있습니다. 첫째, 직접 코딩하지 않고도 시스템에 포함할 수 있는 즉시 사용 가능한 빌딩 블록을 제공하여 시간을 절약할 수 있습니다. + +보안도 중요한 장점입니다. 오픈 소스 스마트 계약 라이브러리는 많은 프로젝트가 이를 의존하므로, 커뮤니티에서 지속적인 검토가 이루어집니다. 응용 프로그램 코드에서 오류를 발견하는 것이 재사용 가능한 계약 라이브러리에서 오류를 발견하는 것보다 훨씬 더 흔합니다. 응용 프로그램 코드에서 오류를 발견하는 것이 재사용 가능한 계약 라이브러리에서 오류를 발견하는 것보다 훨씬 더 흔합니다. 일부 라이브러리는 보안 강화를 위해 [외부 감사](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/audits)를 받기도 합니다. + +그러나 스마트 계약 라이브러리를 사용할 때는 익숙하지 않은 코드를 프로젝트에 포함할 위험이 있습니다. 계약을 가져와 프로젝트에 바로 포함시키는 것은 유혹적이지만, 해당 계약이 무엇을 하는지 잘 모르면, 예상치 못한 동작으로 인해 시스템에 문제를 도입할 수 있습니다. 가져온 코드의 문서를 읽고, 코드를 검토한 후 프로젝트의 일부로 만들도록 하세요! + +마지막으로 라이브러리를 포함할지 여부를 결정할 때, 그 라이브러리의 전체적인 사용성을 고려하세요. 광범위하게 채택된 라이브러리는 커뮤니티가 더 크고 더 많은 사람들이 문제를 점검할 가능성이 있습니다. 스마트 계약을 사용하여 구축할 때 보안을 최우선으로 생각해야 합니다! + +## 관련 도구 {#related-tools} + +**OpenZeppelin Contracts -** **_안전한 스마트 계약 개발을 위한 가장 인기 있는 라이브러리_** + +- [문서](https://docs.openzeppelin.com/contracts/) +- [GitHub](https://github.com/OpenZeppelin/openzeppelin-contracts) +- [커뮤니티 포럼](https://forum.openzeppelin.com/c/general/16) + +**DappSys -** **_안전하고 단순하며 유연한 스마트 계약용 구성 요소_** + +- [문서](https://dappsys.readthedocs.io/) +- [GitHub](https://github.com/dapphub/dappsys) + +**HQ20 -** **_실제 환경에서 모든 기능을 갖춘 분산 애플리케이션을 구축하는 데 도움이 되는 계약, 라이브러리 및 예제가 포함된 솔리디티(Solidity) 프로젝트_** + +- [GitHub](https://github.com/HQ20/contracts) + +**thirdweb 솔리디티(Solidity) SDK -** **_맞춤형 스마트 계약을 효율적으로 구축하는 데 필요한 도구를 제공합니다_** + +- [문서](https://portal.thirdweb.com/contracts/build/overview) +- [GitHub](https://github.com/thirdweb-dev/contracts) + +## 관련 튜토리얼 {#related-tutorials} + +- [이더리움 개발자를 위한 보안 고려사항](/developers/docs/smart-contracts/security/) _– 라이브러리 사용을 포함하여 스마트 계약을 구축할 때의 보안 고려사항에 대한 튜토리얼입니다._ +- [ERC-20 토큰 스마트 계약 이해하기](/developers/tutorials/understand-the-erc-20-token-smart-contract/) _- 여러 라이브러리에서 제공하는 ERC20 표준에 대한 튜토리얼입니다._ + +## 더 읽어보기 {#further-reading} + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ diff --git a/public/content/translations/ko/developers/docs/smart-contracts/naming/index.md b/public/content/translations/ko/developers/docs/smart-contracts/naming/index.md new file mode 100644 index 00000000000..13ee813accc --- /dev/null +++ b/public/content/translations/ko/developers/docs/smart-contracts/naming/index.md @@ -0,0 +1,101 @@ +--- +title: "스마트 계약 이름 지정" +description: "ENS로 이더리움 스마트 계약 이름을 지정하는 모범 사례" +lang: ko +--- + +스마트 계약은 이더리움 탈중앙화 인프라의 핵심으로, 자율적인 애플리케이션과 프로토콜을 가능하게 합니다. 하지만 계약 기능이 발전함에도 불구하고 사용자와 개발자는 여전히 원시 16진수 주소에 의존하여 이러한 계약을 식별하고 참조합니다. + +[Ethereum Name Service(ENS)](https://ens.domains/)로 스마트 계약에 이름을 지정하면 16진수 계약 주소를 제거하여 사용자 경험을 개선하고 주소 포이즈닝 및 스푸핑 공격과 같은 공격의 위험을 줄일 수 있습니다. 이 가이드에서는 스마트 계약 이름 지정이 중요한 이유, 구현 방법, 그리고 [Enscribe](https://www.enscribe.xyz)와 같이 프로세스를 간소화하고 개발자가 이 관행을 채택하는 데 도움이 되는 도구에 대해 설명합니다. + +## 스마트 계약에 이름을 지정하는 이유는 무엇일까요? {#why-name-contracts} + +### 사람이 읽을 수 있는 식별자 {#human-readable-identifiers} + +개발자와 사용자는 `0x8f8e...f9e3`과 같이 불투명한 계약 주소와 상호작용하는 대신 `v2.myapp.eth`와 같이 사람이 읽을 수 있는 이름을 사용할 수 있습니다. 이는 스마트 계약 상호작용을 간소화합니다. + +이는 이더리움 주소에 대한 탈중앙화 이름 지정 서비스를 제공하는 [Ethereum Name Service](https://ens.domains/)를 통해 가능합니다. 이는 인터넷 사용자가 `104.18.176.152`와 같은 IP 주소 대신 ethereum.org와 같은 이름을 사용하여 네트워크 주소에 접속할 수 있도록 하는 도메인 이름 서비스(DNS)와 유사합니다. + +### 향상된 보안 및 신뢰 {#improved-security-and-trust} + +이름이 지정된 계약은 잘못된 주소로의 의도치 않은 거래를 줄이는 데 도움이 됩니다. 또한 사용자가 특정 앱 또는 브랜드와 연결된 계약을 식별하는 데 도움이 됩니다. 이는 특히 `uniswap.eth`와 같이 잘 알려진 상위 도메인에 이름이 연결된 경우 평판 신뢰도를 한층 더 높여줍니다. + +이더리움 주소는 42자 길이이므로 사용자가 몇 글자만 수정된 주소의 작은 변화를 식별하기가 매우 어렵습니다. 예를 들어, `0x58068646C148E313CB414E85d2Fe89dDc3426870`과 같은 주소는 일반적으로 지갑과 같은 사용자용 애플리케이션에서 `0x580...870`으로 잘립니다. 사용자는 몇 글자가 변경된 악의적인 주소를 알아차리기 어렵습니다. + +이러한 유형의 기술은 주소 스푸핑 및 포이즈닝 공격에 사용되며, 사용자는 올바른 주소와 상호작용하거나 자금을 보내고 있다고 믿게 되지만 실제로는 해당 주소가 올바른 주소와 유사할 뿐 동일하지는 않습니다. + +지갑과 계약에 대한 ENS 이름은 이러한 유형의 공격으로부터 보호합니다. DNS 스푸핑 공격과 마찬가지로 ENS 스푸핑 공격도 발생할 수 있지만, 사용자는 16진수 주소의 작은 수정보다 ENS 이름의 오타를 더 쉽게 알아차릴 수 있습니다. + +### 지갑 및 탐색기를 위한 더 나은 UX {#better-ux} + +스마트 계약이 ENS 이름으로 구성된 경우 지갑 및 블록체인 탐색기와 같은 앱에서 16진수 주소 대신 스마트 계약에 대한 ENS 이름을 표시할 수 있습니다. 이는 사용자에게 상당한 사용자 경험(UX) 향상을 제공합니다. + +예를 들어, Uniswap과 같은 앱과 상호작용할 때 사용자는 일반적으로 상호작용하는 앱이 `uniswap.org` 웹사이트에서 호스팅된다는 것을 알 수 있지만, Uniswap이 스마트 계약에 ENS 이름을 지정하지 않은 경우 16진수 계약 주소가 표시됩니다. 계약에 이름이 지정된 경우 대신 훨씬 더 유용한 `v4.contracts.uniswap.eth`를 볼 수 있습니다. + +## 배포 시점의 이름 지정 vs. 배포 후 이름 지정 {#when-to-name} + +스마트 계약에 이름을 지정할 수 있는 시점은 두 가지입니다. + +- **배포 시점**: 계약이 배포될 때 ENS 이름을 할당합니다. +- **배포 후**: 기존 계약 주소를 새로운 ENS 이름에 매핑합니다. + +두 가지 접근 방식 모두 ENS 레코드를 생성하고 설정할 수 있도록 ENS 도메인에 대한 소유자 또는 관리자 액세스 권한이 있어야 합니다. + +## 계약에 대한 ENS 이름 지정 작동 방식 {#how-ens-naming-works} + +ENS 이름은 온체인에 저장되며 ENS 확인자를 통해 이더리움 주소로 확인됩니다. 스마트 계약에 이름을 지정하려면: + +1. 상위 ENS 도메인(예: `myapp.eth`)을 등록하거나 제어합니다. +2. 하위 도메인(예: `v1.myapp.eth`)을 생성합니다. +3. 하위 도메인의 `address` 레코드를 계약 주소로 설정합니다. +4. 계약의 역방향 레코드를 ENS로 설정하여 주소를 통해 이름을 찾을 수 있도록 합니다. + +ENS 이름은 계층적이며 무제한의 하위 이름을 지원합니다. 이러한 레코드를 설정하려면 일반적으로 ENS 레지스트리 및 공용 확인자 계약과 상호작용해야 합니다. + +## 계약 이름 지정을 위한 도구 {#tools} + +스마트 계약에 이름을 지정하는 데는 두 가지 접근 방식이 있습니다. 몇 가지 수동 단계를 거쳐 [ENS 앱](https://app.ens.domains)을 사용하거나 [Enscribe](https://www.enscribe.xyz)를 사용하는 방법이 있습니다. 이에 대한 내용은 아래에 설명되어 있습니다. + +### 수동 ENS 설정 {#manual-ens-setup} + +[ENS 앱](https://app.ens.domains/)을 사용하여 개발자는 수동으로 하위 이름을 생성하고 정방향 주소 레코드를 설정할 수 있습니다. 그러나 ENS 앱을 통해 이름에 대한 역방향 레코드를 설정하여 스마트 계약의 기본 이름을 설정할 수는 없습니다. [ENS 문서](https://docs.ens.domains/web/naming-contracts/)에 설명된 수동 단계를 수행해야 합니다. + +### Enscribe {#enscribe} + +[Enscribe](https://www.enscribe.xyz)는 ENS를 사용하여 스마트 계약 이름 지정을 간소화하고 스마트 계약에 대한 사용자 신뢰를 향상시킵니다. 다음과 같은 기능을 제공합니다. + +- **원자적 배포 및 이름 지정**: 새 계약을 배포할 때 ENS 이름을 할당합니다. +- **배포 후 이름 지정**: 이미 배포된 계약에 이름을 연결합니다. +- **멀티체인 지원**: ENS가 지원되는 이더리움 및 L2 네트워크에서 작동합니다. +- **계약 검증 데이터**: 여러 소스에서 가져온 계약 검증 데이터를 포함하여 사용자의 신뢰를 높입니다. + +Enscribe는 사용자가 제공한 ENS 이름 또는 사용자가 ENS 이름이 없는 경우 자체 도메인을 지원합니다. + +[Enscribe 앱](https://app.enscribe.xyz)에 접속하여 스마트 계약의 이름을 지정하고 볼 수 있습니다. + +## 모범 사례 {#best-practices} + +- **`v1.myapp.eth`와 같이 명확하고 버전이 지정된 이름 사용**: 계약 업그레이드를 투명하게 만듭니다. +- **역방향 레코드 설정**: 계약을 ENS 이름에 연결하여 지갑 및 블록체인 탐색기와 같은 앱에서 가시성을 확보합니다. +- **만료일 면밀히 모니터링**: 의도치 않은 소유권 변경을 방지하려면 만료일을 면밀히 모니터링하세요. +- **계약 소스 확인**: 사용자가 이름이 지정된 계약이 예상대로 작동하는지 신뢰할 수 있도록 계약 소스를 확인하세요. + +## 위험 {#risks} + +스마트 계약의 이름을 지정하면 이더리움 사용자에게 상당한 이점을 제공하지만, ENS 도메인 소유자는 관리에 주의를 기울여야 합니다. 주요 위험은 다음과 같습니다. + +- **만료**: DNS 이름과 마찬가지로 ENS 이름 등록은 유한한 기간 동안만 유효합니다. 따라서 소유자는 도메인 만료일을 모니터링하고 만료일보다 훨씬 전에 갱신하는 것이 중요합니다. ENS 앱과 Enscribe 모두 만료가 다가올 때 도메인 소유자에게 시각적 표시기를 제공합니다. +- **소유권 변경**: ENS 레코드는 이더리움에서 NFT로 표시되며, 특정 `.eth` 도메인의 소유자는 관련 NFT를 소유하게 됩니다. 따라서 다른 계정이 이 NFT의 소유권을 갖게 되면 새 소유자는 자신의 재량에 따라 모든 ENS 레코드를 수정할 수 있습니다. + +이러한 위험을 완화하려면 `.eth` 2단계 도메인(2LD)의 소유자 계정을 다중 서명 지갑을 통해 보호하고 하위 도메인을 생성하여 계약 이름 지정을 관리해야 합니다. 그렇게 하면 하위 도메인 수준에서 우발적이거나 악의적인 소유권 변경이 발생하더라도 2LD 소유자가 이를 무효화할 수 있습니다. + +## 계약 이름 지정의 미래 {#future} + +계약 이름 지정은 웹에서 도메인 이름이 IP 주소를 대체한 것과 유사하게 디앱 개발의 모범 사례가 되고 있습니다. 지갑, 탐색기, 대시보드와 같은 더 많은 인프라가 계약에 대한 ENS 확인 기능을 통합함에 따라, 이름이 지정된 계약은 생태계 전반의 안전성을 개선하고 오류를 줄일 것입니다. + +스마트 계약을 더 쉽게 인식하고 추론할 수 있도록 함으로써, 이름 지정은 이더리움의 사용자와 앱 간의 간극을 메워 사용자의 안전과 UX를 모두 향상시키는 데 도움이 됩니다. + +## 더 읽어보기 {#further-reading} + +- [ENS로 스마트 계약 이름 지정하기](https://docs.ens.domains/web/naming-contracts/) +- [Enscribe로 스마트 계약 이름 지정하기](https://www.enscribe.xyz/docs). diff --git a/public/content/translations/ko/developers/docs/smart-contracts/security/index.md b/public/content/translations/ko/developers/docs/smart-contracts/security/index.md new file mode 100644 index 00000000000..9c4bdbeec85 --- /dev/null +++ b/public/content/translations/ko/developers/docs/smart-contracts/security/index.md @@ -0,0 +1,573 @@ +--- +title: "스마트 콘트랙트 감사" +description: "안전한 이더리움 스마트 계약을 구축하기 위한 가이드라인 개요" +lang: ko +--- + +스마트 계약은 블록체인에 배포된 코드를 기반으로 변경 불가능한 로직을 실행하면서, 매우 유연하고 막대한 가치와 데이터를 제어할 수 있습니다. 이로 인해 기존 시스템보다 많은 이점을 제공하는 무신뢰 및 탈중앙화 애플리케이션의 활발한 생태계가 조성되었습니다. 또한 스마트 계약의 취약점을 악용하여 이익을 얻으려는 공격자에게는 기회가 되기도 합니다. + +이더리움과 같은 퍼블릭 블록체인은 스마트 계약 보안 문제를 더욱 복잡하게 만듭니다. 배포된 계약 코드는 _보통_ 보안 결함을 패치하기 위해 변경될 수 없으며, 스마트 계약에서 도난당한 자산은 불변성 때문에 추적이 매우 어렵고 대부분 복구할 수 없습니다. + +수치는 다양하지만, 스마트 계약의 보안 결함으로 인해 도난당하거나 손실된 총 가치는 10억 달러를 훌쩍 넘는 것으로 추정됩니다. 여기에는 [DAO 해킹](https://hackingdistributed.com/2016/06/18/analysis-of-the-dao-exploit/)(360만 ETH 도난, 현재 시가로 10억 달러 이상), [Parity 다중 서명 지갑 해킹](https://www.coindesk.com/markets/2017/07/19/30-million-ether-reported-stolen-due-to-parity-wallet-breach)(해커에게 3,000만 달러 손실), [Parity 지갑 동결 문제](https://www.theguardian.com/technology/2017/nov/08/cryptocurrency-300m-dollars-stolen-bug-ether)(3억 달러 이상의 ETH가 영구적으로 동결) 등 세간의 이목을 끈 사건들이 포함됩니다. + +앞서 언급한 문제들로 인해 개발자들은 안전하고, 견고하며, 복원력 있는 스마트 계약을 구축하는 데 노력을 기울여야 합니다. 스마트 계약 보안은 중요한 문제이며, 모든 개발자가 잘 배워두면 좋은 것입니다. 이 가이드에서는 이더리움 개발자를 위한 보안 고려 사항을 다루고 스마트 계약 보안을 개선하기 위한 참고 자료를 알아봅니다. + +## 필수 구성 요소 {#prerequisites} + +보안 문제를 다루기 전에 [스마트 계약 개발의 기초](/developers/docs/smart-contracts/)에 익숙해지도록 하세요. + +## 안전한 이더리움 스마트 계약을 구축하기 위한 가이드라인 {#smart-contract-security-guidelines} + +### 1. 적절한 접근 제어 설계 {#design-proper-access-controls} + +스마트 계약에서 `public` 또는 `external`로 표시된 함수는 모든 외부 소유 계정(EOA) 또는 계약 계정에서 호출할 수 있습니다. 다른 사람이 사용자의 계약과 상호 작용하기를 원한다면 함수에 공용 가시성을 지정해야 합니다. 그러나 `private`로 표시된 함수는 스마트 계약 내의 함수에서만 호출할 수 있으며 외부 계정에서는 호출할 수 없습니다. 모든 네트워크 참여자에게 계약 함수에 대한 접근 권한을 부여하면 문제가 발생할 수 있으며, 특히 누구나 민감한 작업(예: 새로운 토큰 발행)을 수행할 수 있다는 것을 의미하는 경우 더욱 그렇습니다. + +스마트 계약 함수의 무단 사용을 방지하려면 안전한 접근 제어를 구현해야 합니다. 접근 제어 메커니즘은 스마트 계약에서 특정 함수를 사용할 수 있는 권한을 계약 관리를 책임지는 계정과 같이 승인된 주체로 제한합니다. 소유 가능 패턴역할 기반 제어는 스마트 계약에서 접근 제어를 구현하는 데 유용한 두 가지 패턴입니다. + +#### 소유 가능 패턴 {#ownable-pattern} + +소유 가능 패턴에서는 계약 생성 과정에서 주소가 계약의 '소유자'로 설정됩니다. 보호된 함수에는 `OnlyOwner` 수정자가 할당되어 계약이 함수를 실행하기 전에 호출 주소의 신원을 인증하도록 합니다. 계약 소유자가 아닌 다른 주소에서 보호된 함수를 호출하면 항상 되돌려지므로 원치 않는 접근을 방지할 수 있습니다. + +#### 역할 기반 접근 제어 {#role-based-access-control} + +스마트 계약에서 단일 주소를 `Owner`로 등록하면 중앙화의 위험이 발생하고 단일 실패 지점이 됩니다. 소유자의 계정 키가 손상되면 공격자가 소유 계약을 공격할 수 있습니다. 이것이 여러 관리 계정이 있는 역할 기반 접근 제어 패턴을 사용하는 것이 더 나은 선택일 수 있는 이유입니다. + +역할 기반 접근 제어에서 민감한 기능에 대한 접근은 신뢰할 수 있는 참여자 집합 간에 분산됩니다. 예를 들어, 한 계정은 토큰 발행을 담당하고 다른 계정은 계약을 업그레이드하거나 일시 중지하는 작업을 수행할 수 있습니다. 이러한 방식으로 접근 제어를 분산하면 단일 실패 지점을 제거하고 사용자에 대한 신뢰 가정을 줄일 수 있습니다. + +##### 다중 서명 지갑 사용 + +안전한 접근 제어를 구현하는 또 다른 방법은 [다중 서명 계정](/developers/docs/smart-contracts/#multisig)을 사용하여 계약을 관리하는 것입니다. 일반 EOA와 달리 다중 서명 계정은 여러 엔티티가 소유하며 트랜잭션을 실행하려면 최소 계정 수(예: 5개 중 3개)의 서명이 필요합니다. + +접근 제어에 다중 서명을 사용하면 대상 계약에 대한 조치에 여러 당사자의 동의가 필요하므로 보안 계층이 추가됩니다. 이는 공격자나 불량 내부자가 악의적인 목적으로 민감한 계약 기능을 조작하기 어렵게 만들기 때문에 소유 가능 패턴을 사용하는 것이 필요한 경우 특히 유용합니다. + +### 2. require(), assert() 및 revert() 문을 사용하여 계약 작업을 보호하세요 {#use-require-assert-revert} + +언급했듯이 스마트 계약이 블록체인에 배포되면 누구나 스마트 계약의 공용 함수를 호출할 수 있습니다. 외부 계정이 계약과 어떻게 상호 작용할지 미리 알 수 없으므로 배포하기 전에 문제가 있는 작업에 대한 내부 보호 장치를 구현하는 것이 이상적입니다. 실행이 특정 요구 사항을 충족하지 못하는 경우 예외를 트리거하고 상태 변경을 되돌리기 위해 `require()`, `assert()` 및 `revert()` 문을 사용하여 스마트 계약에서 올바른 동작을 적용할 수 있습니다. + +**`require()`**: `require`는 함수 시작 부분에 정의되며 호출된 함수가 실행되기 전에 미리 정의된 조건이 충족되도록 합니다. `require` 문은 함수를 진행하기 전에 사용자 입력을 검증하거나, 상태 변수를 확인하거나, 호출 계정의 신원을 인증하는 데 사용할 수 있습니다. + +**`assert()`**: `assert()`는 내부 오류를 감지하고 코드의 '불변' 위반을 확인하는 데 사용됩니다. 불변은 모든 함수 실행에 대해 사실이어야 하는 계약의 상태에 대한 논리적 주장입니다. 불변의 예는 토큰 계약의 최대 총 공급량 또는 잔액입니다. `assert()`를 사용하면 계약이 취약한 상태에 도달하지 않도록 하고, 만약 그렇게 되면 상태 변수에 대한 모든 변경 사항이 롤백됩니다. + +**`revert()`**: `revert()`는 필요한 조건이 충족되지 않으면 예외를 트리거하는 if-else 문에서 사용할 수 있습니다. 아래 샘플 계약은 `revert()`를 사용하여 함수 실행을 보호합니다. + +``` +pragma solidity ^0.8.4; + +contract VendingMachine { + address owner; + error Unauthorized(); + function buy(uint amount) public payable { + if (amount > msg.value / 2 ether) + revert("제공된 이더가 충분하지 않습니다."); + // 구매를 수행합니다. + } + function withdraw() public { + if (msg.sender != owner) + revert Unauthorized(); + + payable(msg.sender).transfer(address(this).balance); + } +} +``` + +### 3. 스마트 계약 테스트 및 코드 정확성 확인 {#test-smart-contracts-and-verify-code-correctness} + +[이더리움 가상 머신](/developers/docs/evm/)에서 실행되는 코드의 불변성은 스마트 계약이 개발 단계에서 더 높은 수준의 품질 평가를 요구함을 의미합니다. 계약을 광범위하게 테스트하고 예기치 않은 결과가 있는지 관찰하면 보안이 크게 향상되고 장기적으로 사용자를 보호할 수 있습니다. + +일반적인 방법은 계약이 사용자로부터 받을 것으로 예상되는 모의 데이터를 사용하여 작은 단위 테스트를 작성하는 것입니다. [단위 테스트](/developers/docs/smart-contracts/testing/#unit-testing)는 특정 기능의 기능을 테스트하고 스마트 계약이 예상대로 작동하는지 확인하는 데 좋습니다. + +불행히도 단위 테스트는 단독으로 사용될 때 스마트 계약 보안을 향상시키는 데 최소한의 효과만 있습니다. 단위 테스트는 모의 데이터에 대해 함수가 제대로 실행됨을 증명할 수 있지만, 단위 테스트는 작성된 테스트만큼만 효과적입니다. 이로 인해 스마트 계약의 안전을 위협할 수 있는 누락된 엣지 케이스와 취약점을 감지하기가 어렵습니다. + +더 나은 접근 방식은 [정적 및 동적 분석](/developers/docs/smart-contracts/testing/#static-dynamic-analysis)을 사용하여 수행되는 속성 기반 테스트와 단위 테스트를 결합하는 것입니다. 정적 분석은 [제어 흐름 그래프](https://en.wikipedia.org/wiki/Control-flow_graph) 및 [추상 구문 트리](https://deepsource.io/glossary/ast/)와 같은 저수준 표현에 의존하여 도달 가능한 프로그램 상태 및 실행 경로를 분석합니다. 한편, [스마트 계약 퍼징](https://www.cyfrin.io/blog/smart-contract-fuzzing-and-invariants-testing-foundry)과 같은 동적 분석 기술은 임의의 입력 값으로 계약 코드를 실행하여 보안 속성을 위반하는 작업을 감지합니다. + +[공식 검증](/developers/docs/smart-contracts/formal-verification)은 스마트 계약의 보안 속성을 검증하는 또 다른 기술입니다. 일반 테스트와 달리 공식 검증은 스마트 계약에 오류가 없음을 결정적으로 증명할 수 있습니다. 이는 원하는 보안 속성을 캡처하는 공식 사양을 만들고 계약의 공식 모델이 이 사양을 준수함을 증명함으로써 달성됩니다. + +### 4. 코드에 대한 독립적인 검토를 요청하세요 {#get-independent-code-reviews} + +계약을 테스트한 후 다른 사람들에게 소스 코드에 보안 문제가 있는지 확인하도록 요청하는 것이 좋습니다. 테스트를 통해 스마트 계약의 모든 결함을 발견할 수는 없지만 독립적인 검토를 받으면 취약점을 발견할 가능성이 높아집니다. + +#### 감사 {#audits} + +스마트 계약 감사를 의뢰하는 것은 독립적인 코드 검토를 수행하는 한 가지 방법입니다. 감사자는 스마트 계약이 안전하고 품질 결함 및 설계 오류가 없는지 확인하는 데 중요한 역할을 합니다. + +그렇다고 감사를 만병통치약으로 취급해서는 안 됩니다. 스마트 계약 감사는 모든 버그를 잡지 못하며 대부분 추가 검토를 제공하도록 설계되어 개발자가 초기 개발 및 테스트 중에 놓친 문제를 감지하는 데 도움이 될 수 있습니다. 또한 스마트 계약 감사의 이점을 극대화하려면 코드를 적절하게 문서화하고 인라인 주석을 추가하는 등 감사자와 작업하기 위한 모범 사례를 따라야 합니다. + +- [스마트 계약 감사 팁 및 요령](https://twitter.com/tinchoabbate/status/1400170232904400897) - _@tinchoabbate_ +- [감사를 최대한 활용하기](https://inference.ag/blog/2023-08-14-tips/) - _Inference_ + +#### 버그 포상금 {#bug-bounties} + +버그 포상금 프로그램을 설정하는 것은 외부 코드 검토를 구현하는 또 다른 접근 방식입니다. 버그 포상금은 애플리케이션에서 취약점을 발견한 개인(보통 화이트햇 해커)에게 주어지는 금전적 보상입니다. + +적절하게 사용하면 버그 포상금은 해커 커뮤니티 구성원에게 코드에 중요한 결함이 있는지 검사하도록 인센티브를 제공합니다. 실제 예는 이더리움에서 실행되는 [레이어 2](/layer-2/) 프로토콜인 [Optimism](https://www.optimism.io/)에서 공격자가 무제한의 이더를 생성할 수 있었던 '무한 돈 버그'입니다. 다행히 화이트햇 해커가 [결함을 발견하고](https://www.saurik.com/optimism.html) 팀에 통보하여 [그 과정에서 큰 포상금을 받았습니다](https://cryptoslate.com/critical-bug-in-ethereum-l2-optimism-2m-bounty-paid/). + +유용한 전략은 이해 관계가 있는 자금의 양에 비례하여 버그 포상금 프로그램의 지불금을 설정하는 것입니다. “[스케일링 버그 포상금](https://medium.com/immunefi/a-defi-security-standard-the-scaling-bug-bounty-9b83dfdc1ba7)”으로 설명되는 이 접근 방식은 개인이 취약점을 악용하는 대신 책임감 있게 공개하도록 재정적 인센티브를 제공합니다. + +### 5. 스마트 계약 개발 중 모범 사례 따르기 {#follow-smart-contract-development-best-practices} + +감사 및 버그 포상금의 존재가 고품질 코드를 작성해야 할 책임을 면제해주지는 않습니다. 우수한 스마트 계약 보안은 적절한 설계 및 개발 프로세스를 따르는 것에서 시작됩니다. + +- git과 같은 버전 제어 시스템에 모든 코드를 저장 + +- 풀 리퀘스트를 통해 모든 코드 수정하기 + +- 풀 리퀘스트에 최소 한 명의 독립적인 검토자가 있는지 확인하세요. 프로젝트에서 단독으로 작업하는 경우 다른 개발자를 찾아 코드 검토를 교환하는 것을 고려하세요. + +- 스마트 계약 테스트, 컴파일, 배포를 위해 [개발 환경](/developers/docs/frameworks/)을 사용하세요. + +- 코드를 [Cyfrin Aderyn](https://github.com/Cyfrin/aderyn), Mythril 및 Slither와 같은 기본 코드 분석 도구로 실행하세요. 이상적으로는 각 풀 리퀘스트가 병합되기 전에 이 작업을 수행하고 출력의 차이점을 비교해야 합니다. + +- 코드가 오류 없이 컴파일되고 솔리디티 컴파일러가 경고를 내보내지 않도록 확인하세요. + +- 코드를 ([NatSpec](https://solidity.readthedocs.io/en/develop/natspec-format.html)을 사용하여) 적절히 문서화하고 계약 아키텍처에 대한 세부 정보를 이해하기 쉬운 언어로 설명하세요. 이렇게 하면 다른 사람들이 코드를 감사하고 검토하기가 더 쉬워집니다. + +### 6. 견고한 재해 복구 계획 구현 {#implement-disaster-recovery-plans} + +안전한 접근 제어 설계, 기능 수정자 구현 및 기타 제안은 스마트 계약 보안을 향상시킬 수 있지만 악의적인 공격의 가능성을 배제할 수는 없습니다. 안전한 스마트 계약을 구축하려면 '실패에 대비'하고 공격에 효과적으로 대응하기 위한 대체 계획을 마련해야 합니다. 적절한 재해 복구 계획에는 다음 구성 요소의 일부 또는 전부가 포함됩니다. + +#### 계약 업그레이드 {#contract-upgrades} + +이더리움 스마트 계약은 기본적으로 불변이지만 업그레이드 패턴을 사용하여 어느 정도의 가변성을 달성할 수 있습니다. 계약 업그레이드는 중요한 결함으로 인해 기존 계약을 사용할 수 없게 되고 새로운 로직을 배포하는 것이 가장 실현 가능한 옵션인 경우에 필요합니다. + +계약 업그레이드 메커니즘은 다르게 작동하지만 '프록시 패턴'은 스마트 계약 업그레이드를 위한 더 인기 있는 접근 방식 중 하나입니다. [프록시 패턴](https://www.cyfrin.io/blog/upgradeable-proxy-smart-contract-pattern)은 애플리케이션의 상태와 로직을 _두_ 계약으로 나눕니다. 첫 번째 계약('프록시 계약')은 상태 변수(예: 사용자 잔액)를 저장하고, 두 번째 계약('로직 계약')은 계약 기능을 실행하기 위한 코드를 보유합니다. + +계정은 프록시 계약과 상호 작용하며, 프록시 계약은 [`delegatecall()`](https://docs.soliditylang.org/en/v0.8.16/introduction-to-smart-contracts.html?highlight=delegatecall#delegatecall-callcode-and-libraries) 저수준 호출을 사용하여 모든 함수 호출을 로직 계약으로 보냅니다. 일반 메시지 호출과 달리 `delegatecall()`은 로직 계약의 주소에서 실행되는 코드가 호출 계약의 컨텍스트에서 실행되도록 보장합니다. 이는 로직 계약이 항상 자신의 저장 공간 대신 프록시의 저장 공간에 쓰고 `msg.sender` 및 `msg.value`의 원래 값이 보존됨을 의미합니다. + +로직 계약에 대한 호출을 위임하려면 해당 주소를 프록시 계약의 저장 공간에 저장해야 합니다. 따라서 계약의 로직을 업그레이드하는 것은 다른 로직 계약을 배포하고 새 주소를 프록시 계약에 저장하는 문제일 뿐입니다. 프록시 계약에 대한 후속 호출은 자동으로 새 로직 계약으로 라우팅되므로 실제로 코드를 수정하지 않고도 계약을 '업그레이드'하게 됩니다. + +[계약 업그레이드에 대해 더 알아보기](/developers/docs/smart-contracts/upgrading/). + +#### 긴급 중지 {#emergency-stops} + +언급했듯이 광범위한 감사 및 테스트로 스마트 계약의 모든 버그를 발견할 수는 없습니다. 배포 후 코드에 취약점이 나타나면 계약 주소에서 실행되는 코드를 변경할 수 없으므로 패치하는 것이 불가능합니다. 또한 업그레이드 메커니즘(예: 프록시 패턴)은 구현하는 데 시간이 걸릴 수 있으며(종종 다른 당사자의 승인이 필요함), 이는 공격자에게 더 많은 피해를 입힐 시간을 줄 뿐입니다. + +핵심 옵션은 계약의 취약한 기능에 대한 호출을 차단하는 '긴급 중지' 기능을 구현하는 것입니다. 긴급 중지는 일반적으로 다음 구성 요소로 구성됩니다. + +1. 스마트 계약이 중지된 상태인지 여부를 나타내는 전역 부울 변수입니다. 이 변수는 계약 설정 시 `false`로 설정되지만 계약이 중지되면 `true`로 되돌아갑니다. + +2. 실행 시 부울 변수를 참조하는 함수. 이러한 함수는 스마트 계약이 중지되지 않았을 때 접근할 수 있으며, 긴급 중지 기능이 트리거되면 접근할 수 없게 됩니다. + +3. 부울 변수를 `true`로 설정하는 긴급 중지 기능에 접근할 수 있는 엔티티입니다. 악의적인 행위를 방지하기 위해 이 함수에 대한 호출은 신뢰할 수 있는 주소(예: 계약 소유자)로 제한될 수 있습니다. + +계약이 긴급 중지를 활성화하면 특정 함수를 호출할 수 없게 됩니다. 이는 전역 변수를 참조하는 수정자로 선택 함수를 래핑하여 달성됩니다. 아래는 계약에서 이 패턴의 구현을 설명하는 [예제](https://github.com/fravoll/solidity-patterns/blob/master/EmergencyStop/EmergencyStop.sol)입니다. + +```solidity +// 이 코드는 전문적인 감사를 받지 않았으며 안전성이나 정확성에 대해 어떠한 약속도 하지 않습니다. 자신의 책임 하에 사용하세요. + +contract EmergencyStop { + + bool isStopped = false; + + modifier stoppedInEmergency { + require(!isStopped); + _; + } + + modifier onlyWhenStopped { + require(isStopped); + _; + } + + modifier onlyAuthorized { + // 여기에서 msg.sender의 권한을 확인하세요 + _; + } + + function stopContract() public onlyAuthorized { + isStopped = true; + } + + function resumeContract() public onlyAuthorized { + isStopped = false; + } + + function deposit() public payable stoppedInEmergency { + // 입금 로직이 여기서 발생합니다 + } + + function emergencyWithdraw() public onlyWhenStopped { + // 긴급 인출이 여기서 발생합니다 + } +} +``` + +이 예제는 긴급 중지의 기본 기능을 보여줍니다. + +- `isStopped`는 처음에 `false`로 평가되고 계약이 긴급 모드로 들어가면 `true`로 평가되는 부울입니다. + +- 함수 수정자 `onlyWhenStopped`와 `stoppedInEmergency`는 `isStopped` 변수를 확인합니다. `stoppedInEmergency`는 계약이 취약할 때 접근할 수 없어야 하는 함수(예: `deposit()`)를 제어하는 데 사용됩니다. 이러한 함수에 대한 호출은 단순히 되돌려집니다. + +`onlyWhenStopped`는 긴급 상황 시 호출 가능해야 하는 함수(예: `emergencyWithdraw()`)에 사용됩니다. 이러한 함수는 상황 해결에 도움이 될 수 있으므로 '제한된 함수' 목록에서 제외됩니다. + +긴급 중지 기능을 사용하면 스마트 계약의 심각한 취약점을 처리하기 위한 효과적인 임시 방편을 제공합니다. 그러나 사용자가 개발자가 이기적인 이유로 이를 활성화하지 않을 것이라고 신뢰해야 할 필요성이 증가합니다. 이를 위해 온체인 투표 메커니즘, 타임락 또는 다중 서명 지갑의 승인을 통해 긴급 중지 제어를 분산하는 것이 가능한 해결책입니다. + +#### 이벤트 모니터링 {#event-monitoring} + +[이벤트](https://docs.soliditylang.org/en/v0.8.15/contracts.html#events)를 사용하면 스마트 계약 함수에 대한 호출을 추적하고 상태 변수의 변경 사항을 모니터링할 수 있습니다. 어떤 당사자가 안전에 중요한 조치(예: 자금 인출)를 취할 때마다 이벤트를 발생시키도록 스마트 계약을 프로그래밍하는 것이 이상적입니다. + +이벤트를 로깅하고 오프체인에서 모니터링하면 계약 운영에 대한 통찰력을 제공하고 악의적인 행동을 더 빨리 발견하는 데 도움이 됩니다. 이는 팀이 해킹에 더 빨리 대응하고 기능 일시 중지 또는 업그레이드 수행과 같은 사용자에게 미치는 영향을 완화하기 위한 조치를 취할 수 있음을 의미합니다. + +누군가 계약과 상호 작용할 때마다 자동으로 알림을 전달하는 기성 모니터링 도구를 선택할 수도 있습니다. 이러한 도구를 사용하면 트랜잭션 양, 함수 호출 빈도 또는 관련된 특정 함수와 같은 다양한 트리거를 기반으로 사용자 지정 알림을 만들 수 있습니다. 예를 들어, 단일 트랜잭션에서 인출된 금액이 특정 임계값을 초과할 때 들어오는 알림을 프로그래밍할 수 있습니다. + +### 7. 안전한 거버넌스 시스템 설계 {#design-secure-governance-systems} + +핵심 스마트 계약의 통제권을 커뮤니티 구성원에게 넘겨 애플리케이션을 분산화할 수 있습니다. 이 경우 스마트 계약 시스템에는 거버넌스 모듈, 즉 커뮤니티 구성원이 온체인 거버넌스 시스템을 통해 관리 조치를 승인할 수 있는 메커니즘이 포함됩니다. 예를 들어, 프록시 계약을 새 구현으로 업그레이드하자는 제안은 토큰 보유자들의 투표에 부쳐질 수 있습니다. + +분산형 거버넌스는 특히 개발자와 최종 사용자의 이익을 일치시키기 때문에 유익할 수 있습니다. 그럼에도 불구하고 스마트 계약 거버넌스 메커니즘은 잘못 구현될 경우 새로운 위험을 초래할 수 있습니다. 있을 법한 시나리오는 공격자가 [플래시 론](/defi/#flash-loans)을 이용하여 엄청난 투표권(보유 토큰 수로 측정)을 획득하고 악의적인 제안을 통과시키는 경우입니다. + +온체인 거버넌스와 관련된 문제를 예방하는 한 가지 방법은 [타임락을 사용하는 것](https://blog.openzeppelin.com/protect-your-users-with-smart-contract-timelocks/)입니다. 타임락은 스마트 계약이 특정 시간이 지날 때까지 특정 작업을 실행하지 못하도록 합니다. 다른 전략으로는 각 토큰이 잠겨 있던 기간에 따라 '투표 가중치'를 할당하거나, 현재 블록이 아닌 과거의 특정 기간(예: 2-3 블록 전)에 주소의 투표권을 측정하는 것이 있습니다. 두 방법 모두 온체인 투표를 흔들기 위해 투표권을 빠르게 축적할 가능성을 줄여줍니다. + +공유된 링크에서 [안전한 거버넌스 시스템 설계](https://blog.openzeppelin.com/smart-contract-security-guidelines-4-strategies-for-safer-governance-systems/), [DAO의 다양한 투표 메커니즘](https://hackernoon.com/governance-is-the-holy-grail-for-daos) 및 [DeFi를 활용한 일반적인 DAO 공격 벡터](https://dacian.me/dao-governance-defi-attacks)에 대해 더 자세히 알아보세요. + +### 8. 코드의 복잡성을 최소화하세요 {#reduce-code-complexity} + +기존 소프트웨어 개발자들은 소프트웨어 설계에 불필요한 복잡성을 도입하지 말 것을 권고하는 KISS('keep it simple, stupid') 원칙에 익숙합니다. 이는 '복잡한 시스템은 복잡한 방식으로 실패한다'는 오랜 생각에 따른 것으로, 비용이 많이 드는 오류에 더 취약합니다. + +스마트 계약은 잠재적으로 막대한 가치를 제어하므로 스마트 계약을 작성할 때 단순함을 유지하는 것이 특히 중요합니다. 스마트 계약을 작성할 때 단순성을 달성하기 위한 팁은 가능한 경우 [OpenZeppelin Contracts](https://docs.openzeppelin.com/contracts/5.x/)와 같은 기존 라이브러리를 재사용하는 것입니다. 이러한 라이브러리는 개발자들에 의해 광범위하게 감사되고 테스트되었기 때문에, 이를 사용하면 처음부터 새로운 기능을 작성함으로써 버그를 도입할 가능성을 줄일 수 있습니다. + +또 다른 일반적인 조언은 작은 함수를 작성하고 비즈니스 로직을 여러 계약에 분산하여 계약을 모듈식으로 유지하는 것입니다. 더 간단한 코드를 작성하면 스마트 계약의 공격 표면을 줄일 수 있을 뿐만 아니라 전체 시스템의 정확성을 추론하고 가능한 설계 오류를 조기에 감지하기가 더 쉬워집니다. + +### 9. 일반적인 스마트 계약 취약점 방어 {#mitigate-common-smart-contract-vulnerabilities} + +#### 재진입 {#reentrancy} + +EVM은 동시성을 허용하지 않으므로 메시지 호출에 관련된 두 계약이 동시에 실행될 수 없습니다. 외부 호출은 호출이 반환될 때까지 호출 계약의 실행과 메모리를 일시 중지하며, 그 시점에서 실행은 정상적으로 진행됩니다. 이 과정은 다른 계약으로 [제어 흐름](https://www.computerhope.com/jargon/c/contflow.htm)을 이전하는 것으로 공식적으로 설명될 수 있습니다. + +대부분 무해하지만 신뢰할 수 없는 계약으로 제어 흐름을 이전하면 재진입과 같은 문제가 발생할 수 있습니다. 재진입 공격은 악성 계약이 원래 함수 호출이 완료되기 전에 취약한 계약으로 다시 호출할 때 발생합니다. 이 유형의 공격은 예시를 통해 가장 잘 설명됩니다. + +누구나 이더를 입금하고 인출할 수 있는 간단한 스마트 계약('Victim')을 고려해 보세요. + +```solidity +// 이 계약은 취약합니다. 프로덕션에서 사용하지 마세요 + +contract Victim { + mapping (address => uint256) public balances; + + function deposit() external payable { + balances[msg.sender] += msg.value; + } + + function withdraw() external { + uint256 amount = balances[msg.sender]; + (bool success, ) = msg.sender.call.value(amount)(""); + require(success); + balances[msg.sender] = 0; + } +} +``` + +이 계약은 사용자가 이전에 계약에 입금한 ETH를 인출할 수 있도록 `withdraw()` 함수를 노출합니다. 인출을 처리할 때 계약은 다음 작업을 수행합니다. + +1. 사용자의 ETH 잔액 확인 +2. 호출 주소로 자금 전송 +3. 사용자의 추가 인출을 방지하기 위해 잔액을 0으로 재설정 + +`Victim` 계약의 `withdraw()` 함수는 '확인-상호작용-효과' 패턴을 따릅니다. 실행에 필요한 조건이 충족되었는지 _확인_(즉, 사용자가 양의 ETH 잔액을 가지고 있는지)하고, 트랜잭션의 _효과_(즉, 사용자 잔액 감소)를 적용하기 전에 호출자의 주소로 ETH를 전송하여 상호작용을 수행합니다. + +`withdraw()`가 외부 소유 계정(EOA)에서 호출되면 함수는 예상대로 실행됩니다. `msg.sender.call.value()`는 호출자에게 ETH를 보냅니다. 그러나 `msg.sender`가 스마트 계약 계정이고 `withdraw()`를 호출하면, `msg.sender.call.value()`를 사용하여 자금을 보내는 것은 해당 주소에 저장된 코드를 실행하게 합니다. + +이것이 계약 주소에 배포된 코드라고 상상해보세요. + +```solidity + contract Attacker { + function beginAttack() external payable { + Victim(victim_address).deposit.value(1 ether)(); + Victim(victim_address).withdraw(); + } + + function() external payable { + if (gasleft() > 40000) { + Victim(victim_address).withdraw(); + } + } +} +``` + +이 계약은 세 가지를 하도록 설계되었습니다. + +1. 다른 계정(공격자의 EOA일 가능성 있음)으로부터 입금 받기 +2. Victim 계약에 1 ETH 입금하기 +3. 스마트 계약에 저장된 1 ETH 인출하기 + +여기에는 아무런 문제가 없지만, `Attacker`는 들어오는 `msg.sender.call.value`에서 남은 가스가 40,000 이상이면 `Victim`에서 `withdraw()`를 다시 호출하는 또 다른 함수를 가지고 있습니다. 이는 `Attacker`가 `Victim`에 재진입하여 첫 번째 `withdraw` 호출이 완료되기 _전에_ 더 많은 자금을 인출할 수 있는 능력을 부여합니다. 주기는 다음과 같습니다. + +```solidity +- 공격자의 EOA가 1 ETH로 `Attacker.beginAttack()`을 호출합니다 +- `Attacker.beginAttack()`이 `Victim`에 1 ETH를 입금합니다 +- `Attacker`가 `Victim`에서 `withdraw()`를 호출합니다 +- `Victim`이 `Attacker`의 잔액(1 ETH)을 확인합니다 +- `Victim`이 `Attacker`에게 1 ETH를 전송합니다(기본 함수를 트리거함) +- `Attacker`가 `Victim.withdraw()`를 다시 호출합니다(`Victim`은 첫 번째 인출에서 `Attacker`의 잔액을 줄이지 않았음에 유의) +- `Victim`이 `Attacker`의 잔액을 확인합니다(첫 번째 호출의 효과를 적용하지 않았기 때문에 여전히 1 ETH임) +- `Victim`이 `Attacker`에게 1 ETH를 전송합니다(기본 함수를 트리거하고 `Attacker`가 `withdraw` 함수에 재진입할 수 있게 함) +- `Attacker`가 가스를 모두 소진할 때까지 프로세스가 반복되며, 그 시점에서 `msg.sender.call.value`는 추가 인출을 트리거하지 않고 반환됩니다 +- `Victim`은 마침내 첫 번째 트랜잭션(및 후속 트랜잭션)의 결과를 상태에 적용하므로 `Attacker`의 잔액은 0으로 설정됩니다 +``` + +요약하자면, 함수 실행이 완료될 때까지 호출자의 잔액이 0으로 설정되지 않기 때문에 후속 호출이 성공하여 호출자가 잔액을 여러 번 인출할 수 있게 됩니다. [2016년 DAO 해킹](https://www.coindesk.com/learn/understanding-the-dao-attack)에서 일어난 것처럼, 이러한 종류의 공격은 스마트 계약의 자금을 고갈시키는 데 사용될 수 있습니다. [재진입 공격의 공개 목록](https://github.com/pcaversaccio/reentrancy-attacks)에서 알 수 있듯이, 재진입 공격은 오늘날에도 여전히 스마트 계약의 중요한 문제입니다. + +##### 재진입 공격을 예방하는 방법 + +재진입을 처리하는 한 가지 방법은 [확인-효과-상호작용 패턴](https://docs.soliditylang.org/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern)을 따르는 것입니다. 이 패턴은 실행을 진행하기 전에 필요한 확인을 수행하는 코드가 먼저 오고, 그 다음 계약 상태를 조작하는 코드가 오고, 마지막으로 다른 계약이나 EOA와 상호작용하는 코드가 오도록 함수 실행 순서를 정합니다. + +확인-효과-상호작용 패턴은 아래에 표시된 `Victim` 계약의 수정된 버전에서 사용됩니다. + +```solidity +contract NoLongerAVictim { + function withdraw() external { + uint256 amount = balances[msg.sender]; + balances[msg.sender] = 0; + (bool success, ) = msg.sender.call.value(amount)(""); + require(success); + } +} +``` + +이 계약은 사용자의 잔액을 확인하고, `withdraw()` 함수의 _효과_(사용자 잔액을 0으로 재설정)를 적용한 후 _상호작용_(사용자 주소로 ETH 전송)을 수행합니다. 이를 통해 계약은 외부 호출 전에 저장 공간을 업그레이드하여 첫 번째 공격을 가능하게 했던 재진입 조건을 제거합니다. `Attacker` 계약은 여전히 `NoLongerAVictim`을 다시 호출할 수 있지만, `balances[msg.sender]`가 0으로 설정되었기 때문에 추가 인출은 오류를 발생시킵니다. + +또 다른 옵션은 함수 호출이 완료될 때까지 계약 상태의 일부를 잠그는 상호 배제 잠금(일반적으로 '뮤텍스'라고 함)을 사용하는 것입니다. 이는 함수가 실행되기 전에 `true`로 설정되고 호출이 완료된 후 `false`로 되돌아가는 부울 변수를 사용하여 구현됩니다. 아래 예에서 볼 수 있듯이, 뮤텍스를 사용하면 원래 호출이 아직 처리 중인 동안 재귀 호출로부터 함수를 보호하여 재진입을 효과적으로 막을 수 있습니다. + +```solidity +pragma solidity ^0.7.0; + +contract MutexPattern { + bool locked = false; + mapping(address => uint256) public balances; + + modifier noReentrancy() { + require(!locked, "재진입이 차단되었습니다."); + locked = true; + _; + locked = false; + } + // 이 함수는 뮤텍스로 보호되므로 'msg.sender.call' 내에서 재진입 호출을 통해 'withdraw'를 다시 호출할 수 없습니다. + // 'return'문은 'true'로 평가되지만 여전히 수정자에서 'locked = false'문을 평가합니다 + function withdraw(uint _amount) public payable noReentrancy returns(bool) { + require(balances[msg.sender] >= _amount, "인출할 잔액이 없습니다."); + + balances[msg.sender] -= _amount; + (bool success, ) = msg.sender.call{value: _amount}(""); + require(success); + + return true; + } +} +``` + +계정으로 자금을 보내는 '푸시 지불' 시스템 대신, 사용자가 스마트 계약에서 자금을 인출해야 하는 [풀 지불](https://docs.openzeppelin.com/contracts/5.x/api/security#PullPayment) 시스템을 사용할 수도 있습니다. 이는 알 수 없는 주소에서 의도치 않게 코드를 트리거할 가능성을 제거하고 특정 서비스 거부 공격을 예방할 수도 있습니다. + +#### 정수 언더플로우 및 오버플로우 {#integer-underflows-and-overflows} + +정수 오버플로우는 산술 연산의 결과가 허용 가능한 값 범위를 벗어나 가장 낮은 표현 가능한 값으로 '롤오버'될 때 발생합니다. 예를 들어, `uint8`은 2^8-1=255까지의 값만 저장할 수 있습니다. 값이 `255`보다 큰 산술 연산은 오버플로우되어 `uint`를 `0`으로 재설정합니다. 이는 자동차의 주행 거리계가 최대 주행 거리(999999)에 도달하면 0으로 재설정되는 것과 유사합니다. + +정수 언더플로우도 비슷한 이유로 발생합니다. 산술 연산의 결과가 허용 가능한 범위 아래로 떨어지는 것입니다. 예를 들어 `uint8`에서 `0`을 감소시키려고 하면 결과는 단순히 표현 가능한 최대값(`255`)으로 롤오버됩니다. + +정수 오버플로우와 언더플로우 모두 계약의 상태 변수에 예기치 않은 변경을 초래하고 계획되지 않은 실행을 초래할 수 있습니다. 아래는 공격자가 스마트 계약에서 산술 오버플로우를 악용하여 잘못된 작업을 수행하는 방법을 보여주는 예입니다. + +``` +pragma solidity ^0.7.6; + +// 이 계약은 시간 금고 역할을 하도록 설계되었습니다. +// 사용자는 이 계약에 입금할 수 있지만 최소 일주일 동안은 인출할 수 없습니다. +// 사용자는 1주 대기 기간을 초과하여 대기 시간을 연장할 수도 있습니다. + +/* +1. TimeLock 배포 +2. TimeLock의 주소로 Attack 배포 +3. 1이더를 보내는 Attack.attack 호출. 즉시 이더를 인출할 수 있습니다. + +무슨 일이 일어났나요? +Attack은 TimeLock.lockTime을 오버플로우시켜 1주 대기 기간 전에 인출할 수 있었습니다. +*/ + +contract TimeLock { + mapping(address => uint) public balances; + mapping(address => uint) public lockTime; + + function deposit() external payable { + balances[msg.sender] += msg.value; + lockTime[msg.sender] = block.timestamp + 1 weeks; + } + + function increaseLockTime(uint _secondsToIncrease) public { + lockTime[msg.sender] += _secondsToIncrease; + } + + function withdraw() public { + require(balances[msg.sender] > 0, "자금 부족"); + require(block.timestamp > lockTime[msg.sender], "잠금 시간이 만료되지 않았습니다"); + + uint amount = balances[msg.sender]; + balances[msg.sender] = 0; + + (bool sent, ) = msg.sender.call{value: amount}(""); + require(sent, "이더 전송 실패"); + } +} + +contract Attack { + TimeLock timeLock; + + constructor(TimeLock _timeLock) { + timeLock = TimeLock(_timeLock); + } + + fallback() external payable {} + + function attack() public payable { + timeLock.deposit{value: msg.value}(); + /* + t가 현재 잠금 시간이라면 x + t = 2**256 = 0이 되는 x를 찾아야 합니다 + 따라서 x = -t + 2**256 = type(uint).max + 1 + 따라서 x = type(uint).max + 1 - t + */ + timeLock.increaseLockTime( + type(uint).max + 1 - timeLock.lockTime(address(this)) + ); + timeLock.withdraw(); + } +} +``` + +##### 정수 언더플로우 및 오버플로우 예방 방법 + +버전 0.8.0부터 솔리디티 컴파일러는 정수 언더플로우 및 오버플로우를 초래하는 코드를 거부합니다. 그러나 더 낮은 컴파일러 버전으로 컴파일된 계약은 산술 연산과 관련된 함수에 대한 확인을 수행하거나 언더플로우/오버플로우를 확인하는 라이브러리(예: [SafeMath](https://docs.openzeppelin.com/contracts/2.x/api/math))를 사용해야 합니다. + +#### 오라클 조작 {#oracle-manipulation} + +[오라클](/developers/docs/oracles/)은 오프체인 정보를 소싱하여 스마트 계약이 사용할 수 있도록 온체인으로 보냅니다. 오라클을 사용하면 자본 시장과 같은 오프체인 시스템과 상호 운용되는 스마트 계약을 설계하여 애플리케이션을 크게 확장할 수 있습니다. + +그러나 오라클이 손상되어 잘못된 정보를 온체인으로 보내면 스마트 계약은 잘못된 입력을 기반으로 실행되어 문제가 발생할 수 있습니다. 이것이 블록체인 오라클의 정보가 정확하고 최신이며 시기적절한지 확인하는 작업을 다루는 '오라클 문제'의 기초입니다. + +관련된 보안 문제는 탈중앙화 거래소와 같은 온체인 오라클을 사용하여 자산의 현물 가격을 얻는 것입니다. [탈중앙화 금융(DeFi)](/defi/) 산업의 대출 플랫폼은 사용자가 얼마나 빌릴 수 있는지 결정하기 위해 사용자의 담보 가치를 결정하기 위해 종종 이 작업을 수행합니다. + +DEX 가격은 주로 차익 거래자들이 시장의 균형을 회복하기 때문에 종종 정확합니다. 그러나 특히 온체인 오라클이 역사적 거래 패턴에 따라 자산 가격을 계산하는 경우(보통 그렇듯이) 조작에 개방되어 있습니다. + +예를 들어, 공격자는 대출 계약과 상호 작용하기 직전에 플래시 론을 받아 자산의 현물 가격을 인위적으로 부풀릴 수 있습니다. DEX에서 자산 가격을 조회하면 (공격자의 대규모 '매수 주문'이 자산 수요를 왜곡하기 때문에) 평소보다 높은 가치가 반환되어 실제보다 더 많이 빌릴 수 있습니다. 이러한 '플래시 론 공격'은 디파이 애플리케이션 간의 가격 오라클 의존도를 악용하는 데 사용되어 프로토콜에 수백만 달러의 자금 손실을 초래했습니다. + +##### 오라클 조작 예방 방법 + +[오라클 조작을 피하기 위한](https://www.cyfrin.io/blog/price-oracle-manipultion-attacks-with-examples) 최소 요구 사항은 단일 실패 지점을 피하기 위해 여러 소스에서 정보를 쿼리하는 탈중앙화 오라클 네트워크를 사용하는 것입니다. 대부분의 경우 탈중앙화 오라클에는 오라클 노드가 올바른 정보를 보고하도록 장려하는 암호경제적 인센티브가 내장되어 있어 중앙화 오라클보다 더 안전합니다. + +자산 가격에 대해 온체인 오라클을 쿼리할 계획이라면 시간 가중 평균 가격(TWAP) 메커니즘을 구현하는 오라클을 사용하는 것을 고려하세요. [TWAP 오라클](https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles)은 서로 다른 두 시점(수정 가능)에서 자산 가격을 쿼리하고 얻은 평균을 기반으로 현물 가격을 계산합니다. 더 긴 기간을 선택하면 최근에 실행된 대규모 주문이 자산 가격에 영향을 미칠 수 없으므로 프로토콜을 가격 조작으로부터 보호할 수 있습니다. + +## 개발자를 위한 스마트 계약 보안 참고 자료 {#smart-contract-security-resources-for-developers} + +### 스마트 계약 분석 및 코드 정확성 검증 도구 {#code-analysis-tools} + +- **[테스트 도구 및 라이브러리](/developers/docs/smart-contracts/testing/#testing-tools-and-libraries)** - _스마트 계약에 대한 단위 테스트, 정적 분석 및 동적 분석을 수행하기 위한 업계 표준 도구 및 라이브러리 모음._ + +- **[공식 검증 도구](/developers/docs/smart-contracts/formal-verification/#formal-verification-tools)** - _스마트 계약의 기능적 정확성을 검증하고 불변을 확인하기 위한 도구._ + +- **[스마트 계약 감사 서비스](/developers/docs/smart-contracts/testing/#smart-contract-auditing-services)** - _이더리움 개발 프로젝트를 위한 스마트 계약 감사 서비스를 제공하는 조직 목록._ + +- **[버그 포상금 플랫폼](/developers/docs/smart-contracts/testing/#bug-bounty-platforms)** - _버그 포상금을 조정하고 스마트 계약의 중요한 취약점에 대한 책임 있는 공개를 보상하기 위한 플랫폼._ + +- **[Fork Checker](https://forkchecker.hashex.org/)** - _포크된 계약에 관한 모든 사용 가능한 정보를 확인하기 위한 무료 온라인 도구._ + +- **[ABI Encoder](https://abi.hashex.org/)** - _솔리디티 계약 기능 및 생성자 인수를 인코딩하기 위한 무료 온라인 서비스._ + +- **[Aderyn](https://github.com/Cyfrin/aderyn)** - _추상 구문 트리(AST)를 순회하여 의심되는 취약점을 찾아내고 문제를 쉽게 소비할 수 있는 마크다운 형식으로 출력하는 솔리디티 정적 분석기._ + +### 스마트 계약 모니터링 도구 {#smart-contract-monitoring-tools} + +- **[Tenderly 실시간 알림](https://tenderly.co/monitoring)** - _스마트 계약이나 지갑에서 비정상적이거나 예상치 못한 이벤트가 발생했을 때 실시간 알림을 받기 위한 도구._ + +### 스마트 계약의 안전한 관리를 위한 도구 {#smart-contract-administration-tools} + +- **[Safe](https://safe.global/)** - _이더리움에서 실행되는 스마트 계약 지갑으로, 트랜잭션이 발생하기 전에 최소한의 사람들이 승인해야 합니다(M-of-N)._ + +- **[OpenZeppelin Contracts](https://docs.openzeppelin.com/contracts/5.x/)** - _계약 소유권, 업그레이드, 접근 제어, 거버넌스, 일시 중지 기능 등을 포함한 관리 기능을 구현하기 위한 계약 라이브러리._ + +### 스마트 계약 감사 서비스 {#smart-contract-auditing-services} + +- **[ConsenSys Diligence](https://diligence.consensys.io/)** - _블록체인 생태계 전반의 프로젝트가 프로토콜을 출시할 준비가 되어 있고 사용자를 보호하도록 구축되었는지 확인하는 데 도움이 되는 스마트 계약 감사 서비스._ + +- **[CertiK](https://www.certik.com/)** - _스마트 계약 및 블록체인 네트워크에 대한 최첨단 공식 검증 기술 사용을 개척하는 블록체인 보안 회사._ + +- **[Trail of Bits](https://www.trailofbits.com/)** - _보안 연구와 공격자 사고방식을 결합하여 위험을 줄이고 코드를 강화하는 사이버 보안 회사._ + +- **[PeckShield](https://peckshield.com/)** - _전체 블록체인 생태계의 보안, 개인 정보 보호 및 유용성을 위한 제품과 서비스를 제공하는 블록체인 보안 회사._ + +- **[QuantStamp](https://quantstamp.com/)** - _보안 및 위험 평가 서비스를 통해 블록체인 기술의 주류 채택을 촉진하는 감사 서비스._ + +- **[OpenZeppelin](https://www.openzeppelin.com/security-audits)** - _분산 시스템에 대한 보안 감사를 제공하는 스마트 계약 보안 회사._ + +- **[Runtime Verification](https://runtimeverification.com/)** - _스마트 계약의 공식 모델링 및 검증을 전문으로 하는 보안 회사._ + +- **[Hacken](https://hacken.io)** - _360도 접근 방식을 블록체인 보안에 도입하는 웹3 사이버 보안 감사자._ + +- **[Nethermind](https://www.nethermind.io/smart-contract-audits)** - _솔리디티 및 Cairo 감사 서비스로, 이더리움 및 Starknet 전반에 걸쳐 스마트 계약의 무결성과 사용자 안전을 보장합니다._ + +- **[HashEx](https://hashex.org/)** - _HashEx는 암호화폐의 보안을 보장하기 위해 블록체인 및 스마트 계약 감사에 중점을 두며, 스마트 계약 개발, 침투 테스트, 블록체인 컨설팅과 같은 서비스를 제공합니다._ + +- **[Code4rena](https://code4rena.com/)** - _스마트 계약 보안 전문가들이 취약점을 찾아내고 웹3를 더 안전하게 만드는 데 도움을 주도록 인센티브를 제공하는 경쟁적인 감사 플랫폼._ + +- **[CodeHawks](https://codehawks.com/)** - _보안 연구원들을 위한 스마트 계약 감사 대회를 개최하는 경쟁적인 감사 플랫폼._ + +- **[Cyfrin](https://cyfrin.io)** - _제품 및 스마트 계약 감사 서비스를 통해 암호화 보안을 육성하는 웹3 보안 강자._ + +- **[ImmuneBytes](https://immunebytes.com/smart-contract-audit/)** - _경험 많은 감사자 팀과 최고 수준의 도구를 통해 블록체인 시스템에 대한 보안 감사를 제공하는 웹3 보안 회사._ + +- **[Oxorio](https://oxor.io/)** - _암호화 회사 및 디파이 프로젝트를 위한 EVM, 솔리디티, ZK, 크로스체인 기술 전문 지식을 갖춘 스마트 계약 감사 및 블록체인 보안 서비스._ + +- **[Inference](https://inference.ag/)** - _EVM 기반 블록체인을 위한 스마트 계약 감사를 전문으로 하는 보안 감사 회사._ 전문 감사자 덕분에 잠재적인 문제를 식별하고 배포 전에 이를 해결하기 위한 실행 가능한 해결책을 제안합니다. + +### 버그 포상금 플랫폼 {#bug-bounty-platforms} + +- **[Immunefi](https://immunefi.com/)** - _스마트 계약 및 디파이 프로젝트를 위한 버그 포상금 플랫폼으로, 보안 연구원들이 코드를 검토하고, 취약점을 공개하고, 보상을 받고, 암호화폐를 더 안전하게 만듭니다._ + +- **[HackerOne](https://www.hackerone.com/)** - _기업과 침투 테스터 및 사이버 보안 연구원을 연결하는 취약점 조정 및 버그 포상금 플랫폼._ + +- **[HackenProof](https://hackenproof.com/)** - _암호화 프로젝트(디파이, 스마트 계약, 지갑, CEX 등)를 위한 전문 버그 포상금 플랫폼으로, 보안 전문가들이 분류 서비스를 제공하고 연구원들은 관련 있고 검증된 버그 보고서에 대해 보상을 받습니다._ + +- **[Sherlock](https://www.sherlock.xyz/)** - _스마트 계약 보안을 위한 웹3의 보험사로, 스마트 계약을 통해 감사자에게 지급되는 보상금을 관리하여 관련 버그가 공정하게 지급되도록 보장합니다._ + +- **[CodeHawks](https://www.codehawks.com/)** - _감사자들이 보안 대회 및 챌린지에 참여하고 (곧) 자신들의 개인 감사에도 참여하는 경쟁적인 버그 포상금 플랫폼._ + +### 알려진 스마트 계약 취약점 및 공격 사례 발표 {#common-smart-contract-vulnerabilities-and-exploits} + +- **[ConsenSys: 스마트 계약 알려진 공격](https://consensysdiligence.github.io/smart-contract-best-practices/attacks/)** - _가장 중요한 계약 취약점에 대한 초보자 친화적인 설명으로, 대부분의 경우에 대한 샘플 코드가 포함되어 있습니다._ + +- **[SWC 레지스트리](https://swcregistry.io/)** - _이더리움 스마트 계약에 적용되는 공통 취약점 목록(CWE) 항목의 선별된 목록._ + +- **[Rekt](https://rekt.news/)** - _주목할 만한 암호화폐 해킹 및 공격 사례에 대한 정기적으로 업데이트되는 간행물로, 상세한 사후 보고서가 함께 제공됩니다._ + +### 스마트 계약 보안 학습을 위한 챌린지 {#challenges-for-learning-smart-contract-security} + +- **[Awesome BlockSec CTF](https://github.com/blockthreat/blocksec-ctfs)** - _블록체인 보안 워게임, 챌린지 및 [캡처 더 플래그](https://www.webopedia.com/definitions/ctf-event/amp/) 대회 및 솔루션 풀이의 선별된 목록._ + +- **[Damn Vulnerable DeFi](https://www.damnvulnerabledefi.xyz/)** - _디파이 스마트 계약의 공격적 보안을 배우고 버그 헌팅 및 보안 감사 기술을 구축하기 위한 워게임._ + +- **[Ethernaut](https://ethernaut.openzeppelin.com/)** - _각 레벨이 '해킹'되어야 하는 스마트 계약인 웹3/솔리디티 기반 워게임._ + +- **[HackenProof x HackTheBox](https://app.hackthebox.com/tracks/HackenProof-Track)** - _판타지 모험을 배경으로 한 스마트 계약 해킹 챌린지._ 챌린지를 성공적으로 완료하면 비공개 버그 포상금 프로그램에 접근할 수도 있습니다. + +### 스마트 계약 보안을 위한 모범 사례 {#smart-contract-security-best-practices} + +- **[ConsenSys: 이더리움 스마트 계약 보안 모범 사례](https://consensys.github.io/smart-contract-best-practices/)** - _이더리움 스마트 계약 보안을 위한 포괄적인 가이드라인 목록._ + +- **[Nascent: 단순 보안 툴킷](https://github.com/nascentxyz/simple-security-toolkit)** - _스마트 계약 개발을 위한 실용적인 보안 중심 가이드 및 체크리스트 모음._ + +- **[솔리디티 패턴](https://fravoll.github.io/solidity-patterns/)** - _스마트 계약 프로그래밍 언어인 솔리디티를 위한 안전한 패턴 및 모범 사례의 유용한 모음집._ + +- **[솔리디티 문서: 보안 고려 사항](https://docs.soliditylang.org/en/v0.8.16/security-considerations.html)** - _솔리디티로 안전한 스마트 계약을 작성하기 위한 가이드라인._ + +- **[스마트 계약 보안 검증 표준](https://github.com/securing/SCSVS)** - _개발자, 설계자, 보안 검토자 및 공급업체를 위해 스마트 계약의 보안을 표준화하기 위해 만들어진 14개 부분으로 구성된 체크리스트._ + +- **[스마트 계약 보안 및 감사 학습](https://updraft.cyfrin.io/courses/security)** - _보안 모범 사례를 향상시키고 보안 연구원이 되고자 하는 스마트 계약 개발자를 위해 만들어진 최고의 스마트 계약 보안 및 감사 과정._ + +### 스마트 계약 보안에 관한 튜토리얼 {#tutorials-on-smart-contract-security} + +- [안전한 스마트 계약 작성 방법](/developers/tutorials/secure-development-workflow/) + +- [Slither를 사용하여 스마트 계약 버그를 찾는 방법](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/) + +- [Manticore를 사용하여 스마트 계약 버그를 찾는 방법](/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/) + +- [스마트 계약 보안 가이드라인](/developers/tutorials/smart-contract-security-guidelines/) + +- [토큰 계약을 임의의 토큰과 안전하게 통합하는 방법](/developers/tutorials/token-integration-checklist/) + +- [Cyfrin Updraft - 스마트 계약 보안 및 감사 전체 과정](https://updraft.cyfrin.io/courses/security) diff --git a/public/content/translations/ko/developers/docs/smart-contracts/testing/index.md b/public/content/translations/ko/developers/docs/smart-contracts/testing/index.md new file mode 100644 index 00000000000..691d8ec7991 --- /dev/null +++ b/public/content/translations/ko/developers/docs/smart-contracts/testing/index.md @@ -0,0 +1,310 @@ +--- +title: "스마트 계약 테스트" +description: "Ethereum 스마트 계약을 테스트하기 위한 기술 및 고려 사항의 개요입니다." +lang: ko +--- + +Ethereum과 같은 공공 블록체인은 불변성이 있어, 배포 후 스마트 계약 코드를 변경하는 것이 어렵습니다. “가상 업그레이드”를 수행하기 위한 [계약 업그레이드 패턴](/developers/docs/smart-contracts/upgrading/)이 존재하지만, 이는 구현하기 어렵고 사회적 합의가 필요합니다. 또한 업그레이드는 오류가 발견된 _후에만_ 수정할 수 있습니다—만약 공격자가 취약점을 먼저 발견하면 스마트 계약은 공격에 노출될 위험이 있습니다. + +이러한 이유로 [배포](/developers/docs/smart-contracts/deploying/)하기 전에 스마트 계약을 테스트하는 것은 [보안](/developers/docs/smart-contracts/security/)을 위한 최소한의 요구 사항입니다. 스마트 계약을 테스트하고 코드의 정확성을 평가하기 위한 다양한 기술이 존재하며, 사용자는 필요에 따라 적절한 방법을 선택할 수 있습니다. 그러나 경미한 보안 결함부터 주요 결함까지 잡아내기 위해서는 다양한 도구와 접근 방식을 포함한 테스트 스위트가 이상적입니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지는 Ethereum 네트워크에 배포하기 전에 스마트 계약을 테스트하는 방법을 설명합니다. 이 문서는 독자가 [스마트 계약](/developers/docs/smart-contracts/)에 익숙하다고 가정합니다. + +## 스마트 계약 테스트란 무엇입니까? 스마트 계약 테스트란? {#what-is-smart-contract-testing} + +스마트 계약 테스트는 스마트 계약 코드가 예상대로 작동하는지 확인하는 과정입니다. 테스트는 특정 스마트 계약이 신뢰성, 사용성 및 보안 요구 사항을 충족하는지 확인하는 데 유용합니다. + +접근 방식은 다양하지만, 대부분의 테스트 방법은 스마트 계약이 처리할 것으로 예상되는 데이터의 소규모 샘플로 계약을 실행하는 것이 필요합니다. 계약이 샘플 데이터에 대해 올바른 결과를 생성하면 정상적으로 작동하는 것으로 간주됩니다. 대부분의 테스트 도구는 계약의 실행이 예상 결과와 일치하는지 확인하기 위해 [테스트 케이스](https://en.m.wikipedia.org/wiki/Test_case)를 작성하고 실행하기 위한 리소스를 제공합니다. + +### 스마트 계약을 테스트하는 것이 왜 중요한가요? 스마트 계약 테스트의 중요성 {#importance-of-testing-smart-contracts} + +스마트 계약은 종종 고가의 금융 자산을 관리하기 때문에, 사소한 프로그래밍 오류가 [사용자에게 막대한 손실](https://rekt.news/leaderboard/)로 이어질 수 있으며, 실제로도 종종 그렇습니다. 엄격한 테스트를 통해 스마트 계약 코드의 결함과 문제를 조기에 발견하고 메인넷에 배포하기 전에 수정할 수 있습니다. + +버그가 발견되면 계약을 업그레이드할 수 있지만, 업그레이드는 복잡하며 부적절하게 처리될 경우 [오류를 초래](https://blog.trailofbits.com/2018/09/05/contract-upgrade-anti-patterns/)할 수 있습니다. 계약을 업그레이드하는 것은 불변성의 원칙을 무시하고 사용자가 추가 신뢰 가정을 가지게 합니다. 반대로, 계약 테스트에 대한 포괄적인 계획은 스마트 계약 보안 위험을 완화하고 배포 후 복잡한 논리 업그레이드 수행 필요성을 줄입니다. + +## 스마트 계약 테스트 방법 {#methods-for-testing-smart-contracts} + +이더리움 스마트 계약 테스트 방법은 자동화된 테스트수동 테스트라는 두 가지 큰 범주로 나뉩니다. 자동화 테스트와 수동 테스트는 각각 고유한 장점과 단점을 제공하지만, 두 가지를 결합하여 계약 분석을 위한 강력한 계획을 수립할 수 있습니다. + +### 자동화된 테스트 {#automated-testing} + +자동화 테스트는 스마트 계약 코드의 실행 오류를 자동으로 검사하는 도구를 사용합니다. 자동화된 테스트의 이점은 계약 기능성 평가를 안내하기 위해 [스크립트](https://www.techtarget.com/whatis/definition/script?amp=1)를 사용하는 데서 비롯됩니다. 스크립트화된 테스트는 최소한의 인간 개입으로 반복적으로 실행되도록 예약할 수 있어 수동 테스트 접근 방식보다 효율적입니다. + +자동화 테스트는 테스트가 반복적이거나 시간 소모적일 때, 수동으로 수행하기 어려울 때, 인간의 실수가 발생할 수 있을 때 또는 중요한 계약 기능을 평가할 때 특히 유용합니다. 그러나 자동화된 테스트 도구는 특정 버그를 놓치거나 많은 [오탐](https://www.contrastsecurity.com/glossary/false-positive)을 생성할 수 있다는 단점이 있을 수 있습니다. 따라서 스마트 계약의 경우 자동화 테스트와 수동 테스트를 결합하는 것이 이상적입니다. + +### 수동 테스트 {#manual-testing} + +수동 테스트는 인간의 도움이 필요하며 스마트 계약의 정확성을 분석할 때 테스트 케이스를 하나씩 실행하는 것입니다. 이는 계약에서 여러 독립 테스트를 동시에 실행하고 모든 실패 및 성공 테스트를 보여주는 보고서를 얻는 자동화 테스트와 다릅니다. + +수동 테스트는 다양한 테스트 시나리오를 포함하는 작성된 테스트 계획에 따라 단일 개인이 수행할 수도 있습니다. 또한 여러 개인 또는 그룹이 지정된 기간 동안 스마트 계약과 상호 작용하는 수동 테스트의 일환으로 참여할 수 있습니다. 테스터는 계약의 실제 동작을 예상 동작과 비교하고 차이점이 발견되면 이를 버그로 표시합니다. + +효과적인 수동 테스트에는 상당한 자원(기술, 시간, 비용, 노력)이 필요하며, 실행 중 실수로 인해 특정 오류가 누락될 수 있습니다. 그러나 수동 테스트는 직관을 사용하여 자동화 테스트 도구에서 놓칠 수 있는 경계 사례를 탐지하는 인간 테스터(예: 감사자)에게 유용할 수 있습니다. + +## 스마트 계약을 위한 자동화된 테스트 {#automated-testing-for-smart-contracts} + +### 단위 테스트 {#unit-testing-for-smart-contracts} + +유닛 테스트는 계약 기능을 개별적으로 평가하고 각 구성 요소가 올바르게 작동하는지 확인합니다. 좋은 유닛 테스트는 간단하고 실행이 빠르며, 테스트 실패 시 어떤 문제가 발생했는지 명확하게 알 수 있습니다. + +유닛 테스트는 함수가 예상된 값을 반환하고 함수 실행 후 계약 저장소가 제대로 업데이트되는지 확인하는 데 유용합니다. 또한, 계약 코드베이스에 변경 사항을 추가한 후 유닛 테스트를 실행하면 새로운 로직이 오류를 도입하지 않았는지 확인할 수 있습니다. 다음은 효과적인 유닛 테스트를 실행하기 위한 몇 가지 지침입니다: + +#### 스마트 계약 단위 테스트 지침 {#unit-testing-guidelines} + +##### 1. 계약의 비즈니스 로직과 워크플로를 이해하세요 + +유닛 테스트를 작성하기 전에 스마트 계약이 제공하는 기능과 사용자가 해당 기능에 액세스하고 사용하는 방법을 아는 것이 좋습니다. 이는 계약의 함수가 유효한 사용자 입력에 대해 올바른 출력을 반환하는지 판단하는 [해피 패스 테스트](https://en.m.wikipedia.org/wiki/Happy_path)를 실행하는 데 특히 유용합니다. 이 개념을 [경매 계약](https://docs.soliditylang.org/en/v0.8.17/solidity-by-example.html?highlight=Auction%20contract#simple-open-auction)의 (축약된) 예시를 사용하여 설명하겠습니다. + +```solidity +constructor( + uint biddingTime, + address payable beneficiaryAddress + ) { + beneficiary = beneficiaryAddress; + auctionEndTime = block.timestamp + biddingTime; + } + +function bid() external payable { + + if (block.timestamp > auctionEndTime) + revert AuctionAlreadyEnded(); + + if (msg.value <= highestBid) + revert BidNotHighEnough(highestBid); + + if (highestBid != 0) { + pendingReturns[highestBidder] += highestBid; + } + highestBidder = msg.sender; + highestBid = msg.value; + emit HighestBidIncreased(msg.sender, msg.value); + } + + function withdraw() external returns (bool) { + uint amount = pendingReturns[msg.sender]; + if (amount > 0) { + pendingReturns[msg.sender] = 0; + + if (!payable(msg.sender).send(amount)) { + pendingReturns[msg.sender] = amount; + return false; + } + } + return true; + } + +function auctionEnd() external { + if (block.timestamp < auctionEndTime) + revert AuctionNotYetEnded(); + if (ended) + revert AuctionEndAlreadyCalled(); + + ended = true; + emit AuctionEnded(highestBidder, highestBid); + + beneficiary.transfer(highestBid); + } +} +``` + +이것은 입찰 기간 동안 입찰을 받도록 설계된 간단한 경매 계약입니다. `highestBid`가 증가하면 이전 최고 입찰자는 자신의 돈을 돌려받습니다. 입찰 기간이 끝나면 `beneficiary`는 계약을 호출하여 자신의 돈을 받습니다. + +이와 같은 계약에 대한 유닛 테스트는 사용자가 계약과 상호 작용할 때 호출할 수 있는 다양한 기능을 다룹니다. 예를 들어, 경매가 진행 중일 때 사용자가 입찰할 수 있는지 확인하는 단위 테스트(`bid()` 호출이 성공하는지)나 사용자가 현재의 `highestBid`보다 높은 입찰을 할 수 있는지 확인하는 테스트가 있을 수 있습니다. + +계약의 운영 워크플로를 이해하면 실행이 요구 사항을 충족하는지 확인하는 유닛 테스트를 작성하는 데 도움이 됩니다. 예를 들어, 경매 계약은 경매가 종료되었을 때(즉, `auctionEndTime`이 `block.timestamp`보다 낮을 때) 사용자가 입찰할 수 없다고 명시합니다. 따라서 개발자는 경매가 끝났을 때(즉, `auctionEndTime` > `block.timestamp`일 때) `bid()` 함수 호출이 성공하는지 또는 실패하는지를 확인하는 단위 테스트를 실행할 수 있습니다. + +##### 2. 계약 실행과 관련된 모든 가정을 평가하세요 + +계약의 실행에 대한 모든 가정을 문서화하고 해당 가정의 타당성을 확인하는 유닛 테스트를 작성하는 것이 중요합니다. 예상치 못한 실행에 대한 보호를 제공할 뿐만 아니라, 테스트 가정을 통해 스마트 계약의 보안 모델을 위반할 수 있는 작업에 대해 생각하게 합니다. 유용한 팁은 "행복한 사용자 테스트"를 넘어서 잘못된 입력에 대해 함수가 실패하는지 확인하는 부정 테스트를 작성하는 것입니다. + +많은 유닛 테스트 프레임워크는 계약이 할 수 있는 것과 할 수 없는 것을 명시하는 간단한 문장인 어설션을 생성하고, 해당 어설션이 실행 중에 유지되는지 확인하는 테스트를 실행할 수 있습니다. 위에서 설명한 경매 계약을 작업하는 개발자는 부정 테스트를 실행하기 전에 다음과 같은 행동에 대한 어설션을 만들 수 있습니다: + +- 경매가 종료되었거나 시작되지 않았을 때 사용자는 입찰할 수 없습니다. + +- 입찰이 허용 가능한 기준에 미달하면 경매 계약이 복구됩니다. + +- 입찰에 실패한 사용자는 자금이 반환됩니다. + +**참고**: 가정을 테스트하는 또 다른 방법은 계약에서, 특히 `require`, `assert`, `if…else` 문과 같은 [함수 제어자](https://docs.soliditylang.org/en/v0.8.16/contracts.html#function-modifiers)를 트리거하는 테스트를 작성하는 것입니다. + +##### 3. 코드 커버리지 측정 + +[코드 커버리지](https://en.m.wikipedia.org/wiki/Code_coverage)는 테스트 중에 실행된 코드의 분기, 줄, 문의 수를 추적하는 테스트 지표입니다. 테스트되지 않은 취약점의 위험을 최소화하기 위해 테스트는 우수한 코드 커버리지를 가져야 합니다. 충분한 커버리지가 없으면 모든 테스트가 통과하기 때문에 계약이 안전하다고 잘못 가정할 수 있지만, 테스트되지 않은 코드 경로에는 여전히 취약점이 존재합니다. 높은 코드 커버리지를 기록하면 스마트 계약의 모든 문장/함수가 충분히 테스트되어 올바르게 작동함을 보장합니다. + +##### 4. 잘 개발된 테스트 프레임워크를 사용하십시오. + +스마트 계약의 단위 테스트를 실행할 때 사용하는 도구의 품질은 매우 중요합니다. 이상적인 테스트 프레임워크는 정기적으로 유지 보수되고, 유용한 기능(예: 로깅 및 보고 기능)을 제공하며, 다른 개발자들에 의해 광범위하게 사용되고 검증된 프레임워크입니다. + +Solidity 스마트 계약을 위한 단위 테스트 프레임워크는 다양한 언어(주로 JavaScript, Python, Rust) 로 제공됩니다. 아래 가이드에서 다양한 테스트 프레임워크로 단위 테스트를 시작하는 방법에 대한 정보를 확인하십시오: + +- **[Brownie로 단위 테스트 실행하기](https://eth-brownie.readthedocs.io/en/v1.0.0_a/tests.html)** +- **[Foundry로 단위 테스트 실행하기](https://book.getfoundry.sh/forge/writing-tests)** +- **[Waffle로 단위 테스트 실행하기](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)** +- **[Remix로 단위 테스트 실행하기](https://remix-ide.readthedocs.io/en/latest/unittesting.html#write-tests)** +- **[Ape로 단위 테스트 실행하기](https://docs.apeworx.io/ape/stable/userguides/testing.html)** +- **[Hardhat으로 단위 테스트 실행하기](https://hardhat.org/hardhat-runner/docs/guides/test-contracts)** +- **[Wake로 단위 테스트 실행하기](https://ackeeblockchain.com/wake/docs/latest/testing-framework/overview/)** + +### 통합 테스트 {#integration-testing-for-smart-contracts} + +단위 테스트가 계약 함수들을 개별적으로 디버깅하는 동안, 통합 테스트는 스마트 계약의 모든 구성 요소를 평가합니다. 통합 테스트는 다른 스마트 계약 간의 상호작용이나 같은 스마트 계약 내의 다양한 함수 간의 호출로 인해 발생하는 문제를 감지할 수 있습니다. 예를 들어, 통합 테스트는 [상속](https://docs.soliditylang.org/en/v0.8.12/contracts.html#inheritance) 및 종속성 주입과 같은 기능이 제대로 작동하는지 확인하는 데 도움이 될 수 있습니다. + +통합 테스트는 계약이 모듈식 아키텍처를 채택하거나 실행 중에 다른 온체인 계약과 인터페이스하는 경우에 유용합니다. 통합 테스트를 실행하는 한 가지 방법은 특정 높이에서 [블록체인을 포크](/glossary/#fork)하고([Forge](https://book.getfoundry.sh/forge/fork-testing) 또는 [Hardhat](https://hardhat.org/hardhat-network/docs/guides/forking-other-networks)과 같은 도구 사용) 계약과 배포된 계약 간의 상호 작용을 시뮬레이션하는 것입니다. + +포크된 블록체인은 메인넷과 유사하게 작동하며 관련 상태와 잔액을 가진 계정을 포함합니다. 그러나 이 환경은 로컬 개발 환경에만 국한되므로 예를 들어 실제 이더리움(ETH)이 트랜잭션에 필요하지 않으며, 실제 이더리움 프로토콜에 영향을 주지 않습니다. + +### 속성 기반 테스트 {#property-based-testing-for-smart-contracts} + +속성 기반 테스트는 스마트 계약이 정의된 속성을 충족하는지 확인하는 과정입니다. 속성은 계약의 동작에 대해 다양한 시나리오에서 참으로 유지될 것으로 예상되는 사실을 나타냅니다—예를 들어, "계약의 산술 연산은 오버플로 또는 언더플로를 발생시키지 않는다"라는 것이 스마트 계약 속성의 예일 수 있습니다. + +정적 분석동적 분석은 속성 기반 테스트를 실행하기 위한 두 가지 일반적인 기술이며, 두 기술 모두 프로그램(이 경우 스마트 계약)의 코드가 미리 정의된 속성을 만족하는지 확인할 수 있습니다. 일부 속성 기반 테스트 도구는 예상되는 계약 속성에 대한 미리 정의된 규칙을 제공하며, 코드가 이러한 규칙을 준수하는지 확인합니다. 다른 도구는 스마트 계약에 대한 사용자 지정 속성을 생성할 수 있도록 합니다. + +#### 정적 분석 {#static-analysis} + +정적 분석 도구는 스마트 계약의 소스 코드를 입력으로 받아 계약이 속성을 충족하는지 여부를 선언하는 결과를 출력합니다. 동적 분석과는 달리, 정적 분석은 계약을 실행하지 않고 올바름을 분석합니다. 정적 분석은 대신 계약이 실행 중에 가질 수 있는 모든 경로를 추론하며(즉, 소스 코드 구조를 검사하여 런타임에 계약의 작동이 어떻게 되는지 결정합니다). + +[린팅](https://www.perforce.com/blog/qac/what-is-linting)과 [정적 테스트](https://www.techtarget.com/whatis/definition/static-analysis-static-code-analysis)는 계약에 대한 정적 분석을 실행하는 일반적인 방법입니다. 두 방법 모두 컴파일러가 출력하는 [추상 구문 트리](https://en.m.wikipedia.org/wiki/Abstract_syntax_tree) 및 [제어 흐름 그래프](https://www.geeksforgeeks.org/software-engineering-control-flow-graph-cfg/amp/)와 같은 계약 실행의 저수준 표현을 분석해야 합니다. + +대부분의 경우, 정적 분석은 코드에서 안전하지 않은 구조물 사용, 구문 오류 또는 코딩 표준 위반과 같은 안전 문제를 감지하는 데 유용합니다. 그러나 정적 분석기는 더 깊은 취약점을 감지하는 데는 일반적으로 효과적이지 않으며, 과도한 거짓 양성 결과를 생성할 수 있습니다. + +#### 동적 분석 {#dynamic-analysis} + +동적 분석은 스마트 계약 함수의 [심볼릭 실행](https://en.m.wikipedia.org/wiki/Symbolic_execution)에서의 심볼릭 입력이나 [퍼징](https://owasp.org/www-community/Fuzzing)에서의 구체적인 입력과 같은 것을 생성하여 실행 추적이 특정 속성을 위반하는지 확인합니다. 이러한 속성 기반 테스트는 테스트 케이스가 여러 시나리오를 포괄하며 프로그램이 테스트 케이스를 생성하는 방식에서 단위 테스트와 다릅니다. + +[퍼징](https://www.halborn.com/blog/post/what-is-fuzz-testing-fuzzing)은 스마트 계약에서 임의의 속성을 검증하기 위한 동적 분석 기법의 한 예입니다. 퍼저는 정의된 입력 값의 무작위 또는 잘못된 변형으로 대상 계약의 함수를 호출합니다. 스마트 계약이 오류 상태(예: 단언이 실패하는 상태)에 들어가면 문제가 플래그 처리되며 취약한 경로로 실행을 유도하는 입력이 보고서에 생성됩니다. + +퍼징은 스마트 계약의 입력 유효성 검사 메커니즘을 평가하는 데 유용합니다. 예상치 못한 입력을 적절히 처리하지 않으면 의도치 않은 실행이 발생하고 위험한 영향을 초래할 수 있기 때문입니다. 이러한 속성 기반 테스트는 여러 이유로 이상적일 수 있습니다: + +1. **많은 시나리오를 다루는 테스트 케이스를 작성하는 것은 어렵습니다.** 속성 테스트는 동작을 정의하고 해당 동작을 테스트할 데이터의 범위를 정의하기만 하면 됩니다. 프로그램은 정의된 속성을 기반으로 테스트 케이스를 자동으로 생성합니다. + +2. **테스트 스위트가 프로그램 내의 모든 가능한 경로를 충분히 다루지 못할 수 있습니다.** 100%의 커버리지를 달성하더라도 에지 케이스를 놓칠 수 있습니다. + +3. **단위 테스트는 샘플 데이터에 대해 계약이 올바르게 실행됨을 증명하지만, 샘플 외부의 입력에 대해 계약이 올바르게 실행되는지는 알 수 없습니다.** 속성 테스트는 주어진 입력 값의 다양한 변형으로 대상 계약을 실행하여 어설션 실패를 유발하는 실행 추적을 찾습니다. 따라서 속성 테스트는 계약이 광범위한 입력 데이터 클래스에 대해 올바르게 실행됨을 더 많이 보장합니다. + +### 스마트 계약의 속성 기반 테스트 실행 지침 {#running-property-based-tests} + +속성 기반 테스트 실행은 일반적으로 스마트 계약에서 검증하려는 속성(예: [정수 오버플로](https://github.com/ConsenSys/mythril/wiki/Integer-Overflow)의 부재) 또는 속성 모음을 정의하는 것으로 시작됩니다. 속성 테스트를 작성할 때 트랜잭션 입력에 대해 프로그램이 생성할 수 있는 값의 범위를 정의해야 할 수도 있습니다. + +적절하게 구성된 속성 테스트 도구는 무작위로 생성된 입력을 사용하여 스마트 계약 기능을 실행합니다. 어설션 위반이 있으면 평가 중인 속성을 위반하는 구체적인 입력 데이터를 포함한 보고서를 받을 수 있습니다. 다음 가이드를 통해 다양한 도구로 속성 기반 테스트를 실행하는 방법을 시작할 수 있습니다: + +- **[Slither를 사용한 스마트 계약의 정적 분석](https://github.com/crytic/slither)** +- **[Wake를 사용한 스마트 계약의 정적 분석](https://ackeeblockchain.com/wake/docs/latest/static-analysis/using-detectors/)** +- **[Brownie를 사용한 속성 기반 테스트](https://eth-brownie.readthedocs.io/en/stable/tests-hypothesis-property.html)** +- **[Foundry를 사용한 계약 퍼징](https://book.getfoundry.sh/forge/fuzz-testing)** +- **[Echidna를 사용한 계약 퍼징](https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/echidna#echidna-tutorial)** +- **[Wake를 사용한 계약 퍼징](https://ackeeblockchain.com/wake/docs/latest/testing-framework/fuzzing/)** +- **[Manticore를 사용한 스마트 계약의 심볼릭 실행](https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/manticore#manticore-tutorial)** +- **[Mythril을 사용한 스마트 계약의 심볼릭 실행](https://mythril-classic.readthedocs.io/en/master/tutorial.html)** + +## 스마트 계약의 수동 테스트 {#manual-testing-for-smart-contracts} + +스마트 계약의 수동 테스트는 일반적으로 자동화된 테스트를 실행한 후 개발 주기 후반에 수행됩니다. 이 형태의 테스트는 스마트 계약을 하나의 통합된 제품으로 평가하여 기술 요구 사항에 지정된 대로 성능을 발휘하는지 확인합니다. + +### 로컬 블록체인에서 계약 테스트하기 {#testing-on-local-blockchain} + +로컬 개발 환경에서 수행된 자동화 테스트는 유용한 디버깅 정보를 제공할 수 있지만, 프로덕션 환경에서 스마트 계약이 어떻게 작동하는지 알아야 합니다. 그러나 메인 이더리움 체인에 배포하면 가스 요금이 발생하며, 스마트 계약에 여전히 버그가 있을 경우 실제 돈을 잃을 수도 있습니다. + +로컬 블록체인([개발 네트워크](/developers/docs/development-networks/)라고도 함)에서 계약을 테스트하는 것은 메인넷에서 테스트하는 것에 대한 권장 대안입니다. 로컬 블록체인은 컴퓨터에서 로컬로 실행되는 이더리움 블록체인의 사본으로 이더리움의 실행 레이어의 동작을 시뮬레이션합니다. 따라서 상당한 오버헤드 없이 계약과 상호 작용하는 트랜잭션을 프로그래밍할 수 있습니다. + +로컬 블록체인에서 계약을 실행하는 것은 수동 통합 테스트의 한 형태로 유용할 수 있습니다. [스마트 계약은 구성성이 높기 때문에](/developers/docs/smart-contracts/composability/) 기존 프로토콜과 통합할 수 있습니다. 하지만 이러한 복잡한 온체인 상호 작용이 올바른 결과를 생성하는지 확인해야 합니다. + +[개발 네트워크에 대해 자세히 알아보기](/developers/docs/development-networks/) + +### 테스트넷에서 계약 테스트하기 {#testing-contracts-on-testnets} + +테스트 네트워크 또는 테스트넷은 실제 가치가 없는 이더(ETH)를 사용한다는 점을 제외하면 이더리움 메인넷과 똑같이 작동합니다. 계약을 [테스트넷](/developers/docs/networks/#ethereum-testnets)에 배포하면 누구나 자금의 위험 없이 계약과 상호 작용할 수 있습니다(예: 탈중앙화앱의 프론트엔드를 통해). + +이 형태의 수동 테스트는 애플리케이션의 엔드투엔드 플로우를 사용자의 관점에서 평가하는 데 유용합니다. 여기에서 베타 테스터도 시운전을 수행하고 계약의 비즈니스 논리 및 전반적인 기능과 관련된 문제를 보고할 수 있습니다. + +로컬 블록체인에서 테스트한 후 테스트넷에 배포하는 것이 이상적입니다. 테스트넷의 동작이 이더리움 가상 머신과 유사하기 때문입니다. 따라서 많은 이더리움 네이티브 프로젝트가 실제 조건에서 스마트 계약 작동을 평가하기 위해 테스트넷에 dapp을 배포하는 것이 일반적입니다. + +[이더리움 테스트넷에 대해 자세히 알아보기](/developers/docs/development-networks/#public-beacon-testchains) + +## 테스트와 형식 검증 비교 {#testing-vs-formal-verification} + +테스트는 특정 데이터 입력에 대해 계약이 예상 결과를 반환하는지 확인하는 데 도움이 되지만, 테스트에 사용되지 않은 입력에 대해 동일한 결과를 확정적으로 입증할 수는 없습니다. 따라서 스마트 계약을 테스트하는 것은 '기능적 정확성'을 보장할 수 없습니다(즉, 프로그램이 `모든` 입력값 세트에 대해 요구되는 대로 동작한다는 것을 보여줄 수 없습니다). + +형식 검증은 프로그램의 형식 모델이 형식 명세와 일치하는지 확인하여 소프트웨어의 정확성을 평가하는 접근 방식입니다. 형식 모델은 프로그램의 추상적 수학적 표현이며, 형식 명세는 프로그램의 속성(즉, 프로그램 실행에 대한 논리적 어설션)을 정의합니다. + +속성이 수학적 용어로 작성되므로 시스템의 형식(수학적) 모델이 논리적 추론 규칙을 사용하여 명세를 충족하는지 검증할 수 있습니다. 따라서 형식 검증 도구는 시스템의 정확성에 대한 '수학적 증거'를 제공한다고 합니다. + +테스트와 달리, 형식 검증은 샘플 데이터로 실행할 필요 없이 `모든` 실행에 대해 스마트 계약 실행이 형식 사양을 만족하는지(즉, 버그가 없는지) 확인하는 데 사용할 수 있습니다. 이는 수많은 단위 테스트를 실행하는 데 걸리는 시간을 줄일 뿐만 아니라 숨겨진 취약점을 잡는 데도 더 효과적입니다. 말하자면, 형식 검증 기술은 구현의 난이도와 유용성에 따라 범위에 따라 다릅니다. + +[스마트 계약의 형식 검증에 대해 자세히 알아보기](/developers/docs/smart-contracts/formal-verification) + +## 테스트와 감사 및 버그 바운티 비교 {#testing-vs-audits-bug-bounties} + +앞서 언급했듯이, 엄격한 테스트는 계약에서 버그가 없음을 보장하기 어렵습니다. 형식 검증 접근 방식은 더 강력한 정확성 보증을 제공할 수 있지만, 현재 사용하기 어렵고 상당한 비용이 듭니다. + +그럼에도 불구하고 타인으로 하여금 계약을 분석하도록 하여 계약의 취약점을 포착할 가능성을 높일 수 있습니다. [스마트 계약 감사](https://www.immunebytes.com/blog/what-is-a-smart-contract-audit/)와 [버그 바운티](https://medium.com/immunefi/a-defi-security-standard-the-scaling-bug-bounty-9b83dfdc1ba7)는 다른 사람이 여러분의 계약을 분석하게 하는 두 가지 방법입니다. + +감사는 스마트 계약에서 보안 결함 및 개발 관행의 부족한 사례를 찾는 데 경험이 많은 감사자가 수행합니다. 감사는 테스트(그리고 가능하면 형식 검증)뿐만 아니라 전체 코드베이스에 대한 수동 검토도 포함됩니다. + +반대로 버그 바운티 프로그램은 일반적으로 스마트 계약의 취약점을 발견하여 개발자에게 공개하는 개인(`[화이트햇 해커]()`라고 흔히 칭함)에게 금전적 보상을 제공하는 것을 포함합니다. 버그 바운티는 스마트 계약에서 결함을 찾는 데 다른 사람의 도움을 요청하는 점에서 감사와 유사합니다. + +주요 차이점은 버그 바운티 프로그램이 더 넓은 개발자/해커 커뮤니티에 개방되어 있으며 독특한 기술과 경험을 가진 다양한 윤리적 해커와 독립 보안 전문가들을 끌어들인다는 것입니다. 이것은 제한되거나 좁은 전문 지식을 가진 팀에 의존하는 스마트 계약 감사를 능가하는 장점이 될 수 있습니다. + +## 테스트 도구 및 라이브러리 {#testing-tools-and-libraries} + +### 단위 테스트 도구 {#unit-testing-tools} + +- **[solidity-coverage](https://github.com/sc-forks/solidity-coverage)** - _Solidity로 작성된 스마트 계약을 위한 코드 커버리지 도구입니다._ + +- **[Waffle](https://ethereum-waffle.readthedocs.io/en/latest/)** - _고급 스마트 계약 개발 및 테스트를 위한 프레임워크(ethers.js 기반)입니다._ + +- **[Remix Tests](https://github.com/ethereum/remix-project/tree/master/libs/remix-tests)** - _Solidity 스마트 계약 테스트용 도구입니다._ Remix IDE의 "Solidity Unit Testing" 플러그인을 통해 계약의 테스트 케이스를 작성하고 실행하는 데 사용됩니다._ + +- **[OpenZeppelin Test Helpers](https://github.com/OpenZeppelin/openzeppelin-test-helpers)** - _이더리움 스마트 계약 테스트를 위한 어설션 라이브러리입니다._ 계약이 예상대로 작동하는지 확인하세요!_ + +- **[Brownie 단위 테스트 프레임워크](https://eth-brownie.readthedocs.io/en/v1.0.0_a/tests.html)** - _Brownie는 기능이 풍부한 테스트 프레임워크인 Pytest를 활용하여 최소한의 코드로 작은 테스트를 작성하고, 대규모 프로젝트에 맞게 확장하며, 높은 확장성을 제공합니다._ + +- **[Foundry 테스트](https://github.com/foundry-rs/foundry/tree/master/crates/forge)** - _Foundry는 간단한 단위 테스트, 가스 최적화 확인, 계약 퍼징을 실행할 수 있는 빠르고 유연한 이더리움 테스트 프레임워크인 Forge를 제공합니다._ + +- **[Hardhat 테스트](https://hardhat.org/hardhat-runner/docs/guides/test-contracts)** - _ethers.js, Mocha, Chai를 기반으로 한 스마트 계약 테스트용 프레임워크입니다._ + +- **[ApeWorx](https://docs.apeworx.io/ape/stable/userguides/testing.html)** - _이더리움 가상 머신을 대상으로 하는 스마트 계약을 위한 Python 기반 개발 및 테스트 프레임워크입니다._ + +- **[Wake](https://ackeeblockchain.com/wake/docs/latest/testing-framework/overview/)** - _강력한 디버깅 기능과 교차 체인 테스트를 지원하는 단위 테스트 및 퍼징을 위한 Python 기반 프레임워크로, 최상의 사용자 경험과 성능을 위해 pytest와 Anvil을 활용합니다._ + +### 속성 기반 테스트 도구 {#property-based-testing-tools} + +#### 정적 분석 도구 {#static-analysis-tools} + +- **[Slither](https://github.com/crytic/slither)** - _취약점 발견, 코드 이해도 향상, 스마트 계약을 위한 맞춤형 분석 작성을 위한 Python 기반 Solidity 정적 분석 프레임워크입니다._ + +- **[Ethlint](https://ethlint.readthedocs.io/en/latest/)** - _Solidity 스마트 계약 프로그래밍 언어에 대한 스타일 및 보안 모범 사례를 적용하기 위한 린터입니다._ + +- **[Cyfrin Aderyn](https://cyfrin.io/tools/aderyn)** - _Web3 스마트 계약 보안 및 개발을 위해 특별히 설계된 Rust 기반 정적 분석기입니다._ + +- **[Wake](https://ackeeblockchain.com/wake/docs/latest/static-analysis/using-detectors/)** - _취약성 및 코드 품질 감지기, 코드에서 유용한 정보를 추출하기 위한 프린터, 맞춤형 하위 모듈 작성을 지원하는 Python 기반 정적 분석 프레임워크입니다._ + +- **[Slippy](https://github.com/fvictorio/slippy)** - _Solidity를 위한 간단하고 강력한 린터입니다._ + +#### 동적 분석 도구 {#dynamic-analysis-tools} + +- **[Echidna](https://github.com/crytic/echidna/)** - _속성 기반 테스트를 통해 스마트 계약의 취약점을 탐지하는 빠른 계약 퍼저입니다._ + +- **[Diligence Fuzzing](https://consensys.net/diligence/fuzzing/)** - _스마트 계약 코드에서 속성 위반을 탐지하는 데 유용한 자동화된 퍼징 도구입니다._ + +- **[Manticore](https://manticore.readthedocs.io/en/latest/index.html)** - _EVM 바이트코드 분석을 위한 동적 심볼릭 실행 프레임워크입니다._ + +- **[Mythril](https://github.com/ConsenSys/mythril-classic)** - _테인트 분석, 콘콜릭 분석 및 제어 흐름 검사를 사용하여 계약 취약점을 탐지하는 EVM 바이트코드 평가 도구입니다._ + +- **[Diligence Scribble](https://consensys.net/diligence/scribble/)** - _Scribble은 명세 언어이자 런타임 검증 도구로, 스마트 계약에 속성을 주석으로 달아 Diligence Fuzzing이나 MythX와 같은 도구로 계약을 자동으로 테스트할 수 있게 해줍니다._ + +## 관련 튜토리얼 {#related-tutorials} + +- [다양한 테스트 제품 개요 및 비교](/developers/tutorials/guide-to-smart-contract-security-tools/) \_ +- [Echidna를 사용하여 스마트 계약을 테스트하는 방법](/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/) +- [Manticore를 사용하여 스마트 계약 버그를 찾는 방법](/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/) +- [Slither를 사용하여 스마트 계약 버그를 찾는 방법](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/) +- [테스트를 위해 Solidity 계약을 모의하는 방법](/developers/tutorials/how-to-mock-solidity-contracts-for-testing/) +- [Foundry를 사용하여 Solidity에서 단위 테스트를 실행하는 방법](https://www.rareskills.io/post/foundry-testing-solidity) + +## 더 읽어보기 {#further-reading} + +- [이더리움 스마트 계약 테스트에 대한 심층 가이드](https://iamdefinitelyahuman.medium.com/an-in-depth-guide-to-testing-ethereum-smart-contracts-2e41b2770297) +- [이더리움 스마트 계약을 테스트하는 방법](https://betterprogramming.pub/how-to-test-ethereum-smart-contracts-35abc8fa199d) +- [MolochDAO의 개발자를 위한 단위 테스트 가이드](https://github.com/MolochVentures/moloch/tree/4e786db8a4aa3158287e0935dcbc7b1e43416e38/test#moloch-testing-guide) +- [록스타처럼 스마트 계약을 테스트하는 방법](https://forum.openzeppelin.com/t/test-smart-contracts-like-a-rockstar/1001) diff --git a/public/content/translations/ko/developers/docs/smart-contracts/upgrading/index.md b/public/content/translations/ko/developers/docs/smart-contracts/upgrading/index.md new file mode 100644 index 00000000000..8d7c3939257 --- /dev/null +++ b/public/content/translations/ko/developers/docs/smart-contracts/upgrading/index.md @@ -0,0 +1,165 @@ +--- +title: "스마트 계약 업그레이드" +description: "이더리움 스마트 계약의 업그레이드 패턴 개요" +lang: ko +--- + +이더리움의 스마트 계약은 이더리움 가상 머신(EVM)에서 실행되는 자동 실행 프로그램입니다. 이 프로그램은 설계상 불변성을 가지므로 계약이 배포된 후에는 비즈니스 로직을 업데이트할 수 없습니다. + +불변성은 스마트 계약의 무신뢰성, 탈중앙화 및 보안에 필수적이지만, 경우에 따라 단점이 될 수 있습니다. 예를 들어, 불변 코드로 인해 개발자가 취약한 계약을 수정하는 것이 불가능할 수 있습니다. + +그러나 스마트 계약 개선에 대한 연구가 증가하면서 여러 업그레이드 패턴이 도입되었습니다. 이러한 업그레이드 패턴을 통해 개발자는 비즈니스 로직을 다른 계약에 배치하여 (불변성을 유지하면서) 스마트 계약을 업그레이드할 수 있습니다. + +## 필수 구성 요소 {#prerequisites} + +[스마트 계약](/developers/docs/smart-contracts/), [스마트 계약 구조](/developers/docs/smart-contracts/anatomy/), [이더리움 가상 머신(EVM)](/developers/docs/evm/)에 대해 잘 이해하고 있어야 합니다. 또한 이 가이드는 독자가 스마트 계약 프로그래밍에 대한 이해가 있다고 가정합니다. + +## 스마트 계약 업그레이드란 무엇인가요? {#what-is-a-smart-contract-upgrade} + +스마트 계약 업그레이드는 계약의 상태를 보존하면서 스마트 계약의 비즈니스 로직을 변경하는 것을 포함합니다. 특히 스마트 계약의 맥락에서 업그레이드 가능성과 가변성은 동일하지 않다는 점을 명확히 하는 것이 중요합니다. + +이더리움 네트워크의 주소에 배포된 프로그램은 여전히 변경할 수 없습니다. 하지만 사용자가 스마트 계약과 상호 작용할 때 실행되는 코드는 변경할 수 있습니다. + +다음과 같은 방법을 통해 수행할 수 있습니다. + +1. 스마트 계약의 여러 버전을 만들고 이전 계약에서 계약의 새 인스턴스로 상태(즉, 데이터)를 마이그레이션합니다. + +2. 비즈니스 로직과 상태를 저장하기 위해 별도의 계약을 생성합니다. + +3. 프록시 패턴을 사용하여 불변 프록시 계약에서 수정 가능한 로직 계약으로 함수 호출을 위임합니다. + +4. 특정 함수를 실행하기 위해 유연한 위성 계약과 인터페이스하고 의존하는 불변 메인 계약을 생성합니다. + +5. 다이아몬드 패턴을 사용하여 프록시 계약에서 로직 계약으로 함수 호출을 위임합니다. + +### 업그레이드 메커니즘 #1: 계약 마이그레이션 {#contract-migration} + +계약 마이그레이션은 버전 관리를 기반으로 합니다. 이는 동일한 소프트웨어의 고유한 상태를 생성하고 관리하는 개념입니다. 계약 마이그레이션은 기존 스마트 계약의 새 인스턴스를 배포하고 저장 공간과 잔액을 새 계약으로 이전하는 것을 포함합니다. + +새로 배포된 계약은 빈 저장 공간을 가지므로 이전 계약에서 데이터를 복구하고 새 구현에 쓸 수 있습니다. 그 후에는 이전 계약과 상호 작용했던 모든 계약을 업데이트하여 새 주소를 반영해야 합니다. + +계약 마이그레이션의 마지막 단계는 사용자가 새 계약을 사용하도록 설득하는 것입니다. 새로운 계약 버전은 사용자 잔액과 주소를 유지하여 불변성을 보존합니다. 토큰 기반 계약인 경우 거래소에 연락하여 이전 계약을 폐기하고 새 계약을 사용하도록 해야 합니다. + +계약 마이그레이션은 사용자 상호 작용을 방해하지 않고 스마트 계약을 업그레이드하는 비교적 간단하고 안전한 방법입니다. 그러나 사용자 저장 공간과 잔액을 새 계약으로 수동으로 마이그레이션하는 것은 시간이 많이 걸리고 높은 가스 비용이 발생할 수 있습니다. + +[계약 마이그레이션에 대해 더 알아보기.](https://blog.trailofbits.com/2018/10/29/how-contract-migration-works/) + +### 업그레이드 메커니즘 #2: 데이터 분리 {#data-separation} + +스마트 계약을 업그레이드하는 또 다른 방법은 비즈니스 로직과 데이터 저장 공간을 별도의 계약으로 분리하는 것입니다. 즉, 사용자는 로직 계약과 상호 작용하고 데이터는 저장 공간 계약에 저장됩니다. + +로직 계약에는 사용자가 애플리케이션과 상호 작용할 때 실행되는 코드가 포함됩니다. 또한 저장 공간 계약의 주소를 보유하고 이와 상호 작용하여 데이터를 가져오고 설정합니다. + +한편, 저장 공간 계약은 사용자 잔액 및 주소와 같은 스마트 계약과 관련된 상태를 보유합니다. 저장 공간 계약은 로직 계약이 소유하며 배포 시 로직 계약의 주소로 구성됩니다. 이를 통해 승인되지 않은 계약이 저장 공간 계약을 호출하거나 데이터를 업데이트하는 것을 방지할 수 있습니다. + +기본적으로 저장 공간 계약은 불변이지만, 가리키는 로직 계약을 새로운 구현으로 교체할 수 있습니다. 이렇게 하면 EVM에서 실행되는 코드가 변경되지만 저장 공간과 잔액은 그대로 유지됩니다. + +이 업그레이드 방법을 사용하려면 저장 공간 계약에서 로직 계약의 주소를 업데이트해야 합니다. 앞서 설명한 이유로 새 로직 계약을 저장 공간 계약의 주소로 구성해야 합니다. + +데이터 분리 패턴은 계약 마이그레이션에 비해 구현하기가 더 쉽다고 할 수 있습니다. 하지만 여러 계약을 관리하고 악의적인 업그레이드로부터 스마트 계약을 보호하기 위해 복잡한 권한 부여 체계를 구현해야 합니다. + +### 업그레이드 메커니즘 #3: 프록시 패턴 {#proxy-patterns} + +프록시 패턴은 또한 데이터 분리를 사용하여 비즈니스 로직과 데이터를 별도의 계약에 보관합니다. 그러나 프록시 패턴에서는 저장 공간 계약(프록시라고 함)이 코드 실행 중에 로직 계약을 호출합니다. 이것은 로직 계약이 저장 공간 계약을 호출하는 데이터 분리 방법의 반대입니다. + +프록시 패턴에서 일어나는 일은 다음과 같습니다. + +1. 사용자는 데이터를 저장하지만 비즈니스 로직은 보유하지 않는 프록시 계약과 상호 작용합니다. + +2. 프록시 계약은 로직 계약의 주소를 저장하고 `delegatecall` 함수를 사용하여 모든 함수 호출을 로직 계약(비즈니스 로직을 보유함)에 위임합니다. + +3. 호출이 로직 계약으로 전달된 후, 로직 계약에서 반환된 데이터는 검색되어 사용자에게 반환됩니다. + +프록시 패턴을 사용하려면 **delegatecall** 함수에 대한 이해가 필요합니다. 기본적으로 `delegatecall`은 계약이 다른 계약을 호출할 수 있도록 하는 옵코드이며, 실제 코드 실행은 호출하는 계약의 컨텍스트에서 발생합니다. 프록시 패턴에서 `delegatecall`을 사용하는 것의 한 가지 의미는 프록시 계약이 내부 함수를 호출하는 것처럼 저장 공간을 읽고 쓰며 로직 계약에 저장된 로직을 실행한다는 것입니다. + +[Solidity 개발문서](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html#delegatecall-callcode-and-libraries)에서: + +> _**delegatecall**이라는 특별한 메시지 호출 변형이 존재합니다. 이는 대상 주소의 코드가 호출 계약의 컨텍스트(즉, 주소)에서 실행되고 `msg.sender`와 `msg.value`의 값이 변경되지 않는다는 점을 제외하면 메시지 호출과 동일합니다._ _이는 계약이 런타임에 다른 주소에서 코드를 동적으로 로드할 수 있음을 의미합니다. 저장 공간, 현재 주소 및 잔액은 여전히 호출 계약을 참조하며, 코드는 호출된 주소에서만 가져옵니다._ + +프록시 계약은 내장된 `fallback` 함수가 있기 때문에 사용자가 함수를 호출할 때마다 `delegatecall`을 호출해야 한다는 것을 알고 있습니다. Solidity 프로그래밍에서 [폴백 함수](https://docs.soliditylang.org/en/latest/contracts.html#fallback-function)는 함수 호출이 계약에 지정된 함수와 일치하지 않을 때 실행됩니다. + +프록시 패턴이 작동하려면 프록시 계약이 지원하지 않는 함수 호출을 처리하는 방법을 지정하는 사용자 지정 폴백 함수를 작성해야 합니다. 이 경우 프록시의 폴백 함수는 delegatecall을 시작하고 사용자의 요청을 현재 로직 계약 구현으로 다시 라우팅하도록 프로그래밍됩니다. + +프록시 계약은 기본적으로 불변이지만, 업데이트된 비즈니스 로직을 가진 새로운 로직 계약을 만들 수 있습니다. 그런 다음 업그레이드를 수행하는 것은 프록시 계약에서 참조되는 로직 계약의 주소를 변경하는 문제입니다. + +프록시 계약이 새로운 로직 계약을 가리키도록 함으로써 사용자가 프록시 계약 함수를 호출할 때 실행되는 코드가 변경됩니다. 이를 통해 사용자에게 새로운 계약과 상호 작용하도록 요청하지 않고도 계약의 로직을 업그레이드할 수 있습니다. + +프록시 패턴은 계약 마이그레이션과 관련된 어려움을 없애주기 때문에 스마트 계약을 업그레이드하는 데 널리 사용되는 방법입니다. 그러나 프록시 패턴은 사용하기가 더 복잡하며 부적절하게 사용될 경우 [함수 선택자 충돌](https://medium.com/nomic-foundation-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357)과 같은 치명적인 결함을 유발할 수 있습니다. + +[프록시 패턴에 대해 더 알아보기.](https://blog.openzeppelin.com/proxy-patterns/) + +### 업그레이드 메커니즘 #4: 전략 패턴 {#strategy-pattern} + +이 기술은 특정 기능을 구현하기 위해 다른 프로그램과 인터페이스하는 소프트웨어 프로그램을 만들도록 장려하는 [전략 패턴](https://en.wikipedia.org/wiki/Strategy_pattern)의 영향을 받았습니다. 전략 패턴을 이더리움 개발에 적용하는 것은 다른 계약의 함수를 호출하는 스마트 계약을 구축하는 것을 의미합니다. + +이 경우 메인 계약에는 핵심 비즈니스 로직이 포함되어 있지만, 특정 함수를 실행하기 위해 다른 스마트 계약("위성 계약")과 인터페이스합니다. 이 메인 계약은 각 위성 계약의 주소를 저장하고 위성 계약의 다른 구현 간에 전환할 수 있습니다. + +새로운 위성 계약을 구축하고 메인 계약을 새 주소로 구성할 수 있습니다. 이를 통해 스마트 계약의 전략을 변경(즉, 새로운 로직 구현)할 수 있습니다. + +앞서 논의한 프록시 패턴과 유사하지만, 전략 패턴은 사용자가 상호 작용하는 메인 계약이 비즈니스 로직을 보유하기 때문에 다릅니다. 이 패턴을 사용하면 핵심 인프라에 영향을 주지 않고 스마트 계약에 제한적인 변경을 도입할 수 있습니다. + +주요 단점은 이 패턴이 주로 사소한 업그레이드를 배포하는 데 유용하다는 것입니다. 또한, 메인 계약이 손상된 경우(예: 해킹) 이 업그레이드 방법을 사용할 수 없습니다. + +### 업그레이드 메커니즘 #5: 다이아몬드 패턴 {#diamond-pattern} + +다이아몬드 패턴은 프록시 패턴의 개선된 버전으로 간주될 수 있습니다. 다이아몬드 패턴은 다이아몬드 프록시 계약이 하나 이상의 로직 계약에 함수 호출을 위임할 수 있다는 점에서 프록시 패턴과 다릅니다. + +다이아몬드 패턴의 로직 계약은 패싯으로 알려져 있습니다. 다이아몬드 패턴이 작동하려면 프록시 계약에 [함수 선택자](https://docs.soliditylang.org/en/latest/abi-spec.html#function-selector)를 다른 패싯 주소에 매핑하는 매핑을 만들어야 합니다. + +사용자가 함수를 호출하면 프록시 계약은 매핑을 확인하여 해당 함수 실행을 담당하는 패싯을 찾습니다. 그런 다음 `delegatecall`(폴백 함수 사용)을 호출하고 해당 로직 계약으로 호출을 리디렉션합니다. + +다이아몬드 업그레이드 패턴은 기존 프록시 업그레이드 패턴에 비해 몇 가지 장점이 있습니다. + +1. 모든 코드를 변경하지 않고도 계약의 작은 부분을 업그레이드할 수 있습니다. 업그레이드를 위해 프록시 패턴을 사용하려면 사소한 업그레이드라도 완전히 새로운 로직 계약을 만들어야 합니다. + +2. 모든 스마트 계약(프록시 패턴에서 사용되는 로직 계약 포함)은 24KB 크기 제한이 있으며, 이는 특히 더 많은 기능이 필요한 복잡한 계약의 경우 제한이 될 수 있습니다. 다이아몬드 패턴은 여러 로직 계약에 함수를 분할하여 이 문제를 쉽게 해결할 수 있습니다. + +3. 프록시 패턴은 액세스 제어에 대해 포괄적인 접근 방식을 채택합니다. 업그레이드 함수에 접근할 수 있는 엔티티는 _전체_ 계약을 변경할 수 있습니다. 하지만 다이아몬드 패턴은 모듈식 권한 접근 방식을 가능하게 하여, 스마트 계약 내에서 특정 함수를 업그레이드하는 것을 엔티티에 제한할 수 있습니다. + +[다이아몬드 패턴에 대해 더 알아보기](https://eip2535diamonds.substack.com/p/introduction-to-the-diamond-standard?s=w). + +## 스마트 계약 업그레이드의 장단점 {#pros-and-cons-of-upgrading-smart-contracts} + +| 장점 | 단점 | +| --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| 스마트 계약 업그레이드를 통해 배포 후 단계에서 발견된 취약점을 더 쉽게 수정할 수 있습니다. | 스마트 계약을 업그레이드하는 것은 코드 불변성이라는 개념에 위배되며, 이는 탈중앙화와 보안에 영향을 미칩니다. | +| 개발자는 로직 업그레이드를 사용하여 탈중앙화 애플리케이션에 새로운 기능을 추가할 수 있습니다. | 사용자는 개발자가 스마트 계약을 임의로 수정하지 않을 것이라고 신뢰해야 합니다. | +| 스마트 계약 업그레이드는 버그를 신속하게 수정할 수 있으므로 최종 사용자의 안전을 향상시킬 수 있습니다. | 스마트 계약에 업그레이드 기능을 프로그래밍하는 것은 또 다른 복잡성을 더하고 치명적인 결함의 가능성을 높입니다. | +| 계약 업그레이드는 개발자에게 다양한 기능을 실험하고 시간이 지남에 따라 탈중앙화앱을 개선할 수 있는 더 많은 여지를 제공합니다. | 스마트 계약을 업그레이드할 수 있는 기회는 개발자가 개발 단계에서 실사를 수행하지 않고 프로젝트를 더 빨리 출시하도록 장려할 수 있습니다. | +| | 스마트 계약의 안전하지 않은 접근 제어 또는 중앙 집중화는 악의적인 행위자가 무단 업그레이드를 수행하기 쉽게 만들 수 있습니다. | + +## 스마트 계약 업그레이드 시 고려 사항 {#considerations-for-upgrading-smart-contracts} + +1. 특히 프록시 패턴, 전략 패턴 또는 데이터 분리를 사용하는 경우 무단 스마트 계약 업그레이드를 방지하기 위해 안전한 접근 제어/권한 부여 메커니즘을 사용하세요. 예를 들어, 계약의 소유자만 호출할 수 있도록 업그레이드 기능에 대한 접근을 제한하는 것입니다. + +2. 스마트 계약 업그레이드는 복잡한 활동이며 취약점 도입을 방지하기 위해 높은 수준의 주의가 필요합니다. + +3. 업그레이드 구현 프로세스를 탈중앙화하여 신뢰 가정을 줄이세요. [다중 서명 지갑 계약](/developers/docs/smart-contracts/#multisig)을 사용하여 업그레이드를 제어하거나 [DAO 구성원](/dao/)이 업그레이드 승인에 투표하도록 요구하는 전략이 포함될 수 있습니다. + +4. 계약 업그레이드에 수반되는 비용을 인지하세요. 예를 들어, 계약 마이그레이션 중에 이전 계약에서 새 계약으로 상태(예: 사용자 잔액)를 복사하는 데 두 개 이상의 트랜잭션이 필요할 수 있으며, 이는 더 많은 가스 수수료를 의미합니다. + +5. 사용자를 보호하기 위해 **타임락** 구현을 고려하세요. 타임락은 시스템 변경에 적용되는 지연을 의미합니다. 타임락은 다중 서명 거버넌스 시스템과 결합하여 업그레이드를 제어할 수 있습니다. 제안된 조치가 필요한 승인 임계값에 도달하면 사전 정의된 지연 기간이 경과할 때까지 실행되지 않습니다. + +타임락은 사용자가 제안된 변경(예: 로직 업그레이드 또는 새로운 수수료 체계)에 동의하지 않을 경우 시스템을 종료할 시간을 줍니다. 타임락이 없으면 사용자는 개발자가 사전 통지 없이 스마트 계약에 임의의 변경을 구현하지 않을 것이라고 신뢰해야 합니다. 여기서 단점은 타임락이 취약점을 신속하게 패치하는 능력을 제한한다는 것입니다. + +## 참고 자료 {#resources} + +**OpenZeppelin 업그레이드 플러그인 - _업그레이드 가능한 스마트 계약을 배포하고 보안을 유지하기 위한 도구 모음._** + +- [GitHub](https://github.com/OpenZeppelin/openzeppelin-upgrades) +- [개발문서](https://docs.openzeppelin.com/upgrades) + +## 튜토리얼 {#tutorials} + +- [스마트 계약 업그레이드하기 | 유튜브 튜토리얼](https://www.youtube.com/watch?v=bdXJmWajZRY) - Patrick Collins +- [이더리움 스마트 계약 마이그레이션 튜토리얼](https://medium.com/coinmonks/ethereum-smart-contract-migration-13f6f12539bd) - Austin Griffith +- [UUPS 프록시 패턴을 사용한 스마트 계약 업그레이드](https://blog.logrocket.com/author/praneshas/) - Pranesh A.S +- [Web3 튜토리얼: OpenZeppelin을 사용하여 업그레이드 가능한 스마트 계약(프록시) 작성하기](https://dev.to/yakult/tutorial-write-upgradeable-smart-contract-proxy-contract-with-openzeppelin-1916) - fangjun.eth + +## 더 읽어보기 {#further-reading} + +- [스마트 계약 업그레이드의 현황](https://blog.openzeppelin.com/the-state-of-smart-contract-upgrades/) - Santiago Palladino +- [Solidity 스마트 계약을 업그레이드하는 여러 방법](https://cryptomarketpool.com/multiple-ways-to-upgrade-a-solidity-smart-contract/) - Crypto Market Pool 블로그 +- [학습: 스마트 계약 업그레이드](https://docs.openzeppelin.com/learn/upgrading-smart-contracts) - OpenZeppelin 개발문서 +- [Solidity 계약의 업그레이드 가능성을 위한 프록시 패턴: 투명 프록시 vs UUPS 프록시](https://mirror.xyz/0xB38709B8198d147cc9Ff9C133838a044d78B064B/M7oTptQkBGXxox-tk9VJjL66E1V8BUF0GF79MMK4YG0) - Naveen Sahu +- [다이아몬드 업그레이드 작동 방식](https://dev.to/mudgen/how-diamond-upgrades-work-417j) - Nick Mudge diff --git a/public/content/translations/ko/developers/docs/smart-contracts/verifying/index.md b/public/content/translations/ko/developers/docs/smart-contracts/verifying/index.md new file mode 100644 index 00000000000..e51bc39c8aa --- /dev/null +++ b/public/content/translations/ko/developers/docs/smart-contracts/verifying/index.md @@ -0,0 +1,113 @@ +--- +title: "스마트 계약 인증" +description: "이더리움 스마트 계약의 소스 코드 검증 개요" +lang: ko +--- + +[스마트 계약](/developers/docs/smart-contracts/)은 '무신뢰성(trustless)'을 갖도록 설계되었습니다. 즉, 사용자가 계약과 상호 작용하기 전에 제3자(예: 개발자 및 회사)를 신뢰할 필요가 없다는 것을 의미합니다. 무신뢰성을 위한 전제 조건으로, 사용자와 다른 개발자는 스마트 계약의 소스 코드를 검증할 수 있어야 합니다. 소스 코드 검증은 게시된 계약 코드가 이더리움 블록체인의 계약 주소에서 실행되는 코드와 동일하다는 것을 사용자와 개발자에게 보장합니다. + +"소스 코드 검증"과 "[정형 검증](/developers/docs/smart-contracts/formal-verification/)"을 구별하는 것이 중요합니다. 아래에서 자세히 설명하겠지만 소스 코드 검증은 고급 언어(예: Solidity)로 작성된 스마트 계약의 주어진 소스 코드가 계약 주소에서 실행될 바이트코드와 동일하게 컴파일되는지 검증하는 것을 말합니다. 하지만 정형 검증은 스마트 계약의 정확성을 검증하는 것을 의미하며, 이는 계약이 예상대로 작동하는 것을 의미합니다. 문맥에 따라 다르지만, 계약 검증은 일반적으로 소스 코드 검증을 의미합니다. + +## 소스 코드 검증이란 무엇인가요? {#what-is-source-code-verification} + +[이더리움 가상 머신(EVM)](/developers/docs/evm/)에 스마트 계약을 배포하기 전에 개발자들은 계약의 소스 코드, 즉 [솔리디티](/developers/docs/smart-contracts/languages/) 또는 다른 고급 프로그래밍 언어로 작성된 지침을 바이트코드로 [컴파일](/developers/docs/smart-contracts/compiling/)합니다. EVM은 고급 지침을 해석할 수 없으므로, 소스 코드를 바이트코드(즉, 저수준 기계 명령어)로 컴파일하는 것은 EVM에서 계약 로직을 실행하는 데 필요합니다. + +소스 코드 검증은 스마트 계약의 소스 코드와 계약 생성 중에 사용된 컴파일된 바이트코드를 비교하여 차이점을 감지하는 것입니다. 스마트 계약을 검증하는 것이 중요한 이유는 광고된 계약 코드가 블록체인에서 실행되는 것과 다를 수 있기 때문입니다. + +스마트 계약 검증을 통해 기계 코드를 읽을 필요 없이 계약이 작성된 고급 언어를 통해 계약이 수행하는 작업을 조사할 수 있습니다. 함수, 값, 그리고 일반적으로 변수 이름과 주석은 컴파일 및 배포된 원본 소스 코드와 동일하게 유지됩니다. 이를 통해 코드를 훨씬 쉽게 읽을 수 있습니다. 소스 검증은 또한 최종 사용자가 스마트 계약이 무엇을 하도록 설계되었는지 알 수 있도록 코드 문서화를 제공합니다. + +### 전체 검증이란 무엇인가요? {#full-verification} + +소스 코드에는 주석이나 변수 이름과 같이 컴파일된 바이트코드에 영향을 주지 않는 일부 부분이 있습니다. 이는 서로 다른 변수 이름과 다른 주석을 가진 두 개의 소스 코드가 모두 동일한 계약을 검증할 수 있다는 것을 의미합니다. 이로 인해 악의적인 행위자가 소스 코드 내에 기만적인 주석을 추가하거나 오해의 소지가 있는 변수 이름을 부여하고 원본 소스 코드와 다른 소스 코드로 계약을 검증받을 수 있습니다. + +소스 코드의 정확성에 대한 암호화 보증과 컴파일 정보의 _지문_ 역할을 하도록 바이트코드에 추가 데이터를 추가하여 이를 방지할 수 있습니다. 필요한 정보는 [솔리디티의 계약 메타데이터](https://docs.soliditylang.org/en/v0.8.15/metadata.html)에 있으며, 이 파일의 해시는 계약의 바이트코드에 추가됩니다. [메타데이터 플레이그라운드](https://playground.sourcify.dev)에서 작동하는 것을 볼 수 있습니다. + +메타데이터 파일에는 소스 파일과 그 해시를 포함하여 계약의 컴파일에 대한 정보가 포함되어 있습니다. 즉, 컴파일 설정이나 소스 파일 중 하나의 바이트라도 변경되면 메타데이터 파일이 변경됩니다. 결과적으로 바이트코드에 추가되는 메타데이터 파일의 해시도 변경됩니다. 즉, 계약의 바이트코드 + 추가된 메타데이터 해시가 주어진 소스 코드 및 컴파일 설정과 일치하면, 이것이 원본 컴파일에 사용된 소스 코드와 정확히 동일하며 단 한 바이트도 다르지 않다는 것을 확신할 수 있습니다. + +메타데이터 해시를 활용하는 이러한 유형의 검증은 **"[전체 검증](https://docs.sourcify.dev/docs/full-vs-partial-match/)"**(또는 "완벽한 검증")이라고 합니다. 메타데이터 해시가 일치하지 않거나 검증에서 고려되지 않으면 "부분 일치"가 되며, 이는 현재 계약을 검증하는 더 일반적인 방법입니다. 전체 검증 없이는 검증된 소스 코드에 반영되지 않는 [악성 코드](https://samczsun.com/hiding-in-plain-sight/)를 삽입하는 것이 가능합니다. 대부분의 개발자는 전체 검증을 인지하지 못하고 컴파일의 메타데이터 파일을 보관하지 않으므로, 지금까지 부분 검증이 계약을 검증하는 사실상의 방법이었습니다. + +## 소스 코드 검증이 왜 중요한가요? {#importance-of-source-code-verification} + +### 무신뢰성 {#trustlessness} + +무신뢰성은 스마트 계약과 [탈중앙화 애플리케이션(탈중앙화앱)](/developers/docs/dapps/)의 가장 큰 전제라고 할 수 있습니다. 스마트 계약은 “불변”이며 변경할 수 없습니다. 계약은 배포 시점에 코드에 정의된 비즈니스 로직만 실행합니다. 이는 개발자와 기업이 이더리움에 배포한 후 계약 코드를 변조할 수 없음을 의미합니다. + +스마트 계약이 무신뢰성을 가지려면 계약 코드를 독립적으로 검증할 수 있어야 합니다. 모든 스마트 계약의 컴파일된 바이트코드는 블록체인에 공개적으로 사용할 수 있지만, 저수준 언어는 개발자와 사용자 모두에게 이해하기 어렵습니다. + +프로젝트는 계약의 소스 코드를 게시하여 신뢰 가정을 줄입니다. 하지만 이는 또 다른 문제로 이어집니다. 게시된 소스 코드가 계약 바이트코드와 일치하는지 확인하기 어렵다는 것입니다. 이 시나리오에서는 사용자가 개발자가 블록체인에 배포하기 전에 계약의 비즈니스 로직(즉, 바이트코드를 변경)을 변경하지 않을 것이라고 신뢰해야 하므로 무신뢰성의 가치가 상실됩니다. + +소스 코드 검증 도구는 스마트 계약의 소스 코드 파일이 어셈블리 코드와 일치함을 보장합니다. 그 결과 사용자가 제3자를 맹목적으로 신뢰하지 않고 계약에 자금을 예치하기 전에 코드를 검증하는 무신뢰 생태계가 만들어집니다. + +### 사용자 안전 {#user-safety} + +스마트 계약에는 일반적으로 많은 돈이 걸려 있습니다. 따라서 스마트 계약을 사용하기 전에 더 높은 보안 보장과 로직 검증이 필요합니다. 문제는 비양심적인 개발자가 스마트 계약에 악성 코드를 삽입하여 사용자를 속일 수 있다는 것입니다. 검증 없이는 악성 스마트 계약에 [백도어](https://www.trustnodes.com/2018/11/10/concerns-rise-over-backdoored-smart-contracts), 논란의 여지가 있는 접근 제어 메커니즘, 악용 가능한 취약점 및 감지되지 않은 채 사용자 안전을 위협하는 기타 사항들이 있을 수 있습니다. + +스마트 계약의 소스 코드 파일을 게시하면 감사자와 같은 이해관계자들이 잠재적인 공격 벡터에 대해 계약을 평가하기가 더 쉬워집니다. 여러 당사자가 독립적으로 스마트 계약을 검증함으로써 사용자는 보안에 대한 더 강력한 보증을 받게 됩니다. + +## 이더리움 스마트 계약의 소스 코드를 검증하는 방법 {#source-code-verification-for-ethereum-smart-contracts} + +[이더리움에 스마트 계약 배포](/developers/docs/smart-contracts/deploying/)는 데이터 페이로드(컴파일된 바이트코드)가 포함된 트랜잭션을 특수 주소로 보내야 합니다. 데이터 페이로드는 소스 코드를 컴파일하여 생성되며, 여기에 트랜잭션의 데이터 페이로드에 추가된 계약 인스턴스의 [생성자 인수](https://docs.soliditylang.org/en/v0.8.14/contracts.html#constructor)가 더해집니다. 컴파일은 결정론적입니다. 즉, 동일한 소스 파일과 컴파일 설정(예: 컴파일러 버전, 최적화 프로그램)이 사용되는 경우 항상 동일한 출력(즉, 계약 바이트코드)을 생성합니다. + +![스마트 계약 소스 코드 검증을 보여주는 다이어그램](./source-code-verification.png) + +스마트 계약을 검증하는 것은 기본적으로 다음 단계를 포함합니다: + +1. 컴파일러에 소스 파일과 컴파일 설정을 입력합니다. + +2. 컴파일러는 계약의 바이트코드를 출력합니다. + +3. 지정된 주소에서 배포된 계약의 바이트코드를 가져옵니다. + +4. 배포된 바이트코드를 다시 컴파일된 바이트코드와 비교합니다. 코드가 일치하면 계약은 주어진 소스 코드와 컴파일 설정으로 검증됩니다. + +5. 추가로, 바이트코드 끝에 있는 메타데이터 해시가 일치하면 전체 일치가 됩니다. + +이는 검증에 대한 단순한 설명이며, [불변 변수](https://docs.sourcify.dev/docs/immutables/)를 갖는 것과 같이 이 방법으로 작동하지 않는 많은 예외가 있다는 점에 유의하세요. + +## 소스 코드 검증 도구 {#source-code-verification-tools} + +계약을 검증하는 전통적인 프로세스는 복잡할 수 있습니다. 이것이 이더리움에 배포된 스마트 계약의 소스 코드를 검증하기 위한 도구가 있는 이유입니다. 이러한 도구는 소스 코드 검증의 많은 부분을 자동화하고 사용자의 이익을 위해 검증된 계약을 큐레이션합니다. + +### Etherscan {#etherscan} + +주로 [이더리움 블록체인 탐색기](/developers/docs/data-and-analytics/block-explorers/)로 알려져 있지만, Etherscan은 스마트 계약 개발자와 사용자를 위한 [소스 코드 검증 서비스](https://etherscan.io/verifyContract)도 제공합니다. + +Etherscan을 사용하면 원본 데이터 페이로드(소스 코드, 라이브러리 주소, 컴파일러 설정, 계약 주소 등)에서 계약 바이트코드를 다시 컴파일할 수 있습니다. 다시 컴파일된 바이트코드가 온체인 계약의 바이트코드(및 생성자 매개변수)와 연결되면 [계약이 검증됩니다](https://info.etherscan.com/types-of-contract-verification/). + +검증이 완료되면 계약의 소스 코드는 "검증됨" 라벨을 받고 다른 사람들이 감사할 수 있도록 Etherscan에 게시됩니다. 또한 검증된 소스 코드가 있는 스마트 계약의 저장소인 [검증된 계약](https://etherscan.io/contractsVerified/) 섹션에도 추가됩니다. + +Etherscan은 계약을 검증하는 데 가장 많이 사용되는 도구입니다. 그러나 Etherscan의 계약 검증에는 단점이 있습니다. 온체인 바이트코드와 재컴파일된 바이트코드의 메타데이터 해시를 비교하지 못합니다. 따라서 Etherscan에서의 일치는 부분 일치입니다. + +[Etherscan에서 계약 검증에 대해 더 알아보기](https://medium.com/etherscan-blog/verifying-contracts-on-etherscan-f995ab772327). + +### Blockscout {#blockscout} + +[Blockscout](https://blockscout.com/)은 오픈소스 블록체인 탐색기로 스마트 계약 개발자와 사용자를 위한 [계약 검증 서비스](https://eth.blockscout.com/contract-verification)도 제공합니다. 오픈 소스 대안으로서 Blockscout은 검증이 수행되는 방식의 투명성을 제공하고 커뮤니티가 검증 프로세스를 개선하는 데 기여할 수 있도록 합니다. + +다른 검증 서비스와 마찬가지로 Blockscout을 사용하면 바이트코드를 다시 컴파일하고 배포된 계약과 비교하여 계약의 소스 코드를 검증할 수 있습니다. 검증이 완료되면 계약은 검증 상태를 받게 되며 소스 코드는 감사 및 상호 작용을 위해 공개적으로 사용할 수 있게 됩니다. 검증된 계약은 쉽게 찾아보고 발견할 수 있도록 Blockscout의 [검증된 계약 저장소](https://eth.blockscout.com/verified-contracts)에도 나열됩니다. + +### Sourcify {#sourcify} + +[Sourcify](https://sourcify.dev/#/verifier)는 오픈 소스이고 분산된 또 다른 계약 검증 도구입니다. 이것은 블록 탐색기가 아니며 [다양한 EVM 기반 네트워크](https://docs.sourcify.dev/docs/chains)에서 계약만 검증합니다. 이는 다른 도구가 그 위에 구축할 수 있는 공용 인프라 역할을 하며, 메타데이터 파일에 있는 [ABI](/developers/docs/smart-contracts/compiling/#web-applications) 및 [NatSpec](https://docs.soliditylang.org/en/v0.8.15/natspec-format.html) 주석을 사용하여 보다 인간 친화적인 계약 상호 작용을 가능하게 하는 것을 목표로 합니다. + +Etherscan과 달리 Sourcify는 메타데이터 해시와의 전체 일치를 지원합니다. 검증된 계약은 HTTP 및 분산된 [콘텐츠 주소 지정](https://docs.storacha.network/concepts/content-addressing/) 스토리지인 [IPFS](https://docs.ipfs.io/concepts/what-is-ipfs/#what-is-ipfs)의 [공개 리포지토리](https://docs.sourcify.dev/docs/repository/)에서 제공됩니다. 추가된 메타데이터 해시가 IPFS 해시이므로 이를 통해 IPFS를 통해 계약의 메타데이터 파일을 가져올 수 있습니다. + +또한 이 파일들의 IPFS 해시도 메타데이터에서 찾을 수 있으므로 IPFS를 통해 소스 코드 파일을 검색할 수도 있습니다. API 또는 [UI](https://sourcify.dev/#/verifier)를 통해 메타데이터 파일과 소스 파일을 제공하거나 플러그인을 사용하여 계약을 확인할 수 있습니다. Sourcify 모니터링 도구는 또한 새 블록에서 계약 생성을 수신하고 메타데이터 및 소스 파일이 IPFS에 게시된 경우 계약을 확인하려고 시도합니다. + +[Sourcify에서 계약 검증에 대해 더 알아보기](https://soliditylang.org/blog/2020/06/25/sourcify-faq/). + +### Tenderly {#tenderly} + +[Tenderly 플랫폼](https://tenderly.co/)은 웹3 개발자가 스마트 계약을 구축, 테스트, 모니터링 및 운영할 수 있도록 합니다. 디버깅 도구와 관찰 가능성 및 인프라 구성 요소를 결합하여 Tenderly는 개발자가 스마트 계약 개발을 가속화하도록 돕습니다. Tenderly 기능을 완전히 활성화하려면 개발자는 여러 방법을 사용하여 [소스 코드 검증을 수행](https://docs.tenderly.co/monitoring/contract-verification)해야 합니다. + +계약을 비공개 또는 공개적으로 확인할 수 있습니다. 비공개로 확인된 경우 스마트 계약은 귀하(및 프로젝트의 다른 구성원)에게만 표시됩니다. 계약을 공개적으로 확인하면 Tenderly 플랫폼을 사용하는 모든 사람이 볼 수 있습니다. + +[대시보드](https://docs.tenderly.co/contract-verification), [Tenderly Hardhat 플러그인](https://docs.tenderly.co/contract-verification/hardhat) 또는 [CLI](https://docs.tenderly.co/monitoring/smart-contract-verification/verifying-contracts-using-cli)를 사용하여 계약을 확인할 수 있습니다. + +대시보드를 통해 계약을 확인할 때 Solidity 컴파일러에서 생성된 소스 파일 또는 메타데이터 파일, 주소/네트워크 및 컴파일러 설정을 가져와야 합니다. + +Tenderly Hardhat 플러그인을 사용하면 더 적은 노력으로 검증 프로세스를 더 많이 제어할 수 있으므로 자동(코드 없음) 및 수동(코드 기반) 검증 중에서 선택할 수 있습니다. + +## 더 읽어보기 {#further-reading} + +- [계약 소스 코드 검증](https://programtheblockchain.com/posts/2018/01/16/verifying-contract-source-code/) diff --git a/public/content/translations/ko/developers/docs/standards/index.md b/public/content/translations/ko/developers/docs/standards/index.md new file mode 100644 index 00000000000..2067fd392a2 --- /dev/null +++ b/public/content/translations/ko/developers/docs/standards/index.md @@ -0,0 +1,59 @@ +--- +title: "이더리움 개발 표준" +description: "EIP, ERC-20, ERC-721과 같은 토큰 표준, 개발 컨벤션을 포함한 이더리움 표준에 대해 알아보세요." +lang: ko +incomplete: true +--- + +## 표준 개요 {#standards-overview} + +이더리움 커뮤니티는 [이더리움 클라이언트](/developers/docs/nodes-and-clients/) 및 지갑과 같은 프로젝트가 여러 구현에서 상호 운용성을 유지하고 스마트 계약과 탈중앙화앱이 구성 가능하도록 유지하는 데 도움이 되는 많은 표준을 채택했습니다. + +일반적으로 표준은 [이더리움 개선 제안](/eips/)(EIP)으로 도입되며, 이는 [표준 절차](https://eips.ethereum.org/EIPS/eip-1)를 통해 커뮤니티 구성원들이 논의합니다. + +- [EIP 소개](/eips/) +- [EIP 목록](https://eips.ethereum.org/) +- [EIP GitHub 리포지토리](https://github.com/ethereum/EIPs) +- [EIP 토론 게시판](https://ethereum-magicians.org/c/eips) +- [이더리움 거버넌스 소개](/governance/) +- [이더리움 거버넌스 개요](https://web.archive.org/web/20201107234050/https://blog.bmannconsulting.com/ethereum-governance/) _2019년 3월 31일 - Boris Mann_ +- [이더리움 프로토콜 개발 거버넌스 및 네트워크 업그레이드 조정](https://hudsonjameson.com/posts/2020-03-23-ethereum-protocol-development-governance-and-network-upgrade-coordination/) _2020년 3월 23일 - Hudson Jameson_ +- [모든 이더리움 코어 개발자 회의 재생목록](https://www.youtube.com/@EthereumProtocol) _(YouTube 재생목록)_ + +## 표준의 유형 {#types-of-standards} + +EIP에는 3가지 유형이 있습니다: + +- 표준 트랙: 대부분 또는 모든 이더리움 구현에 영향을 미치는 변경 사항을 설명합니다 +- [메타 트랙](https://eips.ethereum.org/meta): 이더리움 관련 프로세스를 설명하거나 프로세스 변경을 제안합니다 +- [정보 트랙](https://eips.ethereum.org/informational): 이더리움 설계 문제를 설명하거나 이더리움 커뮤니티에 일반적인 가이드라인이나 정보를 제공합니다 + +또한 표준 트랙은 4가지 카테고리로 세분화됩니다: + +- [코어](https://eips.ethereum.org/core): 합의 포크가 필요한 개선 사항 +- [네트워킹](https://eips.ethereum.org/networking): devp2p 및 라이트 이더리움 하위 프로토콜 관련 개선 사항, 그리고 위스퍼 및 스웜의 네트워크 프로토콜 사양에 대한 제안된 개선 사항. +- [인터페이스](https://eips.ethereum.org/interface): 클라이언트 API/RPC 사양 및 표준 관련 개선 사항, 그리고 메서드 이름 및 계약 ABI와 같은 특정 언어 수준 표준. +- [ERC](https://eips.ethereum.org/erc): 애플리케이션 수준의 표준 및 관례 + +이러한 다양한 유형 및 카테고리에 대한 자세한 정보는 [EIP-1](https://eips.ethereum.org/EIPS/eip-1#eip-types)에서 확인할 수 있습니다 + +### 토큰 표준 {#token-standards} + +- [ERC-20](/developers/docs/standards/tokens/erc-20/) - 투표 토큰, 스테이킹 토큰 또는 가상 화폐와 같은 대체 가능한(상호 교환 가능한) 토큰을 위한 표준 인터페이스입니다. + - [ERC-223](/developers/docs/standards/tokens/erc-223/) - 토큰이 이더와 동일하게 작동하도록 하고 수신자 측에서 토큰 전송 처리를 지원하는 대체 가능한 토큰 표준입니다. + - [ERC-1363](/developers/docs/standards/tokens/erc-1363/) - 단일 트랜잭션에서 수신자 계약에 대한 콜백 실행을 지원하는 ERC-20 토큰의 확장 인터페이스입니다. +- [ERC-721](/developers/docs/standards/tokens/erc-721/) - 예술품이나 노래의 증서와 같은 대체 불가능한 토큰을 위한 표준 인터페이스입니다. + - [ERC-2309](https://eips.ethereum.org/EIPS/eip-2309) - 연속적인 토큰 식별자를 사용하여 하나 또는 여러 개의 대체 불가능한 토큰을 생성/전송할 때 방출되는 표준화된 이벤트입니다. + - [ERC-4400](https://eips.ethereum.org/EIPS/eip-4400) - EIP-721 소비자 역할을 위한 인터페이스 확장입니다. + - [ERC-4907](https://eips.ethereum.org/EIPS/eip-4907) - ERC-721 토큰에 제한된 권한을 가진 시간 제한 역할을 추가합니다. +- [ERC-777](/developers/docs/standards/tokens/erc-777/) - **(권장되지 않음)** ERC-20을 개선한 토큰 표준입니다. +- [ERC-1155](/developers/docs/standards/tokens/erc-1155/) - 대체 가능한 자산과 대체 불가능한 자산을 모두 포함할 수 있는 토큰 표준입니다. +- [ERC-4626](/developers/docs/standards/tokens/erc-4626/) - 수익률 생성 볼트의 기술적 파라미터를 최적화하고 통합하도록 설계된 토큰화된 볼트 표준입니다. + +[토큰 표준](/developers/docs/standards/tokens/)에 대해 더 자세히 알아보세요. + +## 더 읽어보기 {#further-reading} + +- [이더리움 개선 제안(EIP)](/eips/) + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ diff --git a/public/content/translations/ko/developers/docs/standards/tokens/erc-1155/index.md b/public/content/translations/ko/developers/docs/standards/tokens/erc-1155/index.md new file mode 100644 index 00000000000..4c6f68f331f --- /dev/null +++ b/public/content/translations/ko/developers/docs/standards/tokens/erc-1155/index.md @@ -0,0 +1,146 @@ +--- +title: "ERC-1155 멀티 토큰 표준" +description: "단일 계약에서 대체 가능 토큰과 대체 불가 토큰을 결합하는 멀티 토큰 표준인 ERC-1155에 대해 알아보세요." +lang: ko +--- + +## 소개 {#introduction} + +여러 토큰 유형을 관리하는 계약을 위한 표준 인터페이스입니다. 배포된 단일 계약은 대체 가능 토큰, 대체 불가 토큰 또는 기타 구성(예: 준대체 가능 토큰)의 모든 조합을 포함할 수 있습니다. + +**멀티 토큰 표준이란 무엇인가요?** + +이 아이디어는 간단하며, 모든 수의 대체 가능 토큰 유형과 대체 불가 토큰 유형을 나타내고 제어할 수 있는 스마트 계약 인터페이스를 만드는 것을 목표로 합니다. 이러한 방식으로 ERC-1155 토큰은 [ERC-20](/developers/docs/standards/tokens/erc-20/) 및 [ERC-721](/developers/docs/standards/tokens/erc-721/) 토큰과 동일한 기능을 수행할 수 있으며, 심지어 동시에 두 가지 기능 모두를 수행할 수도 있습니다. ERC-20 및 ERC-721 표준의 기능을 모두 개선하여 더 효율적이고 명백한 구현 오류를 수정합니다. + +ERC-1155 토큰은 [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155)에 자세히 설명되어 있습니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하려면 먼저 [토큰 표준](/developers/docs/standards/tokens/), [ERC-20](/developers/docs/standards/tokens/erc-20/), [ERC-721](/developers/docs/standards/tokens/erc-721/)에 대해 읽어보시는 것을 권장합니다. + +## ERC-1155의 기능과 특징: {#body} + +- [일괄 전송](#batch_transfers): 단일 호출로 여러 자산을 전송합니다. +- [일괄 잔액 조회](#batch_balance): 단일 호출로 여러 자산의 잔액을 조회합니다. +- [일괄 승인](#batch_approval): 주소에 모든 토큰을 승인합니다. +- [훅](#receive_hook): 토큰 수신 훅입니다. +- [NFT 지원](#nft_support): 공급량이 1인 경우 NFT로 취급합니다. +- [안전 전송 규칙](#safe_transfer_rule): 안전한 전송을 위한 규칙 집합입니다. + +### 일괄 전송 {#batch-transfers} + +일괄 전송은 일반적인 ERC-20 전송과 매우 유사하게 작동합니다. 일반적인 ERC-20의 `transferFrom` 함수를 살펴보겠습니다. + +```solidity +// ERC-20 +function transferFrom(address from, address to, uint256 value) external returns (bool); + +// ERC-1155 +function safeBatchTransferFrom( + address _from, + address _to, + uint256[] calldata _ids, + uint256[] calldata _values, + bytes calldata _data +) external; +``` + +ERC-1155의 유일한 차이점은 값을 배열로 전달하고, ID 배열도 전달한다는 것입니다. 예를 들어, `ids=[3, 6, 13]`과 `values=[100, 200, 5]`가 주어지면 결과적인 전송은 다음과 같습니다. + +1. `_from`에서 `_to`로 ID가 3인 토큰 100개를 전송합니다. +2. `_from`에서 `_to`로 ID가 6인 토큰 200개를 전송합니다. +3. `_from`에서 `_to`로 ID가 13인 토큰 5개를 전송합니다. + +ERC-1155에는 `transfer`는 없고 `transferFrom`만 있습니다. 일반 `transfer`처럼 사용하려면, from 주소를 함수를 호출하는 주소로 설정하기만 하면 됩니다. + +### 일괄 잔액 조회 {#batch-balance} + +각각의 ERC-20 `balanceOf` 호출에도 마찬가지로 일괄 처리를 지원하는 파트너 함수가 있습니다. 참고로, ERC-20 버전은 다음과 같습니다. + +```solidity +// ERC-20 +function balanceOf(address owner) external view returns (uint256); + +// ERC-1155 +function balanceOfBatch( + address[] calldata _owners, + uint256[] calldata _ids +) external view returns (uint256[] memory); +``` + +잔액 호출의 경우, 단일 호출로 여러 잔액을 훨씬 간단하게 검색할 수 있습니다. 소유자 배열을 전달하고, 이어서 토큰 ID 배열을 전달합니다. + +예를 들어 `_ids=[3, 6, 13]`과 `_owners=[0xbeef..., 0x1337..., 0x1111...]`가 주어지면 반환 값은 다음과 같습니다. + +```solidity +[ + balanceOf(0xbeef...), + balanceOf(0x1337...), + balanceOf(0x1111...) +] +``` + +### 일괄 승인 {#batch-approval} + +```solidity +// ERC-1155 +function setApprovalForAll( + address _operator, + bool _approved +) external; + +function isApprovedForAll( + address _owner, + address _operator +) external view returns (bool); +``` + +승인은 ERC-20과 약간 다릅니다. 특정 금액을 승인하는 대신 `setApprovalForAll`을 통해 운영자를 승인 또는 미승인으로 설정합니다. + +현재 상태는 `isApprovedForAll`을 통해 확인할 수 있습니다. 보시다시피, 이것은 전부 아니면 전무 방식의 작업입니다. 승인할 토큰 수나 토큰 클래스를 정의할 수 없습니다. + +이것은 단순함을 염두에 두고 의도적으로 설계되었습니다. 하나의 주소에 대해서만 모든 것을 승인할 수 있습니다. + +### 수신 훅 {#receive-hook} + +```solidity +function onERC1155BatchReceived( + address _operator, + address _from, + uint256[] calldata _ids, + uint256[] calldata _values, + bytes calldata _data +) external returns(bytes4); +``` + +[EIP-165](https://eips.ethereum.org/EIPS/eip-165) 지원에 따라, ERC-1155는 스마트 계약에 대해서만 수신 훅을 지원합니다. 훅 함수는 다음과 같이 지정된 미리 정의된 특정 bytes4 값을 반환해야 합니다. + +```solidity +bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)")) +``` + +수신 계약이 이 값을 반환하면, 해당 계약이 전송을 수락하고 ERC-1155 토큰을 처리하는 방법을 알고 있는 것으로 간주됩니다. 더 이상 계약에 토큰이 묶이는 일이 없습니다! + +### NFT 지원 {#nft-support} + +공급량이 1일 때, 토큰은 본질적으로 대체 불가 토큰(NFT)입니다. 또한 ERC-721의 표준과 마찬가지로, 메타데이터 URL을 정의할 수 있습니다. 클라이언트가 URL을 읽고 수정할 수 있습니다. 자세한 내용은 [여기](https://eips.ethereum.org/EIPS/eip-1155#metadata)를 참조하세요. + +### 안전 전송 규칙 {#safe-transfer-rule} + +앞선 설명에서 이미 몇 가지 안전 전송 규칙을 다루었습니다. 하지만 가장 중요한 규칙들을 살펴보겠습니다. + +1. 호출자는 `_from` 주소의 토큰을 사용할 수 있도록 승인받았거나, 호출자가 `_from`과 같아야 합니다. +2. 다음과 같은 경우 전송 호출이 되돌려져야 합니다. + 1. `_to` 주소가 0인 경우. + 2. `_ids`의 길이가 `_values`의 길이와 같지 않은 경우. + 3. `_ids`에 있는 토큰 보유자의 잔액 중 어느 하나라도 수신자에게 전송된 `_values`의 해당 금액보다 낮은 경우. + 4. 기타 오류가 발생하는 경우. + +_참고_: 훅을 포함한 모든 일괄 함수는 일괄 처리 기능이 없는 버전으로도 존재합니다. 단일 자산을 전송하는 것이 여전히 가장 보편적으로 사용되는 방법일 가능성이 높다는 점을 고려할 때, 이는 가스 효율성을 위한 것입니다. 설명을 간단하게 하기 위해 안전 전송 규칙을 포함한 해당 내용들을 생략했습니다. 이름은 동일하며, 'Batch'만 제거하면 됩니다. + +## 더 읽어보기 {#further-reading} + +- [EIP-1155: 멀티 토큰 표준](https://eips.ethereum.org/EIPS/eip-1155) +- [ERC-1155: Openzeppelin 문서](https://docs.openzeppelin.com/contracts/5.x/erc1155) +- [ERC-1155: GitHub 저장소](https://github.com/enjin/erc-1155) +- [Alchemy NFT API](https://www.alchemy.com/docs/reference/nft-api-quickstart) diff --git a/public/content/translations/ko/developers/docs/standards/tokens/erc-1363/index.md b/public/content/translations/ko/developers/docs/standards/tokens/erc-1363/index.md new file mode 100644 index 00000000000..a939e576656 --- /dev/null +++ b/public/content/translations/ko/developers/docs/standards/tokens/erc-1363/index.md @@ -0,0 +1,82 @@ +--- +title: "ERC-1363 지불 가능 토큰 표준" +description: "ERC-1363은 단일 트랜잭션 내에서 전송 후 수신자 계약에서 또는 승인 후 지출자 계약에서 맞춤형 로직 실행을 지원하는 ERC-20 토큰의 확장 인터페이스입니다." +lang: ko +--- + +## 소개 {#introduction} + +### ERC-1363은 무엇인가요? {#what-is-erc1363} + +ERC-1363은 단일 트랜잭션 내에서 전송 후 수신자 계약에서 또는 승인 후 지출자 계약에서 맞춤형 로직 실행을 지원하는 ERC-20 토큰의 확장 인터페이스입니다. + +### ERC-20과의 차이점 {#erc20-differences} + +`transfer`, `transferFrom` 및 `approve`와 같은 표준 ERC-20 작업은 별도의 트랜잭션 없이는 수신자 또는 지출자 계약에서 코드 실행을 허용하지 않습니다. +사용자는 첫 번째 트랜잭션을 실행한 다음 두 번째 트랜잭션을 제출해야 하므로 이는 UI 개발의 복잡성을 가중시키고 채택에 마찰을 일으킵니다. +또한 가스를 두 번 지불해야 합니다. + +ERC-1363을 사용하면 대체 가능 토큰이 더 쉽게 작업을 수행하고 오프체인 리스너 없이 작동할 수 있습니다. +단일 트랜잭션에서 전송 또는 승인 후 수신자 또는 지출자 계약에 대한 콜백을 수행할 수 있습니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하려면 먼저 다음에 대해 읽어보는 것을 권장합니다. + +- [토큰 표준](/developers/docs/standards/tokens/) +- [ERC-20](/developers/docs/standards/tokens/erc-20/) + +## 본문 {#body} + +ERC-1363은 `transfer`, `transferFrom` 또는 `approve` 이후 ERC-20 토큰이 스마트 계약과 상호 작용할 수 있는 표준 API를 도입합니다. + +이 표준은 토큰을 전송하는 기본 기능을 제공하며, 토큰이 다른 온체인 제3자에 의해 사용될 수 있도록 승인한 다음 수신자 또는 지출자 계약에 대한 콜백을 수행할 수 있도록 합니다. + +ERC-20 콜백을 수락할 수 있는 스마트 계약의 제안된 용도가 많이 있습니다. + +예는 다음과 같습니다. + +- **크라우드세일**: 전송된 토큰이 즉시 보상 할당을 트리거합니다. +- **서비스**: 결제로 한 단계에서 서비스 액세스가 활성화됩니다. +- **인보이스**: 토큰이 자동으로 인보이스를 정산합니다. +- **구독**: 연간 요금을 승인하면 첫 달 결제 내에서 구독이 활성화됩니다. + +이러한 이유로 원래 \"Payable Token\"이라고 명명되었습니다. + +콜백 동작은 유틸리티를 더욱 확장하여 다음과 같은 원활한 상호 작용을 가능하게 합니다. + +- **스테이킹**: 전송된 토큰이 스테이킹 계약에서 자동 잠금을 트리거합니다. +- **투표**: 수신된 토큰이 거버넌스 시스템에 투표를 등록합니다. +- **스왑**: 토큰 승인으로 한 단계에서 스왑 로직이 활성화됩니다. + +ERC-1363 토큰은 전송 또는 승인 수신 후 콜백을 실행해야 하는 모든 경우에 특정 유틸리티에 사용될 수 있습니다. +ERC-1363은 수신자의 토큰 처리 능력을 확인함으로써 스마트 계약에서 토큰 손실이나 토큰 잠김을 방지하는 데에도 유용합니다. + +다른 ERC-20 확장 제안과 달리, ERC-1363은 ERC-20 `transfer` 및 `transferFrom` 메서드를 재정의하지 않고 ERC-20과의 하위 호환성을 유지하면서 구현할 인터페이스 ID를 정의합니다. + +[EIP-1363](https://eips.ethereum.org/EIPS/eip-1363)에서: + +### 메서드 {#methods} + +ERC-1363 표준을 구현하는 스마트 계약은 `ERC1363` 인터페이스의 모든 함수와 `ERC20` 및 `ERC165` 인터페이스를 **반드시** 구현해야 합니다. + +```solidity +pragma solidity ^0.8.0;\n\n/**\n * @title ERC1363\n * @dev 단일 트랜잭션에서 `transfer` 또는 `transferFrom` 후 수신자 계약에서 코드를 실행하거나, `approve` 후 지출자 계약에서 코드를 실행하는 것을 지원하는 ERC-20 토큰의 확장 인터페이스입니다.\n */\ninterface ERC1363 is ERC20, ERC165 {\n /*\n * 참고: 이 인터페이스의 ERC-165 식별자는 0xb0202a11입니다.\n * 0xb0202a11 ===\n * bytes4(keccak256('transferAndCall(address,uint256)')) ^\n * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n * bytes4(keccak256('approveAndCall(address,uint256)')) ^\n * bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n */\n\n /**\n * @dev 호출자의 계정에서 `to`로 `value` 양의 토큰을 이동시킨 다음\n * `to`에서 `ERC1363Receiver::onTransferReceived`를 호출합니다.\n * @param to 토큰이 전송될 주소입니다.\n * @param value 전송될 토큰의 양입니다.\n * @return 예외를 발생시키지 않는 한 작업이 성공했음을 나타내는 불리언 값입니다.\n */\n function transferAndCall(address to, uint256 value) external returns (bool);\n\n /**\n * @dev 호출자의 계정에서 `to`로 `value` 양의 토큰을 이동시킨 다음\n * `to`에서 `ERC1363Receiver::onTransferReceived`를 호출합니다.\n * @param to 토큰이 전송될 주소입니다.\n * @param value 전송될 토큰의 양입니다.\n * @param data 지정된 형식이 없는 추가 데이터로, `to`를 호출할 때 전송됩니다.\n * @return 예외를 발생시키지 않는 한 작업이 성공했음을 나타내는 불리언 값입니다.\n */\n function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n /**\n * @dev 허용량 메커니즘을 사용하여 `from`에서 `to`로 `value` 양의 토큰을 이동시킨 다음\n * `to`에서 `ERC1363Receiver::onTransferReceived`를 호출합니다.\n * @param from 토큰을 보낼 주소입니다.\n * @param to 토큰이 전송될 주소입니다.\n * @param value 전송될 토큰의 양입니다.\n * @return 예외를 발생시키지 않는 한 작업이 성공했음을 나타내는 불리언 값입니다.\n */\n function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n /**\n * @dev 허용량 메커니즘을 사용하여 `from`에서 `to`로 `value` 양의 토큰을 이동시킨 다음\n * `to`에서 `ERC1363Receiver::onTransferReceived`를 호출합니다.\n * @param from 토큰을 보낼 주소입니다.\n * @param to 토큰이 전송될 주소입니다.\n * @param value 전송될 토큰의 양입니다.\n * @param data 지정된 형식이 없는 추가 데이터로, `to`를 호출할 때 전송됩니다.\n * @return 예외를 발생시키지 않는 한 작업이 성공했음을 나타내는 불리언 값입니다.\n */\n function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n /**\n * @dev 호출자의 토큰에 대해 `spender`의 허용량으로 `value` 양의 토큰을 설정한 다음\n * `spender`에서 `ERC1363Spender::onApprovalReceived`를 호출합니다.\n * @param spender 자금을 사용할 주소입니다.\n * @param value 사용될 토큰의 양입니다.\n * @return 예외를 발생시키지 않는 한 작업이 성공했음을 나타내는 불리언 값입니다.\n */\n function approveAndCall(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev 호출자의 토큰에 대해 `spender`의 허용량으로 `value` 양의 토큰을 설정한 다음\n * `spender`에서 `ERC1363Spender::onApprovalReceived`를 호출합니다.\n * @param spender 자금을 사용할 주소입니다.\n * @param value 사용될 토큰의 양입니다.\n * @param data 지정된 형식이 없는 추가 데이터로, `spender`를 호출할 때 전송됩니다.\n * @return 예외를 발생시키지 않는 한 작업이 성공했음을 나타내는 불리언 값입니다.\n */\n function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n\ninterface ERC20 {\n event Transfer(address indexed from, address indexed to, uint256 value);\n event Approval(address indexed owner, address indexed spender, uint256 value);\n function transfer(address to, uint256 value) external returns (bool);\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n function approve(address spender, uint256 value) external returns (bool);\n function totalSupply() external view returns (uint256);\n function balanceOf(address account) external view returns (uint256);\n function allowance(address owner, address spender) external view returns (uint256);\n}\n\ninterface ERC165 {\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n} +``` + +`transferAndCall` 또는 `transferFromAndCall`을 통해 ERC-1363 토큰을 수락하려는 스마트 계약은 `ERC1363Receiver` 인터페이스를 **반드시** 구현해야 합니다. + +```solidity +/**\n * @title ERC1363Receiver\n * @dev ERC-1363 토큰 계약에서 `transferAndCall` 또는 `transferFromAndCall`을 지원하려는 모든 계약을 위한 인터페이스입니다.\n */\ninterface ERC1363Receiver {\n /**\n * @dev `operator`가 `from`에서 `ERC1363::transferAndCall` 또는 `ERC1363::transferFromAndCall`을 통해\n * ERC-1363 토큰을 이 계약으로 전송할 때마다 이 함수가 호출됩니다.\n *\n * 참고: 전송을 수락하려면 이 함수는\n * `bytes4(keccak256(\"onTransferReceived(address,address,uint256,bytes)\"))`\n * (예: 0x88a7ca5c 또는 자체 함수 선택자)를 반환해야 합니다.\n *\n * @param operator `transferAndCall` 또는 `transferFromAndCall` 함수를 호출한 주소입니다.\n * @param from 토큰이 전송된 주소입니다.\n * @param value 전송된 토큰의 양입니다.\n * @param data 지정된 형식이 없는 추가 데이터입니다.\n * @return 예외를 발생시키지 않는 한 전송이 허용되는 경우 `bytes4(keccak256(\"onTransferReceived(address,address,uint256,bytes)\"))`입니다.\n */\n function onTransferReceived(address operator, address from, uint256 value, bytes calldata data) external returns (bytes4);\n} +``` + +`approveAndCall`을 통해 ERC-1363 토큰을 수락하려는 스마트 계약은 `ERC1363Spender` 인터페이스를 **반드시** 구현해야 합니다. + +```solidity +/**\n * @title ERC1363Spender\n * @dev ERC-1363 토큰 계약에서 `approveAndCall`을 지원하려는 모든 계약을 위한 인터페이스입니다.\n */\ninterface ERC1363Spender {\n /**\n * @dev ERC-1363 토큰 `owner`가 `ERC1363::approveAndCall`을 통해 이 계약이\n * 자신의 토큰을 사용하도록 승인할 때마다 이 함수가 호출됩니다.\n *\n * 참고: 승인을 수락하려면 이 함수는\n * `bytes4(keccak256(\"onApprovalReceived(address,uint256,bytes)\"))`\n * (예: 0x7b04a2d0 또는 자체 함수 선택자)를 반환해야 합니다.\n *\n * @param owner `approveAndCall` 함수를 호출하고 이전에 토큰을 소유했던 주소입니다.\n * @param value 사용될 토큰의 양입니다.\n * @param data 지정된 형식이 없는 추가 데이터입니다.\n * @return 예외를 발생시키지 않는 한 승인이 허용되는 경우 `bytes4(keccak256(\"onApprovalReceived(address,uint256,bytes)\"))`입니다.\n */\n function onApprovalReceived(address owner, uint256 value, bytes calldata data) external returns (bytes4);\n} +``` + +## 더 읽어보기 {#further-reading} + +- [ERC-1363: 지불 가능 토큰 표준](https://eips.ethereum.org/EIPS/eip-1363) +- [ERC-1363: GitHub 리포지토리](https://github.com/vittominacori/erc1363-payable-token) diff --git a/public/content/translations/ko/developers/docs/standards/tokens/erc-20/index.md b/public/content/translations/ko/developers/docs/standards/tokens/erc-20/index.md new file mode 100644 index 00000000000..7eef6f2aebd --- /dev/null +++ b/public/content/translations/ko/developers/docs/standards/tokens/erc-20/index.md @@ -0,0 +1,186 @@ +--- +title: "ERC-20 토큰 표준" +description: "상호 운용 가능한 토큰 애플리케이션을 지원하는 이더리움의 대체 가능한 토큰 표준인 ERC-20에 대해 알아보세요." +lang: ko +--- + +## 소개 {#introduction} + +**토큰이란 무엇인가요?** + +이더리움에서 토큰은 거의 모든 것을 표현할 수 있습니다. + +- 온라인 플랫폼의 평판점수 +- 게임 캐릭터의 스킬 +- 회사 주식지분 같은 금융자산 +- 미국달러와 같은 법정통화 +- 1 온스의 금 +- 그 이상 많은것들... + +이더리움의 이러한 강력한 특성은 견고한 표준 위에서 동작해야 하지 않을까요? 그것이 바로 ERC-20의 역할입니다! 이 표준을 통해서 개발자들은 다른 제품 및 서비스와 상호 연계 운용 가능한 토큰 애플리케이션을 구축할 수 있습니다. ERC-20 표준은 [이더](/glossary/#ether)에 추가적인 기능을 제공하는 데에도 사용됩니다. + +**ERC-20은 무엇인가요?** + +ERC-20은 대체가능 토큰의 표준을 제시합니다. 즉, 각 토큰은 다른 토큰과 정확히 동일(유형 및 가치) 하게 만드는 속성을 가지고 있습니다. 예를 들어 ERC-20 토큰은 ETH로 취급되며, 이는 1 토큰이 다른 모든 토큰과 항상 동일함을 의미합니다. + +## 필수 구성 요소 {#prerequisites} + +- [계정](/developers/docs/accounts) +- [스마트 계약](/developers/docs/smart-contracts/) +- [토큰 표준](/developers/docs/standards/tokens/) + +## 본문 {#body} + +2015년 11월 Fabian Vogelsteller가 제안한 ERC-20(Ethereum Request for Comments 20) 은 스마트 계약 내에서 토큰용 API를 구현하는 토큰 표준이다. + +ERC-20에서 제공하는 기능 예시 + +- 서로 다른 계정간에 토큰 전송하기 +- 계정에서 토큰 잔고 확인하기 +- 가용 중인 네트워크 상의 토큰 총 공급량 확인하기 +- 특정 계정의 토큰을 다른 외부 계정에서 사용 가능한 지 여부를 승인하기 + +스마트 계약이 다음과 같은 방법과 이벤트를 실행할 경우 이를 ERC-20 토큰 계약이라고 할 수 있으며, 한번 구축되면 이더리움에서 생성된 토큰들을 추적해야 한다. + +[EIP-20](https://eips.ethereum.org/EIPS/eip-20)에서: + +### 메서드 {#methods} + +```solidity +function name() public view returns (string) +function symbol() public view returns (string) +function decimals() public view returns (uint8) +function totalSupply() public view returns (uint256) +function balanceOf(address _owner) public view returns (uint256 balance) +function transfer(address _to, uint256 _value) public returns (bool success) +function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) +function approve(address _spender, uint256 _value) public returns (bool success) +function allowance(address _owner, address _spender) public view returns (uint256 remaining) +``` + +### 이벤트 {#events} + +```solidity +event Transfer(address indexed _from, address indexed _to, uint256 _value) +event Approval(address indexed _owner, address indexed _spender, uint256 _value) +``` + +### 예시 {#web3py-example} + +우리가 이더리움상의 어느 ERC-20 토큰 계약을 검사하는데 있어서 이 표준이 얼마나 주요하게 그 검사를 간단히 만드는지 살펴보자. +ERC-20 토큰에 대한 인터페이스를 생성하려면 계약 애플리케이션 바이너리 인터페이스(ABI) 가 필요하다. 아래 보이는 것처럼 우리는 잡음을 줄이기 위해 단순화된 ABI를 사용해 예제를 만들것이다. + +#### Web3.py 예시 {#web3py-example} + +먼저, [Web3.py](https://web3py.readthedocs.io/en/stable/quickstart.html#installation) 파이썬 라이브러리를 설치했는지 확인하세요. + +``` +pip install web3 +``` + +```python +from web3 import Web3 + + +w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com")) + +dai_token_addr = "0x6B175474E89094C44Da98b954EedeAC495271d0F" # DAI +weth_token_addr = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" # Wrapped ether (WETH) + +acc_address = "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11" # Uniswap V2: DAI 2 + +# 이것은 ERC-20 토큰 계약의 단순화된 계약 애플리케이션 바이너리 인터페이스(ABI)입니다. +# balanceOf(address), decimals(), symbol() 및 totalSupply() 메서드만 노출합니다. +simplified_abi = [ + { + 'inputs': [{'internalType': 'address', 'name': 'account', 'type': 'address'}], + 'name': 'balanceOf', + 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'decimals', + 'outputs': [{'internalType': 'uint8', 'name': '', 'type': 'uint8'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'symbol', + 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'totalSupply', + 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + } +] + +dai_contract = w3.eth.contract(address=w3.to_checksum_address(dai_token_addr), abi=simplified_abi) +symbol = dai_contract.functions.symbol().call() +decimals = dai_contract.functions.decimals().call() +totalSupply = dai_contract.functions.totalSupply().call() / 10**decimals +addr_balance = dai_contract.functions.balanceOf(acc_address).call() / 10**decimals + +# DAI +print("===== %s =====" % symbol) +print("Total Supply:", totalSupply) +print("Addr Balance:", addr_balance) + +weth_contract = w3.eth.contract(address=w3.to_checksum_address(weth_token_addr), abi=simplified_abi) +symbol = weth_contract.functions.symbol().call() +decimals = weth_contract.functions.decimals().call() +totalSupply = weth_contract.functions.totalSupply().call() / 10**decimals +addr_balance = weth_contract.functions.balanceOf(acc_address).call() / 10**decimals + +# WETH +print("===== %s =====" % symbol) +print("Total Supply:", totalSupply) +print("Addr Balance:", addr_balance) +``` + +## 알려진 문제점 {#erc20-issues} + +### ERC-20 토큰 수신 문제 {#reception-issue} + +**2024년 6월 20일 기준, 이 문제로 인해 최소 83,656,418달러 상당의 ERC-20 토큰이 손실되었습니다. 아래 목록에 명시된 대로 표준 외에 추가적인 제한 사항을 구현하지 않는 한 순수한 ERC-20 구현은 이 문제에 취약하다는 점에 유의하세요.** + +ERC-20 토큰이 ERC-20 토큰을 처리하도록 설계되지 않은 스마트 계약으로 전송되면, 해당 토큰은 영구적으로 손실될 수 있습니다. 이는 수신 계약이 들어오는 토큰을 인식하거나 응답할 수 있는 기능이 없기 때문에 발생하며, ERC-20 표준에는 수신 계약에 들어오는 토큰을 알리는 메커니즘이 없습니다. 이 문제는 다음과 같은 방식으로 발생합니다: + +1. 토큰 전송 메커니즘 + +- ERC-20 토큰은 transfer 또는 transferFrom 함수를 사용하여 전송됩니다. + - 사용자가 이러한 함수를 사용하여 토큰을 계약 주소로 전송할 때, 수신 계약이 토큰을 처리하도록 설계되었는지와 상관없이 토큰은 전송됩니다. + +2. 알림의 부재 + - 수신 계약은 토큰이 전송되었다는 알림이나 콜백을 받지 않습니다. + - 수신 계약에 토큰을 처리할 메커니즘(예: 폴백 함수나 토큰 수신을 관리하는 전용 함수)이 없는 경우, 토큰은 사실상 계약의 주소에 갇히게 됩니다. +3. 내장된 처리 없음 + - ERC-20 표준은 수신 계약이 구현해야 할 필수 기능을 포함하지 않으므로, 많은 계약이 들어오는 토큰을 적절히 관리할 수 없는 상황이 발생합니다. + +**가능한 해결책** + +ERC-20으로 이 문제를 완전히 방지할 수는 없지만, 최종 사용자의 토큰 손실 가능성을 크게 줄일 수 있는 방법들이 있습니다. + +- 가장 흔한 문제는 사용자가 토큰 계약 주소 자체로 토큰을 보내는 경우입니다(예: USDT 토큰 계약 주소로 USDT를 예치하는 경우). `transfer(..)` 함수를 제한하여 이러한 전송 시도를 되돌리는 것을 권장합니다. `transfer(..)` 함수의 구현 내에 `require(_to != address(this));` 확인을 추가하는 것을 고려하세요. +- 일반적으로 `transfer(..)` 함수는 계약에 토큰을 예치하기 위해 설계되지 않았습니다. `approve(..)` & transferFrom(..)`패턴은 대신 ERC-20 토큰을 계약에 예치하는 데 사용됩니다. 전송 함수를 제한하여 이를 통해 어떤 계약에도 토큰을 예치하는 것을 허용하지 않도록 할 수 있지만,`trasnfer(..)` 함수를 사용하여 계약에 토큰을 예치할 수 있다고 가정하는 계약(예: Uniswap 유동성 풀)과의 호환성을 깨뜨릴 수 있습니다. +- 계약이 어떠한 토큰도 받지 않도록 되어 있더라도 ERC-20 토큰이 계약에 들어올 수 있다고 항상 가정하세요. 수신자 측에서 우발적인 예치를 방지하거나 거부할 방법은 없습니다. 우발적으로 예치된 ERC-20 토큰을 추출할 수 있는 함수를 구현하는 것을 권장합니다. +- 대안 토큰 표준 사용을 고려해 보세요. + +이 문제에서 [ERC-223](/developers/docs/standards/tokens/erc-223) 또는 [ERC-1363](/developers/docs/standards/tokens/erc-1363)과 같은 일부 대안 표준이 나왔습니다. + +## 더 읽어보기 {#further-reading} + +- [EIP-20: ERC-20 토큰 표준](https://eips.ethereum.org/EIPS/eip-20) +- [OpenZeppelin - 토큰](https://docs.openzeppelin.com/contracts/3.x/tokens#ERC20) +- [OpenZeppelin - ERC-20 구현](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol) +- [Alchemy - Solidity ERC20 토큰 가이드](https://www.alchemy.com/overviews/erc20-solidity) + +## 기타 대체 가능한 토큰 표준 {#fungible-token-standards} + +- [ERC-223](/developers/docs/standards/tokens/erc-223) +- [ERC-1363](/developers/docs/standards/tokens/erc-1363) +- [ERC-777](/developers/docs/standards/tokens/erc-777) +- [ERC-4626 - 토큰화된 금고](/developers/docs/standards/tokens/erc-4626) diff --git a/public/content/translations/ko/developers/docs/standards/tokens/erc-223/index.md b/public/content/translations/ko/developers/docs/standards/tokens/erc-223/index.md new file mode 100644 index 00000000000..8b6aaed3d95 --- /dev/null +++ b/public/content/translations/ko/developers/docs/standards/tokens/erc-223/index.md @@ -0,0 +1,197 @@ +--- +title: "ERC-223 토큰 표준" +description: "ERC-223 대체 가능 토큰 표준에 대한 개요, 작동 방식 및 ERC-20과의 비교." +lang: ko +--- + +## 소개 {#introduction} + +### ERC-223은 무엇인가요? {#what-is-erc223} + +ERC-223은 ERC-20 표준과 유사한 대체 가능 토큰 표준입니다. 주요 차이점은 ERC-223이 토큰 API뿐만 아니라 발신자에서 수신자로 토큰을 전송하는 로직도 정의한다는 것입니다. 수신자 측에서 토큰 전송을 처리할 수 있는 통신 모델을 도입합니다. + +### ERC-20과의 차이점 {#erc20-differences} + +ERC-223은 ERC-20의 몇 가지 한계를 해결하고 토큰 계약과 토큰을 받을 수 있는 계약 간의 새로운 상호 작용 방법을 도입합니다. ERC-20에서는 불가능하지만 ERC-223에서는 가능한 몇 가지 사항이 있습니다. + +- 수신자 측에서의 토큰 전송 처리: 수신자는 ERC-223 토큰이 입금되고 있음을 감지할 수 있습니다. +- 부적절하게 전송된 토큰 거부: 사용자가 토큰을 받지 않아야 하는 계약에 ERC-223 토큰을 보내는 경우, 해당 계약은 트랜잭션을 거부하여 토큰 손실을 방지할 수 있습니다. +- 전송 시 메타데이터: ERC-223 토큰은 메타데이터를 포함할 수 있어 토큰 트랜잭션에 임의의 정보를 첨부할 수 있습니다. + +## 필수 구성 요소 {#prerequisites} + +- [계정](/developers/docs/accounts) +- [스마트 계약](/developers/docs/smart-contracts/) +- [토큰 표준](/developers/docs/standards/tokens/) +- [ERC-20](/developers/docs/standards/tokens/erc-20/) + +## 본문 {#body} + +ERC-223은 스마트 계약 내의 토큰을 위한 API를 구현하는 토큰 표준입니다. 또한 ERC-223 토큰을 받도록 되어 있는 계약을 위한 API를 선언합니다. ERC-223 수신자 API를 지원하지 않는 계약은 ERC-223 토큰을 받을 수 없어 사용자 실수를 방지합니다. + +스마트 계약이 다음 메서드와 이벤트를 구현하면 ERC-223 호환 토큰 계약이라고 할 수 있습니다. 배포되면 이더리움에서 생성된 토큰을 추적할 책임이 있습니다. + +계약이 이러한 함수만 가질 의무는 없으며, 개발자는 다른 토큰 표준의 다른 기능을 이 계약에 추가할 수 있습니다. 예를 들어, `approve` 및 `transferFrom` 함수는 ERC-223 표준의 일부는 아니지만 필요한 경우 구현할 수 있습니다. + +[EIP-223](https://eips.ethereum.org/EIPS/eip-223)에서: + +### 메서드 {#methods} + +ERC-223 토큰은 다음 메서드를 구현해야 합니다. + +```solidity +function name() public view returns (string) +function symbol() public view returns (string) +function decimals() public view returns (uint8) +function totalSupply() public view returns (uint256) +function balanceOf(address _owner) public view returns (uint256 balance) +function transfer(address _to, uint256 _value) public returns (bool success) +function transfer(address _to, uint256 _value, bytes calldata _data) public returns (bool success) +``` + +ERC-223 토큰을 받도록 되어 있는 계약은 다음 메서드를 구현해야 합니다. + +```solidity +function tokenReceived(address _from, uint _value, bytes calldata _data) +``` + +`tokenReceived(..)` 함수를 구현하지 않는 계약으로 ERC-223 토큰을 보내면 전송이 실패해야 하며, 토큰이 발신자의 잔액에서 이동해서는 안 됩니다. + +### 이벤트 {#events} + +```solidity +event Transfer(address indexed _from, address indexed _to, uint256 _value, bytes calldata _data) +``` + +### 예시 {#examples} + +ERC-223 토큰의 API는 ERC-20과 유사하므로 UI 개발 관점에서 차이가 없습니다. 여기서 유일한 예외는 ERC-223 토큰에 `approve` + `transferFrom` 함수가 없을 수 있다는 것입니다. 이 함수들은 이 표준에서 선택 사항이기 때문입니다. + +#### 솔리디티 예제 {#solidity-example} + +다음 예제는 기본 ERC-223 토큰 계약이 어떻게 작동하는지 보여줍니다. + +```solidity +pragma solidity ^0.8.19; +abstract contract IERC223Recipient { + function tokenReceived(address _from, uint _value, bytes memory _data) public virtual; +} +contract VeryBasicERC223Token { + event Transfer(address indexed from, address indexed to, uint value, bytes data); + string private _name; + string private _symbol; + uint8 private _decimals; + uint256 private _totalSupply; + mapping(address => uint256) private balances; + function name() public view returns (string memory) { return _name; } + function symbol() public view returns (string memory) {return _symbol; } + function decimals() public view returns (uint8) { return _decimals; } + function totalSupply() public view returns (uint256) { return _totalSupply; } + function balanceOf(address _owner) public view returns (uint256) { return balances[_owner]; } + function isContract(address account) internal view returns (bool) { + uint256 size; + assembly { size := extcodesize(account) } + return size > 0; + } + function transfer(address _to, uint _value, bytes calldata _data) public returns (bool success){ + balances[msg.sender] = balances[msg.sender] - _value; + balances[_to] = balances[_to] + _value; + if(isContract(_to)) { + IERC223Recipient(_to).tokenReceived(msg.sender, _value, _data); + } + emit Transfer(msg.sender, _to, _value, _data); + return true; + } + function transfer(address _to, uint _value) public returns (bool success){ + bytes memory _empty = hex"00000000"; + balances[msg.sender] = balances[msg.sender] - _value; + balances[_to] = balances[_to] + _value; + if(isContract(_to)) { + IERC223Recipient(_to).tokenReceived(msg.sender, _value, _empty); + } + emit Transfer(msg.sender, _to, _value, _empty); + return true; + } +} +``` + +이제 tokenA가 ERC-223 토큰이라고 가정하고, `tokenA`의 입금을 수락하는 다른 계약을 원합니다. 계약은 tokenA만 수락하고 다른 모든 토큰은 거부해야 합니다. 계약이 tokenA를 받으면 `Deposit()` 이벤트를 발생시키고 내부 `deposits` 변수의 값을 증가시켜야 합니다. + +코드는 다음과 같습니다. + +```solidity +contract RecipientContract is IERC223Recipient { + event Deposit(address whoSentTheTokens); + uint256 deposits = 0; + address tokenA; // 우리가 수락하려는 유일한 토큰입니다. + function tokenReceived(address _from, uint _value, bytes memory _data) public override + { + // 이 함수 내에서 다음을 이해하는 것이 중요합니다 + // msg.sender는 수신 중인 토큰의 주소이며, + // msg.value는 대부분의 경우 토큰 계약이 이더를 소유하거나 전송하지 않으므로 항상 0입니다, + // _from은 토큰 전송의 발신자이고, + // _value는 입금된 토큰의 양입니다. + require(msg.sender == tokenA); + deposits += _value; + emit Deposit(_from); + } +} +``` + +## 자주 묻는 질문 {#faq} + +### 계약에 tokenB를 보내면 어떻게 될까요? {#sending-tokens} + +트랜잭션이 실패하고 토큰 전송이 발생하지 않습니다. 토큰은 발신자의 주소로 반환됩니다. + +### 이 계약에 어떻게 입금할 수 있나요? {#contract-deposits} + +ERC-223 토큰의 `transfer(address,uint256)` 또는 `transfer(address,uint256,bytes)` 함수를 호출하여 `RecipientContract`의 주소를 지정합니다. + +### 이 계약에 ERC-20 토큰을 전송하면 어떻게 될까요? {#erc-20-transfers} + +`RecipientContract`에 ERC-20 토큰을 보내면 토큰은 전송되지만, 전송이 인식되지 않습니다(`Deposit()` 이벤트가 발생하지 않으며, deposits 값도 변경되지 않음). 원치 않는 ERC-20 입금은 필터링하거나 방지할 수 없습니다. + +### 토큰 입금이 완료된 후 일부 함수를 실행하려면 어떻게 해야 할까요? {#function-execution} + +여러 가지 방법이 있습니다. 이 예제에서는 ERC-223 전송을 이더 전송과 동일하게 만드는 방법을 따릅니다. + +```solidity +contract RecipientContract is IERC223Recipient { + event Foo(); + event Bar(uint256 someNumber); + address tokenA; // 수락하려는 유일한 토큰입니다. + function tokenReceived(address _from, uint _value, bytes memory _data) public override + { + require(msg.sender == tokenA); + address(this).call(_data); // 들어오는 트랜잭션을 처리하고 후속 함수 호출을 수행합니다. + } + function foo() public + { + emit Foo(); + } + function bar(uint256 _someNumber) public + { + emit Bar(_someNumber); + } +} +``` + +`RecipientContract`가 ERC-223 토큰을 받으면, 계약은 이더리움 트랜잭션이 트랜잭션 `data`로 함수 호출을 인코딩하는 방식과 동일하게 토큰 트랜잭션의 `_data` 매개변수로 인코딩된 함수를 실행합니다. 자세한 내용은 [데이터 필드](/developers/docs/transactions/#the-data-field)를 읽어보세요. + +위 예에서 ERC-223 토큰은 `transfer(address,uin256,bytes calldata _data)` 함수를 사용하여 `RecipientContract`의 주소로 전송되어야 합니다. 데이터 매개변수가 `0xc2985578`(`foo()` 함수의 서명)인 경우, 토큰 입금이 수신된 후 foo() 함수가 호출되고 Foo() 이벤트가 발생합니다. + +매개변수는 토큰 전송의 `data`에도 인코딩될 수 있습니다. 예를 들어, `_someNumber`에 12345 값을 사용하여 bar() 함수를 호출할 수 있습니다. 이 경우 `data`는 `0x0423a13200000000000000000000000000000000000000000000000000000000000004d2`여야 합니다. 여기서 `0x0423a132`는 `bar(uint256)` 함수의 서명이고 `00000000000000000000000000000000000000000000000000000000000004d2`는 uint256으로서의 12345입니다. + +## 한계 {#limitations} + +ERC-223이 ERC-20 표준에서 발견된 여러 문제를 해결하지만, 자체적인 한계도 있습니다. + +- 채택 및 호환성: ERC-223은 아직 널리 채택되지 않아 기존 도구 및 플랫폼과의 호환성이 제한될 수 있습니다. +- 하위 호환성: ERC-223은 ERC-20과 하위 호환되지 않습니다. 즉, 기존 ERC-20 계약 및 도구는 수정 없이는 ERC-223 토큰과 작동하지 않습니다. +- 가스 비용: ERC-223 전송의 추가 확인 및 기능으로 인해 ERC-20 트랜잭션에 비해 가스 비용이 더 많이 발생할 수 있습니다. + +## 더 읽어보기 {#further-reading} + +- [EIP-223: ERC-223 토큰 표준](https://eips.ethereum.org/EIPS/eip-223) +- [초기 ERC-223 제안](https://github.com/ethereum/eips/issues/223) diff --git a/public/content/translations/ko/developers/docs/standards/tokens/erc-4626/index.md b/public/content/translations/ko/developers/docs/standards/tokens/erc-4626/index.md new file mode 100644 index 00000000000..c1945e9b37c --- /dev/null +++ b/public/content/translations/ko/developers/docs/standards/tokens/erc-4626/index.md @@ -0,0 +1,227 @@ +--- +title: "ERC-4626 토큰화된 볼트 표준" +description: "수익을 내는 볼트를 위한 표준입니다." +lang: ko +--- + +## 소개 {#introduction} + +ERC-4626은 수익을 내는 볼트의 기술적 매개변수를 최적화하고 통합하기 위한 표준입니다. 단일 기본 ERC-20 토큰의 지분을 나타내는 토큰화된 수익 볼트를 위한 표준 API를 제공합니다. ERC-4626은 또한 ERC-20을 활용하는 토큰화된 볼트를 위한 선택적 확장의 개요를 설명하며, 토큰 예치, 인출 및 잔액 조회를 위한 기본 기능을 제공합니다. + +**수익을 내는 볼트에서 ERC-4626의 역할** + +대출 시장, 애그리게이터 및 내재적으로 이자가 발생하는 토큰은 다양한 전략을 실행하여 사용자가 자신의 암호화폐 토큰에 대한 최고의 수익률을 찾을 수 있도록 돕습니다. 이러한 전략은 약간의 변형을 거쳐 수행되며, 이로 인해 오류가 발생하기 쉽거나 개발 리소스가 낭비될 수 있습니다. + +수익을 내는 볼트에서 ERC-4626은 보다 일관되고 강력한 구현 패턴을 만들어 개발자의 전문적인 노력을 거의 들이지 않고도 통합 노력을 줄이고 다양한 애플리케이션에서 수익에 대한 액세스를 열어줄 것입니다. + +ERC-4626 토큰은 [EIP-4626](https://eips.ethereum.org/EIPS/eip-4626)에 완전히 설명되어 있습니다. + +**비동기 볼트 확장(ERC-7540)** + +ERC-4626은 한도까지의 원자적 예치 및 상환에 최적화되어 있습니다. 한도에 도달하면 새로운 예치나 상환을 제출할 수 없습니다. 이러한 제한은 볼트와 인터페이스하기 위한 전제 조건으로 비동기 작업 또는 지연이 있는 모든 스마트 계약 시스템(예: 실물 자산 프로토콜, 담보 부족 대출 프로토콜, 교차 체인 대출 프로토콜, 유동 스테이킹 토큰 또는 보험 안전 모듈)에서는 잘 작동하지 않습니다. + +ERC-7540은 비동기 사용 사례를 위해 ERC-4626 볼트의 유용성을 확장합니다. 기존 볼트 인터페이스(`deposit`/`withdraw`/`mint`/`redeem`)는 비동기 요청을 처리하기 위해 완전히 활용됩니다. + +ERC-7540 확장은 [ERC-7540](https://eips.ethereum.org/EIPS/eip-7540)에 완전히 설명되어 있습니다. + +**다중 자산 볼트 확장(ERC-7575)** + +ERC-4626에서 지원하지 않는 한 가지 누락된 사용 사례는 유동성 공급자(LP) 토큰과 같이 여러 자산 또는 진입점을 가진 볼트입니다. 이들은 일반적으로 ERC-4626 자체가 ERC-20이어야 한다는 요구사항으로 인해 다루기 어렵거나 규정을 준수하지 않습니다. + +ERC-7575는 ERC-4626 구현에서 ERC-20 토큰 구현을 외부화하여 다중 자산을 가진 볼트에 대한 지원을 추가합니다. + +ERC-7575 확장은 [ERC-7575](https://eips.ethereum.org/EIPS/eip-7575)에 완전히 설명되어 있습니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하려면 먼저 [토큰 표준](/developers/docs/standards/tokens/) 및 [ERC-20](/developers/docs/standards/tokens/erc-20/)에 대해 읽어보시는 것을 추천합니다. + +## ERC-4626 기능 및 특징: {#body} + +### 메서드 {#methods} + +#### 자산 {#asset} + +```solidity +function asset() public view returns (address assetTokenAddress) +``` + +이 함수는 회계, 예치, 인출을 위해 볼트에 사용되는 기본 토큰의 주소를 반환합니다. + +#### 총자산 {#totalassets} + +```solidity +function totalAssets() public view returns (uint256) +``` + +이 함수는 볼트가 보유한 기본 자산의 총액을 반환합니다. + +#### 지분으로 전환 {#convertoshares} + +```solidity +function convertToShares(uint256 assets) public view returns (uint256 shares) +``` + +이 함수는 제공된 `assets`의 양에 대해 볼트가 교환할 `shares`의 양을 반환합니다. + +#### 자산으로 전환 {#convertoassets} + +```solidity +function convertToAssets(uint256 shares) public view returns (uint256 assets) +``` + +이 함수는 제공된 `shares`의 양에 대해 볼트가 교환할 `assets`의 양을 반환합니다. + +#### 최대 예치 {#maxdeposit} + +```solidity +function maxDeposit(address receiver) public view returns (uint256 maxAssets) +``` + +이 함수는 단일 [`deposit`](#deposit) 호출에서 예치할 수 있는 기본 자산의 최대 금액을 반환하며, 지분은 `receiver`를 위해 발행됩니다. + +#### 예치 미리보기 {#previewdeposit} + +```solidity +function previewDeposit(uint256 assets) public view returns (uint256 shares) +``` + +이 함수를 통해 사용자는 현재 블록에서 자신의 예치가 미치는 영향을 시뮬레이션할 수 있습니다. + +#### 예치 {#deposit} + +```solidity +function deposit(uint256 assets, address receiver) public returns (uint256 shares) +``` + +이 함수는 기본 토큰의 `assets`를 볼트에 예치하고 `shares`의 소유권을 `receiver`에게 부여합니다. + +#### 최대 발행 {#maxmint} + +```solidity +function maxMint(address receiver) public view returns (uint256 maxShares) +``` + +이 함수는 단일 [`mint`](#mint) 호출에서 발행할 수 있는 최대 지분 금액을 반환하며, 지분은 `receiver`를 위해 발행됩니다. + +#### 발행 미리보기 {#previewmint} + +```solidity +function previewMint(uint256 shares) public view returns (uint256 assets) +``` + +이 함수를 통해 사용자는 현재 블록에서 자신의 발행이 미치는 영향을 시뮬레이션할 수 있습니다. + +#### 발행 {#mint} + +```solidity +function mint(uint256 shares, address receiver) public returns (uint256 assets) +``` + +이 함수는 기본 토큰의 `assets`를 예치하여 `receiver`에게 정확히 `shares`만큼의 볼트 지분을 발행합니다. + +#### 최대 인출 {#maxwithdraw} + +```solidity +function maxWithdraw(address owner) public view returns (uint256 maxAssets) +``` + +이 함수는 단일 [`withdraw`](#withdraw) 호출로 `owner`의 잔액에서 인출할 수 있는 기본 자산의 최대 금액을 반환합니다. + +#### 인출 미리보기 {#previewwithdraw} + +```solidity +function previewWithdraw(uint256 assets) public view returns (uint256 shares) +``` + +이 함수를 통해 사용자는 현재 블록에서 자신의 인출이 미치는 영향을 시뮬레이션할 수 있습니다. + +#### 인출 {#withdraw} + +```solidity +function withdraw(uint256 assets, address receiver, address owner) public returns (uint256 shares) +``` + +이 함수는 `owner`로부터 `shares`를 소각하고 볼트에서 `receiver`에게 정확히 `assets` 토큰을 보냅니다. + +#### 최대 상환 {#maxredeem} + +```solidity +function maxRedeem(address owner) public view returns (uint256 maxShares) +``` + +이 함수는 [`redeem`](#redeem) 호출을 통해 `owner`의 잔액에서 상환할 수 있는 최대 지분 금액을 반환합니다. + +#### 상환 미리보기 {#previewredeem} + +```solidity +function previewRedeem(uint256 shares) public view returns (uint256 assets) +``` + +이 함수를 통해 사용자는 현재 블록에서 자신의 상환이 미치는 영향을 시뮬레이션할 수 있습니다. + +#### 상환 {#redeem} + +```solidity +function redeem(uint256 shares, address receiver, address owner) public returns (uint256 assets) +``` + +이 함수는 `owner`로부터 특정 수량의 `shares`를 상환하고 볼트에서 `receiver`에게 기본 토큰의 `assets`를 보냅니다. + +#### 총 공급량 {#totalsupply} + +```solidity +function totalSupply() public view returns (uint256) +``` + +유통 중인 상환되지 않은 볼트 지분의 총 수량을 반환합니다. + +#### 잔액 {#balanceof} + +```solidity +function balanceOf(address owner) public view returns (uint256) +``` + +`owner`가 현재 보유하고 있는 볼트 지분의 총량을 반환합니다. + +### 인터페이스 맵 {#mapOfTheInterface} + +![ERC-4626 인터페이스 맵](./map-of-erc-4626.png) + +### 이벤트 {#events} + +#### 예치 이벤트 + +[`mint`](#mint) 및 [`deposit`](#deposit) 메서드를 통해 토큰이 볼트에 예치될 때 **반드시** 방출되어야 합니다. + +```solidity +event Deposit( + address indexed sender, + address indexed owner, + uint256 assets, + uint256 shares +) +``` + +여기서 `sender`는 `assets`를 `shares`로 교환하고 해당 `shares`를 `owner`에게 전송한 사용자입니다. + +#### 인출 이벤트 + +[`redeem`](#redeem) 또는 [`withdraw`](#withdraw) 메서드에서 예금자가 볼트에서 지분을 인출할 때 **반드시** 방출되어야 합니다. + +```solidity +event Withdraw( + address indexed sender, + address indexed receiver, + address indexed owner, + uint256 assets, + uint256 shares +) +``` + +여기서 `sender`는 인출을 트리거하고 `owner`가 소유한 `shares`를 `assets`로 교환한 사용자입니다. `receiver`는 인출된 `assets`를 받은 사용자입니다. + +## 더 읽어보기 {#further-reading} + +- [EIP-4626: 토큰화된 볼트 표준](https://eips.ethereum.org/EIPS/eip-4626) +- [ERC-4626: GitHub 리포지토리](https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC4626.sol) diff --git a/public/content/translations/ko/developers/docs/standards/tokens/erc-721/index.md b/public/content/translations/ko/developers/docs/standards/tokens/erc-721/index.md new file mode 100644 index 00000000000..2f701439210 --- /dev/null +++ b/public/content/translations/ko/developers/docs/standards/tokens/erc-721/index.md @@ -0,0 +1,248 @@ +--- +title: "ERC-721 대체 불가능 토큰 표준" +description: "이더리움에서 고유한 디지털 자산을 나타내는 대체 불가 토큰(NFT)의 표준인 ERC-721에 대해 알아보세요." +lang: ko +--- + +## 소개 {#introduction} + +**대체 불가능 토큰이란 무엇인가요?** + +대체 불가능 토큰(NFT)은 무언가나 누군가를 독특한 방식으로 식별하는 데 사용됩니다. 이 유형의 토큰은 수집품, 접근 키, 복권, 콘서트 및 스포츠 경기의 번호 매겨진 좌석 등을 제공하는 플랫폼에서 사용하기에 적합합니다. 이 특별한 유형의 토큰은 놀라운 가능성을 가지고 있어 ERC-721이라는 적절한 표준이 필요합니다! + +**ERC-721은 무엇인가요?** + +ERC-721은 NFT 표준을 도입하였으며, 즉, 이 유형의 토큰은 고유하며 같은 스마트 계약의 다른 토큰과는 나이나 희귀성 또는 시각적인 요소 등으로 인해 다른 가치를 가질 수 있습니다. +잠깐, 시각적인 요소라고요? + +네! 모든 NFT에는 `tokenId`라는 `uint256` 변수가 있으므로 모든 ERC-721 계약의 경우 +`contract address, uint256 tokenId` 쌍은 전역적으로 고유해야 합니다. 즉, 탈중앙화앱은 `tokenId`를 입력으로 사용하고 좀비, 무기, 기술 또는 놀라운 고양이 같은 멋진 것을 이미지로 출력하는 "변환기"를 가질 수 있습니다! + +## 필수 구성 요소 {#prerequisites} + +- [계정](/developers/docs/accounts/) +- [스마트 계약](/developers/docs/smart-contracts/) +- [토큰 표준](/developers/docs/standards/tokens/) + +## 본문 {#body} + +ERC-721(Ethereum Request for Comments 721)은 2018년 1월 William Entriken, Dieter Shirley, Jacob Evans, Nastassia Sachs가 제안한 대체 불가능 토큰 표준으로, 스마트 계약 내에서 토큰을 위한 API를 구현합니다. + +이 표준은 한 계정에서 다른 계정으로 토큰을 전송하고, 계정의 현재 토큰 잔액을 확인하고, 특정 토큰의 소유자를 확인하며 네트워크에서 사용 가능한 토큰의 총 공급량을 가져오는 기능을 제공합니다. +또한, 다른 계정이 특정 계정에서 일정량의 토큰을 이동하도록 승인하는 기능도 포함되어 있습니다. + +스마트 계약이 다음 메서드와 이벤트를 구현하면 ERC-721 대체 불가능 토큰 계약이라 부를 수 있으며, 배포되면 이더리움 상에서 생성된 토큰을 추적하는 책임을 갖게 됩니다. + +[EIP-721](https://eips.ethereum.org/EIPS/eip-721)에서 발췌: + +### 메서드 {#methods} + +```solidity + function balanceOf(address _owner) external view returns (uint256); + function ownerOf(uint256 _tokenId) external view returns (address); + function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable; + function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; + function transferFrom(address _from, address _to, uint256 _tokenId) external payable; + function approve(address _approved, uint256 _tokenId) external payable; + function setApprovalForAll(address _operator, bool _approved) external; + function getApproved(uint256 _tokenId) external view returns (address); + function isApprovedForAll(address _owner, address _operator) external view returns (bool); +``` + +### 이벤트 {#events} + +```solidity + event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); + event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); + event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); +``` + +### 예시 {#web3py-example} + +표준이 이더리움의 모든 ERC-721 토큰 계약을 간단하게 검사하는 데 얼마나 중요한지 살펴보겠습니다. +모든 ERC-721 토큰에 대한 인터페이스를 생성하려면 계약 애플리케이션 바이너리 인터페이스(ABI)만 있으면 됩니다. 아래 보이는 것처럼 우리는 잡음을 줄이기 위해 단순화된 ABI를 사용해 예제를 만들것이다. + +#### Web3.py 예시 {#web3py-example} + +먼저, [Web3.py](https://web3py.readthedocs.io/en/stable/quickstart.html#installation) 파이썬 라이브러리를 설치했는지 확인하세요. + +``` +pip install web3 +``` + +```python +from web3 import Web3 +from web3._utils.events import get_event_data + + +w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com")) + +ck_token_addr = "0x06012c8cf97BEaD5deAe237070F9587f8E7A266d" # 크립토키티 계약 + +acc_address = "0xb1690C08E213a35Ed9bAb7B318DE14420FB57d8C" # 크립토키티 판매 경매 + +# 이것은 ERC-721 NFT 계약의 단순화된 계약 애플리케이션 바이너리 인터페이스(ABI)입니다. +# balanceOf(address), name(), ownerOf(tokenId), symbol(), totalSupply() 메서드만 노출합니다. +simplified_abi = [ + { + 'inputs': [{'internalType': 'address', 'name': 'owner', 'type': 'address'}], + 'name': 'balanceOf', + 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}], + 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'name', + 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [{'internalType': 'uint256', 'name': 'tokenId', 'type': 'uint256'}], + 'name': 'ownerOf', + 'outputs': [{'internalType': 'address', 'name': '', 'type': 'address'}], + 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'symbol', + 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'totalSupply', + 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, +] + +ck_extra_abi = [ + { + 'inputs': [], + 'name': 'pregnantKitties', + 'outputs': [{'name': '', 'type': 'uint256'}], + 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [{'name': '_kittyId', 'type': 'uint256'}], + 'name': 'isPregnant', + 'outputs': [{'name': '', 'type': 'bool'}], + 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True + } +] + +ck_contract = w3.eth.contract(address=w3.to_checksum_address(ck_token_addr), abi=simplified_abi+ck_extra_abi) +name = ck_contract.functions.name().call() +symbol = ck_contract.functions.symbol().call() +kitties_auctions = ck_contract.functions.balanceOf(acc_address).call() +print(f"{name} [{symbol}] 경매 중인 NFT: {kitties_auctions}") + +pregnant_kitties = ck_contract.functions.pregnantKitties().call() +print(f"{name} [{symbol}] 임신 중인 NFT: {pregnant_kitties}") + +# 전송 이벤트 ABI를 사용하여 전송된 키티에 대한 정보 얻기 +tx_event_abi = { + 'anonymous': False, + 'inputs': [ + {'indexed': False, 'name': 'from', 'type': 'address'}, + {'indexed': False, 'name': 'to', 'type': 'address'}, + {'indexed': False, 'name': 'tokenId', 'type': 'uint256'}], + 'name': 'Transfer', + 'type': 'event' +} + +# 로그를 필터링하려면 이벤트의 서명이 필요합니다 +event_signature = w3.keccak(text="Transfer(address,address,uint256)").hex() + +logs = w3.eth.get_logs({ + "fromBlock": w3.eth.block_number - 120, + "address": w3.to_checksum_address(ck_token_addr), + "topics": [event_signature] +}) + +# 참고: +# - 전송 이벤트가 반환되지 않으면 블록 수를 120개 이상으로 늘립니다. +# - 전송 이벤트를 찾지 못한 경우 다음에서 tokenId를 얻을 수도 있습니다. +# https://etherscan.io/address/0x06012c8cf97BEaD5deAe237070F9587f8E7A266d#events +# 이벤트 로그를 확장하고 "tokenId" 인수를 복사하려면 클릭하십시오. +recent_tx = [get_event_data(w3.codec, tx_event_abi, log)["args"] for log in logs] + +if recent_tx: + kitty_id = recent_tx[0]['tokenId'] # 위 링크에서 "tokenId"를 여기에 붙여넣습니다. + is_pregnant = ck_contract.functions.isPregnant(kitty_id).call() + print(f"{name} [{symbol}] NFT {kitty_id} 임신 여부: {is_pregnant}") +``` + +CryptoKitties 계약은 표준 이벤트 외에도 몇 가지 흥미로운 이벤트가 있습니다. + +그중 `Pregnant`와 `Birth` 두 가지를 확인해 보겠습니다. + +```python +# Pregnant 및 Birth 이벤트 ABI를 사용하여 새로운 키티에 대한 정보 얻기 +ck_extra_events_abi = [ + { + 'anonymous': False, + 'inputs': [ + {'indexed': False, 'name': 'owner', 'type': 'address'}, + {'indexed': False, 'name': 'matronId', 'type': 'uint256'}, + {'indexed': False, 'name': 'sireId', 'type': 'uint256'}, + {'indexed': False, 'name': 'cooldownEndBlock', 'type': 'uint256'}], + 'name': 'Pregnant', + 'type': 'event' + }, + { + 'anonymous': False, + 'inputs': [ + {'indexed': False, 'name': 'owner', 'type': 'address'}, + {'indexed': False, 'name': 'kittyId', 'type': 'uint256'}, + {'indexed': False, 'name': 'matronId', 'type': 'uint256'}, + {'indexed': False, 'name': 'sireId', 'type': 'uint256'}, + {'indexed': False, 'name': 'genes', 'type': 'uint256'}], + 'name': 'Birth', + 'type': 'event' + }] + +# 로그를 필터링하려면 이벤트의 서명이 필요합니다 +ck_event_signatures = [ + w3.keccak(text="Pregnant(address,uint256,uint256,uint256)").hex(), + w3.keccak(text="Birth(address,uint256,uint256,uint256,uint256)").hex(), +] + +# 다음은 Pregnant 이벤트입니다: +# - https://etherscan.io/tx/0xc97eb514a41004acc447ac9d0d6a27ea6da305ac8b877dff37e49db42e1f8cef#eventlog +pregnant_logs = w3.eth.get_logs({ + "fromBlock": w3.eth.block_number - 120, + "address": w3.to_checksum_address(ck_token_addr), + "topics": [ck_event_signatures[0]] +}) + +recent_pregnants = [get_event_data(w3.codec, ck_extra_events_abi[0], log)["args"] for log in pregnant_logs] + +# 다음은 Birth 이벤트입니다: +# - https://etherscan.io/tx/0x3978028e08a25bb4c44f7877eb3573b9644309c044bf087e335397f16356340a +birth_logs = w3.eth.get_logs({ + "fromBlock": w3.eth.block_number - 120, + "address": w3.to_checksum_address(ck_token_addr), + "topics": [ck_event_signatures[1]] +}) + +recent_births = [get_event_data(w3.codec, ck_extra_events_abi[1], log)["args"] for log in birth_logs] +``` + +## 인기 있는 NFT {#popular-nfts} + +- [Etherscan NFT 추적기](https://etherscan.io/nft-top-contracts)는 전송량을 기준으로 이더리움의 상위 NFT를 나열합니다. +- [CryptoKitties](https://www.cryptokitties.co/)는 우리가 CryptoKitties라고 부르는 번식 가능하고 수집 가능하며 아주 사랑스러운 생물을 중심으로 하는 게임입니다. +- [Sorare](https://sorare.com/)는 한정판 수집품을 수집하고, 팀을 관리하며 상품을 획득하기 위해 경쟁하는 글로벌 판타지 축구 게임입니다. +- [이더리움 이름 서비스(ENS)](https://ens.domains/)는 간단하고 사람이 읽을 수 있는 이름을 사용하여 블록체인 온체인과 오프체인 리소스의 주소를 지정하는 안전하고 분산된 방법을 제공합니다. +- [POAP](https://poap.xyz)는 이벤트에 참석하거나 특정 작업을 완료하는 사람들에게 무료 NFT를 제공합니다. POAP는 무료로 생성 및 배포할 수 있습니다. +- [Unstoppable Domains](https://unstoppabledomains.com/)는 샌프란시스코에 본사를 둔 블록체인 도메인 구축 회사입니다. 블록체인 도메인은 암호화폐 주소를 사람이 읽을 수 있는 이름으로 대체하며, 검열 저항성 웹사이트를 활성화하는 데 사용할 수 있습니다. +- [Gods Unchained Cards](https://godsunchained.com/)는 NFT를 사용하여 게임 내 자산에 대한 실제 소유권을 부여하는 이더리움 블록체인 기반의 TCG입니다. +- [Bored Ape Yacht Club](https://boredapeyachtclub.com)은 10,000개의 고유한 NFT 컬렉션으로, 증명할 수 있는 희귀한 예술 작품일 뿐만 아니라 클럽의 멤버십 토큰 역할을 하며, 커뮤니티의 노력의 결과로 시간이 지남에 따라 증가하는 회원 특전과 혜택을 제공합니다. + +## 더 읽어보기 {#further-reading} + +- [EIP-721: ERC-721 대체 불가 토큰 표준](https://eips.ethereum.org/EIPS/eip-721) +- [OpenZeppelin - ERC-721 문서](https://docs.openzeppelin.com/contracts/3.x/erc721) +- [OpenZeppelin - ERC-721 구현](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol) +- [Alchemy NFT API](https://www.alchemy.com/docs/reference/nft-api-quickstart) diff --git a/public/content/translations/ko/developers/docs/standards/tokens/erc-777/index.md b/public/content/translations/ko/developers/docs/standards/tokens/erc-777/index.md new file mode 100644 index 00000000000..4c898125d7a --- /dev/null +++ b/public/content/translations/ko/developers/docs/standards/tokens/erc-777/index.md @@ -0,0 +1,45 @@ +--- +title: "ERC-777 토큰 표준" +description: "훅(hook)을 통해 개선된 대체 가능한 토큰 표준인 ERC-777에 대해 알아보세요. 단, 보안을 위해 ERC-20 사용을 권장합니다." +lang: ko +--- + +## 경고 {#warning} + +**ERC-777은 [다양한 형태의 공격에 취약](https://github.com/OpenZeppelin/openzeppelin-contracts/issues/2620)하기 때문에 제대로 구현하기가 어렵습니다. 대신 [ERC-20](/developers/docs/standards/tokens/erc-20/)을 사용하는 것이 좋습니다.** 이 페이지는 역사적 기록물로 남아 있습니다. + +## 소개? {#introduction} + +ERC-777은 기존의 [ERC-20](/developers/docs/standards/tokens/erc-20/) 표준을 개선한 대체 가능한 토큰 표준입니다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해하려면 먼저 [ERC-20](/developers/docs/standards/tokens/erc-20/)에 대해 읽어보는 것을 권장합니다. + +## ERC-777은 ERC-20에 비해 어떤 개선점을 제안하나요? {#-erc-777-vs-erc-20} + +ERC-777은 ERC-20에 비해 다음과 같은 개선점을 제공합니다. + +### 훅 {#hooks} + +훅은 스마트 계약의 코드에 기술된 함수입니다. 훅은 계약을 통해 토큰을 보내거나 받을 때 호출됩니다. 이를 통해 스마트 계약은 수신 또는 발신 토큰에 반응할 수 있습니다. + +훅은 [ERC-1820](https://eips.ethereum.org/EIPS/eip-1820) 표준을 사용하여 등록되고 발견됩니다. + +#### 훅의 장점은 무엇인가요? {#why-are-hooks-great} + +1. 이를 위해 이중 호출(`approve`/`transferFrom`)이 필요한 [ERC-20](https://eips.ethereum.org/EIPS/eip-20)과 달리 훅은 단일 트랜잭션으로 계약에 토큰을 보내고 계약에 알림을 보낼 수 있습니다. +2. 훅을 등록하지 않은 계약은 ERC-777과 호환되지 않습니다. 수신 계약이 훅을 등록하지 않은 경우 송신 계약은 트랜잭션을 중단합니다. 이는 비-ERC-777 스마트 계약으로의 의도치 않은 전송을 방지합니다. +3. 훅은 트랜잭션을 거부할 수 있습니다. + +### 소수 자릿수 {#decimals} + +이 표준은 또한 ERC-20에서 발생한 `decimals` 관련 혼란을 해결합니다. 이러한 명확성은 개발자 경험을 개선합니다. + +### ERC-20과의 하위 호환성 {#backwards-compatibility-with-erc-20} + +ERC-777 계약은 마치 ERC-20 계약인 것처럼 상호작용할 수 있습니다. + +## 추가 정보 {#further-reading} + +[EIP-777: 토큰 표준](https://eips.ethereum.org/EIPS/eip-777) diff --git a/public/content/translations/ko/developers/docs/standards/tokens/index.md b/public/content/translations/ko/developers/docs/standards/tokens/index.md new file mode 100644 index 00000000000..dd45932ecb8 --- /dev/null +++ b/public/content/translations/ko/developers/docs/standards/tokens/index.md @@ -0,0 +1,41 @@ +--- +title: "토큰 표준" +description: "대체 가능 토큰 및 대체 불가능 토큰을 위한 ERC-20, ERC-721, ERC-1155를 비롯한 이더리움 토큰 표준을 살펴보세요." +lang: ko +incomplete: true +--- + +## 소개 {#introduction} + +많은 이더리움 개발 표준이 토큰 인터페이스에 초점을 맞추고 있습니다. 이러한 표준은 스마트 계약이 구성 가능성을 유지하도록 도와주므로, 새로운 프로젝트가 토큰을 발행할 때 기존 탈중앙화 거래소 및 애플리케이션과의 호환성을 유지할 수 있습니다. + +토큰 표준은 이더리움 생태계 전반에서 토큰이 어떻게 작동하고 상호작용하는지를 정의합니다. 이는 개발자가 불필요한 수고를 덜고 더 쉽게 구축할 수 있도록 하며, 토큰이 지갑, 거래소 및 디파이 플랫폼과 원활하게 작동하도록 보장합니다. 게임, 거버넌스 또는 기타 사용 사례 등에서 이러한 표준은 일관성을 제공하고 이더리움의 상호 연결성을 더욱 강화합니다. + +## 필수 구성 요소 {#prerequisites} + +- [이더리움 개발 표준](/developers/docs/standards/) +- [스마트 계약](/developers/docs/smart-contracts/) + +## 토큰 표준 {#token-standards} + +다음은 이더리움에서 가장 인기 있는 토큰 표준 중 일부입니다: + +- [ERC-20](/developers/docs/standards/tokens/erc-20/) - 투표 토큰, 스테이킹 토큰 또는 가상 화폐와 같은 대체 가능한(상호 교환 가능한) 토큰을 위한 표준 인터페이스입니다. + +### NFT 표준 {#nft-standards} + +- [ERC-721](/developers/docs/standards/tokens/erc-721/) - 예술품이나 노래의 증서와 같은 대체 불가능한 토큰을 위한 표준 인터페이스입니다. +- [ERC-1155](/developers/docs/standards/tokens/erc-1155/) - ERC-1155는 거래 및 트랜잭션 묶음의 효율성을 높여 비용을 절감합니다. 이 토큰 표준은 $BNB 또는 $BAT 같은 유틸리티 토큰과 CryptoPunks와 같은 대체 불가능한 토큰을 만들 수 있습니다. + +[ERC](https://eips.ethereum.org/erc) 제안 전체 목록. + +## 더 읽어보기 {#further-reading} + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 관련 튜토리얼 {#related-tutorials} + +- [토큰 통합 체크리스트](/developers/tutorials/token-integration-checklist/) _– 토큰과 상호작용할 때 고려해야 할 사항에 대한 체크리스트입니다._ +- [ERC20 토큰 스마트 계약 이해하기](/developers/tutorials/understand-the-erc-20-token-smart-contract/) _– 이더리움 테스트넷에 첫 스마트 계약을 배포하는 방법에 대한 소개입니다._ +- [솔리디티 스마트 계약에서 ERC20 토큰 전송 및 승인하기](/developers/tutorials/transfers-and-approval-of-erc-20-tokens-from-a-solidity-smart-contract/) _– 솔리디티 언어를 사용하여 스마트 계약으로 토큰과 상호작용하는 방법입니다._ +- [ERC721 마켓 구현하기[실용 가이드]](/developers/tutorials/how-to-implement-an-erc721-market/) _– 탈중앙화된 게시판에서 토큰화된 아이템을 판매하는 방법입니다._ diff --git a/public/content/translations/ko/developers/docs/storage/index.md b/public/content/translations/ko/developers/docs/storage/index.md new file mode 100644 index 00000000000..fdfd3f02633 --- /dev/null +++ b/public/content/translations/ko/developers/docs/storage/index.md @@ -0,0 +1,216 @@ +--- +title: "분산형 스토리지" +description: "탈중앙화 저장소의 정의와 이를 하나의 디앱으로 통합하는 데 사용할 수 있는 도구들에 대한 개요" +lang: ko +--- + +하나의 회사나 조직이 운영하는 중앙집중형 서버와 달리, 탈중앙화 저장소 시스템은 전체 데이터의 일부를 보유하는 사용자-운영자들의 P2P 네트워크로 구성되어 안정성 있는 파일 저장소 공유 시스템을 구축합니다. 이런 시스템들은 블록체인 기반 애플리케이션이나 모든 P2P 기반 네트워크에 있을 수 있습니다. + +이더리움은 그 자체로 탈중앙화 저장소 시스템으로 활용될 수 있으며, 모든 스마트 컨트랙트에서의 코드 저장공간이 바로 그것입니다. 하지만 많은 양의 데이터를 저장하는 경우, 이더리움이 설계된 목적에 부합하지 않습니다. 체인은 꾸준히 성장하고 있지만, 이 글을 쓰는 시점에서 이더리움 체인은 약 500GB\~1TB([클라이언트에 따라 다름](https://etherscan.io/chartsync/chaindefault))이며, 네트워크의 모든 노드는 모든 데이터를 저장할 수 있어야 합니다. 체인을 대량의 데이터(예: 5TB)로 확장해야 하는 경우 모든 노드가 계속 실행되는 것은 실현 가능하지 않을 수 있습니다. 또한, 이 많은 양의 데이터를 메인넷에 배포하는 비용은 [가스](/developers/docs/gas) 수수료 때문에 엄청나게 비쌀 것입니다. + +이러한 제약으로 인해, 많은 양의 데이터를 탈중앙화된 방식으로 저장할 수 있는 다른 체인이나 방법론이 필요합니다. + +탈중앙화 저장소(dStorage) 옵션을 살펴볼 때, 사용자가 유의해야 할 몇가지 사항이 있습니다. + +- 지속성 메카니즘 / 인센티브 구조 +- 데이터 보존 시행 +- 분산성 +- 합의 + +## 지속성 메커니즘 / 인센티브 구조 {#persistence-mechanism} + +### 블록체인 기반 {#blockchain-based} + +데이터 조각이 영원히 지속되려면 지속성 메커니즘을 사용해야 합니다. 예를 들어, 이더리움에서 지속성 메커니즘이란 노드를 실행할 때 전체 체인을 고려해야 한다는 것입니다. 새로운 데이터 조각이 체인의 끝에 추가되고 계속해서 성장하여 모든 노드가 임베디드 데이터를 복제해야 합니다. + +이를 **블록체인 기반** 지속성이라고 합니다. + +블록체인 기반 지속성의 문제점은 체인이 너무 커져서 모든 데이터를 실현 가능한 방식으로 유지하고 저장하기 어렵다는 것입니다(예: [여러 출처](https://healthit.com.au/how-big-is-the-internet-and-how-do-we-measure-it/)에 따르면 인터넷에는 40제타바이트 이상의 저장 공간 용량이 필요하다고 추정됩니다). + +블록체인은 또한 일종의 인센티브 구조가 있어야 합니다. 블록체인 기반 지속성을 위해서는 검증자에게 지급되는 대가가 있습니다. 데이터가 체인에 추가될 때 검증자들이 데이터를 추가하기 위해 대가를 받습니다. + +블록체인 기반 지속성을 갖춘 플랫폼 + +- 이더리움 +- [Arweave](https://www.arweave.org/) + +### 계약 기반 {#contract-based} + +**계약 기반** 지속성은 모든 노드에서 데이터를 복제하고 영구적으로 저장할 수 없으며, 대신 계약 합의에 따라 유지되어야 한다는 개념을 기반으로 합니다. 이것은 일정 기간 동안 데이터 조각을 보유하기로 약속한 여러 노드와 맺은 합의입니다. 데이터를 계속 유지하려면 소진될 때마다 재지불하거나 갱신해야 합니다. + +대부분의 경우, 모든 데이터를 온체인으로 저장하는 대신, 체인 상에 데이터가 위치하는 곳의 해시가 저장됩니다. 이렇게 하면 모든 데이터를 유지하기 위해 전체 체인을 확장할 필요가 없습니다. + +컨트랙트 기반 지속성을 갖춘 플랫폼: + +- [Filecoin](https://docs.filecoin.io/basics/what-is-filecoin) +- [Skynet](https://sia.tech/) +- [Storj](https://storj.io/) +- [Züs](https://zus.network/) +- [Crust Network](https://crust.network) +- [Swarm](https://www.ethswarm.org/) +- [4EVERLAND](https://www.4everland.org/) + +### 추가 고려사항 {#additional-consideration} + +IPFS는 파일, 웹사이트, 애플리케이션 및 데이터를 저장하고 액세스하기 위한 분산 시스템입니다. 이 시스템은 내장된 인센티브 체계가 없지만, 장기적인 지속성을 위해 위에 언급된 계약 기반 인센티브 솔루션 중 하나와 함께 사용할 수 있습니다. 또 다른 방법으로 IPFS에서 데이터를 지속시키는 방법은 '고정 서비스'와 협력하는 것입니다. 이 서비스는 사용자의 데이터를 "고정"해 줍니다. 사용자는 자신의 IPFS 노드를 실행하여 자신 또는 다른 사람의 데이터를 무료로 지속시킬 수 있습니다! + +- [IPFS](https://docs.ipfs.io/concepts/what-is-ipfs/) +- [Pinata](https://www.pinata.cloud/) _(IPFS 피닝 서비스)_ +- [web3.storage](https://web3.storage/) _(IPFS/Filecoin 피닝 서비스)_ +- [Infura](https://infura.io/product/ipfs) _(IPFS 피닝 서비스)_ +- [IPFS Scan](https://ipfs-scan.io) _(IPFS 피닝 탐색기)_ +- [4EVERLAND](https://www.4everland.org/)_(IPFS 피닝 서비스)_ +- [Filebase](https://filebase.com) _(IPFS 피닝 서비스)_ +- [Spheron Network](https://spheron.network/) _(IPFS/Filecoin 피닝 서비스)_ + +SWARM은 저장 인센티브 시스템과 저장 임대 가격 예측 시스템을 갖춘 분산 데이터 저장 및 배포 기술입니다. + +## 데이터 보존 {#data-retention} + +데이터를 보존하기 위해, 시스템은 데이터가 확실히 보존되도록 하는 일종의 메커니즘을 가지고 있어야 합니다. + +### 챌린지 메커니즘 {#challenge-mechanism} + +확실히 데이터가 보존되도록 하는 가장 일반적인 방법 중 하나는, 노드에 전송되는 일종의 암호학적 문제를 사용하여 노드가 데이터를 가지고 있는지 확인하는 것입니다. 간단한 방법은 아르위브의 PoA를 살펴보는 것입니다. 이것은 노드에게 가장 최근 블록과 과거의 랜덤 블록 하나에 있는 데이터가 모두 있는지 확인하는 문제를 냅니다. 만약 노드가 답을 내놓지 못하면, 해당 노드는 불이익을 받습니다. + +챌린지 메커니즘을 갖춘 dStorage 유형: + +- Züs +- 스카이넷 +- 아르위브 +- 파일코인 +- Crust Network +- 4EVERLAND + +### 탈중앙성 {#decentrality} + +플랫폼의 분산화 수준을 측정할 수 있는 좋은 도구는 없지만, 일반적으로 KYC의 형태가 없는 도구를 사용하여 중앙집중화되지 않았다는 증거를 제시하고자 할 것입니다. + +KYC가 없는 탈중앙화 도구: + +- 스카이넷 +- 아르위브 +- 파일코인 +- IPFS +- 이더리움 +- Crust Network +- 4EVERLAND + +### 합의 {#consensus} + +이 도구 대부분은 자체 버전의 [합의 메커니즘](/developers/docs/consensus-mechanisms/)을 가지고 있지만, 일반적으로 [**작업 증명(PoW)**](/developers/docs/consensus-mechanisms/pow/) 또는 [**지분 증명(PoS)**](/developers/docs/consensus-mechanisms/pos/)에 기반합니다. + +작업 증명 기반: + +- 스카이넷 +- 아르위브 + +지분 증명 기반: + +- 이더리움 +- 파일코인 +- Züs +- Crust Network + +## 관련 도구 {#related-tools} + +**IPFS - _InterPlanetary File System은 이더리움을 위한 탈중앙화 저장 공간 및 파일 참조 시스템입니다._** + +- [Ipfs.io](https://ipfs.io/) +- [개발문서](https://docs.ipfs.io/) +- [GitHub](https://github.com/ipfs/ipfs) + +**Storj DCS - _개발자를 위한 안전하고, 프라이빗하며, S3와 호환되는 탈중앙화 클라우드 객체 저장 공간입니다._** + +- [Storj.io](https://storj.io/) +- [개발문서](https://docs.storj.io/) +- [GitHub](https://github.com/storj/storj) + +**Sia - _암호학을 활용하여 구매자와 판매자가 직접 거래할 수 있도록 하는 무신뢰 클라우드 저장 공간 마켓플레이스를 만듭니다._** + +- [Skynet.net](https://sia.tech/) +- [개발문서](https://docs.sia.tech/) +- [GitHub](https://github.com/SiaFoundation/) + +**Filecoin - _Filecoin은 IPFS를 개발한 바로 그 팀에서 만들었습니다. IPFS 이상 위에 있는 인센티브 계층입니다._** + +- [Filecoin.io](https://filecoin.io/) +- [개발문서](https://docs.filecoin.io/) +- [GitHub](https://github.com/filecoin-project/) + +**Arweave - _Arweave는 데이터 저장을 위한 dStorage 플랫폼입니다._** + +- [Arweave.org](https://www.arweave.org/) +- [개발문서](https://docs.arweave.org/info/) +- [Arweave](https://github.com/ArweaveTeam/arweave/) + +**Züs - _Züs는 샤딩과 블로버(blobber)를 갖춘 지분 증명 dStorage 플랫폼입니다._** + +- [zus.network](https://zus.network/) +- [개발문서](https://docs.zus.network/zus-docs/) +- [GitHub](https://github.com/0chain/) + +**Crust Network - _Crust는 IPFS 위에 구축된 dStorage 플랫폼입니다._** + +- [Crust.network](https://crust.network) +- [개발문서](https://wiki.crust.network) +- [GitHub](https://github.com/crustio) + +**Swarm - _이더리움 웹3 스택을 위한 분산형 저장 공간 플랫폼 및 콘텐츠 배포 서비스입니다._** + +- [EthSwarm.org](https://www.ethswarm.org/) +- [개발문서](https://docs.ethswarm.org/) +- [GitHub](https://github.com/ethersphere/) + +**OrbitDB - _IPFS 기반의 탈중앙화 P2P 데이터베이스입니다._** + +- [OrbitDB.org](https://orbitdb.org/) +- [개발문서](https://github.com/orbitdb/field-manual/) +- [GitHub](https://github.com/orbitdb/orbit-db/) + +**Aleph.im - _탈중앙화 클라우드 프로젝트(데이터베이스, 파일 저장 공간, 컴퓨팅 및 DID)입니다._** 오프체인과 온체인 P2P 기술의 독특한 조합. IPFS와 멀티체인 양립 가능._\*\* + +- [Aleph.im](https://aleph.cloud/) +- [개발문서](https://docs.aleph.cloud/) +- [GitHub](https://github.com/aleph-im/) + +**Ceramic - _데이터가 풍부하고 흥미로운 애플리케이션을 위한 사용자 제어 IPFS 데이터베이스 저장 공간입니다._** + +- [Ceramic.network](https://ceramic.network/) +- [개발문서](https://developers.ceramic.network/) +- [GitHub](https://github.com/ceramicnetwork/js-ceramic/) + +**Filebase - _S3와 호환되는 탈중앙화 저장 공간 및 지역 중복 IPFS 피닝 서비스. Filebase를 통해 IPFS에 업로드된 모든 파일은 전 세계에 걸쳐 3중으로 복제되어 Filebase 인프라에 자동으로 피닝됩니다._** + +- [Filebase.com](https://filebase.com/) +- [개발문서](https://docs.filebase.com/) +- [GitHub](https://github.com/filebase) + +**4EVERLAND - _저장 공간, 컴퓨팅, 네트워킹 핵심 기능을 통합한 웹3.0 클라우드 컴퓨팅 플랫폼으로, S3와 호환되며 IPFS, Arweave와 같은 탈중앙화 저장 공간 네트워크에서 동기식 데이터 저장을 제공합니다._** + +- [4everland.org](https://www.4everland.org/) +- [개발문서](https://docs.4everland.org/) +- [GitHub](https://github.com/4everland) + +**Kaleido - _클릭 버튼으로 IPFS 노드를 제공하는 서비스형 블록체인(BaaS) 플랫폼입니다._** + +- [Kaleido](https://kaleido.io/) +- [개발문서](https://docs.kaleido.io/kaleido-services/ipfs/) +- [GitHub](https://github.com/kaleido-io) + +**Spheron Network - _Spheron은 최고의 성능을 갖춘 탈중앙화 인프라에서 애플리케이션을 출시하려는 탈중앙화앱을 위해 설계된 서비스형 플랫폼(PaaS)입니다. 컴퓨팅, 탈중앙화 저장 공간, CDN 및 웹 호스팅을 기본으로 제공합니다._** + +- [spheron.network](https://spheron.network/) +- [개발문서](https://docs.spheron.network/) +- [GitHub](https://github.com/spheronFdn) + +## 더 읽어보기 {#further-reading} + +- [탈중앙화 저장 공간이란?](https://coinmarketcap.com/academy/article/what-is-decentralized-storage-a-deep-dive-by-filecoin) - _CoinMarketCap_ +- [탈중앙화 저장 공간에 대한 5가지 일반적인 오해 바로잡기](https://www.storj.io/blog/busting-five-common-myths-about-decentralized-storage) - _Storj_ + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 관련 주제 {#related-topics} + +- [개발 프레임워크](/developers/docs/frameworks/) diff --git a/public/content/translations/ko/developers/docs/transactions/index.md b/public/content/translations/ko/developers/docs/transactions/index.md new file mode 100644 index 00000000000..0d6be0ae39d --- /dev/null +++ b/public/content/translations/ko/developers/docs/transactions/index.md @@ -0,0 +1,231 @@ +--- +title: "트랜잭션" +description: "이더리움 트랜잭션의 개요 - 어떻게 동작하는지, 데이터 구조, 그리고 애플리케이션을 통해 어떻게 전송되는지" +lang: ko +--- + +트랜잭션은 계정으로부터 암호학적으로 서명된 명령들이다. 계정은 이더리움 네트워크의 상태를 업데이트하기 위해 트랜잭션을 초기화 할 것이다. 가장 간단한 트랜잭션은 한 계정에서 다른 계정으로 ETH를 보내는 것이다. + +## 필수 구성 요소 {#prerequisites} + +이 페이지를 더 잘 이해할 수 있도록 [계정](/developers/docs/accounts/) 및 [이더리움 소개](/developers/docs/intro-to-ethereum/)를 먼저 읽어보시는 것을 권장합니다. + +## 트랜잭션이란 무엇인가? 트랜잭션이란 무엇인가요? {#whats-a-transaction} + +이더리움 트랜잭션은 외부 계정, 즉 컨트랙트가 아니라 사람이 관리하는 계정에 의해 초기화된 하나의 동작을 말한다. 예를 들어, 밥이 앨리스에게 1 ETH를 보낸다면, 밥의 계정은 인출되어야 하고, 앨리스의 것은 입금되어야 한다. 이 상태-변경 동작은 트랜잭션 안에서 이루어진다. + +![트랜잭션으로 인한 상태 변화를 보여주는 다이어그램](./tx.png) +_[Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)에서 발췌한 다이어그램_ + +EVM의 상태를 변경하는 트랜잭션은 전체 네트워크로 브로드캐스트되어야 한다. 어떤 노드든 EVM 위에서 실행되는 트랜잭션을 위한 요청을 브로드캐스트 할 수 있다. 이 과정을 거치고나서, 검증자는 트랜잭션을 실행하고 상태변경 결과를 나머지 네트워크로 전파한다. + +트랜잭션은 수수료가 필요하고 검증된 블록에 포함되어 있어야한다. 이 개요를 더 간단히 하기 위해서 우리는 다른곳에서 가스 수수료와 검증에 대해서 다룰 것이다. + +제출된 트랜잭션은 다음 정보를 갖는다. + +- `from` – 트랜잭션에 서명할 보내는 사람의 주소입니다. 컨트랙트 계정은 트랜잭션을 보낼 수 없기 때문에 외부계정에만 존재한다 +- `to` – 받는 주소(외부 소유 계정인 경우, 트랜잭션이 값을 전송합니다). 컨트랙트 계정이라면 트랜잭션은 컨트랙트 코드를 실행할 것이다) +- `signature` – 보내는 사람의 식별자입니다. 이것은 송신자의 개인 키로 트랜잭션을 서명하고 송신자가 트랜잭션을 인증함을 확정하면 생성된다. +- `nonce` - 계정의 트랜잭션 수를 나타내는 순차적으로 증가하는 카운터입니다. +- `value` – 보내는 사람에서 받는 사람으로 전송할 ETH 금액(WEI 단위이며, 1ETH는 1e+18wei와 같습니다). +- `input data` – 임의의 데이터를 포함하기 위한 선택적 필드입니다. +- `gasLimit` – 트랜잭션이 소비할 수 있는 가스 단위의 최대량입니다. [EVM](/developers/docs/evm/opcodes)은 각 계산 단계에 필요한 가스 단위를 명시합니다. +- `maxPriorityFeePerGas` - 검증인에게 팁으로 포함될 소비된 가스의 최대 가격입니다. +- `maxFeePerGas` - 트랜잭션에 대해 지불하고자 하는 가스 단위당 최대 수수료(`baseFeePerGas` 및 `maxPriorityFeePerGas` 포함)입니다. + +가스는 채굴자에 의해 트랜잭션을 처리하는데 필요한 컴퓨팅 계산에 대한 참조이다. 사용자들은 이 컴퓨팅에 수수료를 지불해야 한다. `gasLimit`과 `maxPriorityFeePerGas`는 검증인에게 지불되는 최대 트랜잭션 수수료를 결정합니다. [가스에 대한 자세한 정보](/developers/docs/gas/). + +트랜잭션 객체는 아래처럼 보일 것이다. + +```js +{ + from: "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", + to: "0xac03bb73b6a9e108530aff4df5077c2b3d481e5a", + gasLimit: "21000", + maxFeePerGas: "300", + maxPriorityFeePerGas: "10", + nonce: "0", + value: "10000000000" +} +``` + +그러나 트랜잭션 객체는 송신자의 개인 키를 사용해서 서명되어야 한다. 이는 그 트랜잭션이 그 송신자로부터만 왔고, 부정하게 보내지지 않았음을 증명한다. + +Geth 같은 이더리움 클라이언트가 이 서명 과정을 처리할 것이다. + +[JSON-RPC](/developers/docs/apis/json-rpc) 호출 예시: + +```json +{ + "id": 2, + "jsonrpc": "2.0", + "method": "account_signTransaction", + "params": [ + { + "from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db", + "gas": "0x55555", + "maxFeePerGas": "0x1234", + "maxPriorityFeePerGas": "0x1234", + "input": "0xabcd", + "nonce": "0x0", + "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", + "value": "0x1234" + } + ] +} +``` + +예시 응답: + +```json +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663", + "tx": { + "nonce": "0x0", + "maxFeePerGas": "0x1234", + "maxPriorityFeePerGas": "0x1234", + "gas": "0x55555", + "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", + "value": "0x1234", + "input": "0xabcd", + "v": "0x26", + "r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e", + "s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663", + "hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e" + } + } +} +``` + +- `raw`는 [RLP(Recursive Length Prefix)](/developers/docs/data-structures-and-encoding/rlp)로 인코딩된 서명된 트랜잭션입니다. +- `tx`는 JSON 형식의 서명된 트랜잭션입니다. + +해시를 서명함으로써, 트랜잭션이 네트워크로부터 제출되었음과 송신자로부터 왔음을 암호학적으로 입증할 수 있다. + +### 데이터 필드 {#the-data-field} + +대부분의 트랜잭션은 외부 소유 계정의 컨트랙트를 액세스한다. +대부분의 컨트랙트는 솔리디티(Solidity)로 작성되며, [ABI(애플리케이션 바이너리 인터페이스)](/glossary/#abi)에 따라 데이터 필드를 해석합니다. + +처음 4 바이트는 함수 이름과 arguments의 해시를 사용하여 호출할 함수를 명시합니다. +[이 데이터베이스](https://www.4byte.directory/signatures/)를 사용하여 셀렉터로부터 함수를 식별할 수 있습니다. + +나머지 calldata는 인자이며, [ABI 사양에 명시된 대로 인코딩됩니다](https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding). + +예를 들어, [이 트랜잭션](https://etherscan.io/tx/0xd0dcbe007569fcfa1902dae0ab8b4e078efe42e231786312289b1eee5590f6a1)을 살펴보겠습니다. +calldata를 보려면 Click to see More를 사용하세요. + +함수 셀렉터는 `0xa9059cbb`입니다. [이 서명을 가진 여러 알려진 함수](https://www.4byte.directory/signatures/?bytes4_signature=0xa9059cbb)가 있습니다. +이 경우 [컨트랙트 소스 코드](https://etherscan.io/address/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48#code)가 Etherscan에 업로드되었으므로 함수가 `transfer(address,uint256)`임을 알 수 있습니다. + +나머지 데이터는: + +``` +0000000000000000000000004f6742badb049791cd9a37ea913f2bac38d01279 +000000000000000000000000000000000000000000000000000000003b0559f4 +``` + +ABI 명세서에 따르면, 정수값 (예를 들어 20바이트 정수인 주소) 은 ABI에서 앞에 0이 추가된 32 바이트 단어로 표시된다. +따라서 `to` 주소는 [`4f6742badb049791cd9a37ea913f2bac38d01279`](https://etherscan.io/address/0x4f6742badb049791cd9a37ea913f2bac38d01279)임을 알 수 있습니다. +`value`는 0x3b0559f4 = 990206452입니다. + +## 트랜잭션 유형 {#types-of-transactions} + +이더리움에서는 다른 몇가지 다른 유형의 트랜잭션이 있다. + +- 보통의 트랜잭션: 한 계정에서 다른 계정으로의 트랜잭션 +- Contract deployment transactions: 'to' address 가 없는 트랜잭션으로, 데이터 필드가 컨트랙트 코드로 사용된다. +- 컨트랙트의 실행: 배포된 스마트 컨트랙트와 상호작용하는 트랜잭션이다. 이 경우, 'to' 주소는 스마트 컨트랙트의 주소이다. + +### 가스에 대하여 {#on-gas} + +앞서 언급했듯이 트랜잭션을 실행하려면 [가스](/developers/docs/gas/)가 필요합니다. 간단한 전송 트랜잭션은 21000 단위의 가스가 필요하다. + +따라서 밥이 앨리스에게 `baseFeePerGas` 190gwei와 `maxPriorityFeePerGas` 10gwei로 1ETH를 보내려면, 밥은 다음 수수료를 지불해야 합니다: + +``` +(190 + 10) * 21000 = 4,200,000 gwei +--또는-- +0.0042 ETH +``` + +밥의 계정에서 -1.0042 ETH가 인출됩니다(앨리스에게 1 ETH + 가스 수수료 0.0042 ETH). + +앨리스의 계정에 +1.0 ETH가 입금됩니다. + +-0.00399 ETH의 기본 수수료는 소각됩니다. + +검증인은 팁으로 +0.000210 ETH를 받습니다. + +![사용되지 않은 가스가 환불되는 방식을 보여주는 다이어그램](./gas-tx.png) +_[Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)에서 발췌한 다이어그램_ + +트랜잭션 내에서 사용되지 않은 가스는 사용자 계정으로 환불된다. + +### 스마트 계약 상호작용 {#smart-contract-interactions} + +스마트 계약과 관련된 모든 트랜잭션에는 가스가 필요합니다. + +스마트 계약에는 컨트랙트의 상태를 변경하지 않는 [`view`](https://docs.soliditylang.org/en/latest/contracts.html#view-functions) 또는 [`pure`](https://docs.soliditylang.org/en/latest/contracts.html#pure-functions) 함수로 알려진 함수가 포함될 수도 있습니다. 따라서 EOA에서 이러한 함수를 호출할 때 가스가 필요하지 않습니다. 이 시나리오의 기본 RPC 호출은 [`eth_call`](/developers/docs/apis/json-rpc#eth_call)입니다. + +`eth_call`을 사용하여 액세스할 때와 달리, 이러한 `view` 또는 `pure` 함수는 내부적으로(즉, 컨트랙트 자체 또는 다른 컨트랙트에서) 호출될 때도 가스를 소모합니다. + +## 트랜잭션 생명주기 {#transaction-lifecycle} + +트랜잭션이 제출되면 다음이 일어난다. + +1. 트랜잭션 해시는 암호화 방식으로 생성됩니다: + `0x97d99bc7729211111a21b12c933c949d4f31684f1d6954ff477d0477538ff017` +2. 트랜잭션은 네트워크로 브로드캐스트 되고 다른 모든 보류 중인 네트워크 트랜잭션으로 구성된 트랜잭션 풀에 추가됩니다. +3. 검증인은 트랜잭션을를 입증하고 성공적이라고 처리하기 위해 트랜잭션을 선택하고 이를 블록에 포함해야 한다. +4. 시간이 지날 수록 블록에 포함된 당신의 트랜잭션은 "justified" 에서 "finalized"로 업그레이드 될 것이다. 이러한 업그레이드를 통해 트랜잭션이 성공적으로 완료되고 절대 변경되지 않을 것이라고 훨씬 더 확신할 수 있습니다. 블록이 "완료(finalized)"되면 수십억 달러의 비용이 드는 네트워크 수준의 공격에 의해서만 변경될 수 있습니다. + +## 시각적 데모 {#a-visual-demo} + +오스틴의 트랜잭션, 가스, 그리고 채굴에 대한 안내를 보라. + + + +## 유형화된 트랜잭션 봉투 {#typed-transaction-envelope} + +이더리움은 원래 트랜잭션 형식이 하나였다. 각 트랜잭션은 nonce, gas price, gas limit, to address, value, data, v, r, 와 s 를 포함 되어있었다. 이 필드들은 [RLP 인코딩](/developers/docs/data-structures-and-encoding/rlp/)되며, 다음과 같은 형식을 가집니다: + +`RLP([nonce, gasPrice, gasLimit, to, value, data, v, r, s])` + +이더리움은 기존 트랜잭션 형식에 영향을 주지 않고 액세스 목록 및 [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)와 같은 새로운 기능을 구현할 수 있도록 여러 유형의 트랜잭션을 지원하도록 발전했습니다. + +[EIP-2718](https://eips.ethereum.org/EIPS/eip-2718)은 이러한 동작을 가능하게 합니다. 트랜잭션들은 다음과 같이 해석된다: + +`TransactionType || TransactionPayload` + +필드는 다음과 같이 정의된다. + +- `TransactionType` - 0과 0x7f 사이의 숫자로, 총 128개의 가능한 트랜잭션 유형을 나타냅니다. +- `TransactionPayload` - 트랜잭션 유형에 따라 정의되는 임의의 바이트 배열입니다. + +`TransactionType` 값에 따라 트랜잭션을 다음과 같이 분류할 수 있습니다. + +1. **유형 0(레거시) 트랜잭션:** 이더리움 출시 이후 사용된 원래 트랜잭션 형식입니다. 이 트랜잭션은 [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)의 동적 가스 수수료 계산이나 스마트 계약용 액세스 목록과 같은 기능을 포함하지 않습니다. 레거시 트랜잭션은 직렬화된 형태에서 유형을 나타내는 특정 접두사가 없으며, [RLP(Recursive Length Prefix)](/developers/docs/data-structures-and-encoding/rlp) 인코딩을 사용할 때 바이트 `0xf8`로 시작합니다. 이러한 트랜잭션의 TransactionType 값은 `0x0`입니다. + +2. **유형 1 트랜잭션:** 이더리움의 [베를린 업그레이드](/ethereum-forks/#berlin)의 일부로 [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930)에서 도입되었으며, 이 트랜잭션에는 `accessList` 매개변수가 포함됩니다. 이 목록은 트랜잭션이 액세스할 것으로 예상되는 주소와 스토리지 키를 지정하여 스마트 계약과 관련된 복잡한 트랜잭션의 [가스](/developers/docs/gas/) 비용을 줄이는 데 도움이 될 수 있습니다. 유형 1 트랜잭션에는 EIP-1559 수수료 시장 변경 사항이 포함되지 않습니다. 유형 1 트랜잭션에는 `yParity` 매개변수도 포함되며, `0x0` 또는 `0x1`일 수 있으며 secp256k1 서명의 y-값의 패리티를 나타냅니다. 이 트랜잭션은 바이트 `0x01`로 시작하여 식별되며, TransactionType 값은 `0x1`입니다. + +3. 유형 2 트랜잭션은 일반적으로 EIP-1559 트랜잭션이라고 하며, 이더리움의 [런던 업그레이드](/ethereum-forks/#london)에서 [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)의 일부로 도입되었습니다. 이 트랜잭션들은 이더리움 네트워크의 표준 트랜잭션 유형이 되었습니다. 이 트랜잭션들은 새로운 수수료 시장 메커니즘을 도입하여 기본 수수료와 우선 수수료로 분리하여 수수료 예측성을 향상시킵니다. 이 트랜잭션은 바이트 `0x02`로 시작하며 `maxPriorityFeePerGas` 및 `maxFeePerGas`와 같은 필드를 포함합니다. 유형 2 트랜잭션은 유연성과 효율성 덕분에 현재 기본 설정이며, 특히 높은 네트워크 혼잡 시 사용자들이 트랜잭션 수수료를 보다 예측 가능하게 관리할 수 있게 해줍니다. 이러한 트랜잭션의 TransactionType 값은 `0x2`입니다. + +4. 유형 3(블롭) 트랜잭션은 이더리움의 [덴쿤 업그레이드](/ethereum-forks/#dencun)의 일부로 [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844)에서 도입되었습니다. 이 트랜잭션은 "블롭" 데이터(바이너리 대규모 개체)를 보다 효율적으로 처리하도록 설계되었으며, 특히 이더리움 네트워크에 더 저렴한 비용으로 데이터를 게시하는 방법을 제공하여 레이어 2 롤업에 이점을 줍니다. 블롭 트랜잭션에는 `blobVersionedHashes`, `maxFeePerBlobGas`, `blobGasPrice`와 같은 추가 필드가 포함됩니다. 이 트랜잭션은 바이트 `0x03`으로 시작하며, TransactionType 값은 `0x3`입니다. 블롭 트랜잭션은 이더리움의 데이터 가용성 및 확장성 기능에 있어 상당한 개선을 의미합니다. + +5. 유형 4 트랜잭션은 이더리움의 [펙트라 업그레이드](/roadmap/pectra/)의 일부로 [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702)에서 도입되었습니다. 이러한 트랜잭션은 계정 추상화와 순방향 호환이 가능하도록 설계되었습니다. 이러한 트랜잭션을 사용하면 EOA가 원래 기능을 손상시키지 않으면서 일시적으로 스마트 계약 계정처럼 작동할 수 있습니다. `authorization_list` 매개변수를 포함하며, EOA가 권한을 위임하는 스마트 계약을 지정합니다. 트랜잭션 후 EOA의 코드 필드에는 위임된 스마트 계약의 주소가 포함됩니다. + +## 더 읽어보기 {#further-reading} + +- [EIP-2718: 유형화된 트랜잭션 봉투](https://eips.ethereum.org/EIPS/eip-2718) + +_도움이 되었던 커뮤니티 참고 자료를 알고 계신가요? 이 페이지를 편집해서 추가하세요!_ + +## 관련 주제 {#related-topics} + +- [계정](/developers/docs/accounts/) +- [이더리움 가상 머신(EVM)](/developers/docs/evm/) +- [가스](/developers/docs/gas/) diff --git a/public/content/translations/ko/developers/docs/web2-vs-web3/index.md b/public/content/translations/ko/developers/docs/web2-vs-web3/index.md new file mode 100644 index 00000000000..24885502b23 --- /dev/null +++ b/public/content/translations/ko/developers/docs/web2-vs-web3/index.md @@ -0,0 +1,62 @@ +--- +title: "Web2와 Web3의 비교" +description: "중앙화된 웹2 서비스와 이더리움 블록체인 기술을 기반으로 구축된 탈중앙화 웹3 애플리케이션을 비교해 보세요." +lang: ko +--- + +웹2는 오늘날 대부분의 사람들이 알고 있는 인터넷 버전을 의미합니다. 인터넷은 여러분의 개인 정보를 이용하여 서비스를 제공하는 회사들이 지배합니다. 이더리움의 맥락에서 볼 때 웹3은 블록체인 상에서 구동되는 분산형 앱을 뜻합니다. 웹3은 사용자의 개인 정보를 이용하여 수익 창출을 하지 않고도 누구나 참여할 수 있도록 하는 앱입니다. + +입문자에게 더 친화적인 자료를 찾고 있나요? [웹3 소개](/web3/)를 확인해 보세요. + +## 웹3의 이점 {#web3-benefits} + +많은 웹3 개발자들은 이더리움에 기본적으로 내장된 분산형 방식 때문에 디앱을 구축하기로 했습니다. + +- 네트워크에 있는 누구나 서비스를 사용할 권한이 있으며, 다시 말해 서비스 사용에는 권힌이 필요 없다는 뜻입니다. +- 아무도 여러분을 막을 수도 그 서비스의 접근을 거부할 수도 없다. +- 결제는 기본 토큰인 이더(ETH)를 통해 이루어집니다. +- 이더리움은 튜링-완전으로 대부분의 프로그래밍을 할 수 있다. + +## 실용적인 비교 {#practical-comparisons} + +| 웹2 | 웹3 | +| --------------------------------------- | ------------------------------------------------------------------- | +| 트위터는 모든 계정이나 트윗을 검열할 수 있습니다 | 웹3 트윗은 분산형이기 때문에 검열할 수 없을 것입니다 | +| 지불 서비스는 특정 종류의 일에는 지불을 허용하지 않도록 정할 수 있다 | 웹3 지불 앱들은 개인 데이터가 필요 없고 지불을 막을 수 없다 | +| 긱 이코노미 앱들의 서버들이 다운되어 작업자 수입에 영향을 줄 수 있다 | 웹3 서버들은 다운될 수 없다 - 그들은 그들의 백엔드로 1000여대의 컴퓨터들의 탈중앙화 네트워크인 이더리움을 사용한다 | + +이는 모든 서비스를 디앱으로 전환해야 함을 의미하지는 않습니다. 위의 예시들은 웹2와 웹3 서비스의 주요 차이점을 설명할 뿐입니다. + +## 웹3의 한계 {#web3-limitations} + +웹3에는 현재 다음과 같은 한계가 있습니다. + +- 확장성 - 웹3 상에서의 거래는 분산 방식으로 이루어지기 때문에 좀 더 느립니다. 지불과 같은 상태로의 변경은 채굴자를 통해 처리 후, 네트워크를 통해 전파된다. +- UX – 웹3 애플리케이션과 상호작용하려면 추가적인 단계, 소프트웨어, 교육이 필요할 수 있습니다. 이는 받아들이는데 허들이 될 수 있다. +- 접근성 - 웹브라우저들에 통합된 기능들이 부족하여, web3 접근성이 대부분의 사용자들에게 부족합니다. +- 비용 - 대부분의 성공적인 디앱들은 비용이 비싸서 매우 작은 양의 코드만 블록체인 상에 둔다. + +## 중앙화 vs. 탈중앙화 {#centralization-vs-decentralization} + +아래의 테이블에서 우리는 중앙화와 탈중앙화 디지털 네트워크의 대략적인 장점과 단점을 나열했다. + +| 중앙화 시스템 | 분산형 시스템 | +| -------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| 적은 네트워크 거리 (모든 참여자들이 중앙 기관에 연결된다); 전파는 중앙 기관에 의해 많은 컴퓨터 자원으로 처리 되므로 정보는 빠르게 전파된다. | 네트워크 상의 멀리 떨어진 참여자들은 잠재적으로 서로로부터 멀리 떨어진 많은 모서리들이 될 수 있다. 네트워크 상의 한 쪽으로부터의 정보 브로드캐스트는 다른 쪽까지 닿는데 긴 시간이 걸릴 수 있다. | +| 보통 더 높은 성능(더 높은 처리량, 더 적은 확장된 전체 컴퓨팅 자원)과 더 쉬운 구현. | 보통 더 낮은 성능(더 낮은 처리량, 더 많은 확장된 전체 컴퓨팅 자원)과 구현의 복잡함. | +| 데이터의 충돌 시, 해결이 깔끔하고 쉬움: 최종적인 참이 되는 것은 중앙 기관이다. | 참여자들이 동기화된 것으로 믿는 데이터의 상태에 대해 피어들이 충돌하도록 요청한다면 (대개 복잡한) 프로토콜이 해결을 중재하는데 필요하다. | +| 하나의 실패 지점: 악의적인 사람들이 중앙 기관을 표적 삼아 네트워크를 가동 중지시킬 수 있습니다. | 실패 지점이 하나가 아님: 많은 사람들이 참여하여 공격하거나 가동 중지 시켜도 네트워크는 계속 작동합니다. | +| 네트워크 참어자들간의 조정이 훨씬 쉽고, 중앙 기관에 의해 다뤄진다. 중앙 기관은 네트워크 참여자들이 업그레이드, 프로토콜 업데이트 등을 받아들이도록 매우 적은 노력으로 할 수 있다. | 네트워크 레벨 결정과 프로토콜 업그레이드 등에 최종 의견을 가지는 하나의 중개자가 없어서 조정이 대개 어렵다. 최악의 경우에는 프토토콜 변경에 대해 비동의가 있을 때 네트워크가 균열되기 쉽다. | +| 중앙 기관은 데이터를 검열할 수 있고, 잠재적으로 네트워크의 나머지와 협의해서 네트워크의 일부를 잘라버릴 수 있다. | 정보가 네트워크에 걸쳐 많은 방식으로 전파되어서 검열이 매우 더 어렵다. | +| 네트워크 내의 참여는 중앙 기관에 의해 제어된다. | 누구나 네트워크 안에 참여할 수 있다; “문지기”가 없다. 이상적으로는, 참여 비용이 매우 낮다. | + +모든 네트워크에 참이 될 수 없는 일반적인 패턴이 있음에 주의하라. 더 나아가서 실제로 어떤 네트워크가 중앙화/탈중앙화되어 있는지의 정도는 스펙트럼에 달려 있다; 전부 중앙화된 네트워크는 없다 또는 전부 탈중앙화된 네트워크는 없다. + +## 더 읽어보기 {#further-reading} + +- [웹3란 무엇인가요?](/web3/) - _ethereum.org_ +- [웹 3.0 애플리케이션의 아키텍처](https://www.preethikasireddy.com/post/the-architecture-of-a-web-3-0-application) - _Preethi Kasireddy_ +- [탈중앙화의 의미](https://medium.com/@VitalikButerin/the-meaning-of-decentralization-a0c92b76a274) _2017년 2월 6일 - 비탈릭 부테린_ +- [탈중앙화가 중요한 이유](https://onezero.medium.com/why-decentralization-matters-5e3f79f7638e) _2018년 2월 18일 - 크리스 딕슨_ +- [웹 3.0이란 무엇이며 왜 중요한가](https://medium.com/fabric-ventures/what-is-web-3-0-why-it-matters-934eb07f3d2b) _2019년 12월 31일 - 막스 머쉬, 리차드 뮤어헤드_ +- [왜 우리에게 웹 3.0이 필요한가](https://gavofyork.medium.com/why-we-need-web-3-0-5da4f2bf95ab) _2018년 9월 12일 - 개빈 우드_ diff --git a/public/content/translations/ko/developers/tutorials/a-developers-guide-to-ethereum-part-one/index.md b/public/content/translations/ko/developers/tutorials/a-developers-guide-to-ethereum-part-one/index.md new file mode 100644 index 00000000000..53fa52160e4 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/a-developers-guide-to-ethereum-part-one/index.md @@ -0,0 +1,300 @@ +--- +title: "Python 개발자를 위한 이더리움 소개, 1부" +description: "Python 프로그래밍 언어에 대한 지식이 있는 분들에게 특히 유용한 이더리움 개발 입문서입니다." +author: Marc Garreau +lang: ko +tags: [ "Python", "web3.py" ] +skill: beginner +published: 2020-09-08 +source: Snake charmers +sourceUrl: https://snakecharmers.ethereum.org/a-developers-guide-to-ethereum-pt-1/ +--- + +이더리움에 대해 들어보셨나요? 그렇다면 이제 토끼굴로 모험을 떠날 준비가 되셨나요? 이 게시물에서는 블록체인의 몇 가지 기본 사항을 간략히 다룬 다음, 시뮬레이션된 이더리움 노드와 상호 작용하여 블록 데이터 읽기, 계정 잔액 확인, 트랜잭션 전송 등을 수행하도록 안내합니다. 그 과정에서 기존의 앱 구축 방식과 이 새로운 탈중앙화 패러다임의 차이점을 중점적으로 살펴보겠습니다. + +## 권장 선수 지식 {#soft-prerequisites} + +이 게시물은 광범위한 개발자가 접근할 수 있도록 하는 것을 목표로 합니다. [Python 도구](/developers/docs/programming-languages/python/)가 사용되지만, 아이디어를 전달하기 위한 수단일 뿐이므로 Python 개발자가 아니어도 문제없습니다. 하지만, 독자 여러분이 이미 알고 있는 몇 가지 사항을 가정하고 이더리움 관련 내용으로 빠르게 넘어가겠습니다. + +가정 사항: + +- 터미널을 다룰 수 있어야 합니다. +- Python 코드를 몇 줄 작성해 본 경험이 있어야 합니다. +- 컴퓨터에 Python 3.6 이상 버전이 설치되어 있어야 합니다([가상 환경](https://realpython.com/effective-python-environment/#virtual-environments) 사용을 적극 권장합니다). +- Python의 패키지 설치 프로그램인 `pip`를 사용해 본 경험이 있어야 합니다. + 다시 한번 말씀드리지만, 이 중 어느 하나라도 해당하지 않거나 이 글의 코드를 재현할 계획이 없더라도 내용을 따라가는 데는 큰 무리가 없을 것입니다. + +## 간단히 알아보는 블록체인 {#blockchains-briefly} + +이더리움을 설명하는 방법은 여러 가지가 있지만, 그 중심에는 블록체인이 있습니다. 블록체인은 일련의 블록으로 구성되어 있으니, 여기서부터 시작하겠습니다. 가장 간단한 용어로, 이더리움 블록체인의 각 블록은 약간의 메타데이터와 트랜잭션 목록에 불과합니다. JSON 형식으로는 다음과 같이 보입니다. + +```json +{ + "number": 1234567, + "hash": "0xabc123...", + "parentHash": "0xdef456...", + ..., + "transactions": [...] +} +``` + +각 [블록](/developers/docs/blocks/)은 그 이전 블록에 대한 참조를 가지며, `parentHash`는 단순히 이전 블록의 해시입니다. + +참고: 이더리움은 고정 크기 값('해시')을 생성하기 위해 해시 함수를 정기적으로 사용합니다. 해시는 이더리움에서 중요한 역할을 하지만, 지금은 고유 ID라고 생각해도 무방합니다. + +![각 블록 내부의 데이터를 포함한 블록체인 다이어그램](./blockchain-diagram.png) + +_블록체인은 본질적으로 각 블록이 이전 블록을 참조하는 연결 리스트입니다._ + +이 데이터 구조는 새로운 것이 아니지만, 네트워크를 관장하는 규칙(즉, P2P 프로토콜)은 새롭습니다. 중앙 기관이 없습니다. 피어들의 네트워크는 네트워크를 유지하기 위해 협력해야 하며, 다음 블록에 어떤 트랜잭션을 포함할지 결정하기 위해 경쟁해야 합니다. 따라서 친구에게 돈을 보내려면 해당 트랜잭션을 네트워크에 브로드캐스트한 다음, 다가오는 블록에 포함될 때까지 기다려야 합니다. + +블록체인이 한 사용자에게서 다른 사용자에게로 돈이 실제로 전송되었는지 확인하는 유일한 방법은 해당 블록체인 고유의(즉, 해당 블록체인에 의해 생성 및 관리되는) 통화를 사용하는 것입니다. 이더리움에서 이 통화는 이더(ether)라고 하며, 이더리움 블록체인에는 계정 잔액에 대한 유일한 공식 기록이 포함되어 있습니다. + +## 새로운 패러다임 {#a-new-paradigm} + +이 새로운 탈중앙화 기술 스택은 새로운 개발자 도구를 탄생시켰습니다. 이러한 도구는 많은 프로그래밍 언어에 존재하지만, 우리는 Python의 관점에서 살펴보겠습니다. 다시 한번 강조하지만, Python이 선호하는 언어가 아니더라도 따라가는 데 큰 어려움은 없을 것입니다. + +이더리움과 상호 작용하려는 Python 개발자는 [Web3.py](https://web3py.readthedocs.io/)를 사용할 가능성이 높습니다. Web3.py는 이더리움 노드에 연결하고 데이터를 주고받는 방식을 크게 단순화하는 라이브러리입니다. + +참고: '이더리움 노드'와 '이더리움 클라이언트'는 같은 의미로 사용됩니다. 두 경우 모두 이더리움 네트워크 참여자가 실행하는 소프트웨어를 의미합니다. 이 소프트웨어는 블록 데이터를 읽고, 새로운 블록이 체인에 추가될 때 업데이트를 수신하고, 새로운 트랜잭션을 브로드캐스트하는 등 다양한 작업을 수행할 수 있습니다. 기술적으로, 클라이언트는 소프트웨어이고, 노드는 소프트웨어를 실행하는 컴퓨터입니다. + +[이더리움 클라이언트](/developers/docs/nodes-and-clients/)는 [IPC](https://wikipedia.org/wiki/Inter-process_communication), HTTP 또는 웹소켓으로 연결할 수 있도록 구성할 수 있으므로, Web3.py도 이 구성을 미러링해야 합니다. Web3.py는 이러한 연결 옵션을 공급자(providers)라고 부릅니다. Web3.py 인스턴스를 노드에 연결하려면 세 가지 공급자 중 하나를 선택해야 합니다. + +![web3.py가 IPC를 사용하여 애플리케이션을 이더리움 노드에 연결하는 방법을 보여주는 다이어그램](./web3py-and-nodes.png) + +_이더리움 노드와 Web3.py가 동일한 프로토콜(예: 이 다이어그램의 IPC)을 통해 통신하도록 구성하세요._ + +Web3.py가 제대로 구성되면 블록체인과 상호 작용을 시작할 수 있습니다. 앞으로 나올 내용에 대한 미리보기로 Web3.py 사용 예시 몇 가지를 소개합니다. + +```python +# 블록 데이터 읽기: +w3.eth.get_block('latest') + +# 트랜잭션 전송: +w3.eth.send_transaction({'from': ..., 'to': ..., 'value': ...}) +``` + +## 설치 {#installation} + +이번 연습에서는 Python 인터프리터 내에서만 작업할 것입니다. 디렉터리, 파일, 클래스, 함수 등은 생성하지 않습니다. + +참고: 아래 예제에서 `$`로 시작하는 명령어는 터미널에서 실행되도록 의도된 것입니다. (`$`는 입력하지 마세요. 줄의 시작을 의미할 뿐입니다.) + +먼저, 탐색하기 쉬운 사용자 친화적 환경을 위해 [IPython](https://ipython.org/)을 설치하세요. IPython은 다른 기능들 중에서도 탭 완성 기능을 제공하여 Web3.py 내에서 무엇이 가능한지 훨씬 쉽게 확인할 수 있도록 해줍니다. + +```bash +pip install ipython +``` + +Web3.py는 `web3`라는 이름으로 배포됩니다. 다음과 같이 설치하세요. + +```bash +pip install web3 +``` + +한 가지 더 말씀드리자면, 나중에 블록체인을 시뮬레이션할 건데, 몇 가지 의존성이 더 필요합니다. 다음을 통해 설치할 수 있습니다. + +```bash +pip install 'web3[tester]' +``` + +이제 모든 준비가 끝났습니다! + +참고: `web3[tester]` 패키지는 Python 3.10.xx 버전까지 작동합니다. + +## 샌드박스 실행하기 {#spin-up-a-sandbox} + +터미널에서 `ipython`을 실행하여 새로운 Python 환경을 엽니다. 이는 `python`을 실행하는 것과 비슷하지만, 더 많은 부가 기능을 제공합니다. + +```bash +ipython +``` + +실행 중인 Python 및 IPython 버전에 대한 정보가 출력된 후, 입력을 기다리는 프롬프트가 표시됩니다. + +```python +In [1]: +``` + +지금 대화형 Python 셸을 보고 계십니다. 기본적으로, 마음껏 테스트해볼 수 있는 샌드박스입니다. 여기까지 오셨다면 이제 Web3.py를 가져올 차례입니다. + +```python +In [1]: from web3 import Web3 +``` + +## Web3 모듈 소개 {#introducing-the-web3-module} + +[Web3](https://web3py.readthedocs.io/en/stable/overview.html#base-api) 모듈은 이더리움으로 가는 관문일 뿐만 아니라 몇 가지 편의 함수를 제공합니다. 몇 가지를 살펴보겠습니다. + +이더리움 애플리케이션에서는 보통 통화 단위를 변환해야 합니다. Web3 모듈은 바로 이 작업을 위한 몇 가지 헬퍼 메서드를 제공합니다. 바로 [from_wei](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.from_wei)와 [to_wei](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_wei)입니다. + + +참고: 컴퓨터는 소수점 연산을 잘 처리하지 못하는 것으로 악명 높습니다. 이 문제를 해결하기 위해 개발자들은 종종 달러 금액을 센트 단위로 저장합니다. 예를 들어, 가격이 $5.99인 품목은 데이터베이스에 599로 저장될 수 있습니다. + +이더로 트랜잭션을 처리할 때도 비슷한 패턴이 사용됩니다. 하지만 이더는 소수점 두 자리 대신 18자리를 가집니다! 이더의 가장 작은 단위는 wei라고 하며, 트랜잭션을 보낼 때 지정하는 값이 바로 이것입니다. + +1 이더 = 1,000,000,000,000,000,000 wei + +1 wei = 0.000000000000000001 이더 + + + +몇 가지 값을 wei와 주고받으며 변환해 보세요. 이더와 wei 사이에는 [많은 단위에 대한 이름이 있다](https://web3py.readthedocs.io/en/stable/troubleshooting.html#how-do-i-convert-currency-denominations)는 점에 유의하세요. 그중 더 잘 알려진 단위 중 하나는 gwei인데, 거래 수수료가 종종 이 단위로 표시되기 때문입니다. + +```python +In [2]: Web3.to_wei(1, 'ether') +Out[2]: 1000000000000000000 + +In [3]: Web3.from_wei(500000000, 'gwei') +Out[3]: Decimal('0.5') +``` + +Web3 모듈의 다른 유틸리티 메서드에는 데이터 형식 변환기(예: [`toHex`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.toHex)), 주소 헬퍼(예: [`isAddress`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.isAddress)), 해시 함수(예: [`keccak`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.keccak))가 포함됩니다. 이들 중 상당수는 시리즈의 뒷부분에서 다룰 것입니다. 사용 가능한 모든 메서드와 속성을 보려면, `Web3.`을 입력하고 IPython의 자동 완성 기능을 활용하세요. 마침표 뒤에 탭 키를 두 번 누르세요. + +## 체인과 소통하기 {#talk-to-the-chain} + +편리한 메서드들도 좋지만, 이제 블록체인으로 넘어가 봅시다. 다음 단계는 이더리움 노드와 통신하도록 Web3.py를 구성하는 것입니다. 여기서는 IPC, HTTP 또는 웹소켓 공급자를 사용할 수 있습니다. + +우리는 이 경로를 따르지는 않겠지만, HTTP 공급자를 사용하는 전체 워크플로의 예는 다음과 같을 수 있습니다. + +- 이더리움 노드, 예: [Geth](https://geth.ethereum.org/)를 다운로드합니다. +- 한 터미널 창에서 Geth를 시작하고 네트워크와 동기화될 때까지 기다립니다. 기본 HTTP 포트는 `8545`이지만, 구성할 수 있습니다. +- Web3.py에 `localhost:8545`에서 HTTP를 통해 노드에 연결하도록 지시합니다. + `w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))` +- `w3` 인스턴스를 사용하여 노드와 상호 작용합니다. + +이것이 '실제' 방법 중 하나이긴 하지만, 동기화 과정은 몇 시간이 걸리며 단순히 개발 환경을 원하는 경우에는 불필요합니다. Web3.py는 이러한 목적을 위해 네 번째 공급자인 EthereumTesterProvider를 제공합니다. 이 테스터 공급자는 완화된 권한과 테스트용 가짜 통화를 가진 시뮬레이션된 이더리움 노드에 연결됩니다. + +![EthereumTesterProvider가 web3.py 애플리케이션을 시뮬레이션된 이더리움 노드에 연결하는 것을 보여주는 다이어그램](./ethereumtesterprovider.png) + +_EthereumTesterProvider는 시뮬레이션된 노드에 연결되며 빠른 개발 환경에 유용합니다._ + +그 시뮬레이션된 노드는 [eth-tester](https://github.com/ethereum/eth-tester)라고 불리며, `pip install web3[tester]` 명령의 일부로 설치했습니다. 이 테스터 공급자를 사용하도록 Web3.py를 구성하는 것은 다음과 같이 간단합니다. + +```python +In [4]: w3 = Web3(Web3.EthereumTesterProvider()) +``` + +이제 체인을 서핑할 준비가 되었습니다! 사람들이 그렇게 말하지는 않아요. 방금 제가 지어낸 말입니다. 간단히 둘러봅시다. + +## 간단한 둘러보기 {#the-quick-tour} + +가장 먼저, 간단한 확인부터 해보겠습니다. + +```python +In [5]: w3.is_connected() +Out[5]: True +``` + +테스터 공급자를 사용하고 있기 때문에 이것이 그다지 가치 있는 테스트는 아니지만, 만약 실패한다면 `w3` 변수를 인스턴스화할 때 무언가를 잘못 입력했을 가능성이 있습니다. 내부 괄호, 즉 `Web3.EthereumTesterProvider()`를 포함했는지 다시 확인하세요. + +## 둘러보기 #1: [계정](/developers/docs/accounts/) {#tour-stop-1-accounts} + +편의를 위해, 테스터 공급자는 몇 개의 계정을 생성하고 테스트 이더를 미리 채워 넣었습니다. + +먼저, 해당 계정들의 목록을 살펴보겠습니다. + +```python +In [6]: w3.eth.accounts +Out[6]: ['0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf', + '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF', + '0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69', ...] +``` + +이 명령을 실행하면 `0x`로 시작하는 10개의 문자열 목록이 표시됩니다. 각각은 공개 주소이며, 어떤 면에서는 은행 계좌의 계좌 번호와 유사합니다. 이더를 보내려는 사람에게 이 주소를 제공하면 됩니다. + +언급했듯이, 테스터 공급자는 이러한 각 계정에 일부 테스트 이더를 미리 로드해 두었습니다. 첫 번째 계정에 얼마가 있는지 알아봅시다. + +```python +In [7]: w3.eth.get_balance(w3.eth.accounts[0]) +Out[7]: 1000000000000000000000000 +``` + +0이 정말 많네요! 가짜 은행으로 달려가기 전에, 앞에서 배운 통화 단위에 대한 교훈을 떠올려 보세요. 이더 값은 가장 작은 단위인 wei로 표시됩니다. 이 값을 이더로 변환해 보세요. + +```python +In [8]: w3.from_wei(1000000000000000000000000, 'ether') +Out[8]: Decimal('1000000') +``` + +백만 테스트 이더, 여전히 나쁘지 않네요. + +## 둘러보기 #2: 블록 데이터 {#tour-stop-2-block-data} + +이 시뮬레이션된 블록체인의 상태를 살짝 들여다봅시다. + +```python +In [9]: w3.eth.get_block('latest') +Out[9]: AttributeDict({ + 'number': 0, + 'hash': HexBytes('0x9469878...'), + 'parentHash': HexBytes('0x0000000...'), + ... + 'transactions': [] +}) +``` + +블록에 대해 많은 정보가 반환되지만, 여기서 몇 가지만 짚고 넘어가겠습니다. + +- 블록 번호는 0입니다. 테스터 제공자를 얼마나 오래 전에 구성했는지는 중요하지 않습니다. 약 12초마다 새 블록을 추가하는 실제 이더리움 네트워크와 달리, 이 시뮬레이션은 어떤 작업을 지시할 때까지 기다립니다. +- `transactions`는 빈 목록입니다. 같은 이유로, 우리는 아직 아무것도 하지 않았습니다. 이 첫 번째 블록은 체인을 시작하기 위한 빈 블록입니다. +- `parentHash`가 단지 빈 바이트들의 묶음이라는 점을 주목하세요. 이는 이 블록이 체인의 첫 번째 블록, 즉 제네시스 블록임을 의미합니다. + +## 둘러보기 #3: [트랜잭션](/developers/docs/transactions/) {#tour-stop-3-transactions} + +보류 중인 트랜잭션이 있을 때까지 블록 0에 갇혀 있으니, 하나 만들어 봅시다. 한 계정에서 다른 계정으로 몇 개의 테스트 이더를 보내세요. + +```python +In [10]: tx_hash = w3.eth.send_transaction({ + 'from': w3.eth.accounts[0], + 'to': w3.eth.accounts[1], + 'value': w3.to_wei(3, 'ether'), + 'gas': 21000 +}) +``` + +일반적으로 이 시점에서 트랜잭션이 새 블록에 포함될 때까지 몇 초간 기다려야 합니다. 전체 과정은 다음과 같습니다. + +1. 트랜잭션을 제출하고 트랜잭션 해시를 보관합니다. 트랜잭션을 포함하는 블록이 생성되고 브로드캐스트될 때까지 트랜잭션은 '보류 중(pending)' 상태입니다. + `tx_hash = w3.eth.send_transaction({ … })` +2. 트랜잭션이 블록에 포함될 때까지 기다립니다: + `w3.eth.wait_for_transaction_receipt(tx_hash)` +3. 애플리케이션 로직을 계속 진행합니다. 성공적인 트랜잭션을 보려면: + `w3.eth.get_transaction(tx_hash)` + +우리의 시뮬레이션 환경은 트랜잭션을 즉시 새 블록에 추가하므로, 트랜잭션을 바로 볼 수 있습니다. + +```python +In [11]: w3.eth.get_transaction(tx_hash) +Out[11]: AttributeDict({ + 'hash': HexBytes('0x15e9fb95dc39...'), + 'blockNumber': 1, + 'transactionIndex': 0, + 'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf', + 'to': '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF', + 'value': 3000000000000000000, + ... +}) +``` + +여기서 익숙한 세부 정보들을 볼 수 있습니다. `from`, `to`, `value` 필드는 `send_transaction` 호출의 입력값과 일치해야 합니다. 또 다른 안심할 수 있는 점은 이 트랜잭션이 블록 번호 1 내의 첫 번째 트랜잭션(`'transactionIndex': 0`)으로 포함되었다는 것입니다. + +관련된 두 계정의 잔액을 확인하여 이 거래의 성공 여부를 쉽게 확인할 수도 있습니다. 3 이더가 한 계정에서 다른 계정으로 이동했어야 합니다. + +```python +In [12]: w3.eth.get_balance(w3.eth.accounts[0]) +Out[12]: 999996999979000000000000 + +In [13]: w3.eth.get_balance(w3.eth.accounts[1]) +Out[13]: 1000003000000000000000000 +``` + +두 번째 것은 좋아 보입니다! 잔액이 1,000,000 이더에서 1,000,003 이더로 증가했습니다. 그런데 첫 번째 계정은 어떻게 된 걸까요? 3 이더보다 약간 더 많이 잃은 것처럼 보입니다. 아쉽게도, 인생에 공짜는 없으며 이더리움 퍼블릭 네트워크를 사용하려면 동료들의 지원 역할에 대해 보상해야 합니다. 트랜잭션을 제출한 계정에서 소액의 거래 수수료가 차감되었습니다. 이 수수료는 소모된 가스량(ETH 전송의 경우 21,000 가스 단위)에 네트워크 활동량에 따라 달라지는 기본 수수료를 곱한 값과, 트랜잭션을 블록에 포함하는 검증자에게 가는 팁을 더한 금액입니다. + +[가스](/developers/docs/gas/#post-london)에 대해 더 알아보기 + +참고: 퍼블릭 네트워크에서 거래 수수료는 네트워크 수요와 트랜잭션 처리 속도에 따라 변동됩니다. 수수료 계산 방식에 대한 자세한 내용이 궁금하다면, 이전에 작성한 '트랜잭션이 블록에 포함되는 방법'에 대한 게시물을 참조하세요. + +## 그리고 숨 고르기 {#and-breathe} + +꽤 오랫동안 달려왔으니, 이쯤에서 잠시 쉬어가는 것이 좋겠습니다. 토끼굴은 계속 이어지며, 이 시리즈의 2부에서 계속 탐험할 것입니다. 앞으로 다룰 개념: 실제 노드에 연결하기, 스마트 계약, 그리고 토큰. 궁금한 점이 있으신가요? 알려주세요! 여러분의 피드백은 앞으로의 방향에 영향을 미칠 것입니다. 요청은 [트위터](https://twitter.com/wolovim)를 통해 환영합니다. diff --git a/public/content/translations/ko/developers/tutorials/ai-trading-agent/index.md b/public/content/translations/ko/developers/tutorials/ai-trading-agent/index.md new file mode 100644 index 00000000000..bf4d7dcb6c7 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/ai-trading-agent/index.md @@ -0,0 +1,980 @@ +--- +title: "이더리움에서 자신만의 AI 트레이딩 에이전트 만들기" +description: "이 튜토리얼에서는 간단한 AI 트레이딩 에이전트를 만드는 방법을 배웁니다. 이 에이전트는 블록체인에서 정보를 읽고, 해당 정보를 기반으로 LLM에 추천을 요청하고, LLM이 추천하는 교환을 수행한 후, 대기하고 반복합니다." +author: Ori Pomerantz +tags: [ "AI", "트레이딩", "에이전트", "python" ] +skill: intermediate +published: 2026-02-13 +lang: ko +sidebarDepth: 3 +--- + +이 튜토리얼에서는 간단한 AI 트레이딩 에이전트를 구축하는 방법을 배웁니다. 이 에이전트는 다음 단계를 사용하여 작동합니다. + +1. 토큰의 현재 및 과거 가격과 기타 잠재적으로 관련 있는 정보를 읽습니다. +2. 이 정보와 함께 그 관련성을 설명하는 배경 정보로 쿼리를 작성합니다. +3. 쿼리를 제출하고 예상 가격을 받습니다. +4. 추천에 따라 교환합니다. +5. 대기하고 반복합니다. + +이 에이전트는 정보를 읽고, 사용 가능한 답변을 생성하는 쿼리로 변환하고, 해당 답변을 사용하는 방법을 보여줍니다. 이 모든 단계는 AI 에이전트에 필요합니다. 이 에이전트는 Python으로 구현되었습니다. Python이 AI에서 가장 일반적으로 사용되는 언어이기 때문입니다. + +## 왜 이렇게 해야 할까요? {#why-do-this} + +자동화된 트레이딩 에이전트는 개발자가 트레이딩 전략을 선택하고 실행할 수 있도록 합니다. [AI 에이전트](/ai-agents)는 개발자가 사용을 고려조차 하지 않았던 정보와 알고리즘을 잠재적으로 사용하여 더 복잡하고 동적인 트레이딩 전략을 가능하게 합니다. + +## 도구 {#tools} + +이 튜토리얼은 시세 조회 및 트레이딩을 위해 [Python](https://www.python.org/), [Web3 라이브러리](https://web3py.readthedocs.io/en/stable/), [Uniswap v3](https://github.com/Uniswap/v3-periphery)를 사용합니다. + +### 왜 Python인가요? {#python} + +AI에 가장 널리 사용되는 언어는 [Python](https://www.python.org/)이므로 여기서도 사용합니다. Python을 모르더라도 걱정하지 마세요. 언어가 매우 명확하며, 무엇을 하는지 정확히 설명해 드리겠습니다. + +[Web3 라이브러리](https://web3py.readthedocs.io/en/stable/)는 가장 일반적인 Python 이더리움 API입니다. 사용하기가 매우 쉽습니다. + +### 블록체인에서 트레이딩하기 {#trading-on-blockchain} + +이더리움에서 토큰을 교환할 수 있는 [많은 분산형 거래소(DEX)](/apps/categories/defi/)가 있습니다. 하지만 [차익거래](/developers/docs/smart-contracts/composability/#better-user-experience) 때문에 환율은 비슷한 경향이 있습니다. + +[Uniswap](https://app.uniswap.org/)은 널리 사용되는 DEX이며, 시세 조회(토큰 상대 가치 확인)와 교환 모두에 사용할 수 있습니다. + +### OpenAI {#openai} + +대규모 언어 모델의 경우, [OpenAI](https://openai.com/)로 시작하기로 했습니다. 이 튜토리얼의 애플리케이션을 실행하려면 API 액세스 비용을 지불해야 합니다. 최소 결제 금액인 5달러는 충분하고도 남습니다. + +## 단계별 개발 {#step-by-step} + +개발을 단순화하기 위해 단계별로 진행합니다. 각 단계는 GitHub의 브랜치입니다. + +### 시작하기 {#getting-started} + +UNIX 또는 Linux([WSL](https://learn.microsoft.com/en-us/windows/wsl/install) 포함)에서 시작하는 단계가 있습니다. + +1. 아직 설치하지 않았다면 [Python](https://www.python.org/downloads/)을 다운로드하여 설치하세요. + +2. GitHub 리포지토리를 복제합니다. + + ```sh + git clone https://github.com/qbzzt/260215-ai-agent.git -b 01-getting-started + cd 260215-ai-agent + ``` + +3. [`uv`](https://docs.astral.sh/uv/getting-started/installation/)를 설치합니다. 시스템에 따라 명령어가 다를 수 있습니다. + + ```sh + pipx install uv + ``` + +4. 라이브러리를 다운로드합니다. + + ```sh + uv sync + ``` + +5. 가상 환경을 활성화합니다. + + ```sh + source .venv/bin/activate + ``` + +6. Python과 Web3가 올바르게 작동하는지 확인하려면 `python3`을 실행하고 이 프로그램을 제공하세요. `>>>` 프롬프트에 입력할 수 있으며 파일을 만들 필요는 없습니다. + + ```python + from web3 import Web3 + MAINNET_URL = "https://eth.drpc.org" + w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) + w3.eth.block_number + quit() + ``` + +### 블록체인에서 읽기 {#read-blockchain} + +다음 단계는 블록체인에서 읽는 것입니다. 그렇게 하려면 `02-read-quote` 브랜치로 변경한 다음 `uv`를 사용하여 프로그램을 실행해야 합니다. + +```sh +git checkout 02-read-quote +uv run agent.py +``` + +타임스탬프, 가격, 자산(현재는 항상 `WETH/USDC`)을 포함하는 `Quote` 객체 목록을 받게 됩니다. + +다음은 한 줄씩 설명한 것입니다. + +```python +from web3 import Web3 +from web3.contract import Contract +from decimal import Decimal, ROUND_HALF_UP +from dataclasses import dataclass +from datetime import datetime, timezone +from pprint import pprint +import time +import functools +import sys +``` + +필요한 라이브러리를 가져옵니다. 사용 시 아래에 설명되어 있습니다. + +```python +print = functools.partial(print, flush=True) +``` + +Python의 `print`를 항상 출력을 즉시 플러시하는 버전으로 바꿉니다. 상태 업데이트나 디버깅 출력을 기다릴 필요가 없으므로 장기 실행 스크립트에서 유용합니다. + +```python +MAINNET_URL = "https://eth.drpc.org" +``` + +메인넷에 접속하기 위한 URL입니다. [서비스형 노드](/developers/docs/nodes-and-clients/nodes-as-a-service/)에서 얻거나 [Chainlist](https://chainlist.org/chain/1)에 광고된 것 중 하나를 사용할 수 있습니다. + +```python +BLOCK_TIME_SECONDS = 12 +MINUTE_BLOCKS = int(60 / BLOCK_TIME_SECONDS) +HOUR_BLOCKS = MINUTE_BLOCKS * 60 +DAY_BLOCKS = HOUR_BLOCKS * 24 +``` + +이더리움 메인넷 블록은 일반적으로 12초마다 생성되므로, 이는 특정 기간에 생성될 것으로 예상되는 블록 수입니다. 이것은 정확한 수치가 아닙니다. [블록 제안자](/developers/docs/consensus-mechanisms/pos/block-proposal/)가 다운되면 해당 블록은 건너뛰어지고 다음 블록까지의 시간은 24초가 됩니다. 타임스탬프에 대한 정확한 블록을 얻으려면 [이진 검색](https://en.wikipedia.org/wiki/Binary_search)을 사용합니다. 하지만, 우리의 목적에는 이 정도로도 충분합니다. 미래를 예측하는 것은 정확한 과학이 아닙니다. + +```python +CYCLE_BLOCKS = DAY_BLOCKS +``` + +주기의 크기입니다. 주기당 한 번씩 시세를 검토하고 다음 주기 말의 가치를 추정합니다. + +```python +# 읽고 있는 풀의 주소 +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +``` + +시세 값은 [`0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`](https://eth.blockscout.com/address/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640?tab=read_write_contract) 주소의 Uniswap 3 USDC/WETH 풀에서 가져옵니다. 이 주소는 이미 체크섬 형식이지만, 코드 재사용성을 높이려면 [`Web3.to_checksum_address`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_checksum_address)를 사용하는 것이 좋습니다. + +```python +POOL_ABI = [ + { "name": "slot0", ... }, + { "name": "token0", ... }, + { "name": "token1", ... }, +] + +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... } +] +``` + +이는 우리가 연결해야 하는 두 계약의 [ABI](https://docs.soliditylang.org/en/latest/abi-spec.html)입니다. 코드를 간결하게 유지하기 위해 호출해야 하는 함수만 포함합니다. + +```python +w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) +``` + +[`Web3`](https://web3py.readthedocs.io/en/stable/quickstart.html#remote-providers) 라이브러리를 시작하고 이더리움 노드에 연결합니다. + +```python +@dataclass(frozen=True) +class ERC20Token: + address: str + symbol: str + decimals: int + contract: Contract +``` + +이것은 Python에서 데이터 클래스를 만드는 한 가지 방법입니다. [`Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) 데이터 유형은 계약에 연결하는 데 사용됩니다. `(frozen=True)`에 주목하세요. Python에서 [불리언](https://en.wikipedia.org/wiki/Boolean_data_type)은 대문자로 시작하는 `True` 또는 `False`로 정의됩니다. 이 데이터 클래스는 `frozen`이며, 필드를 수정할 수 없음을 의미합니다. + +들여쓰기에 주목하세요. [C 파생 언어](https://en.wikipedia.org/wiki/List_of_C-family_programming_languages)와 달리 Python은 들여쓰기를 사용하여 블록을 나타냅니다. Python 인터프리터는 다음 정의가 데이터 클래스 필드와 동일한 들여쓰기에서 시작하지 않기 때문에 이 데이터 클래스의 일부가 아님을 압니다. + +```python +@dataclass(frozen=True) +class PoolInfo: + address: str + token0: ERC20Token + token1: ERC20Token + contract: Contract + asset: str + decimal_factor: Decimal = 1 +``` + +[`Decimal`](https://docs.python.org/3/library/decimal.html) 유형은 십진 분수를 정확하게 처리하는 데 사용됩니다. + +```python + def get_price(self, block: int) -> Decimal: +``` + +이것이 Python에서 함수를 정의하는 방법입니다. 이 정의는 여전히 `PoolInfo`의 일부임을 보여주기 위해 들여쓰기됩니다. + +데이터 클래스의 일부인 함수에서 첫 번째 매개변수는 항상 여기에서 호출된 데이터 클래스 인스턴스인 `self`입니다. 여기에는 블록 번호라는 또 다른 매개변수가 있습니다. + +```python + assert block <= w3.eth.block_number, "블록이 미래에 있습니다" +``` + +미래를 읽을 수 있다면 트레이딩에 AI가 필요하지 않을 것입니다. + +```python + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) +``` + +Web3에서 EVM의 함수를 호출하는 구문은 다음과 같습니다. `.functions."().call()`. 매개변수는 EVM 함수의 매개변수(있는 경우, 여기서는 없음)이거나 블록체인 동작을 수정하기 위한 [명명된 매개변수](https://en.wikipedia.org/wiki/Named_parameter)일 수 있습니다. 여기서는 `block_identifier`를 사용하여 실행하려는 [블록 번호](/developers/docs/apis/json-rpc/#default-block)를 지정합니다. + +결과는 [배열 형식의 이 구조체](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol#L56-L72)입니다. 첫 번째 값은 두 토큰 간의 환율 함수입니다. + +```python + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 +``` + +온체인 계산을 줄이기 위해 Uniswap v3는 실제 환율 요소가 아닌 제곱근을 저장합니다. EVM은 부동 소수점 연산이나 분수를 지원하지 않으므로 실제 값 대신 응답은 price296입니다. + +```python + # (토큰 0당 토큰 1) + return 1/(raw_price * self.decimal_factor) +``` + +우리가 얻는 원시 가격은 각 `token1`에 대해 얻는 `token0`의 수입니다. 우리 풀에서 `token0`은 USDC(미국 달러와 동일한 가치를 지닌 스테이블 코인)이고 `token1`은 [WETH](https://opensea.io/learn/blockchain/what-is-weth)입니다. 우리가 정말로 원하는 값은 WETH당 달러 수이지 그 역수가 아닙니다. + +소수점 계수는 두 토큰의 [소수점 계수](https://docs.openzeppelin.com/contracts/4.x/erc20#a-note-on-decimals) 간의 비율입니다. + +```python +@dataclass(frozen=True) +class Quote: + timestamp: str + price: Decimal + asset: str +``` + +이 데이터 클래스는 시세, 즉 특정 시점의 특정 자산 가격을 나타냅니다. 이 시점에서는 단일 풀을 사용하므로 단일 자산만 있으므로 `asset` 필드는 관련이 없습니다. 하지만 나중에 더 많은 자산을 추가할 것입니다. + +```python +def read_token(address: str) -> ERC20Token: + token = w3.eth.contract(address=address, abi=ERC20_ABI) + symbol = token.functions.symbol().call() + decimals = token.functions.decimals().call() + + return ERC20Token( + address=address, + symbol=symbol, + decimals=decimals, + contract=token + ) +``` + +이 함수는 주소를 받아 해당 주소에 있는 토큰 계약에 대한 정보를 반환합니다. 새로운 [Web3 `Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html)를 만들려면 `w3.eth.contract`에 주소와 ABI를 제공합니다. + +```python +def read_pool(address: str) -> PoolInfo: + pool_contract = w3.eth.contract(address=address, abi=POOL_ABI) + token0Address = pool_contract.functions.token0().call() + token1Address = pool_contract.functions.token1().call() + token0 = read_token(token0Address) + token1 = read_token(token1Address) + + return PoolInfo( + address=address, + asset=f"{token1.symbol}/{token0.symbol}", + token0=token0, + token1=token1, + contract=pool_contract, + decimal_factor=Decimal(10) ** Decimal(token0.decimals - token1.decimals) + ) +``` + +이 함수는 [특정 풀](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol)에 대해 필요한 모든 것을 반환합니다. `f""` 구문은 [포맷된 문자열](https://docs.python.org/3/reference/lexical_analysis.html#f-strings)입니다. + +```python +def get_quote(pool: PoolInfo, block_number: int = None) -> Quote: +``` + +`Quote` 객체를 가져옵니다. `block_number`의 기본값은 `None`(값 없음)입니다. + +```python + if block_number is None: + block_number = w3.eth.block_number +``` + +블록 번호가 지정되지 않은 경우 최신 블록 번호인 `w3.eth.block_number`를 사용합니다. 이것은 [`if` 문](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement)의 구문입니다. + +기본값을 `w3.eth.block_number`로 설정하는 것이 더 나아 보일 수 있지만, 함수가 정의된 시점의 블록 번호가 되기 때문에 잘 작동하지 않습니다. 장기 실행 에이전트에서는 이것이 문제가 될 수 있습니다. + +```python + block = w3.eth.get_block(block_number) + price = pool.get_price(block_number) + return Quote( + timestamp=datetime.fromtimestamp(block.timestamp, timezone.utc).isoformat(), + price=price.quantize(Decimal("0.01")), + asset=pool.asset + ) +``` + +[`datetime` 라이브러리](https://docs.python.org/3/library/datetime.html)를 사용하여 사람과 대규모 언어 모델(LLM)이 읽을 수 있는 형식으로 포맷합니다. [`Decimal.quantize`](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize)를 사용하여 값을 소수점 이하 두 자리로 반올림합니다. + +```python +def get_quotes(pool: PoolInfo, start_block: int, end_block: int, step: int) -> list[Quote]: +``` + +Python에서는 `list[]`를 사용하여 특정 유형만 포함할 수 있는 [목록](https://docs.python.org/3/library/stdtypes.html#typesseq-list)을 정의합니다. + +```python + quotes = [] + for block in range(start_block, end_block + 1, step): +``` + +Python에서 [`for` 루프](https://docs.python.org/3/tutorial/controlflow.html#for-statements)는 일반적으로 목록을 반복합니다. 시세를 찾을 블록 번호 목록은 [`range`](https://docs.python.org/3/library/stdtypes.html#range)에서 가져옵니다. + +```python + quote = get_quote(pool, block) + quotes.append(quote) + return quotes +``` + +각 블록 번호에 대해 `Quote` 객체를 가져와 `quotes` 목록에 추가합니다. 그런 다음 해당 목록을 반환합니다. + +```python +pool = read_pool(WETHUSDC_ADDRESS) +quotes = get_quotes( + pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) + +pprint(quotes) +``` + +이것은 스크립트의 메인 코드입니다. 풀 정보를 읽고, 12개의 시세를 가져와 [`pprint`](https://docs.python.org/3/library/pprint.html#pprint.pprint)로 출력합니다. + +### 프롬프트 만들기 {#prompt} + +다음으로, 이 시세 목록을 LLM용 프롬프트로 변환하고 예상 미래 가치를 얻어야 합니다. + +```sh +git checkout 03-create-prompt +uv run agent.py +``` + +이제 출력은 다음과 유사한 LLM에 대한 프롬프트가 됩니다. + +``` +Given these quotes: +Asset: WETH/USDC + 2026-01-20T16:34 3016.21 + . + . + . + 2026-02-01T17:49 2299.10 + +Asset: WBTC/WETH + 2026-01-20T16:34 29.84 + . + . + . + 2026-02-01T17:50 33.46 + + +What would you expect the value for WETH/USDC to be at time 2026-02-02T17:56? + +Provide your answer as a single number rounded to two decimal places, +without any other text. +``` + +여기에 `WETH/USDC`와 `WBTC/WETH`라는 두 자산에 대한 시세가 있다는 점에 주목하세요. 다른 자산의 시세를 추가하면 예측 정확도가 향상될 수 있습니다. + +#### 프롬프트는 어떻게 생겼나요? {#prompt-explanation} + +이 프롬프트에는 LLM 프롬프트에서 흔히 볼 수 있는 세 가지 섹션이 포함되어 있습니다. + +1. 정보입니다. LLM은 훈련을 통해 많은 정보를 가지고 있지만, 보통 최신 정보는 가지고 있지 않습니다. 이것이 바로 여기서 최신 시세를 검색해야 하는 이유입니다. 프롬프트에 정보를 추가하는 것을 [검색 증강 생성(RAG)](https://en.wikipedia.org/wiki/Retrieval-augmented_generation)이라고 합니다. + +2. 실제 질문입니다. 이것이 우리가 알고 싶은 것입니다. + +3. 출력 형식 지정 지침입니다. 일반적으로 LLM은 추정치와 그에 도달한 방법에 대한 설명을 제공합니다. 이는 사람에게는 더 좋지만, 컴퓨터 프로그램에는 결론만 필요합니다. + +#### 코드 설명 {#prompt-code} + +다음은 새로운 코드입니다. + +```python +from datetime import datetime, timezone, timedelta +``` + +추정치를 원하는 시간을 LLM에 제공해야 합니다. 미래의 "n분/시간/일" 후의 시간을 얻으려면 [`timedelta` 클래스](https://docs.python.org/3/library/datetime.html#datetime.timedelta)를 사용합니다. + +```python +# 읽고 있는 풀의 주소 +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +WETHWBTC_ADDRESS = Web3.to_checksum_address("0xCBCdF9626bC03E24f779434178A73a0B4bad62eD") +``` + +읽어야 할 풀이 두 개 있습니다. + +```python +@dataclass(frozen=True) +class PoolInfo: + . + . + . + reverse: bool = False + + def get_price(self, block: int) -> Decimal: + assert block <= w3.eth.block_number, "Block is in the future" + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 # (token1 per token0) + if self.reverse: + return 1/(raw_price * self.decimal_factor) + else: + return raw_price * self.decimal_factor +``` + +WETH/USDC 풀에서 우리는 `token1`(WETH) 하나를 사기 위해 `token0`(USD 코인)이 몇 개 필요한지 알고 싶습니다. WETH/WBTC 풀에서 우리는 `token0`(WBTC, 래핑된 비트코인) 하나를 사기 위해 `token1`(WETH)이 몇 개 필요한지 알고 싶습니다. 풀의 비율을 역전시켜야 하는지 추적해야 합니다. + +```python +def read_pool(address: str, reverse: bool = False) -> PoolInfo: + . + . + . + + return PoolInfo( + . + . + . + + asset= f"{token1.symbol}/{token0.symbol}" if reverse else f"{token0.symbol}/{token1.symbol}", + reverse=reverse + ) +``` + +풀을 역전시켜야 하는지 알기 위해 `read_pool`에 입력으로 전달해야 합니다. 또한, 자산 기호를 올바르게 설정해야 합니다. + +` if else ` 구문은 Python의 [삼항 조건 연산자](https://en.wikipedia.org/wiki/Ternary_conditional_operator)에 해당하며, C 파생 언어에서는 ` ? : `가 됩니다. + +```python +def format_quotes(quotes: list[Quote]) -> str: + result = f"Asset: {quotes[0].asset}\n" + for quote in quotes: + result += f"\t{quote.timestamp[0:16]} {quote.price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)}\n" + return result +``` + +이 함수는 `Quote` 객체 목록의 형식을 지정하는 문자열을 만듭니다. 이때 모든 객체가 동일한 자산에 적용된다고 가정합니다. + +```python +def make_prompt(quotes: list[list[Quote]], expected_time: str, asset: str) -> str: + return f""" +``` + +Python에서 [여러 줄 문자열 리터럴](https://www.w3schools.com/python/gloss_python_multi_line_strings.asp)은 `"""` ....로 작성됩니다. `"""`. + +```python +Given these quotes: +{ + functools.reduce(lambda acc, q: acc + '\n' + q, + map(lambda q: format_quotes(q), quotes)) +} +``` + +여기서는 [맵리듀스](https://en.wikipedia.org/wiki/MapReduce) 패턴을 사용하여 각 시세 목록에 대해 `format_quotes`로 문자열을 생성한 다음, 이를 단일 문자열로 축소하여 프롬프트에 사용합니다. + +```python +What would you expect the value for {asset} to be at time {expected_time}? + +Provide your answer as a single number rounded to two decimal places, +without any other text. + """ +``` + +프롬프트의 나머지 부분은 예상대로입니다. + +```python +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +두 풀을 검토하고 양쪽에서 시세를 얻습니다. + +```python +future_time = (datetime.now(timezone.utc) + timedelta(days=1)).isoformat()[0:16] + +print(make_prompt(wethusdc_quotes + wethwbtc_quotes, future_time, wethusdc_pool.asset)) +``` + +추정치를 원하는 미래 시점을 결정하고 프롬프트를 만듭니다. + +### LLM과 인터페이스하기 {#interface-llm} + +다음으로, 실제 LLM에 프롬프트를 보내고 예상 미래 가치를 받습니다. 이 프로그램은 OpenAI를 사용하여 작성되었으므로 다른 제공업체를 사용하려면 수정해야 합니다. + +1. [OpenAI 계정](https://auth.openai.com/create-account) 만들기 + +2. [계정 자금 조달](https://platform.openai.com/settings/organization/billing/overview) — 이 글을 쓰는 시점의 최소 금액은 5달러입니다. + +3. [API 키 만들기](https://platform.openai.com/settings/organization/api-keys) + +4. 명령줄에서 프로그램이 사용할 수 있도록 API 키를 내보냅니다. + + ```sh + export OPENAI_API_KEY=sk- + ``` + +5. 에이전트 체크아웃 및 실행 + + ```sh + git checkout 04-interface-llm + uv run agent.py + ``` + +다음은 새로운 코드입니다. + +```python +from openai import OpenAI + +open_ai = OpenAI() # The client reads the OPENAI_API_KEY environment variable +``` + +OpenAI API를 가져와 인스턴스화합니다. + +```python +response = open_ai.chat.completions.create( + model="gpt-4-turbo", + messages=[ + {"role": "user", "content": prompt} + ], + temperature=0.0, + max_tokens=16, +) +``` + +OpenAI API(`open_ai.chat.completions.create`)를 호출하여 응답을 생성합니다. + +```python +expected_price = Decimal(response.choices[0].message.content.strip()) +current_price = wethusdc_quotes[-1].price + +print ("Current price:", wethusdc_quotes[-1].price) +print(f"In {future_time}, expected price: {expected_price} USD") + +if (expected_price > current_price): + print(f"Buy, I expect the price to go up by {expected_price - current_price} USD") +else: + print(f"Sell, I expect the price to go down by {current_price - expected_price} USD") +``` + +가격을 출력하고 매수 또는 매도 추천을 제공합니다. + +#### 예측 테스트하기 {#testing-the-predictions} + +이제 예측을 생성할 수 있으므로 과거 데이터를 사용하여 유용한 예측을 생성하는지 평가할 수도 있습니다. + +```sh +uv run test-predictor.py +``` + +예상 결과는 다음과 유사합니다. + +``` +Prediction for 2026-01-05T19:50: predicted 3138.93 USD, real 3218.92 USD, error 79.99 USD +Prediction for 2026-01-06T19:56: predicted 3243.39 USD, real 3221.08 USD, error 22.31 USD +Prediction for 2026-01-07T20:02: predicted 3223.24 USD, real 3146.89 USD, error 76.35 USD +Prediction for 2026-01-08T20:11: predicted 3150.47 USD, real 3092.04 USD, error 58.43 USD +. +. +. +Prediction for 2026-01-31T22:33: predicted 2637.73 USD, real 2417.77 USD, error 219.96 USD +Prediction for 2026-02-01T22:41: predicted 2381.70 USD, real 2318.84 USD, error 62.86 USD +Prediction for 2026-02-02T22:49: predicted 2234.91 USD, real 2349.28 USD, error 114.37 USD +Mean prediction error over 29 predictions: 83.87103448275862068965517241 USD +Mean change per recommendation: 4.787931034482758620689655172 USD +Standard variance of changes: 104.42 USD +Profitable days: 51.72% +Losing days: 48.28% +``` + +대부분의 테스터는 에이전트와 동일하지만, 새롭거나 수정된 부분은 다음과 같습니다. + +```python +CYCLES_FOR_TEST = 40 # For the backtest, how many cycles we test over + +# Get lots of quotes +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +우리는 `CYCLES_FOR_TEST`(여기서는 40으로 지정)일 전을 살펴봅니다. + +```python +# Create predictions and check them against real history + +total_error = Decimal(0) +changes = [] +``` + +우리가 관심 있는 오류에는 두 가지 유형이 있습니다. 첫 번째, `total_error`는 예측기가 만든 오류의 합계입니다. + +두 번째, `changes`를 이해하려면 에이전트의 목적을 기억해야 합니다. WETH/USDC 비율(ETH 가격)을 예측하는 것이 아닙니다. 매도 및 매수 추천을 발행하는 것입니다. 현재 가격이 2000달러이고 내일 2010달러를 예측한다면, 실제 결과가 2020달러가 되어 추가 수익을 얻는 것은 상관없습니다. 하지만 2010달러를 예측하고 그 추천에 따라 ETH를 매수했는데 가격이 1990달러로 떨어지면 문제가 됩니다. + +```python +for index in range(0,len(wethusdc_quotes)-CYCLES_BACK): +``` + +전체 기록(예측에 사용된 값과 비교할 실제 값)이 사용 가능한 경우만 볼 수 있습니다. 이는 가장 최신 사례가 `CYCLES_BACK` 전에 시작된 것이어야 함을 의미합니다. + +```python + wethusdc_slice = wethusdc_quotes[index:index+CYCLES_BACK] + wethwbtc_slice = wethwbtc_quotes[index:index+CYCLES_BACK] +``` + +[슬라이스](https://www.w3schools.com/python/ref_func_slice.asp)를 사용하여 에이전트가 사용하는 것과 동일한 수의 샘플을 얻습니다. 여기서부터 다음 세그먼트까지의 코드는 에이전트에 있는 예측을 얻는 코드와 동일합니다. + +```python + predicted_price = Decimal(response.choices[0].message.content.strip()) + real_price = wethusdc_quotes[index+CYCLES_BACK].price + prediction_time_price = wethusdc_quotes[index+CYCLES_BACK-1].price +``` + +예측 가격, 실제 가격, 예측 시점의 가격을 가져옵니다. 추천이 매수인지 매도인지 결정하려면 예측 시점의 가격이 필요합니다. + +```python + error = abs(predicted_price - real_price) + total_error += error + print (f"Prediction for {prediction_time}: predicted {predicted_price} USD, real {real_price} USD, error {error} USD") +``` + +오류를 계산하고 총계에 더합니다. + +```python + recomended_action = 'buy' if predicted_price > prediction_time_price else 'sell' + price_increase = real_price - prediction_time_price + changes.append(price_increase if recomended_action == 'buy' else -price_increase) +``` + +`changes`의 경우, 1ETH를 매수하거나 매도할 때의 금전적 영향을 원합니다. 따라서 먼저 추천을 결정한 다음, 실제 가격이 어떻게 변했는지, 그리고 추천이 수익을 냈는지(양의 변화) 또는 손실을 입혔는지(음의 변화) 평가해야 합니다. + +```python +print (f"Mean prediction error over {len(wethusdc_quotes)-CYCLES_BACK} predictions: {total_error / Decimal(len(wethusdc_quotes)-CYCLES_BACK)} USD") + +length_changes = Decimal(len(changes)) +mean_change = sum(changes, Decimal(0)) / length_changes +print (f"Mean change per recommendation: {mean_change} USD") +var = sum((x - mean_change) ** 2 for x in changes) / length_changes +print (f"Standard variance of changes: {var.sqrt().quantize(Decimal("0.01"))} USD") +``` + +결과를 보고합니다. + +```python +print (f"Profitable days: {len(list(filter(lambda x: x > 0, changes)))/length_changes:.2%}") +print (f"Losing days: {len(list(filter(lambda x: x < 0, changes)))/length_changes:.2%}") +``` + +[`filter`](https://www.w3schools.com/python/ref_func_filter.asp)를 사용하여 수익성 있는 날의 수와 손실이 발생한 날의 수를 셉니다. 결과는 필터 객체이며, 길이를 얻으려면 목록으로 변환해야 합니다. + +### 트랜잭션 제출하기 {#submit-txn} + +이제 실제로 트랜잭션을 제출해야 합니다. 하지만 시스템이 입증되기 전인 이 시점에서는 실제 돈을 쓰고 싶지 않습니다. 대신, 메인넷의 로컬 포크를 만들고 해당 네트워크에서 "교환"할 것입니다. + +다음은 로컬 포크를 만들고 트레이딩을 활성화하는 단계입니다. + +1. [Foundry](https://getfoundry.sh/introduction/installation) 설치 + +2. [`anvil`](https://getfoundry.sh/anvil/overview) 시작 + + ```sh + anvil --fork-url https://eth.drpc.org --block-time 12 + ``` + + `anvil`은 Foundry의 기본 URL인 http://localhost:8545에서 수신 대기하므로 블록체인을 조작하는 데 사용하는 [`cast` 명령](https://getfoundry.sh/cast/overview)에 대한 URL을 지정할 필요가 없습니다. + +3. `anvil`에서 실행할 때 ETH가 있는 10개의 테스트 계정이 있습니다. 첫 번째 계정에 대한 환경 변수를 설정합니다. + + ```sh + PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ADDRESS=`cast wallet address $PRIVATE_KEY` + ``` + +4. 사용해야 하는 계약은 다음과 같습니다. [`SwapRouter`](https://github.com/Uniswap/v3-periphery/blob/main/contracts/SwapRouter.sol)는 실제로 교환하는 데 사용하는 Uniswap v3 계약입니다. 풀을 통해 직접 교환할 수도 있지만, 이 방법이 훨씬 쉽습니다. + + 아래 두 변수는 WETH와 USDC 간에 교환하는 데 필요한 Uniswap v3 경로입니다. + + ```sh + WETH_ADDRESS=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + USDC_ADDRESS=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + POOL_ADDRESS=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 + SWAP_ROUTER=0xE592427A0AEce92De3Edee1F18E0157C05861564 + WETH_TO_USDC=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + USDC_TO_WETH=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + ``` + +5. 각 테스트 계정에는 10,000 ETH가 있습니다. WETH 계약을 사용하여 1000 ETH를 래핑하여 트레이딩에 사용할 1000 WETH를 얻습니다. + + ```sh + cast send $WETH_ADDRESS "deposit()" --value 1000ether --private-key $PRIVATE_KEY + ``` + +6. `SwapRouter`를 사용하여 500 WETH를 USD 코인으로 교환합니다. + + ```sh + cast send $WETH_ADDRESS "approve(address,uint256)" $SWAP_ROUTER 500ether --private-key $PRIVATE_KEY + MAXINT=`cast max-int uint256` + cast send $SWAP_ROUTER \ + "exactInput((bytes,address,uint256,uint256,uint256))" \ + "($WETH_TO_USDC,$ADDRESS,$MAXINT,500ether,1000000)" \ + --private-key $PRIVATE_KEY + ``` + + `approve` 호출은 `SwapRouter`가 우리 토큰의 일부를 사용할 수 있도록 허용하는 허용량을 생성합니다. 계약은 이벤트를 모니터링할 수 없으므로 토큰을 `SwapRouter` 계약으로 직접 전송하면 지급되었는지 알 수 없습니다. 대신 `SwapRouter` 계약이 특정 금액을 사용하도록 허용한 다음 `SwapRouter`가 이를 수행합니다. 이는 `SwapRouter`가 호출하는 함수를 통해 수행되므로 성공 여부를 알 수 있습니다. + +7. 두 토큰이 모두 충분한지 확인합니다. + + ```sh + cast call $WETH_ADDRESS "balanceOf(address)" $ADDRESS | cast from-wei + echo `cast call $USDC_ADDRESS "balanceOf(address)" $ADDRESS | cast to-dec`/10^6 | bc + ``` + +이제 WETH와 USD 코인이 있으므로 실제로 에이전트를 실행할 수 있습니다. + +```sh +git checkout 05-trade +uv run agent.py +``` + +출력은 다음과 유사합니다. + +``` +(ai-trading-agent) qbzzt@Ori-Cloudnomics:~/260215-ai-agent$ uv run agent.py +Current price: 1843.16 +In 2026-02-06T23:07, expected price: 1724.41 USD +Account balances before trade: +USDC Balance: 927301.578272 +WETH Balance: 500 +Sell, I expect the price to go down by 118.75 USD +Approve transaction sent: 74e367ddbb407c1aaf567d87aa5863049991b1d2aa092b6b85195d925e2bd41f +Approve transaction mined. +Sell transaction sent: fad1bcf938585c9e90364b26ac7a80eea9efd34c37e5db81e58d7655bcae28bf +Sell transaction mined. +Account balances after trade: +USDC Balance: 929143.797116 +WETH Balance: 499 +``` + +실제로 사용하려면 몇 가지 사소한 변경이 필요합니다. + +- 14행에서 `MAINNET_URL`을 `https://eth.drpc.org`와 같은 실제 액세스 포인트로 변경합니다. +- 28행에서 `PRIVATE_KEY`를 자신의 개인 키로 변경합니다. +- 입증되지 않은 에이전트를 위해 매일 1 ETH를 사거나 팔 수 있을 만큼 부유하지 않다면 29행을 변경하여 `WETH_TRADE_AMOUNT`를 줄이는 것이 좋습니다. + +#### 코드 설명 {#trading-code} + +다음은 새로운 코드입니다. + +```python +SWAP_ROUTER_ADDRESS=Web3.to_checksum_address("0xE592427A0AEce92De3Edee1F18E0157C05861564") +WETH_TO_USDC=bytes.fromhex("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") +USDC_TO_WETH=bytes.fromhex("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +``` + +4단계에서 사용한 것과 동일한 변수입니다. + +```python +WETH_TRADE_AMOUNT=1 +``` + +교환할 금액입니다. + +```python +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... }, + { "name": "balanceOf", ...}, + { "name": "approve", ...} +] +``` + +실제로 교환하려면 `approve` 함수가 필요합니다. 또한 잔액을 전후로 보여주고 싶으므로 `balanceOf`도 필요합니다. + +```python +SWAP_ROUTER_ABI = [ + { "name": "exactInput", ...}, +] +``` + +`SwapRouter` ABI에서는 `exactInput`만 필요합니다. 관련 함수인 `exactOutput`을 사용하여 정확히 1 WETH를 구매할 수 있지만, 단순화를 위해 두 경우 모두 `exactInput`만 사용합니다. + +```python +account = w3.eth.account.from_key(PRIVATE_KEY) +swap_router = w3.eth.contract( + address=SWAP_ROUTER_ADDRESS, + abi=SWAP_ROUTER_ABI +) +``` + +[`계정`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html)과 `SwapRouter` 계약에 대한 Web3 정의입니다. + +```python +def txn_params() -> dict: + return { + "from": account.address, + "value": 0, + "gas": 300000, + "nonce": w3.eth.get_transaction_count(account.address), + } +``` + +트랜잭션 매개변수입니다. [논스](https://en.wikipedia.org/wiki/Cryptographic_nonce)는 매번 변경되어야 하므로 여기에 함수가 필요합니다. + +```python +def approve_token(contract: Contract, amount: int): +``` + +`SwapRouter`에 대한 토큰 허용량을 승인합니다. + +```python + txn = contract.functions.approve(SWAP_ROUTER_ADDRESS, amount).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) +``` + +이것이 Web3에서 트랜잭션을 보내는 방법입니다. 먼저 [`Contract` 객체](https://web3py.readthedocs.io/en/stable/web3.contract.html)를 사용하여 트랜잭션을 빌드합니다. 그런 다음 [`web3.eth.account.sign_transaction`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-contract-transaction)을 사용하여 `PRIVATE_KEY`로 트랜잭션에 서명합니다. 마지막으로 [`w3.eth.send_raw_transaction`](https://web3py.readthedocs.io/en/stable/transactions.html#chapter-2-w3-eth-send-raw-transaction)을 사용하여 트랜잭션을 보냅니다. + +```python + print(f"Approve transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Approve transaction mined.") +``` + +[`w3.eth.wait_for_transaction_receipt`](https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.wait_for_transaction_receipt)는 트랜잭션이 채굴될 때까지 기다립니다. 필요한 경우 영수증을 반환합니다. + +```python +SELL_PARAMS = { + "path": WETH_TO_USDC, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": WETH_TRADE_AMOUNT * 10 ** wethusdc_pool.token1.decimals, + "amountOutMinimum": 0, +} +``` + +WETH를 판매할 때의 매개변수입니다. + +```python +def make_buy_params(quote: Quote) -> dict: + return { + "path": USDC_TO_WETH, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": int(quote.price*WETH_TRADE_AMOUNT) * 10**wethusdc_pool.token0.decimals, + "amountOutMinimum": 0, + } +``` + +`SELL_PARAMS`와 달리 구매 매개변수는 변경될 수 있습니다. 입력 금액은 `quote`에서 사용할 수 있는 1 WETH의 비용입니다. + +```python +def buy(quote: Quote): + buy_params = make_buy_params(quote) + approve_token(wethusdc_pool.token0.contract, buy_params["amountIn"]) + txn = swap_router.functions.exactInput(buy_params).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Buy transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Buy transaction mined.") + + +def sell(): + approve_token(wethusdc_pool.token1.contract, + WETH_TRADE_AMOUNT * 10**wethusdc_pool.token1.decimals) + txn = swap_router.functions.exactInput(SELL_PARAMS).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Sell transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Sell transaction mined.") +``` + +`buy()` 및 `sell()` 함수는 거의 동일합니다. 먼저 `SwapRouter`에 대한 충분한 허용량을 승인한 다음 올바른 경로와 금액으로 호출합니다. + +```python +def balances(): + token0_balance = wethusdc_pool.token0.contract.functions.balanceOf(account.address).call() + token1_balance = wethusdc_pool.token1.contract.functions.balanceOf(account.address).call() + + print(f"{wethusdc_pool.token0.symbol} Balance: {Decimal(token0_balance) / Decimal(10 ** wethusdc_pool.token0.decimals)}") + print(f"{wethusdc_pool.token1.symbol} Balance: {Decimal(token1_balance) / Decimal(10 ** wethusdc_pool.token1.decimals)}") +``` + +두 통화의 사용자 잔액을 보고합니다. + +```python +print("Account balances before trade:") +balances() + +if (expected_price > current_price): + print(f"Buy, I expect the price to go up by {expected_price - current_price} USD") + buy(wethusdc_quotes[-1]) +else: + print(f"Sell, I expect the price to go down by {current_price - expected_price} USD") + sell() + +print("Account balances after trade:") +balances() +``` + +이 에이전트는 현재 한 번만 작동합니다. 하지만 [`crontab`](https://man7.org/linux/man-pages/man1/crontab.1.html)에서 실행하거나 368-400행을 루프로 감싸고 [`time.sleep`](https://docs.python.org/3/library/time.html#time.sleep)를 사용하여 다음 주기가 될 때까지 기다리도록 변경하여 계속 작동하게 할 수 있습니다. + +## 개선 가능성 {#improvements} + +이것은 완전한 프로덕션 버전이 아니며, 단지 기본 사항을 가르치기 위한 예시일 뿐입니다. 다음은 개선을 위한 몇 가지 아이디어입니다. + +### 더 스마트한 트레이딩 {#smart-trading} + +에이전트가 무엇을 할지 결정할 때 무시하는 두 가지 중요한 사실이 있습니다. + +- _예상되는 변화의 크기_. 에이전트는 가격이 하락할 것으로 예상되면 하락의 크기에 관계없이 고정된 양의 `WETH`를 판매합니다. + 사소한 변화는 무시하고 가격이 얼마나 하락할 것으로 예상되는지에 따라 판매하는 것이 더 나을 것입니다. +- _현재 포트폴리오_. 포트폴리오의 10%가 WETH이고 가격이 오를 것이라고 생각한다면 더 많이 사는 것이 합리적일 수 있습니다. 그러나 포트폴리오의 90%가 WETH인 경우, 이미 충분히 노출되어 있으므로 더 이상 구매할 필요가 없습니다. 가격이 하락할 것으로 예상하면 그 반대입니다. + +### 트레이딩 전략을 비밀로 유지하고 싶다면 어떻게 해야 할까요? {#secret} + +AI 공급업체는 LLM에 보내는 쿼리를 볼 수 있으며, 이는 에이전트로 개발한 천재적인 트레이딩 시스템을 노출시킬 수 있습니다. 너무 많은 사람이 사용하는 트레이딩 시스템은 가치가 없습니다. 왜냐하면 사고 싶을 때 너무 많은 사람이 사려고 해서 가격이 오르고, 팔고 싶을 때 너무 많은 사람이 팔려고 해서 가격이 내려가기 때문입니다. + +이 문제를 피하기 위해 [LM-Studio](https://lmstudio.ai/) 등을 사용하여 로컬에서 LLM을 실행할 수 있습니다. + +### AI 봇에서 AI 에이전트로 {#bot-to-agent} + +이것이 [AI 에이전트가 아닌 AI 봇](/ai-agents/#ai-agents-vs-ai-bots)이라는 좋은 주장을 할 수 있습니다. 미리 정의된 정보에 의존하는 비교적 간단한 전략을 구현합니다. 예를 들어, Uniswap v3 풀 목록과 최신 값을 제공하고 어떤 조합이 가장 좋은 예측 가치를 갖는지 물어봄으로써 자기 개선을 가능하게 할 수 있습니다. + +### 슬리피지 보호 {#slippage-protection} + +현재 [슬리피지 보호](https://uniswapv3book.com/milestone_3/slippage-protection.html) 기능이 없습니다. 현재 시세가 2000달러이고 예상 가격이 2100달러라면 에이전트는 매수할 것입니다. 그러나 에이전트가 매수하기 전에 비용이 2200달러로 오르면 더 이상 매수할 의미가 없습니다. + +슬리피지 보호를 구현하려면 [`agent.py`](https://github.com/qbzzt/260215-ai-agent/blob/05-trade/agent.py#L325)의 325행과 334행에 `amountOutMinimum` 값을 지정합니다. + +## 결론 {#conclusion} + +이제 AI 에이전트를 시작하는 데 충분한 정보를 얻으셨기를 바랍니다. 이것은 이 주제에 대한 포괄적인 개요가 아니며, 전체 책이 그에 할애되어 있지만, 시작하기에는 충분합니다. 행운을 빕니다! + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). diff --git a/public/content/translations/ko/developers/tutorials/all-you-can-cache/index.md b/public/content/translations/ko/developers/tutorials/all-you-can-cache/index.md new file mode 100644 index 00000000000..f70ee5fc9d7 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/all-you-can-cache/index.md @@ -0,0 +1,867 @@ +--- +title: "캐시할 수 있는 모든 것" +description: "더 저렴한 롤업 트랜잭션을 위해 캐싱 계약을 생성하고 사용하는 방법을 알아보세요." +author: Ori Pomerantz +tags: [ "레이어 2", "캐싱", "저장 공간" ] +skill: intermediate +published: 2022-09-15 +lang: ko +--- + +롤업을 사용할 때 트랜잭션에서 1바이트의 비용은 저장 공간 슬롯의 비용보다 훨씬 더 비쌉니다. 따라서 가능한 한 많은 정보를 온체인에 캐시하는 것이 합리적입니다. + +이 글에서는 여러 번 사용될 가능성이 있는 모든 매개변수 값이 캐시되어 (처음 사용 이후) 훨씬 적은 수의 바이트로 사용할 수 있도록 캐싱 계약을 생성하고 사용하는 방법과 이 캐시를 사용하는 오프체인 코드를 작성하는 방법을 배웁니다. + +기사를 건너뛰고 소스 코드만 보려면 [여기를](https://github.com/qbzzt/20220915-all-you-can-cache) 클릭하세요. 개발 스택은 [Foundry](https://getfoundry.sh/introduction/installation/)입니다. + +## 전체적인 설계 {#overall-design} + +단순화를 위해 모든 트랜잭션 매개변수가 32바이트 길이의 `uint256`이라고 가정하겠습니다. 트랜잭션을 수신하면 각 매개변수를 다음과 같이 파싱합니다. + +1. 첫 번째 바이트가 `0xFF`이면 다음 32바이트를 매개변수 값으로 사용하여 캐시에 씁니다. + +2. 첫 번째 바이트가 `0xFE`이면 다음 32바이트를 매개변수 값으로 사용하지만 캐시에 쓰지는 _마세요_. + +3. 다른 값의 경우 상위 4비트는 추가 바이트 수로, 하위 4비트는 캐시 키의 최상위 비트로 사용합니다. 몇 가지 예는 다음과 같습니다. + + | calldata의 바이트 | 캐시 키 | + | :-------------- | -------: | + | 0x0F | 0x0F | + | 0x10,0x10 | 0x10 | + | 0x12,0xAC | 0x02AC | + | 0x2D,0xEA, 0xD6 | 0x0DEAD6 | + +## 캐시 조작 {#cache-manipulation} + +캐시는 [`Cache.sol`](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/src/Cache.sol)에 구현되어 있습니다. 한 줄씩 살펴보겠습니다. + +```solidity +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + + +contract Cache { + + bytes1 public constant INTO_CACHE = 0xFF; + bytes1 public constant DONT_CACHE = 0xFE; +``` + +이러한 상수는 모든 정보를 제공하고 이를 캐시에 쓸지 여부를 결정하는 특수한 경우를 해석하는 데 사용됩니다. 캐시에 쓰는 작업은 이전에 사용되지 않은 저장 공간 슬롯에 각각 22100 가스 비용으로 두 개의 [`SSTORE`](https://www.evm.codes/#55) 작업이 필요하므로 선택 사항으로 만듭니다. + +```solidity + + mapping(uint => uint) public val2key; +``` + +값과 해당 키 간의 [매핑](https://www.geeksforgeeks.org/solidity/solidity-mappings/)입니다. 이 정보는 트랜잭션을 보내기 전에 값을 인코딩하는 데 필요합니다. + +```solidity + // 위치 n에는 키 n+1의 값이 들어갑니다. + // 0은 "캐시에 없음"을 나타내기 위해 남겨둬야 합니다. + uint[] public key2val; +``` + +키를 할당하고 단순화를 위해 순차적으로 수행하기 때문에 키에서 값으로의 매핑에 배열을 사용할 수 있습니다. + +```solidity + function cacheRead(uint _key) public view returns (uint) { + require(_key <= key2val.length, "초기화되지 않은 캐시 항목 읽기"); + return key2val[_key-1]; + } // cacheRead +``` + +캐시에서 값을 읽습니다. + +```solidity + // 캐시에 값이 아직 없는 경우 값을 씁니다 + // 테스트가 작동하도록 공개(public)로 설정 + function cacheWrite(uint _value) public returns (uint) { + // 값이 이미 캐시에 있는 경우 현재 키를 반환합니다 + if (val2key[_value] != 0) { + return val2key[_value]; + } +``` + +동일한 값을 캐시에 두 번 이상 넣을 필요가 없습니다. 값이 이미 있는 경우 기존 키를 반환하면 됩니다. + +```solidity + // 0xFE는 특수한 경우이므로 캐시가 가질 수 있는 + // 가장 큰 키는 0x0D 뒤에 15개의 0xFF가 오는 것입니다. 캐시 길이가 이미 + // 그만큼 크면 실패합니다. + // 1 2 3 4 5 6 7 8 9 A B C D E F + require(key2val.length+1 < 0x0DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + "캐시 오버플로우"); +``` + +캐시가 그렇게 커질 것이라고는 생각하지 않습니다(약 1.8\*1037개의 항목, 저장하는 데 약 1027TB가 필요). 하지만 저는 ["640kB면 항상 충분할 것이다"](https://quoteinvestigator.com/2011/09/08/640k-enough/)를 기억할 만큼 나이가 많습니다. 이 테스트는 비용이 매우 저렴합니다. + +```solidity + // 다음 키를 사용하여 값을 씁니다 + val2key[_value] = key2val.length+1; +``` + +역방향 조회(값에서 키로)를 추가합니다. + +```solidity + key2val.push(_value); +``` + +정방향 조회(키에서 값으로)를 추가합니다. 값을 순차적으로 할당하기 때문에 마지막 배열 값 뒤에 추가하면 됩니다. + +```solidity + return key2val.length; + } // cacheWrite +``` + +새 값이 저장되는 셀인 `key2val`의 새 길이를 반환합니다. + +```solidity + function _calldataVal(uint startByte, uint length) + private pure returns (uint) +``` + +이 함수는 임의의 길이(최대 32바이트, 워드 크기)의 calldata에서 값을 읽습니다. + +```solidity + { + uint _retVal; + + require(length < 0x21, + "_calldataVal 길이 제한은 32바이트입니다"); + require(length + startByte <= msg.data.length, + "_calldataVal이 calldatasize를 초과하여 읽으려 합니다"); +``` + +이 함수는 내부 함수이므로 나머지 코드가 올바르게 작성되었다면 이러한 테스트는 필요하지 않습니다. 하지만 비용이 많이 들지 않으므로 추가하는 것이 좋습니다. + +```solidity + assembly { + _retVal := calldataload(startByte) + } +``` + +이 코드는 [Yul](https://docs.soliditylang.org/en/v0.8.16/yul.html)로 작성되었습니다. calldata에서 32바이트 값을 읽습니다. EVM의 초기화되지 않은 공간은 0으로 간주되기 때문에 `startByte+32` 이전에 calldata가 중지되더라도 이 작업은 작동합니다. + +```solidity + _retVal = _retVal >> (256-length*8); +``` + +반드시 32바이트 값이 필요한 것은 아닙니다. 이렇게 하면 초과 바이트를 제거할 수 있습니다. + +```solidity + return _retVal; + } // _calldataVal + + + // _fromByte에서 시작하여 calldata에서 단일 매개변수를 읽습니다. + function _readParam(uint _fromByte) internal + returns (uint _nextByte, uint _parameterValue) + { +``` + +calldata에서 단일 매개변수를 읽습니다. 매개변수의 길이는 1바이트에서 33바이트까지 다양할 수 있으므로 읽은 값뿐만 아니라 다음 바이트의 위치도 반환해야 합니다. + +```solidity + // 첫 번째 바이트는 나머지를 해석하는 방법을 알려줍니다. + uint8 _firstByte; + + _firstByte = uint8(_calldataVal(_fromByte, 1)); +``` + +Solidity는 잠재적으로 위험한 [암시적 유형 변환](https://docs.soliditylang.org/en/v0.8.16/types.html#implicit-conversions)을 금지하여 버그 수를 줄이려고 합니다. 예를 들어 256비트에서 8비트로의 다운그레이드는 명시적이어야 합니다. + +```solidity + + // 값을 읽지만 캐시에 쓰지 않습니다. + if (_firstByte == uint8(DONT_CACHE)) + return(_fromByte+33, _calldataVal(_fromByte+1, 32)); + + // 값을 읽고 캐시에 씁니다. + if (_firstByte == uint8(INTO_CACHE)) { + uint _param = _calldataVal(_fromByte+1, 32); + cacheWrite(_param); + return(_fromByte+33, _param); + } + + // 여기까지 오면 캐시에서 읽어야 한다는 의미입니다. + + // 읽을 추가 바이트 수 + uint8 _extraBytes = _firstByte / 16; +``` + +하위 [니블](https://en.wikipedia.org/wiki/Nibble)을 가져와 다른 바이트와 결합하여 캐시에서 값을 읽습니다. + +```solidity + uint _key = (uint256(_firstByte & 0x0F) << (8*_extraBytes)) + + _calldataVal(_fromByte+1, _extraBytes); + + return (_fromByte+_extraBytes+1, cacheRead(_key)); + + } // _readParam + + + // n개의 매개변수 읽기(함수는 예상하는 매개변수 수를 알고 있습니다) + function _readParams(uint _paramNum) internal returns (uint[] memory) { +``` + +calldata 자체에서 매개변수 수를 가져올 수 있지만, 우리를 호출하는 함수는 예상하는 매개변수 수를 알고 있습니다. 그들이 알려주는 것이 더 쉽습니다. + +```solidity + // 읽은 매개변수들 + uint[] memory params = new uint[](_paramNum); + + // 매개변수는 4번째 바이트에서 시작하며, 그 이전은 함수 서명입니다. + uint _atByte = 4; + + for(uint i=0; i<_paramNum; i++) { + (_atByte, params[i]) = _readParam(_atByte); + } +``` + +필요한 수의 매개변수를 가질 때까지 매개변수를 읽습니다. calldata의 끝을 지나면 `_readParams`가 호출을 되돌립니다. + +```solidity + + return(params); + } // readParams + + // _readParams 테스트를 위해 4개의 매개변수 읽기 테스트 + function fourParam() public + returns (uint256,uint256,uint256,uint256) + { + uint[] memory params; + params = _readParams(4); + return (params[0], params[1], params[2], params[3]); + } // fourParam +``` + +Foundry의 큰 장점 중 하나는 Solidity로 테스트를 작성할 수 있다는 것입니다([아래 캐시 테스트](#testing-the-cache) 참조). 이렇게 하면 단위 테스트가 훨씬 쉬워집니다. 이 함수는 네 개의 매개변수를 읽고 반환하여 테스트에서 올바른지 확인할 수 있도록 하는 함수입니다. + +```solidity + // 값을 가져와 인코딩할 바이트를 반환합니다(가능한 경우 캐시 사용). + function encodeVal(uint _val) public view returns(bytes memory) { +``` + +`encodeVal`은 오프체인 코드가 캐시를 사용하는 calldata를 만드는 데 도움을 주기 위해 호출하는 함수입니다. 단일 값을 받아 인코딩된 바이트를 반환합니다. 이 함수는 `view`이므로 트랜잭션이 필요하지 않으며 외부에서 호출할 때 가스가 들지 않습니다. + +```solidity + uint _key = val2key[_val]; + + // 값이 아직 캐시에 없으므로 추가합니다. + if (_key == 0) + return bytes.concat(INTO_CACHE, bytes32(_val)); +``` + +[EVM](/developers/docs/evm/)에서 모든 초기화되지 않은 저장 공간은 0으로 간주됩니다. 따라서 존재하지 않는 값의 키를 찾으면 0을 얻게 됩니다. 이 경우 인코딩된 바이트는 `INTO_CACHE`(다음에 캐시됨)이고 그 뒤에 실제 값이 옵니다. + +```solidity + // 키가 0x10보다 작으면 단일 바이트로 반환합니다. + if (_key < 0x10) + return bytes.concat(bytes1(uint8(_key))); +``` + +단일 바이트가 가장 쉽습니다. `bytes.concat`([https://docs.soliditylang.org/en/v0.8.16/types.html#the-functions-bytes-concat-and-string-concat](https://docs.soliditylang.org/en/v0.8.16/types.html#the-functions-bytes-concat-and-string-concat))을 사용하여 `bytes` 유형을 임의의 길이의 바이트 배열로 변환합니다. 이름에도 불구하고 단 하나의 인수를 제공해도 잘 작동합니다. + +```solidity + // 0x1vvv로 인코딩된 2바이트 값 + if (_key < 0x1000) + return bytes.concat(bytes2(uint16(_key) | 0x1000)); +``` + +163보다 작은 키가 있을 때 두 바이트로 표현할 수 있습니다. 먼저 256비트 값인 `_key`를 16비트 값으로 변환하고 논리적 or를 사용하여 첫 번째 바이트에 추가 바이트 수를 더합니다. 그런 다음 `bytes`로 변환할 수 있는 `bytes2` 값으로 변환합니다. + +```solidity + // 다음 줄을 루프로 수행하는 영리한 방법이 있을 수 있지만, + // view 함수이므로 프로그래머 시간과 + // 단순성을 위해 최적화하고 있습니다. + + if (_key < 16*256**2) + return bytes.concat(bytes3(uint24(_key) | (0x2 * 16 * 256**2))); + if (_key < 16*256**3) + return bytes.concat(bytes4(uint32(_key) | (0x3 * 16 * 256**3))); + . + . + . + if (_key < 16*256**14) + return bytes.concat(bytes15(uint120(_key) | (0xE * 16 * 256**14))); + if (_key < 16*256**15) + return bytes.concat(bytes16(uint128(_key) | (0xF * 16 * 256**15))); +``` + +다른 값(3바이트, 4바이트 등) 필드 크기만 다를 뿐 동일한 방식으로 처리됩니다. + +```solidity + // 여기에 도달하면 뭔가 잘못된 것입니다. + revert("encodeVal 오류, 발생해서는 안 됨"); +``` + +여기에 도달하면 16\*25615보다 작지 않은 키를 얻었다는 의미입니다. 그러나 `cacheWrite`는 키를 제한하므로 14\*25616(첫 번째 바이트가 0xFE이므로 `DONT_CACHE`처럼 보임)까지도 도달할 수 없습니다. 하지만 향후 프로그래머가 버그를 도입할 경우를 대비하여 테스트를 추가하는 데 비용이 많이 들지 않습니다. + +```solidity + } // encodeVal + +} // Cache +``` + +### 캐시 테스트 {#testing-the-cache} + +Foundry의 장점 중 하나는 [Solidity로 테스트를 작성할 수 있다는 것](https://getfoundry.sh/forge/tests/overview/)이며, 이는 단위 테스트 작성을 더 쉽게 만듭니다. `Cache` 클래스에 대한 테스트는 [여기](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/test/Cache.t.sol)에 있습니다. 테스트 코드는 테스트 경향에 따라 반복적이므로 이 기사에서는 흥미로운 부분만 설명합니다. + +```solidity +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Test.sol"; + + +// console을 사용하려면 `forge test -vv`를 실행해야 합니다. +import "forge-std/console.sol"; +``` + +이는 테스트 패키지와 `console.log`를 사용하는 데 필요한 상용구일 뿐입니다. + +```solidity +import "src/Cache.sol"; +``` + +테스트 중인 계약을 알아야 합니다. + +```solidity +contract CacheTest is Test { + Cache cache; + + function setUp() public { + cache = new Cache(); + } +``` + +`setUp` 함수는 각 테스트 전에 호출됩니다. 이 경우 새 캐시를 만들어 테스트가 서로 영향을 미치지 않도록 합니다. + +```solidity + function testCaching() public { +``` + +테스트는 이름이 `test`로 시작하는 함수입니다. 이 함수는 값을 쓰고 다시 읽는 기본 캐시 기능을 확인합니다. + +```solidity + for(uint i=1; i<5000; i++) { + cache.cacheWrite(i*i); + } + + for(uint i=1; i<5000; i++) { + assertEq(cache.cacheRead(i), i*i); +``` + +이것이 [`assert...` 함수](https://getfoundry.sh/reference/forge-std/std-assertions/)를 사용하여 실제 테스트를 수행하는 방법입니다. 이 경우 우리가 쓴 값이 우리가 읽은 값과 동일한지 확인합니다. 캐시 키가 선형적으로 할당된다는 것을 알기 때문에 `cache.cacheWrite`의 결과를 버릴 수 있습니다. + +```solidity + } + } // testCaching + + + // 동일한 값을 여러 번 캐시하고 키가 동일하게 + // 유지되는지 확인합니다. + function testRepeatCaching() public { + for(uint i=1; i<100; i++) { + uint _key1 = cache.cacheWrite(i); + uint _key2 = cache.cacheWrite(i); + assertEq(_key1, _key2); + } +``` + +먼저 각 값을 캐시에 두 번 쓰고 키가 동일한지 확인합니다(두 번째 쓰기는 실제로 발생하지 않았음을 의미). + +```solidity + for(uint i=1; i<100; i+=3) { + uint _key = cache.cacheWrite(i); + assertEq(_key, i); + } + } // testRepeatCaching +``` + +이론적으로 연속적인 캐시 쓰기에 영향을 미치지 않는 버그가 있을 수 있습니다. 따라서 여기서는 연속적이지 않은 일부 쓰기를 수행하고 값이 여전히 다시 쓰여지지 않는지 확인합니다. + +```solidity + // 메모리 버퍼에서 uint를 읽습니다(보낸 매개변수를 + // 다시 받는지 확인하기 위해). + function toUint256(bytes memory _bytes, uint256 _start) internal pure + returns (uint256) +``` + +`bytes memory` 버퍼에서 256비트 워드를 읽습니다. 이 유틸리티 함수를 사용하면 캐시를 사용하는 함수 호출을 실행할 때 올바른 결과를 받는지 확인할 수 있습니다. + +```solidity + { + require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); + uint256 tempUint; + + assembly { + tempUint := mload(add(add(_bytes, 0x20), _start)) + } +``` + +Yul은 `uint256` 이상의 자료 구조를 지원하지 않으므로 메모리 버퍼 `_bytes`와 같은 더 복잡한 자료 구조를 참조할 때 해당 구조의 주소를 얻게 됩니다. Solidity는 `bytes memory` 값을 길이, 그 다음에 실제 바이트가 포함된 32바이트 워드로 저장하므로 `_start` 번 바이트를 얻으려면 `_bytes+32+_start`를 계산해야 합니다. + +```solidity + + return tempUint; + } // toUint256 + + // fourParams()의 함수 서명, 제공처: + // https://www.4byte.directory/signatures/?bytes4_signature=0x3edc1e6d + bytes4 constant FOUR_PARAMS = 0x3edc1e6d; + + // 올바른 값을 반환하는지 확인하기 위한 일부 상수 값 + uint256 constant VAL_A = 0xDEAD60A7; + uint256 constant VAL_B = 0xBEEF; + uint256 constant VAL_C = 0x600D; + uint256 constant VAL_D = 0x600D60A7; +``` + +테스트에 필요한 일부 상수입니다. + +```solidity + function testReadParam() public { +``` + +`readParams`를 사용하는 함수인 `fourParams()`를 호출하여 매개변수를 올바르게 읽을 수 있는지 테스트합니다. + +```solidity + address _cacheAddr = address(cache); + bool _success; + bytes memory _callInput; + bytes memory _callOutput; +``` + +일반 ABI 메커니즘을 사용하여 캐시를 사용하는 함수를 호출할 수 없으므로 하위 수준 [`
.call()`](https://docs.soliditylang.org/en/v0.8.16/types.html#members-of-addresses) 메커니즘을 사용해야 합니다. 이 메커니즘은 `bytes memory`를 입력으로 받고 출력으로 반환합니다(부울 값과 함께). + +```solidity + // 첫 번째 호출, 캐시는 비어 있습니다. + _callInput = bytes.concat( + FOUR_PARAMS, +``` + +동일한 계약이 캐시된 함수(트랜잭션에서 직접 호출)와 캐시되지 않은 함수(다른 스마트 계약에서 호출)를 모두 지원하는 것이 유용합니다. 이를 위해서는 모든 것을 [a `fallback` 함수](https://docs.soliditylang.org/en/v0.8.16/contracts.html#fallback-function)에 넣는 대신 올바른 함수를 호출하기 위해 Solidity 메커니즘에 계속 의존해야 합니다. 이렇게 하면 구성 가능성이 훨씬 쉬워집니다. 대부분의 경우 단일 바이트로 함수를 식별하기에 충분하므로 3바이트(16\*3=48 가스)를 낭비하고 있습니다. 하지만 이 글을 쓰는 시점에서 48 가스 비용은 0.07센트로, 더 간단하고 버그가 적은 코드에 대한 합리적인 비용입니다. + +```solidity + // 첫 번째 값, 캐시에 추가합니다. + cache.INTO_CACHE(), + bytes32(VAL_A), +``` + +첫 번째 값: 캐시에 써야 하는 전체 값임을 나타내는 플래그와 그 뒤에 오는 값의 32바이트입니다. 다른 세 값은 비슷하지만 `VAL_B`는 캐시에 기록되지 않고 `VAL_C`는 세 번째 매개변수와 네 번째 매개변수라는 점이 다릅니다. + +```solidity + . + . + . + ); + (_success, _callOutput) = _cacheAddr.call(_callInput); +``` + +여기서 실제로 `Cache` 계약을 호출합니다. + +```solidity + assertEq(_success, true); +``` + +호출이 성공할 것으로 예상합니다. + +```solidity + assertEq(cache.cacheRead(1), VAL_A); + assertEq(cache.cacheRead(2), VAL_C); +``` + +빈 캐시로 시작한 다음 `VAL_A`와 `VAL_C`를 차례로 추가합니다. 첫 번째는 키 1을, 두 번째는 2를 가질 것으로 예상합니다. + +``` + assertEq(toUint256(_callOutput,0), VAL_A); + assertEq(toUint256(_callOutput,32), VAL_B); + assertEq(toUint256(_callOutput,64), VAL_C); + assertEq(toUint256(_callOutput,96), VAL_C); +``` + +출력은 네 개의 매개변수입니다. 여기서 올바른지 확인합니다. + +```solidity + // 두 번째 호출, 캐시를 사용할 수 있습니다. + _callInput = bytes.concat( + FOUR_PARAMS, + + // 캐시의 첫 번째 값 + bytes1(0x01), +``` + +16 미만의 캐시 키는 1바이트입니다. + +```solidity + // 두 번째 값, 캐시에 추가하지 마십시오. + cache.DONT_CACHE(), + bytes32(VAL_B), + + // 세 번째 및 네 번째 값, 동일한 값 + bytes1(0x02), + bytes1(0x02) + ); + . + . + . + } // testReadParam +``` + +호출 후 테스트는 첫 번째 호출 후 테스트와 동일합니다. + +```solidity + function testEncodeVal() public { +``` + +이 함수는 매개변수를 명시적으로 작성하는 대신 `encodeVal()`을 사용한다는 점을 제외하면 `testReadParam`과 유사합니다. + +```solidity + . + . + . + _callInput = bytes.concat( + FOUR_PARAMS, + cache.encodeVal(VAL_A), + cache.encodeVal(VAL_B), + cache.encodeVal(VAL_C), + cache.encodeVal(VAL_D) + ); + . + . + . + assertEq(_callInput.length, 4+1*4); + } // testEncodeVal +``` + +`testEncodeVal()`의 유일한 추가 테스트는 `_callInput`의 길이가 올바른지 확인하는 것입니다. 첫 번째 호출의 경우 4+33*4입니다. 모든 값이 이미 캐시에 있는 두 번째 호출의 경우 4+1*4입니다. + +```solidity + // 키가 단일 바이트 이상일 때 encodeVal 테스트 + // 캐시를 4바이트로 채우는 데 시간이 + // 너무 오래 걸리므로 최대 3바이트. + function testEncodeValBig() public { + // 캐시에 여러 값을 넣습니다. + // 간단하게 하기 위해 키 n을 값 n에 사용합니다. + for(uint i=1; i<0x1FFF; i++) { + cache.cacheWrite(i); + } +``` + +위의 `testEncodeVal` 함수는 캐시에 네 개의 값만 쓰므로 [다중 바이트 값을 처리하는 함수 부분](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/src/Cache.sol#L144-L171)은 확인되지 않습니다. 하지만 그 코드는 복잡하고 오류가 발생하기 쉽습니다. + +이 함수의 첫 번째 부분은 1에서 0x1FFF까지의 모든 값을 순서대로 캐시에 쓰는 루프이므로 해당 값을 인코딩하고 어디로 가는지 알 수 있습니다. + +```solidity + . + . + . + + _callInput = bytes.concat( + FOUR_PARAMS, + cache.encodeVal(0x000F), // 1바이트 0x0F + cache.encodeVal(0x0010), // 2바이트 0x1010 + cache.encodeVal(0x0100), // 2바이트 0x1100 + cache.encodeVal(0x1000) // 3바이트 0x201000 + ); +``` + +1바이트, 2바이트 및 3바이트 값을 테스트합니다. 충분한 스택 항목(최소 0x10000000, 약 2억 5천만)을 쓰는 데 너무 오래 걸리기 때문에 그 이상은 테스트하지 않습니다. + +```solidity + . + . + . + . + } // testEncodeValBig + + + // 너무 작은 버퍼로 되돌림을 얻는 것을 테스트합니다. + function testShortCalldata() public { +``` + +매개변수가 충분하지 않은 비정상적인 경우에 어떤 일이 발생하는지 테스트합니다. + +```solidity + . + . + . + (_success, _callOutput) = _cacheAddr.call(_callInput); + assertEq(_success, false); + } // testShortCalldata +``` + +되돌리기 때문에 얻어야 할 결과는 `false`입니다. + +``` + // 없는 캐시 키로 호출 + function testNoCacheKey() public { + . + . + . + _callInput = bytes.concat( + FOUR_PARAMS, + + // 첫 번째 값, 캐시에 추가합니다. + cache.INTO_CACHE(), + bytes32(VAL_A), + + // 두 번째 값 + bytes1(0x0F), + bytes2(0x1234), + bytes11(0xA10102030405060708090A) + ); +``` + +이 함수는 캐시가 비어 있어서 읽을 값이 없다는 점을 제외하면 완벽하게 합법적인 4개의 매개변수를 얻습니다. + +```solidity + . + . + . + // 너무 긴 버퍼로 모든 것이 잘 작동하는지 테스트합니다. + function testLongCalldata() public { + address _cacheAddr = address(cache); + bool _success; + bytes memory _callInput; + bytes memory _callOutput; + + // 첫 번째 호출, 캐시는 비어 있습니다. + _callInput = bytes.concat( + FOUR_PARAMS, + + // 첫 번째 값, 캐시에 추가합니다. + cache.INTO_CACHE(), bytes32(VAL_A), + + // 두 번째 값, 캐시에 추가합니다. + cache.INTO_CACHE(), bytes32(VAL_B), + + // 세 번째 값, 캐시에 추가합니다. + cache.INTO_CACHE(), bytes32(VAL_C), + + // 네 번째 값, 캐시에 추가합니다. + cache.INTO_CACHE(), bytes32(VAL_D), + + // 그리고 "행운을 빌며" 또 다른 값을 추가합니다. + bytes4(0x31112233) + ); +``` + +이 함수는 다섯 개의 값을 보냅니다. 다섯 번째 값은 유효한 캐시 항목이 아니기 때문에 무시된다는 것을 알고 있습니다. 포함되지 않았다면 되돌림이 발생했을 것입니다. + +```solidity + (_success, _callOutput) = _cacheAddr.call(_callInput); + assertEq(_success, true); + . + . + . + } // testLongCalldata + +} // CacheTest + +``` + +## 샘플 애플리케이션 {#a-sample-app} + +Solidity로 테스트를 작성하는 것은 모두 매우 좋지만, 결국 탈중앙화앱은 유용하려면 체인 외부의 요청을 처리할 수 있어야 합니다. 이 기사에서는 "한 번 쓰고, 여러 번 읽기"를 의미하는 `WORM`을 사용하여 탈중앙화앱에서 캐싱을 사용하는 방법을 보여줍니다. 키가 아직 쓰여지지 않았다면 값을 쓸 수 있습니다. 키가 이미 쓰여졌다면 되돌림을 받게 됩니다. + +### 계약 {#the-contract} + +[이것이 계약입니다](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/src/WORM.sol). 주로 `Cache`와 `CacheTest`로 이미 수행한 작업을 반복하므로 흥미로운 부분만 다룹니다. + +```solidity +import "./Cache.sol"; + +contract WORM is Cache { +``` + +`Cache`를 사용하는 가장 쉬운 방법은 우리 자신의 계약에서 상속하는 것입니다. + +```solidity + function writeEntryCached() external { + uint[] memory params = _readParams(2); + writeEntry(params[0], params[1]); + } // writeEntryCached +``` + +이 함수는 위의 `CacheTest`에 있는 `fourParam`과 유사합니다. ABI 사양을 따르지 않기 때문에 함수에 매개변수를 선언하지 않는 것이 가장 좋습니다. + +```solidity + // 더 쉽게 호출할 수 있도록 합니다. + // writeEntryCached()의 함수 서명, 제공처: + // https://www.4byte.directory/signatures/?bytes4_signature=0xe4e4f2d3 + bytes4 constant public WRITE_ENTRY_CACHED = 0xe4e4f2d3; +``` + +ABI 사양을 따르지 않기 때문에 `writeEntryCached`를 호출하는 외부 코드는 `worm.writeEntryCached`를 사용하는 대신 수동으로 calldata를 빌드해야 합니다. 이 상수 값을 사용하면 작성하기가 더 쉬워집니다. + +`WRITE_ENTRY_CACHED`를 상태 변수로 정의하더라도 외부에서 읽으려면 `worm.WRITE_ENTRY_CACHED()` 게터 함수를 사용해야 합니다. + +```solidity + function readEntry(uint key) public view + returns (uint _value, address _writtenBy, uint _writtenAtBlock) +``` + +읽기 함수는 `view`이므로 트랜잭션이 필요하지 않으며 가스가 들지 않습니다. 결과적으로 매개변수에 캐시를 사용하는 이점이 없습니다. view 함수를 사용하면 더 간단한 표준 메커니즘을 사용하는 것이 가장 좋습니다. + +### 테스트 코드 {#the-testing-code} + +[이것은 계약에 대한 테스트 코드입니다](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/test/WORM.t.sol). 다시 한 번, 흥미로운 것만 살펴봅시다. + +```solidity + function testWReadWrite() public { + worm.writeEntry(0xDEAD, 0x60A7); + + vm.expectRevert(bytes("항목이 이미 작성됨")); + worm.writeEntry(0xDEAD, 0xBEEF); +``` + +[이것(`vm.expectRevert`)](https://book.getfoundry.sh/cheatcodes/expect-revert#expectrevert)은 Foundry 테스트에서 다음 호출이 실패해야 한다는 것과 실패의 보고된 이유를 지정하는 방법입니다. 이는 `.()` 구문을 사용할 때 적용되며, calldata를 빌드하고 하위 수준 인터페이스(`.call()` 등)를 사용하여 계약을 호출하는 경우에는 적용되지 않습니다. + +```solidity + function testReadWriteCached() public { + uint cacheGoat = worm.cacheWrite(0x60A7); +``` + +여기서는 `cacheWrite`가 캐시 키를 반환한다는 사실을 사용합니다. `cacheWrite`는 상태를 변경하므로 트랜잭션 중에만 호출할 수 있기 때문에 프로덕션 환경에서 사용할 것으로 예상되는 것은 아닙니다. 트랜잭션에는 반환 값이 없으며, 결과가 있는 경우 해당 결과는 이벤트로 내보내져야 합니다. 따라서 `cacheWrite` 반환 값은 온체인 코드에서만 액세스할 수 있으며 온체인 코드는 매개변수 캐싱이 필요하지 않습니다. + +```solidity + (_success,) = address(worm).call(_callInput); +``` + +이것이 `.call()`에 두 개의 반환 값이 있지만 첫 번째 값에만 관심이 있다는 것을 Solidity에 알리는 방법입니다. + +```solidity + (_success,) = address(worm).call(_callInput); + assertEq(_success, false); +``` + +하위 수준 `
.call()` 함수를 사용하기 때문에 `vm.expectRevert()`를 사용할 수 없으며 호출에서 얻는 부울 성공 값을 확인해야 합니다. + +```solidity + event EntryWritten(uint indexed key, uint indexed value); + + . + . + . + + _callInput = bytes.concat( + worm.WRITE_ENTRY_CACHED(), worm.encodeVal(a), worm.encodeVal(b)); + vm.expectEmit(true, true, false, false); + emit EntryWritten(a, b); + (_success,) = address(worm).call(_callInput); +``` + +이것이 Foundry에서 코드가 [이벤트를 올바르게 내보내는지](https://getfoundry.sh/reference/cheatcodes/expect-emit/) 확인하는 방법입니다. + +### 클라이언트 {#the-client} + +Solidity 테스트에서 얻을 수 없는 한 가지는 자신의 애플리케이션에 잘라내어 붙여넣을 수 있는 JavaScript 코드입니다. 그 코드를 작성하기 위해 WORM을 [Optimism Goerli](https://community.optimism.io/docs/useful-tools/networks/#optimism-goerli), [Optimism의](https://www.optimism.io/) 새로운 테스트넷에 배포했습니다. 주소는 [`0xd34335b1d818cee54e3323d3246bd31d94e6a78a`](https://goerli-optimism.etherscan.io/address/0xd34335b1d818cee54e3323d3246bd31d94e6a78a)입니다. + +[클라이언트에 대한 JavaScript 코드는 여기에서 볼 수 있습니다](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/javascript/index.js). 사용 방법: + +1. git 리포지토리 복제: + + ```sh + git clone https://github.com/qbzzt/20220915-all-you-can-cache.git + ``` + +2. 필요한 패키지 설치: + + ```sh + cd javascript + yarn + ``` + +3. 구성 파일 복사: + + ```sh + cp .env.example .env + ``` + +4. 구성을 위해 `.env` 편집: + + | 매개 변수 | 값 | + | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | + | MNEMONIC | 트랜잭션 비용을 지불할 수 있는 충분한 ETH가 있는 계정의 니모닉입니다. [여기에서 Optimism Goerli 네트워크용 무료 ETH를 얻을 수 있습니다](https://optimismfaucet.xyz/). | + | OPTIMISM_GOERLI_URL | Optimism Goerli URL. 공용 엔드포인트 `https://goerli.optimism.io`는 속도가 제한되지만 여기서 필요한 만큼 충분합니다. | + +5. `index.js`를 실행합니다. + + ```sh + node index.js + ``` + + 이 샘플 애플리케이션은 먼저 WORM에 항목을 쓰고 calldata와 Etherscan의 트랜잭션 링크를 표시합니다. 그런 다음 해당 항목을 다시 읽고 사용하는 키와 항목의 값(값, 블록 번호 및 작성자)을 표시합니다. + +대부분의 클라이언트는 일반적인 Dapp JavaScript입니다. 따라서 다시 흥미로운 부분만 살펴보겠습니다. + +```javascript +. +. +. +const main = async () => { + const func = await worm.WRITE_ENTRY_CACHED() + + // 매번 새로운 키가 필요합니다. + const key = await worm.encodeVal(Number(new Date())) +``` + +주어진 슬롯은 한 번만 쓸 수 있으므로 타임스탬프를 사용하여 슬롯을 재사용하지 않도록 합니다. + +```javascript +const val = await worm.encodeVal("0x600D") + +// 항목 작성 +const calldata = func + key.slice(2) + val.slice(2) +``` + +Ethers는 호출 데이터가 16진수 문자열, 즉 `0x` 다음에 짝수 개의 16진수 숫자가 오는 것으로 예상합니다. `key`와 `val` 모두 `0x`로 시작하므로 해당 헤더를 제거해야 합니다. + +```javascript +const tx = await worm.populateTransaction.writeEntryCached() +tx.data = calldata + +sentTx = await wallet.sendTransaction(tx) +``` + +Solidity 테스트 코드와 마찬가지로 캐시된 함수를 정상적으로 호출할 수 없습니다. 대신 하위 수준 메커니즘을 사용해야 합니다. + +```javascript + . + . + . + // 방금 작성한 항목 읽기 + const realKey = '0x' + key.slice(4) // FF 플래그 제거 + const entryRead = await worm.readEntry(realKey) + . + . + . +``` + +항목을 읽을 때는 일반적인 메커니즘을 사용할 수 있습니다. `view` 함수와 함께 매개변수 캐싱을 사용할 필요가 없습니다. + +## 결론 {#conclusion} + +이 기사의 코드는 개념 증명이며, 아이디어를 쉽게 이해하도록 하는 것이 목적입니다. 프로덕션 준비 시스템의 경우 몇 가지 추가 기능을 구현할 수 있습니다. + +- `uint256`이 아닌 값을 처리합니다. 예를 들어, 문자열입니다. +- 전역 캐시 대신 사용자-캐시 간 매핑을 사용할 수 있습니다. 사용자마다 다른 값을 사용합니다. +- 주소에 사용되는 값은 다른 용도로 사용되는 값과 구별됩니다. 주소 전용 캐시를 별도로 두는 것이 합리적일 수 있습니다. +- 현재 캐시 키는 "선착순, 가장 작은 키" 알고리즘을 따릅니다. 처음 16개 값은 단일 바이트로 보낼 수 있습니다. 다음 4080개 값은 2바이트로 보낼 수 있습니다. 다음 약 백만 개의 값은 3바이트 등입니다. 프로덕션 시스템은 캐시 항목에 대한 사용 카운터를 유지하고 이를 재구성하여 가장 흔한 16개 값은 1바이트, 다음 4080개 가장 흔한 값은 2바이트 등이 되도록 해야 합니다. + + 하지만 이는 잠재적으로 위험한 작업입니다. 다음과 같은 일련의 이벤트를 상상해 보십시오. + + 1. Noam Naive는 `encodeVal`을 호출하여 토큰을 보내려는 주소를 인코딩합니다. 해당 주소는 애플리케이션에서 처음 사용된 주소 중 하나이므로 인코딩된 값은 0x06입니다. 이것은 트랜잭션이 아닌 `view` 함수이므로 Noam과 그가 사용하는 노드 사이의 일이며 다른 누구도 알지 못합니다. + + 2. Owen Owner는 캐시 재정렬 작업을 실행합니다. 실제로 해당 주소를 사용하는 사람은 거의 없으므로 이제 0x201122로 인코딩됩니다. 다른 값인 1018이 0x06에 할당됩니다. + + 3. Noam Naive는 자신의 토큰을 0x06으로 보냅니다. 토큰은 `0x0000000000000000000000000de0b6b3a7640000` 주소로 이동하며, 해당 주소의 개인 키를 아는 사람이 없으므로 그냥 갇혀 있습니다. Noam은 _행복하지 않습니다_. + + 이 문제와 캐시 재정렬 중 멤풀에 있는 트랜잭션 관련 문제를 해결할 방법이 있지만, 이를 인지하고 있어야 합니다. + +저는 Optimism 직원이고 이것이 제가 가장 잘 아는 롤업이기 때문에 여기서 Optimism으로 캐싱을 시연했습니다. 하지만 내부 처리에 최소한의 비용을 부과하여 트랜잭션 데이터를 L1에 쓰는 것이 주요 비용이 되는 모든 롤업에서 작동해야 합니다. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). + diff --git a/public/content/translations/ko/developers/tutorials/app-plasma/index.md b/public/content/translations/ko/developers/tutorials/app-plasma/index.md new file mode 100644 index 00000000000..e5d63b58943 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/app-plasma/index.md @@ -0,0 +1,1255 @@ +--- +title: "개인 정보를 보호하는 앱별 플라즈마 작성하기" +description: "이 튜토리얼에서는 예금을 위한 반비밀 은행을 구축합니다. 은행은 중앙화된 구성 요소이며, 각 사용자의 잔액을 알고 있습니다. 하지만 이 정보는 온체인에 저장되지 않습니다. 대신 은행은 상태의 해시를 게시합니다. 트랜잭션이 발생할 때마다 은행은 새로운 해시를 게시하며, 해시 상태를 새로운 상태로 변경하는 서명된 트랜잭션이 있음을 증명하는 영지식 증명도 함께 게시합니다. 이 튜토리얼을 읽고 나면 영지식 증명을 사용하는 방법뿐만 아니라 영지식 증명을 사용하는 이유와 안전하게 사용하는 방법까지 이해하게 될 것입니다." +author: Ori Pomerantz +tags: [ "영지식", "서버", "오프체인", "개인정보 보호" ] +skill: advanced +lang: ko +published: 2025-10-15 +--- + +## 소개 {#introduction} + +[롤업](/developers/docs/scaling/zk-rollups/)과 달리 [플라즈마](/developers/docs/scaling/plasma)는 무결성을 위해 이더리움 메인넷을 사용하지만 가용성을 위해서는 사용하지 않습니다. 이 글에서는 이더리움이 무결성(무단 변경 없음)을 보장하지만 가용성(중앙화된 구성 요소가 다운되어 전체 시스템을 비활성화할 수 있음)은 보장하지 않는 플라즈마처럼 작동하는 애플리케이션을 작성합니다. + +여기서 작성하는 애플리케이션은 개인 정보를 보호하는 은행입니다. 다른 주소에는 잔액이 있는 계정이 있으며, 다른 계정으로 돈(ETH)을 보낼 수 있습니다. 은행은 상태(계정 및 잔액) 및 트랜잭션의 해시를 게시하지만 실제 잔액은 비공개로 유지될 수 있는 오프체인에 보관합니다. + +## 설계 {#design} + +이는 프로덕션용 시스템이 아니라 교육용 도구입니다. 따라서 몇 가지 단순화된 가정을 바탕으로 작성되었습니다. + +- 고정된 계정 풀. 특정 수의 계정이 있으며, 각 계정은 미리 정해진 주소에 속합니다. 영지식 증명에서는 가변 크기 데이터 구조를 처리하기 어렵기 때문에 시스템이 훨씬 더 간단해집니다. 프로덕션용 시스템의 경우, [머클 루트](/developers/tutorials/merkle-proofs-for-offline-data-integrity/)를 상태 해시로 사용하고 필요한 잔액에 대한 머클 증명을 제공할 수 있습니다. + +- 메모리 저장 공간. 프로덕션 시스템에서는 재시작 시 모든 계정 잔액을 보존하기 위해 디스크에 기록해야 합니다. 여기서는 정보가 단순히 손실되어도 괜찮습니다. + +- 전송만 가능. 프로덕션 시스템에서는 은행에 자산을 입금하고 출금하는 방법이 필요합니다. 하지만 여기서는 개념을 설명하기 위한 것이므로 이 은행은 전송으로 제한됩니다. + +### 영지식 증명 {#zero-knowledge-proofs} + +근본적인 수준에서 영지식 증명은 일부 공개 데이터인 Datapublic과 _Dataprivate_ 사이에 관계 Relationship이 존재하도록 증명자가 일부 데이터인 Dataprivate를 알고 있음을 보여줍니다. 검증자는 RelationshipDatapublic을 알고 있습니다. + +개인정보를 보호하려면 상태와 트랜잭션을 비공개로 유지해야 합니다. 하지만 무결성을 보장하려면 상태의 [암호화 해시](https://en.wikipedia.org/wiki/Cryptographic_hash_function)를 공개해야 합니다. 트랜잭션을 제출하는 사람들에게 해당 트랜잭션이 실제로 발생했음을 증명하기 위해 트랜잭션 해시도 게시해야 합니다. + +대부분의 경우 Dataprivate은 영지식 증명 프로그램의 입력이고 Datapublic은 출력입니다. + +다음은 Dataprivate의 필드입니다. + +- _Staten_, 이전 상태 +- _Staten+1_, 새로운 상태 +- _Transaction_, 이전 상태에서 새로운 상태로 변경하는 트랜잭션. 이 트랜잭션에는 다음 필드가 포함되어야 합니다. + - _수신 주소_, 전송을 받는 주소 + - 전송되는 _금액_ + - 각 트랜잭션이 한 번만 처리되도록 보장하는 _Nonce_. + 발신 주소는 서명에서 복구할 수 있으므로 트랜잭션에 포함될 필요가 없습니다. +- _서명_, 트랜잭션 수행을 승인하는 서명. 이 경우 트랜잭션을 수행할 수 있는 유일한 권한이 있는 주소는 발신 주소입니다. 우리의 영지식 시스템이 작동하는 방식 때문에 이더리움 서명 외에도 계정의 공개 키가 필요합니다. + +다음은 Datapublic의 필드입니다. + +- _Hash(Staten)_ 이전 상태의 해시 +- _Hash(Staten+1)_ 새로운 상태의 해시 +- _Hash(Transaction)_, 상태를 Staten에서 Staten+1로 변경하는 트랜잭션의 해시. + +관계는 여러 조건을 확인합니다. + +- 공개 해시는 실제로 비공개 필드에 대한 올바른 해시입니다. +- 이전 상태에 적용된 트랜잭션은 새로운 상태를 생성합니다. +- 서명은 트랜잭션의 발신 주소에서 비롯됩니다. + +암호화 해시 함수의 속성으로 인해 이러한 조건을 증명하는 것만으로도 무결성을 보장할 수 있습니다. + +### 데이터 구조 {#data-structures} + +기본 데이터 구조는 서버가 보유한 상태입니다. 모든 계정에 대해 서버는 계정 잔액과 [재전송 공격](https://en.wikipedia.org/wiki/Replay_attack)을 방지하는 데 사용되는 [논스](https://en.wikipedia.org/wiki/Cryptographic_nonce)를 추적합니다. + +### 구성 요소 {#components} + +이 시스템에는 두 가지 구성 요소가 필요합니다. + +- 트랜잭션을 수신하고 처리하며, 영지식 증명과 함께 해시를 체인에 게시하는 _서버_. +- 해시를 저장하고 영지식 증명을 검증하여 상태 전환이 합법적인지 확인하는 _스마트 계약_. + +### 데이터 및 제어 흐름 {#flows} + +다음은 다양한 구성 요소가 한 계정에서 다른 계정으로 전송하기 위해 통신하는 방법입니다. + +1. 웹 브라우저는 서명자의 계정에서 다른 계정으로 전송을 요청하는 서명된 트랜잭션을 제출합니다. + +2. 서버는 트랜잭션이 유효한지 확인합니다. + + - 서명자는 은행에 충분한 잔액이 있는 계정을 가지고 있습니다. + - 수신자는 은행에 계정을 가지고 있습니다. + +3. 서버는 서명자의 잔액에서 전송된 금액을 빼고 수신자의 잔액에 더하여 새로운 상태를 계산합니다. + +4. 서버는 상태 변경이 유효하다는 영지식 증명을 계산합니다. + +5. 서버는 다음을 포함하는 트랜잭션을 이더리움에 제출합니다. + + - 새로운 상태 해시 + - 트랜잭션 해시(트랜잭션 발신자가 처리되었는지 알 수 있도록) + - 새로운 상태로의 전환이 유효함을 증명하는 영지식 증명 + +6. 스마트 계약은 영지식 증명을 검증합니다. + +7. 영지식 증명이 확인되면 스마트 계약은 다음 작업을 수행합니다. + - 현재 상태 해시를 새로운 상태 해시로 업데이트합니다. + - 새로운 상태 해시와 트랜잭션 해시로 로그 항목을 내보냅니다. + +### 도구 {#tools} + +클라이언트 측 코드의 경우 [Vite](https://vite.dev/), [React](https://react.dev/), [Viem](https://viem.sh/), [Wagmi](https://wagmi.sh/)를 사용할 것입니다. 이것들은 업계 표준 도구입니다. 익숙하지 않다면 [이 튜토리얼](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/)을 사용할 수 있습니다. + +서버의 대부분은 [Node](https://nodejs.org/en)를 사용하는 JavaScript로 작성되었습니다. 영지식 부분은 [Noir](https://noir-lang.org/)로 작성되었습니다. `1.0.0-beta.10` 버전이 필요하므로 [지침에 따라 Noir를 설치](https://noir-lang.org/docs/getting_started/quick_start)한 후 다음을 실행합니다. + +``` +noirup -v 1.0.0-beta.10 +``` + +우리가 사용하는 블록체인은 [Foundry](https://getfoundry.sh/introduction/installation)의 일부인 로컬 테스트 블록체인 `anvil`입니다. + +## 구현 {#implementation} + +복잡한 시스템이므로 단계적으로 구현하겠습니다. + +### 1단계 - 수동 영지식 {#stage-1} + +첫 번째 단계에서는 브라우저에서 트랜잭션에 서명한 다음 영지식 증명에 정보를 수동으로 제공합니다. 영지식 코드는 `server/noir/Prover.toml`([여기](https://noir-lang.org/docs/getting_started/project_breakdown#provertoml-1)에 문서화됨)에서 해당 정보를 얻을 것으로 예상합니다. + +작동 모습을 보려면: + +1. [Node](https://nodejs.org/en/download)와 [Noir](https://noir-lang.org/install)가 설치되어 있는지 확인합니다. macOS, Linux 또는 [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)과 같은 UNIX 시스템에 설치하는 것이 좋습니다. + +2. 1단계 코드를 다운로드하고 웹 서버를 시작하여 클라이언트 코드를 제공합니다. + + ```sh + git clone https://github.com/qbzzt/250911-zk-bank.git -b 01-manual-zk + cd 250911-zk-bank + cd client + npm install + npm run dev + ``` + + 여기에 웹 서버가 필요한 이유는 특정 유형의 사기를 방지하기 위해 많은 지갑(예: MetaMask)이 디스크에서 직접 제공되는 파일을 허용하지 않기 때문입니다. + +3. 지갑이 있는 브라우저를 엽니다. + +4. 지갑에 새 암호 구문을 입력합니다. 이렇게 하면 기존 암호 구문이 삭제되므로 _반드시 백업해 두어야 합니다_. + + 암호 구문은 `test test test test test test test test test test test junk`이며, anvil의 기본 테스트 암호 구문입니다. + +5. [클라이언트 측 코드](http://localhost:5173/)로 이동합니다. + +6. 지갑에 연결하고 수신 계정과 금액을 선택합니다. + +7. 서명을 클릭하고 트랜잭션에 서명합니다. + +8. **Prover.toml** 제목 아래에 텍스트가 있습니다. `server/noir/Prover.toml`을 해당 텍스트로 바꿉니다. + +9. 영지식 증명을 실행합니다. + + ```sh + cd ../server/noir + nargo execute + ``` + + 출력은 다음과 유사해야 합니다. + + ``` + ori@CryptoDocGuy:~/noir/250911-zk-bank/server/noir$ nargo execute + + [zkBank] Circuit witness successfully solved + [zkBank] Witness saved to target/zkBank.gz + [zkBank] Circuit output: (0x199aa62af8c1d562a6ec96e66347bf3240ab2afb5d022c895e6bf6a5e617167b, 0x0cfc0a67cb7308e4e9b254026b54204e34f6c8b041be207e64c5db77d95dd82d, 0x450cf9da6e180d6159290554ae3d8787, 0x6d8bc5a15b9037e52fb59b6b98722a85) + ``` + +10. 마지막 두 값을 웹 브라우저에 표시되는 해시와 비교하여 메시지가 올바르게 해시되었는지 확인합니다. + +#### `server/noir/Prover.toml` {#server-noir-prover-toml} + +[이 파일](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/server/noir/Prover.toml)은 Noir에서 예상하는 정보 형식을 보여줍니다. + +```toml +message="send 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 500 finney (milliEth) 0 " +``` + +메시지는 텍스트 형식으로 되어 있어 사용자가 쉽게 이해할 수 있고(서명 시 필요함) Noir 코드가 구문 분석하기 쉽습니다. 금액은 피니 단위로 표시되어 한편으로는 소수점 단위의 전송을 가능하게 하고 다른 한편으로는 쉽게 읽을 수 있도록 합니다. 마지막 숫자는 [논스](https://en.wikipedia.org/wiki/Cryptographic_nonce)입니다. + +문자열의 길이는 100자입니다. 영지식 증명은 가변 크기 데이터를 잘 처리하지 못하므로 데이터를 패딩해야 하는 경우가 많습니다. + +```toml +pubKeyX=["0x83",...,"0x75"] +pubKeyY=["0x35",...,"0xa5"] +signature=["0xb1",...,"0x0d"] +``` + +이 세 가지 매개변수는 고정 크기 바이트 배열입니다. + +```toml +[[accounts]] +address="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +balance=100_000 +nonce=0 + +[[accounts]] +address="0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +balance=100_000 +nonce=0 +``` + +이는 구조체 배열을 지정하는 방법입니다. 각 항목에 대해 주소, 잔액(밀리ETH, 즉 [피니](https://cryptovalleyjournal.com/glossary/finney/)) 및 다음 논스 값을 지정합니다. + +#### `client/src/Transfer.tsx` {#client-src-transfer-tsx} + +[이 파일](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/client/src/Transfer.tsx)은 클라이언트 측 처리를 구현하고 `server/noir/Prover.toml` 파일(영지식 매개변수를 포함하는 파일)을 생성합니다. + +다음은 더 흥미로운 부분에 대한 설명입니다. + +```tsx +export default attrs => { +``` + +이 함수는 다른 파일에서 가져올 수 있는 `Transfer` React 구성 요소를 만듭니다. + +```tsx + const accounts = [ + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", + "0x90F79bf6EB2c4f870365E785982E1f101E93b906", + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65", + ] +``` + +이것은 계정 주소, 즉 `test ...`에 의해 생성된 주소입니다. test junk` 암호 구문. 자신만의 주소를 사용하려면 이 정의를 수정하기만 하면 됩니다. + +```tsx + const account = useAccount() + const wallet = createWalletClient({ + transport: custom(window.ethereum!) + }) +``` + +이러한 [Wagmi 후크](https://wagmi.sh/react/api/hooks)를 통해 [viem](https://viem.sh/) 라이브러리와 지갑에 접근할 수 있습니다. + +```tsx + const message = `send ${toAccount} ${ethAmount*1000} finney (milliEth) ${nonce}`.padEnd(100, " ") +``` + +이것은 공백으로 채워진 메시지입니다. [`useState`](https://react.dev/reference/react/useState) 변수 중 하나가 변경될 때마다 구성 요소가 다시 그려지고 `message`가 업데이트됩니다. + +```tsx + const sign = async () => { +``` + +이 함수는 사용자가 **서명** 버튼을 클릭할 때 호출됩니다. 메시지는 자동으로 업데이트되지만, 서명에는 지갑에서 사용자 승인이 필요하며, 필요하지 않은 경우에는 요청하고 싶지 않습니다. + +```tsx + const signature = await wallet.signMessage({ + account: fromAccount, + message, + }) +``` + +지갑에 [메시지 서명](https://viem.sh/docs/accounts/local/signMessage)을 요청합니다. + +```tsx + const hash = hashMessage(message) +``` + +메시지 해시를 가져옵니다. 디버깅(Noir 코드의)을 위해 사용자에게 제공하는 것이 도움이 됩니다. + +```tsx + const pubKey = await recoverPublicKey({ + hash, + signature + }) +``` + +[공개 키 가져오기](https://viem.sh/docs/utilities/recoverPublicKey). 이는 [Noir `ecrecover`](https://github.com/colinnielsen/ecrecover-noir) 함수에 필요합니다. + +```tsx + setSignature(signature) + setHash(hash) + setPubKey(pubKey) +``` + +상태 변수를 설정합니다. 이렇게 하면 구성 요소가 다시 그려지고 사용자에게 업데이트된 값이 표시됩니다. + +```tsx + let proverToml = ` +``` + +`Prover.toml`의 텍스트입니다. + +```tsx +message="${message}" + +pubKeyX=${hexToArray(pubKey.slice(4,4+2*32))} +pubKeyY=${hexToArray(pubKey.slice(4+2*32))} +``` + +Viem은 65바이트 16진수 문자열로 공개 키를 제공합니다. 첫 번째 바이트는 버전 마커인 `0x04`입니다. 그 뒤에는 공개 키의 `x`에 대한 32바이트와 공개 키의 `y`에 대한 32바이트가 이어집니다. + +그러나 Noir는 이 정보를 두 개의 바이트 배열, 즉 `x`용과 `y`용으로 받기를 기대합니다. 영지식 증명의 일부가 아닌 클라이언트에서 구문 분석하는 것이 더 쉽습니다. + +이는 일반적으로 영지식에서 좋은 관행입니다. 영지식 증명 내부의 코드는 비용이 많이 들기 때문에 영지식 증명 외부에서 수행할 수 있는 모든 처리는 영지식 증명 외부에서 수행_해야 합니다_. + +```tsx +signature=${hexToArray(signature.slice(2,-2))} +``` + +서명은 65바이트 16진수 문자열로도 제공됩니다. 그러나 마지막 바이트는 공개 키를 복구하는 데만 필요합니다. 공개 키는 이미 Noir 코드에 제공될 것이므로 서명을 확인하는 데 필요하지 않으며 Noir 코드에서도 요구하지 않습니다. + +```tsx +${accounts.map(accountInProverToml).reduce((a,b) => a+b, "")} +` +``` + +계정을 제공합니다. + +```tsx + setProverToml(proverToml) + } + + return ( + <> +

전송

+``` + +이것은 구성 요소의 HTML(더 정확하게는 [JSX](https://react.dev/learn/writing-markup-with-jsx)) 형식입니다. + +#### `server/noir/src/main.nr` {#server-noir-src-main-nr} + +[이 파일](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/server/noir/src/main.nr)은 실제 영지식 코드입니다. + +``` +use std::hash::pedersen_hash; +``` + +[페더슨 해시](https://rya-sge.github.io/access-denied/2024/05/07/pedersen-hash-function/)는 [Noir 표준 라이브러리](https://noir-lang.org/docs/noir/standard_library/cryptographic_primitives/hashes#pedersen_hash)와 함께 제공됩니다. 영지식 증명은 일반적으로 이 해시 함수를 사용합니다. 표준 해시 함수에 비해 [산술 회로](https://rareskills.io/post/arithmetic-circuit) 내부에서 계산하기가 훨씬 쉽습니다. + +``` +use keccak256::keccak256; +use dep::ecrecover; +``` + +이 두 함수는 [`Nargo.toml`](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/server/noir/Nargo.toml)에 정의된 외부 라이브러리입니다. 이름 그대로 [keccak256 해시](https://emn178.github.io/online-tools/keccak_256.html)를 계산하는 함수와 이더리움 서명을 확인하고 서명자의 이더리움 주소를 복구하는 함수입니다. + +``` +global ACCOUNT_NUMBER : u32 = 5; +``` + +Noir는 [Rust](https://www.rust-lang.org/)에서 영감을 받았습니다. 변수는 기본적으로 상수입니다. 이것이 전역 구성 상수를 정의하는 방법입니다. 특히 `ACCOUNT_NUMBER`는 우리가 저장하는 계정의 수입니다. + +`u`라는 이름의 데이터 유형은 해당 비트 수의 부호 없는 숫자입니다. 지원되는 유형은 `u8`, `u16`, `u32`, `u64` 및 `u128`뿐입니다. + +``` +global FLAT_ACCOUNT_FIELDS : u32 = 2; +``` + +이 변수는 아래 설명된 대로 계정의 페더슨 해시에 사용됩니다. + +``` +global MESSAGE_LENGTH : u32 = 100; +``` + +위에서 설명한 것처럼 메시지 길이는 고정되어 있습니다. 여기에 지정되어 있습니다. + +``` +global ASCII_MESSAGE_LENGTH : [u8; 3] = [0x31, 0x30, 0x30]; +global HASH_BUFFER_SIZE : u32 = 26+3+MESSAGE_LENGTH; +``` + +[EIP-191 서명](https://eips.ethereum.org/EIPS/eip-191)에는 26바이트 접두사, ASCII의 메시지 길이, 마지막으로 메시지 자체가 포함된 버퍼가 필요합니다. + +``` +struct Account { + balance: u128, + address: Field, + nonce: u32, +} +``` + +계정에 대해 저장하는 정보입니다. [`Field`](https://noir-lang.org/docs/noir/concepts/data_types/fields)는 일반적으로 최대 253비트의 숫자로, 영지식 증명을 구현하는 [산술 회로](https://rareskills.io/post/arithmetic-circuit)에서 직접 사용할 수 있습니다. 여기서는 `Field`를 사용하여 160비트 이더리움 주소를 저장합니다. + +``` +struct TransferTxn { + from: Field, + to: Field, + amount: u128, + nonce: u32 +} +``` + +전송 트랜잭션에 대해 저장하는 정보입니다. + +``` +fn flatten_account(account: Account) -> [Field; FLAT_ACCOUNT_FIELDS] { +``` + +함수 정의. 매개변수는 `Account` 정보입니다. 결과는 길이가 `FLAT_ACCOUNT_FIELDS`인 `Field` 변수의 배열입니다. + +``` + let flat = [ + account.address, + ((account.balance << 32) + account.nonce.into()).into(), + ]; +``` + +배열의 첫 번째 값은 계정 주소입니다. 두 번째 값에는 잔액과 논스가 모두 포함됩니다. `.into()` 호출은 숫자를 필요한 데이터 유형으로 변경합니다. `account.nonce`는 `u32` 값이지만, `u128` 값인 `account.balance « 32`에 더하려면 `u128`이어야 합니다. 이것이 첫 번째 `.into()`입니다. 두 번째는 `u128` 결과를 `Field`로 변환하여 배열에 맞도록 합니다. + +``` + flat +} +``` + +Noir에서 함수는 끝에서만 값을 반환할 수 있습니다(조기 반환은 없음). 반환 값을 지정하려면 함수의 닫는 괄호 바로 앞에서 평가합니다. + +``` +fn flatten_accounts(accounts: [Account; ACCOUNT_NUMBER]) -> [Field; FLAT_ACCOUNT_FIELDS*ACCOUNT_NUMBER] { +``` + +이 함수는 계정 배열을 Petersen 해시의 입력으로 사용할 수 있는 `Field` 배열로 바꿉니다. + +``` + let mut flat: [Field; FLAT_ACCOUNT_FIELDS*ACCOUNT_NUMBER] = [0; FLAT_ACCOUNT_FIELDS*ACCOUNT_NUMBER]; +``` + +이것은 가변 변수, 즉 상수가 _아닌_ 변수를 지정하는 방법입니다. Noir의 변수는 항상 값을 가져야 하므로 이 변수를 모두 0으로 초기화합니다. + +``` + for i in 0..ACCOUNT_NUMBER { +``` + +이것은 `for` 루프입니다. 경계는 상수입니다. Noir 루프는 컴파일 시간에 경계를 알아야 합니다. 그 이유는 산술 회로가 흐름 제어를 지원하지 않기 때문입니다. `for` 루프를 처리할 때 컴파일러는 각 반복에 대해 한 번씩 코드를 여러 번 넣습니다. + +``` + let fields = flatten_account(accounts[i]); + for j in 0..FLAT_ACCOUNT_FIELDS { + flat[i*FLAT_ACCOUNT_FIELDS + j] = fields[j]; + } + } + + flat +} + +fn hash_accounts(accounts: [Account; ACCOUNT_NUMBER]) -> Field { + pedersen_hash(flatten_accounts(accounts)) +} +``` + +마지막으로 계정 배열을 해시하는 함수에 도달했습니다. + +``` +fn find_account(accounts: [Account; ACCOUNT_NUMBER], address: Field) -> u32 { + let mut account : u32 = ACCOUNT_NUMBER; + + for i in 0..ACCOUNT_NUMBER { + if accounts[i].address == address { + account = i; + } + } +``` + +이 함수는 특정 주소를 가진 계정을 찾습니다. 이 함수는 주소를 찾은 후에도 모든 계정을 반복하기 때문에 표준 코드에서는 매우 비효율적입니다. + +그러나 영지식 증명에는 흐름 제어가 없습니다. 조건을 확인해야 하는 경우 매번 확인해야 합니다. + +`if` 문에서도 비슷한 일이 발생합니다. 위의 루프에 있는 `if` 문은 다음 수학적 문으로 변환됩니다. + +_conditionresult = accounts[i].address == address_ // 같으면 1, 그렇지 않으면 0 + +_accountnew = conditionresult\*i + (1-conditionresult)\*accountold_ + +```rust + assert (account < ACCOUNT_NUMBER, f"{address} does not have an account"); + + account +} +``` + +[`assert`](https://noir-lang.org/docs/dev/noir/concepts/assert) 함수는 어설션이 거짓이면 영지식 증명을 충돌시킵니다. 이 경우 관련 주소를 가진 계정을 찾을 수 없습니다. 주소를 보고하려면 [서식 문자열](https://noir-lang.org/docs/noir/concepts/data_types/strings#format-strings)을 사용합니다. + +```rust +fn apply_transfer_txn(accounts: [Account; ACCOUNT_NUMBER], txn: TransferTxn) -> [Account; ACCOUNT_NUMBER] { +``` + +이 함수는 전송 트랜잭션을 적용하고 새 계정 배열을 반환합니다. + +```rust + let from = find_account(accounts, txn.from); + let to = find_account(accounts, txn.to); + + let (txnFrom, txnAmount, txnNonce, accountNonce) = + (txn.from, txn.amount, txn.nonce, accounts[from].nonce); +``` + +Noir의 서식 문자열 내부에서는 구조 요소에 액세스할 수 없으므로 사용 가능한 복사본을 만듭니다. + +```rust + assert (accounts[from].balance >= txn.amount, + f"{txnFrom} does not have {txnAmount} finney"); + + assert (accounts[from].nonce == txn.nonce, + f"Transaction has nonce {txnNonce}, but the account is expected to use {accountNonce}"); +``` + +이들은 트랜잭션을 무효화할 수 있는 두 가지 조건입니다. + +```rust + let mut newAccounts = accounts; + + newAccounts[from].balance -= txn.amount; + newAccounts[from].nonce += 1; + newAccounts[to].balance += txn.amount; + + newAccounts +} +``` + +새 계정 배열을 만들고 반환합니다. + +```rust +fn readAddress(messageBytes: [u8; MESSAGE_LENGTH]) -> Field +``` + +이 함수는 메시지에서 주소를 읽습니다. + +```rust +{ + let mut result : Field = 0; + + for i in 7..47 { +``` + +주소는 항상 20바이트(즉 16진수 40자리) 길이이며 7번째 문자에서 시작합니다. + +```rust + result *= 0x10; + if messageBytes[i] >= 48 & messageBytes[i] <= 57 { // 0-9 + result += (messageBytes[i]-48).into(); + } + if messageBytes[i] >= 65 & messageBytes[i] <= 70 { // A-F + result += (messageBytes[i]-65+10).into() + } + if messageBytes[i] >= 97 & messageBytes[i] <= 102 { // a-f + result += (messageBytes[i]-97+10).into() + } + } + + result +} + +fn readAmountAndNonce(messageBytes: [u8; MESSAGE_LENGTH]) -> (u128, u32) +``` + +메시지에서 금액과 논스를 읽습니다. + +```rust +{ + let mut amount : u128 = 0; + let mut nonce: u32 = 0; + let mut stillReadingAmount: bool = true; + let mut lookingForNonce: bool = false; + let mut stillReadingNonce: bool = false; +``` + +메시지에서 주소 뒤의 첫 번째 숫자는 전송할 피니(즉 ETH의 천분의 일)의 양입니다. 두 번째 숫자는 논스입니다. 그 사이의 텍스트는 무시됩니다. + +```rust + for i in 48..MESSAGE_LENGTH { + if messageBytes[i] >= 48 & messageBytes[i] <= 57 { // 0-9 + let digit = (messageBytes[i]-48); + + if stillReadingAmount { + amount = amount*10 + digit.into(); + } + + if lookingForNonce { // We just found it + stillReadingNonce = true; + lookingForNonce = false; + } + + if stillReadingNonce { + nonce = nonce*10 + digit.into(); + } + } else { + if stillReadingAmount { + stillReadingAmount = false; + lookingForNonce = true; + } + if stillReadingNonce { + stillReadingNonce = false; + } + } + } + + (amount, nonce) +} +``` + +[튜플](https://noir-lang.org/docs/noir/concepts/data_types/tuples)을 반환하는 것은 Noir가 함수에서 여러 값을 반환하는 방법입니다. + +```rust +fn readTransferTxn(message: str) -> TransferTxn +{ + let mut txn: TransferTxn = TransferTxn { from: 0, to: 0, amount:0, nonce:0 }; + let messageBytes = message.as_bytes(); + + txn.to = readAddress(messageBytes); + let (amount, nonce) = readAmountAndNonce(messageBytes); + txn.amount = amount; + txn.nonce = nonce; + + txn +} +``` + +이 함수는 메시지를 바이트로 변환한 다음 금액을 `TransferTxn`으로 변환합니다. + +```rust +// Viem의 hashMessage에 해당함 +// https://viem.sh/docs/utilities/hashMessage#hashmessage +fn hashMessage(message: str) -> [u8;32] { +``` + +계정은 영지식 증명 내에서만 해시되므로 페더슨 해시를 사용할 수 있었습니다. 그러나 이 코드에서는 브라우저에서 생성된 메시지의 서명을 확인해야 합니다. 이를 위해 [EIP 191](https://eips.ethereum.org/EIPS/eip-191)의 이더리움 서명 형식을 따라야 합니다. 이는 표준 접두사, ASCII의 메시지 길이, 메시지 자체를 사용하여 결합된 버퍼를 만들고 이더리움 표준 keccak256을 사용하여 해시해야 함을 의미합니다. + +```rust + // ASCII 접두사 + let prefix_bytes = [ + 0x19, // \x19 + 0x45, // 'E' + 0x74, // 't' + 0x68, // 'h' + 0x65, // 'e' + 0x72, // 'r' + 0x65, // 'e' + 0x75, // 'u' + 0x6D, // 'm' + 0x20, // ' ' + 0x53, // 'S' + 0x69, // 'i' + 0x67, // 'g' + 0x6E, // 'n' + 0x65, // 'e' + 0x64, // 'd' + 0x20, // ' ' + 0x4D, // 'M' + 0x65, // 'e' + 0x73, // 's' + 0x73, // 's' + 0x61, // 'a' + 0x67, // 'g' + 0x65, // 'e' + 0x3A, // ':' + 0x0A // '\n' + ]; +``` + +애플리케이션이 사용자에게 트랜잭션이나 다른 목적으로 사용될 수 있는 메시지에 서명하도록 요청하는 경우를 방지하기 위해 EIP 191에서는 모든 서명된 메시지가 0x19(유효한 ASCII 문자가 아님) 문자로 시작하고 그 뒤에 `Ethereum Signed Message:`와 줄 바꿈이 오도록 지정합니다. + +```rust + let mut buffer: [u8; HASH_BUFFER_SIZE] = [0u8; HASH_BUFFER_SIZE]; + for i in 0..26 { + buffer[i] = prefix_bytes[i]; + } + + let messageBytes : [u8; MESSAGE_LENGTH] = message.as_bytes(); + + if MESSAGE_LENGTH <= 9 { + for i in 0..1 { + buffer[i+26] = ASCII_MESSAGE_LENGTH[i]; + } + + for i in 0..MESSAGE_LENGTH { + buffer[i+26+1] = messageBytes[i]; + } + } + + if MESSAGE_LENGTH >= 10 & MESSAGE_LENGTH <= 99 { + for i in 0..2 { + buffer[i+26] = ASCII_MESSAGE_LENGTH[i]; + } + + for i in 0..MESSAGE_LENGTH { + buffer[i+26+2] = messageBytes[i]; + } + } + + if MESSAGE_LENGTH >= 100 { + for i in 0..3 { + buffer[i+26] = ASCII_MESSAGE_LENGTH[i]; + } + + for i in 0..MESSAGE_LENGTH { + buffer[i+26+3] = messageBytes[i]; + } + } + + assert(MESSAGE_LENGTH < 1000, "Messages whose length is over three digits are not supported"); +``` + +최대 999개의 메시지 길이를 처리하고 그보다 크면 실패합니다. 메시지 길이가 상수임에도 불구하고 이 코드를 추가한 이유는 변경하기가 더 쉽기 때문입니다. 프로덕션 시스템에서는 더 나은 성능을 위해 `MESSAGE_LENGTH`가 변경되지 않는다고 가정할 것입니다. + +```rust + keccak256::keccak256(buffer, HASH_BUFFER_SIZE) +} +``` + +이더리움 표준 `keccak256` 함수를 사용합니다. + +```rust +fn signatureToAddressAndHash( + message: str, + pubKeyX: [u8; 32], + pubKeyY: [u8; 32], + signature: [u8; 64] + ) -> (Field, Field, Field) // address, first 16 bytes of hash, last 16 bytes of hash +{ +``` + +이 함수는 서명을 확인하며, 여기에는 메시지 해시가 필요합니다. 그런 다음 서명한 주소와 메시지 해시를 제공합니다. 메시지 해시는 바이트 배열보다 프로그램의 나머지 부분에서 사용하기 쉬운 두 개의 `Field` 값으로 제공됩니다. + +필드 계산은 큰 숫자의 [나머지](https://en.wikipedia.org/wiki/Modulo)로 수행되지만 해당 숫자는 일반적으로 256비트보다 작기 때문에(그렇지 않으면 EVM에서 해당 계산을 수행하기 어려움) 두 개의 `Field` 값을 사용해야 합니다. + +```rust + let hash = hashMessage(message); + + let mut (hash1, hash2) = (0,0); + + for i in 0..16 { + hash1 = hash1*256 + hash[31-i].into(); + hash2 = hash2*256 + hash[15-i].into(); + } +``` + +`hash1`과 `hash2`를 가변 변수로 지정하고 해시를 바이트 단위로 씁니다. + +```rust + ( + ecrecover::ecrecover(pubKeyX, pubKeyY, signature, hash), +``` + +이는 [솔리디티의 `ecrecover`](https://docs.soliditylang.org/en/v0.8.30/cheatsheet.html#mathematical-and-cryptographic-functions)와 유사하지만 두 가지 중요한 차이점이 있습니다. + +- 서명이 유효하지 않으면 호출이 `assert`에 실패하고 프로그램이 중단됩니다. +- 공개 키는 서명과 해시에서 복구할 수 있지만, 이는 외부에서 수행할 수 있는 처리이므로 영지식 증명 내에서 수행할 가치가 없습니다. 여기서 누군가 우리를 속이려고 하면 서명 확인이 실패합니다. + +```rust + hash1, + hash2 + ) +} + +fn main( + accounts: [Account; ACCOUNT_NUMBER], + message: str, + pubKeyX: [u8; 32], + pubKeyY: [u8; 32], + signature: [u8; 64], + ) -> pub ( + Field, // Hash of old accounts array + Field, // Hash of new accounts array + Field, // First 16 bytes of message hash + Field, // Last 16 bytes of message hash + ) +``` + +마지막으로 `main` 함수에 도달합니다. 계정 해시를 이전 값에서 새 값으로 유효하게 변경하는 트랜잭션이 있음을 증명해야 합니다. 또한 보낸 사람이 자신의 트랜잭션이 처리되었음을 알 수 있도록 특정 트랜잭션 해시가 있음을 증명해야 합니다. + +```rust +{ + let mut txn = readTransferTxn(message); +``` + +메시지에서 발신 주소를 읽는 것이 아니라 서명에서 읽기 때문에 `txn`이 변경 가능해야 합니다. + +```rust + let (fromAddress, txnHash1, txnHash2) = signatureToAddressAndHash( + message, + pubKeyX, + pubKeyY, + signature); + + txn.from = fromAddress; + + let newAccounts = apply_transfer_txn(accounts, txn); + + ( + hash_accounts(accounts), + hash_accounts(newAccounts), + txnHash1, + txnHash2 + ) +} +``` + +### 2단계 - 서버 추가 {#stage-2} + +두 번째 단계에서는 브라우저에서 전송 트랜잭션을 수신하고 구현하는 서버를 추가합니다. + +작동 모습을 보려면: + +1. Vite가 실행 중이면 중지합니다. + +2. 서버가 포함된 브랜치를 다운로드하고 필요한 모든 모듈이 있는지 확인합니다. + + ```sh + git checkout 02-add-server + cd client + npm install + cd ../server + npm install + ``` + + Noir 코드를 컴파일할 필요는 없으며, 1단계에서 사용한 코드와 동일합니다. + +3. 서버를 시작하세요. + + ```sh + npm run start + ``` + +4. 별도의 명령줄 창에서 Vite를 실행하여 브라우저 코드를 제공합니다. + + ```sh + cd client + npm run dev + ``` + +5. [http://localhost:5173](http://localhost:5173)에서 클라이언트 코드로 이동합니다. + +6. 트랜잭션을 실행하기 전에 보낼 수 있는 금액과 논스를 알아야 합니다. 이 정보를 얻으려면 **계정 데이터 업데이트**를 클릭하고 메시지에 서명합니다. + + 여기에 딜레마가 있습니다. 한편으로 우리는 재사용될 수 있는 메시지에 서명하는 것을 원하지 않으며([재전송 공격](https://en.wikipedia.org/wiki/Replay_attack)), 이것이 우리가 애초에 논스를 원하는 이유입니다. 하지만 아직 논스가 없습니다. 해결책은 한 번만 사용할 수 있고 양쪽 모두에 이미 있는 논스(예: 현재 시간)를 선택하는 것입니다. + + 이 해결책의 문제는 시간이 완벽하게 동기화되지 않을 수 있다는 것입니다. 따라서 대신 1분마다 변경되는 값에 서명합니다. 이는 재전송 공격에 대한 취약성 기간이 최대 1분임을 의미합니다. 프로덕션에서 서명된 요청은 TLS로 보호되고 터널의 다른 쪽(서버)이 이미 잔액과 논스를 공개할 수 있다는 점(작동하려면 알아야 함)을 고려할 때 이는 수용 가능한 위험입니다. + +7. 브라우저가 잔액과 논스를 다시 받으면 전송 양식이 표시됩니다. 수신 주소와 금액을 선택하고 **전송**을 클릭합니다. 이 요청에 서명합니다. + +8. 전송을 보려면 **계정 데이터 업데이트**를 하거나 서버를 실행하는 창을 확인하세요. 서버는 상태가 변경될 때마다 상태를 기록합니다. + + ``` + ori@CryptoDocGuy:~/x/250911-zk-bank/server$ npm run start + + > server@1.0.0 start + > node --experimental-json-modules index.mjs + + Listening on port 3000 + Txn send 0x90F79bf6EB2c4f870365E785982E1f101E93b906 36000 finney (milliEth) 0 processed + New state: + 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 has 64000 (1) + 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 has 100000 (0) + 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC has 100000 (0) + 0x90F79bf6EB2c4f870365E785982E1f101E93b906 has 136000 (0) + 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 has 100000 (0) + Txn send 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 7200 finney (milliEth) 1 processed + New state: + 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 has 56800 (2) + 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 has 107200 (0) + 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC has 100000 (0) + 0x90F79bf6EB2c4f870365E785982E1f101E93b906 has 136000 (0) + 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 has 100000 (0) + Txn send 0x90F79bf6EB2c4f870365E785982E1f101E93b906 3000 finney (milliEth) 2 processed + New state: + 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 has 53800 (3) + 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 has 107200 (0) + 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC has 100000 (0) + 0x90F79bf6EB2c4f870365E785982E1f101E93b906 has 139000 (0) + 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 has 100000 (0) + ``` + +#### `server/index.mjs` {#server-index-mjs-1} + +[이 파일](https://github.com/qbzzt/250911-zk-bank/blob/02-add-server/server/index.mjs)은 서버 프로세스를 포함하고 [`main.nr`](https://github.com/qbzzt/250911-zk-bank/blob/02-add-server/server/noir/src/main.nr)에서 Noir 코드와 상호 작용합니다. 다음은 흥미로운 부분에 대한 설명입니다. + +```js +import { Noir } from '@noir-lang/noir_js' +``` + +[noir.js](https://www.npmjs.com/package/@noir-lang/noir_js) 라이브러리는 JavaScript 코드와 Noir 코드 간의 인터페이스입니다. + +```js +const circuit = JSON.parse(await fs.readFile("./noir/target/zkBank.json")) +const noir = new Noir(circuit) +``` + +산술 회로(이전 단계에서 만든 컴파일된 Noir 프로그램)를 로드하고 실행할 준비를 합니다. + +```js +// 서명된 요청에 대한 응답으로만 계정 정보를 제공합니다. +const accountInformation = async signature => { + const fromAddress = await recoverAddress({ + hash: hashMessage("Get account data " + Math.floor((new Date().getTime())/60000)), + signature + }) +``` + +계정 정보를 제공하려면 서명만 필요합니다. 메시지가 어떻게 될지 이미 알고 있으므로 메시지 해시도 알고 있기 때문입니다. + +```js +const processMessage = async (message, signature) => { +``` + +메시지를 처리하고 인코딩하는 트랜잭션을 실행합니다. + +```js + // 공개 키 가져오기 + const pubKey = await recoverPublicKey({ + hash, + signature + }) +``` + +이제 서버에서 JavaScript를 실행하므로 클라이언트가 아닌 서버에서 공개 키를 검색할 수 있습니다. + +```js + let noirResult + try { + noirResult = await noir.execute({ + message, + signature: signature.slice(2,-2).match(/.{2}/g).map(x => `0x${x}`), + pubKeyX, + pubKeyY, + accounts: Accounts + }) +``` + +`noir.execute`는 Noir 프로그램을 실행합니다. 매개변수는 [`Prover.toml`](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/server/noir/Prover.toml)에 제공된 매개변수와 동일합니다. 긴 값은 Viem에서와 같이 단일 16진수 값(`0x60A7`)이 아닌 16진수 문자열 배열(`["0x60", "0xA7"]`)로 제공됩니다. + +```js + } catch (err) { + console.log(`Noir error: ${err}`) + throw Error("Invalid transaction, not processed") + } +``` + +오류가 발생하면 이를 포착한 다음 단순화된 버전을 클라이언트에 전달합니다. + +```js + Accounts[fromAccountNumber].nonce++ + Accounts[fromAccountNumber].balance -= amount + Accounts[toAccountNumber].balance += amount +``` + +트랜잭션을 적용합니다. 이미 Noir 코드에서 수행했지만 거기에서 결과를 추출하는 것보다 여기에서 다시 수행하는 것이 더 쉽습니다. + +```js +let Accounts = [ + { + address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + balance: 5000, + nonce: 0, + }, +``` + +초기 `Accounts` 구조입니다. + +### 3단계 - 이더리움 스마트 계약 {#stage-3} + +1. 서버 및 클라이언트 프로세스를 중지합니다. + +2. 스마트 계약이 포함된 브랜치를 다운로드하고 필요한 모든 모듈이 있는지 확인합니다. + + ```sh + git checkout 03-smart-contracts + cd client + npm install + cd ../server + npm install + ``` + +3. 별도의 명령줄 창에서 `anvil`을 실행합니다. + +4. 검증 키와 솔리디티 검증기를 생성한 다음 검증기 코드를 솔리디티 프로젝트에 복사합니다. + + ```sh + cd noir + bb write_vk -b ./target/zkBank.json -o ./target --oracle_hash keccak + bb write_solidity_verifier -k ./target/vk -o ./target/Verifier.sol + cp target/Verifier.sol ../../smart-contracts/src + ``` + +5. 스마트 계약으로 이동하여 `anvil` 블록체인을 사용하도록 환경 변수를 설정합니다. + + ```sh + cd ../../smart-contracts + export ETH_RPC_URL=http://localhost:8545 + ETH_PRIVATE_KEY=ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ``` + +6. `Verifier.sol`을 배포하고 주소를 환경 변수에 저장합니다. + + ```sh + VERIFIER_ADDRESS=`forge create src/Verifier.sol:HonkVerifier --private-key $ETH_PRIVATE_KEY --optimize --broadcast | awk '/Deployed to:/ {print $3}'` + echo $VERIFIER_ADDRESS + ``` + +7. `ZkBank` 계약을 배포합니다. + + ```sh + ZKBANK_ADDRESS=`forge create ZkBank --private-key $ETH_PRIVATE_KEY --broadcast --constructor-args $VERIFIER_ADDRESS 0x199aa62af8c1d562a6ec96e66347bf3240ab2afb5d022c895e6bf6a5e617167b | awk '/Deployed to:/ {print $3}'` + echo $ZKBANK_ADDRESS + ``` + + `0x199..67b` 값은 `Accounts` 초기 상태의 페더슨 해시입니다. `server/index.mjs`에서 이 초기 상태를 수정하면 트랜잭션을 실행하여 영지식 증명에서 보고된 초기 해시를 볼 수 있습니다. + +8. 서버를 실행합니다. + + ```sh + cd ../server + npm run start + ``` + +9. 다른 명령줄 창에서 클라이언트를 실행합니다. + + ```sh + cd client + npm run dev + ``` + +10. 일부 트랜잭션을 실행합니다. + +11. 상태가 온체인에서 변경되었는지 확인하려면 서버 프로세스를 다시 시작합니다. 트랜잭션의 원래 해시 값이 온체인에 저장된 해시 값과 다르기 때문에 `ZkBank`가 더 이상 트랜잭션을 수락하지 않는 것을 확인합니다. + + 이것은 예상되는 오류 유형입니다. + + ``` + ori@CryptoDocGuy:~/x/250911-zk-bank/server$ npm run start + + > server@1.0.0 start + > node --experimental-json-modules index.mjs + + Listening on port 3000 + Verification error: ContractFunctionExecutionError: The contract function "processTransaction" reverted with the following reason: + Wrong old state hash + + Contract Call: + address: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 + function: processTransaction(bytes _proof, bytes32[] _publicInputs) + args: (0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf00000000000000000000000000000000000000000000000b75c020998797da7800000000000000000000000000000000000000000000000 + ``` + +#### `server/index.mjs` {#server-index-mjs-2} + +이 파일의 변경 사항은 주로 실제 증명을 만들고 온체인에 제출하는 것과 관련이 있습니다. + +```js +import { exec } from 'child_process' +import util from 'util' + +const execPromise = util.promisify(exec) +``` + +온체인으로 보낼 실제 증명을 만들려면 [Barretenberg 패키지](https://github.com/AztecProtocol/aztec-packages/tree/next/barretenberg)를 사용해야 합니다. 이 패키지는 명령줄 인터페이스(`bb`)를 실행하거나 [JavaScript 라이브러리인 `bb.js`](https://www.npmjs.com/package/@aztec/bb.js)를 사용하여 사용할 수 있습니다. JavaScript 라이브러리는 네이티브 코드를 실행하는 것보다 훨씬 느리므로 여기서는 [`exec`](https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback)를 사용하여 명령줄을 사용합니다. + +`bb.js`를 사용하기로 결정했다면 사용 중인 Noir 버전과 호환되는 버전을 사용해야 합니다. 작성 당시 현재 Noir 버전(1.0.0-beta.11)은 `bb.js` 버전 0.87을 사용합니다. + +```js +const zkBankAddress = process.env.ZKBANK_ADDRESS || "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" +``` + +여기 주소는 깨끗한 `anvil`로 시작하여 위 지침을 따를 때 얻는 주소입니다. + +```js +const walletClient = createWalletClient({ + chain: anvil, + transport: http(), + account: privateKeyToAccount("0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6") +}) +``` + +이 개인 키는 `anvil`의 기본 사전 자금 지원 계정 중 하나입니다. + +```js +const generateProof = async (witness, fileID) => { +``` + +`bb` 실행 파일을 사용하여 증명을 생성합니다. + +```js + const fname = `witness-${fileID}.gz` + await fs.writeFile(fname, witness) +``` + +증인을 파일에 씁니다. + +```js + await execPromise(`bb prove -b ./noir/target/zkBank.json -w ${fname} -o ${fileID} --oracle_hash keccak --output_format fields`) +``` + +실제로 증명을 만듭니다. 이 단계에서는 공개 변수가 있는 파일도 만들지만 필요하지 않습니다. 이미 `noir.execute`에서 해당 변수를 가져왔습니다. + +```js + const proof = "0x" + JSON.parse(await fs.readFile(`./${fileID}/proof_fields.json`)).reduce((a,b) => a+b, "").replace(/0x/g, "") +``` + +증명은 각각 16진수 값으로 표시되는 `Field` 값의 JSON 배열입니다. 그러나 Viem이 큰 16진수 문자열로 나타내는 단일 `bytes` 값으로 트랜잭션에서 보내야 합니다. 여기서는 모든 값을 연결하고 모든 `0x`를 제거한 다음 끝에 하나를 추가하여 형식을 변경합니다. + +```js + await execPromise(`rm -r ${fname} ${fileID}`) + + return proof +} +``` + +정리하고 증명을 반환합니다. + +```js +const processMessage = async (message, signature) => { + . + . + . + + const publicFields = noirResult.returnValue.map(x=>'0x' + x.slice(2).padStart(64, "0")) +``` + +공개 필드는 32바이트 값의 배열이어야 합니다. 그러나 두 개의 `Field` 값 사이에 트랜잭션 해시를 분할해야 했기 때문에 16바이트 값으로 나타납니다. 여기서는 Viem이 실제로는 32바이트라는 것을 이해하도록 0을 추가합니다. + +```js + const proof = await generateProof(noirResult.witness, `${fromAddress}-${nonce}`) +``` + +각 주소는 각 논스를 한 번만 사용하므로 증인 파일과 출력 디렉터리의 고유 식별자로 `fromAddress`와 `nonce`의 조합을 사용할 수 있습니다. + +```js + try { + await zkBank.write.processTransaction([ + proof, publicFields]) + } catch (err) { + console.log(`Verification error: ${err}`) + throw Error("Can't verify the transaction onchain") + } + . + . + . +} +``` + +체인에 트랜잭션을 보냅니다. + +#### `smart-contracts/src/ZkBank.sol` {#smart-contracts-src-zkbank-sol} + +이것은 트랜잭션을 받는 온체인 코드입니다. + +```solidity +// SPDX-License-Identifier: MIT + +pragma solidity >=0.8.21; + +import {HonkVerifier} from "./Verifier.sol"; + +contract ZkBank { + HonkVerifier immutable myVerifier; + bytes32 currentStateHash; + + constructor(address _verifierAddress, bytes32 _initialStateHash) { + currentStateHash = _initialStateHash; + myVerifier = HonkVerifier(_verifierAddress); + } +``` + +온체인 코드는 검증기(`nargo`에서 만든 별도의 계약)와 현재 상태 해시라는 두 변수를 추적해야 합니다. + +```solidity + event TransactionProcessed( + bytes32 indexed transactionHash, + bytes32 oldStateHash, + bytes32 newStateHash + ); +``` + +상태가 변경될 때마다 `TransactionProcessed` 이벤트를 내보냅니다. + +```solidity + function processTransaction( + bytes calldata _proof, + bytes32[] calldata _publicFields + ) public { +``` + +이 함수는 트랜잭션을 처리합니다. 검증기가 요구하는 형식(온체인 처리 최소화 및 가스 비용 최소화)으로 증명(`bytes`)과 공개 입력(`bytes32` 배열)을 가져옵니다. + +```solidity + require(_publicInputs[0] == currentStateHash, + "Wrong old state hash"); +``` + +영지식 증명은 트랜잭션이 현재 해시에서 새 해시로 변경된다는 것이어야 합니다. + +```solidity + myVerifier.verify(_proof, _publicFields); +``` + +검증자 계약을 호출하여 영지식 증명을 확인합니다. 이 단계는 영지식 증명이 잘못된 경우 트랜잭션을 되돌립니다. + +```solidity + currentStateHash = _publicFields[1]; + + emit TransactionProcessed( + _publicFields[2]<<128 | _publicFields[3], + _publicFields[0], + _publicFields[1] + ); + } +} +``` + +모든 것이 확인되면 상태 해시를 새 값으로 업데이트하고 `TransactionProcessed` 이벤트를 내보냅니다. + +## 중앙화된 구성 요소에 의한 남용 {#abuses} + +정보 보안은 세 가지 속성으로 구성됩니다. + +- _기밀성_, 사용자는 읽을 권한이 없는 정보를 읽을 수 없습니다. +- _무결성_, 정보는 승인된 사용자에 의해 승인된 방식으로만 변경할 수 있습니다. +- _가용성_, 승인된 사용자는 시스템을 사용할 수 있습니다. + +이 시스템에서는 영지식 증명을 통해 무결성이 제공됩니다. 은행이 각 계정의 잔액과 모든 트랜잭션을 알아야 하므로 가용성을 보장하기는 훨씬 더 어렵고 기밀성은 불가능합니다. 정보를 가진 주체가 해당 정보를 공유하는 것을 막을 방법은 없습니다. + +[스텔스 주소](https://vitalik.eth.limo/general/2023/01/20/stealth.html)를 사용하여 진정으로 기밀인 은행을 만들 수 있을지 모르지만, 이는 이 글의 범위를 벗어납니다. + +### 허위 정보 {#false-info} + +서버가 무결성을 위반하는 한 가지 방법은 [데이터가 요청될 때](https://github.com/qbzzt/250911-zk-bank/blob/03-smart-contracts/server/index.mjs#L278-L291) 허위 정보를 제공하는 것입니다. + +이 문제를 해결하기 위해 계정을 비공개 입력으로 받고 정보가 요청된 주소를 공개 입력으로 받는 두 번째 Noir 프로그램을 작성할 수 있습니다. 출력은 해당 주소의 잔액과 논스, 그리고 계정의 해시입니다. + +물론, 논스와 잔액을 온체인에 게시하고 싶지 않기 때문에 이 증명은 온체인에서 확인할 수 없습니다. 그러나 브라우저에서 실행되는 클라이언트 코드로 확인할 수 있습니다. + +### 강제 트랜잭션 {#forced-txns} + +L2에서 가용성을 보장하고 검열을 방지하는 일반적인 메커니즘은 [강제 트랜잭션](https://docs.optimism.io/stack/transactions/forced-transaction)입니다. 그러나 강제 트랜잭션은 영지식 증명과 결합되지 않습니다. 서버는 트랜잭션을 확인할 수 있는 유일한 주체입니다. + +`smart-contracts/src/ZkBank.sol`을 수정하여 강제 트랜잭션을 수락하고 처리될 때까지 서버가 상태를 변경하지 못하도록 할 수 있습니다. 그러나 이것은 우리를 단순한 서비스 거부 공격에 노출시킵니다. 강제 트랜잭션이 유효하지 않아 처리할 수 없다면 어떻게 될까요? + +해결책은 강제 트랜잭션이 유효하지 않다는 영지식 증명을 갖는 것입니다. 이렇게 하면 서버에 세 가지 옵션이 제공됩니다. + +- 강제 트랜잭션을 처리하여 처리되었고 새 상태 해시임을 증명하는 영지식 증명을 제공합니다. +- 강제 트랜잭션을 거부하고 트랜잭션이 유효하지 않음(알 수 없는 주소, 잘못된 논스 또는 잔액 부족)을 계약에 대한 영지식 증명을 제공합니다. +- 강제 트랜잭션을 무시합니다. 서버가 실제로 트랜잭션을 처리하도록 강제할 방법은 없지만, 이는 전체 시스템을 사용할 수 없음을 의미합니다. + +#### 가용성 채권 {#avail-bonds} + +실제 구현에서는 서버를 계속 실행하기 위한某种 이윤 동기가 있을 것입니다. 강제 트랜잭션이 일정 기간 내에 처리되지 않으면 누구나 소각할 수 있는 가용성 채권을 서버가 게시하도록 하여 이 인센티브를 강화할 수 있습니다. + +### 잘못된 Noir 코드 {#bad-noir-code} + +일반적으로 사람들이 스마트 계약을 신뢰하도록 하려면 소스 코드를 [블록 탐색기](https://eth.blockscout.com/address/0x7D16d2c4e96BCFC8f815E15b771aC847EcbDB48b?tab=contract)에 업로드합니다. 그러나 영지식 증명의 경우에는 이것으로 충분하지 않습니다. + +`Verifier.sol`에는 Noir 프로그램의 함수인 검증 키가 포함되어 있습니다. 그러나 그 키는 우리에게 Noir 프로그램이 무엇이었는지 알려주지 않습니다. 실제로 신뢰할 수 있는 솔루션을 가지려면 Noir 프로그램(및 이를 만든 버전)을 업로드해야 합니다. 그렇지 않으면 영지식 증명이 백도어가 있는 다른 프로그램을 반영할 수 있습니다. + +블록 탐색기에서 Noir 프로그램을 업로드하고 확인할 수 있게 될 때까지는 직접 수행해야 합니다(가급적이면 [IPFS](/developers/tutorials/ipfs-decentralized-ui/)에). 그런 다음 정교한 사용자는 소스 코드를 다운로드하고 직접 컴파일하고 `Verifier.sol`을 만들고 온체인에 있는 것과 동일한지 확인할 수 있습니다. + +## 결론 {#conclusion} + +플라즈마 유형 애플리케이션에는 정보 저장 공간으로 중앙화된 구성 요소가 필요합니다. 이는 잠재적인 취약점을 열지만, 그 대가로 블록체인 자체에서는 사용할 수 없는 방식으로 개인정보를 보호할 수 있습니다. 영지식 증명을 사용하면 무결성을 보장하고 중앙화된 구성 요소를 실행하는 사람이 가용성을 유지하는 것이 경제적으로 유리하도록 할 수 있습니다. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). + +## 감사의 말 {#acknowledgements} + +- Josh Crites는 이 글의 초안을 읽고 까다로운 Noir 문제를 해결하는 데 도움을 주었습니다. + +남아있는 오류는 제 책임입니다. diff --git a/public/content/translations/ko/developers/tutorials/calling-a-smart-contract-from-javascript/index.md b/public/content/translations/ko/developers/tutorials/calling-a-smart-contract-from-javascript/index.md new file mode 100644 index 00000000000..59f7c516570 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/calling-a-smart-contract-from-javascript/index.md @@ -0,0 +1,131 @@ +--- +title: "자바스크립트에서 스마트 계약 호출하기" +description: "Dai 토큰 예제를 사용하여 자바스크립트에서 스마트 계약 함수를 호출하는 방법" +author: jdourlens +tags: [ "트랜잭션", "프론트엔드", "JavaScript", "web3.js" ] +skill: beginner +lang: ko +published: 2020-04-19 +source: EthereumDev +sourceUrl: https://ethereumdev.io/calling-a-smart-contract-from-javascript/ +address: "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE" +--- + +이번 튜토리얼에서는 자바스크립트에서 [스마트 계약](/developers/docs/smart-contracts/) 함수를 호출하는 방법을 알아봅니다. 먼저 스마트 계약의 상태(예: ERC20 보유자의 잔액)를 읽은 다음, 토큰 전송을 통해 블록체인의 상태를 수정합니다. [블록체인과 상호작용하기 위한 JS 환경 설정](/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/)에 이미 익숙해야 합니다. + +이 예제에서는 DAI 토큰을 사용합니다. 테스트 목적으로 ganache-cli를 사용하여 블록체인을 포크하고 이미 많은 DAI를 보유한 주소를 잠금 해제(unlock)할 것입니다: + +```bash +ganache-cli -f https://mainnet.infura.io/v3/[YOUR INFURA KEY] -d -i 66 1 --unlock 0x4d10ae710Bd8D1C31bd7465c8CBC3add6F279E81 +``` + +스마트 계약과 상호작용하려면 주소와 ABI가 필요합니다. + +```js +const ERC20TransferABI = [ + { + constant: false, + inputs: [ + { + name: "_to", + type: "address", + }, + { + name: "_value", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + name: "", + type: "bool", + }, + ], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [ + { + name: "_owner", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + name: "balance", + type: "uint256", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, +] + +const DAI_ADDRESS = "0x6b175474e89094c44da98b954eedeac495271d0f" +``` + +이 프로젝트에서는 `balanceOf`와 `transfer` 함수만 유지하기 위해 전체 ERC20 ABI를 간소화했지만, [전체 ERC20 ABI는 여기](https://ethereumdev.io/abi-for-erc20-contract-on-ethereum/)에서 확인할 수 있습니다. + +그런 다음 스마트 계약을 인스턴스화해야 합니다. + +```js +const web3 = new Web3("http://localhost:8545") + +const daiToken = new web3.eth.Contract(ERC20TransferABI, DAI_ADDRESS) +``` + +또한 두 개의 주소를 설정합니다. + +- 전송을 받을 주소와 +- 이미 잠금을 해제했으며 토큰을 보낼 주소: + +```js +const senderAddress = "0x4d10ae710Bd8D1C31bd7465c8CBC3add6F279E81" +const receiverAddress = "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE" +``` + +다음 파트에서는 `balanceOf` 함수를 호출하여 두 주소가 보유한 현재 토큰 양을 가져옵니다. + +## 호출(Call): 스마트 계약에서 값 읽기 {#call-reading-value-from-a-smart-contract} + +첫 번째 예제에서는 'constant' 메서드를 호출하고 트랜잭션을 전송하지 않고 EVM에서 스마트 계약 메서드를 실행합니다. 이를 위해 주소의 ERC20 잔액을 읽습니다. [ERC20 토큰에 대한 글을 읽어보세요](/developers/tutorials/understand-the-erc-20-token-smart-contract/). + +다음과 같이 ABI를 제공한 인스턴스화된 스마트 계약의 메서드에 접근할 수 있습니다: `yourContract.methods.methodname`. `call` 함수를 사용하면 함수 실행 결과를 받게 됩니다. + +```js +daiToken.methods.balanceOf(senderAddress).call(function (err, res) { + if (err) { + console.log("An error occurred", err) + return + } + console.log("The balance is: ", res) +}) +``` + +DAI ERC20은 소수점 18자리이므로 정확한 금액을 얻으려면 0을 18개 제거해야 합니다. JavaScript는 큰 숫자 값을 처리하지 못하므로 uint256은 문자열로 반환됩니다. JS에서 큰 숫자를 다루는 방법이 확실하지 않다면, [bignumber.js에 대한 저희 튜토리얼을 확인해 보세요](https://ethereumdev.io/how-to-deal-with-big-numbers-in-javascript/). + +## 전송(Send): 스마트 계약 함수에 트랜잭션 보내기 {#send-sending-a-transaction-to-a-smart-contract-function} + +두 번째 예제에서는 DAI 스마트 계약의 전송(transfer) 함수를 호출하여 두 번째 주소로 10 DAI를 보냅니다. 전송(transfer) 함수는 받는 사람 주소와 전송할 토큰 양이라는 두 가지 매개변수를 받습니다. + +```js +daiToken.methods + .transfer(receiverAddress, "100000000000000000000") + .send({ from: senderAddress }, function (err, res) { + if (err) { + console.log("An error occurred", err) + return + } + console.log("Hash of the transaction: " + res) + }) +``` + +call 함수는 블록체인에 채굴될 트랜잭션의 해시를 반환합니다. 이더리움에서 트랜잭션 해시는 예측 가능합니다. 이를 통해 트랜잭션이 실행되기 전에 해시를 얻을 수 있습니다([여기에서 해시가 계산되는 방법 알아보기](https://ethereum.stackexchange.com/questions/45648/how-to-calculate-the-assigned-txhash-of-a-transaction)). + +이 함수는 트랜잭션을 블록체인에 제출만 하기 때문에, 트랜잭션이 채굴되어 블록체인에 포함될 때까지 그 결과를 볼 수 없습니다. 다음 튜토리얼에서는 [해시를 이용해 블록체인에서 트랜잭션이 실행되기를 기다리는 방법](https://ethereumdev.io/waiting-for-a-transaction-to-be-mined-on-ethereum-with-js/)에 대해 알아봅니다. diff --git a/public/content/translations/ko/developers/tutorials/creating-a-wagmi-ui-for-your-contract/index.md b/public/content/translations/ko/developers/tutorials/creating-a-wagmi-ui-for-your-contract/index.md new file mode 100644 index 00000000000..f6a44268c9a --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/creating-a-wagmi-ui-for-your-contract/index.md @@ -0,0 +1,585 @@ +--- +title: "계약용 사용자 인터페이스 구축" +description: "TypeScript, React, Vite, Wagmi와 같은 최신 구성 요소를 사용하여 현대적이면서도 최소한의 사용자 인터페이스를 살펴보고, 사용자 인터페이스에 지갑을 연결하고, 스마트 계약을 호출하여 정보를 읽고, 스마트 계약에 트랜잭션을 보내고, 스마트 계약의 이벤트를 모니터링하여 변경 사항을 식별하는 방법을 알아봅니다." +author: Ori Pomerantz +tags: [ "TypeScript", "react", "vite", "wagmi", "프론트엔드" ] +skill: beginner +published: 2023-11-01 +lang: ko +sidebarDepth: 3 +--- + +이더리움 생태계에 필요한 기능을 발견했습니다. 이를 구현하기 위해 스마트 계약을 작성했고, 어쩌면 오프체인에서 실행되는 관련 코드를 작성했을 수도 있습니다. 훌륭합니다! 안타깝게도 사용자 인터페이스가 없으면 사용자가 없을 것이고, 마지막으로 웹 사이트를 작성했을 때는 사람들이 전화 접속 모뎀을 사용했으며 JavaScript는 새로운 것이었습니다. + +이 글은 바로 당신을 위한 것입니다. 프로그래밍과 JavaScript 및 HTML에 대해 약간 알고 있지만, 사용자 인터페이스 기술은 녹슬고 구식이라고 가정하겠습니다. 요즘에는 어떻게 하는지 볼 수 있도록 간단한 최신 애플리케이션을 함께 살펴보겠습니다. + +## 이것이 왜 중요한가요? {#why-important} + +이론적으로는 사람들이 [Etherscan](https://holesky.etherscan.io/address/0x432d810484add7454ddb3b5311f0ac2e95cecea8#writeContract) 또는 [Blockscout](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=write_contract)을 사용하여 계약과 상호 작용하도록 할 수 있습니다. 경험 많은 이더리안에게는 좋을 것입니다. 하지만 저희는 [또 다른 10억 명의 사람들](https://blog.ethereum.org/2021/05/07/ethereum-for-the-next-billion)에게 서비스를 제공하려고 합니다. 훌륭한 사용자 경험 없이는 이런 일이 일어나지 않을 것이며, 친숙한 사용자 인터페이스가 그 큰 부분을 차지합니다. + +## Greeter 애플리케이션 {#greeter-app} + +최신 UI 작동 방식에 대한 많은 이론이 있으며 [이를 설명하는](https://wagmi.sh/core/getting-started) [많은 좋은 사이트](https://react.dev/learn/thinking-in-react)가 있습니다. 이러한 사이트에서 수행한 훌륭한 작업을 반복하는 대신, 직접 해보면서 배우는 것을 선호하고 직접 다뤄볼 수 있는 애플리케이션으로 시작한다고 가정하겠습니다. 일을 처리하려면 여전히 이론이 필요하며, 저희는 그 이론을 다룰 것입니다. 소스 파일별로 진행하며, 해당 부분에 도달할 때마다 논의할 것입니다. + +### 설치 {#installation} + +1. 필요한 경우, 지갑에 [Holesky 블록체인](https://chainlist.org/?search=holesky&testnets=true)을 추가하고 [테스트용 ETH를 받으세요](https://www.holeskyfaucet.io/). + +2. github 리포지토리를 복제합니다. + + ```sh + git clone https://github.com/qbzzt/20230801-modern-ui.git + ``` + +3. 필요한 패키지를 설치합니다. + + ```sh + cd 20230801-modern-ui + pnpm install + ``` + +4. 애플리케이션을 시작합니다. + + ```sh + pnpm dev + ``` + +5. 애플리케이션에 표시된 URL로 이동합니다. 대부분의 경우 [http://localhost:5173/](http://localhost:5173/)입니다. + +6. Hardhat의 Greeter를 약간 수정한 버전인 계약 소스 코드를 [블록체인 탐색기](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=contract)에서 볼 수 있습니다. + +### 파일 살펴보기 {#file-walk-through} + +#### `index.html` {#index-html} + +이 파일은 스크립트 파일을 가져오는 이 줄을 제외하고는 표준 HTML 상용구입니다. + +```html + +``` + +#### `src/main.tsx` {#main-tsx} + +파일 확장자는 이 파일이 [타입 검사](https://en.wikipedia.org/wiki/Type_system#Type_checking)를 지원하는 JavaScript의 확장인 [TypeScript](https://www.typescriptlang.org/)로 작성된 [React 컴포넌트](https://www.w3schools.com/react/react_components.asp)임을 알려줍니다. TypeScript는 JavaScript로 컴파일되므로 클라이언트 측 실행에 사용할 수 있습니다. + +```tsx +import '@rainbow-me/rainbowkit/styles.css' +import { RainbowKitProvider } from '@rainbow-me/rainbowkit' +import * as React from 'react' +import * as ReactDOM from 'react-dom/client' +import { WagmiConfig } from 'wagmi' +import { chains, config } from './wagmi' +``` + +필요한 라이브러리 코드를 가져옵니다. + +```tsx +import { App } from './App' +``` + +애플리케이션을 구현하는 React 컴포넌트를 가져옵니다(아래 참조). + +```tsx +ReactDOM.createRoot(document.getElementById('root')!).render( +``` + +루트 React 컴포넌트를 생성합니다. `render`의 매개변수는 HTML과 JavaScript/TypeScript를 모두 사용하는 확장 언어인 [JSX](https://www.w3schools.com/react/react_jsx.asp)입니다. 여기서 느낌표는 TypeScript 컴포넌트에 "`document.getElementById('root')`가 `ReactDOM.createRoot`의 유효한 매개변수가 될지 모르지만, 걱정하지 마세요. 제가 개발자이고 그렇게 될 것이라고 말해주고 있습니다"라고 알려줍니다. + +```tsx + +``` + +애플리케이션은 [`React.StrictMode` 컴포넌트](https://react.dev/reference/react/StrictMode) 안에 들어갑니다. 이 컴포넌트는 React 라이브러리에 추가 디버깅 검사를 삽입하도록 지시하며, 이는 개발 중에 유용합니다. + +```tsx + +``` + +애플리케이션은 또한 [`WagmiConfig` 컴포넌트](https://wagmi.sh/react/api/WagmiProvider) 안에 있습니다. [wagmi(we are going to make it) 라이브러리](https://wagmi.sh/)는 React UI 정의를 이더리움 탈중앙화 애플리케이션 작성을 위한 [viem 라이브러리](https://viem.sh/)와 연결합니다. + +```tsx + +``` + +그리고 마지막으로, [`RainbowKitProvider` 컴포넌트](https://www.rainbowkit.com/)입니다. 이 컴포넌트는 로그인과 지갑과 애플리케이션 간의 통신을 처리합니다. + +```tsx + +``` + +이제 실제로 UI를 구현하는 애플리케이션용 컴포넌트를 가질 수 있습니다. 컴포넌트 끝에 있는 `/>`는 XML 표준에 따라 이 컴포넌트 내부에 정의가 없다는 것을 React에 알려줍니다. + +```tsx + + + , +) +``` + +물론, 다른 컴포넌트들도 닫아야 합니다. + +#### `src/App.tsx` {#app-tsx} + +```tsx +import { ConnectButton } from '@rainbow-me/rainbowkit' +import { useAccount } from 'wagmi' +import { Greeter } from './components/Greeter' + +export function App() { +``` + +이것은 React 컴포넌트를 만드는 표준적인 방법입니다. 렌더링이 필요할 때마다 호출되는 함수를 정의하는 것입니다. 이 함수는 일반적으로 상단에 일부 TypeScript 또는 JavaScript 코드가 있고, 그 뒤에 JSX 코드를 반환하는 `return` 문이 따릅니다. + +```tsx + const { isConnected } = useAccount() +``` + +여기서는 [`useAccount`](https://wagmi.sh/react/api/hooks/useAccount)를 사용하여 지갑을 통해 블록체인에 연결되어 있는지 여부를 확인합니다. + +관례적으로, React에서 `use...`라고 불리는 함수는 일종의 데이터를 반환하는 [훅](https://www.w3schools.com/react/react_hooks.asp)입니다. 이러한 훅을 사용하면 컴포넌트가 데이터를 얻을 뿐만 아니라, 해당 데이터가 변경될 때 컴포넌트가 업데이트된 정보로 다시 렌더링됩니다. + +```tsx + return ( + <> +``` + +React 컴포넌트의 JSX는 _반드시_ 하나의 컴포넌트를 반환해야 합니다. 여러 컴포넌트가 있고 "자연스럽게" 묶는 것이 없을 때 빈 컴포넌트(`<> ... `)를 사용하여 단일 컴포넌트로 만듭니다. + +```tsx +

Greeter

+ +``` + +RainbowKit에서 [`ConnectButton` 컴포넌트](https://www.rainbowkit.com/docs/connect-button)를 가져옵니다. 연결되지 않았을 때, 지갑을 설명하고 사용할 지갑을 선택할 수 있는 모달을 여는 `Connect Wallet` 버튼을 제공합니다. 연결되면, 우리가 사용하는 블록체인, 계정 주소, 그리고 ETH 잔액을 표시합니다. 이 디스플레이를 사용하여 네트워크를 전환하거나 연결을 끊을 수 있습니다. + +```tsx + {isConnected && ( +``` + +실제 JavaScript(또는 JavaScript로 컴파일될 TypeScript)를 JSX에 삽입해야 할 때, 우리는 중괄호(`{}`)를 사용합니다. + +`a && b` 구문은 [`a ?` b : a`](https://www.w3schools.com/react/react_es6_ternary.asp)의 줄임말입니다. 즉, `a`가 참이면 `b`로 평가되고, 그렇지 않으면 `a`(`false`, `0` 등일 수 있음)로 평가됩니다. 이는 특정 조건이 충족될 경우에만 컴포넌트를 표시하도록 React에 알리는 쉬운 방법입니다. + +이 경우, 사용자가 블록체인에 연결된 경우에만 사용자에게 `Greeter`를 표시하고자 합니다. + +```tsx + + )} + + ) +} +``` + +#### `src/components/Greeter.tsx` {#greeter-tsx} + +이 파일에는 대부분의 UI 기능이 포함되어 있습니다. 여기에는 일반적으로 여러 파일에 있을 정의가 포함되어 있지만, 이 프로그램은 튜토리얼이므로 성능이나 유지보수의 용이성보다는 처음 이해하기 쉽도록 최적화되어 있습니다. + +```tsx +import { useState, ChangeEventHandler } from 'react' +import { useNetwork, + useReadContract, + usePrepareContractWrite, + useContractWrite, + useContractEvent + } from 'wagmi' +``` + +이러한 라이브러리 함수를 사용합니다. 다시 말하지만, 이 함수들은 아래에서 사용되는 곳에서 설명됩니다. + +```tsx +import { AddressType } from 'abitype' +``` + +[`abitype` 라이브러리](https://abitype.dev/)는 [`AddressType`](https://abitype.dev/config#addresstype)과 같은 다양한 이더리움 데이터 유형에 대한 TypeScript 정의를 제공합니다. + +```tsx +let greeterABI = [ + . + . + . +] as const // greeterABI +``` + +`Greeter` 계약의 ABI입니다. +계약과 UI를 동시에 개발하는 경우 일반적으로 동일한 리포지토리에 넣고 솔리디티 컴파일러에서 생성된 ABI를 애플리케이션의 파일로 사용합니다. 하지만 계약이 이미 개발되었고 변경되지 않을 것이기 때문에 여기서는 이 작업이 필요하지 않습니다. + +```tsx +type AddressPerBlockchainType = { + [key: number]: AddressType +} +``` + +TypeScript는 강력한 형식의 언어입니다. 이 정의를 사용하여 다른 체인에 배포된 `Greeter` 계약의 주소를 지정합니다. 키는 숫자(chainId)이고 값은 `AddressType`(주소)입니다. + +```tsx +const contractAddrs: AddressPerBlockchainType = { + // Holesky + 17000: '0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8', + + // Sepolia + 11155111: '0x7143d5c190F048C8d19fe325b748b081903E3BF0' +} +``` + +지원되는 두 네트워크인 [Holesky](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=contact_code)와 [Sepolia](https://eth-sepolia.blockscout.com/address/0x7143d5c190F048C8d19fe325b748b081903E3BF0?tab=contact_code)에서의 계약 주소입니다. + +참고: 실제로는 Redstone Holesky에 대한 세 번째 정의가 있으며, 아래에서 설명할 것입니다. + +```tsx +type ShowObjectAttrsType = { + name: string, + object: any +} +``` + +이 유형은 `ShowObject` 컴포넌트(나중에 설명)의 매개변수로 사용됩니다. 여기에는 객체의 이름과 값이 포함되며, 디버깅 목적으로 표시됩니다. + +```tsx +type ShowGreetingAttrsType = { + greeting: string | undefined +} +``` + +어느 시점에서든 인사말이 무엇인지 알 수도 있고(블록체인에서 읽었기 때문에) 모를 수도 있습니다(아직 받지 못했기 때문에). 따라서 문자열이거나 아무것도 아닐 수 있는 유형을 갖는 것이 유용합니다. + +##### `Greeter` 컴포넌트 {#greeter-component} + +```tsx +const Greeter = () => { +``` + +마지막으로 컴포넌트를 정의합니다. + +```tsx + const { chain } = useNetwork() +``` + +사용 중인 체인에 대한 정보는 [wagmi](https://wagmi.sh/react/hooks/useNetwork)에서 제공합니다. +이것은 훅(`use...`)이므로 이 정보가 변경될 때마다 컴포넌트가 다시 그려집니다. + +```tsx + const greeterAddr = chain && contractAddrs[chain.id] +``` + +Greeter 계약의 주소는 체인에 따라 다르며(체인 정보가 없거나 해당 계약이 없는 체인에 있는 경우 `undefined`임). + +```tsx + const readResults = useReadContract({ + address: greeterAddr, + abi: greeterABI, + functionName: "greet" , // No arguments + watch: true + }) +``` + +[`useReadContract` 훅](https://wagmi.sh/react/api/hooks/useReadContract)은 계약에서 정보를 읽습니다. UI에서 `readResults`를 확장하면 어떤 정보를 반환하는지 정확히 볼 수 있습니다. 이 경우 인사말이 변경될 때 알림을 받을 수 있도록 계속 확인하기를 원합니다. + +**참고:** 인사말이 변경될 때 이를 알기 위해 [`setGreeting` 이벤트](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=logs)를 수신하고 그런 식으로 업데이트할 수 있습니다. 하지만 더 효율적일 수는 있지만 모든 경우에 적용되지는 않습니다. 사용자가 다른 체인으로 전환하면 인사말도 변경되지만 해당 변경에는 이벤트가 수반되지 않습니다. 코드의 한 부분은 이벤트를 수신하고 다른 부분은 체인 변경을 식별하도록 할 수 있지만, 이는 [`watch` 매개변수](https://wagmi.sh/react/api/hooks/useReadContract#watch-optional)를 설정하는 것보다 더 복잡합니다. + +```tsx + const [ newGreeting, setNewGreeting ] = useState("") +``` + +React의 [`useState` 훅](https://www.w3schools.com/react/react_usestate.asp)을 사용하면 컴포넌트의 한 렌더링에서 다른 렌더링으로 값이 유지되는 상태 변수를 지정할 수 있습니다. 초기값은 매개변수이며, 이 경우에는 빈 문자열입니다. + +`useState` 훅은 두 가지 값을 가진 목록을 반환합니다. + +1. 상태 변수의 현재 값입니다. +2. 필요할 때 상태 변수를 수정하는 함수입니다. 이것은 훅이므로 호출될 때마다 컴포넌트가 다시 렌더링됩니다. + +이 경우, 사용자가 설정하려는 새 인사말에 대한 상태 변수를 사용하고 있습니다. + +```tsx + const greetingChange : ChangeEventHandler = (evt) => + setNewGreeting(evt.target.value) +``` + +이것은 새 인사말 입력 필드가 변경될 때의 이벤트 핸들러입니다. 유형인 [`ChangeEventHandler`](https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/forms_and_events/)는 이것이 HTML 입력 요소의 값 변경에 대한 핸들러임을 지정합니다. `` 부분은 이것이 [제네릭 유형](https://www.w3schools.com/typescript/typescript_basic_generics.php)이기 때문에 사용됩니다. + +```tsx + const preparedTx = usePrepareContractWrite({ + address: greeterAddr, + abi: greeterABI, + functionName: 'setGreeting', + args: [ newGreeting ] + }) + const workingTx = useContractWrite(preparedTx.config) +``` + +이것은 클라이언트 관점에서 블록체인 트랜잭션을 제출하는 프로세스입니다. + +1. [`eth_estimateGas`](https://docs.alchemy.com/reference/eth-estimategas)를 사용하여 블록체인의 노드에 트랜잭션을 보냅니다. +2. 노드로부터 응답을 기다립니다. +3. 응답을 받으면 사용자에게 지갑을 통해 트랜잭션에 서명하도록 요청합니다. 이 단계는 사용자가 서명하기 전에 트랜잭션의 가스 비용을 보기 때문에 노드 응답을 받은 후에 _반드시_ 발생해야 합니다. +4. 사용자의 승인을 기다립니다. +5. 이번에는 [`eth_sendRawTransaction`](https://docs.alchemy.com/reference/eth-sendrawtransaction)을 사용하여 트랜잭션을 다시 보냅니다. + +2단계는 인지할 수 있는 시간이 걸릴 가능성이 있으며, 이 동안 사용자들은 자신의 명령이 사용자 인터페이스에 의해 실제로 수신되었는지, 왜 아직 트랜잭션에 서명하라는 요청을 받지 못하는지 궁금해할 것입니다. 이는 나쁜 사용자 경험(UX)을 만듭니다. + +해결책은 [준비 훅](https://wagmi.sh/react/prepare-hooks)을 사용하는 것입니다. 매개변수가 변경될 때마다 즉시 노드에 `eth_estimateGas` 요청을 보냅니다. 그러면 사용자가 실제로 트랜잭션을 보내고 싶을 때(이 경우 **인사말 업데이트**를 눌러서), 가스 비용이 알려지고 사용자는 즉시 지갑 페이지를 볼 수 있습니다. + +```tsx + return ( +``` + +이제 드디어 반환할 실제 HTML을 만들 수 있습니다. + +```tsx + <> +

Greeter

+ { + !readResults.isError && !readResults.isLoading && + + } +
+``` + +`ShowGreeting` 컴포넌트(아래 설명)를 만들지만, 인사말이 블록체인에서 성공적으로 읽혔을 경우에만 만듭니다. + +```tsx + +``` + +이것은 사용자가 새 인사말을 설정할 수 있는 입력 텍스트 필드입니다. 사용자가 키를 누를 때마다 `greetingChange`를 호출하고, 이는 `setNewGreeting`을 호출합니다. `setNewGreeting`은 `useState` 훅에서 나오므로 `Greeter` 컴포넌트가 다시 렌더링되게 합니다. 이것은 다음을 의미합니다. + +- 새 인사말의 값을 유지하려면 `value`를 지정해야 합니다. 그렇지 않으면 기본값인 빈 문자열로 돌아가기 때문입니다. +- `usePrepareContractWrite`는 `newGreeting`이 변경될 때마다 호출되므로 준비된 트랜잭션에 항상 최신 `newGreeting`이 포함됩니다. + +```tsx + +``` + +`workingTx.write`가 없으면 인사말 업데이트를 보내는 데 필요한 정보를 아직 기다리고 있는 것이므로 버튼이 비활성화됩니다. `workingTx.write` 값이 있으면 그것이 트랜잭션을 보내기 위해 호출할 함수입니다. + +```tsx +
+ + + + + ) +} +``` + +마지막으로, 우리가 무엇을 하고 있는지 쉽게 볼 수 있도록, 우리가 사용하는 세 가지 객체를 보여줍니다. + +- `readResults` +- `preparedTx` +- `workingTx` + +##### `ShowGreeting` 컴포넌트 {#showgreeting-component} + +이 컴포넌트는 다음을 보여줍니다. + +```tsx +const ShowGreeting = (attrs : ShowGreetingAttrsType) => { +``` + +컴포넌트 함수는 컴포넌트의 모든 속성을 가진 매개변수를 받습니다. + +```tsx + return {attrs.greeting} +} +``` + +##### `ShowObject` 컴포넌트 {#showobject-component} + +정보 제공을 위해, `ShowObject` 컴포넌트를 사용하여 중요한 객체(인사말을 읽기 위한 `readResults`와 우리가 만드는 트랜잭션을 위한 `preparedTx` 및 `workingTx`)를 보여줍니다. + +```tsx +const ShowObject = (attrs: ShowObjectAttrsType ) => { + const keys = Object.keys(attrs.object) + const funs = keys.filter(k => typeof attrs.object[k] == "function") + return <> +
+``` + +UI를 모든 정보로 어지럽히고 싶지 않으므로, 정보를 보거나 닫을 수 있도록 [`details`](https://www.w3schools.com/tags/tag_details.asp) 태그를 사용합니다. + +```tsx + {attrs.name} +
+        {JSON.stringify(attrs.object, null, 2)}
+```
+
+대부분의 필드는 [`JSON.stringify`](https://www.w3schools.com/js/js_json_stringify.asp)를 사용하여 표시됩니다.
+
+```tsx
+      
+ { funs.length > 0 && + <> + Functions: +
    +``` + +예외는 함수인데, 이들은 [JSON 표준](https://www.json.org/json-en.html)의 일부가 아니므로 별도로 표시해야 합니다. + +```tsx + {funs.map((f, i) => +``` + +JSX 내에서 `{` 중괄호 `}` 안의 코드는 JavaScript로 해석됩니다. 그런 다음, `(` 일반 괄호 `)` 안의 코드는 다시 JSX로 해석됩니다. + +```tsx + (
  • {f}
  • ) + )} +``` + +React는 [DOM 트리](https://www.w3schools.com/js/js_htmldom.asp)의 태그에 고유한 식별자가 있어야 합니다. 이는 동일한 태그의 자식(이 경우, [순서 없는 목록](https://www.w3schools.com/tags/tag_ul.asp))은 다른 `key` 속성이 필요하다는 것을 의미합니다. + +```tsx +
+ + } +
+ +} +``` + +다양한 HTML 태그를 끝냅니다. + +##### 최종 `export` {#the-final-export} + +```tsx +export { Greeter } +``` + +`Greeter` 컴포넌트는 애플리케이션에 내보내야 하는 컴포넌트입니다. + +#### `src/wagmi.ts` {#wagmi-ts} + +마지막으로 WAGMI와 관련된 다양한 정의는 `src/wagmi.ts`에 있습니다. 대부분 변경할 필요가 없는 상용구이므로 여기서는 모든 것을 설명하지 않겠습니다. + +여기의 코드는 [github](https://github.com/qbzzt/20230801-modern-ui/blob/main/src/wagmi.ts)에 있는 것과 정확히 같지 않습니다. 왜냐하면 기사 뒷부분에서 다른 체인([Redstone Holesky](https://redstone.xyz/docs/network-info))을 추가하기 때문입니다. + +```ts +import { getDefaultWallets } from '@rainbow-me/rainbowkit' +import { configureChains, createConfig } from 'wagmi' +import { holesky, sepolia } from 'wagmi/chains' +``` + +애플리케이션이 지원하는 블록체인을 가져옵니다. 지원되는 체인 목록은 [viem github](https://github.com/wagmi-dev/viem/tree/main/src/chains/definitions)에서 볼 수 있습니다. + +```ts +import { publicProvider } from 'wagmi/providers/public' + +const walletConnectProjectId = 'c96e690bb92b6311e8e9b2a6a22df575' +``` + +[WalletConnect](https://walletconnect.com/)를 사용하려면 애플리케이션에 대한 프로젝트 ID가 필요합니다. [cloud.walletconnect.com](https://cloud.walletconnect.com/sign-in)에서 얻을 수 있습니다. + +```ts +const { chains, publicClient, webSocketPublicClient } = configureChains( + [ holesky, sepolia ], + [ + publicProvider(), + ], +) + +const { connectors } = getDefaultWallets({ + appName: 'My wagmi + RainbowKit App', + chains, + projectId: walletConnectProjectId, +}) + +export const config = createConfig({ + autoConnect: true, + connectors, + publicClient, + webSocketPublicClient, +}) + +export { chains } +``` + +### 다른 블록체인 추가 {#add-blockchain} + +요즘에는 많은 [L2 확장 솔루션](/layer-2/)이 있으며, viem이 아직 지원하지 않는 일부를 지원하고 싶을 수 있습니다. 이를 위해 `src/wagmi.ts`를 수정합니다. 이 지침은 [Redstone Holesky](https://redstone.xyz/docs/network-info)를 추가하는 방법을 설명합니다. + +1. viem에서 `defineChain` 유형을 가져옵니다. + + ```ts + import { defineChain } from 'viem' + ``` + +2. 네트워크 정의를 추가합니다. + + ```ts + const redstoneHolesky = defineChain({ + id: 17_001, + name: 'Redstone Holesky', + network: 'redstone-holesky', + nativeCurrency: { + decimals: 18, + name: 'Ether', + symbol: 'ETH', + }, + rpcUrls: { + default: { + http: ['https://rpc.holesky.redstone.xyz'], + webSocket: ['wss://rpc.holesky.redstone.xyz/ws'], + }, + public: { + http: ['https://rpc.holesky.redstone.xyz'], + webSocket: ['wss://rpc.holesky.redstone.xyz/ws'], + }, + }, + blockExplorers: { + default: { name: 'Explorer', url: 'https://explorer.holesky.redstone.xyz' }, + }, + }) + ``` + +3. `configureChains` 호출에 새 체인을 추가합니다. + + ```ts + const { chains, publicClient, webSocketPublicClient } = configureChains( + [ holesky, sepolia, redstoneHolesky ], + [ publicProvider(), ], + ) + ``` + +4. 애플리케이션이 새 네트워크에서 계약 주소를 알고 있는지 확인합니다. 이 경우 `src/components/Greeter.tsx`를 수정합니다. + + ```ts + const contractAddrs : AddressPerBlockchainType = { + // Holesky + 17000: '0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8', + + // Redstone Holesky + 17001: '0x4919517f82a1B89a32392E1BF72ec827ba9986D3', + + // Sepolia + 11155111: '0x7143d5c190F048C8d19fe325b748b081903E3BF0' + } + ``` + +## 결론 {#conclusion} + +물론, `Greeter`를 위한 사용자 인터페이스를 제공하는 데는 그다지 관심이 없을 것입니다. 자신만의 계약을 위한 사용자 인터페이스를 만들고 싶을 것입니다. 자신만의 애플리케이션을 만들려면 다음 단계를 실행하세요. + +1. wagmi 애플리케이션을 생성하도록 지정합니다. + + ```sh copy + pnpm create wagmi + ``` + +2. 애플리케이션의 이름을 지정합니다. + +3. **React** 프레임워크를 선택합니다. + +4. **Vite** 변형을 선택합니다. + +5. [Rainbow kit를 추가](https://www.rainbowkit.com/docs/installation#manual-setup)할 수 있습니다. + +이제 여러분의 계약을 전 세계가 사용할 수 있도록 만들어 보세요. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). + diff --git a/public/content/translations/ko/developers/tutorials/deploying-your-first-smart-contract/index.md b/public/content/translations/ko/developers/tutorials/deploying-your-first-smart-contract/index.md new file mode 100644 index 00000000000..a0c84b7deb4 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/deploying-your-first-smart-contract/index.md @@ -0,0 +1,95 @@ +--- +title: "첫 번째 스마트 계약 배포하기" +description: "이더리움 테스트넷에 첫 스마트 계약 배포하기 소개" +author: "jdourlens" +tags: [ "스마트 계약", "Remix", "Solidity", "배포하기" ] +skill: beginner +lang: ko +published: 2020-04-03 +source: EthereumDev +sourceUrl: https://ethereumdev.io/deploying-your-first-smart-contract/ +address: "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE" +--- + +여러분도 저희처럼 이더리움 블록체인에서 첫 [스마트 계약](/developers/docs/smart-contracts/)을 [배포](/developers/docs/smart-contracts/deploying/)하고 상호작용하는 것에 대해 기대가 크실 것으로 생각합니다. + +걱정 마세요. 첫 스마트 계약이니만큼 [로컬 테스트넷](/developers/docs/networks/)에 배포할 것이므로, 배포하고 원하는 만큼 자유롭게 테스트해보는 데 비용이 전혀 들지 않습니다. + +## 계약 작성하기 {#writing-our-contract} + +[Remix에 방문](https://remix.ethereum.org/)하여 새 파일을 만드는 것이 첫 번째 단계입니다. Remix 인터페이스 왼쪽 상단에서 새 파일을 추가하고 원하는 파일 이름을 입력하세요. + +![Remix 인터페이스에서 새 파일 추가하기](./remix.png) + +새 파일에 다음 코드를 붙여넣습니다. + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity >=0.5.17; + +contract Counter { + + // 카운트 수를 저장하는 부호 없는 정수 유형의 공개 변수 + uint256 public count = 0; + + // 카운터를 증가시키는 함수 + function increment() public { + count += 1; + } + + // 카운트 값을 가져오기 위한 필수적이지 않은 getter + function getCount() public view returns (uint256) { + return count; + } + +} +``` + +프로그래밍에 익숙하다면 이 프로그램이 무엇을 하는지 쉽게 추측할 수 있습니다. 한 줄씩 설명해 보겠습니다. + +- 4번 줄: `Counter`라는 이름의 계약을 정의합니다. +- 7번 줄: 계약은 0에서 시작하는 `count`라는 이름의 부호 없는 정수 하나를 저장합니다. +- 10번 줄: 첫 번째 함수는 계약의 상태를 수정하고 `count` 변수를 `increment()`합니다. +- 15번 줄: 두 번째 함수는 스마트 계약 외부에서 `count` 변수의 값을 읽을 수 있게 해주는 getter일 뿐입니다. 참고로, `count` 변수를 public으로 정의했기 때문에 이 함수는 필수는 아니지만 예시로 보여드립니다. + +첫 번째 간단한 스마트 계약에 대한 설명은 여기까지입니다. 아시다시피, 이것은 Java나 C++와 같은 OOP(객체 지향 프로그래밍) 언어의 클래스와 비슷해 보입니다. 이제 우리 계약을 다뤄볼 시간입니다. + +## 계약 배포하기 {#deploying-our-contract} + +첫 번째 스마트 계약을 작성했으니, 이제 블록체인에 배포하여 테스트해 보겠습니다. + +[블록체인에 스마트 계약을 배포하는 것](/developers/docs/smart-contracts/deploying/)은 사실 수신자를 지정하지 않고 컴파일된 스마트 계약의 코드가 포함된 트랜잭션을 보내는 것일 뿐입니다. + +먼저 왼쪽의 컴파일 아이콘을 클릭하여 [계약을 컴파일합니다](/developers/docs/smart-contracts/compiling/): + +![Remix 툴바의 컴파일 아이콘](./remix-compile-button.png) + +그런 다음 컴파일 버튼을 클릭하세요: + +![Remix Solidity 컴파일러의 컴파일 버튼](./remix-compile.png) + +텍스트 편집기에서 내용을 저장할 때 계약이 항상 컴파일되도록 '자동 컴파일' 옵션을 선택할 수 있습니다. + +그런 다음 'deploy and run transactions' 화면으로 이동합니다: + +![Remix 툴바의 배포 아이콘](./remix-deploy.png) + +'deploy and run transactions' 화면에서 계약 이름이 나타나는지 다시 확인하고 배포(Deploy)를 클릭하세요. 페이지 상단에서 볼 수 있듯이 현재 환경은 'JavaScript VM'입니다. 이는 더 빠르고 수수료 없이 테스트하기 위해 로컬 테스트 블록체인에 스마트 계약을 배포하고 상호작용한다는 의미입니다. + +![Remix Solidity 컴파일러의 배포 버튼](./remix-deploy-button.png) + +'배포(Deploy)' 버튼을 클릭하면 하단에 계약이 표시됩니다. 왼쪽의 화살표를 클릭하여 확장하면 계약 내용을 볼 수 있습니다. 이것은 우리의 `counter` 변수와, `increment()` 함수, 그리고 getter인 `getCounter()`입니다. + +`count` 또는 `getCount` 버튼을 클릭하면 실제로 계약의 `count` 변수 내용을 가져와 표시합니다. 아직 `increment` 함수를 호출하지 않았으므로 0이 표시되어야 합니다. + +![Remix Solidity 컴파일러의 함수 버튼](./remix-function-button.png) + +이제 버튼을 클릭하여 increment 함수를 호출해 보겠습니다. 창 하단에 생성된 트랜잭션의 로그가 나타나는 것을 볼 수 있습니다. `increment` 버튼 대신 데이터를 가져오는 버튼을 누를 때 로그가 다른 것을 볼 수 있습니다. 이는 블록체인에서 데이터를 읽는 데는 트랜잭션(쓰기)이나 수수료가 필요하지 않기 때문입니다. 블록체인의 상태를 수정하는 경우에만 트랜잭션을 생성해야 하기 때문입니다. + +![트랜잭션 로그](./transaction-log.png) + +`increment()` 함수를 호출하는 트랜잭션을 생성하는 increment 버튼을 누른 후, count 또는 getCount 버튼을 다시 클릭하면 count 변수가 0보다 커져 새로 업데이트된 스마트 계약의 상태를 읽게 됩니다. + +![새롭게 업데이트된 스마트 계약 상태](./updated-state.png) + +다음 튜토리얼에서는 [스마트 계약에 이벤트를 추가하는 방법](/developers/tutorials/logging-events-smart-contracts/)에 대해 다룹니다. 이벤트 로깅은 스마트 계약을 디버깅하고 함수를 호출하는 동안 어떤 일이 발생하는지 이해하는 편리한 방법입니다. diff --git a/public/content/translations/ko/developers/tutorials/develop-and-test-dapps-with-a-multi-client-local-eth-testnet/index.md b/public/content/translations/ko/developers/tutorials/develop-and-test-dapps-with-a-multi-client-local-eth-testnet/index.md new file mode 100644 index 00000000000..e155a8e81fc --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/develop-and-test-dapps-with-a-multi-client-local-eth-testnet/index.md @@ -0,0 +1,371 @@ +--- +title: "로컬, 멀티클라이언트 테스트넷에서 dApp을 개발하고 테스트하는 방법" +description: "이 가이드에서는 먼저 다중 클라이언트 로컬 이더리움 테스트넷을 인스턴스화하고 구성하는 방법을 안내한 다음, 테스트넷을 사용하여 dApp을 배포하고 테스트합니다." +author: "Tedi Mitiku" +tags: + [ + "클라이언트", + "노드", + "스마트 계약", + "결합성", + "합의 레이어", + "실행 레이어", + "테스트" + ] +skill: intermediate +lang: ko +published: 2023-04-11 +--- + +## 소개 {#introduction} + +이 가이드는 구성 가능한 로컬 이더리움 테스트넷을 인스턴스화하고, 스마트 계약을 배포하며, 테스트넷을 사용하여 dApp에 대한 테스트를 실행하는 과정을 안내합니다. 이 가이드는 라이브 테스트넷이나 메인넷에 배포하기 전에 다양한 네트워크 구성에 대해 로컬에서 dApp을 개발하고 테스트하려는 dApp 개발자를 위해 설계되었습니다. + +이 가이드에서는 다음을 수행합니다. + +- [Kurtosis](https://www.kurtosis.com/)를 사용하여 [`eth-network-package`](https://github.com/kurtosis-tech/eth-network-package)로 로컬 이더리움 테스트넷을 인스턴스화합니다. +- Hardhat dApp 개발 환경을 로컬 테스트넷에 연결하여 dApp을 컴파일, 배포 및 테스트합니다. +- 노드 수 및 특정 EL/CL 클라이언트 페어링과 같은 파라미터를 포함하여 로컬 테스트넷을 구성하여 다양한 네트워크 구성에 대한 개발 및 테스트 워크플로를 활성화합니다. + +### Kurtosis란 무엇인가요? {#what-is-kurtosis} + +[Kurtosis](https://www.kurtosis.com/)는 다중 컨테이너 테스트 환경 구성을 위해 설계된 구성 가능한 빌드 시스템입니다. 이를 통해 개발자는 블록체인 테스트넷과 같이 동적 설정 로직이 필요한 재현 가능한 환경을 만들 수 있습니다. + +이 가이드에서 Kurtosis eth-network-package는 [`geth`](https://geth.ethereum.org/) 실행 레이어(EL) 클라이언트와 [`teku`](https://consensys.io/teku), [`lighthouse`](https://lighthouse.sigmaprime.io/), [`lodestar`](https://lodestar.chainsafe.io/) 합의 레이어(CL) 클라이언트를 지원하는 로컬 이더리움 테스트넷을 가동합니다. 이 패키지는 Hardhat Network, Ganache, Anvil과 같은 프레임워크의 네트워크에 대한 구성 가능하고 조합 가능한 대안 역할을 합니다. Kurtosis는 개발자가 사용하는 테스트넷에 대한 더 큰 제어와 유연성을 제공하며, 이것이 [이더리움 재단이 머지를 테스트하기 위해 Kurtosis를 사용한](https://www.kurtosis.com/blog/testing-the-ethereum-merge) 주된 이유이며 네트워크 업그레이드를 테스트하기 위해 계속 사용하고 있습니다. + +## Kurtosis 설정 {#setting-up-kurtosis} + +진행하기 전에 다음을 확인하십시오. + +- 로컬 머신에 [Docker 엔진을 설치하고 시작](https://docs.kurtosis.com/install/#i-install--start-docker)했습니다. +- [Kurtosis CLI를 설치](https://docs.kurtosis.com/install#ii-install-the-cli)했습니다(CLI가 이미 설치되어 있는 경우 최신 릴리스로 업그레이드). +- [Node.js](https://nodejs.org/en), [yarn](https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable), [npx](https://www.npmjs.com/package/npx)를 설치했습니다(dApp 환경용). + +## 로컬 이더리움 테스트넷 인스턴스화 {#instantiate-testnet} + +로컬 이더리움 테스트넷을 가동하려면 다음을 실행하세요. + +```python +kurtosis --enclave local-eth-testnet run github.com/kurtosis-tech/eth-network-package +``` + +참고: 이 명령어는 '--enclave' 플래그를 사용하여 네트워크 이름을 "local-eth-testnet"으로 지정합니다. + +Kurtosis는 지침을 해석, 검증 및 실행하는 동안 내부적으로 수행하는 단계를 출력합니다. 마지막으로 다음과 유사한 출력이 표시되어야 합니다. + +```python +INFO[2023-04-04T18:09:44-04:00] ====================================================== +INFO[2023-04-04T18:09:44-04:00] || Created enclave: local-eth-testnet || +INFO[2023-04-04T18:09:44-04:00] ====================================================== +Name: local-eth-testnet +UUID: 39372d756ae8 +Status: RUNNING +Creation Time: Tue, 04 Apr 2023 18:09:03 EDT + +========================================= Files Artifacts ========================================= +UUID Name +d4085a064230 cl-genesis-data +1c62cb792e4c el-genesis-data +bd60489b73a7 genesis-generation-config-cl +b2e593fe5228 genesis-generation-config-el +d552a54acf78 geth-prefunded-keys +5f7e661eb838 prysm-password +054e7338bb59 validator-keystore-0 + +========================================== User Services ========================================== +UUID Name Ports Status +e20f129ee0c5 cl-client-0-beacon http: 4000/tcp -> RUNNING + metrics: 5054/tcp -> + tcp-discovery: 9000/tcp -> 127.0.0.1:54263 + udp-discovery: 9000/udp -> 127.0.0.1:60470 +a8b6c926cdb4 cl-client-0-validator http: 5042/tcp -> 127.0.0.1:54267 RUNNING + metrics: 5064/tcp -> +d7b802f623e8 el-client-0 engine-rpc: 8551/tcp -> 127.0.0.1:54253 RUNNING + rpc: 8545/tcp -> 127.0.0.1:54251 + tcp-discovery: 30303/tcp -> 127.0.0.1:54254 + udp-discovery: 30303/udp -> 127.0.0.1:53834 + ws: 8546/tcp -> 127.0.0.1:54252 +514a829c0a84 prelaunch-data-generator-1680646157905431468 STOPPED +62bd62d0aa7a prelaunch-data-generator-1680646157915424301 STOPPED +05e9619e0e90 prelaunch-data-generator-1680646157922872635 STOPPED +``` + +축하합니다! Docker를 통해 Kurtosis를 사용하여 CL(`lighthouse`) 및 EL 클라이언트(`geth`)가 있는 로컬 이더리움 테스트넷을 인스턴스화했습니다. + +### 검토 {#review-instantiate-testnet} + +이 섹션에서는 Kurtosis [Enclave](https://docs.kurtosis.com/advanced-concepts/enclaves/) 내에서 로컬 이더리움 테스트넷을 시작하기 위해 Kurtosis가 [GitHub에 원격으로 호스팅된 `eth-network-package`](https://github.com/kurtosis-tech/eth-network-package)를 사용하도록 지시하는 명령을 실행했습니다. 엔클레이브 내부에는 "파일 아티팩트"와 "사용자 서비스"가 모두 있습니다. + +엔클레이브의 [파일 아티팩트](https://docs.kurtosis.com/advanced-concepts/files-artifacts/)에는 EL 및 CL 클라이언트를 부트스트랩하기 위해 생성 및 활용된 모든 데이터가 포함됩니다. 데이터는 이 [Docker 이미지](https://github.com/ethpandaops/ethereum-genesis-generator)에서 빌드된 `prelaunch-data-generator` 서비스를 사용하여 생성되었습니다. + +사용자 서비스는 엔클레이브에서 작동하는 모든 컨테이너화된 서비스를 표시합니다. EL 클라이언트와 CL 클라이언트를 모두 갖춘 단일 노드가 생성된 것을 알 수 있습니다. + +## dApp 개발 환경을 로컬 이더리움 테스트넷에 연결 {#connect-your-dapp} + +### dApp 개발 환경 설정 {#set-up-dapp-env} + +이제 실행 중인 로컬 테스트넷이 있으므로 dApp 개발 환경을 연결하여 로컬 테스트넷을 사용할 수 있습니다. 이 가이드에서는 Hardhat 프레임워크를 사용하여 블랙잭 dApp을 로컬 테스트넷에 배포합니다. + +dApp 개발 환경을 설정하려면 샘플 dApp이 포함된 저장소를 클론하고 종속성을 설치한 후 다음을 실행하세요. + +```python +git clone https://github.com/kurtosis-tech/awesome-kurtosis.git && cd awesome-kurtosis/smart-contract-example && yarn +``` + +여기서 사용되는 [smart-contract-example](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/smart-contract-example) 폴더에는 [Hardhat](https://hardhat.org/) 프레임워크를 사용하는 dApp 개발자를 위한 일반적인 설정이 포함되어 있습니다. + +- [`contracts/`](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/smart-contract-example/contracts)에는 Blackjack dApp을 위한 몇 가지 간단한 스마트 계약이 포함되어 있습니다. +- [`scripts/`](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/smart-contract-example/scripts)에는 로컬 이더리움 네트워크에 토큰 계약을 배포하는 스크립트가 포함되어 있습니다. +- [`test/`](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/smart-contract-example/test)에는 토큰 계약에 대한 간단한 .js 테스트가 포함되어 있으며, Blackjack dApp의 각 플레이어에게 1000개가 민팅되었는지 확인합니다. +- [`hardhat.config.ts`](https://github.com/kurtosis-tech/awesome-kurtosis/blob/main/smart-contract-example/hardhat.config.ts)는 Hardhat 설정을 구성합니다. + +### 로컬 테스트넷을 사용하도록 Hardhat 구성 {#configure-hardhat} + +dApp 개발 환경이 설정되었으므로 이제 Kurtosis를 사용하여 생성된 로컬 이더리움 테스트넷을 사용하도록 Hardhat을 연결합니다. 이를 위해 `hardhat.config.ts` 구성 파일의 `localnet` 구조체에서 `<$YOUR_PORT>`를 `el-client-` 서비스의 rpc uri 출력 포트로 바꿉니다. 이 샘플의 경우 포트는 `64248`입니다. 사용자의 포트는 다를 것입니다. + +`hardhat.config.ts`의 예시: + +```js +localnet: { +url: 'http://127.0.0.1:<$YOUR_PORT>',// TODO: $YOUR_PORT를 ETH 네트워크 KURTOSIS 패키지에서 생성한 노드 URI의 포트로 교체하세요 + +// 이들은 eth-network-package에 의해 생성된, 사전에 자금이 충전된 테스트 계정과 연관된 개인 키입니다 +// +accounts: [ + "ef5177cd0b6b21c87db5a0bf35d4084a8a57a9d6a064f86d51ac85f2b873a4e2", + "48fcc39ae27a0e8bf0274021ae6ebd8fe4a0e12623d61464c498900b28feb567", + "7988b3a148716ff800414935b305436493e1f25237a2a03e5eebc343735e2f31", + "b3c409b6b0b3aa5e65ab2dc1930534608239a478106acf6f3d9178e9f9b00b35", + "df9bb6de5d3dc59595bcaa676397d837ff49441d211878c024eabda2cd067c9f", + "7da08f856b5956d40a72968f93396f6acff17193f013e8053f6fbb6c08c194d6", + ], +}, +``` + +파일을 저장하면 Hardhat dApp 개발 환경이 로컬 이더리움 테스트넷에 연결됩니다! 다음을 실행하여 테스트넷이 작동하는지 확인할 수 있습니다. + +```python +npx hardhat balances --network localnet +``` + +출력은 다음과 같아야 합니다. + +```python +0x878705ba3f8Bc32FCf7F4CAa1A35E72AF65CF766 has balance 10000000000000000000000000 +0x4E9A3d9D1cd2A2b2371b8b3F489aE72259886f1A has balance 10000000000000000000000000 +0xdF8466f277964Bb7a0FFD819403302C34DCD530A has balance 10000000000000000000000000 +0x5c613e39Fc0Ad91AfDA24587e6f52192d75FBA50 has balance 10000000000000000000000000 +0x375ae6107f8cC4cF34842B71C6F746a362Ad8EAc has balance 10000000000000000000000000 +0x1F6298457C5d76270325B724Da5d1953923a6B88 has balance 10000000000000000000000000 +``` + +이는 Hardhat이 로컬 테스트넷을 사용하고 있으며 `eth-network-package`에 의해 생성된 사전에 자금이 충전된 계정을 감지했음을 확인합니다. + +### 로컬에서 dApp 배포 및 테스트 {#deploy-and-test-dapp} + +dApp 개발 환경이 로컬 이더리움 테스트넷에 완전히 연결되었으므로 이제 로컬 테스트넷을 사용하여 dApp에 대한 개발 및 테스트 워크플로를 실행할 수 있습니다. + +`ChipToken.sol` 스마트 계약을 로컬 프로토타이핑 및 개발을 위해 컴파일하고 배포하려면 다음을 실행하세요. + +```python +npx hardhat compile +npx hardhat run scripts/deploy.ts --network localnet +``` + +출력은 다음과 같아야 합니다. + +```python +ChipToken이 0xAb2A01BC351770D09611Ac80f1DE076D56E0487d에 배포되었습니다 +``` + +이제 로컬 dApp에 대해 `simple.js` 테스트를 실행하여 Blackjack dApp의 각 플레이어에게 1000개가 민팅되었는지 확인하세요. + +출력은 다음과 같아야 합니다. + +```python +npx hardhat test --network localnet +``` + +출력은 다음과 같아야 합니다. + +```python +ChipToken + mint + ✔ should mint 1000 chips for PLAYER ONE + + 1 passing (654ms) +``` + +### 검토 {#review-dapp-workflows} + +이 시점에서 dApp 개발 환경을 설정하고, Kurtosis가 생성한 로컬 이더리움 네트워크에 연결했으며, dApp에 대해 컴파일, 배포 및 간단한 테스트를 실행했습니다. + +이제 다양한 네트워크 구성에서 dApp을 테스트하기 위해 기본 네트워크를 구성하는 방법을 살펴보겠습니다. + +## 로컬 이더리움 테스트넷 구성 {#configure-testnet} + +### 클라이언트 구성 및 노드 수 변경 {#configure-client-config-and-num-nodes} + +로컬 이더리움 테스트넷은 개발 또는 테스트하려는 시나리오 및 특정 네트워크 구성에 따라 다양한 EL 및 CL 클라이언트 쌍과 다양한 수의 노드를 사용하도록 구성할 수 있습니다. 즉, 일단 설정되면 맞춤형 로컬 테스트넷을 가동하고 이를 사용하여 동일한 워크플로(배포, 테스트 등)를 실행할 수 있습니다. 다양한 네트워크 구성 하에서 모든 것이 예상대로 작동하는지 확인합니다. 수정할 수 있는 다른 파라미터에 대해 자세히 알아보려면 이 링크를 방문하세요. + +시도해 보세요! JSON 파일을 통해 `eth-network-package`에 다양한 구성 옵션을 전달할 수 있습니다. 이 네트워크 파라미터 JSON 파일은 Kurtosis가 로컬 이더리움 네트워크를 설정하는 데 사용할 특정 구성을 제공합니다. + +기본 구성 파일을 사용하여 다른 EL/CL 쌍을 가진 두 개의 노드를 시작하도록 편집하세요. + +- 노드 1: `geth`/`lighthouse` +- 노드 2: `geth`/`lodestar` +- 노드 3: `geth`/`teku` + +이 구성은 dApp 테스트를 위해 이더리움 노드 구현의 이기종 네트워크를 생성합니다. 이제 구성 파일은 다음과 같이 표시됩니다. + +```yaml +{ + "participants": + [ + { + "el_client_type": "geth", + "el_client_image": "", + "el_client_log_level": "", + "cl_client_type": "lighthouse", + "cl_client_image": "", + "cl_client_log_level": "", + "beacon_extra_params": [], + "el_extra_params": [], + "validator_extra_params": [], + "builder_network_params": null, + }, + { + "el_client_type": "geth", + "el_client_image": "", + "el_client_log_level": "", + "cl_client_type": "lodestar", + "cl_client_image": "", + "cl_client_log_level": "", + "beacon_extra_params": [], + "el_extra_params": [], + "validator_extra_params": [], + "builder_network_params": null, + }, + { + "el_client_type": "geth", + "el_client_image": "", + "el_client_log_level": "", + "cl_client_type": "teku", + "cl_client_image": "", + "cl_client_log_level": "", + "beacon_extra_params": [], + "el_extra_params": [], + "validator_extra_params": [], + "builder_network_params": null, + }, + ], + "network_params": + { + "preregistered_validator_keys_mnemonic": "giant issue aisle success illegal bike spike question tent bar rely arctic volcano long crawl hungry vocal artwork sniff fantasy very lucky have athlete", + "num_validator_keys_per_node": 64, + "network_id": "3151908", + "deposit_contract_address": "0x4242424242424242424242424242424242424242", + "seconds_per_slot": 12, + "genesis_delay": 120, + "capella_fork_epoch": 5, + }, +} +``` + +각 `participants` 구조체는 네트워크의 노드에 매핑되므로 3개의 `participants` 구조체는 Kurtosis에게 네트워크에 3개의 노드를 가동하도록 지시합니다. 각 `participants` 구조체를 통해 특정 노드에 사용되는 EL 및 CL 쌍을 지정할 수 있습니다. + +`network_params` 구조체는 각 노드의 제네시스 파일을 생성하는 데 사용되는 네트워크 설정과 네트워크의 슬롯당 시간(초)과 같은 기타 설정을 구성합니다. + +편집한 파라미터 파일을 원하는 디렉터리에 저장하고(아래 예에서는 바탕화면에 저장됨) 다음을 실행하여 Kurtosis 패키지를 실행하는 데 사용합니다. + +```python +kurtosis clean -a && kurtosis run --enclave local-eth-testnet github.com/kurtosis-tech/eth-network-package "$(cat ~/eth-network-params.json)" +``` + +참고: `kurtosis clean -a` 명령어는 Kurtosis에게 새 테스트넷을 시작하기 전에 이전 테스트넷과 그 내용을 파괴하도록 지시하는 데 사용됩니다. + +다시 한 번, Kurtosis가 잠시 작동하고 진행 중인 개별 단계를 출력합니다. 결과적으로 출력은 다음과 같아야 합니다. + +```python +Starlark code successfully run. No output was returned. +INFO[2023-04-07T11:43:16-04:00] ========================================================== +INFO[2023-04-07T11:43:16-04:00] || Created enclave: local-eth-testnet || +INFO[2023-04-07T11:43:16-04:00] ========================================================== +Name: local-eth-testnet +UUID: bef8c192008e +Status: RUNNING +Creation Time: Fri, 07 Apr 2023 11:41:58 EDT + +========================================= Files Artifacts ========================================= +UUID Name +cc495a8e364a cl-genesis-data +7033fcdb5471 el-genesis-data +a3aef43fc738 genesis-generation-config-cl +8e968005fc9d genesis-generation-config-el +3182cca9d3cd geth-prefunded-keys +8421166e234f prysm-password +d9e6e8d44d99 validator-keystore-0 +23f5ba517394 validator-keystore-1 +4d28dea40b5c validator-keystore-2 + +========================================== User Services ========================================== +UUID Name Ports Status +485e6fde55ae cl-client-0-beacon http: 4000/tcp -> http://127.0.0.1:65010 RUNNING + metrics: 5054/tcp -> http://127.0.0.1:65011 + tcp-discovery: 9000/tcp -> 127.0.0.1:65012 + udp-discovery: 9000/udp -> 127.0.0.1:54455 +73739bd158b2 cl-client-0-validator http: 5042/tcp -> 127.0.0.1:65016 RUNNING + metrics: 5064/tcp -> http://127.0.0.1:65017 +1b0a233cd011 cl-client-1-beacon http: 4000/tcp -> 127.0.0.1:65021 RUNNING + metrics: 8008/tcp -> 127.0.0.1:65023 + tcp-discovery: 9000/tcp -> 127.0.0.1:65024 + udp-discovery: 9000/udp -> 127.0.0.1:56031 + validator-metrics: 5064/tcp -> 127.0.0.1:65022 +949b8220cd53 cl-client-1-validator http: 4000/tcp -> 127.0.0.1:65028 RUNNING + metrics: 8008/tcp -> 127.0.0.1:65030 + tcp-discovery: 9000/tcp -> 127.0.0.1:65031 + udp-discovery: 9000/udp -> 127.0.0.1:60784 + validator-metrics: 5064/tcp -> 127.0.0.1:65029 +c34417bea5fa cl-client-2 http: 4000/tcp -> 127.0.0.1:65037 RUNNING + metrics: 8008/tcp -> 127.0.0.1:65035 + tcp-discovery: 9000/tcp -> 127.0.0.1:65036 + udp-discovery: 9000/udp -> 127.0.0.1:63581 +e19738e6329d el-client-0 engine-rpc: 8551/tcp -> 127.0.0.1:64986 RUNNING + rpc: 8545/tcp -> 127.0.0.1:64988 + tcp-discovery: 30303/tcp -> 127.0.0.1:64987 + udp-discovery: 30303/udp -> 127.0.0.1:55706 + ws: 8546/tcp -> 127.0.0.1:64989 +e904687449d9 el-client-1 engine-rpc: 8551/tcp -> 127.0.0.1:64993 RUNNING + rpc: 8545/tcp -> 127.0.0.1:64995 + tcp-discovery: 30303/tcp -> 127.0.0.1:64994 + udp-discovery: 30303/udp -> 127.0.0.1:58096 + ws: 8546/tcp -> 127.0.0.1:64996 +ad6f401126fa el-client-2 engine-rpc: 8551/tcp -> 127.0.0.1:65003 RUNNING + rpc: 8545/tcp -> 127.0.0.1:65001 + tcp-discovery: 30303/tcp -> 127.0.0.1:65000 + udp-discovery: 30303/udp -> 127.0.0.1:57269 + ws: 8546/tcp -> 127.0.0.1:65002 +12d04a9dbb69 prelaunch-data-generator-1680882122181135513 STOPPED +5b45f9c0504b prelaunch-data-generator-1680882122192182847 STOPPED +3d4aaa75e218 prelaunch-data-generator-1680882122201668972 STOPPED +``` + +축하합니다! 로컬 테스트넷을 1개가 아닌 3개의 노드를 갖도록 성공적으로 구성했습니다. dApp에 대해 이전과 동일한 워크플로(배포 및 테스트)를 실행하려면 `hardhat.config.ts` 구성 파일의 `localnet` 구조체에서 `<$YOUR_PORT>`를 새 3노드 로컬 테스트넷의 `el-client-` 서비스에서 출력된 rpc uri의 포트로 바꾸어 이전과 동일한 작업을 수행하세요. + +## 결론 {#conclusion} + +이것으로 끝입니다! 이 짧은 가이드를 요약하자면 다음과 같습니다. + +- Kurtosis를 사용하여 Docker를 통해 로컬 이더리움 테스트넷을 생성했습니다. +- 로컬 dApp 개발 환경을 로컬 이더리움 네트워크에 연결했습니다. +- 로컬 이더리움 네트워크에서 dApp을 배포하고 간단한 테스트를 실행했습니다. +- 기본 이더리움 네트워크를 3개의 노드를 갖도록 구성했습니다. + +잘된 점, 개선할 점 또는 질문에 대한 답변에 대해 여러분의 의견을 듣고 싶습니다. 주저하지 마시고 [GitHub](https://github.com/kurtosis-tech/kurtosis/issues/new/choose)를 통해 연락하시거나 [이메일을 보내주세요](mailto:feedback@kurtosistech.com)! + +### 기타 예제 및 가이드 {#other-examples-guides} + +[빠른 시작](https://docs.kurtosis.com/quickstart)(Postgres 데이터베이스와 API를 구축)과 [awesome-kurtosis 저장소](https://github.com/kurtosis-tech/awesome-kurtosis)의 다른 예제를 확인해 보시기 바랍니다. 여기에는 다음 패키지를 포함한 훌륭한 예제가 있습니다. + +- 동일한 로컬 이더리움 테스트넷을 가동하지만 트랜잭션 스패머(트랜잭션 시뮬레이션용), 포크 모니터, 연결된 Grafana 및 Prometheus 인스턴스와 같은 추가 서비스가 연결되어 있습니다. +- 동일한 로컬 이더리움 네트워크에 대한 [하위 네트워킹 테스트](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/ethereum-network-partition-test) 수행 diff --git a/public/content/translations/ko/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/index.md b/public/content/translations/ko/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/index.md new file mode 100644 index 00000000000..3f06c083eae --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/index.md @@ -0,0 +1,144 @@ +--- +title: "컨트랙트 크기 제한에 맞서 컨트랙트 축소하기" +description: "스마트 계약이 너무 커지는 것을 방지하기 위해 무엇을 할 수 있을까요?" +author: Markus Waas +lang: ko +tags: [ "Solidity", "스마트 계약", "저장 공간" ] +skill: intermediate +published: 2020-06-26 +source: soliditydeveloper.com +sourceUrl: https://soliditydeveloper.com/max-contract-size +--- + +## 왜 크기 제한이 있나요? {#why-is-there-a-limit} + +[2016년 11월 22일](https://blog.ethereum.org/2016/11/18/hard-fork-no-4-spurious-dragon/)에 스퓨리어스 드래곤(Spurious Dragon) 하드포크는 24.576kb의 스마트 계약 크기 제한을 추가한 [EIP-170](https://eips.ethereum.org/EIPS/eip-170)을 도입했습니다. 솔리디티 개발자로서 컨트랙트에 기능을 점점 더 많이 추가하면 어느 시점에 한계에 도달하게 되며, 배포 시 다음과 같은 오류가 표시됩니다: + +`경고: 컨트랙트 코드 크기가 24576바이트를 초과합니다(스퓨리어스 드래곤(Spurious Dragon)에서 도입된 제한). 이 컨트랙트는 메인넷에 배포되지 않을 수 있습니다. 옵티마이저를 활성화하거나('runs' 값을 낮게 설정!), revert 문자열을 끄거나, 라이브러리를 사용하는 것을 고려해 보세요.` + +이 제한은 서비스 거부(DOS) 공격을 방지하기 위해 도입되었습니다. 컨트랙트에 대한 모든 호출은 가스 측면에서 비교적 저렴합니다. 하지만 이더리움 노드에 대한 컨트랙트 호출의 영향은 호출된 컨트랙트 코드의 크기(디스크에서 코드 읽기, 코드 사전 처리, 머클 증명에 데이터 추가)에 따라 불균형적으로 증가합니다. 공격자가 적은 리소스를 사용하여 다른 사람에게 많은 작업을 유발할 수 있는 상황이 발생하면 DOS 공격의 가능성이 생깁니다. + +원래 블록 가스 한도가 자연스러운 컨트랙트 크기 제한 역할을 했기 때문에 이는 큰 문제가 되지 않았습니다. 당연히, 컨트랙트는 해당 컨트랙트의 모든 바이트코드를 포함하는 트랜잭션 내에서 배포되어야 합니다. 하나의 블록에 해당 트랜잭션 하나만 포함시키면 모든 가스를 사용할 수 있지만, 이는 무한하지 않습니다. [런던 업그레이드](/ethereum-forks/#london) 이후, 블록 가스 한도는 네트워크 수요에 따라 1,500만에서 3,000만 단위 사이에서 변동할 수 있게 되었습니다. + +다음에서는 잠재적 영향력 순으로 몇 가지 방법을 살펴보겠습니다. 체중 감량의 관점에서 생각해 보세요. 목표 체중(이 경우 24kb)에 도달하기 위한 최선의 전략은 영향이 큰 방법에 먼저 집중하는 것입니다. 대부분의 경우 식단을 조절하는 것만으로도 목표에 도달할 수 있지만, 때로는 그 이상이 필요합니다. 그 다음에는 운동(중간 영향)이나 보충제(작은 영향)를 추가할 수도 있습니다. + +## 큰 영향 {#big-impact} + +### 컨트랙트 분리하기 {#separate-your-contracts} + +이 방법이 항상 첫 번째 접근 방식이 되어야 합니다. 컨트랙트를 여러 개의 작은 컨트랙트로 어떻게 분리할 수 있을까요? 일반적으로 이 과정을 통해 컨트랙트에 대한 좋은 아키텍처를 구상하게 됩니다. 코드 가독성 측면에서는 항상 더 작은 컨트랙트가 선호됩니다. 컨트랙트를 분리하려면 다음을 자문해 보세요: + +- 어떤 함수들이 함께 속해 있나요? 각 함수 집합은 자체 컨트랙트에 두는 것이 가장 좋을 수 있습니다. +- 어떤 함수가 컨트랙트 상태를 읽을 필요가 없거나 상태의 특정 하위 집합만 필요로 하나요? +- 저장 공간과 기능을 분리할 수 있나요? + +### 라이브러리 {#libraries} + +저장 공간에서 기능 코드를 분리하는 간단한 방법 중 하나는 [라이브러리](https://solidity.readthedocs.io/en/v0.6.10/contracts.html#libraries)를 사용하는 것입니다. `internal`로 선언하지 마세요. 컴파일 중에 [컨트랙트에 직접 추가](https://ethereum.stackexchange.com/questions/12975/are-internal-functions-in-libraries-not-covered-by-linking)되기 때문입니다. 하지만 `public` 함수를 사용하면 실제로는 별도의 라이브러리 컨트랙트에 있게 됩니다. 라이브러리를 더 편리하게 사용하려면 [`using for`](https://solidity.readthedocs.io/en/v0.6.10/contracts.html#using-for) 사용을 고려해 보세요. + +### 프록시 {#proxies} + +더 발전된 전략은 프록시 시스템을 사용하는 것입니다. 라이브러리는 내부적으로 `DELEGATECALL`을 사용하는데, 이는 호출하는 컨트랙트의 상태로 다른 컨트랙트의 함수를 단순히 실행합니다. 프록시 시스템에 대해 자세히 알아보려면 [이 블로그 게시물](https://hackernoon.com/how-to-make-smart-contracts-upgradable-2612e771d5a2)을 확인하세요. 프록시는 업그레이드 가능성과 같은 더 많은 기능을 제공하지만, 복잡성도 크게 증가시킵니다. 어떤 이유로든 유일한 옵션이 아닌 이상, 단지 컨트랙트 크기를 줄이기 위해 프록시를 추가하는 것은 권장하지 않습니다. + +## 중간 영향 {#medium-impact} + +### 함수 제거하기 {#remove-functions} + +이 방법은 당연하게 들릴 수 있습니다. 함수는 컨트랙트 크기를 상당히 증가시킵니다. + +- **External**: 편의를 위해 `view` 함수를 많이 추가하는 경우가 많습니다. 크기 제한에 도달하기 전까지는 괜찮습니다. 그때는 정말 필수적인 함수를 제외하고 모두 제거하는 것을 고려해야 합니다. +- **Internal**: 함수가 한 번만 호출되는 경우 `internal`/`private` 함수를 제거하고 코드를 인라인으로 처리할 수도 있습니다. + +### 추가 변수 사용 피하기 {#avoid-additional-variables} + +```solidity +function get(uint id) returns (address,address) { + MyStruct memory myStruct = myStructs[id]; + return (myStruct.addr1, myStruct.addr2); +} +``` + +```solidity +function get(uint id) returns (address,address) { + return (myStructs[id].addr1, myStructs[id].addr2); +} +``` + +이처럼 간단한 변경만으로도 0.28kb의 차이를 만들 수 있습니다. 컨트랙트에서 이와 유사한 상황을 많이 찾을 수 있으며, 이것들이 모이면 상당한 크기를 줄일 수 있습니다. + +### 오류 메시지 줄이기 {#shorten-error-message} + +긴 revert 메시지, 특히 다양한 revert 메시지는 컨트랙트 크기를 부풀릴 수 있습니다. 대신 짧은 오류 코드를 사용하고 컨트랙트에서 디코딩하세요. 긴 메시지를 다음과 같이 훨씬 짧게 만들 수 있습니다. + +```solidity +require(msg.sender == owner, "이 컨트랙트의 소유자만 이 함수를 호출할 수 있습니다"); +``` + +```solidity +require(msg.sender == owner, "OW1"); +``` + +### 오류 메시지 대신 사용자 정의 오류 사용하기 + +사용자 정의 오류는 [솔리디티 0.8.4](https://blog.soliditylang.org/2021/04/21/custom-errors/)에서 도입되었습니다. 사용자 정의 오류는 함수처럼 선택자로 ABI 인코딩되므로 컨트랙트의 크기를 줄이는 좋은 방법입니다. + +```solidity +error Unauthorized(); + +if (msg.sender != owner) { + revert Unauthorized(); +} +``` + +### 옵티마이저에서 낮은 실행(run) 값 고려하기 {#consider-a-low-run-value-in-the-optimizer} + +옵티마이저 설정을 변경할 수도 있습니다. 기본값인 200은 함수가 200번 호출되는 것처럼 바이트코드를 최적화한다는 의미입니다. 이 값을 1로 변경하면 기본적으로 옵티마이저에게 각 함수를 한 번만 실행하는 경우에 최적화하도록 지시하는 것입니다. 한 번만 실행하도록 최적화된 함수는 배포 자체에 최적화되었음을 의미합니다. 함수를 실행하는 데 드는 [가스 비용](/developers/docs/gas/)이 증가하므로 이 방법을 사용하지 않는 것이 좋을 수 있습니다. + +## 작은 영향 {#small-impact} + +### 함수에 구조체 전달 피하기 {#avoid-passing-structs-to-functions} + +[ABIEncoderV2](https://solidity.readthedocs.io/en/v0.6.10/layout-of-source-files.html#abiencoderv2)를 사용하고 있다면, 함수에 구조체를 전달하지 않는 것이 도움이 될 수 있습니다. 매개변수를 구조체로 전달하는 대신, 필요한 매개변수를 직접 전달하세요. 이 예시에서는 0.1kb를 추가로 절약했습니다. + +```solidity +function get(uint id) returns (address,address) { + return _get(myStruct); +} + +function _get(MyStruct memory myStruct) private view returns(address,address) { + return (myStruct.addr1, myStruct.addr2); +} +``` + +```solidity +function get(uint id) returns(address,address) { + return _get(myStructs[id].addr1, myStructs[id].addr2); +} + +function _get(address addr1, address addr2) private view returns(address,address) { + return (addr1, addr2); +} +``` + +### 함수와 변수에 올바른 가시성 선언하기 {#declare-correct-visibility-for-functions-and-variables} + +- 외부에서만 호출되는 함수나 변수인가요? `public` 대신 `external`로 선언하세요. +- 컨트랙트 내에서만 호출되는 함수나 변수인가요? `public` 대신 `private` 또는 `internal`로 선언하세요. + +### 수식어(modifier) 제거하기 {#remove-modifiers} + +수식어(Modifier)는 특히 많이 사용될 경우 컨트랙트 크기에 상당한 영향을 미칠 수 있습니다. 수식어를 제거하고 대신 함수를 사용하는 것을 고려해 보세요. + +```solidity +modifier checkStuff() {} + +function doSomething() checkStuff {} +``` + +```solidity +function checkStuff() private {} + +function doSomething() { checkStuff(); } +``` + +이 팁들은 컨트랙트 크기를 크게 줄이는 데 도움이 될 것입니다. 다시 한번 강조하지만, 가장 큰 영향을 위해 가능하다면 항상 컨트랙트를 분리하는 데 집중하세요. diff --git a/public/content/translations/ko/developers/tutorials/eip-1271-smart-contract-signatures/index.md b/public/content/translations/ko/developers/tutorials/eip-1271-smart-contract-signatures/index.md new file mode 100644 index 00000000000..078246e7031 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/eip-1271-smart-contract-signatures/index.md @@ -0,0 +1,101 @@ +--- +title: "EIP-1271: 스마트 계약 서명 및 확인" +description: "EIP-1271을 사용한 스마트 계약 서명 생성 및 확인에 대한 개요입니다. 또한 스마트 계약 개발자가 참고할 수 있는 구체적인 예시를 제공하기 위해 Safe(이전 Gnosis Safe)에서 사용되는 EIP-1271 구현을 살펴봅니다." +author: Nathan H. Leung +lang: ko +tags: [ "eip-1271", "스마트 컨트랙트", "확인", "서명" ] +skill: intermediate +published: 2023-01-12 +--- + +[EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) 표준을 사용하면 스마트 계약이 서명을 확인할 수 있습니다. + +이 튜토리얼에서는 전자 서명, EIP-1271의 배경 및 [Safe](https://safe.global/)(이전 Gnosis Safe)에서 사용하는 EIP-1271의 특정 구현에 대해 간략히 설명합니다. 이 모든 내용은 여러분의 계약에 EIP-1271을 구현하기 위한 시작점이 될 수 있습니다. + +## 서명이란 무엇인가요? + +이 맥락에서 서명(보다 정확하게는 '전자 서명')은 메시지와 해당 메시지가 특정 개인/보낸 사람/주소로부터 왔다는 일종의 증명을 더한 것입니다. + +예를 들어, 전자 서명은 다음과 같을 수 있습니다. + +1. 메시지: '내 이더리움 지갑으로 이 웹사이트에 로그인하고 싶습니다.' +2. 서명자: 내 주소는 `0x000…`입니다. +3. 증명: 여기 `0x000…`인 제가 실제로 이 전체 메시지를 생성했다는 증거가 있습니다(이것은 일반적으로 암호화된 것입니다). + +전자 서명에는 '메시지'와 '서명'이 모두 포함된다는 점에 유의해야 합니다. + +왜 그럴까요? 예를 들어, 당신이 저에게 서명할 계약서를 주었는데, 제가 서명 페이지만 잘라내고 나머지 계약서 없이 제 서명만 돌려준다면 그 계약은 유효하지 않을 것입니다. + +마찬가지로, 전자 서명은 연관된 메시지 없이는 아무 의미가 없습니다! + +## EIP-1271은 왜 존재하나요? + +이더리움 기반 블록체인에서 사용할 전자 서명을 생성하려면 일반적으로 다른 사람은 아무도 모르는 비밀 개인 키가 필요합니다. 이것이 바로 당신의 서명을 당신의 것으로 만드는 것입니다(비밀 키를 모르면 다른 누구도 동일한 서명을 생성할 수 없습니다). + +이더리움 계정(즉, 외부 소유 계정/EOA)에는 개인 키가 연결되어 있으며, 이 개인 키는 웹사이트나 디앱에서 서명을 요청할 때(예: '이더리움으로 로그인') 일반적으로 사용됩니다. + +앱은 ethers.js와 같은 제3자 라이브러리를 사용하여 사용자가 생성한 [서명을 확인할](https://www.alchemy.com/docs/how-to-verify-a-message-signature-on-ethereum) 수 있으며, [사용자의 개인 키를 몰라도](https://en.wikipedia.org/wiki/Public-key_cryptography) 사용자가 서명을 생성했음을 확신할 수 있습니다. + +> 사실, EOA 전자 서명은 공개 키 암호학을 사용하기 때문에 오프체인에서 생성 및 확인할 수 있습니다! 이것이 바로 가스 없는 DAO 투표가 작동하는 방식입니다. 온체인에서 투표를 제출하는 대신 암호화 라이브러리를 사용하여 오프체인에서 전자 서명을 생성하고 확인할 수 있습니다. + +EOA 계정에는 개인 키가 있지만, 스마트 계약 계정에는 개인 키나 비밀 키가 없습니다(따라서 '이더리움으로 로그인' 등은 스마트 계약 계정에서 기본적으로 작동할 수 없습니다). + +EIP-1271이 해결하려는 문제는 다음과 같습니다. 스마트 계약에 서명에 포함할 수 있는 '비밀'이 없는 경우 스마트 계약 서명이 유효한지 어떻게 알 수 있을까요? + +## EIP-1271은 어떻게 작동하나요? + +스마트 계약에는 메시지에 서명하는 데 사용할 수 있는 개인 키가 없습니다. 그렇다면 서명이 진짜인지 어떻게 알 수 있을까요? + +한 가지 아이디어는 스마트 계약에 서명이 진짜인지 _물어보는_ 것입니다! + +EIP-1271은 주어진 서명이 유효한지 스마트 계약에 '질문'하는 이 아이디어를 표준화합니다. + +EIP-1271을 구현하는 계약에는 메시지와 서명을 입력으로 받는 `isValidSignature`라는 함수가 있어야 합니다. 그런 다음 계약은 일부 유효성 검사 로직을 실행하고(사양에서 여기에서 구체적인 내용을 강제하지는 않음) 서명이 유효한지 여부를 나타내는 값을 반환할 수 있습니다. + +`isValidSignature`가 유효한 결과를 반환하면, 이는 계약이 '네, 이 서명 + 메시지를 승인합니다!'라고 말하는 것과 거의 같습니다. + +### 인터페이스 + +다음은 EIP-1271 사양의 정확한 인터페이스입니다(아래에서 `_hash` 매개변수에 대해 이야기하겠지만, 지금은 확인 중인 메시지로 생각하세요). + +```jsx +pragma solidity ^0.5.0;\n\ncontract ERC1271 {\n\n // bytes4(keccak256(\"isValidSignature(bytes32,bytes)\")\n bytes4 constant internal MAGICVALUE = 0x1626ba7e;\n\n /**\n * @dev 제공된 해시에 대해 제공된 서명이 유효한지 여부를 반환해야 합니다.\n * @param _hash 서명할 데이터의 해시\n * @param _signature _hash와 연관된 서명 바이트 배열\n *\n * 함수가 통과하면 bytes4 매직 값 0x1626ba7e를 반환해야 합니다(MUST).\n * 상태를 수정해서는 안 됩니다(MUST NOT)(solc < 0.5의 경우 STATICCALL 사용, solc > 0.5의 경우 view 한정자 사용).\n * 외부 호출을 허용해야 합니다(MUST).\n */\n function isValidSignature(\n bytes32 _hash,\n bytes memory _signature)\n public\n view\n returns (bytes4 magicValue);\n} +``` + +## 예제 EIP-1271 구현: Safe + +계약은 `isValidSignature`를 여러 가지 방법으로 구현할 수 있습니다. 사양에서는 정확한 구현에 대해 많이 언급하지 않습니다. + +EIP-1271을 구현하는 주목할 만한 계약 중 하나는 Safe(이전 Gnosis Safe)입니다. + +Safe의 코드에서 `isValidSignature`는 [두 가지 방법](https://ethereum.stackexchange.com/questions/122635/signing-messages-as-a-gnosis-safe-eip1271-support)으로 서명을 생성하고 확인할 수 있도록 [구현](https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/CompatibilityFallbackHandler.sol)되었습니다. + +1. 온체인 메시지 + 1. 생성: Safe 소유자는 메시지에 '서명'하기 위해 새로운 Safe 트랜잭션을 생성하고 메시지를 데이터로 트랜잭션에 전달합니다. 충분한 수의 소유자가 트랜잭션에 서명하여 멀티시그 임계값에 도달하면 트랜잭션이 브로드캐스트되고 실행됩니다. 트랜잭션에는 메시지를 '승인된' 메시지 목록에 추가하는 `signMessage(bytes calldata _data)`라는 Safe 함수가 있습니다. + 2. 확인: Safe 계약에서 `isValidSignature`를 호출하고, 확인할 메시지를 메시지 매개변수로 전달하고 [서명 매개변수에는 빈 값](https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/CompatibilityFallbackHandler.sol#L32)(즉, `0x`)을 전달합니다. Safe는 서명 매개변수가 비어 있는 것을 보고 서명을 암호학적으로 확인하는 대신, 메시지가 '승인된' 메시지 목록에 있는지 확인합니다. +2. 오프체인 메시지: + 1. 생성: Safe 소유자는 오프체인에서 메시지를 생성한 다음, 멀티시그 승인 임계값을 넘을 만큼 충분한 서명이 모일 때까지 다른 Safe 소유자가 각자 개별적으로 메시지에 서명하도록 합니다. + 2. 확인: `isValidSignature`를 호출합니다. 메시지 매개변수에는 확인할 메시지를 전달합니다. 서명 매개변수에는 각 Safe 소유자의 개별 서명을 모두 차례로 연결하여 전달합니다. Safe는 임계값을 충족하기에 충분한 서명이 있는지 **그리고** 각 서명이 유효한지 확인합니다. 그렇다면 서명 확인이 성공했음을 나타내는 값을 반환합니다. + +## `_hash` 매개변수는 정확히 무엇인가요? 전체 메시지를 전달하지 않는 이유는 무엇인가요? + +[EIP-1271 인터페이스](https://eips.ethereum.org/EIPS/eip-1271)의 `isValidSignature` 함수가 메시지 자체를 받지 않고 대신 `_hash` 매개변수를 받는다는 것을 눈치채셨을 겁니다. 이는 `isValidSignature`에 전체 임의 길이 메시지를 전달하는 대신, 메시지의 32바이트 해시(일반적으로 keccak256)를 전달한다는 것을 의미합니다. + +calldata의 각 바이트, 즉 스마트 계약 함수에 전달되는 함수 매개변수 데이터는 [16 가스(0바이트인 경우 4 가스)의 비용](https://eips.ethereum.org/EIPS/eip-2028)이 들기 때문에 메시지가 길 경우 많은 가스를 절약할 수 있습니다. + +### 이전 EIP-1271 사양 + +실제 사용되는 EIP-1271 사양 중에는 첫 번째 매개변수 유형이 `bytes`(고정 길이 `bytes32` 대신 임의 길이)이고 매개변수 이름이 `message`인 `isValidSignature` 함수를 가진 사양이 있습니다. 이것은 EIP-1271 표준의 [이전 버전](https://github.com/safe-global/safe-contracts/issues/391#issuecomment-1075427206)입니다. + +## 내 계약에 EIP-1271을 어떻게 구현해야 하나요? + +사양은 이 부분에서 매우 개방적입니다. Safe 구현에는 몇 가지 좋은 아이디어가 있습니다. + +- 계약의 '소유자'로부터의 EOA 서명을 유효한 것으로 간주할 수 있습니다. +- 승인된 메시지 목록을 저장하고 해당 메시지만 유효한 것으로 간주할 수 있습니다. + +결국, 계약 개발자인 당신에게 달려 있습니다! + +## 결론 + +[EIP-1271](https://eips.ethereum.org/EIPS/eip-1271)은 스마트 계약이 서명을 확인할 수 있도록 하는 다재다능한 표준입니다. 이 표준은 스마트 계약이 EOA처럼 작동할 수 있는 길을 열어주며, 예를 들어 '이더리움으로 로그인'이 스마트 계약과 함께 작동하는 방법을 제공합니다. 또한 여러 가지 방식으로 구현할 수 있습니다(Safe는 고려해 볼 만한 간단하지 않으면서도 흥미로운 구현을 가지고 있습니다). diff --git a/public/content/translations/ko/developers/tutorials/erc-721-vyper-annotated-code/index.md b/public/content/translations/ko/developers/tutorials/erc-721-vyper-annotated-code/index.md new file mode 100644 index 00000000000..b5a29deee75 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/erc-721-vyper-annotated-code/index.md @@ -0,0 +1,637 @@ +--- +title: "Vyper ERC-721 계약 살펴보기" +description: "Ryuya Nakamura의 ERC-721 계약 및 작동 원리" +author: Ori Pomerantz +lang: ko +tags: [ "Vyper", "erc-721", "Python" ] +skill: beginner +published: 2021-04-01 +--- + +## 소개 {#introduction} + +[ERC-721](/developers/docs/standards/tokens/erc-721/) 표준은 대체 불가능한 토큰(NFT)의 소유권을 보유하는 데 사용됩니다. +[ERC-20](/developers/docs/standards/tokens/erc-20/) 토큰은 개별 토큰 간에 차이가 없으므로 상품처럼 작동합니다. +이와 대조적으로 ERC-721 토큰은 서로 다른 고양이 +만화 또는 서로 다른 부동산 소유권과 같이 유사하지만 동일하지는 않은 자산을 위해 설계되었습니다. + +이 글에서는 [Ryuya Nakamura의 ERC-721 계약](https://github.com/vyperlang/vyper/blob/master/examples/tokens/ERC721.vy)을 분석합니다. +이 계약은 파이썬과 유사한 계약 언어인 [Vyper](https://vyper.readthedocs.io/en/latest/index.html)로 작성되었으며, 솔리디티보다 안전하지 않은 코드를 작성하기 어렵게 설계되었습니다. + +## 계약 {#contract} + +```python +# @dev ERC-721 대체 불가능한 토큰 표준 구현 +# @author Ryuya Nakamura (@nrryuya) +# 수정 출처: https://github.com/vyperlang/vyper/blob/de74722bf2d8718cca46902be165f9fe0e3641dd/examples/tokens/ERC721.vy +``` + +Vyper에서는 파이썬에서처럼 주석이 해시(`#`)로 시작하여 줄 끝까지 이어집니다. `@`를 포함하는 주석은 [NatSpec](https://vyper.readthedocs.io/en/latest/natspec.html)에서 사람이 읽을 수 있는 개발문서를 생성하는 데 사용됩니다. + +```python +from vyper.interfaces import ERC721 + +implements: ERC721 +``` + +ERC-721 인터페이스는 Vyper 언어에 내장되어 있습니다. +[여기에서 코드 정의를 볼 수 있습니다](https://github.com/vyperlang/vyper/blob/master/vyper/builtin_interfaces/ERC721.py). +인터페이스 정의는 Vyper가 아닌 파이썬으로 작성되었습니다. 인터페이스는 블록체인 내에서뿐만 아니라 외부 클라이언트에서 블록체인으로 트랜잭션을 보낼 때도 사용되며, 이 클라이언트는 파이썬으로 작성될 수 있기 때문입니다. + +첫 번째 줄은 인터페이스를 가져오고, 두 번째 줄은 여기서 구현하고 있음을 지정합니다. + +### ERC721Receiver 인터페이스 {#receiver-interface} + +```python +# safeTransferFrom()에 의해 호출되는 계약의 인터페이스 +interface ERC721Receiver: + def onERC721Received( +``` + +ERC-721은 두 가지 유형의 전송을 지원합니다. + +- `transferFrom`은 전송자가 모든 대상 주소를 지정하고 전송에 대한 책임을 전송자에게 부여할 수 있도록 합니다. 이는 잘못된 주소로 전송할 수 있음을 의미하며, 이 경우 NFT는 영원히 손실됩니다. +- `safeTransferFrom`은 대상 주소가 계약인지 확인합니다. 만약 그렇다면, ERC-721 계약은 수신 계약에 NFT를 수신할 것인지 묻습니다. + +`safeTransferFrom` 요청에 응답하려면 수신 계약이 `ERC721Receiver`를 구현해야 합니다. + +```python + _operator: address, + _from: address, +``` + +`_from` 주소는 토큰의 현재 소유자입니다. `_operator` 주소는 전송을 요청한 주소입니다(허용량 때문에 이 둘은 같지 않을 수 있습니다). + +```python + _tokenId: uint256, +``` + +ERC-721 토큰 ID는 256비트입니다. 일반적으로 토큰이 나타내는 것에 대한 설명을 해싱하여 생성됩니다. + +```python + _data: Bytes[1024] +``` + +요청은 최대 1024바이트의 사용자 데이터를 가질 수 있습니다. + +```python + ) -> bytes32: view +``` + +계약이 실수로 전송을 수락하는 경우를 방지하기 위해 반환 값은 부울이 아니라 특정 값을 가진 256비트입니다. + +이 함수는 `view`이며, 이는 블록체인의 상태를 읽을 수는 있지만 수정할 수는 없음을 의미합니다. + +### 이벤트 {#events} + +[이벤트](https://media.consensys.net/technical-introduction-to-events-and-logs-in-ethereum-a074d65dd61e)는 블록체인 외부의 사용자와 서버에 이벤트를 알리기 위해 발생됩니다. 이벤트의 내용은 블록체인의 계약에서 사용할 수 없습니다. + +```python +# @dev 모든 NFT의 소유권이 어떤 메커니즘으로든 변경될 때 발생합니다. 이 이벤트는 NFT가 +# 생성(`from` == 0)되거나 소멸(`to` == 0)될 때 발생합니다. 예외: 계약 생성 중에는 +# Transfer를 발생시키지 않고 여러 개의 NFT를 생성하고 할당할 수 있습니다. 전송 시점에 +# 해당 NFT에 대해 승인된 주소(있는 경우)는 없음으로 재설정됩니다. +# @param _from NFT의 전송자(주소가 0 주소인 경우 토큰 생성을 나타냄). +# @param _to NFT의 수신자(주소가 0 주소인 경우 토큰 소멸을 나타냄). +# @param _tokenId 전송된 NFT. +event Transfer: + sender: indexed(address) + receiver: indexed(address) + tokenId: indexed(uint256) +``` + +이는 금액 대신 `tokenId`를 보고한다는 점을 제외하면 ERC-20 전송 이벤트와 유사합니다. +아무도 0 주소를 소유하지 않으므로, 관례적으로 토큰의 생성과 소멸을 보고하는 데 사용합니다. + +```python +# @dev NFT에 대한 승인된 주소가 변경되거나 재확인될 때 발생합니다. 0 주소는 +# 승인된 주소가 없음을 나타냅니다. 전송 이벤트가 발생하면 이는 또한 +# 해당 NFT에 대한 승인된 주소(있는 경우)가 없음으로 재설정됨을 나타냅니다. +# @param _owner NFT의 소유자. +# @param _approved 승인하려는 주소. +# @param _tokenId 승인하려는 NFT. +event Approval: + owner: indexed(address) + approved: indexed(address) + tokenId: indexed(uint256) +``` + +ERC-721 승인은 ERC-20 허용량과 유사합니다. 특정 주소는 특정 토큰을 전송할 수 있습니다. 이는 계약이 토큰을 수락할 때 응답할 수 있는 메커니즘을 제공합니다. 계약은 이벤트를 수신할 수 없으므로, 토큰을 전송하기만 하면 계약은 이를 "알지" 못합니다. 이러한 방식으로 소유자는 먼저 승인을 제출한 다음 계약에 요청을 보냅니다: "토큰 X를 전송하도록 승인했으니, ...해 주세요." + +이는 ERC-721 표준을 ERC-20 표준과 유사하게 만들기 위한 설계상의 선택입니다. ERC-721 토큰은 대체 불가능하기 때문에, 계약은 토큰의 소유권을 보고 특정 토큰을 받았음을 식별할 수도 있습니다. + +```python +# @dev 소유자에 대해 운영자가 활성화 또는 비활성화될 때 발생합니다. 운영자는 +# 소유자의 모든 NFT를 관리할 수 있습니다. +# @param _owner NFT의 소유자. +# @param _operator 운영자 권한을 설정할 주소. +# @param _approved 운영자 권한 상태(운영자 권한이 부여되면 true, 취소되면 false). +event ApprovalForAll: + owner: indexed(address) + operator: indexed(address) + approved: bool +``` + +위임장과 유사하게 특정 유형(특정 계약에 의해 관리되는)의 계정의 모든 토큰을 관리할 수 있는 운영자가 있으면 유용할 때가 있습니다. 예를 들어, 6개월 동안 연락이 없으면 자산을 상속인에게 분배하는 계약에 이러한 권한을 부여할 수 있습니다(상속인 중 한 명이 요청하는 경우, 계약은 트랜잭션에 의해 호출되지 않으면 아무것도 할 수 없음). ERC-20에서는 상속 계약에 높은 허용량을 부여할 수 있지만, ERC-721은 토큰이 대체 불가능하기 때문에 작동하지 않습니다. 이것이 그에 상응하는 것입니다. + +`approved` 값은 이벤트가 승인을 위한 것인지, 아니면 승인 철회를 위한 것인지를 알려줍니다. + +### 상태 변수 {#state-vars} + +이 변수에는 토큰의 현재 상태, 즉 어떤 토큰이 사용 가능하고 누가 소유하고 있는지가 포함됩니다. 이들 대부분은 두 유형 사이에 존재하는 단방향 매핑인 `HashMap` 객체입니다[https://vyper.readthedocs.io/en/latest/types.html#mappings]. + +```python +# @dev NFT ID에서 이를 소유한 주소로의 매핑. +idToOwner: HashMap[uint256, address] + +# @dev NFT ID에서 승인된 주소로의 매핑. +idToApprovals: HashMap[uint256, address] +``` + +이더리움에서 사용자와 계약 신원은 160비트 주소로 표시됩니다. 이 두 변수는 토큰 ID에서 소유자 및 전송이 승인된 자(각각 최대 1명)로 매핑됩니다. 이더리움에서 초기화되지 않은 데이터는 항상 0이므로, 소유자나 승인된 전송자가 없는 경우 해당 토큰의 값은 0입니다. + +```python +# @dev 소유자 주소에서 토큰 수로의 매핑. +ownerToNFTokenCount: HashMap[address, uint256] +``` + +이 변수는 각 소유자의 토큰 수를 보유합니다. 소유자에서 토큰으로의 매핑이 없으므로, 특정 소유자가 소유한 토큰을 식별하는 유일한 방법은 블록체인의 이벤트 기록을 되돌아보고 적절한 `Transfer` 이벤트를 보는 것입니다. 이 변수를 사용하여 모든 NFT를 가지고 있고 더 이상 시간을 거슬러 볼 필요가 없을 때를 알 수 있습니다. + +이 알고리즘은 사용자 인터페이스와 외부 서버에서만 작동합니다. 블록체인 자체에서 실행되는 코드는 과거 이벤트를 읽을 수 없습니다. + +```python +# @dev 소유자 주소에서 운영자 주소 매핑으로의 매핑. +ownerToOperators: HashMap[address, HashMap[address, bool]] +``` + +하나의 계정은 여러 운영자를 가질 수 있습니다. 단순한 `HashMap`으로는 각 키가 단일 값으로 연결되기 때문에 이를 추적하기에 충분하지 않습니다. 대신, 값으로 `HashMap[address, bool]`를 사용할 수 있습니다. 기본적으로 각 주소의 값은 `False`이며, 이는 운영자가 아님을 의미합니다. 필요에 따라 값을 `True`로 설정할 수 있습니다. + +```python +# @dev 토큰을 발행할 수 있는 발행자의 주소 +minter: address +``` + +새로운 토큰은 어떻게든 생성되어야 합니다. 이 계약에는 이를 수행할 수 있는 단일 엔티티, 즉 `minter`가 있습니다. 예를 들어, 게임에는 이것으로 충분할 것입니다. 다른 목적을 위해서는 더 복잡한 비즈니스 로직을 생성해야 할 수도 있습니다. + +```python +# @dev 인터페이스 ID에서 지원 여부에 대한 부울로의 매핑 +supportedInterfaces: HashMap[bytes32, bool] + +# @dev ERC165의 ERC165 인터페이스 ID +ERC165_INTERFACE_ID: constant(bytes32) = 0x0000000000000000000000000000000000000000000000000000000001ffc9a7 + +# @dev ERC721의 ERC165 인터페이스 ID +ERC721_INTERFACE_ID: constant(bytes32) = 0x0000000000000000000000000000000000000000000000000000000080ac58cd +``` + +[ERC-165](https://eips.ethereum.org/EIPS/eip-165)는 계약이 애플리케이션과 통신하는 방법, 즉 어떤 ERC를 준수하는지 공개하는 메커니즘을 지정합니다. 이 경우, 계약은 ERC-165와 ERC-721을 준수합니다. + +### 함수 {#functions} + +이들은 실제로 ERC-721을 구현하는 함수입니다. + +#### 생성자 {#constructor} + +```python +@external +def __init__(): +``` + +Vyper에서는 파이썬에서처럼 생성자 함수를 `__init__`이라고 합니다. + +```python + """ + @dev 계약 생성자. + """ +``` + +파이썬과 Vyper에서는 여러 줄 문자열(`"""`로 시작하고 끝나는)을 지정하고 어떤 방식으로도 사용하지 않음으로써 주석을 만들 수도 있습니다. 이러한 주석에는 [NatSpec](https://vyper.readthedocs.io/en/latest/natspec.html)도 포함될 수 있습니다. + +```python + self.supportedInterfaces[ERC165_INTERFACE_ID] = True + self.supportedInterfaces[ERC721_INTERFACE_ID] = True + self.minter = msg.sender +``` + +상태 변수에 액세스하려면 `self.<변수 이름>`을(를) 사용합니다.`(파이썬에서와 동일합니다). + +#### 뷰 함수 {#views} + +이 함수들은 블록체인의 상태를 수정하지 않으므로 외부에서 호출될 경우 무료로 실행될 수 있습니다. 뷰 함수가 계약에 의해 호출되더라도 모든 노드에서 실행되어야 하므로 가스가 소모됩니다. + +```python +@view +@external +``` + +함수 정의 이전에 `@` 기호로 시작하는 이러한 키워드를 _데코레이션_이라고 합니다. 함수가 호출될 수 있는 상황을 지정합니다. + +- `@view`는 이 함수가 뷰임을 지정합니다. +- `@external`은 이 특정 함수가 트랜잭션 및 다른 계약에 의해 호출될 수 있음을 지정합니다. + +```python +def supportsInterface(_interfaceID: bytes32) -> bool: +``` + +파이썬과 달리 Vyper는 [정적 타입 언어](https://wikipedia.org/wiki/Type_system#Static_type_checking)입니다. +[데이터 유형](https://vyper.readthedocs.io/en/latest/types.html)을 식별하지 않고는 변수나 함수 매개변수를 선언할 수 없습니다. 이 경우 입력 매개변수는 256비트 값인 `bytes32`입니다(256비트는 [이더리움 가상 머신](/developers/docs/evm/)의 네이티브 워드 크기입니다). 출력은 부울 값입니다. 관례적으로 함수 매개변수의 이름은 밑줄(`_`)로 시작합니다. + +```python + """ + @dev 인터페이스 식별은 ERC-165에 지정됩니다. + @param _interfaceID 인터페이스의 ID + """ + return self.supportedInterfaces[_interfaceID] +``` + +생성자(`__init__`)에서 설정된 `self.supportedInterfaces` HashMap에서 값을 반환합니다. + +```python +### 뷰 함수 ### + +``` + +이들은 토큰에 대한 정보를 사용자 및 다른 계약에서 사용할 수 있도록 하는 뷰 함수입니다. + +```python +@view +@external +def balanceOf(_owner: address) -> uint256: + """ + @dev `_owner`가 소유한 NFT 수를 반환합니다. + `_owner`가 0 주소인 경우 예외를 발생시킵니다. 0 주소에 할당된 NFT는 유효하지 않은 것으로 간주됩니다. + @param _owner 잔액을 쿼리할 주소. + """ + assert _owner != ZERO_ADDRESS +``` + +이 줄은 `_owner`가 0이 아님을 [주장](https://vyper.readthedocs.io/en/latest/statements.html#assert)합니다. 만약 그렇다면 오류가 발생하고 작업이 되돌려집니다. + +```python + return self.ownerToNFTokenCount[_owner] + +@view +@external +def ownerOf(_tokenId: uint256) -> address: + """ + @dev NFT 소유자의 주소를 반환합니다. + `_tokenId`가 유효한 NFT가 아닌 경우 예외를 발생시킵니다. + @param _tokenId NFT의 식별자. + """ + owner: address = self.idToOwner[_tokenId] + # `_tokenId`가 유효한 NFT가 아닌 경우 예외를 발생시킵니다 + assert owner != ZERO_ADDRESS + return owner +``` + +이더리움 가상 머신(EVM)에서 값이 저장되지 않은 저장 공간은 모두 0입니다. +`_tokenId`에 토큰이 없으면 `self.idToOwner[_tokenId]`의 값은 0입니다. 이 경우 함수는 되돌려집니다. + +```python +@view +@external +def getApproved(_tokenId: uint256) -> address: + """ + @dev 단일 NFT에 대한 승인된 주소를 가져옵니다. + `_tokenId`가 유효한 NFT가 아닌 경우 예외를 발생시킵니다. + @param _tokenId 승인을 쿼리할 NFT의 ID. + """ + # `_tokenId`가 유효한 NFT가 아닌 경우 예외를 발생시킵니다 + assert self.idToOwner[_tokenId] != ZERO_ADDRESS + return self.idToApprovals[_tokenId] +``` + +`getApproved`는 0을 반환할 _수_ 있습니다. 토큰이 유효하면 `self.idToApprovals[_tokenId]`를 반환합니다. +승인자가 없으면 그 값은 0입니다. + +```python +@view +@external +def isApprovedForAll(_owner: address, _operator: address) -> bool: + """ + @dev `_operator`가 `_owner`에 대해 승인된 운영자인지 확인합니다. + @param _owner NFT를 소유한 주소. + @param _operator 소유자를 대신하여 행동하는 주소. + """ + return (self.ownerToOperators[_owner])[_operator] +``` + +이 함수는 `_operator`가 이 계약에서 `_owner`의 모든 토큰을 관리할 수 있는지 확인합니다. +여러 운영자가 있을 수 있으므로 이는 2단계 HashMap입니다. + +#### 전송 헬퍼 함수 {#transfer-helpers} + +이 함수는 토큰 전송 또는 관리의 일부인 작업을 구현합니다. + +```python + +### 전송 함수 헬퍼 ### + +@view +@internal +``` + +이 데코레이션, `@internal`은 함수가 동일한 계약 내의 다른 함수에서만 액세스할 수 있음을 의미합니다. 관례적으로 이러한 함수 이름도 밑줄(`_`)로 시작합니다. + +```python +def _isApprovedOrOwner(_spender: address, _tokenId: uint256) -> bool: + """ + @dev 주어진 지출자가 주어진 토큰 ID를 전송할 수 있는지 여부를 반환합니다. + @param spender 쿼리할 지출자의 주소 + @param tokenId 전송될 토큰의 uint256 ID + @return bool msg.sender가 주어진 토큰 ID에 대해 승인되었는지, + 소유자의 운영자인지, 또는 토큰의 소유자인지 여부 + """ + owner: address = self.idToOwner[_tokenId] + spenderIsOwner: bool = owner == _spender + spenderIsApproved: bool = _spender == self.idToApprovals[_tokenId] + spenderIsApprovedForAll: bool = (self.ownerToOperators[owner])[_spender] + return (spenderIsOwner or spenderIsApproved) or spenderIsApprovedForAll +``` + +주소가 토큰을 전송할 수 있도록 허용되는 세 가지 방법이 있습니다. + +1. 주소가 토큰의 소유자입니다 +2. 주소가 해당 토큰을 사용하도록 승인되었습니다 +3. 주소는 토큰 소유자의 운영자입니다 + +위의 함수는 상태를 변경하지 않으므로 뷰가 될 수 있습니다. 운영 비용을 줄이기 위해, 뷰가 될 _수_ 있는 모든 함수는 뷰가 되어야 _합니다_. + +```python +@internal +def _addTokenTo(_to: address, _tokenId: uint256): + """ + @dev 주어진 주소에 NFT 추가 + `_tokenId`가 누군가에 의해 소유된 경우 예외를 발생시킵니다. + """ + # `_tokenId`가 누군가에 의해 소유된 경우 예외를 발생시킵니다 + assert self.idToOwner[_tokenId] == ZERO_ADDRESS + # 소유자 변경 + self.idToOwner[_tokenId] = _to + # 수량 추적 변경 + self.ownerToNFTokenCount[_to] += 1 + + +@internal +def _removeTokenFrom(_from: address, _tokenId: uint256): + """ + @dev 주어진 주소에서 NFT 제거 + `_from`이 현재 소유자가 아닌 경우 예외를 발생시킵니다. + """ + # `_from`이 현재 소유자가 아닌 경우 예외를 발생시킵니다 + assert self.idToOwner[_tokenId] == _from + # 소유자 변경 + self.idToOwner[_tokenId] = ZERO_ADDRESS + # 수량 추적 변경 + self.ownerToNFTokenCount[_from] -= 1 +``` + +전송에 문제가 발생하면 호출을 되돌립니다. + +```python +@internal +def _clearApproval(_owner: address, _tokenId: uint256): + """ + @dev 주어진 주소의 승인 취소 + `_owner`가 현재 소유자가 아닌 경우 예외를 발생시킵니다. + """ + # `_owner`가 현재 소유자가 아닌 경우 예외를 발생시킵니다 + assert self.idToOwner[_tokenId] == _owner + if self.idToApprovals[_tokenId] != ZERO_ADDRESS: + # 승인 재설정 + self.idToApprovals[_tokenId] = ZERO_ADDRESS +``` + +필요한 경우에만 값을 변경합니다. 상태 변수는 저장 공간에 있습니다. 저장 공간에 쓰는 것은 EVM(이더리움 가상 머신)이 수행하는 가장 비싼 작업 중 하나입니다([가스](/developers/docs/gas/) 측면에서). 따라서 기존 값을 쓰는 것조차 높은 비용이 들기 때문에 이를 최소화하는 것이 좋습니다. + +```python +@internal +def _transferFrom(_from: address, _to: address, _tokenId: uint256, _sender: address): + """ + @dev NFT 전송 실행. + `msg.sender`가 현재 소유자, 승인된 운영자 또는 이 NFT에 대해 승인된 주소가 아닌 경우 예외를 발생시킵니다. + (참고: `msg.sender`는 비공개 함수에서 허용되지 않으므로 `_sender`를 전달합니다.) + `_to`가 0 주소인 경우 예외를 발생시킵니다. + `_from`이 현재 소유자가 아닌 경우 예외를 발생시킵니다. + `_tokenId`가 유효한 NFT가 아닌 경우 예외를 발생시킵니다. + """ +``` + +토큰을 전송하는 두 가지 방법(일반 및 안전)이 있지만, 감사를 더 쉽게 하기 위해 코드를 한 곳에서만 수행하기 위해 이 내부 함수를 사용합니다. + +```python + # 요구 사항 확인 + assert self._isApprovedOrOwner(_sender, _tokenId) + # `_to`가 0 주소인 경우 예외를 발생시킵니다 + assert _to != ZERO_ADDRESS + # 승인 취소. `_from`이 현재 소유자가 아닌 경우 예외를 발생시킵니다 + self._clearApproval(_from, _tokenId) + # NFT 제거. `_tokenId`가 유효한 NFT가 아닌 경우 예외를 발생시킵니다 + self._removeTokenFrom(_from, _tokenId) + # NFT 추가 + self._addTokenTo(_to, _tokenId) + # 전송 기록 + log Transfer(_from, _to, _tokenId) +``` + +Vyper에서 이벤트를 발생시키려면 `log` 문을 사용합니다([자세한 내용은 여기 참조](https://vyper.readthedocs.io/en/latest/event-logging.html#event-logging)). + +#### 전송 함수 {#transfer-funs} + +```python + +### 전송 함수 ### + +@external +def transferFrom(_from: address, _to: address, _tokenId: uint256): + """ + @dev `msg.sender`가 현재 소유자, 승인된 운영자 또는 이 NFT에 대해 승인된 주소가 아닌 경우 예외를 발생시킵니다. + `_from`이 현재 소유자가 아닌 경우 예외를 발생시킵니다. + `_to`가 0 주소인 경우 예외를 발생시킵니다. + `_tokenId`가 유효한 NFT가 아닌 경우 예외를 발생시킵니다. + @notice 호출자는 `_to`가 NFT를 수신할 수 있는지 확인해야 할 책임이 있으며, 그렇지 않으면 영구적으로 손실될 수 있습니다. + @param _from NFT의 현재 소유자. + @param _to 새로운 소유자. + @param _tokenId 전송할 NFT. + """ + self._transferFrom(_from, _to, _tokenId, msg.sender) +``` + +이 함수를 사용하면 임의의 주소로 전송할 수 있습니다. 주소가 사용자이거나 토큰을 전송하는 방법을 아는 계약이 아닌 한, 전송하는 모든 토큰은 해당 주소에 갇혀 쓸모없게 됩니다. + +```python +@external +def safeTransferFrom( + _from: address, + _to: address, + _tokenId: uint256, + _data: Bytes[1024]=b"" + ): + """ + @dev 한 주소에서 다른 주소로 NFT의 소유권을 이전합니다. + `msg.sender`가 현재 소유자, 승인된 운영자 또는 이 NFT에 대해 승인된 주소가 아닌 경우 예외를 발생시킵니다. + `_from`이 현재 소유자가 아닌 경우 예외를 발생시킵니다. + `_to`가 0 주소인 경우 예외를 발생시킵니다. + `_tokenId`가 유효한 NFT가 아닌 경우 예외를 발생시킵니다. + `_to`가 스마트 계약인 경우 `_to`에서 `onERC721Received`를 호출하고 반환 값이 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`가 아닌 경우 예외를 발생시킵니다. + 참고: bytes4는 패딩이 있는 bytes32로 표시됩니다. + @param _from NFT의 현재 소유자. + @param _to 새로운 소유자. + @param _tokenId 전송할 NFT. + @param _data 지정된 형식이 없는 추가 데이터, `_to` 호출 시 전송됩니다. + """ + self._transferFrom(_from, _to, _tokenId, msg.sender) +``` + +어쨌든 문제가 발생하면 되돌릴 것이므로 먼저 전송을 수행해도 괜찮습니다. 그러면 호출에서 수행된 모든 작업이 취소됩니다. + +```python + if _to.is_contract: # `_to`가 계약 주소인지 확인 +``` + +먼저 주소가 계약인지(코드가 있는지) 확인합니다. 그렇지 않은 경우 사용자 주소라고 가정하고 사용자는 토큰을 사용하거나 전송할 수 있습니다. 그러나 그것이 당신을 잘못된 안도감에 빠지게 하지는 마십시오. `safeTransferFrom`을 사용하더라도 아무도 개인 키를 모르는 주소로 토큰을 전송하면 토큰을 잃을 수 있습니다. + +```python + returnValue: bytes32 = ERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) +``` + +대상 계약을 호출하여 ERC-721 토큰을 수신할 수 있는지 확인합니다. + +```python + # 전송 대상이 'onERC721Received'를 구현하지 않는 계약인 경우 예외를 발생시킵니다 + assert returnValue == method_id("onERC721Received(address,address,uint256,bytes)", output_type=bytes32) +``` + +대상이 계약이지만 ERC-721 토큰을 허용하지 않거나(또는 이 특정 전송을 허용하지 않기로 결정한) 경우 되돌립니다. + +```python +@external +def approve(_approved: address, _tokenId: uint256): + """ + @dev NFT에 대해 승인된 주소를 설정하거나 재확인합니다. 0 주소는 승인된 주소가 없음을 나타냅니다. + `msg.sender`가 현재 NFT 소유자이거나 현재 소유자의 승인된 운영자가 아닌 경우 예외를 발생시킵니다. + `_tokenId`가 유효한 NFT가 아닌 경우 예외를 발생시킵니다. (참고: EIP에 기록되지 않음) + `_approved`가 현재 소유자인 경우 예외를 발생시킵니다. (참고: EIP에 기록되지 않음) + @param _approved 주어진 NFT ID에 대해 승인될 주소. + @param _tokenId 승인될 토큰의 ID. + """ + owner: address = self.idToOwner[_tokenId] + # `_tokenId`가 유효한 NFT가 아닌 경우 예외를 발생시킵니다 + assert owner != ZERO_ADDRESS + # `_approved`가 현재 소유자인 경우 예외를 발생시킵니다 + assert _approved != owner +``` + +관례적으로 승인자를 두지 않으려면 자신을 지정하는 것이 아니라 0 주소를 지정합니다. + +```python + # 요구 사항 확인 + senderIsOwner: bool = self.idToOwner[_tokenId] == msg.sender + senderIsApprovedForAll: bool = (self.ownerToOperators[owner])[msg.sender] + assert (senderIsOwner or senderIsApprovedForAll) +``` + +승인을 설정하려면 소유자이거나 소유자가 승인한 운영자여야 합니다. + +```python + # 승인 설정 + self.idToApprovals[_tokenId] = _approved + log Approval(owner, _approved, _tokenId) + + +@external +def setApprovalForAll(_operator: address, _approved: bool): + """ + @dev 제3자("운영자")가 `msg.sender`의 모든 자산을 관리할 수 있도록 승인을 활성화하거나 비활성화합니다. 또한 ApprovalForAll 이벤트를 발생시킵니다. + `_operator`가 `msg.sender`인 경우 예외를 발생시킵니다. (참고: EIP에 기록되지 않음) + @notice 이는 전송자가 당시 토큰을 소유하지 않은 경우에도 작동합니다. + @param _operator 승인된 운영자 집합에 추가할 주소. + @param _approved 운영자가 승인되면 True, 승인을 취소하려면 false입니다. + """ + # `_operator`가 `msg.sender`인 경우 예외를 발생시킵니다 + assert _operator != msg.sender + self.ownerToOperators[msg.sender][_operator] = _approved + log ApprovalForAll(msg.sender, _operator, _approved) +``` + +#### 새 토큰 발행 및 기존 토큰 소멸 {#mint-burn} + +계약을 생성한 계정은 새로운 NFT를 발행할 권한이 있는 슈퍼 사용자인 `minter`입니다. 그러나 기존 토큰을 소각하는 것은 허용되지 않습니다. 소유자 또는 소유자가 승인한 엔티티만 그렇게 할 수 있습니다. + +```python +### 발행 및 소각 함수 ### + +@external +def mint(_to: address, _tokenId: uint256) -> bool: +``` + +이 함수는 작업이 실패하면 되돌려지기 때문에 항상 `True`를 반환합니다. + +```python + """ + @dev 토큰을 발행하는 함수 + `msg.sender`가 발행자가 아닌 경우 예외를 발생시킵니다. + `_to`가 0 주소인 경우 예외를 발생시킵니다. + `_tokenId`가 누군가에 의해 소유된 경우 예외를 발생시킵니다. + @param _to 발행된 토큰을 받을 주소. + @param _tokenId 발행할 토큰 ID. + @return 작업이 성공했는지 여부를 나타내는 부울 값. + """ + # `msg.sender`가 발행자가 아닌 경우 예외를 발생시킵니다 + assert msg.sender == self.minter +``` + +발행자(ERC-721 계약을 생성한 계정)만이 새로운 토큰을 발행할 수 있습니다. 이는 나중에 발행자의 신원을 변경하고자 할 때 문제가 될 수 있습니다. 프로덕션 계약에서는 발행자가 발행자 권한을 다른 사람에게 이전할 수 있도록 하는 함수를 원할 것입니다. + +```python + # `_to`가 0 주소인 경우 예외를 발생시킵니다 + assert _to != ZERO_ADDRESS + # NFT 추가. `_tokenId`가 누군가에 의해 소유된 경우 예외를 발생시킵니다 + self._addTokenTo(_to, _tokenId) + log Transfer(ZERO_ADDRESS, _to, _tokenId) + return True +``` + +관례적으로 새로운 토큰 발행은 0 주소로부터의 전송으로 간주됩니다. + +```python + +@external +def burn(_tokenId: uint256): + """ + @dev 특정 ERC721 토큰을 소각합니다. + `msg.sender`가 현재 소유자, 승인된 운영자 또는 이 NFT에 대해 승인된 주소가 아닌 경우 예외를 발생시킵니다. + `_tokenId`가 유효한 NFT가 아닌 경우 예외를 발생시킵니다. + @param _tokenId 소각될 ERC721 토큰의 uint256 ID. + """ + # 요구 사항 확인 + assert self._isApprovedOrOwner(msg.sender, _tokenId) + owner: address = self.idToOwner[_tokenId] + # `_tokenId`가 유효한 NFT가 아닌 경우 예외를 발생시킵니다 + assert owner != ZERO_ADDRESS + self._clearApproval(owner, _tokenId) + self._removeTokenFrom(owner, _tokenId) + log Transfer(owner, ZERO_ADDRESS, _tokenId) +``` + +토큰을 전송할 수 있는 사람은 누구나 소각할 수 있습니다. 소각은 0 주소로 전송하는 것과 동일하게 보이지만, 0 주소는 실제로 토큰을 받지 않습니다. 이를 통해 토큰에 사용된 모든 저장 공간을 확보할 수 있으므로 트랜잭션의 가스 비용을 줄일 수 있습니다. + +## 이 계약 사용하기 {#using-contract} + +솔리디티와 달리 Vyper는 상속이 없습니다. 이는 코드를 더 명확하게 하여 보안을 더 쉽게 하기 위한 의도적인 설계 선택입니다. 따라서 자신만의 Vyper ERC-721 계약을 만들려면 [이 계약](https://github.com/vyperlang/vyper/blob/master/examples/tokens/ERC721.vy)을 가져와 원하는 비즈니스 로직을 구현하도록 수정합니다. + +## 결론 {#conclusion} + +검토를 위해, 이 계약의 가장 중요한 몇 가지 아이디어는 다음과 같습니다: + +- 안전한 전송으로 ERC-721 토큰을 받으려면 계약이 `ERC721Receiver` 인터페이스를 구현해야 합니다. +- 안전한 전송을 사용하더라도 개인 키를 알 수 없는 주소로 보내면 토큰이 여전히 갇힐 수 있습니다. +- 작업에 문제가 있을 경우 실패 값을 반환하는 것보다 호출을 `revert`하는 것이 좋습니다. +- ERC-721 토큰은 소유자가 있을 때 존재합니다. +- NFT를 전송할 권한을 부여받는 방법은 세 가지가 있습니다. 소유자가 되거나, 특정 토큰에 대해 승인받거나, 소유자의 모든 토큰에 대한 운영자가 될 수 있습니다. +- 과거 이벤트는 블록체인 외부에서만 볼 수 있습니다. 블록체인 내부에서 실행되는 코드는 이를 볼 수 없습니다. + +이제 안전한 Vyper 계약을 구현해 보세요. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). + diff --git a/public/content/translations/ko/developers/tutorials/erc20-annotated-code/index.md b/public/content/translations/ko/developers/tutorials/erc20-annotated-code/index.md new file mode 100644 index 00000000000..2d75ab1604f --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/erc20-annotated-code/index.md @@ -0,0 +1,809 @@ +--- +title: "ERC-20 계약 살펴보기" +description: "OpenZeppelin ERC-20 계약에는 무엇이 있으며 왜 사용될까요?" +author: Ori Pomerantz +lang: ko +tags: [ "Solidity", "erc-20" ] +skill: beginner +published: 2021-03-09 +--- + +## 소개 {#introduction} + +이더리움이 사용되는 대표적인 곳 중 하나는 거래 가능한 토큰을 만드는 그룹입니다. 거래 가능한 토큰은 자체 통화라고도 불립니다. 이러한 토큰은 일반적으로 [ERC-20](/developers/docs/standards/tokens/erc-20/) 표준을 따릅니다. 이 표준을 통해 모든 ERC-20 토큰에서 작동하는 유동성 풀이나 지갑 같은 도구를 작성할 수 있습니다. 이 글에서는 [OpenZeppelin 솔리디티 ERC20 구현](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)과 [인터페이스 정의](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol)에 대해 분석해 보겠습니다. + +이 문서에 나오는 소스 코드는 주석을 포함합니다. ERC-20을 구현하고 싶다면 [이 튜토리얼을 읽어보세요](https://docs.openzeppelin.com/contracts/2.x/erc20-supply). + +## 인터페이스 {#the-interface} + +ERC-20과 같은 표준의 목적은 지갑 및 탈중앙화 거래소와 같은 애플리케이션 전반에서 상호 운용 가능한 많은 토큰 구현을 허용하는 것입니다. 이를 위해 [인터페이스](https://www.geeksforgeeks.org/solidity/solidity-basics-of-interface/)를 만듭니다. 토큰 계약을 사용해야 하는 코드는 인터페이스에서 동일한 정의를 사용하여 이를 사용하는 모든 토큰 계약과 호환될 수 있습니다. MetaMask와 같은 지갑이든, etherscan.io와 같은 탈중앙화앱이든, 유동성 풀과 같은 다른 계약이든 상관없습니다. + +![ERC-20 인터페이스 그림](erc20_interface.png) + +숙련된 프로그래머라면 [Java](https://www.w3schools.com/java/java_interface.asp)나 [C 헤더 파일](https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html)에서 비슷한 구조를 본 기억이 있을 것입니다. + +이것은 OpenZeppelin의 [ERC-20 인터페이스](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol)에 대한 정의입니다. 이는 [사람이 읽을 수 있는 표준](https://eips.ethereum.org/EIPS/eip-20)을 솔리디티 코드로 번역한 것입니다. 물론 인터페이스 자체가 무언가를 _어떻게_ 해야 하는지 정의하지는 않습니다. 이는 아래 계약 소스 코드에 설명되어 있습니다. + +  + +```solidity +// SPDX-License-Identifier: MIT +``` + +솔리디티 파일은 라이선스 식별자를 포함해야 합니다. [여기에서 라이선스 목록을 볼 수 있습니다](https://spdx.org/licenses/). 다른 라이선스가 필요한 경우 주석에 설명하면 됩니다. + +  + +```solidity +pragma solidity >=0.6.0 <0.8.0; +``` + +솔리디티 언어는 여전히 빠르게 발전하고 있으며, 새 버전은 이전 코드와 호환되지 않을 수 있습니다([여기 참조](https://docs.soliditylang.org/en/v0.7.0/070-breaking-changes.html)). 따라서 언어의 최소 버전뿐만 아니라 코드를 테스트한 최신 버전인 최대 버전도 지정하는 것이 좋습니다. + +  + +```solidity +/** + * @dev EIP에 정의된 ERC20 표준의 인터페이스입니다. + */ +``` + +주석의 `@dev`는 소스 코드에서 문서를 생성하는 데 사용되는 [NatSpec 형식](https://docs.soliditylang.org/en/develop/natspec-format.html)의 일부입니다. + +  + +```solidity +interface IERC20 { +``` + +관례적으로 인터페이스 이름은 `I`로 시작합니다. + +  + +```solidity + /** + * @dev 존재하는 토큰의 양을 반환합니다. + */ + function totalSupply() external view returns (uint256); +``` + +이 함수는 `external`이며, 이는 [계약 외부에서만 호출할 수 있음](https://docs.soliditylang.org/en/v0.7.0/cheatsheet.html#index-2)을 의미합니다. +계약에 있는 토큰의 총공급량을 반환합니다. 이 값은 이더리움에서 가장 일반적인 유형인 부호 없는 256비트를 사용하여 반환됩니다(256비트는 EVM의 기본 워드 크기임). 이 함수는 또한 `view` 함수인데, 이는 상태를 변경하지 않으므로 블록체인의 모든 노드에서 실행하는 대신 단일 노드에서 실행할 수 있음을 의미합니다. 이러한 종류의 함수는 트랜잭션을 생성하지 않으며 [가스](/developers/docs/gas/)가 들지 않습니다. + +**참고:** 이론적으로 계약 생성자가 실제 값보다 적은 총공급량을 반환하여 각 토큰이 실제보다 더 가치 있는 것처럼 보이게 속일 수 있는 것처럼 보일 수 있습니다. 그러나 그 두려움은 블록체인의 진정한 본질을 무시하는 것입니다. 블록체인에서 일어나는 모든 일은 모든 노드에서 검증할 수 있습니다. 이를 위해 모든 계약의 기계어 코드와 저장 공간은 모든 노드에서 사용할 수 있습니다. 계약에 대한 솔리디티 코드를 공개할 필요는 없지만, 소스 코드와 컴파일된 솔리디티 버전을 공개하지 않으면 누구도 진지하게 받아들이지 않을 것입니다. 그래야 제공한 기계어 코드와 대조하여 검증할 수 있기 때문입니다. +예를 들어, [이 계약](https://eth.blockscout.com/address/0xa530F85085C6FE2f866E7FdB716849714a89f4CD?tab=contract)을 참조하세요. + +  + +```solidity + /** + * @dev `account`가 소유한 토큰의 양을 반환합니다. + */ + function balanceOf(address account) external view returns (uint256); +``` + +이름에서 알 수 있듯이, `balanceOf`는 계정의 잔액을 반환합니다. 이더리움 계정은 솔리디티에서 160비트를 보유하는 `address` 유형을 사용하여 식별됩니다. +이 함수 또한 `external` 및 `view`입니다. + +  + +```solidity + /** + * @dev 호출자 계정에서 `recipient`로 `amount` 만큼의 토큰을 이동시킵니다. + * + * 작업 성공 여부를 나타내는 불리언 값을 반환합니다. + * + * {Transfer} 이벤트를 발생시킵니다. + */ + function transfer(address recipient, uint256 amount) external returns (bool); +``` + +`transfer` 함수는 호출자로부터 다른 주소로 토큰을 전송합니다. 이는 상태 변경을 포함하므로 `view`가 아닙니다. +사용자가 이 함수를 호출하면 트랜잭션이 생성되고 가스가 소모됩니다. 또한 `Transfer` 이벤트를 발생시켜 블록체인의 모든 사람에게 해당 이벤트를 알립니다. + +이 함수는 두 가지 다른 유형의 호출자에 대해 두 가지 유형의 출력을 가집니다. + +- 사용자 인터페이스에서 직접 함수를 호출하는 사용자. 일반적으로 사용자는 트랜잭션을 제출하고 응답을 기다리지 않는데, 이는 무기한의 시간이 걸릴 수 있습니다. 사용자는 트랜잭션 영수증(트랜잭션 해시로 식별됨)을 찾거나 `Transfer` 이벤트를 찾아 무슨 일이 일어났는지 확인할 수 있습니다. +- 전체 트랜잭션의 일부로 함수를 호출하는 다른 계약. 이러한 계약은 동일한 트랜잭션에서 실행되기 때문에 즉시 결과를 얻으므로 함수 반환 값을 사용할 수 있습니다. + +계약의 상태를 변경하는 다른 함수에 의해서도 동일한 유형의 출력이 생성됩니다. + +  + +허용량을 사용하면 계정이 다른 소유자에게 속한 일부 토큰을 사용할 수 있습니다. +예를 들어 판매자 역할을 하는 계약에 유용합니다. 계약은 이벤트를 모니터링할 수 없으므로 구매자가 판매자 계약으로 직접 토큰을 전송하면 해당 계약은 지불되었는지 알 수 없습니다. 대신, 구매자는 판매자 계약이 특정 금액을 사용하도록 허용하고 판매자는 해당 금액을 전송합니다. +이는 판매자 계약이 호출하는 함수를 통해 수행되므로 판매자 계약은 성공 여부를 알 수 있습니다. + +```solidity + /** + * @dev {transferFrom}을 통해 `spender`가 `owner`를 대신하여 사용할 수 있도록 허용된 나머지 토큰 수를 반환합니다. 기본값은 0입니다. + * + * {approve} 또는 {transferFrom}이 호출되면 이 값이 변경됩니다. + */ + function allowance(address owner, address spender) external view returns (uint256); +``` + +`allowance` 함수를 사용하면 누구나 한 주소(`owner`)가 다른 주소(`spender`)에게 허용한 허용량이 얼마인지 조회할 수 있습니다. + +  + +```solidity + /** + * @dev 호출자의 토큰에 대한 `spender`의 허용량으로 `amount`를 설정합니다. + * + * 작업 성공 여부를 나타내는 불리언 값을 반환합니다. + * + * 중요: 이 방법으로 허용량을 변경하면 불행한 + * 트랜잭션 순서로 인해 누군가 이전 허용량과 새 허용량을 모두 사용할 수 있는 위험이 따릅니다. 이 경쟁 + * 조건을 완화하기 위한 한 가지 가능한 해결책은 먼저 지출자의 허용량을 0으로 줄이고 그 후에 + * 원하는 값을 설정하는 것입니다: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * {Approval} 이벤트를 발생시킵니다. + */ + function approve(address spender, uint256 amount) external returns (bool); +``` + +`approve` 함수는 허용량을 생성합니다. 이 함수가 어떻게 남용될 수 있는지에 대한 메시지를 반드시 읽어보세요. 이더리움에서는 자신의 트랜잭션 순서는 제어할 수 있지만, 상대방의 트랜잭션이 발생한 것을 보기 전까지는 자신의 트랜잭션을 제출하지 않는 한 다른 사람의 트랜잭션이 실행되는 순서는 제어할 수 없습니다. + +  + +```solidity + /** + * @dev 허용량 메커니즘을 사용하여 `sender`에서 `recipient`로 `amount` 토큰을 이동합니다. 그러면 호출자의 + * 허용량에서 `amount`가 차감됩니다. + * + * 작업 성공 여부를 나타내는 불리언 값을 반환합니다. + * + * {Transfer} 이벤트를 발생시킵니다. + */ + function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); +``` + +마지막으로 지출자는 `transferFrom`을 사용하여 실제로 허용량을 사용합니다. + +  + +```solidity + + /** + * @dev `value` 토큰이 한 계정(`from`)에서 + * 다른 계정(`to`)으로 이동할 때 발생합니다. + * + * `value`는 0일 수 있다는 점에 유의하세요. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev {approve}를 호출하여 `owner`의 `spender`에 대한 허용 한도를 + * 설정할 때 발생합니다. `value`는 새로운 허용 한도입니다. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); +} +``` + +이러한 이벤트는 ERC-20 컨트랙트의 상태가 변경될 때 발생합니다. + +## 실제 컨트랙트 {#the-actual-contract} + +이는 ERC-20 표준을 구현하는 실제 컨트랙트이며, +[여기](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)에서 가져왔습니다. +있는 그대로 사용하기 위한 것은 아니지만, +여기에서 [상속](https://www.tutorialspoint.com/solidity/solidity_inheritance.htm)하여 사용 가능한 것으로 확장할 수 있습니다. + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.0 <0.8.0; +``` + +  + +### 가져오기 구문 {#import-statements} + +위의 인터페이스 정의 외에도 컨트랙트 정의는 두 개의 다른 파일을 가져옵니다: + +```solidity + +import "../../GSN/Context.sol"; +import "./IERC20.sol"; +import "../../math/SafeMath.sol"; +``` + +- `GSN/Context.sol`은 이더가 없는 사용자가 블록체인을 사용할 수 있도록 하는 시스템인 [OpenGSN](https://www.opengsn.org/)을 사용하기 위해 필요한 정의입니다. 이것은 이전 버전이므로 OpenGSN과 통합하려면 + [이 튜토리얼](https://docs.opengsn.org/javascript-client/tutorial.html)을 사용하세요. +- [SafeMath 라이브러리](https://ethereumdev.io/using-safe-math-library-to-prevent-from-overflows/)는 **<0.8.0** 버전의 솔리디티에서 산술 오버플로우/언더플로우를 방지합니다. 솔리디티 ≥0.8.0에서는 산술 연산이 오버플로우/언더플로우 시 자동으로 되돌려지므로 SafeMath가 불필요합니다. 이 컨트랙트는 이전 컴파일러 버전과의 하위 호환성을 위해 SafeMath를 사용합니다. + +  + +이 주석은 컨트랙트의 목적을 설명합니다. + +```solidity +/** + * @dev {IERC20} 인터페이스의 구현입니다. + * + * 이 구현은 토큰 생성 방식과 무관합니다. 즉, {_mint}를 사용하여 + * 파생된 컨트랙트에 공급 메커니즘을 추가해야 함을 의미합니다. + * 일반적인 메커니즘은 {ERC20PresetMinterPauser}를 참조하세요. + * + * 팁: 자세한 내용은 가이드 + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[공급 메커니즘 구현 방법]을 참조하세요. + * + * 일반적인 OpenZeppelin 가이드라인을 따랐습니다. 함수는 실패 시 `false`를 반환하는 대신 + * 되돌려집니다. 이 동작은 관례적이며 ERC20 애플리케이션의 + * 기대와 충돌하지 않습니다. + * + * 또한 {transferFrom}을 호출하면 {Approval} 이벤트가 발생합니다. + * 이를 통해 애플리케이션은 해당 이벤트를 수신하는 것만으로 모든 계정의 허용량을 + * 재구성할 수 있습니다. EIP의 다른 구현에서는 사양에 요구되지 않으므로 + * 이러한 이벤트를 발생시키지 않을 수 있습니다. + * + * 마지막으로, 허용량 설정과 관련된 잘 알려진 문제를 완화하기 위해 + * 비표준 {decreaseAllowance} 및 {increaseAllowance} + * 함수가 추가되었습니다. {IERC20-approve}를 참조하세요. + */ + +``` + +### 컨트랙트 정의 {#contract-definition} + +```solidity +contract ERC20 is Context, IERC20 { +``` + +이 줄은 상속을 지정하며, 이 경우 OpenGSN을 위해 위에서 설명한 `IERC20` 및 `Context`로부터 상속받습니다. + +  + +```solidity + + using SafeMath for uint256; + +``` + +이 줄은 `SafeMath` 라이브러리를 `uint256` 유형에 연결합니다. 이 라이브러리는 +[여기](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol)에서 찾을 수 있습니다. + +### 변수 정의 {#variable-definitions} + +이 정의는 컨트랙트의 상태 변수를 지정합니다. 이 변수들은 `private`으로 선언되었지만, +이는 블록체인의 다른 컨트랙트가 이를 읽을 수 없다는 것을 의미할 뿐입니다. _블록체인에는 +비밀이 없습니다_. 모든 노드의 소프트웨어는 모든 블록에서 모든 컨트랙트의 상태를 가집니다. 관례적으로, 상태 변수는 `_<무엇인가>`로 명명됩니다. + +처음 두 변수는 [매핑](https://www.tutorialspoint.com/solidity/solidity_mappings.htm)으로, +키가 숫자 값이라는 점을 제외하고 [연관 배열](https://wikipedia.org/wiki/Associative_array)과 거의 동일하게 작동합니다. 저장 공간은 기본값(0)과 다른 값을 가진 항목에 대해서만 할당됩니다. + +```solidity + mapping (address => uint256) private _balances; +``` + +첫 번째 매핑인 `_balances`는 주소와 해당 토큰의 잔액입니다. 잔액에 접근하려면 +`_balances[<주소>]` 구문을 사용합니다. + +  + +```solidity + mapping (address => mapping (address => uint256)) private _allowances; +``` + +이 변수 `_allowances`는 앞서 설명한 허용량을 저장합니다. 첫 번째 인덱스는 토큰의 소유자이며, +두 번째 인덱스는 허용량이 부여된 컨트랙트입니다. 주소 A가 주소 B의 계정에서 사용할 수 있는 +금액에 접근하려면 `_allowances[B][A]`를 사용합니다. + +  + +```solidity + uint256 private _totalSupply; +``` + +이름에서 알 수 있듯이 이 변수는 토큰의 총 공급량을 추적합니다. + +  + +```solidity + string private _name; + string private _symbol; + uint8 private _decimals; +``` + +이 세 가지 변수는 가독성을 높이기 위해 사용됩니다. 처음 두 개는 그 자체로 설명이 되지만, `_decimals`는 그렇지 않습니다. + +한편, 이더리움에는 부동 소수점이나 분수 변수가 없습니다. 반면에 +인간은 토큰을 나눌 수 있기를 원합니다. 사람들이 금을 화폐로 정착시킨 한 가지 이유는 누군가 소 한 마리의 가치로 오리 한 마리를 사려고 할 때 거스름돈을 만들기 어려웠기 때문입니다. + +해결책은 정수를 추적하되, 실제 토큰 대신 거의 가치가 없는 +부분 토큰을 세는 것입니다. 이더의 경우 부분 토큰을 wei라고 하며, 10^18 wei는 1 +ETH와 같습니다. 작성 시점에서 10,000,000,000,000 wei는 대략 미국 또는 유로 1센트입니다. + +애플리케이션은 토큰 잔액을 표시하는 방법을 알아야 합니다. 사용자가 3,141,000,000,000,000,000 wei를 가지고 있다면, 그것은 +3.14 ETH일까요? 31.41 ETH일까요? 3,141 ETH일까요? 이더의 경우 ETH에 대해 10^18 wei로 정의되어 있지만, 여러분의 +토큰에 대해서는 다른 값을 선택할 수 있습니다. 토큰을 나누는 것이 의미가 없다면 +`_decimals` 값을 0으로 사용할 수 있습니다. ETH와 동일한 표준을 사용하고 싶다면 **18** 값을 사용하세요. + +### 생성자 {#the-constructor} + +```solidity + /** + * @dev {name} 및 {symbol} 값을 설정하고, {decimals}를 + * 기본값 18로 초기화합니다. + * + * {decimals}에 다른 값을 선택하려면 {_setupDecimals}를 사용하세요. + * + * 이 세 값은 모두 불변입니다. 즉, 생성 중에 + * 한 번만 설정할 수 있습니다. + */ + constructor (string memory name_, string memory symbol_) public { + // 솔리디티 ≥0.7.0에서는 'public'이 암시적이므로 생략할 수 있습니다. + + _name = name_; + _symbol = symbol_; + _decimals = 18; + } +``` + +생성자는 컨트랙트가 처음 생성될 때 호출됩니다. 관례적으로 함수 매개변수는 `_`으로 명명됩니다. + +### 사용자 인터페이스 함수 {#user-interface-functions} + +```solidity + /** + * @dev 토큰의 이름을 반환합니다. + */ + function name() public view returns (string memory) { + return _name; + } + + /** + * @dev 토큰의 심볼을 반환하며, 일반적으로 이름의 + * 축약 버전입니다. + */ + function symbol() public view returns (string memory) { + return _symbol; + } + + /** + * @dev 사용자 표현을 얻는 데 사용되는 소수점 자릿수를 반환합니다. + * 예를 들어, `decimals`가 `2`이면, `505` 토큰의 잔액은 + * 사용자에게 `5,05`(`505 / 10 ** 2`)로 표시되어야 합니다. + * + * 토큰은 보통 이더와 wei 간의 관계를 모방하여 18이라는 값을 + * 선택합니다. 이는 {_setupDecimals}가 호출되지 않는 한 {ERC20}이 사용하는 + * 값입니다. + * + * 참고: 이 정보는 _표시_ 목적으로만 사용되며, + * {IERC20-balanceOf} 및 {IERC20-transfer}를 포함한 컨트랙트의 어떠한 + * 산술 연산에도 영향을 미치지 않습니다. + */ + function decimals() public view returns (uint8) { + return _decimals; + } +``` + +`name`, `symbol`, `decimals` 함수는 사용자 인터페이스가 컨트랙트에 대해 알 수 있도록 하여 제대로 표시할 수 있도록 돕습니다. + +반환 유형은 `string memory`이며, 이는 메모리에 저장된 문자열을 반환함을 의미합니다. 문자열과 같은 변수는 +세 위치에 저장될 수 있습니다: + +| | 수명 | 컨트랙트 액세스 | 가스 비용 | +| ---- | ------- | -------- | --------------------------------------------- | +| 메모리 | 함수 호출 | 읽기/쓰기 | 수십 또는 수백 (더 높은 위치일수록 더 높음) | +| 콜데이터 | 함수 호출 | 읽기 전용 | 반환 유형으로 사용할 수 없으며, 함수 매개변수 유형으로만 사용 가능 | +| 스토리지 | 변경될 때까지 | 읽기/쓰기 | 높음 (읽기 800, 쓰기 20k) | + +이 경우 `memory`가 가장 좋은 선택입니다. + +### 토큰 정보 읽기 {#read-token-information} + +이 함수들은 총 공급량 또는 계정의 잔액과 같은 토큰에 대한 정보를 제공합니다. + +```solidity + /** + * @dev {IERC20-totalSupply}를 참조하세요. + */ + function totalSupply() public view override returns (uint256) { + return _totalSupply; + } +``` + +`totalSupply` 함수는 토큰의 총 공급량을 반환합니다. + +  + +```solidity + /** + * @dev {IERC20-balanceOf}를 참조하세요. + */ + function balanceOf(address account) public view override returns (uint256) { + return _balances[account]; + } +``` + +계정의 잔액을 읽습니다. 누구나 다른 사람의 계정 잔액을 조회할 수 있음에 유의하세요. 이 정보는 모든 노드에서 확인할 수 있으므로 숨기려고 해도 소용없습니다. _블록체인에는 비밀이 없습니다._ + +### 토큰 전송 {#transfer-tokens} + +```solidity + /** + * @dev {IERC20-transfer}를 참조하세요. + * + * 요구 사항: + * + * - `수신자`는 0 주소일 수 없습니다. + * - 호출자는 최소 `금액`의 잔액을 가지고 있어야 합니다. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { +``` + +`transfer` 함수는 보낸 사람의 계정에서 다른 계정으로 토큰을 전송하기 위해 호출됩니다. 부울 값을 반환하지만 그 값은 항상 true라는 점에 유의하세요. 전송이 실패하면 컨트랙트는 호출을 되돌립니다. + +  + +```solidity + _transfer(_msgSender(), recipient, amount); + return true; + } +``` + +`_transfer` 함수가 실제 작업을 수행합니다. 이 함수는 다른 컨트랙트 함수에서만 호출할 수 있는 비공개 함수입니다. 관례적으로 비공개 함수는 상태 변수와 마찬가지로 `_`으로 명명됩니다. + +일반적으로 솔리디티에서는 메시지 발신자에 대해 `msg.sender`를 사용합니다. 그러나 이는 [OpenGSN](http://opengsn.org/)에서 문제를 일으킵니다. 토큰으로 이더 없는 트랜잭션을 허용하려면 `_msgSender()`를 사용해야 합니다. 일반 트랜잭션의 경우 `msg.sender`를 반환하지만 이더가 없는 트랜잭션의 경우 메시지를 중계한 컨트랙트가 아닌 원래 서명자를 반환합니다. + +### 허용량 함수 {#allowance-functions} + +다음은 허용량 기능을 구현하는 함수입니다: `allowance`, `approve`, `transferFrom`, `_approve`. 또한 OpenZeppelin 구현은 기본 표준을 넘어 보안을 개선하는 몇 가지 기능인 `increaseAllowance` 및 `decreaseAllowance`를 포함합니다. + +#### allowance 함수 {#allowance} + +```solidity + /** + * @dev {IERC20-allowance}를 참조하세요. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } +``` + +`allowance` 함수를 사용하면 누구나 허용량을 확인할 수 있습니다. + +#### approve 함수 {#approve} + +```solidity + /** + * @dev {IERC20-approve}를 참조하세요. + * + * 요구 사항: + * + * - `spender`는 0 주소일 수 없습니다. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { +``` + +이 함수는 허용량을 생성하기 위해 호출됩니다. 위의 `transfer` 함수와 유사합니다: + +- 이 함수는 실제 작업을 수행하는 내부 함수(이 경우 `_approve`)를 호출할 뿐입니다. +- 함수는 `true`를 반환하거나(성공 시) 되돌립니다(실패 시). + +  + +```solidity + _approve(_msgSender(), spender, amount); + return true; + } +``` + +상태 변경이 발생하는 곳의 수를 최소화하기 위해 내부 함수를 사용합니다. 상태를 변경하는 _모든_ 함수는 보안 감사가 필요한 잠재적인 보안 위험입니다. 이렇게 하면 실수를 할 가능성이 줄어듭니다. + +#### transferFrom 함수 {#transferFrom} + +지출자가 허용량을 사용하기 위해 호출하는 함수입니다. 여기에는 두 가지 작업이 필요합니다. 사용된 금액을 전송하고 그 금액만큼 허용량을 줄이는 것입니다. + +```solidity + /** + * @dev {IERC20-transferFrom}를 참조하세요. + * + * 업데이트된 허용량을 나타내는 {Approval} 이벤트를 발생시킵니다. 이는 + * EIP에서 요구하지 않습니다. {ERC20}의 시작 부분에 있는 참고 사항을 참조하세요. + * + * 요구 사항: + * + * - `sender` 및 `recipient`는 0 주소일 수 없습니다. + * - `sender`는 최소 `amount`의 잔액을 가지고 있어야 합니다. + * - 호출자는 ``sender``의 토큰에 대해 최소 + * `amount`의 허용량을 가지고 있어야 합니다. + */ + function transferFrom(address sender, address recipient, uint256 amount) public virtual + override returns (bool) { + _transfer(sender, recipient, amount); +``` + +  + +`a.sub(b, "메시지")` 함수 호출은 두 가지 작업을 수행합니다. 첫째, 새로운 허용량인 `a-b`를 계산합니다. +둘째, 이 결과가 음수가 아닌지 확인합니다. 음수이면 제공된 메시지와 함께 호출이 되돌려집니다. 호출이 되돌려질 때 해당 호출 중에 이전에 수행된 모든 처리는 무시되므로 `_transfer`를 되돌릴 필요가 없다는 점에 유의하세요. + +```solidity + _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, + "ERC20: 전송 금액이 허용량을 초과합니다")); + return true; + } +``` + +#### OpenZeppelin 안전 추가 사항 {#openzeppelin-safety-additions} + +0이 아닌 허용량을 다른 0이 아닌 값으로 설정하는 것은 위험합니다. 자신의 트랜잭션 순서만 제어할 수 있고 다른 사람의 트랜잭션 순서는 제어할 수 없기 때문입니다. 순진한 앨리스와 부정직한 빌이라는 두 사용자가 있다고 상상해 보세요. 앨리스는 빌에게서 어떤 서비스를 원하는데, 그 비용이 5 토큰이라고 생각해서 빌에게 5 토큰의 허용량을 줍니다. + +그런 다음 상황이 바뀌어 빌의 가격이 10 토큰으로 오릅니다. 여전히 서비스를 원하는 앨리스는 빌의 허용량을 10으로 설정하는 트랜잭션을 보냅니다. 빌은 트랜잭션 풀에서 이 새로운 트랜잭션을 보는 순간 앨리스의 5 토큰을 사용하는 트랜잭션을 보내고 훨씬 더 높은 가스 가격을 설정하여 더 빨리 채굴되도록 합니다. 그렇게 하면 빌은 먼저 5 토큰을 사용하고, 앨리스의 새로운 허용량이 채굴되면 10 토큰을 더 사용하여 총 15 토큰을 사용할 수 있습니다. 이는 앨리스가 승인하려던 것보다 많은 금액입니다. 이 기술을 [선행매매](https://consensysdiligence.github.io/smart-contract-best-practices/attacks/#front-running)라고 합니다. + +| 앨리스의 트랜잭션 | 앨리스 Nonce | 빌 트랜잭션 | 빌 Nonce | 빌의 허용량 | 앨리스로부터의 빌 총수입 | +| ------------------------------------ | --------- | ------------------------------------------------ | ------- | ------ | ------------- | +| approve(Bill, 5) | 10 | | | 5 | 0 | +| | | transferFrom(Alice, Bill, 5) | 10,123 | 0 | 5 | +| approve(Bill, 10) | 11 | | | 10 | 5 | +| | | transferFrom(Alice, Bill, 10) | 10,124 | 0 | 15 | + +이 문제를 피하기 위해, 이 두 함수(`increaseAllowance`와 `decreaseAllowance`)를 사용하면 허용량을 특정 금액만큼 수정할 수 있습니다. 따라서 빌이 이미 5개의 토큰을 사용했다면, 그는 5개만 더 사용할 수 있을 것입니다. 타이밍에 따라 두 가지 방식으로 작동할 수 있으며, 두 가지 모두 빌이 10개의 토큰만 얻는 것으로 끝납니다: + +A: + +| 앨리스의 트랜잭션 | 앨리스 Nonce | 빌 트랜잭션 | 빌 Nonce | 빌의 허용량 | 앨리스로부터의 빌 총수입 | +| --------------------------------------------- | --------: | ----------------------------------------------- | ------: | ------: | ------------- | +| approve(Bill, 5) | 10 | | | 5 | 0 | +| | | transferFrom(Alice, Bill, 5) | 10,123 | 0 | 5 | +| increaseAllowance(Bill, 5) | 11 | | | 0+5 = 5 | 5 | +| | | transferFrom(Alice, Bill, 5) | 10,124 | 0 | 10 | + +B: + +| 앨리스의 트랜잭션 | 앨리스 Nonce | 빌 트랜잭션 | 빌 Nonce | 빌의 허용량 | 앨리스로부터의 빌 총수입 | +| --------------------------------------------- | --------: | ------------------------------------------------ | ------: | -------: | ------------: | +| approve(Bill, 5) | 10 | | | 5 | 0 | +| increaseAllowance(Bill, 5) | 11 | | | 5+5 = 10 | 0 | +| | | transferFrom(Alice, Bill, 10) | 10,124 | 0 | 10 | + +```solidity + /** + * @dev 호출자에 의해 `spender`에게 부여된 허용량을 원자적으로 증가시킵니다. + * + * 이것은 {IERC20-approve}에 설명된 문제에 대한 완화책으로 사용할 수 있는 {approve}의 대안입니다. + * + * 업데이트된 허용량을 나타내는 {Approval} 이벤트를 발생시킵니다. + * + * 요구 사항: + * + * - `spender`는 0 주소일 수 없습니다. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); + return true; + } +``` + +관례적으로 상태 변수는 `_`으로 명명됩니다. 첫 두 변수는 [매핑](https://www.tutorialspoint.com/solidity/solidity_mappings.htm)으로, 키가 숫자 값이라는 점을 제외하고는 [연관 배열](https://wikipedia.org/wiki/Associative_array)과 거의 동일하게 동작합니다. + +저장 공간은 기본값(0)과 다른 값을 가진 항목에만 할당됩니다. + +```solidity + mapping (address => uint256) private _balances; +``` + +첫 번째 매핑인 `_balances`는 주소와 해당 토큰의 잔액입니다. + +#### 잔액에 접근하려면 `_balances[
]` 구문을 사용합니다. + +```solidity + mapping (address => mapping (address => uint256)) private _allowances; +``` + +이 변수 `_allowances`는 앞에서 설명한 허용량을 저장합니다. 첫 번째 인덱스는 토큰의 소유자이고, 두 번째는 허용량이 있는 계약입니다. + +  + +```solidity + uint256 private _totalSupply; +``` + +이름에서 알 수 있듯이, 이 변수는 토큰의 총 공급량을 추적합니다. string private _name; +string private _symbol; +uint8 private _decimals; + +  + +```solidity +처음 두 개는 자명하지만 `_decimals`는 그렇지 않습니다. +``` + +한편으로, 이더리움에는 부동 소수점이나 분수 변수가 없습니다. + +1. 다른 한편으로, 인간은 토큰을 나눌 수 있는 것을 좋아합니다. +2. 사람들이 통화로 금을 선택한 이유 중 하나는 누군가가 소 한 마리 값의 오리를 사려고 할 때 거스름돈을 만들기가 어려웠기 때문입니다. + +해결책은 정수를 추적하는 것이지만, 실제 토큰 대신 거의 가치가 없는 분수 토큰을 세는 것입니다. 이더의 경우, 분수 토큰은 wei라고 불리며, 10^18 wei는 1 ETH와 같습니다. + +글을 쓰는 시점에서 10,000,000,000,000 wei는 대략 1 미국 센트 또는 유로 센트입니다. 애플리케이션은 토큰 잔액을 어떻게 표시해야 하는지 알아야 합니다. 사용자가 3,141,000,000,000,000,000 wei를 가지고 있다면, 그것은 3.14 ETH인가요? 31.41 ETH인가요? + +  + +```solidity +이더의 경우 ETH에 대해 10^18 wei로 정의되지만, 토큰에 대해서는 다른 값을 선택할 수 있습니다. +``` + +토큰을 나누는 것이 의미가 없다면 `_decimals` 값을 0으로 사용할 수 있습니다. ETH와 동일한 표준을 사용하려면 값 18을 사용하세요. + +### 생성자 {#the-constructor} + +```solidity + /** + * @dev {name}과 {symbol}의 값을 설정하고, {decimals}를 기본값인 18로 초기화합니다. + * + * {decimals}에 대해 다른 값을 선택하려면 {_setupDecimals}를 사용하세요. + * + * 이 세 가지 값은 모두 불변입니다: 생성 중에 한 번만 설정할 수 있습니다. + */ + constructor (string memory name_, string memory symbol_) public { + // 솔리디티 ≥0.7.0에서는 'public'이 암시적이므로 생략할 수 있습니다. + _name = name_; + _symbol = symbol_; + _decimals = 18; + } +``` + +  + +```solidity +관례적으로 함수 매개변수는 `_`로 명명됩니다. +``` + +### 사용자 인터페이스 함수 {#user-interface-functions} + +```solidity + /** + * @dev 토큰의 이름을 반환합니다. + */ + function name() public view returns (string memory) { + return _name; + } +``` + +```solidity + /** + * @dev 토큰의 기호를 반환하며, 보통 이름의 짧은 버전입니다. + */ + function symbol() public view returns (string memory) { + return _symbol; + } +``` + +```solidity + /** + * @dev 사용자 표현을 얻는 데 사용되는 소수점 자릿수를 반환합니다. + * 예를 들어, `decimals`가 `2`이면, `505` 토큰의 잔액은 + * 사용자에게 `5,05`(`505 / 10 ** 2`)로 표시되어야 합니다. + * + * 토큰은 보통 18의 값을 선택하며, 이는 이더와 wei의 관계를 모방한 것입니다. 이는 {_setupDecimals}가 호출되지 않는 한 + * {ERC20}이 사용하는 값입니다. + * + * 참고: 이 정보는 _표시_ 목적으로만 사용됩니다: 계약의 어떤 + * 산술에도 영향을 미치지 않으며, {IERC20-balanceOf} 및 {IERC20-transfer}를 포함합니다. + */ + function decimals() public view returns (uint8) { + return _decimals; + } +``` + +이 함수들, `name`, `symbol`, `decimals`는 사용자 인터페이스가 계약에 대해 알 수 있도록 도와주어 제대로 표시할 수 있게 합니다. + +#### 반환 유형은 `string memory`로, 메모리에 저장된 문자열을 반환한다는 의미입니다. + +문자열과 같은 변수는 세 곳에 저장될 수 있습니다: +수명 + +계약 액세스 +가스 비용 메모리 + +```solidity +함수 호출 +``` + +읽기/쓰기 + +  + +```solidity +읽기 전용 +``` + +반환 유형으로 사용할 수 없고, 함수 매개변수 유형으로만 사용 가능 + +#### 변경될 때까지 + +높음 (읽기 800, 쓰기 20k) 이 경우, `memory`가 최선의 선택입니다. + +### 토큰 정보 읽기 {#read-token-information} + +이 함수들은 총 공급량이나 계정 잔액과 같은 토큰에 대한 정보를 제공합니다. + +`totalSupply` 함수는 토큰의 총 공급량을 반환합니다. + +  + +```solidity + /** + * @dev {IERC20-balanceOf}를 참조하세요. + */ + function balanceOf(address account) public view override returns (uint256) { + return _balances[account]; + } +``` + +계정의 잔액을 읽습니다. + +### 누구나 다른 사람의 계정 잔액을 가져올 수 있다는 점에 유의하세요. + +이 정보는 어쨌든 모든 노드에서 사용할 수 있으므로 숨기려고 해도 소용이 없습니다. _블록체인에는 비밀이 없습니다._ + +### 토큰 전송하기 {#transfer-tokens} + +```solidity + /** + * @dev {IERC20-transfer}를 참조하세요. + * + * 요구 사항: + * + * - `recipient`는 0 주소일 수 없습니다. + * - 호출자는 최소 `amount`의 잔액을 가지고 있어야 합니다. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { +``` + +### 훅 {#hooks} + +이 함수는 부울 값을 반환하지만, 그 값은 항상 true라는 점에 유의하세요. 전송이 실패하면 계약은 호출을 되돌립니다. + +```solidity + _transfer(_msgSender(), recipient, amount); + return true; + } +``` + +## 결론 {#conclusion} + +이것은 다른 계약 함수에 의해서만 호출될 수 있는 비공개 함수입니다. + +- _이더리움 상에 비공개 정보란 없습니다_. 일반적으로 솔리디티에서는 메시지 발신인으로 `msg.sender`를 사용합니다. +- 하지만 이는 [OpenGSN](http://opengsn.org/)을 깨뜨립니다. 토큰으로 이더 없는 트랜잭션을 허용하려면 `_msgSender()`를 사용해야 합니다. +- 이 함수는 일반 트랜잭션의 경우 `msg.sender`를 반환하지만, 이더 없는 트랜잭션의 경우 메시지를 중계한 계약이 아닌 원래 서명자를 반환합니다. + +### 허용량 함수 {#allowance-functions} + +이 함수들은 허용량 기능을 구현하는 함수들입니다: `allowance`, `approve`, `transferFrom`, 그리고 `_approve`. 또한, OpenZeppelin 구현은 기본 표준을 넘어 보안을 향상시키는 몇 가지 기능, 즉 `increaseAllowance`와 `decreaseAllowance`를 포함합니다. + +#### allowance 함수 {#allowance} + +```solidity + /** + * @dev {IERC20-allowance}를 참조하세요. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } +``` + +`allowance` 함수는 누구나 어떤 허용량이든 확인할 수 있게 해줍니다. + +#### approve 함수 {#approve} + +```solidity + /** + * @dev {IERC20-approve}를 참조하세요. + * + * 요구 사항: + * + * - `spender`는 0 주소일 수 없습니다. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { +``` + +이 함수는 허용량을 생성하기 위해 호출됩니다. + +위의 `transfer` 함수와 비슷합니다. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). diff --git a/public/content/translations/ko/developers/tutorials/erc20-with-safety-rails/index.md b/public/content/translations/ko/developers/tutorials/erc20-with-safety-rails/index.md new file mode 100644 index 00000000000..fa0935b8168 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/erc20-with-safety-rails/index.md @@ -0,0 +1,217 @@ +--- +title: "안전장치가 있는 ERC-20" +description: "사람들이 사소한 실수를 피하도록 돕는 방법" +author: Ori Pomerantz +lang: ko +tags: [ "erc-20" ] +skill: beginner +published: 2022-08-15 +--- + +## 소개 {#introduction} + +이더리움의 가장 큰 장점 중 하나는 트랜잭션을 수정하거나 취소할 수 있는 중앙 기관이 없다는 것입니다. 이더리움의 큰 문제 중 하나는 사용자 실수나 불법적인 트랜잭션을 취소할 권한을 가진 중앙 기관이 없다는 것입니다. 이 글에서는 사용자가 [ERC-20](/developers/docs/standards/tokens/erc-20/) 토큰으로 저지르는 일반적인 실수와 사용자가 이러한 실수를 피하도록 돕거나 중앙 기관에 일부 권한(예: 계정 동결)을 부여하는 ERC-20 계약을 만드는 방법에 대해 알아봅니다. + +[OpenZeppelin ERC-20 토큰 계약](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20)을 사용하지만 이 글에서는 자세히 설명하지 않습니다. 이 정보는 [여기](/developers/tutorials/erc20-annotated-code)에서 찾을 수 있습니다. + +전체 소스 코드를 보려면: + +1. [Remix IDE](https://remix.ethereum.org/)를 엽니다. +2. 깃허브 복제 아이콘(![깃허브 복제 아이콘](icon-clone.png))을 클릭합니다. +3. 깃허브 리포지토리 `https://github.com/qbzzt/20220815-erc20-safety-rails`를 복제합니다. +4. contracts > erc20-safety-rails.sol을 엽니다. + +## ERC-20 계약 생성 {#creating-an-erc-20-contract} + +안전장치 기능을 추가하기 전에 ERC-20 계약이 필요합니다. 이 글에서는 [OpenZeppelin 계약 마법사](https://docs.openzeppelin.com/contracts/5.x/wizard)를 사용합니다. 다른 브라우저에서 열고 다음 지침을 따르세요. + +1. ERC20을 선택합니다. + +2. 다음 설정을 입력하세요. + + | 매개 변수 | 값 | + | -------- | ---------------- | + | 이름 | SafetyRailsToken | + | 기호 | SAFE | + | Premint | 1000 | + | 기능 | 없음 | + | 액세스 제어 | Ownable | + | 업그레이드 기능 | 없음 | + +3. 위로 스크롤하여 **Remix에서 열기**(Remix용)를 클릭하거나 다운로드를 클릭하여 다른 환경을 사용합니다. Remix를 사용한다고 가정하고, 다른 것을 사용한다면 적절하게 변경하세요. + +4. 이제 완전히 작동하는 ERC-20 계약이 있습니다. `.deps` > `npm`을 확장하여 가져온 코드를 볼 수 있습니다. + +5. 계약을 컴파일하고 배포하고 테스트하여 ERC-20 계약으로 작동하는지 확인합니다. Remix 사용법을 배워야 한다면 [이 튜토리얼](https://remix.ethereum.org/?#activate=udapp,solidity,LearnEth)을 사용하세요. + +## 일반적인 실수 {#common-mistakes} + +### 실수 {#the-mistakes} + +사용자는 때때로 잘못된 주소로 토큰을 보냅니다. 사용자가 무엇을 하려고 했는지 마음을 읽을 수는 없지만, 자주 발생하고 쉽게 감지할 수 있는 두 가지 오류 유형이 있습니다. + +1. 계약 자체 주소로 토큰 보내기. 예를 들어, [옵티미즘의 OP 토큰](https://optimism.mirror.xyz/qvd0WfuLKnePm1Gxb9dpGchPf5uDz5NSMEFdgirDS4c)은 두 달도 채 되지 않아 [120,000개 이상의](https://optimism.blockscout.com/address/0x4200000000000000000000000000000000000042) OP 토큰을 축적했습니다. 이는 아마도 사람들이 그냥 잃어버린 상당한 양의 자산을 나타냅니다. + +2. [외부 소유 계정](/developers/docs/accounts/#externally-owned-accounts-and-key-pairs) 또는 [스마트 계약](/developers/docs/smart-contracts)에 해당하지 않는 빈 주소로 토큰을 보냅니다. 이런 일이 얼마나 자주 발생하는지에 대한 통계는 없지만, [한 사건으로 20,000,000개의 토큰 손실이 발생할 뻔했습니다](https://gov.optimism.io/t/message-to-optimism-community-from-wintermute/2595). + +### 전송 방지 {#preventing-transfers} + +OpenZeppelin ERC-20 계약에는 토큰이 전송되기 전에 호출되는 [훅, `_beforeTokenTransfer`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol#L364-L368)가 포함되어 있습니다. 기본적으로 이 훅은 아무것도 하지 않지만, 문제가 있는 경우 되돌리는 확인과 같은 자체 기능을 추가할 수 있습니다. + +훅을 사용하려면 생성자 뒤에 이 함수를 추가하세요. + +```solidity + function _beforeTokenTransfer(address from, address to, uint256 amount) + internal virtual + override(ERC20) + { + super._beforeTokenTransfer(from, to, amount); + } +``` + +솔리디티에 익숙하지 않다면 이 함수의 일부가 새로울 수 있습니다. + +```solidity + internal virtual +``` + +`virtual` 키워드는 `ERC20`에서 기능을 상속하고 이 함수를 재정의한 것처럼 다른 계약이 우리에게서 상속하고 이 함수를 재정의할 수 있음을 의미합니다. + +```solidity + override(ERC20) +``` + +`_beforeTokenTransfer`의 ERC20 토큰 정의를 [재정의](https://docs.soliditylang.org/en/v0.8.15/contracts.html#function-overriding)하고 있음을 명시적으로 지정해야 합니다. 일반적으로 보안 관점에서는 명시적 정의가 암시적 정의보다 훨씬 낫습니다. 바로 앞에 있으면 무언가를 했다는 사실을 잊을 수 없습니다. 이것이 또한 우리가 재정의하는 슈퍼클래스의 `_beforeTokenTransfer`를 지정해야 하는 이유입니다. + +```solidity + super._beforeTokenTransfer(from, to, amount); +``` + +이 줄은 우리가 상속한 계약의 `_beforeTokenTransfer` 함수를 호출합니다. 이 경우 `ERC20`만 해당하며, `Ownable`에는 이 훅이 없습니다. 현재 `ERC20._beforeTokenTransfer`는 아무것도 하지 않지만, 나중에 기능이 추가될 경우를 대비하여 호출합니다(그리고 계약은 배포 후 변경되지 않기 때문에 계약을 다시 배포하기로 결정합니다). + +### 요구 사항 코딩 {#coding-the-requirements} + +함수에 다음 요구 사항을 추가하려고 합니다. + +- `to` 주소는 ERC-20 계약 자체의 주소인 `address(this)`와 같을 수 없습니다. +- `to` 주소는 비어 있을 수 없으며, 다음 중 하나여야 합니다. + - 외부 소유 계정(EOA). 주소가 EOA인지 직접 확인할 수는 없지만, 주소의 ETH 잔액을 확인할 수 있습니다. EOA는 더 이상 사용되지 않더라도 거의 항상 잔액이 있습니다. 마지막 wei까지 비우기는 어렵습니다. + - 스마트 계약. 주소가 스마트 계약인지 테스트하는 것은 조금 더 어렵습니다. 외부 코드 길이를 확인하는 [`EXTCODESIZE`](https://www.evm.codes/#3b)라는 opcode가 있지만 솔리디티에서 직접 사용할 수는 없습니다. 이를 위해 EVM 어셈블리인 [Yul](https://docs.soliditylang.org/en/v0.8.15/yul.html)을 사용해야 합니다. 솔리디티에서 사용할 수 있는 다른 값([`
.code` 및 `
.codehash`](https://docs.soliditylang.org/en/v0.8.15/units-and-global-variables.html#members-of-address-types))이 있지만, 비용이 더 많이 듭니다. + +새 코드를 한 줄씩 살펴보겠습니다. + +```solidity + require(to != address(this), "토큰을 계약 주소로 보낼 수 없습니다"); +``` + +이것이 첫 번째 요구 사항입니다. `to`와 `this(address)`가 같지 않은지 확인합니다. + +```solidity + bool isToContract; + assembly { + isToContract := gt(extcodesize(to), 0) + } +``` + +이렇게 주소가 계약인지 확인합니다. Yul에서 직접 출력을 받을 수 없으므로 대신 결과를 저장할 변수(`isToContract`)를 정의합니다. Yul의 작동 방식은 모든 opcode가 함수로 간주된다는 것입니다. 따라서 먼저 [`EXTCODESIZE`](https://www.evm.codes/#3b)를 호출하여 계약 크기를 가져온 다음, [`GT`](https://www.evm.codes/#11)를 사용하여 0이 아닌지 확인합니다(부호 없는 정수를 다루므로 물론 음수가 될 수 없습니다). 그런 다음 결과를 `isToContract`에 씁니다. + +```solidity + require(to.balance != 0 || isToContract, "토큰을 빈 주소로 보낼 수 없습니다"); +``` + +그리고 마지막으로, 빈 주소에 대한 실제 확인이 있습니다. + +## 관리자 액세스 {#admin-access} + +때로는 실수를 되돌릴 수 있는 관리자가 있는 것이 유용합니다. 악용 가능성을 줄이기 위해 이 관리자는 [다중서명](https://blog.logrocket.com/security-choices-multi-signature-wallets/)이 될 수 있으므로 여러 사람이 조치에 동의해야 합니다. 이 글에서는 두 가지 관리 기능을 다룹니다. + +1. 계정 동결 및 해제. 예를 들어 계정이 손상되었을 수 있을 때 유용할 수 있습니다. +2. 자산 정리. + + 때로는 사기꾼이 합법성을 얻기 위해 사기 토큰을 실제 토큰의 계약으로 보냅니다. 예를 들어, [여기](https://optimism.blockscout.com/token/0x2348B1a1228DDCd2dB668c3d30207c3E1852fBbe?tab=holders)를 참조하세요. 합법적인 ERC-20 계약은 [0x4200....0042](https://optimism.blockscout.com/token/0x4200000000000000000000000000000000000042)입니다. 그것을 사칭하는 사기는 [0x234....bbe](https://optimism.blockscout.com/token/0x2348B1a1228DDCd2dB668c3d30207c3E1852fBbe)입니다. + + 사람들이 실수로 합법적인 ERC-20 토큰을 우리 계약에 보낼 수도 있는데, 이는 토큰을 꺼낼 방법을 원하는 또 다른 이유입니다. + +OpenZeppelin은 관리자 액세스를 활성화하는 두 가지 메커니즘을 제공합니다. + +- [`Ownable`](https://docs.openzeppelin.com/contracts/5.x/access-control#ownership-and-ownable) 계약에는 단일 소유자가 있습니다. `onlyOwner` [제어자](https://www.tutorialspoint.com/solidity/solidity_function_modifiers.htm)가 있는 함수는 해당 소유자만 호출할 수 있습니다. 소유자는 소유권을 다른 사람에게 이전하거나 완전히 포기할 수 있습니다. 다른 모든 계정의 권한은 일반적으로 동일합니다. +- [`AccessControl`](https://docs.openzeppelin.com/contracts/5.x/access-control#role-based-access-control) 계약에는 [역할 기반 접근 제어(RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)가 있습니다. + +간단하게 하기 위해 이 글에서는 `Ownable`을 사용합니다. + +### 계약 동결 및 해제 {#freezing-and-thawing-contracts} + +계약을 동결하고 해제하려면 몇 가지 변경이 필요합니다. + +- 어떤 주소가 동결되었는지 추적하기 위한 주소에서 [부울](https://en.wikipedia.org/wiki/Boolean_data_type)로의 [매핑](https://www.tutorialspoint.com/solidity/solidity_mappings.htm). 모든 값은 초기에 0이며, 부울 값의 경우 거짓으로 해석됩니다. 기본적으로 계정은 동결되지 않기 때문에 이것이 우리가 원하는 것입니다. + + ```solidity + mapping(address => bool) public frozenAccounts; + ``` + +- 계정이 동결되거나 해제될 때 관심 있는 사람에게 알리는 [이벤트](https://www.tutorialspoint.com/solidity/solidity_events.htm). 기술적으로 말해서 이러한 작업에는 이벤트가 필요하지 않지만, 오프체인 코드가 이러한 이벤트를 수신하고 무슨 일이 일어나고 있는지 알 수 있도록 도와줍니다. 스마트 계약이 다른 사람과 관련이 있을 수 있는 일이 발생했을 때 이벤트를 내보내는 것은 좋은 매너로 간주됩니다. + + 이벤트는 인덱싱되므로 계정이 동결되거나 해제된 모든 시간을 검색할 수 있습니다. + + ```solidity + // 계정이 동결되거나 해제될 때 + event AccountFrozen(address indexed _addr); + event AccountThawed(address indexed _addr); + ``` + +- 계정 동결 및 해제 기능. 이 두 함수는 거의 동일하므로 동결 함수만 살펴보겠습니다. + + ```solidity + function freezeAccount(address addr) + public + onlyOwner + ``` + + [`public`](https://www.tutorialspoint.com/solidity/solidity_contracts.htm)으로 표시된 함수는 다른 스마트 계약에서 또는 트랜잭션에 의해 직접 호출될 수 있습니다. + + ```solidity + { + require(!frozenAccounts[addr], "계정이 이미 동결되었습니다"); + frozenAccounts[addr] = true; + emit AccountFrozen(addr); + } // freezeAccount + ``` + + 계정이 이미 동결된 경우 되돌립니다. 그렇지 않으면 동결하고 이벤트를 `emit`합니다. + +- 동결된 계정에서 자금이 이동되는 것을 방지하기 위해 `_beforeTokenTransfer`를 변경합니다. 자금은 여전히 동결된 계정으로 이체될 수 있습니다. + + ```solidity + require(!frozenAccounts[from], "계정이 동결되었습니다"); + ``` + +### 자산 정리 {#asset-cleanup} + +이 계약이 보유한 ERC-20 토큰을 해제하려면 해당 토큰이 속한 토큰 계약에서 [`transfer`](https://eips.ethereum.org/EIPS/eip-20#transfer) 또는 [`approve`](https://eips.ethereum.org/EIPS/eip-20#approve) 함수를 호출해야 합니다. 이 경우 허용량에 가스를 낭비할 필요가 없으므로 직접 전송하는 것이 좋습니다. + +```solidity + function cleanupERC20( + address erc20, + address dest + ) + public + onlyOwner + { + IERC20 token = IERC20(erc20); +``` + +이것은 주소를 받았을 때 계약에 대한 객체를 만드는 구문입니다. 소스 코드의 일부로 ERC20 토큰에 대한 정의가 있고(4행 참조), 해당 파일에 OpenZeppelin ERC-20 계약의 인터페이스인 [IERC20에 대한 정의](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol)가 포함되어 있기 때문에 이 작업을 수행할 수 있습니다. + +```solidity + uint balance = token.balanceOf(address(this)); + token.transfer(dest, balance); + } +``` + +이것은 정리 기능이므로 아마도 토큰을 남기고 싶지 않을 것입니다. 사용자로부터 수동으로 잔액을 가져오는 대신 프로세스를 자동화하는 것이 좋습니다. + +## 결론 {#conclusion} + +이것은 완벽한 해결책이 아닙니다. "사용자가 실수를 했다" 문제에 대한 완벽한 해결책은 없습니다. 그러나 이러한 종류의 확인을 사용하면 적어도 일부 실수를 방지할 수 있습니다. 계정을 동결하는 기능은 위험하지만 해커에게 도난당한 자금을 거부함으로써 특정 해킹의 피해를 제한하는 데 사용할 수 있습니다. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). diff --git a/public/content/translations/ko/developers/tutorials/ethereum-for-web2-auth/index.md b/public/content/translations/ko/developers/tutorials/ethereum-for-web2-auth/index.md new file mode 100644 index 00000000000..4328a51dd2d --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/ethereum-for-web2-auth/index.md @@ -0,0 +1,886 @@ +--- +title: "웹2 인증에 이더리움 사용하기" +description: "이 튜토리얼을 읽고 나면, 개발자는 이더리움 로그인(웹3)을 웹2에서 SSO(Single Sign-On) 및 기타 관련 서비스를 제공하는 데 사용되는 표준인 SAML 로그인과 통합할 수 있게 될 것입니다. 이를 통해 이더리움 서명을 통해 웹2 리소스에 대한 액세스를 인증할 수 있으며, 사용자 속성은 인증에서 가져옵니다." +author: Ori Pomerantz +tags: [ "웹2", "인증", "eas" ] +skill: beginner +lang: ko +published: 2025-04-30 +--- + +## 소개 + +[SAML](https://www.onelogin.com/learn/saml)은 웹2에서 [ID 공급자(IdP)](https://en.wikipedia.org/wiki/Identity_provider#SAML_identity_provider)가 [서비스 공급자(SP)](https://en.wikipedia.org/wiki/Service_provider_\(SAML\))에 대한 사용자 정보를 제공할 수 있도록 하는 데 사용되는 표준입니다. + +이 튜토리얼에서는 이더리움 서명을 SAML과 통합하여 사용자가 아직 이더리움을 기본적으로 지원하지 않는 웹2 서비스에 대해 이더리움 지갑을 사용하여 자신을 인증할 수 있도록 하는 방법을 배웁니다. + +이 튜토리얼은 두 가지 별개의 독자 그룹을 위해 작성되었습니다. + +- 이더리움을 이해하고 SAML을 배워야 하는 이더리움 사용자 +- SAML 및 웹2 인증을 이해하고 이더리움을 배워야 하는 웹2 사용자 + +따라서 이미 알고 있는 많은 입문 자료가 포함될 것입니다. 자유롭게 건너뛰어도 좋습니다. + +### 이더리움 사용자를 위한 SAML + +SAML은 중앙화된 프로토콜입니다. 서비스 공급자(SP)는 해당 ID 공급자(IdP) 또는 해당 IdP의 인증서에 서명한 [인증 기관](https://www.ssl.com/article/what-is-a-certificate-authority-ca/)과 사전 신뢰 관계가 있는 경우에만 ID 공급자로부터 어설션(예: "이 사용자는 John이고, 그는 A, B, C를 수행할 수 있는 권한을 가져야 합니다")을 수락합니다. + +예를 들어, SP는 회사에 여행 서비스를 제공하는 여행사일 수 있고 IdP는 회사의 내부 웹사이트일 수 있습니다. 직원들이 출장을 예약해야 할 때, 여행사는 실제로 여행을 예약하기 전에 회사에 인증을 보내도록 합니다. + +![SAML 단계별 프로세스](./fig-01-saml.png) + +이것은 브라우저, SP, IdP 세 엔티티가 액세스를 위해 협상하는 방식입니다. SP는 사전에 브라우저를 사용하는 사용자에 대해 아무것도 알 필요 없이 IdP를 신뢰하기만 하면 됩니다. + +### SAML 사용자를 위한 이더리움 + +이더리움은 탈중앙화된 시스템입니다. + +![이더리움 로그온](./fig-02-eth-logon.png) + +사용자는 개인 키를 가집니다(일반적으로 브라우저 확장 프로그램에 보관됨). 개인 키에서 공개 키를 파생할 수 있고, 공개 키에서 20바이트 주소를 파생할 수 있습니다. 사용자가 시스템에 로그인해야 할 때, 논스(일회용 값)가 포함된 메시지에 서명하도록 요청받습니다. 서버는 해당 주소에 의해 서명이 생성되었는지 확인할 수 있습니다. + +![인증에서 추가 데이터 가져오기](./fig-03-eas-data.png) + +서명은 이더리움 주소만 확인합니다. 다른 사용자 속성을 얻으려면 일반적으로 [인증](https://attest.org/)을 사용합니다. 인증에는 일반적으로 다음과 같은 필드가 있습니다. + +- **인증자**, 인증을 만든 주소 +- **수신자**, 인증이 적용되는 주소 +- **데이터**, 이름, 권한 등과 같이 인증되는 데이터입니다. +- **스키마**, 데이터를 해석하는 데 사용되는 스키마의 ID입니다. + +이더리움의 탈중앙화된 특성 때문에 모든 사용자가 인증을 생성할 수 있습니다. 신뢰할 수 있는 인증을 식별하려면 인증자의 신원이 중요합니다. + +## 설정 + +첫 번째 단계는 SAML SP와 SAML IdP가 서로 통신하도록 하는 것입니다. + +1. 소프트웨어를 다운로드합니다. 이 글의 샘플 소프트웨어는 [github](https://github.com/qbzzt/250420-saml-ethereum)에 있습니다. 여러 단계가 여러 브랜치에 저장되어 있습니다. 이 단계에서는 `saml-only`를 원합니다. + + ```sh + git clone https://github.com/qbzzt/250420-saml-ethereum -b saml-only + cd 250420-saml-ethereum + pnpm install + ``` + +2. 자체 서명된 인증서로 키를 생성합니다. 이는 키가 자체 인증 기관이며 서비스 공급자로 수동으로 가져와야 함을 의미합니다. 자세한 내용은 [OpenSSL 문서](https://docs.openssl.org/master/man1/openssl-req/)를 참조하세요. + + ```sh + mkdir keys + cd keys + openssl req -new -x509 -days 365 -nodes -sha256 -out saml-sp.crt -keyout saml-sp.pem -subj /CN=sp/ + openssl req -new -x509 -days 365 -nodes -sha256 -out saml-idp.crt -keyout saml-idp.pem -subj /CN=idp/ + cd .. + ``` + +3. 서버(SP 및 IdP 모두) 시작 + + ```sh + pnpm start + ``` + +4. URL [http://localhost:3000/](http://localhost:3000/)에서 SP로 이동하여 버튼을 클릭하면 IdP(포트 3001)로 리디렉션됩니다. + +5. IdP에 이메일 주소를 제공하고 서비스 공급자에 로그인을 클릭합니다. 서비스 공급자(포트 3000)로 다시 리디렉션되고 이메일 주소로 사용자를 인식하는지 확인합니다. + +### 자세한 설명 + +다음은 단계별로 일어나는 일입니다. + +![이더리움 없는 일반 SAML 로그온](./fig-04-saml-no-eth.png) + +#### src/config.mts + +이 파일에는 ID 공급자와 서비스 공급자 모두에 대한 구성이 포함되어 있습니다. 일반적으로 이 둘은 서로 다른 엔티티이지만 여기서는 단순화를 위해 코드를 공유할 수 있습니다. + +```typescript +const fs = await import("fs") + +const protocol="http" +``` + +지금은 테스트 중이므로 HTTP를 사용해도 괜찮습니다. + +```typescript +export const spCert = fs.readFileSync("keys/saml-sp.crt").toString() +export const idpCert = fs.readFileSync("keys/saml-idp.crt").toString() +``` + +일반적으로 두 구성 요소 모두에서 사용할 수 있는 공개 키를 읽습니다(직접 신뢰하거나 신뢰할 수 있는 인증 기관에서 서명함). + +```typescript +export const spPort = 3000 +export const spHostname = "localhost" +export const spDir = "sp" + +export const idpPort = 3001 +export const idpHostname = "localhost" +export const idpDir = "idp" + +export const spUrl = `${protocol}://${spHostname}:${spPort}/${spDir}` +export const idpUrl = `${protocol}://${idpHostname}:${idpPort}/${idpDir}` +``` + +두 구성 요소의 URL입니다. + +```typescript +export const spPublicData = { +``` + +서비스 공급자의 공개 데이터입니다. + +```typescript + entityID: `${spUrl}/metadata`, +``` + +관례적으로 SAML에서 `entityID`는 엔티티의 메타데이터를 사용할 수 있는 URL입니다. 이 메타데이터는 XML 형식이라는 점을 제외하고 여기의 공개 데이터에 해당합니다. + +```typescript + wantAssertionsSigned: true, + authnRequestsSigned: false, + signingCert: spCert, + allowCreate: true, + assertionConsumerService: [{ + Binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', + Location: `${spUrl}/assertion`, + }] + } +``` + +우리의 목적에 가장 중요한 정의는 `assertionConsumerServer`입니다. 이는 서비스 공급자에게 무언가를 주장하기 위해(예: "이 정보를 보내는 사용자는 somebody@example.com입니다") [HTTP POST](https://www.w3schools.com/tags/ref_httpmethods.asp)를 사용하여 URL `http://localhost:3000/sp/assertion`으로 보내야 함을 의미합니다. + +```typescript +export const idpPublicData = { + entityID: `${idpUrl}/metadata`, + signingCert: idpCert, + wantAuthnRequestsSigned: false, + singleSignOnService: [{ + Binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", + Location: `${idpUrl}/login` + }], + singleLogoutService: [{ + Binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", + Location: `${idpUrl}/logout` + }], + } +``` + +ID 공급자의 공개 데이터는 비슷합니다. 사용자를 로그인하려면 `http://localhost:3001/idp/login`에 POST하고 사용자를 로그아웃하려면 `http://localhost:3001/idp/logout`에 POST하도록 지정합니다. + +#### src/sp.mts + +서비스 공급자를 구현하는 코드입니다. + +```typescript +import * as config from "./config.mts" +const fs = await import("fs") +const saml = await import("samlify") +``` + +[`samlify`](https://www.npmjs.com/package/samlify) 라이브러리를 사용하여 SAML을 구현합니다. + +```typescript +import * as validator from "@authenio/samlify-node-xmllint" +saml.setSchemaValidator(validator) +``` + +`samlify` 라이브러리는 XML이 올바른지, 예상 공개 키로 서명되었는지 등을 확인하는 패키지가 있어야 합니다. 이 목적을 위해 [`@authenio/samlify-node-xmllint`](https://www.npmjs.com/package/@authenio/samlify-node-xmllint)를 사용합니다. + +```typescript +const express = (await import("express")).default +const spRouter = express.Router() +const app = express() +``` + +[`express`](https://expressjs.com/) [`Router`](https://expressjs.com/en/5x/api.html#router)는 웹 사이트 내에 마운트할 수 있는 "미니 웹 사이트"입니다. 이 경우 모든 서비스 공급자 정의를 함께 그룹화하는 데 사용됩니다. + +```typescript +const spPrivateKey = fs.readFileSync("keys/saml-sp.pem").toString() + +const sp = saml.ServiceProvider({ + privateKey: spPrivateKey, + ...config.spPublicData +}) +``` + +서비스 공급자의 자체 표현은 모든 공개 데이터와 정보를 서명하는 데 사용하는 개인 키입니다. + +```typescript +const idp = saml.IdentityProvider(config.idpPublicData); +``` + +공개 데이터에는 서비스 공급자가 ID 공급자에 대해 알아야 할 모든 것이 포함됩니다. + +```typescript +spRouter.get(`/metadata`, + (req, res) => res.header("Content-Type", "text/xml").send(sp.getMetadata()) +) +``` + +다른 SAML 구성 요소와의 상호 운용성을 활성화하려면 서비스 및 ID 공급자의 공개 데이터(메타데이터라고 함)를 `/metadata`의 XML 형식으로 사용할 수 있어야 합니다. + +```typescript +spRouter.post(`/assertion`, +``` + +이것은 브라우저가 자신을 식별하기 위해 액세스하는 페이지입니다. 어설션에는 사용자 식별자(여기서는 이메일 주소를 사용)가 포함되며 추가 속성을 포함할 수 있습니다. 위 시퀀스 다이어그램의 7단계에 대한 핸들러입니다. + +```typescript + async (req, res) => { + // console.log(`SAML response:\n${Buffer.from(req.body.SAMLResponse, 'base64').toString('utf-8')}`) +``` + +주석 처리된 명령을 사용하여 어설션에 제공된 XML 데이터를 볼 수 있습니다. [base64로 인코딩](https://en.wikipedia.org/wiki/Base64)되어 있습니다. + +```typescript + try { + const loginResponse = await sp.parseLoginResponse(idp, 'post', req); +``` + +ID 서버에서 로그인 요청을 구문 분석합니다. + +```typescript + res.send(` + + +

Hello ${loginResponse.extract.nameID}

+ + + `) + res.send(); +``` + +로그인을 받았음을 사용자에게 보여주기 위해 HTML 응답을 보냅니다. + +```typescript + } catch (err) { + console.error('Error processing SAML response:', err); + res.status(400).send('SAML authentication failed'); + } + } +) +``` + +실패 시 사용자에게 알립니다. + +```typescript +spRouter.get('/login', +``` + +브라우저가 이 페이지를 가져오려고 할 때 로그인 요청을 생성합니다. 위 시퀀스 다이어그램의 1단계에 대한 핸들러입니다. + +```typescript + async (req, res) => { + const loginRequest = await sp.createLoginRequest(idp, "post") +``` + +로그인 요청을 게시할 정보를 가져옵니다. + +```typescript + res.send(` + + + +``` + +이 페이지는 양식(아래 참조)을 자동으로 제출합니다. 이렇게 하면 사용자가 리디렉션되기 위해 아무것도 할 필요가 없습니다. 위 시퀀스 다이어그램의 2단계입니다. + +```typescript +
+``` + +`loginRequest.entityEndpoint`(ID 공급자 엔드포인트의 URL)에 게시합니다. + +```typescript + +``` + +입력 이름은 `loginRequest.type`(`SAMLRequest`)입니다. 해당 필드의 내용은 `loginRequest.context`이며, 다시 base64로 인코딩된 XML입니다. + +```typescript +
+ + + `) + } +) + +app.use(express.urlencoded({extended: true})) +``` + +[이 미들웨어는](https://expressjs.com/en/5x/api.html#express.urlencoded) [HTTP 요청](https://www.tutorialspoint.com/http/http_requests.htm)의 본문을 읽습니다. 기본적으로 express는 대부분의 요청에 필요하지 않기 때문에 무시합니다. POST는 본문을 사용하기 때문에 필요합니다. + +```typescript +app.use(`/${config.spDir}`, spRouter) +``` + +서비스 공급자 디렉터리(`/sp`)에 라우터를 마운트합니다. + +```typescript +app.get("/", (req, res) => { + res.send(` + + + + + + `) +}) +``` + +브라우저가 루트 디렉터리를 가져오려고 하면 로그인 페이지 링크를 제공합니다. + +```typescript +app.listen(config.spPort, () => { + console.log(`service provider is running on http://${config.spHostname}:${config.spPort}`) +}) +``` + +이 express 애플리케이션으로 `spPort`를 수신합니다. + +#### src/idp.mts + +ID 공급자입니다. 서비스 공급자와 매우 유사하며 아래 설명은 다른 부분에 대한 것입니다. + +```typescript +const xmlParser = new (await import("fast-xml-parser")).XMLParser( + { + ignoreAttributes: false, // Preserve attributes + attributeNamePrefix: "@_", // Prefix for attributes + } +) +``` + +서비스 공급자로부터 수신하는 XML 요청을 읽고 이해해야 합니다. + +```typescript +const getLoginPage = requestId => ` +``` + +이 함수는 위 시퀀스 다이어그램의 4단계에서 반환되는 자동 제출 양식이 있는 페이지를 만듭니다. + +```typescript + + + 로그인 페이지 + + +

로그인 페이지

+
+ + 이메일 주소: +
+ +``` + +서비스 공급자에게 보내는 필드는 두 가지입니다. + +1. 응답 중인 `requestId`. +2. 사용자 식별자(지금은 사용자가 제공한 이메일 주소를 사용). + +```typescript +
+ + + +const idpRouter = express.Router() + +idpRouter.post("/loginSubmitted", async (req, res) => { + const loginResponse = await idp.createLoginResponse( +``` + +위 시퀀스 다이어그램의 5단계에 대한 핸들러입니다. [`idp.createLoginResponse`](https://github.com/tngan/samlify/blob/master/src/entity-idp.ts#L73-L125)는 로그인 응답을 생성합니다. + +```typescript + sp, + { + authnContextClassRef: 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport', + audience: sp.entityID, +``` + +대상은 서비스 공급자입니다. + +```typescript + extract: { + request: { + id: req.body.requestId + } + }, +``` + +요청에서 추출한 정보입니다. 요청에서 우리가 신경 쓰는 매개변수 중 하나는 requestId로, 서비스 공급자가 요청과 응답을 일치시킬 수 있게 해줍니다. + +```typescript + signingKey: { privateKey: idpPrivateKey, publicKey: config.idpCert } // Ensure signing +``` + +응답에 서명할 데이터를 가지려면 `signingKey`가 필요합니다. 서비스 공급자는 서명되지 않은 요청을 신뢰하지 않습니다. + +```typescript + }, + "post", + { + email: req.body.email +``` + +서비스 공급자에게 다시 보내는 사용자 정보가 있는 필드입니다. + +```typescript + } + ); + + res.send(` + + + + +
+ +
+ + + `) +}) +``` + +다시 자동 제출 양식을 사용합니다. 위 시퀀스 다이어그램의 6단계입니다. + +```typescript + +// IdP endpoint for login requests +idpRouter.post(`/login`, +``` + +서비스 공급자로부터 로그인 요청을 수신하는 엔드포인트입니다. 위 시퀀스 다이어그램의 3단계에 대한 핸들러입니다. + +```typescript + async (req, res) => { + try { + // Workaround because I couldn't get parseLoginRequest to work. + // const loginRequest = await idp.parseLoginRequest(sp, 'post', req) + const samlRequest = xmlParser.parse(Buffer.from(req.body.SAMLRequest, 'base64').toString('utf-8')) + res.send(getLoginPage(samlRequest["samlp:AuthnRequest"]["@_ID"])) +``` + +인증 요청의 ID를 읽으려면 [`idp.parseLoginRequest`](https://github.com/tngan/samlify/blob/master/src/entity-idp.ts#L127-L144)를 사용할 수 있어야 합니다. 하지만 작동하게 할 수 없었고 많은 시간을 할애할 가치가 없었기 때문에 [범용 XML 파서](https://www.npmjs.com/package/fast-xml-parser)를 사용했습니다. 필요한 정보는 XML의 최상위 수준에 있는 `` 태그 내의 `ID` 속성입니다. + +## 이더리움 서명 사용하기 + +이제 서비스 공급자에게 사용자 ID를 보낼 수 있으므로 다음 단계는 신뢰할 수 있는 방식으로 사용자 ID를 얻는 것입니다. Viem을 사용하면 지갑에 사용자 주소를 요청할 수 있지만, 이는 브라우저에 정보를 요청하는 것을 의미합니다. 브라우저를 제어할 수 없으므로 브라우저에서 받은 응답을 자동으로 신뢰할 수 없습니다. + +대신 IdP는 브라우저에 서명할 문자열을 보냅니다. 브라우저의 지갑이 이 문자열에 서명하면 실제로 해당 주소라는 것을 의미합니다(즉, 주소에 해당하는 개인 키를 알고 있음). + +이것이 작동하는 것을 보려면 기존 IdP와 SP를 중지하고 다음 명령을 실행하세요. + +```sh +git checkout eth-signatures +pnpm install +pnpm start +``` + +그런 다음 [SP](http://localhost:3000)로 이동하여 지침을 따릅니다. + +이 시점에서는 이더리움 주소에서 이메일 주소를 얻는 방법을 모르므로 대신 `<이더리움 주소>@bad.email.address`를 SP에 보고합니다. + +### 자세한 설명 + +변경 사항은 이전 다이어그램의 4-5단계에 있습니다. + +![이더리움 서명을 사용한 SAML](./fig-05-saml-w-signature.png) + +변경된 유일한 파일은 `idp.mts`입니다. 변경된 부분은 다음과 같습니다. + +```typescript +import { v4 as uuidv4 } from 'uuid' +import { verifyMessage } from 'viem' +``` + +이 두 개의 추가 라이브러리가 필요합니다. [`uuid`](https://www.npmjs.com/package/uuid)를 사용하여 [논스](https://en.wikipedia.org/wiki/Cryptographic_nonce) 값을 생성합니다. 값 자체는 중요하지 않고 한 번만 사용된다는 사실만 중요합니다. + +[`viem`](https://viem.sh/) 라이브러리를 사용하면 이더리움 정의를 사용할 수 있습니다. 여기서는 서명이 실제로 유효한지 확인해야 합니다. + +```typescript +const loginPrompt = "서비스 공급자에 액세스하려면 이 논스에 서명하세요: " +``` + +지갑은 사용자에게 메시지에 서명할 권한을 요청합니다. 논스만 있는 메시지는 사용자를 혼란스럽게 할 수 있으므로 이 프롬프트를 포함합니다. + +```typescript +// Keep requestIDs here +let nonces = {} +``` + +응답하려면 요청 정보가 필요합니다. 요청(4단계)과 함께 보내고 다시 받을 수 있습니다(5단계). 그러나 잠재적으로 적대적인 사용자의 통제하에 있는 브라우저에서 얻는 정보는 신뢰할 수 없습니다. 따라서 여기에 nonce를 키로 저장하는 것이 좋습니다. + +여기서는 단순성을 위해 변수로 수행하고 있음을 참고하세요. 그러나 여기에는 몇 가지 단점이 있습니다. + +- 서비스 거부 공격에 취약합니다. 악의적인 사용자가 여러 번 로그온을 시도하여 메모리를 채울 수 있습니다. +- IdP 프로세스를 다시 시작해야 하는 경우 기존 값을 잃게 됩니다. +- 각각 고유한 변수를 가지므로 여러 프로세스에 걸쳐 부하를 분산할 수 없습니다. + +프로덕션 시스템에서는 데이터베이스를 사용하고 일종의 만료 메커니즘을 구현합니다. + +```typescript +const getSignaturePage = requestId => { + const nonce = uuidv4() + nonces[nonce] = requestId +``` + +논스를 만들고 나중에 사용할 수 있도록 `requestId`를 저장합니다. + +```typescript + return ` + + + + + +

서명하세요

+ +
+ + + +` +} +``` + +나머지는 표준 HTML입니다. + +```typescript +idpRouter.get("/signature/:nonce/:account/:signature", async (req, res) => { +``` + +시퀀스 다이어그램의 5단계에 대한 핸들러입니다. + +```typescript + const requestId = nonces[req.params.nonce] + if (requestId === undefined) { + res.send("Bad nonce") + return ; + } + + nonces[req.params.nonce] = undefined +``` + +요청 ID를 가져오고 재사용할 수 없도록 `nonces`에서 논스를 삭제합니다. + +```typescript + try { +``` + +서명이 유효하지 않을 수 있는 방법이 너무 많기 때문에 `try ...`로 래핑합니다. catch` 블록으로 발생한 오류를 포착합니다. + +```typescript + const validSignature = await verifyMessage({ + address: req.params.account, + message: `${loginPrompt}${req.params.nonce}`, + signature: req.params.signature + }) +``` + +시퀀스 다이어그램의 5.5단계를 구현하려면 [`verifyMessage`](https://viem.sh/docs/actions/public/verifyMessage#verifymessage)를 사용합니다. + +```typescript + if (!validSignature) + throw("Bad signature") + } catch (err) { + res.send("Error:" + err) + return ; + } +``` + +핸들러의 나머지 부분은 한 가지 작은 변경 사항을 제외하고 이전에 `/loginSubmitted` 핸들러에서 수행한 것과 동일합니다. + +```typescript + const loginResponse = await idp.createLoginResponse( + . + . + . + { + email: req.params.account + "@bad.email.address" + } + ); +``` + +실제 이메일 주소는 없으므로(다음 섹션에서 얻을 수 있음) 지금은 이더리움 주소를 반환하고 이메일 주소가 아님을 명확하게 표시합니다. + +```typescript +// IdP endpoint for login requests +idpRouter.post(`/login`, + async (req, res) => { + try { + // Workaround because I couldn't get parseLoginRequest to work. + // const loginRequest = await idp.parseLoginRequest(sp, 'post', req) + const samlRequest = xmlParser.parse(Buffer.from(req.body.SAMLRequest, 'base64').toString('utf-8')) + res.send(getSignaturePage(samlRequest["samlp:AuthnRequest"]["@_ID"])) + } catch (err) { + console.error('Error processing SAML response:', err); + res.status(400).send('SAML authentication failed'); + } + } +) +``` + +3단계 핸들러에서 `getLoginPage` 대신 이제 `getSignaturePage`를 사용합니다. + +## 이메일 주소 받기 + +다음 단계는 서비스 공급자가 요청한 식별자인 이메일 주소를 얻는 것입니다. 이를 위해 [이더리움 증명 서비스(EAS)](https://attest.org/)를 사용합니다. + +인증을 얻는 가장 쉬운 방법은 [GraphQL API](https://docs.attest.org/docs/developer-tools/api)를 사용하는 것입니다. 다음 쿼리를 사용합니다. + +``` +query GetAttestationsByRecipient { + attestations( + where: { + recipient: { equals: "${getAddress(ethAddr)}" } + schemaId: { equals: "0xfa2eff59a916e3cc3246f9aec5e0ca00874ae9d09e4678e5016006f07622f977" } + } + take: 1 + ) { + data + id + attester + } +} +``` + +이 [`schemaId`](https://optimism.easscan.org/schema/view/0xfa2eff59a916e3cc3246f9aec5e0ca00874ae9d09e4678e5016006f07622f977)는 이메일 주소만 포함합니다. 이 쿼리는 이 스키마의 인증을 요청합니다. 인증의 주체는 `recipient`라고 합니다. 항상 이더리움 주소입니다. + +경고: 여기서 인증을 얻는 방식에는 두 가지 보안 문제가 있습니다. + +- 중앙화된 구성 요소인 API 엔드포인트 `https://optimism.easscan.org/graphql`로 이동합니다. `id` 속성을 가져와서 온체인 조회를 통해 인증이 진짜인지 확인할 수 있지만, API 엔드포인트는 인증에 대해 알려주지 않음으로써 여전히 인증을 검열할 수 있습니다. + + 이 문제는 해결 불가능한 것이 아니며, 자체 GraphQL 엔드포인트를 실행하고 체인 로그에서 인증을 얻을 수 있지만, 우리의 목적에는 과도합니다. + +- 인증자 신원을 보지 않습니다. 누구나 거짓 정보를 제공할 수 있습니다. 실제 구현에서는 신뢰할 수 있는 인증자 집합이 있고 그들의 인증만 살펴봅니다. + +이것이 작동하는 것을 보려면 기존 IdP와 SP를 중지하고 다음 명령을 실행하세요. + +```sh +git checkout email-address +pnpm install +pnpm start +``` + +그런 다음 이메일 주소를 제공합니다. 두 가지 방법이 있습니다. + +- 개인 키를 사용하여 지갑을 가져오고 테스트 개인 키 `0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80`을 사용합니다. + +- 자신의 이메일 주소에 대한 인증을 추가합니다. + + 1. 인증 탐색기에서 [스키마](https://optimism.easscan.org/schema/view/0xfa2eff59a916e3cc3246f9aec5e0ca00874ae9d09e4678e5016006f07622f977)로 이동합니다. + + 2. **스키마로 인증**을 클릭합니다. + + 3. 이더리움 주소를 수신자로 입력하고, 이메일 주소를 이메일 주소로 입력하고, **온체인**을 선택합니다. 그런 다음 **인증 만들기**를 클릭합니다. + + 4. 지갑에서 트랜잭션을 승인합니다. 가스를 지불하려면 [옵티미즘 블록체인](https://app.optimism.io/bridge/deposit)에 ETH가 필요합니다. + +어느 쪽이든 이 작업을 마친 후 [http://localhost:3000](http://localhost:3000)으로 이동하여 지침을 따릅니다. 테스트 개인 키를 가져온 경우 받는 이메일은 `test_addr_0@example.com`입니다. 자신의 주소를 사용했다면 인증한 주소여야 합니다. + +### 자세한 설명 + +![이더리움 주소에서 이메일로 가져오기](./fig-06-saml-sig-n-email.png) + +새로운 단계는 GraphQL 통신, 5.6 및 5.7단계입니다. + +다시 한 번, `idp.mts`의 변경된 부분은 다음과 같습니다. + +```typescript +import { GraphQLClient } from 'graphql-request' +import { SchemaEncoder } from '@ethereum-attestation-service/eas-sdk' +``` + +필요한 라이브러리를 가져옵니다. + +```typescript +const graphqlEndpointUrl = "https://optimism.easscan.org/graphql" +``` + +[각 블록체인에 대한 별도의 엔드포인트](https://docs.attest.org/docs/developer-tools/api)가 있습니다. + +```typescript +const graphqlClient = new GraphQLClient(graphqlEndpointUrl, { fetch }) +``` + +엔드포인트 쿼리에 사용할 수 있는 새로운 `GraphQLClient` 클라이언트를 만듭니다. + +```typescript +const graphqlSchema = 'string emailAddress' +const graphqlEncoder = new SchemaEncoder(graphqlSchema) +``` + +GraphQL은 바이트가 포함된 불투명한 데이터 객체만 제공합니다. 이를 이해하려면 스키마가 필요합니다. + +```typescript +const ethereumAddressToEmail = async ethAddr => { +``` + +이더리움 주소에서 이메일 주소로 변환하는 함수입니다. + +```typescript + const query = ` + query GetAttestationsByRecipient { +``` + +GraphQL 쿼리입니다. + +```typescript + attestations( +``` + +인증을 찾고 있습니다. + +```typescript + where: { + recipient: { equals: "${getAddress(ethAddr)}" } + schemaId: { equals: "0xfa2eff59a916e3cc3246f9aec5e0ca00874ae9d09e4678e5016006f07622f977" } + } +``` + +원하는 인증은 스키마에 있으며 수신자가 `getAddress(ethAddr)`인 인증입니다. [`getAddress`](https://viem.sh/docs/utilities/getAddress#getaddress) 함수는 주소에 올바른 [체크섬](https://github.com/ethereum/ercs/blob/master/ERCS/erc-55.md)이 있는지 확인합니다. 이는 GraphQL이 대소문자를 구분하기 때문에 필요합니다. "0xBAD060A7", "0xBad060A7", "0xbad060a7"은 서로 다른 값입니다. + +```typescript + take: 1 +``` + +몇 개의 인증을 찾든 첫 번째 것만 원합니다. + +```typescript + ) { + data + id + attester + } + }` +``` + +받고 싶은 필드입니다. + +- `attester`: 인증을 제출한 주소. 일반적으로 인증을 신뢰할지 여부를 결정하는 데 사용됩니다. +- `id`: 인증 ID. 이 값을 사용하여 [온체인에서 인증을 읽어](https://optimism.blockscout.com/address/0x4200000000000000000000000000000000000021?tab=read_proxy&source_address=0x4E0275Ea5a89e7a3c1B58411379D1a0eDdc5b088#0xa3112a64) GraphQL 쿼리의 정보가 올바른지 확인할 수 있습니다. +- `data`: 스키마 데이터(이 경우 이메일 주소). + +```typescript + const queryResult = await graphqlClient.request(query) + + if (queryResult.attestations.length == 0) + return "no_address@available.is" +``` + +인증이 없는 경우 명백히 잘못되었지만 서비스 공급자에게 유효하게 표시되는 값을 반환합니다. + +```typescript + const attestationDataFields = graphqlEncoder.decodeData(queryResult.attestations[0].data) + return attestationDataFields[0].value.value +} +``` + +값이 있으면 `decodeData`를 사용하여 데이터를 디코딩합니다. 제공하는 메타데이터는 필요하지 않고 값 자체만 필요합니다. + +```typescript + const loginResponse = await idp.createLoginResponse( + sp, + { + . + . + . + }, + "post", + { + email: await ethereumAddressToEmail(req.params.account) + } + ); +``` + +새 함수를 사용하여 이메일 주소를 가져옵니다. + +## 탈중앙화는 어떻습니까? + +이 구성에서 사용자는 이더리움-이메일 주소 매핑을 위해 신뢰할 수 있는 인증자에 의존하는 한 다른 사람인 척할 수 없습니다. 그러나 ID 공급자는 여전히 중앙화된 구성 요소입니다. ID 공급자의 개인 키를 가진 사람은 누구나 서비스 공급자에게 거짓 정보를 보낼 수 있습니다. + +[다자간 계산(MPC)](https://en.wikipedia.org/wiki/Secure_multi-party_computation)를 사용하는 솔루션이 있을 수 있습니다. 다음 튜토리얼에서 이에 대해 쓸 수 있기를 바랍니다. + +## 결론 + +이더리움 서명과 같은 로그온 표준을 채택하는 것은 닭과 달걀 문제에 직면합니다. 서비스 공급자는 가능한 가장 넓은 시장에 어필하기를 원합니다. 사용자는 로그온 표준 지원에 대해 걱정하지 않고 서비스에 액세스할 수 있기를 원합니다. +이더리움 IdP와 같은 어댑터를 만들면 이 장애물을 극복하는 데 도움이 될 수 있습니다. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). diff --git a/public/content/translations/ko/developers/tutorials/getting-started-with-ethereum-development-using-alchemy/index.md b/public/content/translations/ko/developers/tutorials/getting-started-with-ethereum-development-using-alchemy/index.md new file mode 100644 index 00000000000..023e8ed5ad7 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/getting-started-with-ethereum-development-using-alchemy/index.md @@ -0,0 +1,149 @@ +--- +title: "이더리움 개발 시작하기" +description: "이더리움 개발을 시작하는 입문자를 위한 가이드입니다. API 엔드포인트를 구동하는 것부터 명령줄 요청을 보내고, 첫 웹3 스크립트를 작성하는 것까지 안내해 드립니다! 사전 블록체인 개발 경험은 필요 없어요!" +author: "Elan Halpern" +tags: [ "JavaScript", "ethers.js", "노드", "요청", "Alchemy" ] +skill: beginner +lang: ko +published: 2020-10-30 +source: Medium +sourceUrl: https://medium.com/alchemy-api/getting-started-with-ethereum-development-using-alchemy-c3d6a45c567f +--- + +![이더리움과 Alchemy 로고](./ethereum-alchemy.png) + +이더리움 개발을 시작하는 입문자를 위한 가이드입니다. 이번 튜토리얼에서는 Maker, 0x, MyEtherWallet, Dharma, Kyber를 비롯한 상위 블록체인 앱 70%가 사용하는 수백만 명의 사용자를 지원하는 선도적인 블록체인 개발자 플랫폼인 [Alchemy](https://alchemyapi.io/)를 사용합니다. Alchemy는 이더리움 체인의 API 엔드포인트에 대한 액세스를 제공하여 트랜잭션을 읽고 쓸 수 있도록 합니다. + +Alchemy에 가입하는 것부터 첫 웹3 스크립트를 작성하는 것까지 안내해 드립니다! 사전 블록체인 개발 경험은 필요 없어요! + +## 1. 무료 Alchemy 계정 가입하기 {#sign-up-for-a-free-alchemy-account} + +Alchemy 계정 생성은 간단합니다. [여기에서 무료로 가입하세요](https://auth.alchemy.com/). + +## 2. Alchemy 앱 만들기 {#create-an-alchemy-app} + +이더리움 체인과 통신하고 Alchemy 제품을 사용하려면 요청을 인증할 API 키가 필요합니다. + +[대시보드에서 API 키를 생성](https://dashboard.alchemy.com/)할 수 있습니다. 새 키를 생성하려면 아래와 같이 “앱 만들기” 로 이동합니다. + +[_ShapeShift_](https://shapeshift.com/)가 _대시보드를 보여주도록 허락해준 것에 대해 특별히 감사드립니다!_ + +![Alchemy 대시보드](./alchemy-dashboard.png) + +“앱 만들기” 밑의 입력란을 채워 새 키를 얻으세요. 여기에서 이전에 만들었던 앱을 보거나 팀에서 만든 앱을 볼 수 있습니다. 아무 앱에서나 '키 보기'를 클릭하여 기존 키를 가져올 수 있습니다. + +![Alchemy로 앱 만들기 스크린샷](./create-app.png) + +'앱' 위에 마우스를 올리고 하나를 선택하여 기존 API 키를 가져올 수도 있습니다. 여기에서 '키 보기'를 하거나, '앱 편집'에서 특정 도메인을 화이트리스트에 추가하고, 여러 개발자 도구를 확인하며, 분석을 볼 수 있습니다. + +![사용자에게 API 키를 가져오는 방법을 보여주는 Gif](./pull-api-keys.gif) + +## 3. 명령줄에서 요청하기 {#make-a-request-from-the-command-line} + +JSON-RPC와 curl을 사용하여 Alchemy를 통해 이더리움 블록체인과 상호작용합니다. + +수동 요청의 경우 `POST` 요청을 통해 `JSON-RPC`와 상호작용하는 것을 권장합니다. 다음 필드와 함께 `Content-Type: application/json` 헤더와 쿼리를 `POST` 본문으로 전달하기만 하면 됩니다: + +- `jsonrpc`: JSON-RPC 버전—현재는 `2.0`만 지원됩니다. +- `method`: ETH API 메서드. [API 참조 보기](https://docs.alchemyapi.io/documentation/alchemy-api-reference/json-rpc) +- `params`: 메서드에 전달할 파라미터 목록입니다. +- `id`: 요청의 ID입니다. 응답에 의해 반환되므로 어떤 요청에 대한 응답인지 추적할 수 있습니다. + +다음은 명령줄에서 실행하여 현재 가스 가격을 검색하는 예제입니다: + +```bash +curl https://eth-mainnet.alchemyapi.io/v2/demo \ +-X POST \ +-H "Content-Type: application/json" \ +-d '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":73}' +``` + +_**참고:** [https://eth-mainnet.alchemyapi.io/v2/demo](https://eth-mainnet.alchemyapi.io/jsonrpc/demo)를 본인의 API 키 `https://eth-mainnet.alchemyapi.io/v2/**your-api-key`로 바꾸세요._ + +**결과:** + +```json +{ "id": 73,"jsonrpc": "2.0","result": "0x09184e72a000" // 10000000000000 } +``` + +## 4. 웹3 클라이언트 설정하기 {#set-up-your-web3-client} + +**기존 클라이언트가 있는 경우,** 현재 노드 공급자 URL을 API 키가 포함된 Alchemy URL로 변경하세요: `“https://eth-mainnet.alchemyapi.io/v2/your-api-key"` + +**_참고:_** 아래 스크립트는 명령줄에서 실행하는 것이 아니라 노드 컨텍스트에서 실행하거나 파일에 저장해야 합니다. Node나 npm이 아직 설치되지 않았다면, 이 빠른 [mac용 설정 가이드](https://app.gitbook.com/@alchemyapi/s/alchemy/guides/alchemy-for-macs)를 확인하세요. + +Alchemy와 통합할 수 있는 [웹3 라이브러리](https://docs.alchemyapi.io/guides/getting-started#other-web3-libraries)는 많지만, web3.js를 바로 대체할 수 있으며 Alchemy와 원활하게 작동하도록 빌드 및 구성된 [Alchemy 웹3](https://docs.alchemy.com/reference/api-overview) 사용을 권장합니다. 이는 자동 재시도 및 강력한 WebSocket 지원과 같은 여러 이점을 제공합니다. + +AlchemyWeb3.js를 설치하려면 프로젝트 디렉터리로 이동하고 다음을 실행하세요: + +**Yarn 사용 시:** + +``` +yarn add @alch/alchemy-web3 +``` + +**NPM 사용 시:** + +``` +npm install @alch/alchemy-web3 +``` + +Alchemy의 노드 인프라와 상호작용하려면 NodeJS에서 실행하거나 이 코드를 JavaScript 파일에 추가하세요: + +```js +const { createAlchemyWeb3 } = require("@alch/alchemy-web3") +const web3 = createAlchemyWeb3( + "https://eth-mainnet.alchemyapi.io/v2/your-api-key" +) +``` + +## 5. 첫 웹3 스크립트 작성하기! {#write-your-first-web3-script} + +이제 웹3 프로그래밍을 본격적으로 시작해보기 위해 이더리움 메인넷에서 최신 블록 번호를 출력하는 간단한 스크립트를 작성해 보겠습니다. + +**1.** 아직 하지 않았다면, 터미널에서 새 프로젝트 디렉터리를 만들고 그 안으로 이동(cd)하세요:\*\* + +``` +mkdir web3-example +cd web3-example +``` + +**2.** 아직 설치하지 않았다면 프로젝트에 Alchemy 웹3(또는 다른 웹3) 의존성을 설치하세요:\*\* + +``` +npm install @alch/alchemy-web3 +``` + +**3.** `index.js`라는 이름의 파일을 만들고 다음 내용을 추가하세요:\*\* + +> `demo`는 본인의 Alchemy HTTP API 키로 교체해야 합니다. + +```js +async function main() { + const { createAlchemyWeb3 } = require("@alch/alchemy-web3") + const web3 = createAlchemyWeb3("https://eth-mainnet.alchemyapi.io/v2/demo") + const blockNumber = await web3.eth.getBlockNumber() + console.log("최신 블록 번호는 " + blockNumber) +} +main() +``` + +비동기와 관련된 것들이 낯선가요? 이 [Medium 게시물](https://medium.com/better-programming/understanding-async-await-in-javascript-1d81bb079b2c)을 확인해보세요. + +**4. node를 사용하여 터미널에서 실행하세요** + +``` +node index.js +``` + +**5. 이제 콘솔에 최신 블록 번호 출력이 표시될 것입니다!** + +``` +최신 블록 번호는 11043912 +``` + +**수고하셨어요!** 축하해요! Alchemy를 사용하여 첫 번째 웹3 스크립트를 작성했습니다 🎉\*\* + +다음으로 해야 될 걸 모르겠나요? [Hello World 스마트 계약 가이드](https://www.alchemy.com/docs/hello-world-smart-contract)에서 첫 스마트 계약을 배포하고 솔리디티 프로그래밍을 직접 해보거나, [대시보드 데모 앱](https://docs.alchemyapi.io/tutorials/demo-app)으로 대시보드 지식을 테스트해보세요! + +_[무료로 Alchemy에 가입](https://auth.alchemy.com/)하고, [개발문서](https://www.alchemy.com/docs/)를 확인하고, 최신 소식을 보려면 [Twitter](https://twitter.com/AlchemyPlatform)에서 저희를 팔로우하세요_. diff --git a/public/content/translations/ko/developers/tutorials/guide-to-smart-contract-security-tools/index.md b/public/content/translations/ko/developers/tutorials/guide-to-smart-contract-security-tools/index.md new file mode 100644 index 00000000000..a6f8366a355 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/guide-to-smart-contract-security-tools/index.md @@ -0,0 +1,102 @@ +--- +title: "스마트 계약 보안 도구 가이드" +description: "세 가지 다른 테스팅 및 프로그램 분석 기법 개요" +author: "Trailofbits" +lang: ko +tags: [ "Solidity", "스마트 계약", "보안" ] +skill: intermediate +published: 2020-09-07 +source: Building secure contracts +sourceUrl: https://github.com/crytic/building-secure-contracts/tree/master/program-analysis +--- + +세 가지 독특한 테스팅 및 프로그램 분석 기법을 사용할 것입니다. + +- **[Slither](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/)를 사용한 정적 분석.** 프로그램의 모든 경로를 다양한 프로그램 표현(예: 제어 흐름 그래프)을 통해 동시에 근사화하고 분석합니다. +- **[Echidna](/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/)를 사용한 퍼징.** 트랜잭션을 의사 난수 생성하여 코드를 실행합니다. 퍼저는 주어진 속성을 위반하는 트랜잭션 시퀀스를 찾으려고 시도합니다. +- **[Manticore](/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/)를 사용한 심볼릭 실행.** 각 실행 경로를 수학 공식으로 변환하고 그 위에 제약 조건을 확인할 수 있는 정형 검증 기법입니다. + +각 기법은 장점과 단점이 있으며 [특정 사례](#determining-security-properties)에서 유용합니다. + +| 기법 | 도구 | 사용 방식 | 속도 | 놓친 버그 | 오탐 | +| ------ | --------- | ------------------ | ----- | ----- | -- | +| 정적 분석 | Slither | CLI 및 스크립트 | 초 단위 | 보통 | 낮음 | +| 퍼징 | Echidna | Solidity 속성 | 분 단위 | 낮음 | 없음 | +| 심볼릭 실행 | Manticore | Solidity 속성 및 스크립트 | 시간 단위 | 없음\* | 없음 | + +\* 시간 초과 없이 모든 경로를 탐색하는 경우 + +Slither는 몇 초 안에 계약을 분석하지만 정적 분석은 오탐을 유발할 수 있으며 복잡한 검사(예: 산술 검사)에는 덜 적합합니다. API를 통해 Slither를 실행하여 내장된 탐지기에 간편하게 액세스하거나 사용자 정의 검사를 수행할 수 있습니다. + +Echidna는 몇 분 동안 실행해야 하며 실제 참(true positive)만 생성합니다. Echidna는 Solidity로 작성된 사용자 제공 보안 속성을 확인합니다. 무작위 탐색을 기반으로 하므로 버그를 놓칠 수 있습니다. + +Manticore는 가장 "무거운" 분석을 수행합니다. Echidna와 마찬가지로 Manticore는 사용자가 제공한 속성을 확인합니다. 실행하는 데 더 많은 시간이 필요하지만 속성의 유효성을 증명할 수 있으며 오탐을 보고하지 않습니다. + +## 권장 워크플로 {#suggested-workflow} + +Slither의 내장 탐지기로 시작하여 간단한 버그가 현재 존재하지 않거나 나중에 유입되지 않도록 하세요. Slither를 사용하여 상속, 변수 종속성 및 구조적 문제와 관련된 속성을 확인하세요. 코드베이스가 커짐에 따라 Echidna를 사용하여 상태 머신의 더 복잡한 속성을 테스트하세요. Solidity에서 사용할 수 없는 보호 기능(예: 함수 재정의 방지)을 위해 Slither를 다시 사용하여 맞춤형 검사를 개발하세요. 마지막으로 Manticore를 사용하여 중요한 보안 속성(예: 산술 연산)의 대상 검증을 수행하세요. + +- Slither의 CLI를 사용하여 일반적인 문제 발견 +- Echidna를 사용하여 계약의 상위 수준 보안 속성 테스트 +- Slither를 사용하여 맞춤형 정적 검사 작성 +- 중요한 보안 속성에 대한 심층적인 보증을 원할 때 Manticore 사용 + +**단위 테스트에 대한 참고 사항**. 단위 테스트는 고품질 소프트웨어를 구축하는 데 필요합니다. 그러나 이러한 기법은 보안 결함을 찾는 데 가장 적합하지는 않습니다. 일반적으로 코드의 긍정적인 동작(즉, 코드가 일반적인 컨텍스트에서 예상대로 작동함)을 테스트하는 데 사용되는 반면, 보안 결함은 개발자가 고려하지 않은 엣지 케이스에 있는 경향이 있습니다. 수십 건의 스마트 계약 보안 검토에 대한 저희의 연구에서, [저희가 고객의 코드에서 발견한 보안 결함의 수나 심각도에 단위 테스트 커버리지는 영향을 미치지 않았습니다](https://blog.trailofbits.com/2019/08/08/246-findings-from-our-smart-contract-audits-an-executive-summary/). + +## 보안 속성 결정하기 {#determining-security-properties} + +코드를 효과적으로 테스트하고 검증하려면 주의가 필요한 영역을 식별해야 합니다. 보안에 사용하는 리소스는 제한적이므로, 코드베이스의 취약하거나 가치가 높은 부분의 범위를 정하는 것이 노력을 최적화하는 데 중요합니다. 위협 모델링이 도움이 될 수 있습니다. 다음을 검토해 보세요. + +- [신속한 위험 평가](https://infosec.mozilla.org/guidelines/risk/rapid_risk_assessment.html)(시간이 부족할 때 선호하는 접근 방식) +- [데이터 중심 시스템 위협 모델링 가이드](https://csrc.nist.gov/pubs/sp/800/154/ipd)(일명 NIST 800-154) +- [Shostack 위협 모델링](https://www.amazon.com/Threat-Modeling-Designing-Adam-Shostack/dp/1118809998) +- [STRIDE](https://wikipedia.org/wiki/STRIDE_\(security\)) / [DREAD](https://wikipedia.org/wiki/DREAD_\(risk_assessment_model\)) +- [PASTA](https://wikipedia.org/wiki/Threat_model#P.A.S.T.A.) +- [단언문 사용](https://blog.regehr.org/archives/1091) + +### 구성 요소 {#components} + +확인하려는 내용을 알면 적절한 도구를 선택하는 데도 도움이 됩니다. + +스마트 계약과 자주 관련된 광범위한 영역은 다음과 같습니다. + +- **상태 머신.** 대부분의 계약은 상태 머신으로 표현될 수 있습니다. (1) 유효하지 않은 상태에 도달할 수 없는지, (2) 상태가 유효할 경우 도달할 수 있는지, (3) 어떤 상태도 계약을 가두지 않는지 확인하는 것을 고려해 보세요. + + - Echidna와 Manticore는 상태 머신 사양을 테스트하는 데 선호되는 도구입니다. + +- **액세스 제어.** 시스템에 권한 있는 사용자(예: 소유자, 컨트롤러 등)가 있는 경우 (1) 각 사용자는 승인된 작업만 수행할 수 있고, (2) 어떤 사용자도 더 많은 권한을 가진 사용자의 작업을 차단할 수 없도록 보장해야 합니다. + + - Slither, Echidna, Manticore는 올바른 액세스 제어를 확인할 수 있습니다. 예를 들어, Slither는 화이트리스트에 있는 함수에만 onlyOwner 수정자가 없는지 확인할 수 있습니다. Echidna와 Manticore는 계약이 특정 상태에 도달한 경우에만 권한이 부여되는 것과 같은 더 복잡한 액세스 제어에 유용합니다. + +- **산술 연산.** 산술 연산의 건전성을 확인하는 것은 매우 중요합니다. 모든 곳에서 `SafeMath`를 사용하는 것은 오버플로우/언더플로우를 방지하는 좋은 방법이지만, 반올림 문제와 계약을 가두는 결함을 포함한 다른 산술적 결함도 여전히 고려해야 합니다. + + - 여기서는 Manticore가 최선의 선택입니다. 산술이 SMT 솔버의 범위를 벗어나는 경우 Echidna를 사용할 수 있습니다. + +- **상속 정확성.** Solidity 계약은 다중 상속에 크게 의존합니다. `super` 호출이 누락된 섀도잉 함수, 잘못 해석된 c3 선형화 순서와 같은 실수가 쉽게 발생할 수 있습니다. + + - Slither는 이러한 문제를 확실하게 탐지할 수 있는 도구입니다. + +- **외부 상호작용.** 계약은 서로 상호작용하며, 일부 외부 계약은 신뢰해서는 안 됩니다. 예를 들어, 계약이 외부 오라클에 의존하는 경우 사용 가능한 오라클의 절반이 손상되어도 안전하게 유지될까요? + + - Manticore와 Echidna는 계약과의 외부 상호작용을 테스트하는 데 최선의 선택입니다. Manticore에는 외부 계약을 스텁하는 내장 메커니즘이 있습니다. + +- **표준 준수.** 이더리움 표준(예: ERC20)은 설계에 결함이 있었던 이력이 있습니다. 구축 기반이 되는 표준의 한계를 인지하고 있어야 합니다. + - Slither, Echidna, Manticore는 주어진 표준에서 벗어나는 것을 탐지하는 데 도움이 될 것입니다. + +### 도구 선택 치트 시트 {#tool-selection-cheatsheet} + +| 구성 요소 | 도구 | 예시 | +| ------- | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 상태 머신 | Echidna, Manticore | | +| 액세스 제어 | Slither, Echidna, Manticore | [Slither 연습 문제 2](https://github.com/crytic/slither/blob/7f54c8b948c34fb35e1d61adaa1bd568ca733253/docs/src/tutorials/exercise2.md), [Echidna 연습 문제 2](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/exercises/Exercise-2.md) | +| 산술 연산 | Manticore, Echidna | [Echidna 연습 문제 1](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/exercises/Exercise-1.md), [Manticore 연습 문제 1 - 3](https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/manticore/exercises) | +| 상속 정확성 | Slither | [Slither 연습 문제 1](https://github.com/crytic/slither/blob/7f54c8b948c34fb35e1d61adaa1bd568ca733253/docs/src/tutorials/exercise1.md) | +| 외부 상호작용 | Manticore, Echidna | | +| 표준 준수 | Slither, Echidna, Manticore | [`slither-erc`](https://github.com/crytic/slither/wiki/ERC-Conformance) | + +목표에 따라 다른 영역도 확인해야 하지만, 이러한 대략적인 집중 영역은 모든 스마트 계약 시스템에 좋은 시작입니다. + +저희의 공개 감사에는 검증되거나 테스트된 속성의 예가 포함되어 있습니다. 실제 보안 속성을 검토하려면 다음 보고서의 `자동화된 테스트 및 검증` 섹션을 읽어보세요. + +- [0x](https://github.com/trailofbits/publications/blob/master/reviews/0x-protocol.pdf) +- [Balancer](https://github.com/trailofbits/publications/blob/master/reviews/BalancerCore.pdf) diff --git a/public/content/translations/ko/developers/tutorials/hello-world-smart-contract-fullstack/index.md b/public/content/translations/ko/developers/tutorials/hello-world-smart-contract-fullstack/index.md new file mode 100644 index 00000000000..bf354600e2c --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/hello-world-smart-contract-fullstack/index.md @@ -0,0 +1,1542 @@ +--- +title: "초보자를 위한 Hello World 스마트 계약 - 풀스택" +description: "이더리움에 간단한 스마트 계약을 작성하고 배포하는 방법에 대한 입문 튜토리얼입니다." +author: "nstrike2" +tags: + [ + "솔리디티", + "hardhat", + "alchemy", + "스마트 계약", + "배포하기", + "블록 탐색기", + "프론트엔드", + "트랜잭션" + ] +skill: beginner +lang: ko +published: 2021-10-25 +--- + +이 가이드는 블록체인 개발을 처음 접하시거나 스마트 계약을 배포하고 상호 작용하는 방법을 모르는 분들을 위한 것입니다. [MetaMask](https://metamask.io), [Solidity](https://docs.soliditylang.org/en/v0.8.0/), [Hardhat](https://hardhat.org), [Alchemy](https://alchemy.com/eth)를 사용하여 Goerli 테스트 네트워크에 간단한 스마트 계약을 생성하고 배포하는 과정을 안내합니다. + +이 튜토리얼을 완료하려면 Alchemy 계정이 필요합니다. [무료 계정으로 가입하세요](https://www.alchemy.com/). + +궁금한 점이 있으면 언제든지 [Alchemy Discord](https://discord.gg/gWuC7zB)에 문의하세요! + +## 1부 - Hardhat을 사용하여 스마트 계약 생성 및 배포하기 {#part-1} + +### 이더리움 네트워크에 연결하기 {#connect-to-the-ethereum-network} + +이더리움 체인에 요청을 보내는 방법은 여러 가지가 있습니다. 간단하게 하기 위해, 자체적으로 노드를 실행하지 않고도 이더리움 체인과 통신할 수 있게 해주는 블록체인 개발자 플랫폼이자 API인 Alchemy의 무료 계정을 사용하겠습니다. Alchemy는 모니터링 및 분석을 위한 개발자 도구도 제공합니다. 이 튜토리얼에서 이러한 도구를 활용하여 스마트 계약 배포 시 내부적으로 어떤 일이 일어나는지 이해해 보겠습니다. + +### 앱과 API 키 만들기 {#create-your-app-and-api-key} + +Alchemy 계정을 생성한 후에는 앱을 만들어 API 키를 생성할 수 있습니다. 이를 통해 Goerli 테스트넷에 요청을 보낼 수 있습니다. 테스트넷에 익숙하지 않은 경우 [네트워크 선택에 대한 Alchemy 가이드](https://www.alchemy.com/docs/choosing-a-web3-network)를 읽어보세요. + +Alchemy 대시보드의 탐색 모음에서 **Apps** 드롭다운을 찾아 Create App을 클릭합니다. + +![Hello world create app](./hello-world-create-app.png) + +앱 이름을 '_Hello World_'로 지정하고 간단한 설명을 작성합니다. 환경으로 Staging을, 네트워크로 Goerli를 선택합니다. + +![create app view hello world](./create-app-view-hello-world.png) + +_참고: Goerli를 반드시 선택해야 합니다. 그렇지 않으면 이 튜토리얼이 작동하지 않습니다._ + +앱 만들기를 클릭하세요. 생성한 앱이 아래 표에 나타납니다. + +### 이더리움 계정 만들기 {#create-an-ethereum-account} + +트랜잭션을 보내고 받으려면 이더리움 계정이 필요합니다. 브라우저에서 이더리움 계정 주소를 관리할 수 있는 가상 지갑인 MetaMask를 사용하겠습니다. + +[여기](https://metamask.io/download)에서 MetaMask 계정을 무료로 다운로드하고 생성할 수 있습니다. 계정을 생성하거나 이미 계정이 있는 경우, 오른쪽 상단에서 'Goerli 테스트 네트워크'로 전환했는지 확인하세요(실제 돈을 다루지 않기 위함입니다). + +### 4단계: 파우셋에서 이더 추가하기 {#step-4-add-ether-from-a-faucet} + +테스트 네트워크에 스마트 계약을 배포하려면 가짜 ETH가 필요합니다. Goerli 네트워크에서 ETH를 받으려면, Goerli 파우셋으로 이동하여 Goerli 계정 주소를 입력하세요. 최근 Goerli 파우셋이 약간 불안정할 수 있습니다. [테스트 네트워크 페이지](/developers/docs/networks/#goerli)에서 시도해 볼 수 있는 옵션 목록을 확인하세요. + +_참고: 네트워크 혼잡으로 인해 시간이 다소 걸릴 수 있습니다._ +`` + +### 5단계: 잔액 확인하기 {#step-5-check-your-balance} + +지갑에 ETH가 있는지 다시 확인하기 위해 [Alchemy의 컴포저 도구](https://composer.alchemyapi.io/?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D)를 사용하여 [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) 요청을 보냅니다. 이것은 지갑에 있는 ETH의 양을 반환할 것입니다. 더 자세한 내용은 [컴포저 도구 사용법에 대한 Alchemy의 짧은 튜토리얼](https://youtu.be/r6sjRxBZJuU)을 확인하세요. + +MetaMask 계정 주소를 입력하고 **요청 보내기**를 클릭하세요. 아래 코드 스니펫과 같은 응답을 보게 될 것입니다. + +```json +{ "jsonrpc": "2.0", "id": 0, "result": "0x2B5E3AF16B1880000" } +``` + +> _참고: 이 결과는 ETH가 아닌 wei 단위입니다. Wei는 ether의 가장 작은 단위로 사용됩니다._ + +휴! 우리의 가짜 돈이 다 있군요. + +### 6단계: 프로젝트 초기화하기 {#step-6-initialize-our-project} + +먼저 프로젝트를 위한 폴더를 만들어야 합니다. 명령줄로 이동하여 다음을 입력하세요. + +``` +mkdir hello-world +cd hello-world +``` + +이제 프로젝트 폴더 안으로 들어왔으니, `npm init`을 사용하여 프로젝트를 초기화하겠습니다. + +> 아직 npm이 설치되지 않았다면 [Node.js 및 npm 설치 지침](https://docs.alchemyapi.io/alchemy/guides/alchemy-for-macs#1-install-nodejs-and-npm)을 따르세요. + +이 튜토리얼에서는 초기화 질문에 어떻게 대답하든 상관없습니다. 참고를 위해 다음과 같이 진행했습니다. + +``` +패키지 이름: (hello-world) +버전: (1.0.0) +설명: hello world 스마트 계약 +진입점: (index.js) +테스트 명령어: +git 저장소: +키워드: +작성자: +라이선스: (ISC) + +/Users/.../.../.../hello-world/package.json에 쓰기 직전: + +{ + "name": "hello-world", + "version": "1.0.0", + "description": "hello world 스마트 계약", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +} +``` + +package.json을 승인하면 준비 완료입니다! + +### 7단계: Hardhat 다운로드하기 {#step-7-download-hardhat} + +Hardhat은 이더리움 소프트웨어를 컴파일, 배포, 테스트 및 디버그하기 위한 개발 환경입니다. 실제 블록체인에 배포하기 전에 로컬에서 스마트 컨트랙트 및 dApp을 구축할 때 사용됩니다. + +`hello-world` 프로젝트 내부에서 다음을 실행하세요: + +``` +npm install --save-dev hardhat +``` + +설치 지침에 대한 자세한 내용은 [이 페이지](https://hardhat.org/getting-started/#overview)를 확인하세요. + +### 8단계: Hardhat 프로젝트 생성하기 {#step-8-create-hardhat-project} + +`hello-world` 프로젝트 폴더 안에서 다음을 실행합니다: + +``` +npx hardhat +``` + +그러면 환영 메시지와 원하는 작업을 선택할 수 있는 옵션이 표시됩니다. "create an empty hardhat.config.js"를 선택합니다. + +``` +888 888 888 888 888 +888 888 888 888 888 +888 888 888 888 888 +8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 +888 888 "88b 888P" d88" 888 888 "88b "88b 888 +888 888 .d888888 888 888 888 888 888 .d888888 888 +888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. +888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 + +👷 Hardhat v2.0.11에 오신 것을 환영합니다 👷‍ + +무엇을 하시겠습니까? … +샘플 프로젝트 생성 +❯ 빈 hardhat.config.js 생성 +종료 +``` + +이렇게 하면 프로젝트에 `hardhat.config.js` 파일이 생성됩니다. 튜토리얼의 뒷부분에서 이 파일을 사용하여 프로젝트 설정을 지정할 것입니다. + +### 9단계: 프로젝트 폴더 추가하기 {#step-9-add-project-folders} + +프로젝트를 체계적으로 정리하기 위해 두 개의 새 폴더를 만들겠습니다. 명령줄에서 `hello-world` 프로젝트의 루트 디렉토리로 이동하여 다음을 입력합니다. + +``` +mkdir contracts +mkdir scripts +``` + +- `contracts/`는 hello world 스마트 계약 코드 파일을 보관할 곳입니다. +- `scripts/`는 계약을 배포하고 상호작용하기 위한 스크립트를 보관할 곳입니다. + +### 10단계: 계약 작성하기 {#step-10-write-our-contract} + +언제 코드를 작성하게 될지 궁금하실 겁니다. 바로 지금입니다! + +선호하는 편집기에서 hello-world 프로젝트를 여세요. 스마트 계약은 대부분 Solidity로 작성되며, 저희도 스마트 계약을 작성하는 데 Solidity를 사용할 것입니다.‌ + +1. `contracts` 폴더로 이동하여 `HelloWorld.sol`이라는 새 파일을 만듭니다. +2. 아래는 이 튜토리얼에서 사용할 샘플 Hello World 스마트 계약입니다. 아래 내용을 `HelloWorld.sol` 파일에 복사하세요. + +_참고: 이 계약이 어떤 역할을 하는지 이해하려면 주석을 꼭 읽어보세요._ + +``` +// 시맨틱 버저닝을 사용하여 Solidity 버전을 지정합니다. +// 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma +pragma solidity >=0.7.3; + +// 'HelloWorld'라는 계약을 정의합니다. +// 계약은 함수와 데이터(그 상태)의 모음입니다. 배포되면, 계약은 이더리움 블록체인의 특정 주소에 위치하게 됩니다. 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html +contract HelloWorld { + + //업데이트 함수가 호출될 때 발생합니다 + //스마트 계약 이벤트는 계약이 블록체인에서 발생한 일을 앱 프론트엔드에 전달하는 방법으로, 특정 이벤트를 '수신'하고 이벤트가 발생할 때 조치를 취할 수 있습니다. + event UpdatedMessages(string oldStr, string newStr); + + // 'string' 타입의 상태 변수 `message`를 선언합니다. + // 상태 변수는 값이 계약 스토리지에 영구적으로 저장되는 변수입니다. `public` 키워드는 변수를 계약 외부에서 액세스할 수 있도록 하고 다른 계약이나 클라이언트가 값을 액세스하기 위해 호출할 수 있는 함수를 생성합니다. + string public message; + + // 많은 클래스 기반 객체 지향 언어와 마찬가지로 생성자는 계약 생성 시에만 실행되는 특수 함수입니다. + // 생성자는 계약의 데이터를 초기화하는 데 사용됩니다. 자세히 알아보기:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors + constructor(string memory initMessage) { + + // 문자열 인수 `initMessage`를 수락하고 계약의 `message` 스토리지 변수에 값을 설정합니다). + message = initMessage; + } + + // 문자열 인수를 허용하고 `message` 스토리지 변수를 업데이트하는 공개 함수입니다. + function update(string memory newMessage) public { + string memory oldMsg = message; + message = newMessage; + emit UpdatedMessages(oldMsg, newMessage); + } +} +``` + +이것은 생성 시 메시지를 저장하는 기본적인 스마트 계약입니다. `update` 함수를 호출하여 업데이트할 수 있습니다. + +### 11단계: MetaMask와 Alchemy를 프로젝트에 연결하기 {#step-11-connect-metamask-alchemy-to-your-project} + +MetaMask 지갑, Alchemy 계정을 만들고 스마트 계약을 작성했습니다. 이제 이 세 가지를 연결할 차례입니다. + +지갑에서 전송되는 모든 트랜잭션은 고유한 개인 키를 사용한 서명이 필요합니다. 프로그램에 이 권한을 제공하기 위해, 개인 키를 환경 파일에 안전하게 저장할 수 있습니다. 여기에 Alchemy용 API 키도 저장할 것입니다. + +> 트랜잭션 전송에 대해 더 알아보려면 web3를 사용한 트랜잭션 전송에 관한 [이 튜토리얼](https://www.alchemy.com/docs/hello-world-smart-contract#step-11-connect-metamask--alchemy-to-your-project)을 확인하세요. + +먼저 프로젝트 디렉터리에 dotenv 패키지를 설치합니다. + +``` +npm install dotenv --save +``` + +그런 다음, 프로젝트의 루트 디렉터리에 `.env` 파일을 생성합니다. 여기에 MetaMask 개인 키와 HTTP Alchemy API URL을 추가합니다. + +환경 파일의 이름은 `.env`여야 합니다. 그렇지 않으면 환경 파일로 인식되지 않습니다. + +`process.env`나 `.env-custom` 또는 다른 이름으로 지정하지 마세요. + +- 개인 키를 내보내려면 [다음 지침](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key)을 따르세요. +- HTTP Alchemy API URL을 얻으려면 아래를 참조하세요. + +![](./get-alchemy-api-key.gif) + +`.env` 파일은 다음과 같아야 합니다: + +``` +API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key" +PRIVATE_KEY = "your-metamask-private-key" +``` + +이를 실제로 코드에 연결하기 위해 13단계의 `hardhat.config.js` 파일에서 이러한 변수를 참조합니다. + +### 12단계: Ethers.js 설치하기 {#step-12-install-ethersjs} + +Ethers.js는 [표준 JSON-RPC 메서드](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc)를 보다 사용자 친화적인 메서드로 래핑하여 이더리움과 더 쉽게 상호 작용하고 요청할 수 있도록 하는 라이브러리입니다. + +Hardhat은 추가적인 툴링 및 확장된 기능을 위해 [플러그인](https://hardhat.org/plugins/)을 통합할 수 있게 해줍니다. 계약 배포를 위해 [Ethers 플러그인](https://hardhat.org/docs/plugins/official-plugins#hardhat-ethers)을 활용할 것입니다. + +프로젝트 디렉토리에 다음을 입력합니다. + +```bash +npm install --save-dev @nomiclabs/hardhat-ethers "ethers@^5.0.0" +``` + +### 13단계: hardhat.config.js 업데이트하기 {#step-13-update-hardhat-configjs} + +지금까지 여러 종속성과 플러그인을 추가했습니다. 이제 프로젝트가 이 모든 것을 인식할 수 있도록 `hardhat.config.js`를 업데이트해야 합니다. + +`hardhat.config.js`를 다음과 같이 업데이트하세요: + +```javascript +/** + * @type import('hardhat/config').HardhatUserConfig + */ + +require("dotenv").config() +require("@nomiclabs/hardhat-ethers") + +const { API_URL, PRIVATE_KEY } = process.env + +module.exports = { + solidity: "0.7.3", + defaultNetwork: "goerli", + networks: { + hardhat: {}, + goerli: { + url: API_URL, + accounts: [`0x${PRIVATE_KEY}`], + }, + }, +} +``` + +### 14단계: 계약 컴파일하기 {#step-14-compile-our-contract} + +지금까지 모든 것이 제대로 작동하는지 확인하기 위해 스마트 컨트랙트를 컴파일해 보겠습니다. `compile` 작업은 hardhat에 내장된 작업 중 하나입니다. + +명령줄에서 다음을 실행합니다. + +```bash +npx hardhat compile +``` + +`SPDX license identifier not provided in source file`에 대한 경고가 표시될 수 있지만 걱정할 필요는 없습니다. 다른 모든 것이 잘 보이기를 바랍니다! 그렇지 않은 경우 언제든지 [Alchemy discord](https://discord.gg/u72VCg3)로 메시지를 보내주세요. + +### 15단계: 배포 스크립트 작성하기 {#step-15-write-our-deploy-script} + +이제 스마트 컨트랙트가 작성되고 설정 파일을 사용할 수 있으므로 스마트 컨트랙트 배포 스크립트를 작성할 차례입니다. + +`scripts/` 폴더로 이동하여 `deploy.js`라는 새 파일을 만들고 다음 내용을 추가하세요. + +```javascript +async function main() { + const HelloWorld = await ethers.getContractFactory("HelloWorld") + + // 배포를 시작하고, 계약 객체로 확인되는 프라미스를 반환합니다 + const hello_world = await HelloWorld.deploy("Hello World!") + console.log("계약이 배포된 주소:", hello_world.address) +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error) + process.exit(1) + }) +``` + +Hardhat은 [계약 튜토리얼](https://hardhat.org/tutorial/testing-contracts.html#writing-tests)에서 각 코드 라인이 무엇을 하는지 훌륭하게 설명하고 있으며, 저희는 그 설명을 여기에 채택했습니다. + +```javascript +const HelloWorld = await ethers.getContractFactory("HelloWorld") +``` + +ethers.js의 `ContractFactory`는 새로운 스마트 계약을 배포하는 데 사용되는 추상화이므로, 여기서 `HelloWorld`는 [팩토리](https://en.wikipedia.org/wiki/Factory_\(object-oriented_programming\)) 계약 인스턴스를 위한 팩토리입니다. `hardhat-ethers` 플러그인을 사용할 때 `ContractFactory` 및 `Contract` 인스턴스는 기본적으로 첫 번째 서명자(소유자)에게 연결됩니다. + +```javascript +const hello_world = await HelloWorld.deploy() +``` + +`ContractFactory`에서 `deploy()`를 호출하면 배포가 시작되고, `Contract` 객체로 확인되는 `Promise`를 반환합니다. 이것은 각 스마트 컨트랙트 기능에 대한 메소드가 있는 개체입니다. + +### 16단계: 계약 배포하기 {#step-16-deploy-our-contract} + +마침내 스마트 컨트랙트를 배포할 준비가 되었습니다! 명령줄로 이동하여 다음을 실행하세요: + +```bash +npx hardhat run scripts/deploy.js --network goerli +``` + +그러면 다음과 같은 내용이 표시됩니다. + +```bash +계약이 배포된 주소: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570 +``` + +**이 주소를 저장해주세요**. 튜토리얼 뒷부분에서 사용할 것입니다. + +[Goerli Etherscan](https://goerli.etherscan.io)으로 이동하여 계약 주소를 검색하면 성공적으로 배포된 것을 볼 수 있습니다. 트랜잭션은 다음과 같습니다. + +![](./etherscan-contract.png) + +`From` 주소는 MetaMask 계정 주소와 일치해야 하며, `To` 주소는 **계약 생성**이라고 표시됩니다. 트랜잭션을 클릭하면 `To` 필드에 계약 주소가 표시됩니다. + +![](./etherscan-transaction.png) + +축하해요! 방금 이더리움 테스트넷에 스마트 계약을 배포했습니다. + +내부적으로 어떤 일이 일어나고 있는지 이해하기 위해 [Alchemy 대시보드](https://dashboard.alchemy.com/explorer)의 Explorer 탭으로 이동해 보겠습니다. 여러 개의 Alchemy 앱이 있는 경우 앱별로 필터링하고 **Hello World**를 선택해야 합니다. + +![](./hello-world-explorer.png) + +여기에서 `.deploy()` 함수를 호출했을 때 Hardhat/Ethers가 내부적으로 수행한 몇 가지 JSON-RPC 메서드를 볼 수 있습니다. 여기서 중요한 두 가지 메서드는 계약을 Goerli 체인에 작성하는 요청인 [`eth_sendRawTransaction`](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_sendrawtransaction)과, 해시가 주어졌을 때 트랜잭션에 대한 정보를 읽는 요청인 [`eth_getTransactionByHash`](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_gettransactionbyhash)입니다. 트랜잭션 전송에 대해 더 자세히 알아보려면 [Web3를 사용한 트랜잭션 전송 튜토리얼](/developers/tutorials/sending-transactions-using-web3-and-alchemy/)을 확인하세요. + +## 2부: 스마트 계약과 상호작용하기 {#part-2-interact-with-your-smart-contract} + +이제 Goerli 네트워크에 스마트 계약을 성공적으로 배포했으니, 이와 상호 작용하는 방법을 알아보겠습니다. + +### interact.js 파일 생성하기 {#create-a-interactjs-file} + +이 파일은 상호 작용 스크립트를 작성할 파일입니다. 1부에서 이전에 설치한 Ethers.js 라이브러리를 사용할 것입니다. + +`scripts/` 폴더 안에 `interact.js`라는 새 파일을 만들고 다음 코드를 추가합니다. + +```javascript +// interact.js + +const API_KEY = process.env.API_KEY +const PRIVATE_KEY = process.env.PRIVATE_KEY +const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS +``` + +### .env 파일 업데이트하기 {#update-your-env-file} + +새로운 환경 변수를 사용할 것이므로 [이전에 생성한](#step-11-connect-metamask-&-alchemy-to-your-project) `.env` 파일에 정의해야 합니다. + +Alchemy `API_KEY`와 스마트 계약이 배포된 `CONTRACT_ADDRESS`에 대한 정의를 추가해야 합니다. + +`.env` 파일은 다음과 같아야 합니다. + +```bash +# .env + +API_URL = "https://eth-goerli.alchemyapi.io/v2/" +API_KEY = "" +PRIVATE_KEY = "" +CONTRACT_ADDRESS = "0x" +``` + +### 계약 ABI 가져오기 {#grab-your-contract-ABI} + +계약 [ABI(애플리케이션 바이너리 인터페이스)](/glossary/#abi)는 스마트 계약과 상호 작용하기 위한 인터페이스입니다. Hardhat은 자동으로 ABI를 생성하여 `HelloWorld.json`에 저장합니다. ABI를 사용하려면 `interact.js` 파일에 다음 코드 줄을 추가하여 내용을 구문 분석해야 합니다. + +```javascript +// interact.js +const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json") +``` + +ABI를 보려면 콘솔에 출력할 수 있습니다. + +```javascript +console.log(JSON.stringify(contract.abi)) +``` + +ABI가 콘솔에 출력되는 것을 보려면 터미널로 이동하여 다음을 실행하세요. + +```bash +npx hardhat run scripts/interact.js +``` + +### 계약 인스턴스 생성하기 {#create-an-instance-of-your-contract} + +계약과 상호 작용하려면 코드에서 계약 인스턴스를 생성해야 합니다. Ethers.js로 이를 수행하려면 세 가지 개념을 다루어야 합니다. + +1. 제공자 - 블록체인에 대한 읽기 및 쓰기 접근 권한을 제공하는 노드 제공자 +2. 서명자 - 트랜잭션에 서명할 수 있는 이더리움 계정을 나타냅니다 +3. 계약 - 온체인에 배포된 특정 계약을 나타내는 Ethers.js 객체 + +이전 단계의 계약 ABI를 사용하여 계약 인스턴스를 생성합니다. + +```javascript +// interact.js + +// 제공자 +const alchemyProvider = new ethers.providers.AlchemyProvider( + (network = "goerli"), + API_KEY +) + +// 서명자 +const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider) + +// 계약 +const helloWorldContract = new ethers.Contract( + CONTRACT_ADDRESS, + contract.abi, + signer +) +``` + +제공자, 서명자, 계약에 대한 자세한 내용은 [ethers.js 개발문서](https://docs.ethers.io/v5/)에서 알아보세요. + +### 초기 메시지 읽기 {#read-the-init-message} + +`initMessage = "Hello world!"`로 계약을 배포했던 것을 기억하시나요? 이제 스마트 계약에 저장된 메시지를 읽어 콘솔에 출력할 것입니다. + +JavaScript에서는 네트워크와 상호 작용할 때 비동기 함수가 사용됩니다. 비동기 함수에 대해 더 알아보려면 [이 미디엄 기사](https://blog.bitsrc.io/understanding-asynchronous-javascript-the-event-loop-74cd408419ff)를 읽어보세요. + +아래 코드를 사용하여 스마트 계약에서 `message` 함수를 호출하고 초기 메시지를 읽으세요. + +```javascript +// interact.js + +// ... + +async function main() { + const message = await helloWorldContract.message() + console.log("메시지는: " + message) +} +main() +``` + +터미널에서 `npx hardhat run scripts/interact.js`를 사용하여 파일을 실행한 후 다음과 같은 응답을 볼 수 있어야 합니다. + +``` +메시지는: Hello world! +``` + +축하해요! 이더리움 블록체인에서 스마트 계약 데이터를 성공적으로 읽었습니다. 잘하셨습니다! + +### 메시지 업데이트하기 {#update-the-message} + +단순히 메시지를 읽는 대신, `update` 함수를 사용하여 스마트 계약에 저장된 메시지를 업데이트할 수도 있습니다! 꽤 멋지죠? + +메시지를 업데이트하려면 인스턴스화된 계약 객체에서 `update` 함수를 직접 호출할 수 있습니다. + +```javascript +// interact.js + +// ... + +async function main() { + const message = await helloWorldContract.message() + console.log("메시지는: " + message) + + console.log("메시지 업데이트 중...") + const tx = await helloWorldContract.update("This is the new message.") + await tx.wait() +} +main() +``` + +11번째 줄에서 반환된 트랜잭션 객체에 대해 `.wait()`를 호출하는 것을 주목하세요. 이를 통해 스크립트가 함수를 종료하기 전에 트랜잭션이 블록체인에서 채굴될 때까지 기다리게 됩니다. `.wait()` 호출이 포함되지 않으면 스크립트가 계약에서 업데이트된 `message` 값을 보지 못할 수 있습니다. + +### 새 메시지 읽기 {#read-the-new-message} + +[이전 단계](#read-the-init-message)를 반복하여 업데이트된 `message` 값을 읽을 수 있어야 합니다. 잠시 시간을 내어 새 값을 출력하는 데 필요한 변경 사항을 적용해 보세요! + +힌트가 필요하다면, 이 시점에서 `interact.js` 파일은 다음과 같아야 합니다. + +```javascript +// interact.js + +const API_KEY = process.env.API_KEY +const PRIVATE_KEY = process.env.PRIVATE_KEY +const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS + +const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json") + +// 제공자 - Alchemy +const alchemyProvider = new ethers.providers.AlchemyProvider( + (network = "goerli"), + API_KEY +) + +// 서명자 - 당신 +const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider) + +// 계약 인스턴스 +const helloWorldContract = new ethers.Contract( + CONTRACT_ADDRESS, + contract.abi, + signer +) + +async function main() { + const message = await helloWorldContract.message() + console.log("메시지는: " + message) + + console.log("메시지 업데이트 중...") + const tx = await helloWorldContract.update("this is the new message") + await tx.wait() + + const newMessage = await helloWorldContract.message() + console.log("새 메시지는: " + newMessage) +} + +main() +``` + +이제 스크립트를 실행하면 이전 메시지, 업데이트 상태, 그리고 새 메시지가 터미널에 출력되는 것을 볼 수 있습니다! + +`npx hardhat run scripts/interact.js --network goerli` + +``` +메시지: Hello World! +메시지 업데이트 중... +새 메시지: This is the new message. +``` + +스크립트를 실행하는 동안, 새 메시지가 로드되기 전에 `메시지 업데이트 중...` 단계가 로드되는 데 시간이 걸리는 것을 알 수 있습니다. 이는 채굴 과정 때문입니다. 채굴 중인 트랜잭션을 추적하는 데 관심이 있다면 [Alchemy 멤풀](https://dashboard.alchemyapi.io/mempool)을 방문하여 트랜잭션 상태를 확인하세요. 트랜잭션이 중단된 경우, [Goerli Etherscan](https://goerli.etherscan.io)을 확인하고 트랜잭션 해시를 검색하는 것도 도움이 됩니다. + +## 3부: Etherscan에 스마트 계약 게시하기 {#part-3-publish-your-smart-contract-to-etherscan} + +스마트 계약을 현실로 만드는 힘든 작업을 모두 마쳤습니다. 이제 세상과 공유할 시간입니다! + +Etherscan에서 스마트 계약을 확인하면 누구나 소스 코드를 보고 스마트 계약과 상호 작용할 수 있습니다. 시작해 보겠습니다! + +### 1단계: Etherscan 계정에서 API 키 생성하기 {#step-1-generate-an-api-key-on-your-etherscan-account} + +게시하려는 스마트 계약을 소유하고 있음을 확인하려면 Etherscan API 키가 필요합니다. + +아직 Etherscan 계정이 없다면 [계정을 등록하세요](https://etherscan.io/register). + +로그인한 후 탐색 모음에서 사용자 이름을 찾아 마우스를 올리고 **내 프로필** 버튼을 선택합니다. + +프로필 페이지에 측면 탐색 모음이 표시됩니다. 측면 탐색 모음에서 **API 키**를 선택합니다. 다음으로 '추가' 버튼을 눌러 새 API 키를 만들고, 앱 이름을 **hello-world**로 지정한 다음 **새 API 키 만들기** 버튼을 누릅니다. + +새로운 API 키가 API 키 표에 나타납니다. API 키를 클립보드에 복사합니다. + +다음으로 Etherscan API 키를 `.env` 파일에 추가해야 합니다. + +추가한 후 `.env` 파일은 다음과 같아야 합니다. + +```javascript +API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key" +PUBLIC_KEY = "your-public-account-address" +PRIVATE_KEY = "your-private-account-address" +CONTRACT_ADDRESS = "your-contract-address" +ETHERSCAN_API_KEY = "your-etherscan-key" +``` + +### Hardhat 배포 스마트 계약 {#hardhat-deployed-smart-contracts} + +#### hardhat-etherscan 설치하기 {#install-hardhat-etherscan} + +Hardhat을 사용하여 Etherscan에 계약을 게시하는 것은 간단합니다. 시작하려면 먼저 `hardhat-etherscan` 플러그인을 설치해야 합니다. `hardhat-etherscan`은 Etherscan에서 스마트 계약의 소스 코드와 ABI를 자동으로 확인합니다. 이를 추가하려면 `hello-world` 디렉터리에서 다음을 실행합니다. + +```text +npm install --save-dev @nomiclabs/hardhat-etherscan +``` + +설치되면 `hardhat.config.js` 상단에 다음 문을 포함하고 Etherscan 구성 옵션을 추가합니다. + +```javascript +// hardhat.config.js + +require("dotenv").config() +require("@nomiclabs/hardhat-ethers") +require("@nomiclabs/hardhat-etherscan") + +const { API_URL, PRIVATE_KEY, ETHERSCAN_API_KEY } = process.env + +module.exports = { + solidity: "0.7.3", + defaultNetwork: "goerli", + networks: { + hardhat: {}, + goerli: { + url: API_URL, + accounts: [`0x${PRIVATE_KEY}`], + }, + }, + etherscan: { + // Etherscan용 API 키 + // https://etherscan.io/에서 하나를 얻으십시오. + apiKey: ETHERSCAN_API_KEY, + }, +} +``` + +#### Etherscan에서 스마트 계약 확인하기 {#verify-your-smart-contract-on-etherscan} + +모든 파일이 저장되고 모든 `.env` 변수가 올바르게 구성되었는지 확인하세요. + +`verify` 작업을 실행하여 계약 주소와 배포된 네트워크를 전달합니다. + +```text +npx hardhat verify --network goerli DEPLOYED_CONTRACT_ADDRESS 'Hello World!' +``` + +`DEPLOYED_CONTRACT_ADDRESS`가 Goerli 테스트 네트워크에 배포된 스마트 계약의 주소인지 확인하세요. 또한 마지막 인수(`'Hello World!'`)는 [1부의 배포 단계](#write-our-deploy-script)에서 사용한 문자열 값과 동일해야 합니다. + +모든 것이 순조롭게 진행되면 터미널에 다음 메시지가 표시됩니다. + +```text +계약 소스 코드가 성공적으로 제출되었습니다 +contracts/HelloWorld.sol:HelloWorld at 0xdeployed-contract-address +Etherscan에서 확인을 위해 대기 중... 확인 결과를 기다리는 중... + + +Etherscan에서 HelloWorld 계약을 성공적으로 확인했습니다. +https://goerli.etherscan.io/address/#contracts +``` + +축하해요! 스마트 계약 코드가 Etherscan에 있습니다! + +### Etherscan에서 스마트 계약을 확인하세요! {#check-out-your-smart-contract-on-etherscan} + +터미널에 제공된 링크로 이동하면 Etherscan에 게시된 스마트 계약 코드와 ABI를 볼 수 있습니다! + +**와우, 해내셨군요!** 이제 누구나 당신의 스마트 계약을 호출하거나 쓸 수 있습니다! **다음에 무엇을 만들지 기대됩니다!** + +## 4부 - 스마트 계약을 프런트엔드와 통합하기 {#part-4-integrating-your-smart-contract-with-the-frontend} + +이 튜토리얼을 마치면 다음을 알게 될 것입니다. + +- MetaMask 지갑을 탈중앙화앱에 연결 +- [Alchemy Web3](https://docs.alchemy.com/alchemy/documentation/alchemy-web3) API를 사용하여 스마트 계약에서 데이터 읽기 +- MetaMask를 사용하여 이더리움 트랜잭션 서명하기 + +이 탈중앙화앱에서는 프런트엔드 프레임워크로 [React](https://react.dev/)를 사용할 것입니다. 하지만 저희는 주로 프로젝트에 웹3 기능을 도입하는 데 중점을 둘 것이므로 React의 기초를 자세히 다루지는 않을 것입니다. + +전제 조건으로 React에 대한 초급 수준의 이해가 있어야 합니다. 그렇지 않은 경우 공식 [React 소개 튜토리얼](https://react.dev/learn)을 완료하는 것이 좋습니다. + +### 스타터 파일 복제하기 {#clone-the-starter-files} + +먼저 [hello-world-part-four GitHub 저장소](https://github.com/alchemyplatform/hello-world-part-four-tutorial)로 이동하여 이 프로젝트의 시작 파일을 가져오고 이 저장소를 로컬 컴퓨터에 복제합니다. + +복제된 저장소를 로컬에서 엽니다. 두 개의 폴더, 즉 `starter-files`와 `completed`가 포함되어 있음을 알 수 있습니다. + +- `starter-files` - **이 디렉토리에서 작업할 것입니다**. UI를 이더리움 지갑과 [3부](#part-3)에서 Etherscan에 게시한 스마트 계약에 연결할 것입니다. +- `completed`는 전체 튜토리얼을 포함하며 막혔을 경우에만 참고용으로 사용해야 합니다. + +다음으로, `starter-files` 사본을 즐겨 사용하는 코드 편집기에서 열고 `src` 폴더로 이동합니다. + +우리가 작성할 모든 코드는 `src` 폴더 아래에 위치하게 됩니다. 프로젝트에 웹3 기능을 부여하기 위해 `HelloWorld.js` 구성 요소와 `util/interact.js` JavaScript 파일을 편집할 것입니다. + +### 시작 파일 확인하기 {#check-out-the-starter-files} + +코딩을 시작하기 전에 시작 파일에 무엇이 제공되는지 살펴보겠습니다. + +#### React 프로젝트 실행하기 {#get-your-react-project-running} + +먼저 브라우저에서 React 프로젝트를 실행해 봅시다. React의 장점은 일단 브라우저에서 프로젝트가 실행되면, 저장하는 모든 변경 사항이 브라우저에 실시간으로 업데이트된다는 것입니다. + +프로젝트를 실행하려면 `starter-files` 폴더의 루트 디렉터리로 이동하고 터미널에서 `npm install`을 실행하여 프로젝트의 종속성을 설치합니다. + +```bash +cd starter-files +npm install +``` + +설치가 완료되면 터미널에서 `npm start`를 실행합니다: + +```bash +npm start +``` + +이렇게 하면 브라우저에서 [http://localhost:3000/](http://localhost:3000/)이 열리고 프로젝트의 프런트엔드가 표시됩니다. 하나의 필드(스마트 계약에 저장된 메시지를 업데이트하는 곳), "지갑 연결" 버튼, "업데이트" 버튼으로 구성되어야 합니다. + +두 버튼 중 하나를 클릭해 보면 작동하지 않는 것을 알 수 있습니다. 아직 해당 기능을 프로그래밍해야 하기 때문입니다. + +#### `HelloWorld.js` 구성 요소 {#the-helloworld-js-component} + +편집기에서 `src` 폴더로 다시 돌아가 `HelloWorld.js` 파일을 엽니다. 이 파일은 우리가 작업할 기본 React 컴포넌트이므로 파일의 모든 내용을 이해하는 것이 매우 중요합니다. + +이 파일의 맨 위에는 React 라이브러리, useEffect 및 useState 후크, `./util/interact.js`의 일부 항목(곧 자세히 설명하겠습니다!), 그리고 Alchemy 로고를 포함하여 프로젝트를 실행하는 데 필요한 여러 가져오기 문이 있습니다. + +```javascript +// HelloWorld.js + +import React from "react" +import { useEffect, useState } from "react" +import { + helloWorldContract, + connectWallet, + updateMessage, + loadCurrentMessage, + getCurrentWalletConnected, +} from "./util/interact.js" + +import alchemylogo from "./alchemylogo.svg" +``` + +다음으로, 특정 이벤트 후에 업데이트할 상태 변수가 있습니다. + +```javascript +// HelloWorld.js + +//상태 변수 +const [walletAddress, setWallet] = useState("") +const [status, setStatus] = useState("") +const [message, setMessage] = useState("네트워크에 연결되지 않았습니다.") +const [newMessage, setNewMessage] = useState("") +``` + +각 변수가 나타내는 내용은 다음과 같습니다. + +- `walletAddress` - 사용자의 지갑 주소를 저장하는 문자열 +- `status`- 사용자가 탈중앙화앱과 상호 작용하는 방법을 안내하는 유용한 메시지를 저장하는 문자열 +- `message` - 스마트 계약의 현재 메시지를 저장하는 문자열 +- `newMessage` - 스마트 계약에 작성될 새 메시지를 저장하는 문자열 + +상태 변수 다음에는 아직 구현되지 않은 다섯 개의 함수가 보입니다: `useEffect`, `addSmartContractListener`, `addWalletListener`, `connectWalletPressed`, `onUpdatePressed`. 각 함수의 역할은 다음과 같습니다. + +```javascript +// HelloWorld.js + +//한 번만 호출됨 +useEffect(async () => { + //TODO: 구현 +}, []) + +function addSmartContractListener() { + //TODO: 구현 +} + +function addWalletListener() { + //TODO: 구현 +} + +const connectWalletPressed = async () => { + //TODO: 구현 +} + +const onUpdatePressed = async () => { + //TODO: 구현 +} +``` + +- [`useEffect`](https://legacy.reactjs.org/docs/hooks-effect.html) - 컴포넌트가 렌더링된 후 호출되는 React 후크입니다. 빈 배열 `[]` 속성이 전달되었기 때문에(4번째 줄 참조), 컴포넌트의 _첫 번째_ 렌더링에서만 호출됩니다. 여기에서는 스마트 계약에 저장된 현재 메시지를 로드하고, 스마트 계약 및 지갑 리스너를 호출하며, 지갑이 이미 연결되었는지 여부를 반영하도록 UI를 업데이트합니다. +- `addSmartContractListener` - 이 함수는 HelloWorld 계약의 `UpdatedMessages` 이벤트를 감시하고 스마트 계약의 메시지가 변경될 때 UI를 업데이트하는 리스너를 설정합니다. +- `addWalletListener` - 이 함수는 사용자가 지갑을 연결 해제하거나 주소를 전환하는 등 사용자의 MetaMask 지갑 상태 변경을 감지하는 리스너를 설정합니다. +- `connectWalletPressed` - 이 함수는 사용자의 MetaMask 지갑을 탈중앙화앱에 연결할 때 호출됩니다. +- `onUpdatePressed` - 이 함수는 사용자가 스마트 계약에 저장된 메시지를 업데이트하고 싶을 때 호출됩니다. + +이 파일의 끝부분에는 컴포넌트의 UI가 있습니다. + +```javascript +// HelloWorld.js + +//컴포넌트의 UI +return ( +
+ + + +

현재 메시지:

+

{message}

+ +

새 메시지:

+ +
+ setNewMessage(e.target.value)} + value={newMessage} + /> +

{status}

+ + +
+ +
+) +``` + +이 코드를 자세히 살펴보면 UI에서 다양한 상태 변수를 사용하는 위치를 알 수 있습니다. + +- 6-12줄에서 사용자의 지갑이 연결된 경우(즉, `walletAddress.length > 0`), ID가 "walletButton"인 버튼에 사용자의 `walletAddress`의 축약된 버전을 표시하고, 그렇지 않으면 "지갑 연결"이라고만 표시합니다. +- 17번 줄에는 `message` 문자열에 캡처된 스마트 계약에 저장된 현재 메시지를 표시합니다. +- 23-26줄에서는 [제어된 컴포넌트](https://legacy.reactjs.org/docs/forms.html#controlled-components)를 사용하여 텍스트 필드의 입력이 변경될 때 `newMessage` 상태 변수를 업데이트합니다. + +상태 변수 외에도 `publishButton` 및 `walletButton` ID를 가진 버튼을 각각 클릭하면 `connectWalletPressed` 및 `onUpdatePressed` 함수가 호출되는 것을 볼 수 있습니다. + +마지막으로, 이 `HelloWorld.js` 컴포넌트가 어디에 추가되는지 알아보겠습니다. + +React의 메인 컴포넌트로 다른 모든 컴포넌트의 컨테이너 역할을 하는 `App.js` 파일로 이동하면, 7번째 줄에 `HelloWorld.js` 컴포넌트가 주입된 것을 볼 수 있습니다. + +마지막으로, 제공된 또 다른 파일인 `interact.js` 파일을 확인해 보겠습니다. + +#### `interact.js` 파일 {#the-interact-js-file} + +[M-V-C](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) 패러다임을 따르기 위해, 탈중앙화앱의 로직, 데이터, 규칙을 관리하는 모든 함수를 포함하는 별도의 파일을 원할 것입니다. 그리고 이 함수들을 프런트엔드(`HelloWorld.js` 컴포넌트)로 내보낼 수 있어야 합니다. + +👆🏽이것이 바로 `interact.js` 파일의 정확한 목적입니다! + +`src` 디렉터리의 `util` 폴더로 이동하면, 모든 스마트 계약 상호 작용 및 지갑 함수와 변수를 포함할 `interact.js`라는 파일이 포함된 것을 볼 수 있습니다. + +```javascript +// interact.js + +//export const helloWorldContract; + +export const loadCurrentMessage = async () => {} + +export const connectWallet = async () => {} + +const getCurrentWalletConnected = async () => {} + +export const updateMessage = async (message) => {} +``` + +파일 상단에서 `helloWorldContract` 객체가 주석 처리된 것을 볼 수 있습니다. 이 튜토리얼의 뒷부분에서 이 객체의 주석을 해제하고 이 변수에 스마트 계약을 인스턴스화한 다음, `HelloWorld.js` 컴포넌트로 내보낼 것입니다. + +`helloWorldContract` 객체 뒤에 있는 네 개의 미구현 함수는 다음을 수행합니다. + +- `loadCurrentMessage` - 이 함수는 스마트 계약에 저장된 현재 메시지를 로드하는 로직을 처리합니다. [Alchemy Web3 API](https://github.com/alchemyplatform/alchemy-web3)를 사용하여 Hello World 스마트 계약에 _읽기_ 호출을 합니다. +- `connectWallet` - 이 함수는 사용자의 MetaMask를 탈중앙화앱에 연결합니다. +- `getCurrentWalletConnected` - 이 함수는 페이지 로드 시 이더리움 계정이 이미 탈중앙화앱에 연결되어 있는지 확인하고 그에 따라 UI를 업데이트합니다. +- `updateMessage` - 이 함수는 스마트 계약에 저장된 메시지를 업데이트합니다. Hello World 스마트 계약에 _쓰기_ 호출을 하므로, 사용자의 MetaMask 지갑은 메시지를 업데이트하기 위해 이더리움 트랜잭션에 서명해야 합니다. + +이제 무엇을 다루고 있는지 이해했으니, 스마트 계약에서 어떻게 읽어오는지 알아봅시다! + +### 3단계: 스마트 계약에서 데이터 읽기 {#step-3-read-from-your-smart-contract} + +스마트 계약에서 읽으려면 다음을 성공적으로 설정해야 합니다. + +- 이더리움 체인에 대한 API 연결 +- 로드된 스마트 계약 인스턴스 +- 스마트 계약 함수를 호출하는 함수 +- 스마트 계약에서 읽고 있는 데이터가 변경될 때 업데이트를 감시하는 리스너 + +많은 단계처럼 들릴 수 있지만, 걱정하지 마세요! 각 단계를 하나씩 안내해 드리겠습니다! :\) + +#### 이더리움 체인에 API 연결 설정하기 {#establish-an-api-connection-to-the-ethereum-chain} + +이 튜토리얼 2부에서 [Alchemy Web3 키를 사용하여 스마트 계약에서 읽어왔던](https://docs.alchemy.com/alchemy/tutorials/hello-world-smart-contract/interacting-with-a-smart-contract#step-1-install-web3-library) 것을 기억하시나요? 체인에서 읽기 위해 탈중앙화앱에서도 Alchemy 웹3 키가 필요합니다. + +아직 설치하지 않았다면, `starter-files`의 루트 디렉터리로 이동하여 터미널에서 다음을 실행하여 [Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3)를 설치하세요. + +```text +npm install @alch/alchemy-web3 +``` + +[Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3)는 [Web3.js](https://docs.web3js.org/)의 래퍼로, 향상된 API 메서드와 기타 중요한 이점을 제공하여 웹3 개발자로서의 삶을 더 쉽게 만듭니다. 최소한의 구성만으로 바로 앱에서 사용할 수 있도록 설계되었습니다! + +그런 다음 프로젝트 디렉터리에 [dotenv](https://www.npmjs.com/package/dotenv) 패키지를 설치하여 가져온 후 API 키를 안전하게 보관할 수 있도록 합니다. + +```text +npm install dotenv --save +``` + +탈중앙화앱에서는 HTTP API 키 대신 **웹소켓 API 키를 사용할 것**입니다. 이를 통해 스마트 계약에 저장된 메시지가 변경될 때 감지하는 리스너를 설정할 수 있습니다. + +API 키를 받으면 루트 디렉터리에 `.env` 파일을 만들고 Alchemy 웹소켓 URL을 추가하세요. 그 후 `.env` 파일은 다음과 같이 보일 것입니다. + +```javascript +REACT_APP_ALCHEMY_KEY = wss://eth-goerli.ws.alchemyapi.io/v2/ +``` + +이제 탈중앙화앱에서 Alchemy 웹3 엔드포인트를 설정할 준비가 되었습니다! 이제 `util` 폴더 안에 있는 `interact.js`로 돌아가서 파일 상단에 다음 코드를 추가합니다. + +```javascript +// interact.js + +require("dotenv").config() +const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY +const { createAlchemyWeb3 } = require("@alch/alchemy-web3") +const web3 = createAlchemyWeb3(alchemyKey) + +//export const helloWorldContract; +``` + +위에서는 먼저 `.env` 파일에서 Alchemy 키를 가져온 다음 `alchemyKey`를 `createAlchemyWeb3`에 전달하여 Alchemy 웹3 엔드포인트를 설정했습니다. + +이 엔드포인트가 준비되었으니, 이제 스마트 계약을 로드할 시간입니다! + +#### Hello World 스마트 계약 로드하기 {#loading-your-hello-world-smart-contract} + +Hello World 스마트 계약을 로드하려면 계약 주소와 ABI가 필요하며, [이 튜토리얼 3부](/developers/tutorials/hello-world-smart-contract-fullstack/#part-3-publish-your-smart-contract-to-etherscan-part-3-publish-your-smart-contract-to-etherscan)를 완료했다면 두 가지 모두 Etherscan에서 찾을 수 있습니다. + +#### Etherscan에서 계약 ABI를 가져오는 방법 {#how-to-get-your-contract-abi-from-etherscan} + +이 튜토리얼의 3부를 건너뛰었다면 [0x6f3f635A9762B47954229Ea479b4541eAF402A6A](https://goerli.etherscan.io/address/0x6f3f635a9762b47954229ea479b4541eaf402a6a#code) 주소의 HelloWorld 계약을 사용할 수 있습니다. ABI는 [여기](https://goerli.etherscan.io/address/0x6f3f635a9762b47954229ea479b4541eaf402a6a#code)에서 찾을 수 있습니다. + +계약 ABI는 계약이 어떤 함수를 호출할지 지정하고, 함수가 예상하는 형식으로 데이터를 반환하도록 보장하는 데 필요합니다. 계약 ABI를 복사한 후, `src` 디렉터리에 `contract-abi.json`이라는 JSON 파일로 저장합니다. + +contract-abi.json은 src 폴더에 저장되어야 합니다. + +계약 주소, ABI, Alchemy 웹3 엔드포인트를 사용하여 [contract 메서드](https://docs.web3js.org/api/web3-eth-contract/class/Contract)를 통해 스마트 계약 인스턴스를 로드할 수 있습니다. `interact.js` 파일에 계약 ABI를 가져오고 계약 주소를 추가합니다. + +```javascript +// interact.js + +const contractABI = require("../contract-abi.json") +const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A" +``` + +이제 드디어 `helloWorldContract` 변수의 주석을 해제하고 AlchemyWeb3 엔드포인트를 사용하여 스마트 계약을 로드할 수 있습니다. + +```javascript +// interact.js +export const helloWorldContract = new web3.eth.Contract( + contractABI, + contractAddress +) +``` + +요약하자면, `interact.js`의 첫 12줄은 이제 다음과 같아야 합니다. + +```javascript +// interact.js + +require("dotenv").config() +const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY +const { createAlchemyWeb3 } = require("@alch/alchemy-web3") +const web3 = createAlchemyWeb3(alchemyKey) + +const contractABI = require("../contract-abi.json") +const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A" + +export const helloWorldContract = new web3.eth.Contract( + contractABI, + contractAddress +) +``` + +이제 계약이 로드되었으니 `loadCurrentMessage` 함수를 구현할 수 있습니다! + +#### `interact.js` 파일에 `loadCurrentMessage` 구현하기 {#implementing-loadCurrentMessage-in-your-interact-js-file} + +이 함수는 매우 간단합니다. 간단한 비동기 웹3 호출을 하여 계약에서 읽어올 것입니다. 함수는 스마트 계약에 저장된 메시지를 반환합니다. + +`interact.js` 파일의 `loadCurrentMessage`를 다음과 같이 업데이트합니다. + +```javascript +// interact.js + +export const loadCurrentMessage = async () => { + const message = await helloWorldContract.methods.message().call() + return message +} +``` + +이 스마트 계약을 UI에 표시하고 싶으므로, `HelloWorld.js` 컴포넌트의 `useEffect` 함수를 다음과 같이 업데이트합시다. + +```javascript +// HelloWorld.js + +//한 번만 호출됨 +useEffect(async () => { + const message = await loadCurrentMessage() + setMessage(message) +}, []) +``` + +컴포넌트의 첫 번째 렌더링 중에 `loadCurrentMessage`가 한 번만 호출되기를 원합니다. 곧 `addSmartContractListener`를 구현하여 스마트 계약의 메시지가 변경된 후 UI를 자동으로 업데이트할 것입니다. + +리스너에 대해 자세히 알아보기 전에, 지금까지의 결과를 확인해 봅시다! `HelloWorld.js`와 `interact.js` 파일을 저장한 다음 [http://localhost:3000/](http://localhost:3000/)으로 이동하세요. + +현재 메시지가 더 이상 "네트워크에 연결되지 않았습니다."라고 표시되지 않는 것을 볼 수 있습니다. 대신 스마트 계약에 저장된 메시지를 반영합니다. 멋져요! + +#### 이제 UI가 스마트 계약에 저장된 메시지를 반영해야 합니다. {#your-UI-should-now-reflect-the-message-stored-in-the-smart-contract} + +이제 그 리스너에 대해 이야기해 봅시다... + +#### `addSmartContractListener` 구현하기 {#implement-addsmartcontractlistener} + +[이 튜토리얼 시리즈의 1부](https://docs.alchemy.com/alchemy/tutorials/hello-world-smart-contract#step-10-write-our-contract)에서 작성한 `HelloWorld.sol` 파일을 다시 생각해 보면, 스마트 계약의 `update` 함수가 호출된 후 `UpdatedMessages`라는 스마트 계약 이벤트가 발생한다는 것을 기억할 것입니다(9번과 27번 줄 참조). + +```javascript +// HelloWorld.sol + +// 시맨틱 버저닝을 사용하여 Solidity 버전을 지정합니다. +// 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma +pragma solidity ^0.7.3; + +// 'HelloWorld'라는 계약을 정의합니다. +// 계약은 함수와 데이터(그 상태)의 모음입니다. 배포되면, 계약은 이더리움 블록체인의 특정 주소에 위치하게 됩니다. 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html +contract HelloWorld { + + //업데이트 함수가 호출될 때 발생합니다 + //스마트 계약 이벤트는 계약이 블록체인에서 발생한 일을 앱 프론트엔드에 전달하는 방법으로, 특정 이벤트를 '수신'하고 이벤트가 발생할 때 조치를 취할 수 있습니다. + event UpdatedMessages(string oldStr, string newStr); + + // 'string' 타입의 상태 변수 `message`를 선언합니다. + // 상태 변수는 값이 계약 스토리지에 영구적으로 저장되는 변수입니다. `public` 키워드는 변수를 계약 외부에서 액세스할 수 있도록 하고 다른 계약이나 클라이언트가 값을 액세스하기 위해 호출할 수 있는 함수를 생성합니다. + string public message; + + // 많은 클래스 기반 객체 지향 언어와 마찬가지로 생성자는 계약 생성 시에만 실행되는 특수 함수입니다. + // 생성자는 계약의 데이터를 초기화하는 데 사용됩니다. 자세히 알아보기:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors + constructor(string memory initMessage) { + + // 문자열 인수 `initMessage`를 수락하고 계약의 `message` 스토리지 변수에 값을 설정합니다). + message = initMessage; + } + + // 문자열 인수를 허용하고 `message` 스토리지 변수를 업데이트하는 공개 함수입니다. + function update(string memory newMessage) public { + string memory oldMsg = message; + message = newMessage; + emit UpdatedMessages(oldMsg, newMessage); + } +} +``` + +스마트 계약 이벤트는 블록체인에서 어떤 일이 일어났음(즉, _이벤트_가 발생했음)을 계약이 프런트엔드 애플리케이션에 전달하는 방법으로, 특정 이벤트를 '수신'하고 해당 이벤트가 발생하면 조치를 취할 수 있습니다. + +`addSmartContractListener` 함수는 특별히 Hello World 스마트 계약의 `UpdatedMessages` 이벤트를 수신하고, UI를 업데이트하여 새 메시지를 표시합니다. + +`addSmartContractListener`를 다음과 같이 수정합니다. + +```javascript +// HelloWorld.js + +function addSmartContractListener() { + helloWorldContract.events.UpdatedMessages({}, (error, data) => { + if (error) { + setStatus("😥 " + error.message) + } else { + setMessage(data.returnValues[1]) + setNewMessage("") + setStatus("🎉 메시지가 업데이트되었습니다!") + } + }) +} +``` + +리스너가 이벤트를 감지할 때 어떤 일이 발생하는지 분석해 보겠습니다. + +- 이벤트가 발생할 때 오류가 발생하면 `status` 상태 변수를 통해 UI에 반영됩니다. +- 그렇지 않으면 반환된 `data` 객체를 사용합니다. `data.returnValues`는 0부터 인덱싱된 배열로, 배열의 첫 번째 요소는 이전 메시지를 저장하고 두 번째 요소는 업데이트된 메시지를 저장합니다. 전체적으로, 성공적인 이벤트 발생 시 `message` 문자열을 업데이트된 메시지로 설정하고, `newMessage` 문자열을 지우고, `status` 상태 변수를 업데이트하여 스마트 계약에 새 메시지가 게시되었음을 반영합니다. + +마지막으로, `HelloWorld.js` 컴포넌트의 첫 렌더링 시 초기화되도록 `useEffect` 함수에서 리스너를 호출합니다. 전체적으로 `useEffect` 함수는 다음과 같아야 합니다. + +```javascript +// HelloWorld.js + +useEffect(async () => { + const message = await loadCurrentMessage() + setMessage(message) + addSmartContractListener() +}, []) +``` + +이제 스마트 계약에서 읽을 수 있게 되었으니, 쓰는 방법도 알아보면 좋겠습니다! 하지만 탈중앙화앱에 쓰려면 먼저 이더리움 지갑이 연결되어 있어야 합니다. + +따라서 다음으로 이더리움 지갑(MetaMask)을 설정하고 탈중앙화앱에 연결하는 방법을 다루겠습니다! + +### 4단계: 이더리움 지갑 설정하기 {#step-4-set-up-your-ethereum-wallet} + +이더리움 체인에 무엇이든 쓰려면 사용자는 가상 지갑의 개인 키를 사용하여 트랜잭션에 서명해야 합니다. 이 튜토리얼에서는 최종 사용자에게 이 트랜잭션 서명을 매우 쉽게 만들어주는 브라우저 내 가상 지갑인 [MetaMask](https://metamask.io/)를 사용하여 이더리움 계정 주소를 관리합니다. + +이더리움의 트랜잭션 작동 방식에 대해 더 자세히 알아보려면 이더리움 재단의 [이 페이지](/developers/docs/transactions/)를 확인하세요. + +#### MetaMask 다운로드하기 {#download-metamask} + +[여기](https://metamask.io/download)에서 MetaMask 계정을 무료로 다운로드하고 생성할 수 있습니다. 계정을 생성하거나 이미 계정이 있는 경우, 오른쪽 상단에서 'Goerli 테스트 네트워크'로 전환했는지 확인하세요(실제 돈을 다루지 않기 위함입니다). + +#### 파우셋에서 이더 추가하기 {#add-ether-from-a-faucet} + +이더리움 블록체인에서 트랜잭션에 서명하려면 가짜 Eth가 필요합니다. Eth를 얻으려면 [FaucETH](https://fauceth.komputing.org)로 이동하여 Goerli 계정 주소를 입력하고 '자금 요청'을 클릭한 다음, 드롭다운에서 '이더리움 테스트넷 Goerli'를 선택하고 마지막으로 '자금 요청' 버튼을 다시 클릭하세요. 곧 MetaMask 계정에서 Eth를 볼 수 있을 것입니다! + +#### 잔액 확인하기 {#check-your-balance} + +잔액이 있는지 다시 확인하기 위해 [Alchemy의 컴포저 도구](https://composer.alchemyapi.io/?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D)를 사용하여 [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) 요청을 해봅시다. 그러면 지갑에 있는 Eth의 양이 반환됩니다. MetaMask 계정 주소를 입력하고 "Send Request"를 클릭하면 다음과 같은 응답이 표시됩니다. + +```text +{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"} +``` + +**참고:** 이 결과는 eth가 아닌 wei 단위입니다. Wei는 ether의 최소 단위로 사용됩니다. wei에서 eth로의 변환은 1 eth = 10¹⁸ wei입니다. 따라서 0xde0b6b3a7640000을 10진수로 변환하면 1\*10¹⁸이 되고 이는 1eth와 같습니다. + +휴! 우리의 가짜 돈이 다 있군요! 🤑 + +### 5단계: MetaMask를 UI에 연결하기 {#step-5-connect-metamask-to-your-UI} + +이제 MetaMask 지갑이 설정되었으니, 탈중앙화앱을 연결해 봅시다! + +#### `connectWallet` 함수 {#the-connectWallet-function} + +`interact.js` 파일에서 `connectWallet` 함수를 구현한 다음, `HelloWorld.js` 컴포넌트에서 호출할 수 있습니다. + +`connectWallet`을 다음과 같이 수정합시다. + +```javascript +// interact.js + +export const connectWallet = async () => { + if (window.ethereum) { + try { + const addressArray = await window.ethereum.request({ + method: "eth_requestAccounts", + }) + const obj = { + status: "👆🏽 위 텍스트 필드에 메시지를 작성하세요.", + address: addressArray[0], + } + return obj + } catch (err) { + return { + address: "", + status: "😥 " + err.message, + } + } + } else { + return { + address: "", + status: ( + +

+ {" "} + 🦊 + 브라우저에 가상 이더리움 지갑인 MetaMask를 설치해야 합니다. + +

+ + ), + } + } +} +``` + +이 거대한 코드 블록은 정확히 무엇을 하는 걸까요? + +먼저, 브라우저에서 `window.ethereum`이 활성화되어 있는지 확인합니다. + +`window.ethereum`은 MetaMask 및 기타 지갑 제공업체에서 주입하는 글로벌 API로, 웹사이트가 사용자의 이더리움 계정을 요청할 수 있도록 합니다. 승인되면 사용자가 연결된 블록체인에서 데이터를 읽고, 사용자에게 메시지 및 트랜잭션 서명을 제안할 수 있습니다. 자세한 내용은 [MetaMask 문서](https://docs.metamask.io/guide/ethereum-provider.html#table-of-contents)를 확인하세요! + +`window.ethereum`이 _없으면_ MetaMask가 설치되지 않았다는 의미입니다. 그러면 `address`가 빈 문자열로 반환되고 `status` JSX 객체는 사용자가 MetaMask를 설치해야 한다는 것을 전달하는 JSON 객체가 반환됩니다. + +이제 `window.ethereum`이 _있으면_ 상황이 흥미로워집니다. + +try/catch 루프를 사용하여 [`window.ethereum.request({ method: "eth_requestAccounts" });`](https://docs.metamask.io/guide/rpc-api.html#eth-requestaccounts)를 호출하여 MetaMask에 연결을 시도합니다. 이 함수를 호출하면 브라우저에서 MetaMask가 열리고 사용자에게 지갑을 탈중앙화앱에 연결하라는 메시지가 표시됩니다. + +- 사용자가 연결하기로 선택하면 `method: "eth_requestAccounts"`는 탈중앙화앱에 연결된 모든 사용자의 계정 주소를 포함하는 배열을 반환합니다. 전체적으로 `connectWallet` 함수는 이 배열의 _첫 번째_ `address`\(9번째 줄 참조\)와 사용자에게 스마트 계약에 메시지를 작성하라는 `status` 메시지를 포함하는 JSON 객체를 반환합니다. +- 사용자가 연결을 거부하면 JSON 객체는 반환된 `address`에 대해 빈 문자열을 포함하고 사용자가 연결을 거부했음을 반영하는 `status` 메시지를 포함합니다. + +이제 이 `connectWallet` 함수를 작성했으므로 다음 단계는 `HelloWorld.js` 컴포넌트에서 호출하는 것입니다. + +#### `connectWallet` 함수를 `HelloWorld.js` UI 컴포넌트에 추가하기 {#add-the-connectWallet-function-to-your-HelloWorld-js-ui-component} + +`HelloWorld.js`의 `connectWalletPressed` 함수로 이동하여 다음과 같이 업데이트하세요. + +```javascript +// HelloWorld.js + +const connectWalletPressed = async () => { + const walletResponse = await connectWallet() + setStatus(walletResponse.status) + setWallet(walletResponse.address) +} +``` + +`interact.js` 파일에서 대부분의 기능이 `HelloWorld.js` 컴포넌트에서 어떻게 추상화되었는지 주목하세요. 이것은 M-V-C 패러다임을 준수하기 위함입니다! + +`connectWalletPressed`에서 가져온 `connectWallet` 함수를 await 호출하고, 그 응답을 사용하여 상태 훅을 통해 `status` 및 `walletAddress` 변수를 업데이트합니다. + +이제 두 파일(`HelloWorld.js` 및 `interact.js`)을 모두 저장하고 지금까지의 UI를 테스트해 보겠습니다. + +[http://localhost:3000/](http://localhost:3000/) 페이지에서 브라우저를 열고 페이지 오른쪽 상단의 "지갑 연결" 버튼을 누르세요. + +MetaMask가 설치되어 있다면, 지갑을 탈중앙화앱에 연결하라는 메시지가 표시됩니다. 연결 초대를 수락합니다. + +이제 지갑 버튼에 주소가 연결되었음이 반영되는 것을 볼 수 있습니다! 좋아요 🔥 + +다음으로, 페이지를 새로고침해 보세요... 이상하네요. 지갑이 이미 연결되어 있음에도 불구하고 지갑 버튼은 MetaMask에 연결하라는 메시지를 표시합니다... + +하지만 두려워하지 마세요! 이 주소 문제를 쉽게 해결할 수 있습니다(이해하셨나요?) `getCurrentWalletConnected`를 구현하여 주소가 이미 탈중앙화앱에 연결되어 있는지 확인하고 그에 따라 UI를 업데이트하면 됩니다! + +#### `getCurrentWalletConnected` 함수 {#the-getcurrentwalletconnected-function} + +`interact.js` 파일의 `getCurrentWalletConnected` 함수를 다음과 같이 업데이트하세요. + +```javascript +// interact.js + +export const getCurrentWalletConnected = async () => { + if (window.ethereum) { + try { + const addressArray = await window.ethereum.request({ + method: "eth_accounts", + }) + if (addressArray.length > 0) { + return { + address: addressArray[0], + status: "👆🏽 위 텍스트 필드에 메시지를 작성하세요.", + } + } else { + return { + address: "", + status: "🦊 오른쪽 상단 버튼을 사용하여 MetaMask에 연결하세요.", + } + } + } catch (err) { + return { + address: "", + status: "😥 " + err.message, + } + } + } else { + return { + address: "", + status: ( + +

+ {" "} + 🦊 + 브라우저에 가상 이더리움 지갑인 MetaMask를 설치해야 합니다. + +

+
+ ), + } + } +} +``` + +이 코드는 이전 단계에서 작성한 `connectWallet` 함수와 _매우_ 유사합니다. + +주요 차이점은 사용자가 지갑을 연결하기 위해 MetaMask를 여는 `eth_requestAccounts` 메서드를 호출하는 대신, 여기서는 현재 탈중앙화앱에 연결된 MetaMask 주소를 포함하는 배열을 반환하는 `eth_accounts` 메서드를 호출한다는 것입니다. + +이 함수가 작동하는 것을 보려면 `HelloWorld.js` 컴포넌트의 `useEffect` 함수에서 호출해 봅시다. + +```javascript +// HelloWorld.js + +useEffect(async () => { + const message = await loadCurrentMessage() + setMessage(message) + addSmartContractListener() + + const { address, status } = await getCurrentWalletConnected() + setWallet(address) + setStatus(status) +}, []) +``` + +`getCurrentWalletConnected` 호출의 응답을 사용하여 `walletAddress`와 `status` 상태 변수를 업데이트하는 것을 확인하세요. + +이제 이 코드를 추가했으니 브라우저 창을 새로고침해 봅시다. + +좋아요! 버튼에는 연결되었다고 표시되고 연결된 지갑 주소의 미리보기가 표시되어야 합니다 - 새로고침 후에도 말이죠! + +#### `addWalletListener` 구현하기 {#implement-addwalletlistener} + +탈중앙화앱 지갑 설정의 마지막 단계는 사용자가 연결을 끊거나 계정을 전환할 때와 같이 지갑의 상태가 변경될 때 UI가 업데이트되도록 지갑 리스너를 구현하는 것입니다. + +`HelloWorld.js` 파일에서 `addWalletListener` 함수를 다음과 같이 수정하세요. + +```javascript +// HelloWorld.js + +function addWalletListener() { + if (window.ethereum) { + window.ethereum.on("accountsChanged", (accounts) => { + if (accounts.length > 0) { + setWallet(accounts[0]) + setStatus("👆🏽 위 텍스트 필드에 메시지를 작성하세요.") + } else { + setWallet("") + setStatus("🦊 오른쪽 상단 버튼을 사용하여 MetaMask에 연결하세요.") + } + }) + } else { + setStatus( +

+ {" "} + 🦊 + 브라우저에 가상 이더리움 지갑인 MetaMask를 설치해야 합니다. + +

+ ) + } +} +``` + +이 시점에서는 여기서 무슨 일이 일어나고 있는지 이해하는 데 도움이 필요 없을 것이라고 확신하지만, 철저함을 위해 간단히 분석해 보겠습니다. + +- 먼저, 함수는 `window.ethereum`이 활성화되어 있는지(즉, MetaMask가 설치되어 있는지) 확인합니다. + - 그렇지 않다면, `status` 상태 변수를 사용자가 MetaMask를 설치하도록 유도하는 JSX 문자열로 설정합니다. + - 활성화된 경우, 3번째 줄에서 `window.ethereum.on("accountsChanged")` 리스너를 설정하여 사용자가 탈중앙화앱에 추가 계정을 연결하거나 계정을 전환하거나 계정 연결을 끊는 등 MetaMask 지갑의 상태 변화를 수신합니다. 연결된 계정이 하나 이상 있는 경우, `walletAddress` 상태 변수는 리스너가 반환한 `accounts` 배열의 첫 번째 계정으로 업데이트됩니다. 그렇지 않으면 `walletAddress`는 빈 문자열로 설정됩니다. + +마지막으로 `useEffect` 함수에서 호출해야 합니다. + +```javascript +// HelloWorld.js + +useEffect(async () => { + const message = await loadCurrentMessage() + setMessage(message) + addSmartContractListener() + + const { address, status } = await getCurrentWalletConnected() + setWallet(address) + setStatus(status) + + addWalletListener() +}, []) +``` + +이것으로 끝입니다! 모든 지갑 기능을 성공적으로 프로그래밍했습니다! 이제 마지막 작업인 스마트 계약에 저장된 메시지 업데이트로 넘어갑시다! + +### 6단계: `updateMessage` 함수 구현하기 {#step-6-implement-the-updateMessage-function} + +자, 이제 마지막 단계에 도착했습니다! `interact.js` 파일의 `updateMessage`에서 다음을 수행할 것입니다. + +1. 스마트 계약에 게시하려는 메시지가 유효한지 확인합니다 +2. MetaMask를 사용하여 트랜잭션에 서명합니다 +3. `HelloWorld.js` 프런트엔드 컴포넌트에서 이 함수를 호출합니다 + +오래 걸리지 않을 것입니다. 이 탈중앙화앱을 완성합시다! + +#### 입력 오류 처리 {#input-error-handling} + +당연히 함수 시작 부분에 일종의 입력 오류 처리를 하는 것이 합리적입니다. + +MetaMask 확장 프로그램이 설치되지 않았거나, 지갑이 연결되지 않았거나(즉, 전달된 `주소`가 빈 문자열인 경우), `메시지`가 빈 문자열인 경우 함수가 조기에 반환되도록 하고 싶을 것입니다. `updateMessage`에 다음 오류 처리를 추가합시다. + +```javascript +// interact.js + +export const updateMessage = async (address, message) => { + if (!window.ethereum || address === null) { + return { + status: + "💡 블록체인에서 메시지를 업데이트하려면 MetaMask 지갑을 연결하세요.", + } + } + + if (message.trim() === "") { + return { + status: "❌ 메시지는 빈 문자열이 될 수 없습니다.", + } + } +} +``` + +이제 적절한 입력 오류 처리가 있으니, MetaMask를 통해 트랜잭션에 서명할 시간입니다! + +#### 트랜잭션 서명하기 {#signing-our-transaction} + +전통적인 웹3 이더리움 트랜잭션에 이미 익숙하다면 다음에 작성할 코드는 매우 친숙할 것입니다. 입력 오류 처리 코드 아래에 `updateMessage`에 다음을 추가합니다. + +```javascript +// interact.js + +//트랜잭션 매개변수 설정 +const transactionParameters = { + to: contractAddress, // 계약 게시 중을 제외하고 필수입니다. + from: address, // 사용자의 활성 주소와 일치해야 합니다. + data: helloWorldContract.methods.update(message).encodeABI(), +} + +//트랜잭션 서명 +try { + const txHash = await window.ethereum.request({ + method: "eth_sendTransaction", + params: [transactionParameters], + }) + return { + status: ( + + ✅{" "} + + Etherscan에서 트랜잭션 상태 보기! + +
+ ℹ️ 트랜잭션이 네트워크에 의해 확인되면 메시지가 + 자동으로 업데이트됩니다. +
+ ), + } +} catch (error) { + return { + status: "😥 " + error.message, + } +} +``` + +어떤 일이 일어나는지 분석해 봅시다. 먼저, 트랜잭션 매개변수를 설정합니다. 여기서: + +- `to`는 수신자 주소(우리의 스마트 계약)를 지정합니다. +- `from`은 트랜잭션의 서명자, 즉 함수에 전달된 `주소` 변수를 지정합니다. +- `data`는 Hello World 스마트 계약의 `update` 메서드에 대한 호출을 포함하며, `message` 문자열 변수를 입력으로 받습니다. + +그런 다음, `window.ethereum.request`라는 await 호출을 통해 MetaMask에 트랜잭션 서명을 요청합니다. 11번과 12번 줄에서 eth 메서드 `eth_sendTransaction`을 지정하고 `transactionParameters`를 전달하는 것을 주목하세요. + +이 시점에서 MetaMask가 브라우저에서 열리고 사용자에게 트랜잭션에 서명하거나 거부하라는 메시지를 표시합니다. + +- 트랜잭션이 성공하면, 함수는 `status` JSX 문자열이 사용자에게 트랜잭션에 대한 자세한 정보를 Etherscan에서 확인하도록 안내하는 JSON 객체를 반환합니다. +- 트랜잭션이 실패하면, 함수는 `status` 문자열이 오류 메시지를 전달하는 JSON 객체를 반환합니다. + +전체적으로 `updateMessage` 함수는 다음과 같아야 합니다. + +```javascript +// interact.js + +export const updateMessage = async (address, message) => { + //입력 오류 처리 + if (!window.ethereum || address === null) { + return { + status: + "💡 블록체인에서 메시지를 업데이트하려면 MetaMask 지갑을 연결하세요.", + } + } + + if (message.trim() === "") { + return { + status: "❌ 메시지는 빈 문자열이 될 수 없습니다.", + } + } + + //트랜잭션 매개변수 설정 + const transactionParameters = { + to: contractAddress, // 계약 게시 중을 제외하고 필수입니다. + from: address, // 사용자의 활성 주소와 일치해야 합니다. + data: helloWorldContract.methods.update(message).encodeABI(), + } + + //트랜잭션 서명 + try { + const txHash = await window.ethereum.request({ + method: "eth_sendTransaction", + params: [transactionParameters], + }) + return { + status: ( + + ✅{" "} + + Etherscan에서 트랜잭션 상태 보기! + +
+ ℹ️ 트랜잭션이 네트워크에 의해 확인되면 메시지가 + 자동으로 업데이트됩니다. +
+ ), + } + } catch (error) { + return { + status: "😥 " + error.message, + } + } +} +``` + +마지막으로, `updateMessage` 함수를 `HelloWorld.js` 컴포넌트에 연결해야 합니다. + +#### `updateMessage`를 `HelloWorld.js` 프런트엔드에 연결하기 {#connect-updatemessage-to-the-helloworld-js-frontend} + +`onUpdatePressed` 함수는 가져온 `updateMessage` 함수에 대한 await 호출을 하고 `status` 상태 변수를 수정하여 트랜잭션이 성공했는지 실패했는지를 반영해야 합니다. + +```javascript +// HelloWorld.js + +const onUpdatePressed = async () => { + const { status } = await updateMessage(walletAddress, newMessage) + setStatus(status) +} +``` + +매우 깔끔하고 간단합니다. 그리고 그거 아시나요... 탈중앙화앱이 완성되었습니다!!! + +**업데이트** 버튼을 테스트해 보세요! + +### 나만의 맞춤형 탈중앙화앱 만들기 {#make-your-own-custom-dapp} + +와, 튜토리얼 끝까지 오셨네요! 요약하자면, 다음을 배웠습니다. + +- MetaMask 지갑을 탈중앙화앱 프로젝트에 연결하기 +- [Alchemy Web3](https://docs.alchemy.com/alchemy/documentation/alchemy-web3) API를 사용하여 스마트 계약에서 데이터 읽기 +- MetaMask를 사용하여 이더리움 트랜잭션 서명하기 + +이제 이 튜토리얼에서 배운 기술을 적용하여 자신만의 맞춤형 탈중앙화앱 프로젝트를 구축할 준비가 되었습니다! 언제나 그렇듯이 질문이 있으시면 [Alchemy Discord](https://discord.gg/gWuC7zB)에서 주저하지 말고 도움을 요청하세요. 🧙‍♂️ + +이 튜토리얼을 완료한 후, Twitter에서 [@alchemyplatform](https://twitter.com/AlchemyPlatform)을 태그하여 경험이 어땠는지 또는 피드백이 있는지 알려주세요! diff --git a/public/content/translations/ko/developers/tutorials/hello-world-smart-contract/index.md b/public/content/translations/ko/developers/tutorials/hello-world-smart-contract/index.md new file mode 100644 index 00000000000..8bfd7a1ccaf --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/hello-world-smart-contract/index.md @@ -0,0 +1,359 @@ +--- +title: "초보자용 Hello World 스마트 컨트랙트" +description: "이더리움에 간단한 스마트 계약을 작성하고 배포하는 방법에 대한 입문 튜토리얼입니다." +author: "elanh" +tags: [ "Solidity", "Hardhat", "Alchemy", "스마트 계약", "배포하기" ] +skill: beginner +lang: ko +published: 2021-03-31 +--- + +블록체인 개발이 처음이라 어디서부터 시작해야 할지 모르거나, 스마트 계약을 배포하고 상호작용하는 방법을 이해하고 싶다면 이 가이드가 도움이 될 것입니다. 가상 지갑 [MetaMask](https://metamask.io/), [Solidity](https://docs.soliditylang.org/en/v0.8.0/), [Hardhat](https://hardhat.org/) 및 [Alchemy](https://www.alchemy.com/eth)를 사용하여 Sepolia 테스트 네트워크에 간단한 스마트 계약을 만들고 배포하는 과정을 안내합니다(아직 이 내용이 무엇을 의미하는지 이해하지 못하더라도 걱정하지 마세요. 앞으로 설명해 드릴 것입니다). + +이 튜토리얼의 [2부](https://docs.alchemy.com/docs/interacting-with-a-smart-contract)에서는 스마트 계약이 배포된 후 상호작용하는 방법을 살펴보고, [3부](https://www.alchemy.com/docs/submitting-your-smart-contract-to-etherscan)에서는 Etherscan에 게시하는 방법을 다룹니다. + +궁금한 점이 있으면 언제든지 [Alchemy Discord](https://discord.gg/gWuC7zB)에 문의하세요! + +## 1단계: 이더리움 네트워크에 연결하기 {#step-1} + +이더리움 체인에 요청을 보내는 방법은 여러 가지가 있습니다. 간단하게 설명하기 위해, 자체 노드를 실행하지 않고도 이더리움 체인과 통신할 수 있는 블록체인 개발자 플랫폼 및 API인 Alchemy의 무료 계정을 사용하겠습니다. 이 플랫폼에는 모니터링 및 분석을 위한 개발자 도구도 있습니다. 이 튜토리얼에서는 이 도구를 활용하여 스마트 계약 배포 시 내부적으로 어떤 일이 일어나는지 이해해 보겠습니다. Alchemy 계정이 아직 없다면 [여기서 무료로 가입할 수 있습니다](https://dashboard.alchemy.com/signup). + +## 2단계: 앱 만들기(및 API 키) {#step-2} + +Alchemy 계정을 생성한 후에는 앱을 생성하여 API 키를 생성할 수 있습니다. 이를 통해 Sepolia 테스트넷에 요청을 보낼 수 있습니다. 테스트넷에 익숙하지 않다면 [이 페이지](/developers/docs/networks/)를 확인하세요. + +1. Alchemy 대시보드에서 탐색 모음의 "Select an app"을 선택하고 "Create new app"을 클릭하여 "Create new app" 페이지로 이동하세요. + +![Hello world create app](./hello-world-create-app.png) + +2. 앱 이름을 “Hello World”로 지정하고, 간단한 설명을 제공한 다음, 사용 사례(예: "Infra & Tooling")를 선택하세요. 다음으로 "Ethereum"을 검색하고 네트워크를 선택하세요. + +![create app view hello world](./create-app-view-hello-world.png) + +3. "Next"를 클릭하여 진행한 다음, “Create app”을 클릭하면 완료됩니다! 앱이 탐색 모음 드롭다운 메뉴에 나타나며, API 키를 복사할 수 있습니다. + +## 3단계: 이더리움 계정(주소) 생성하기 {#step-3} + +거래를 보내고 받기 위해서는 이더리움 계정이 필요합니다. 이 튜토리얼에서는 이더리움 계정 주소를 관리하는 데 사용되는 브라우저의 가상 지갑인 MetaMask를 사용합니다. [트랜잭션](/developers/docs/transactions/)에 대해 자세히 알아보기. + +[여기](https://metamask.io/download)에서 MetaMask를 다운로드하고 이더리움 계정을 무료로 만들 수 있습니다. 계정을 만들 때나 이미 계정이 있는 경우, 네트워크 드롭다운 메뉴를 사용하여 "Sepolia" 테스트 네트워크로 전환해야 합니다(실제 돈을 다루지 않도록 하기 위함입니다). + +Sepolia가 목록에 표시되지 않으면 메뉴로 이동한 다음 '고급'으로 가서 아래로 스크롤하여 "테스트 네트워크 표시"를 켜세요. 네트워크 선택 메뉴에서 "사용자 지정" 탭을 선택하여 테스트넷 목록을 찾고 "Sepolia"를 선택하세요. + +![metamask sepolia example](./metamask-sepolia-example.png) + +## 4단계: 파우셋에서 이더 추가하기 {#step-4} + +스마트 계약을 테스트넷에 배포하려면 가짜 Eth가 필요합니다. Sepolia ETH를 얻으려면 [Sepolia 네트워크 세부 정보](/developers/docs/networks/#sepolia)로 이동하여 다양한 파우셋 목록을 볼 수 있습니다. 하나가 작동하지 않으면 다른 것을 시도해 보세요. 때때로 고갈될 수 있습니다. 네트워크 트래픽으로 인해 가짜 ETH를 받는 데 시간이 걸릴 수 있습니다. 곧 MetaMask 계정에서 ETH를 확인할 수 있습니다! + +## 5단계: 잔액 확인하기 {#step-5} + +잔액이 있는지 다시 확인하기 위해 [Alchemy의 컴포저 도구](https://sandbox.alchemy.com/?network=ETH_SEPOLIA&method=eth_getBalance&body.id=1&body.jsonrpc=2.0&body.method=eth_getBalance&body.params%5B0%5D=&body.params%5B1%5D=latest)를 사용하여 [eth_getBalance](/developers/docs/apis/json-rpc/#eth_getbalance) 요청을 해보겠습니다. 이것은 지갑에 있는 ETH의 양을 반환할 것입니다. MetaMask 계정 주소를 입력하고 "Send Request"를 클릭하면 다음과 같은 응답이 표시됩니다. + +```json +{ "jsonrpc": "2.0", "id": 0, "result": "0x2B5E3AF16B1880000" } +``` + +> **참고:** 이 결과는 ETH가 아닌 wei 단위입니다. Wei는 ether의 최소 단위로 사용됩니다. wei를 ETH로 변환하면 다음과 같습니다: 1 eth = 1018 wei. 따라서 0x2B5E3AF16B1880000을 10진수로 변환하면 5\*10¹⁸이 되며 이는 5 ETH와 같습니다. +> +> 휴! 가짜 돈이 모두 준비되었습니다 . + +## 6단계: 프로젝트 초기화하기 {#step-6} + +먼저 프로젝트를 위한 폴더를 만들어야 합니다. 커맨드 라인으로 이동하여 다음을 입력합니다. + +``` +mkdir hello-world +cd hello-world +``` + +이제 프로젝트 폴더 안으로 들어왔으니, `npm init`을 사용하여 프로젝트를 초기화하겠습니다. npm이 아직 설치되어 있지 않다면 [이 지침](https://docs.alchemyapi.io/alchemy/guides/alchemy-for-macs#1-install-nodejs-and-npm)을 따르세요(Node.js도 필요하니 함께 다운로드하세요!). + +``` +npm init +``` + +설치 질문에 어떻게 답하든 크게 상관없습니다. 참고용으로 저희가 진행한 방식은 다음과 같습니다: + +``` +package name: (hello-world) +version: (1.0.0) +description: hello world 스마트 계약 +entry point: (index.js) +test command: +git repository: +keywords: +author: +license: (ISC) +/Users/.../.../.../hello-world/package.json에 쓸 내용: + +{ + "name": "hello-world", + "version": "1.0.0", + "description": "hello world 스마트 계약", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +} +``` + +package.json을 승인하면 준비 완료입니다! + +## 7단계: [Hardhat](https://hardhat.org/getting-started/#overview) 다운로드하기 {#step-7} + +Hardhat은 이더리움 소프트웨어를 컴파일, 배포, 테스트 및 디버그하기 위한 개발 환경입니다. 실제 블록체인에 배포하기 전에 로컬에서 스마트 컨트랙트 및 dApp을 구축할 때 사용됩니다. + +`hello-world` 프로젝트 내부에서 다음을 실행하세요: + +``` +npm install --save-dev hardhat +``` + +설치 지침에 대한 자세한 내용은 [이 페이지](https://hardhat.org/getting-started/#overview)를 확인하세요. + +## 8단계: Hardhat 프로젝트 생성하기 {#step-8} + +프로젝트 폴더 내에서 다음을 실행합니다. + +``` +npx hardhat +``` + +그러면 환영 메시지와 원하는 작업을 선택할 수 있는 옵션이 표시됩니다. "create an empty hardhat.config.js"를 선택합니다. + +``` +888 888 888 888 888 +888 888 888 888 888 +888 888 888 888 888 +8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 +888 888 "88b 888P" d88" 888 888 "88b "88b 888 +888 888 .d888888 888 888 888 888 888 .d888888 888 +888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. +888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 + +👷 Hardhat v2.0.11에 오신 것을 환영합니다 👷‍? + +무엇을 하시겠습니까? … +샘플 프로젝트 생성 +❯ 빈 hardhat.config.js 생성 +종료 +``` + +이렇게 하면 `hardhat.config.js` 파일이 생성되며, 여기에 프로젝트에 대한 모든 설정을 지정하게 됩니다(13단계). + +## 9단계: 프로젝트 폴더 추가하기 {#step-9} + +프로젝트를 체계적으로 관리하기 위해 두 개의 새 폴더를 만들겠습니다. 명령줄에서 프로젝트의 루트 디렉터리로 이동하고 다음을 입력합니다. + +``` +mkdir contracts +mkdir scripts +``` + +- `contracts/`는 hello world 스마트 계약 코드 파일을 보관할 곳입니다. +- `scripts/`는 계약을 배포하고 상호작용하기 위한 스크립트를 보관할 곳입니다. + +## 10단계: 스마트 컨트랙트 작성하기 {#step-10} + +도대체 언제 코드를 작성하는 거지? 라고 자문하고 있을지도 모릅니다. 자, 이제 10단계입니다. + +선호하는 편집기(저희는 [VSCode](https://code.visualstudio.com/)를 좋아합니다)에서 hello-world 프로젝트를 여세요. 스마트 계약은 Solidity라는 언어로 작성되며, HelloWorld.sol 스마트 계약을 작성하는 데 이 언어를 사용할 것입니다.‌ + +1. “contracts” 폴더로 이동하여 HelloWorld.sol이라는 새 파일을 만드세요. +2. 아래는 이 튜토리얼에서 사용할 이더리움 재단의 샘플 Hello World 스마트 계약입니다. 아래 내용을 복사하여 HelloWorld.sol 파일에 붙여넣고, 주석을 읽고 이 계약이 어떤 역할을 하는지 이해하세요: + +```solidity +// 시맨틱 버저닝을 사용하여 Solidity 버전을 지정합니다. +// 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma +pragma solidity ^0.7.0; + +// `HelloWorld`라는 이름의 계약을 정의합니다. +// 계약은 함수와 데이터(상태)의 모음입니다. 배포되면 계약은 이더리움 블록체인의 특정 주소에 상주하게 됩니다. 자세히 알아보기: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html +contract HelloWorld { + + // `string` 타입의 상태 변수 `message`를 선언합니다. + // 상태 변수는 그 값이 계약 저장소에 영구적으로 저장되는 변수입니다. `public` 키워드는 변수를 계약 외부에서 접근할 수 있게 만들고, 다른 계약이나 클라이언트가 값을 접근하기 위해 호출할 수 있는 함수를 생성합니다. + string public message; + + // 많은 클래스 기반 객체 지향 언어와 유사하게, 생성자는 계약 생성 시에만 실행되는 특별한 함수입니다. + // 생성자는 계약의 데이터를 초기화하는 데 사용됩니다. 자세히 알아보기:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors + constructor(string memory initMessage) { + + // 문자열 인수 `initMessage`를 받아 계약의 `message` 저장 변수에 값을 설정합니다. + message = initMessage; + } + + // 문자열 인수를 받아 `message` 저장 변수를 업데이트하는 public 함수입니다. + function update(string memory newMessage) public { + message = newMessage; + } +} +``` + +이것은 생성 시 메시지를 저장하고 `update` 함수를 호출하여 업데이트할 수 있는 매우 간단한 스마트 계약입니다. + +## 11단계: MetaMask와 Alchemy를 프로젝트에 연결하기 {#step-11} + +MetaMask 지갑, Alchemy 계정을 만들고 스마트 계약을 작성했습니다. 이제 이 세 가지를 연결할 차례입니다. + +디지털 지갑에서 전송되는 모든 거래에는 고유한 개인 키를 사용하는 서명이 필요합니다. 프로그램에 이 권한을 제공하기 위해 개인 키(및 Alchemy API 키) 를 환경 파일에 안전하게 저장할 수 있습니다. + +> 트랜잭션 전송에 대해 더 자세히 알아보려면 web3를 사용하여 트랜잭션을 전송하는 [이 튜토리얼](/developers/tutorials/sending-transactions-using-web3-and-alchemy/)을 확인하세요. + +먼저 프로젝트 디렉터리에 dotenv 패키지를 설치합니다. + +``` +npm install dotenv --save +``` + +그런 다음 프로젝트의 루트 디렉터리에 `.env` 파일을 만들고 여기에 MetaMask 개인 키와 HTTP Alchemy API URL을 추가합니다. + +- 개인 키를 내보내려면 [이 지침](https://support.metamask.io/configure/accounts/how-to-export-an-accounts-private-key/)을 따르세요. +- HTTP Alchemy API URL을 얻으려면 아래를 참조하세요. + +![get alchemy api key](./get-alchemy-api-key.png) + +Alchemy API URL 복사하세요. + +`.env` 파일은 다음과 같아야 합니다: + +``` +API_URL = "https://eth-sepolia.g.alchemy.com/v2/your-api-key" +PRIVATE_KEY = "your-metamask-private-key" +``` + +이를 실제로 코드에 연결하기 위해 13단계의 `hardhat.config.js` 파일에서 이러한 변수를 참조합니다. + + + + +.env를 커밋하지 마세요! .env 파일을 다른 사람과 공유하거나 노출하지 마세요. 그렇게 하면 민감한 정보가 노출될 수 있습니다. 버전 관리 시스템을 사용하는 경우 .envgitignore 파일에 추가하세요. + + + + +## 12단계: Ethers.js 설치하기 {#step-12-install-ethersjs} + +Ethers.js는 [표준 JSON-RPC 메서드](/developers/docs/apis/json-rpc/)를 더 사용자 친화적인 메서드로 래핑하여 이더리움과 더 쉽게 상호 작용하고 요청할 수 있게 해주는 라이브러리입니다. + +Hardhat을 사용하면 추가 도구 및 확장된 기능을 위해 [플러그인](https://hardhat.org/plugins/)을 매우 쉽게 통합할 수 있습니다. 계약 배포를 위해 [Ethers 플러그인](https://hardhat.org/docs/plugins/official-plugins#hardhat-ethers)을 활용할 것입니다([Ethers.js](https://github.com/ethers-io/ethers.js/)는 매우 깔끔한 계약 배포 방법을 제공합니다). + +프로젝트 디렉토리에 다음을 입력합니다. + +``` +npm install --save-dev @nomiclabs/hardhat-ethers "ethers@^5.0.0" +``` + +다음 단계에서 `hardhat.config.js`에 ethers를 추가해야 합니다. + +## 13단계: hardhat.config.js 업데이트하기 {#step-13-update-hardhatconfigjs} + +지금까지 여러 종속성과 플러그인을 추가했습니다. 이제 프로젝트가 이 모든 것을 인식할 수 있도록 `hardhat.config.js`를 업데이트해야 합니다. + +`hardhat.config.js`를 다음과 같이 업데이트하세요: + +``` +require('dotenv').config(); + +require("@nomiclabs/hardhat-ethers"); +const { API_URL, PRIVATE_KEY } = process.env; + +/** +* @type import('hardhat/config').HardhatUserConfig +*/ +module.exports = { + solidity: "0.7.3", + defaultNetwork: "sepolia", + networks: { + hardhat: {}, + sepolia: { + url: API_URL, + accounts: [`0x${PRIVATE_KEY}`] + } + }, +} +``` + +## 14단계: 계약 컴파일하기 {#step-14-compile-our-contracts} + +지금까지 모든 것이 제대로 작동하는지 확인하기 위해 스마트 컨트랙트를 컴파일해 보겠습니다. `compile` 작업은 hardhat에 내장된 작업 중 하나입니다. + +명령줄에서 다음을 실행합니다. + +``` +npx hardhat compile +``` + +`SPDX license identifier not provided in source file`에 대한 경고가 표시될 수 있지만, 걱정할 필요는 없습니다. 나머지는 모두 정상일 것입니다! 그렇지 않은 경우 언제든지 [Alchemy discord](https://discord.gg/u72VCg3)로 메시지를 보내주세요. + +## 15단계: 배포 스크립트 작성하기 {#step-15-write-our-deploy-scripts} + +이제 스마트 컨트랙트가 작성되고 설정 파일을 사용할 수 있으므로 스마트 컨트랙트 배포 스크립트를 작성할 차례입니다. + +`scripts/` 폴더로 이동하여 `deploy.js`라는 새 파일을 만들고 다음 내용을 추가하세요. + +``` +async function main() { + const HelloWorld = await ethers.getContractFactory("HelloWorld"); + + // 배포를 시작하고, 계약 객체로 확인되는 프로미스를 반환합니다. + const hello_world = await HelloWorld.deploy("Hello World!"); + console.log("Contract deployed to address:", hello_world.address);} + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); +``` + +Hardhat은 [계약 튜토리얼](https://hardhat.org/tutorial/testing-contracts.html#writing-tests)에서 각 코드 라인이 무엇을 하는지 훌륭하게 설명하고 있으며, 저희는 그 설명을 여기에 채택했습니다. + +``` +const HelloWorld = await ethers.getContractFactory("HelloWorld"); +``` + +ethers.js의 `ContractFactory`는 새 스마트 계약을 배포하는 데 사용되는 추상화이므로, 여기서 `HelloWorld`는 우리의 hello world 계약 인스턴스를 위한 팩토리입니다. `hardhat-ethers` 플러그인을 사용할 때 `ContractFactory` 및 `Contract` 인스턴스는 기본적으로 첫 번째 서명자에 연결됩니다. + +``` +const hello_world = await HelloWorld.deploy(); +``` + +`ContractFactory`에서 `deploy()`를 호출하면 배포가 시작되고, `Contract`로 해석되는 `Promise`가 반환됩니다. 이것은 각 스마트 컨트랙트 기능에 대한 메소드가 있는 개체입니다. + +## 16단계: 계약 배포하기 {#step-16-deploy-our-contract} + +마침내 스마트 컨트랙트를 배포할 준비가 되었습니다! 명령줄로 이동하여 다음을 실행하세요: + +``` +npx hardhat run scripts/deploy.js --network sepolia +``` + +그러면 다음과 같은 내용이 표시됩니다. + +``` +계약이 배포된 주소: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570 +``` + +[Sepolia etherscan](https://sepolia.etherscan.io/)으로 이동하여 계약 주소를 검색하면 성공적으로 배포되었음을 확인할 수 있습니다. 트랜잭션은 다음과 같습니다. + +![etherscan contract](./etherscan-contract.png) + +`From` 주소는 MetaMask 계정 주소와 일치해야 하며 `To` 주소는 "Contract Creation"이라고 표시됩니다. 하지만 트랜잭션을 클릭하면 `To` 필드에 우리의 계약 주소가 표시됩니다: + +![etherscan transaction](./etherscan-transaction.png) + +축하해요! 이더리움 체인에 스마트 계약을 성공적으로 배포했습니다 🎉 + +내부에서 무슨 일이 일어나고 있는지 이해하기 위해 [Alchemy 대시보드](https://dashboard.alchemyapi.io/explorer)의 Explorer 탭으로 이동해 보겠습니다. Alchemy 앱이 여러 개 있는 경우, 앱별로 필터링하고 “Hello World”를 선택하세요. +![hello world explorer](./hello-world-explorer.png) + +여기서 `.deploy()` 함수를 호출했을 때 Hardhat/Ethers가 내부적으로 수행한 몇 가지 JSON-RPC 호출을 볼 수 있습니다. 여기서 주목해야 할 두 가지 중요한 호출은 실제로 Sepolia 체인에 계약을 작성하는 요청인 [`eth_sendRawTransaction`](https://www.alchemy.com/docs/node/abstract/abstract-api-endpoints/eth-send-raw-transaction)과, 해시가 주어졌을 때 트랜잭션에 대한 정보를 읽는 요청인 [`eth_getTransactionByHash`](https://www.alchemy.com/docs/node/abstract/abstract-api-endpoints/eth-get-transaction-by-hash)입니다(트랜잭션 시 일반적인 패턴). 트랜잭션 전송에 대해 더 알아보려면 [Web3를 사용한 트랜잭션 전송](/developers/tutorials/sending-transactions-using-web3-and-alchemy/)에 대한 이 튜토리얼을 확인하세요. + +이것으로 이 튜토리얼의 1부를 마칩니다. 2부에서는 초기 메시지를 업데이트하여 [스마트 계약과 실제로 상호작용](https://www.alchemy.com/docs/interacting-with-a-smart-contract)하고, 3부에서는 모든 사람이 상호작용 방법을 알 수 있도록 [스마트 계약을 Etherscan에 게시](https://www.alchemy.com/docs/submitting-your-smart-contract-to-etherscan)할 것입니다. + +**Alchemy에 대해 더 자세히 알고 싶으신가요?** 저희 [웹사이트](https://www.alchemy.com/eth)를 확인해 보세요. 업데이트를 놓치고 싶지 않으신가요? [여기](https://www.alchemy.com/newsletter)에서 뉴스레터를 구독하세요! 저희 [Discord](https://discord.gg/u72VCg3)에도 꼭 참여하세요.\*\*. diff --git a/public/content/translations/ko/developers/tutorials/how-to-implement-an-erc721-market/index.md b/public/content/translations/ko/developers/tutorials/how-to-implement-an-erc721-market/index.md new file mode 100644 index 00000000000..d7c5772dfa5 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/how-to-implement-an-erc721-market/index.md @@ -0,0 +1,145 @@ +--- +title: "ERC-721 마켓을 구현하는 방법" +description: "토큰화된 아이템을 탈중앙화된 분류 게시판에 판매용으로 올리는 방법" +author: "Alberto Cuesta Cañada" +tags: [ "스마트 컨트랙트", "erc-721", "Solidity", "토큰" ] +skill: intermediate +lang: ko +published: 2020-03-19 +source: Hackernoon +sourceUrl: https://hackernoon.com/how-to-implement-an-erc721-market-1e1a32j9 +--- + +이 글에서는 이더리움 블록체인을 위한 Craigslist를 코딩하는 방법을 보여드리겠습니다. + +Gumtree, Ebay, Craigslist 이전에는 분류 게시판이 주로 코르크나 종이로 만들어졌습니다. 학교 복도, 신문, 가로등, 상점 앞에 분류 게시판이 있었습니다. + +인터넷의 등장으로 모든 것이 바뀌었습니다. 특정 분류 게시판을 볼 수 있는 사람들의 수가 몇 배로 증가했습니다. 그로 인해, 그들이 대표하는 시장은 훨씬 더 효율적이 되었고 글로벌 규모로 확장되었습니다. Ebay는 이러한 물리적 분류 게시판에서 기원한 거대한 사업입니다. + +블록체인으로 이 시장들은 다시 한번 바뀔 것이며, 어떻게 바뀌는지 보여드리겠습니다. + +## 수익화 {#monetization} + +공개 블록체인 분류 게시판의 비즈니스 모델은 Ebay 및 그 회사의 모델과는 달라야 합니다. + +첫째, [탈중앙화의 관점](/developers/docs/web2-vs-web3/)이 있습니다. 기존 플랫폼은 자체 서버를 유지해야 합니다. 탈중앙화된 플랫폼은 사용자에 의해 유지되므로, 핵심 플랫폼을 운영하는 비용이 플랫폼 소유자에게는 0으로 떨어집니다. + +그리고 플랫폼에 대한 접근을 제공하는 웹사이트나 인터페이스인 프런트 엔드가 있습니다. 여기에는 많은 옵션이 있습니다. 플랫폼 소유자는 접근을 제한하고 모두가 자신의 인터페이스를 사용하도록 강제하며 수수료를 부과할 수 있습니다. 플랫폼 소유자는 접근을 개방하기로 결정할 수도 있습니다(권력을 민중에게!). 그리고 누구나 플랫폼에 대한 인터페이스를 구축하도록 허용할 수 있습니다. 또는 소유자는 이러한 극단적인 방법 사이의 어떤 접근 방식이든 결정할 수 있습니다. + +_저보다 더 큰 비전을 가진 비즈니스 리더들은 이것을 어떻게 수익화할지 알 것입니다._ _제가 보기에는 이것이 현상 유지와는 다르며 아마도 수익성이 있을 것이라는 점입니다._ + +더욱이, 자동화 및 결제 관점이 있습니다. 어떤 것들은 매우 [효과적으로 토큰화](https://hackernoon.com/tokenization-of-digital-assets-g0ffk3v8s?ref=hackernoon.com)될 수 있으며 분류 게시판에서 거래될 수 있습니다. 토큰화된 자산은 블록체인에서 쉽게 전송됩니다. 매우 복잡한 결제 방법도 블록체인에서 쉽게 구현될 수 있습니다. + +저는 여기서 사업 기회를 보고 있습니다. 운영 비용이 없는 분류 게시판은 각 거래에 복잡한 결제 경로를 포함하여 쉽게 구현될 수 있습니다. 누군가 이것을 무엇에 사용할지에 대한 아이디어를 낼 것이라고 확신합니다. + +저는 그냥 그것을 만드는 것이 행복합니다. 코드를 살펴보겠습니다. + +## 구현 {#implementation} + +얼마 전 우리는 비즈니스 사례 예제 구현 및 기타 유용한 것들이 포함된 [오픈 소스 리포지토리](https://github.com/HQ20/contracts?ref=hackernoon.com)를 시작했으니, 한번 살펴보세요. + +이 [이더리움 분류 게시판](https://github.com/HQ20/contracts/tree/master/contracts/classifieds?ref=hackernoon.com)의 코드가 거기에 있으니, 마음껏 활용하세요. 단, 이 코드는 감사를 받지 않았으므로 자금을 투입하기 전에 직접 실사를 해야 한다는 점을 유념하세요. + +게시판의 기본 사항은 복잡하지 않습니다. 게시판의 모든 광고는 몇 개의 필드를 가진 구조체일 뿐입니다. + +```solidity +struct Trade { + address poster; + uint256 item; + uint256 price; + bytes32 status; // 개시됨, 실행됨, 취소됨 +} +``` + +따라서 광고를 게시하는 사람이 있습니다. 판매용 아이템. 아이템의 가격. 거래의 상태는 개시됨, 실행됨 또는 취소됨일 수 있습니다. + +이 모든 거래는 매핑에 보관될 것입니다. 솔리디티의 모든 것이 매핑인 것 같기 때문입니다. 또한 편리하기 때문이기도 합니다. + +```solidity +mapping(uint256 => Trade) public trades; +``` + +매핑을 사용한다는 것은 각 광고를 게시하기 전에 ID를 만들어야 하며, 해당 광고에 대해 작업을 수행하기 전에 광고의 ID를 알아야 한다는 것을 의미합니다. 스마트 계약이나 프런트엔드에서 이를 처리하는 여러 방법이 있습니다. 조언이 필요하면 물어보세요. + +다음은 우리가 다루는 아이템이 무엇인지, 그리고 거래에 사용되는 통화가 무엇인지에 대한 질문입니다. + +아이템의 경우, 우리는 [ERC-721](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/IERC721.sol?ref=hackernoon.com) 인터페이스를 구현하도록 요구할 것입니다. 이는 실제로 블록체인에서 현실 세계의 아이템을 나타내는 방법일 뿐이지만, [디지털 자산에 가장 잘 작동](https://hackernoon.com/tokenization-of-digital-assets-g0ffk3v8s?ref=hackernoon.com)합니다. 우리는 생성자에서 자체 ERC721 계약을 지정할 것이며, 이는 우리 분류 게시판의 모든 자산이 사전에 토큰화되어야 함을 의미합니다. + +결제의 경우, 우리는 비슷한 작업을 할 것입니다. 대부분의 블록체인 프로젝트는 자체 [ERC-20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol?ref=hackernoon.com) 암호화폐를 정의합니다. 다른 일부는 DAI와 같은 주류 통화를 사용하는 것을 선호합니다. 이 분류 게시판에서는 구축 시 어떤 통화를 사용할지만 결정하면 됩니다. 쉽습니다. + +```solidity +constructor ( + address _currencyTokenAddress, address _itemTokenAddress +) public { + currencyToken = IERC20(_currencyTokenAddress); + itemToken = IERC721(_itemTokenAddress); + tradeCounter = 0; +} +``` + +거의 다 됐습니다. 광고, 거래할 아이템, 결제할 통화가 있습니다. 광고를 만든다는 것은, 자신이 아이템을 가지고 있다는 것과 다른 게시판 등에 두 번 게시하지 않았다는 것을 모두 보여주기 위해 아이템을 에스크로에 넣는 것을 의미합니다. + +아래 코드는 정확히 그 작업을 수행합니다. 아이템을 에스크로에 넣고, 광고를 생성하며, 몇 가지 정리 작업을 수행합니다. + +```solidity +function openTrade(uint256 _item, uint256 _price) + public +{ + itemToken.transferFrom(msg.sender, address(this), _item); + trades[tradeCounter] = Trade({ + poster: msg.sender, + item: _item, + price: _price, + status: "Open" + }); + tradeCounter += 1; + emit TradeStatusChange(tradeCounter - 1, "Open"); +} +``` + +거래를 수락한다는 것은 광고(거래)를 선택하고, 가격을 지불하며, 아이템을 받는 것을 의미합니다. 아래 코드는 거래를 검색합니다. 이용 가능한지 확인합니다. 아이템 대금을 지불합니다. 아이템을 받습니다. 광고를 업데이트합니다. + +```solidity +function executeTrade(uint256 _trade) + public +{ + Trade memory trade = trades[_trade]; + require(trade.status == "Open", "거래가 개시되지 않았습니다."); + currencyToken.transferFrom(msg.sender, trade.poster, trade.price); + itemToken.transferFrom(address(this), msg.sender, trade.item); + trades[_trade].status = "Executed"; + emit TradeStatusChange(_trade, "Executed"); +} +``` + +마지막으로, 판매자가 구매자가 수락하기 전에 거래를 취소할 수 있는 옵션이 있습니다. 일부 모델에서는 광고가 만료되기 전 일정 기간 동안 활성화됩니다. 시장의 디자인에 따라 선택하면 됩니다. + +코드는 거래를 실행하는 데 사용되는 코드와 매우 유사하며, 단지 통화가 오가지 않고 아이템이 광고 게시자에게 돌아간다는 점만 다릅니다. + +```solidity +function cancelTrade(uint256 _trade) + public +{ + Trade memory trade = trades[_trade]; + require( + msg.sender == trade.poster, + "거래는 게시자만 취소할 수 있습니다." + ); + require(trade.status == "Open", "거래가 개시되지 않았습니다."); + itemToken.transferFrom(address(this), trade.poster, trade.item); + trades[_trade].status = "Cancelled"; + emit TradeStatusChange(_trade, "Cancelled"); +} +``` + +이것으로 끝입니다. 구현의 끝까지 오셨습니다. 일부 비즈니스 개념이 코드로 표현될 때 얼마나 간결해지는지는 꽤 놀라운데, 이것이 바로 그런 경우 중 하나입니다. 전체 계약은 [저희 리포지토리](https://github.com/HQ20/contracts/blob/master/contracts/classifieds/Classifieds.sol)에서 확인하세요. + +## 결론 {#conclusion} + +분류 게시판은 인터넷과 함께 대규모로 확장된 일반적인 시장 구성으로, 소수의 독점적 승자와 함께 매우 인기 있는 비즈니스 모델이 되었습니다. + +또한 분류 게시판은 블록체인 환경에서 복제하기 쉬운 도구이며, 기존의 거대 기업에 대한 도전을 가능하게 하는 매우 특정한 기능을 가지고 있습니다. + +이 글에서 저는 분류 게시판 비즈니스의 비즈니스 현실과 기술적 구현을 연결하려고 시도했습니다. 이 지식은 여러분이 적절한 기술을 가지고 있다면 구현을 위한 비전과 로드맵을 만드는 데 도움이 될 것입니다. + +언제나처럼, 재미있는 것을 만들고 있고 조언이 필요하다면 언제든지 [연락 주세요](https://albertocuesta.es/)! 언제나 기꺼이 도와드리겠습니다. diff --git a/public/content/translations/ko/developers/tutorials/how-to-mint-an-nft/index.md b/public/content/translations/ko/developers/tutorials/how-to-mint-an-nft/index.md new file mode 100644 index 00000000000..d8bac9dc9ba --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/how-to-mint-an-nft/index.md @@ -0,0 +1,329 @@ +--- +title: "NFT 발행 방법(NFT 튜토리얼 시리즈 2/3부)" +description: "이 튜토리얼에서는 스마트 계약과 Web3를 사용하여 이더리움 블록체인에서 NFT를 발행하는 방법을 설명합니다." +author: "Sumi Mudgil" +tags: [ "ERC-721", "Alchemy", "Solidity", "스마트 계약" ] +skill: beginner +lang: ko +published: 2021-04-22 +--- + +[Beeple](https://www.nytimes.com/2021/03/11/arts/design/nft-auction-christies-beeple.html): 6,900만 달러 +[3LAU](https://www.forbes.com/sites/abrambrown/2021/03/03/3lau-nft-nonfungible-tokens-justin-blau/?sh=5f72ef64643b): 1,100만 달러 +[Grimes](https://www.theguardian.com/music/2021/mar/02/grimes-sells-digital-art-collection-non-fungible-tokens): 600만 달러 + +이들 모두 Alchemy의 강력한 API를 사용하여 NFT를 발행했습니다. 이 튜토리얼에서는 10분 이내에 동일한 작업을 수행하는 방법을 알려드립니다. + +'NFT 발행'은 블록체인에 ERC-721 토큰의 고유한 인스턴스를 게시하는 행위입니다. [이 NFT 튜토리얼 시리즈의 1부](/developers/tutorials/how-to-write-and-deploy-an-nft/)의 스마트 계약을 사용하여 Web3 기술을 발휘하고 NFT를 발행해 봅시다. 이 튜토리얼이 끝나면 여러분(과 여러분의 지갑)이 원하는 만큼 많은 NFT를 발행할 수 있게 될 것입니다! + +이제 시작하겠습니다! + +## 1단계: Web3 설치하기 {#install-web3} + +NFT 스마트 계약 생성에 대한 첫 번째 튜토리얼을 따라오셨다면, 이미 Ethers.js를 사용해 본 경험이 있으실 것입니다. Web3는 이더리움 블록체인에 대한 요청 생성을 더 쉽게 만들어주는 라이브러리라는 점에서 Ethers와 비슷합니다. 이 튜토리얼에서는 자동 재시도와 강력한 WebSocket 지원을 제공하는 향상된 Web3 라이브러리인 [Alchemy Web3](https://docs.alchemyapi.io/alchemy/documentation/alchemy-web3)를 사용할 것입니다. + +프로젝트 홈 디렉터리에서 다음을 실행하세요. + +``` +npm install @alch/alchemy-web3 +``` + +## 2단계: `mint-nft.js` 파일 생성하기 {#create-mintnftjs} + +scripts 디렉터리 내부에 `mint-nft.js` 파일을 만들고 다음 코드 줄을 추가하세요. + +```js +require("dotenv").config() +const API_URL = process.env.API_URL +const { createAlchemyWeb3 } = require("@alch/alchemy-web3") +const web3 = createAlchemyWeb3(API_URL) +``` + +## 3단계: 계약 ABI 가져오기 {#contract-abi} + +계약 ABI(애플리케이션 바이너리 인터페이스)는 스마트 계약과 상호 작용하기 위한 인터페이스입니다. 계약 ABI에 대해 [여기](https://docs.alchemyapi.io/alchemy/guides/eth_getlogs#what-are-ab-is)에서 더 자세히 알아볼 수 있습니다. Hardhat은 자동으로 ABI를 생성하여 `MyNFT.json` 파일에 저장합니다. 이를 사용하려면 `mint-nft.js` 파일에 다음 코드 줄을 추가하여 내용을 파싱해야 합니다. + +```js +const contract = require("../artifacts/contracts/MyNFT.sol/MyNFT.json") +``` + +ABI를 보려면 콘솔에 출력할 수 있습니다. + +```js +console.log(JSON.stringify(contract.abi)) +``` + +`mint-nft.js`를 실행하고 ABI가 콘솔에 출력되는 것을 보려면 터미널로 이동하여 다음을 실행하세요. + +```js +node scripts/mint-nft.js +``` + +## 4단계: IPFS를 사용하여 NFT 메타데이터 구성하기 {#config-meta} + +1부 튜토리얼에서 기억하시겠지만, `mintNFT` 스마트 계약 함수는 NFT의 메타데이터를 설명하는 JSON 문서로 확인되어야 하는 tokenURI 매개변수를 받습니다. 이 메타데이터는 이름, 설명, 이미지 및 기타 속성과 같은 구성 가능한 속성을 가질 수 있게 하여 NFT에 생명을 불어넣는 것입니다. + +> _IPFS(Interplanetary File System)는 분산 파일 시스템에서 데이터를 저장하고 공유하기 위한 탈중앙화 프로토콜 및 P2P 네트워크입니다._ + +NFT가 진정으로 탈중앙화되도록 보장하기 위해, 편리한 IPFS API 및 툴킷인 Pinata를 사용하여 NFT 자산과 메타데이터를 저장할 것입니다. Pinata 계정이 없다면, [여기](https://app.pinata.cloud)에서 무료 계정에 가입하고 이메일 인증 절차를 완료하세요. + +계정을 생성한 후: + +- '파일' 페이지로 이동하여 페이지 왼쪽 상단의 파란색 '업로드' 버튼을 클릭합니다. + +- Pinata에 이미지를 업로드합니다. 이 이미지가 NFT의 이미지 자산이 됩니다. 자산 이름은 원하는 대로 지정할 수 있습니다 + +- 업로드 후에는 '파일' 페이지의 표에서 파일 정보를 볼 수 있습니다. CID 열도 표시됩니다. CID 옆에 있는 복사 버튼을 클릭하여 CID를 복사할 수 있습니다. 업로드한 파일은 `https://gateway.pinata.cloud/ipfs/`에서 볼 수 있습니다. 예를 들어, 저희가 사용한 이미지는 IPFS [여기](https://gateway.pinata.cloud/ipfs/QmZdd5KYdCFApWn7eTZJ1qgJu18urJrP9Yh1TZcZrZxxB5)에서 찾을 수 있습니다. + +시각적 학습자를 위해 위 단계는 여기에 요약되어 있습니다. + +![Pinata에 이미지 업로드 방법](./instructionsPinata.gif) + +이제 Pinata에 문서를 하나 더 업로드해야 합니다. 하지만 그 전에 문서를 만들어야 합니다! + +루트 디렉터리에서 `nft-metadata.json`이라는 새 파일을 만들고 다음 JSON 코드를 추가합니다. + +```json +{ + "attributes": [ + { + "trait_type": "Breed", + "value": "Maltipoo" + }, + { + "trait_type": "Eye color", + "value": "Mocha" + } + ], + "description": "The world's most adorable and sensitive pup.", + "image": "ipfs://QmWmvTJmJU3pozR9ZHFmQC2DNDwi2XJtf3QGyYiiagFSWb", + "name": "Ramses" +} +``` + +JSON의 데이터는 자유롭게 변경할 수 있습니다. attributes 섹션을 제거하거나 추가할 수 있습니다. 가장 중요한 것은 `image` 필드가 여러분의 IPFS 이미지 위치를 가리키도록 하는 것입니다. 그렇지 않으면 여러분의 NFT에는 (아주 귀여운!) 강아지 사진이 포함될 것입니다. + +JSON 파일 편집이 끝나면 저장한 다음, 이미지를 업로드할 때와 동일한 단계에 따라 Pinata에 업로드하세요. + +![Pinata에 nft-metadata.json 업로드 방법](./uploadPinata.gif) + +## 5단계: 계약 인스턴스 생성하기 {#instance-contract} + +이제 계약과 상호 작용하려면 코드에서 계약의 인스턴스를 만들어야 합니다. 이를 위해 계약 주소가 필요하며, 이는 배포에서 얻거나 계약을 배포하는 데 사용한 주소를 [Blockscout](https://eth-sepolia.blockscout.com/)에서 조회하여 얻을 수 있습니다. + +![Etherscan에서 계약 주소 보기](./view-contract-etherscan.png) + +위 예시에서 계약 주소는 0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778입니다. + +다음으로 Web3 [contract 메서드](https://docs.web3js.org/api/web3-eth-contract/class/Contract)를 사용하여 ABI와 주소를 이용해 계약을 생성합니다. `mint-nft.js` 파일에 다음을 추가하세요: + +```js +const contractAddress = "0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778" + +const nftContract = new web3.eth.Contract(contract.abi, contractAddress) +``` + +## 6단계: `.env` 파일 업데이트하기 {#update-env} + +이제 이더리움 체인에 트랜잭션을 생성하고 전송하기 위해, 여러분의 공개 이더리움 계정 주소를 사용하여 계정 논스(아래에서 설명)를 가져옵니다. + +공개 키를 `.env` 파일에 추가하세요. 튜토리얼 1부를 완료했다면 `.env` 파일은 이제 다음과 같을 것입니다: + +```js +API_URL = "https://eth-sepolia.g.alchemy.com/v2/your-api-key" +PRIVATE_KEY = "your-private-account-address" +PUBLIC_KEY = "your-public-account-address" +``` + +## 7단계: 트랜잭션 생성하기 {#create-txn} + +먼저 `mintNFT(tokenData)`라는 이름의 함수를 정의하고 다음을 수행하여 트랜잭션을 생성해 보겠습니다. + +1. `.env` 파일에서 _PRIVATE_KEY_와 _PUBLIC_KEY_를 가져옵니다. + +2. 다음으로 계정 논스를 알아내야 합니다. 논스 사양은 여러분의 주소에서 보낸 트랜잭션 수를 추적하는 데 사용됩니다. 이는 보안 목적과 [재전송 공격](https://docs.alchemyapi.io/resources/blockchain-glossary#account-nonce)을 방지하기 위해 필요합니다. 주소에서 보낸 트랜잭션 수를 가져오려면 [getTransactionCount](https://docs.alchemyapi.io/documentation/alchemy-api-reference/json-rpc#eth_gettransactioncount)를 사용합니다. + +3. 마지막으로 다음 정보로 트랜잭션을 설정합니다. + +- `'from': PUBLIC_KEY` — 트랜잭션의 발신지는 공개 주소입니다 + +- `'to': contractAddress` — 상호 작용하고 트랜잭션을 보낼 계약입니다 + +- `'nonce': nonce` — 주소에서 보낸 트랜잭션 수가 포함된 계정 논스입니다 + +- `'gas': estimatedGas` — 트랜잭션을 완료하는 데 필요한 예상 가스입니다 + +- `'data': nftContract.methods.mintNFT(PUBLIC_KEY, md).encodeABI()` — 이 트랜잭션에서 수행하려는 계산으로, 이 경우 NFT를 발행하는 것입니다 + +이제 `mint-nft.js` 파일은 다음과 같아야 합니다: + +```js + require('dotenv').config(); + const API_URL = process.env.API_URL; + const PUBLIC_KEY = process.env.PUBLIC_KEY; + const PRIVATE_KEY = process.env.PRIVATE_KEY; + + const { createAlchemyWeb3 } = require("@alch/alchemy-web3"); + const web3 = createAlchemyWeb3(API_URL); + + const contract = require("../artifacts/contracts/MyNFT.sol/MyNFT.json"); + const contractAddress = "0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778"; + const nftContract = new web3.eth.Contract(contract.abi, contractAddress); + + async function mintNFT(tokenURI) { + const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, 'latest'); //최신 논스 가져오기 + + //트랜잭션 + const tx = { + 'from': PUBLIC_KEY, + 'to': contractAddress, + 'nonce': nonce, + 'gas': 500000, + 'data': nftContract.methods.mintNFT(PUBLIC_KEY, tokenURI).encodeABI() + }; + }​ +``` + +## 8단계: 트랜잭션 서명하기 {#sign-txn} + +이제 트랜잭션을 만들었으므로 전송하기 위해 서명해야 합니다. 여기서 개인 키를 사용합니다. + +`web3.eth.sendSignedTransaction`은 트랜잭션 해시를 제공하며, 이를 사용하여 트랜잭션이 채굴되었는지, 네트워크에서 누락되지 않았는지 확인할 수 있습니다. 트랜잭션 서명 섹션에서 트랜잭션이 성공적으로 통과되었는지 알 수 있도록 몇 가지 오류 확인을 추가한 것을 알 수 있습니다. + +```js +require("dotenv").config() +const API_URL = process.env.API_URL +const PUBLIC_KEY = process.env.PUBLIC_KEY +const PRIVATE_KEY = process.env.PRIVATE_KEY + +const { createAlchemyWeb3 } = require("@alch/alchemy-web3") +const web3 = createAlchemyWeb3(API_URL) + +const contract = require("../artifacts/contracts/MyNFT.sol/MyNFT.json") +const contractAddress = "0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778" +const nftContract = new web3.eth.Contract(contract.abi, contractAddress) + +async function mintNFT(tokenURI) { + const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, "latest") //최신 논스 가져오기 + + //트랜잭션 + const tx = { + from: PUBLIC_KEY, + to: contractAddress, + nonce: nonce, + gas: 500000, + data: nftContract.methods.mintNFT(PUBLIC_KEY, tokenURI).encodeABI(), + } + + const signPromise = web3.eth.accounts.signTransaction(tx, PRIVATE_KEY) + signPromise + .then((signedTx) => { + web3.eth.sendSignedTransaction( + signedTx.rawTransaction, + function (err, hash) { + if (!err) { + console.log( + "트랜잭션의 해시는 다음과 같습니다: ", + hash, + "\nAlchemy의 Mempool에서 트랜잭션 상태를 확인하세요!" + ) + } else { + console.log( + "트랜잭션을 제출하는 동안 문제가 발생했습니다:", + err + ) + } + } + ) + }) + .catch((err) => { + console.log(" Promise 실패:", err) + }) +} +``` + +## 9단계: `mintNFT` 호출 및 `node mint-nft.js` 실행하기 {#call-mintnft-fn} + +Pinata에 업로드한 `metadata.json`을 기억하시나요? Pinata에서 해시코드를 가져와 `https://gateway.pinata.cloud/ipfs/`를 `mintNFT` 함수에 매개변수로 전달하세요. + +해시코드를 찾는 방법은 아래와 같습니다. + +![Pinata에서 NFT 메타데이터 해시코드 가져오는 방법](./metadataPinata.gif)_Pinata에서 NFT 메타데이터 해시코드를 가져오는 방법_ + +> 복사한 해시코드가 `https://gateway.pinata.cloud/ipfs/`를 별도의 창에 로드하여 metadata.json에 연결되는지 다시 확인하세요. 페이지는 아래 스크린샷과 비슷하게 보일 것입니다. + +![페이지에 json 메타데이터가 표시되어야 합니다](./metadataJSON.png)_페이지에 json 메타데이터가 표시되어야 합니다_ + +전체 코드는 다음과 같아야 합니다. + +```js +require("dotenv").config() +const API_URL = process.env.API_URL +const PUBLIC_KEY = process.env.PUBLIC_KEY +const PRIVATE_KEY = process.env.PRIVATE_KEY + +const { createAlchemyWeb3 } = require("@alch/alchemy-web3") +const web3 = createAlchemyWeb3(API_URL) + +const contract = require("../artifacts/contracts/MyNFT.sol/MyNFT.json") +const contractAddress = "0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778" +const nftContract = new web3.eth.Contract(contract.abi, contractAddress) + +async function mintNFT(tokenURI) { + const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, "latest") //최신 논스 가져오기 + + //트랜잭션 + const tx = { + from: PUBLIC_KEY, + to: contractAddress, + nonce: nonce, + gas: 500000, + data: nftContract.methods.mintNFT(PUBLIC_KEY, tokenURI).encodeABI(), + } + + const signPromise = web3.eth.accounts.signTransaction(tx, PRIVATE_KEY) + signPromise + .then((signedTx) => { + web3.eth.sendSignedTransaction( + signedTx.rawTransaction, + function (err, hash) { + if (!err) { + console.log( + "트랜잭션의 해시는 다음과 같습니다: ", + hash, + "\nAlchemy의 Mempool에서 트랜잭션 상태를 확인하세요!" + ) + } else { + console.log( + "트랜잭션을 제출하는 동안 문제가 발생했습니다:", + err + ) + } + } + ) + }) + .catch((err) => { + console.log("Promise 실패:", err) + }) +} + +mintNFT("ipfs://QmYueiuRNmL4MiA2GwtVMm6ZagknXnSpQnB3z2gWbz36hP") +``` + +이제 `node scripts/mint-nft.js`를 실행하여 NFT를 배포하세요. 몇 초 후 터미널에 다음과 같은 응답이 표시되어야 합니다. + + ``` + 트랜잭션의 해시는 다음과 같습니다: 0x301791fdf492001fcd9d5e5b12f3aa1bbbea9a88ed24993a8ab2cdae2d06e1e8 + + Alchemy의 Mempool에서 트랜잭션 상태를 확인하세요! + ``` + +다음으로 [Alchemy mempool](https://dashboard.alchemyapi.io/mempool)을 방문하여 트랜잭션 상태(대기 중, 채굴됨 또는 네트워크에서 누락됨)를 확인하세요. 트랜잭션이 누락된 경우, [Blockscout](https://eth-sepolia.blockscout.com/)에서 트랜잭션 해시를 검색해 보는 것도 도움이 됩니다. + +![Etherscan에서 NFT 트랜잭션 해시 보기](./view-nft-etherscan.png)_Etherscan에서 NFT 트랜잭션 해시 보기_ + +이것으로 끝입니다! 이제 이더리움 블록체인에서 NFT를 배포하고 발행했습니다 + +`mint-nft.js`를 사용하면 여러분(과 여러분의 지갑)이 원하는 만큼 많은 NFT를 발행할 수 있습니다! NFT의 메타데이터를 설명하는 새로운 tokenURI를 전달해야 합니다(그렇지 않으면 ID만 다른 동일한 NFT를 여러 개 만들게 됩니다). + +아마 여러분의 지갑에 있는 NFT를 자랑하고 싶을 것입니다. 그렇다면 [3부: 지갑에서 NFT를 보는 방법](/developers/tutorials/how-to-view-nft-in-metamask/)을 꼭 확인하세요! diff --git a/public/content/translations/ko/developers/tutorials/how-to-mock-solidity-contracts-for-testing/index.md b/public/content/translations/ko/developers/tutorials/how-to-mock-solidity-contracts-for-testing/index.md new file mode 100644 index 00000000000..27988f91f34 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/how-to-mock-solidity-contracts-for-testing/index.md @@ -0,0 +1,102 @@ +--- +title: "테스트를 위해 솔리디티 스마트 계약을 모의하는 방법" +description: "테스트할 때 계약을 놀려야 하는 이유" +author: Markus Waas +lang: ko +tags: [ "Solidity", "스마트 계약", "테스트", "모킹" ] +skill: intermediate +published: 2020-05-02 +source: soliditydeveloper.com +sourceUrl: https://soliditydeveloper.com/mocking-contracts +--- + +[모의 객체](https://wikipedia.org/wiki/Mock_object)는 객체 지향 프로그래밍에서 흔히 사용되는 디자인 패턴입니다. 이는 '놀리다'라는 의미를 가진 고대 프랑스어 'mocquer'에서 유래했으며, '실제 무언가를 모방하다'라는 의미로 발전했습니다. 이것이 바로 프로그래밍에서 우리가 하는 일입니다. 원한다면 스마트 계약을 놀려도 되지만, 가능하면 언제든지 모의(mock)하세요. 그러면 삶이 더 편해집니다. + +## 모의 객체로 계약 단위 테스트하기 {#unit-testing-contracts-with-mocks} + +계약을 모의한다는 것은 기본적으로 원래 계약과 매우 유사하게 작동하지만 개발자가 쉽게 제어할 수 있는 방식으로 해당 계약의 두 번째 버전을 만드는 것을 의미합니다. 계약이 복잡해서 [계약의 일부만 단위 테스트](/developers/docs/smart-contracts/testing/)하고 싶은 경우가 많습니다. 문제는 이 작은 부분을 테스트하는 데 도달하기 어려운 매우 특정한 계약 상태가 필요한 경우입니다. + +매번 계약을 필요한 상태로 만드는 복잡한 테스트 설정 로직을 작성하거나 모의 객체를 작성할 수 있습니다. 상속을 사용하면 계약을 쉽게 모의할 수 있습니다. 원래 계약에서 상속받는 두 번째 모의 계약을 만들기만 하면 됩니다. 이제 모의 객체에 대한 함수를 재정의할 수 있습니다. 예를 들어 살펴보겠습니다. + +## 예시: 비공개 ERC20 {#example-private-erc20} + +초기 비공개 기간이 있는 ERC-20 계약 예시를 사용합니다. 소유자는 비공개 사용자를 관리할 수 있으며, 초기에는 해당 사용자만 토큰을 받을 수 있습니다. 일정 시간이 지나면 누구나 토큰을 사용할 수 있습니다. 궁금하시다면, 새로운 OpenZeppelin 계약 v3의 [`_beforeTokenTransfer`](https://docs.openzeppelin.com/contracts/5.x/extending-contracts#using-hooks) 훅을 사용하고 있습니다. + +```solidity +pragma solidity ^0.6.0; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract PrivateERC20 is ERC20, Ownable { + mapping (address => bool) public isPrivateUser; + uint256 private publicAfterTime; + + constructor(uint256 privateERC20timeInSec) ERC20("PrivateERC20", "PRIV") public { + publicAfterTime = now + privateERC20timeInSec; + } + + function addUser(address user) external onlyOwner { + isPrivateUser[user] = true; + } + + function isPublic() public view returns (bool) { + return now >= publicAfterTime; + } + + function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override { + super._beforeTokenTransfer(from, to, amount); + + require(_validRecipient(to), "PrivateERC20: invalid recipient"); + } + + function _validRecipient(address to) private view returns (bool) { + if (isPublic()) { + return true; + } + + return isPrivateUser[to]; + } +} +``` + +이제 모의해 보겠습니다. + +```solidity +pragma solidity ^0.6.0; +import "../PrivateERC20.sol"; + +contract PrivateERC20Mock is PrivateERC20 { + bool isPublicConfig; + + constructor() public PrivateERC20(0) {} + + function setIsPublic(bool isPublic) external { + isPublicConfig = isPublic; + } + + function isPublic() public view returns (bool) { + return isPublicConfig; + } +} +``` + +다음 오류 메시지 중 하나가 표시됩니다. + +- `PrivateERC20Mock.sol: TypeError: Overriding function is missing "override" specifier.` +- `PrivateERC20.sol: TypeError: Trying to override non-virtual function. Did you forget to add "virtual"?.` + +새로운 0.6 솔리디티 버전을 사용하고 있으므로, 재정의할 수 있는 함수에는 `virtual` 키워드를 추가하고 재정의하는 함수에는 `override`를 추가해야 합니다. 따라서 두 `isPublic` 함수에 이를 추가해 보겠습니다. + +이제 단위 테스트에서 대신 `PrivateERC20Mock`을 사용할 수 있습니다. 비공개 사용 시간 동안의 동작을 테스트하려면 `setIsPublic(false)`를 사용하고, 공개 사용 시간을 테스트하려면 `setIsPublic(true)`를 사용하세요. 물론 이 예시에서는 [시간 헬퍼](https://docs.openzeppelin.com/test-helpers/0.5/api#increase)를 사용하여 시간을 적절하게 변경할 수도 있습니다. 하지만 이제 모킹의 개념이 명확해졌을 것이며, 단순히 시간을 앞당기는 것만큼 쉽지 않은 시나리오를 상상할 수 있을 것입니다. + +## 많은 계약 모킹하기 {#mocking-many-contracts} + +모든 단일 모의 객체에 대해 다른 계약을 만들어야 한다면 복잡해질 수 있습니다. 이것이 불편하다면 [MockContract](https://github.com/gnosis/mock-contract) 라이브러리를 살펴볼 수 있습니다. 이를 통해 즉석에서 계약의 동작을 재정의하고 변경할 수 있습니다. 하지만 다른 계약에 대한 호출을 모의하는 경우에만 작동하므로 우리 예시에는 적용되지 않습니다. + +## 모킹은 훨씬 더 강력할 수 있습니다 {#mocking-can-be-even-more-powerful} + +모킹의 힘은 여기서 그치지 않습니다. + +- 함수 추가: 특정 함수를 재정의하는 것뿐만 아니라 추가 함수를 더하는 것도 유용합니다. 토큰의 좋은 예는 모든 사용자가 무료로 새 토큰을 받을 수 있도록 추가적인 `mint` 함수를 두는 것입니다. +- 테스트넷에서 사용: 탈중앙화앱과 함께 테스트넷에서 계약을 배포하고 테스트할 때 모의 버전을 사용하는 것을 고려해 보세요. 꼭 필요한 경우가 아니면 함수 재정의를 피하세요. 결국 실제 로직을 테스트하고 싶을 것입니다. 하지만 예를 들어 계약 상태를 처음으로 간단히 리셋하는 리셋 함수를 추가하면 유용할 수 있으며, 새로운 배포가 필요하지 않습니다. 당연히 메인넷 계약에는 이것을 원하지 않을 것입니다. diff --git a/public/content/translations/ko/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/index.md b/public/content/translations/ko/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/index.md new file mode 100644 index 00000000000..0480e9e3764 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/index.md @@ -0,0 +1,697 @@ +--- +title: "Echidna를 사용하여 스마트 계약을 테스트하는 방법" +description: "Echidna를 사용하여 스마트 계약을 자동으로 테스트하는 방법" +author: "Trailofbits" +lang: ko +tags: [ "Solidity", "스마트 계약", "보안", "테스트", "퍼징" ] +skill: advanced +published: 2020-04-10 +source: Building secure contracts +sourceUrl: https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/echidna +--- + +## 설치 {#installation} + +Echidna는 도커를 통해 설치하거나 사전 컴파일된 바이너리를 사용하여 설치할 수 있습니다. + +### 도커를 통한 Echidna 설치 {#echidna-through-docker} + +```bash +docker pull trailofbits/eth-security-toolbox +docker run -it -v "$PWD":/home/training trailofbits/eth-security-toolbox +``` + +_마지막 명령어는 현재 디렉터리에 액세스할 수 있는 docker에서 eth-security-toolbox를 실행합니다. 호스트에서 파일을 변경하고 docker의 파일에서 도구를 실행할 수 있습니다_ + +도커 내부에서 다음을 실행하세요: + +```bash +solc-select 0.5.11 +cd /home/training +``` + +### 바이너리 {#binary} + +[https://github.com/crytic/echidna/releases/tag/v1.4.0.0](https://github.com/crytic/echidna/releases/tag/v1.4.0.0) + +## 속성 기반 퍼징 소개 {#introduction-to-property-based-fuzzing} + +Echidna는 속성 기반 퍼저이며, 이전 블로그 게시물([1](https://blog.trailofbits.com/2018/03/09/echidna-a-smart-fuzzer-for-ethereum/), [2](https://blog.trailofbits.com/2018/05/03/state-machine-testing-with-echidna/), [3](https://blog.trailofbits.com/2020/03/30/an-echidna-for-all-seasons/))에서 설명했습니다. + +### 퍼징 {#fuzzing} + +[퍼징](https://wikipedia.org/wiki/Fuzzing)은 보안 커뮤니티에서 잘 알려진 기술입니다. 이는 프로그램의 버그를 찾기 위해 다소 무작위적인 입력을 생성하는 것으로 구성됩니다. [AFL](http://lcamtuf.coredump.cx/afl/) 또는 [LibFuzzer](https://llvm.org/docs/LibFuzzer.html)와 같은 기존 소프트웨어용 퍼저는 버그를 찾는 데 효율적인 도구로 알려져 있습니다. + +순전히 무작위적인 입력 생성 외에도 다음과 같이 좋은 입력을 생성하기 위한 많은 기술과 전략이 있습니다. + +- 각 실행에서 피드백을 얻고 이를 사용하여 생성을 유도합니다. 예를 들어, 새로 생성된 입력이 새로운 경로의 발견으로 이어지는 경우, 그와 가까운 새 입력을 생성하는 것이 합리적일 수 있습니다. +- 구조적 제약 조건을 준수하는 입력 생성. 예를 들어, 입력에 체크섬이 있는 헤더가 포함된 경우 퍼저가 체크섬을 검증하는 입력을 생성하도록 하는 것이 합리적입니다. +- 알려진 입력을 사용하여 새 입력 생성: 유효한 입력의 대규모 데이터 세트에 액세스할 수 있는 경우, 퍼저는 처음부터 생성을 시작하는 대신 이를 통해 새 입력을 생성할 수 있습니다. 이를 보통 시드라고 합니다. + +### 속성 기반 퍼징 {#property-based-fuzzing} + +Echidna는 [QuickCheck](https://wikipedia.org/wiki/QuickCheck)에서 크게 영감을 받은 속성 기반 퍼징이라는 특정 퍼저 제품군에 속합니다. 충돌을 찾으려는 기존 퍼저와 달리, Echidna는 사용자 정의 불변 속성을 깨려고 시도합니다. + +스마트 계약에서 불변 속성은 솔리디티 함수로, 계약이 도달할 수 있는 부정확하거나 유효하지 않은 상태를 나타낼 수 있으며 다음을 포함합니다. + +- 부정확한 접근 제어: 공격자가 계약의 소유자가 됩니다. +- 부정확한 상태 머신: 계약이 일시 중지된 동안 토큰이 전송될 수 있습니다. +- 부정확한 산술: 사용자가 잔액 언더플로를 일으켜 무제한 무료 토큰을 얻을 수 있습니다. + +### Echidna로 속성 테스트하기 {#testing-a-property-with-echidna} + +Echidna로 스마트 계약을 테스트하는 방법을 알아보겠습니다. 대상은 다음 스마트 계약인 [`token.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/token.sol)입니다. + +```solidity +contract Token{ + mapping(address => uint) public balances; + function airdrop() public{ + balances[msg.sender] = 1000; + } + function consume() public{ + require(balances[msg.sender]>0); + balances[msg.sender] -= 1; + } + function backdoor() public{ + balances[msg.sender] += 1; + } +} +``` + +이 토큰이 다음과 같은 속성을 가져야 한다고 가정하겠습니다. + +- 누구나 최대 1,000개의 토큰을 가질 수 있습니다. +- 토큰은 전송할 수 없습니다(ERC20 토큰이 아닙니다). + +### 속성 작성하기 {#write-a-property} + +Echidna 속성은 솔리디티 함수입니다. 속성은 다음을 충족해야 합니다. + +- 인수가 없어야 합니다. +- 성공하면 `true`를 반환해야 합니다. +- 이름이 `echidna`로 시작해야 합니다. + +Echidna는 다음을 수행합니다. + +- 속성을 테스트하기 위해 임의의 트랜잭션을 자동으로 생성합니다. +- 속성이 `false`를 반환하거나 오류를 발생시키는 모든 트랜잭션을 보고합니다. +- 속성을 호출할 때 부작용을 무시합니다(즉, 속성이 상태 변수를 변경하면 테스트 후 폐기됩니다). + +다음 속성은 호출자가 1,000개 이하의 토큰을 가지고 있는지 확인합니다. + +```solidity +function echidna_balance_under_1000() public view returns(bool){ + return balances[msg.sender] <= 1000; +} +``` + +상속을 사용하여 계약과 속성을 분리하세요. + +```solidity +contract TestToken is Token{ + function echidna_balance_under_1000() public view returns(bool){ + return balances[msg.sender] <= 1000; + } + } +``` + +[`token.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/token.sol)은 속성을 구현하고 토큰에서 상속받습니다. + +### 계약 초기화하기 {#initiate-a-contract} + +Echidna는 인수가 없는 [생성자](/developers/docs/smart-contracts/anatomy/#constructor-functions)가 필요합니다. 계약에 특정 초기화가 필요한 경우 생성자에서 수행해야 합니다. + +Echidna에는 몇 가지 특정 주소가 있습니다. + +- 생성자를 호출하는 `0x00a329c0648769A73afAc7F9381E08FB43dBEA72` +- 다른 함수를 무작위로 호출하는 `0x10000`, `0x20000`, `0x00a329C0648769a73afAC7F9381e08fb43DBEA70` + +현재 예시에서는 특별한 초기화가 필요 없으므로 생성자가 비어 있습니다. + +### Echidna 실행하기 {#run-echidna} + +Echidna는 다음으로 실행됩니다. + +```bash +echidna-test contract.sol +``` + +contract.sol에 여러 계약이 포함된 경우 대상을 지정할 수 있습니다. + +```bash +echidna-test contract.sol --contract MyContract +``` + +### 요약: 속성 테스트하기 {#summary-testing-a-property} + +다음은 예시에 대한 Echidna 실행 요약입니다. + +```solidity +contract TestToken is Token{ + constructor() public {} + function echidna_balance_under_1000() public view returns(bool){ + return balances[msg.sender] <= 1000; + } + } +``` + +```bash +echidna-test testtoken.sol --contract TestToken +... + +echidna_balance_under_1000: failed!💥 + Call sequence, shrinking (1205/5000): + airdrop() + backdoor() + +... +``` + +Echidna는 `backdoor`가 호출되면 속성이 위반된다는 것을 발견했습니다. + +## 퍼징 캠페인 중 호출할 함수 필터링하기 {#filtering-functions-to-call-during-a-fuzzing-campaign} + +퍼징될 함수를 필터링하는 방법을 알아보겠습니다. +대상은 다음 스마트 계약입니다. + +```solidity +contract C { + bool state1 = false; + bool state2 = false; + bool state3 = false; + bool state4 = false; + + function f(uint x) public { + require(x == 12); + state1 = true; + } + + function g(uint x) public { + require(state1); + require(x == 8); + state2 = true; + } + + function h(uint x) public { + require(state2); + require(x == 42); + state3 = true; + } + + function i() public { + require(state3); + state4 = true; + } + + function reset1() public { + state1 = false; + state2 = false; + state3 = false; + return; + } + + function reset2() public { + state1 = false; + state2 = false; + state3 = false; + return; + } + + function echidna_state4() public returns (bool) { + return (!state4); + } +} +``` + +이 간단한 예시는 Echidna가 상태 변수를 변경하기 위해 특정 트랜잭션 시퀀스를 찾도록 강제합니다. +이는 퍼저에게는 어려운 일입니다( [Manticore](https://github.com/trailofbits/manticore)와 같은 심볼릭 실행 도구를 사용하는 것이 좋습니다). +Echidna를 실행하여 이를 확인할 수 있습니다. + +```bash +echidna-test multi.sol +... +echidna_state4: passed! 🎉 +Seed: -3684648582249875403 +``` + +### 함수 필터링하기 {#filtering-functions} + +Echidna는 두 개의 리셋 함수(`reset1` 및 `reset2`)가 모든 상태 변수를 `false`로 설정하기 때문에 이 계약을 테스트할 올바른 시퀀스를 찾는 데 어려움을 겪습니다. +하지만 특별한 Echidna 기능을 사용하여 리셋 함수를 블랙리스트에 추가하거나 `f`, `g`, `h`, `i` 함수만 화이트리스트에 추가할 수 있습니다. + +함수를 블랙리스트에 추가하려면 이 구성 파일을 사용할 수 있습니다. + +```yaml +filterBlacklist: true +filterFunctions: ["reset1", "reset2"] +``` + +함수를 필터링하는 또 다른 접근 방식은 화이트리스트에 추가된 함수를 나열하는 것입니다. 이를 위해 이 구성 파일을 사용할 수 있습니다. + +```yaml +filterBlacklist: false +filterFunctions: ["f", "g", "h", "i"] +``` + +- `filterBlacklist`는 기본적으로 `true`입니다. +- 필터링은 이름으로만 수행됩니다(매개변수 없음). `f()`와 `f(uint256)`이 있는 경우 `"f"` 필터는 두 함수 모두와 일치합니다. + +### Echidna 실행하기 {#run-echidna-1} + +`blacklist.yaml` 구성 파일로 Echidna를 실행하려면: + +```bash +echidna-test multi.sol --config blacklist.yaml +... +echidna_state4: failed!💥 + Call sequence: + f(12) + g(8) + h(42) + i() +``` + +Echidna는 속성이 거짓임을 증명하는 트랜잭션 시퀀스를 거의 즉시 찾을 것입니다. + +### 요약: 함수 필터링하기 {#summary-filtering-functions} + +Echidna는 퍼징 캠페인 중에 다음을 사용하여 호출할 함수를 블랙리스트 또는 화이트리스트에 추가할 수 있습니다. + +```yaml +filterBlacklist: true +filterFunctions: ["f1", "f2", "f3"] +``` + +```bash +echidna-test contract.sol --config config.yaml +... +``` + +Echidna는 `filterBlacklist` 불리언 값에 따라 `f1`, `f2`, `f3`을 블랙리스트에 추가하거나 이들만 호출하는 퍼징 캠페인을 시작합니다. + +## Echidna로 솔리디티의 assert 테스트하는 방법 {#how-to-test-soliditys-assert-with-echidna} + +이 짧은 튜토리얼에서는 Echidna를 사용하여 계약의 어설션 확인을 테스트하는 방법을 보여줍니다. 다음과 같은 계약이 있다고 가정해 보겠습니다. + +```solidity +contract Incrementor { + uint private counter = 2**200; + + function inc(uint val) public returns (uint){ + uint tmp = counter; + counter += val; + // tmp <= counter + return (counter - tmp); + } +} +``` + +### 어설션 작성하기 {#write-an-assertion} + +차이를 반환한 후 `tmp`가 `counter`보다 작거나 같은지 확인하고 싶습니다. Echidna 속성을 작성할 수 있지만, `tmp` 값을 어딘가에 저장해야 합니다. 대신 다음과 같은 어설션을 사용할 수 있습니다. + +```solidity +contract Incrementor { + uint private counter = 2**200; + + function inc(uint val) public returns (uint){ + uint tmp = counter; + counter += val; + assert (tmp <= counter); + return (counter - tmp); + } +} +``` + +### Echidna 실행하기 {#run-echidna-2} + +어설션 실패 테스트를 활성화하려면 [Echidna 구성 파일](https://github.com/crytic/echidna/wiki/Config) `config.yaml`을 만드세요. + +```yaml +checkAsserts: true +``` + +Echidna에서 이 계약을 실행하면 예상된 결과를 얻을 수 있습니다. + +```bash +echidna-test assert.sol --config config.yaml +Analyzing contract: assert.sol:Incrementor +assertion in inc: failed!💥 + Call sequence, shrinking (2596/5000): + inc(21711016731996786641919559689128982722488122124807605757398297001483711807488) + inc(7237005577332262213973186563042994240829374041602535252466099000494570602496) + inc(86844066927987146567678238756515930889952488499230423029593188005934847229952) + +Seed: 1806480648350826486 +``` + +보시다시피, Echidna는 `inc` 함수에서 일부 어설션 실패를 보고합니다. 함수당 하나 이상의 어설션을 추가할 수 있지만, Echidna는 어떤 어설션이 실패했는지 알 수 없습니다. + +### 어설션을 사용하는 시기와 방법 {#when-and-how-use-assertions} + +어설션은 명시적 속성의 대안으로 사용될 수 있으며, 특히 확인할 조건이 일부 작업 `f`의 올바른 사용과 직접적으로 관련된 경우에 유용합니다. 일부 코드 뒤에 어설션을 추가하면 코드가 실행된 직후에 확인이 수행되도록 강제합니다. + +```solidity +function f(..) public { + // some complex code + ... + assert (condition); + ... +} + +``` + +반대로, 명시적 Echidna 속성을 사용하면 트랜잭션이 무작위로 실행되며 언제 확인될지 정확히 강제할 쉬운 방법이 없습니다. 다음과 같은 해결 방법을 사용할 수는 있습니다. + +```solidity +function echidna_assert_after_f() public returns (bool) { + f(..); + return(condition); +} +``` + +하지만 몇 가지 문제가 있습니다. + +- `f`가 `internal` 또는 `external`로 선언된 경우 실패합니다. +- `f`를 호출하는 데 어떤 인수를 사용해야 하는지 불분명합니다. +- `f`가 revert되면 속성이 실패합니다. + +일반적으로 어설션 사용 방법에 대한 [John Regehr의 권장 사항](https://blog.regehr.org/archives/1091)을 따르는 것이 좋습니다. + +- 어설션 확인 중에 부작용을 강제하지 마세요. 예: `assert(ChangeStateAndReturn() == 1)` +- 명백한 문장을 어설션하지 마세요. 예: `var`가 `uint`로 선언된 경우 `assert(var >= 0)` + +마지막으로, Echidna가 이를 감지할 수 없으므로(하지만 계약은 어쨌든 revert됩니다) `assert` 대신 `require`를 **사용하지 마세요**. + +### 요약: 어설션 확인 {#summary-assertion-checking} + +다음은 예시에 대한 Echidna 실행 요약입니다. + +```solidity +contract Incrementor { + uint private counter = 2**200; + + function inc(uint val) public returns (uint){ + uint tmp = counter; + counter += val; + assert (tmp <= counter); + return (counter - tmp); + } +} +``` + +```bash +echidna-test assert.sol --config config.yaml +Analyzing contract: assert.sol:Incrementor +assertion in inc: failed!💥 + Call sequence, shrinking (2596/5000): + inc(21711016731996786641919559689128982722488122124807605757398297001483711807488) + inc(7237005577332262213973186563042994240829374041602535252466099000494570602496) + inc(86844066927987146567678238756515930889952488499230423029593188005934847229952) + +Seed: 1806480648350826486 +``` + +Echidna는 이 함수가 큰 인수로 여러 번 호출될 경우 `inc`의 어설션이 실패할 수 있음을 발견했습니다. + +## Echidna 코퍼스 수집 및 수정하기 {#collecting-and-modifying-an-echidna-corpus} + +Echidna로 트랜잭션 코퍼스를 수집하고 사용하는 방법을 알아보겠습니다. 대상은 다음 스마트 계약인 [`magic.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/magic.sol)입니다. + +```solidity +contract C { + bool value_found = false; + function magic(uint magic_1, uint magic_2, uint magic_3, uint magic_4) public { + require(magic_1 == 42); + require(magic_2 == 129); + require(magic_3 == magic_4+333); + value_found = true; + return; + } + + function echidna_magic_values() public returns (bool) { + return !value_found; + } + +} +``` + +이 작은 예제는 Echidna가 상태 변수를 변경하기 위해 특정 값을 찾도록 강제합니다. 이는 퍼저에게는 어려운 일입니다( [Manticore](https://github.com/trailofbits/manticore)와 같은 심볼릭 실행 도구를 사용하는 것이 좋습니다). +Echidna를 실행하여 이를 확인할 수 있습니다. + +```bash +echidna-test magic.sol +... + +echidna_magic_values: passed! 🎉 + +Seed: 2221503356319272685 +``` + +하지만, 이 퍼징 캠페인을 실행할 때 Echidna를 사용하여 코퍼스를 수집할 수 있습니다. + +### 코퍼스 수집하기 {#collecting-a-corpus} + +코퍼스 수집을 활성화하려면 코퍼스 디렉터리를 만드세요. + +```bash +mkdir corpus-magic +``` + +그리고 [Echidna 구성 파일](https://github.com/crytic/echidna/wiki/Config) `config.yaml`: + +```yaml +coverage: true +corpusDir: "corpus-magic" +``` + +이제 도구를 실행하고 수집된 코퍼스를 확인할 수 있습니다. + +```bash +echidna-test magic.sol --config config.yaml +``` + +Echidna는 여전히 올바른 매직 값을 찾을 수 없지만 수집된 코퍼스를 살펴볼 수 있습니다. +예를 들어, 이러한 파일 중 하나는 다음과 같습니다. + +```json +[ + { + "_gas'": "0xffffffff", + "_delay": ["0x13647", "0xccf6"], + "_src": "00a329c0648769a73afac7f9381e08fb43dbea70", + "_dst": "00a329c0648769a73afac7f9381e08fb43dbea72", + "_value": "0x0", + "_call": { + "tag": "SolCall", + "contents": [ + "magic", + [ + { + "contents": [ + 256, + "93723985220345906694500679277863898678726808528711107336895287282192244575836" + ], + "tag": "AbiUInt" + }, + { + "contents": [256, "334"], + "tag": "AbiUInt" + }, + { + "contents": [ + 256, + "68093943901352437066264791224433559271778087297543421781073458233697135179558" + ], + "tag": "AbiUInt" + }, + { + "tag": "AbiUInt", + "contents": [256, "332"] + } + ] + ] + }, + "_gasprice'": "0xa904461f1" + } +] +``` + +분명히, 이 입력은 우리 속성의 실패를 유발하지 않을 것입니다. 하지만, 다음 단계에서 이를 위해 수정하는 방법을 알아보겠습니다. + +### 코퍼스 시딩하기 {#seeding-a-corpus} + +Echidna는 `magic` 함수를 처리하기 위해 약간의 도움이 필요합니다. 적절한 매개변수를 사용하도록 입력을 복사하고 수정할 것입니다. + +```bash +cp corpus/2712688662897926208.txt corpus/new.txt +``` + +`new.txt`를 수정하여 `magic(42,129,333,0)`을 호출할 것입니다. 이제 Echidna를 다시 실행할 수 있습니다. + +```bash +echidna-test magic.sol --config config.yaml +... +echidna_magic_values: failed!💥 + Call sequence: + magic(42,129,333,0) + + +Unique instructions: 142 +Unique codehashes: 1 +Seed: -7293830866560616537 + +``` + +이번에는 속성이 즉시 위반된다는 것을 발견했습니다. + +## 높은 가스 소비량을 가진 트랜잭션 찾기 {#finding-transactions-with-high-gas-consumption} + +Echidna를 사용하여 높은 가스 소비량을 가진 트랜잭션을 찾는 방법을 알아보겠습니다. 대상은 다음 스마트 계약입니다. + +```solidity +contract C { + uint state; + + function expensive(uint8 times) internal { + for(uint8 i=0; i < times; i++) + state = state + i; + } + + function f(uint x, uint y, uint8 times) public { + if (x == 42 && y == 123) + expensive(times); + else + state = 0; + } + + function echidna_test() public returns (bool) { + return true; + } + +} +``` + +여기서 `expensive`는 많은 가스를 소비할 수 있습니다. + +현재 Echidna는 항상 테스트할 속성이 필요합니다. 여기서 `echidna_test`는 항상 `true`를 반환합니다. +Echidna를 실행하여 이를 확인할 수 있습니다. + +``` +echidna-test gas.sol +... +echidna_test: passed! 🎉 + +Seed: 2320549945714142710 +``` + +### 가스 소비량 측정하기 {#measuring-gas-consumption} + +Echidna로 가스 소비량 측정을 활성화하려면 구성 파일 `config.yaml`을 만드세요. + +```yaml +estimateGas: true +``` + +이 예제에서는 결과를 더 쉽게 이해할 수 있도록 트랜잭션 시퀀스의 크기도 줄일 것입니다. + +```yaml +seqLen: 2 +estimateGas: true +``` + +### Echidna 실행하기 {#run-echidna-3} + +구성 파일이 생성되면 다음과 같이 Echidna를 실행할 수 있습니다. + +```bash +echidna-test gas.sol --config config.yaml +... +echidna_test: passed! 🎉 + +f used a maximum of 1333608 gas + Call sequence: + f(42,123,249) Gas price: 0x10d5733f0a Time delay: 0x495e5 Block delay: 0x88b2 + +Unique instructions: 157 +Unique codehashes: 1 +Seed: -325611019680165325 + +``` + +- 표시된 가스는 [HEVM](https://github.com/dapphub/dapptools/tree/master/src/hevm#hevm-)에서 제공하는 추정치입니다. + +### 가스 감소 호출 필터링하기 {#filtering-out-gas-reducing-calls} + +위의 **퍼징 캠페인 중 호출할 함수 필터링하기** 튜토리얼은 테스트에서 일부 함수를 제거하는 방법을 보여줍니다. +이는 정확한 가스 추정치를 얻는 데 중요할 수 있습니다. +다음 예시를 살펴보겠습니다. + +```solidity +contract C { + address [] addrs; + function push(address a) public { + addrs.push(a); + } + function pop() public { + addrs.pop(); + } + function clear() public{ + addrs.length = 0; + } + function check() public{ + for(uint256 i = 0; i < addrs.length; i++) + for(uint256 j = i+1; j < addrs.length; j++) + if (addrs[i] == addrs[j]) + addrs[j] = address(0x0); + } + function echidna_test() public returns (bool) { + return true; + } +} +``` + +Echidna가 모든 함수를 호출할 수 있다면 높은 가스 비용의 트랜잭션을 쉽게 찾을 수 없습니다. + +``` +echidna-test pushpop.sol --config config.yaml +... +pop used a maximum of 10746 gas +... +check used a maximum of 23730 gas +... +clear used a maximum of 35916 gas +... +push used a maximum of 40839 gas +``` + +비용이 `addrs`의 크기에 따라 달라지고 무작위 호출은 배열을 거의 비어 있게 만드는 경향이 있기 때문입니다. +그러나 `pop`과 `clear`를 블랙리스트에 추가하면 훨씬 더 좋은 결과를 얻을 수 있습니다. + +```yaml +filterBlacklist: true +filterFunctions: ["pop", "clear"] +``` + +``` +echidna-test pushpop.sol --config config.yaml +... +push used a maximum of 40839 gas +... +check used a maximum of 1484472 gas +``` + +### 요약: 높은 가스 소비량을 가진 트랜잭션 찾기 {#summary-finding-transactions-with-high-gas-consumption} + +`estimateGas` 구성 옵션을 사용하여 Echidna는 높은 가스 소비량을 가진 트랜잭션을 찾을 수 있습니다. + +```yaml +estimateGas: true +``` + +```bash +echidna-test contract.sol --config config.yaml +... +``` + +Echidna는 퍼징 캠페인이 끝나면 모든 기능에 대한 최대 가스 소비량과 함께 시퀀스를 보고합니다. diff --git a/public/content/translations/ko/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/index.md b/public/content/translations/ko/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/index.md new file mode 100644 index 00000000000..d8ba0720055 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/index.md @@ -0,0 +1,519 @@ +--- +title: "Manticore를 사용하여 스마트 계약 버그를 찾는 방법" +description: "Manticore를 사용하여 스마트 계약에서 버그를 자동으로 찾는 방법" +author: Trailofbits +lang: ko +tags: [ "Solidity", "스마트 계약", "보안", "테스트", "형식 검증" ] +skill: advanced +published: 2020-01-13 +source: Building secure contracts +sourceUrl: https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/manticore +--- + +이 튜토리얼의 목표는 Manticore를 사용하여 스마트 계약의 버그를 자동으로 찾는 방법을 보여주는 것입니다. + +## 설치 {#installation} + +Manticore를 사용하려면 Python 3.6 이상이 필요합니다. pip를 통해 설치하거나 docker를 사용하여 설치할 수 있습니다. + +### docker를 통한 Manticore {#manticore-through-docker} + +```bash +docker pull trailofbits/eth-security-toolbox +docker run -it -v "$PWD":/home/training trailofbits/eth-security-toolbox +``` + +_마지막 명령어는 현재 디렉터리에 액세스할 수 있는 docker에서 eth-security-toolbox를 실행합니다. 호스트에서 파일을 변경하고 docker의 파일에서 도구를 실행할 수 있습니다_ + +docker 내부에서 다음을 실행합니다. + +```bash +solc-select 0.5.11 +cd /home/trufflecon/ +``` + +### pip를 통한 Manticore {#manticore-through-pip} + +```bash +pip3 install --user manticore +``` + +solc 0.5.11을 권장합니다. + +### 스크립트 실행 {#running-a-script} + +python 3로 python 스크립트를 실행하려면: + +```bash +python3 script.py +``` + +## 동적 심볼릭 실행 소개 {#introduction-to-dynamic-symbolic-execution} + +### 동적 심볼릭 실행 요약 {#dynamic-symbolic-execution-in-a-nutshell} + +동적 심볼릭 실행(DSE)은 높은 수준의 시맨틱 인식을 통해 상태 공간을 탐색하는 프로그램 분석 기법입니다. 이 기법은 '경로 술어'라고 불리는 수학적 공식으로 표현되는 "프로그램 경로"의 발견을 기반으로 합니다. 개념적으로 이 기법은 두 단계로 경로 술어를 처리합니다. + +1. 프로그램 입력에 대한 제약 조건을 사용하여 구성됩니다. +2. 연관된 경로를 실행시키는 프로그램 입력을 생성하는 데 사용됩니다. + +이 접근 방식은 식별된 모든 프로그램 상태가 구체적인 실행 중에 트리거될 수 있다는 점에서 거짓 양성을 생성하지 않습니다. 예를 들어, 분석에서 정수 오버플로우를 발견하면 재현이 보장됩니다. + +### 경로 술어 예시 {#path-predicate-example} + +DSE가 어떻게 작동하는지 이해하기 위해 다음 예시를 살펴보겠습니다. + +```solidity +function f(uint a){ + + if (a == 65) { + // 버그가 존재함 + } + +} +``` + +`f()`는 두 개의 경로를 포함하므로 DSE는 두 개의 다른 경로 술어를 구성합니다. + +- 경로 1: `a == 65` +- 경로 2: `Not (a == 65)` + +각 경로 술어는 소위 [SMT 솔버](https://wikipedia.org/wiki/Satisfiability_modulo_theories)에 제공될 수 있는 수학적 공식이며, 이 솔버는 방정식을 풀려고 시도합니다. `경로 1`의 경우, 솔버는 `a = 65`로 경로를 탐색할 수 있다고 말할 것입니다. `경로 2`의 경우, 솔버는 `a`에 65가 아닌 다른 값을 할당할 수 있습니다(예: `a = 0`). + +### 속성 검증 {#verifying-properties} + +Manticore를 사용하면 각 경로의 모든 실행을 완벽하게 제어할 수 있습니다. 결과적으로 거의 모든 것에 임의의 제약 조건을 추가할 수 있습니다. 이 제어를 통해 계약에 대한 속성을 생성할 수 있습니다. + +다음 예시를 살펴보겠습니다. + +```solidity +function unsafe_add(uint a, uint b) returns(uint c){ + c = a + b; // 오버플로우 보호 없음 + return c; +} +``` + +여기 함수에서 탐색할 경로는 하나뿐입니다. + +- 경로 1: `c = a + b` + +Manticore를 사용하여 오버플로우를 확인하고 경로 술어에 제약 조건을 추가할 수 있습니다. + +- `c = a + b AND (c < a OR c < b)` + +위의 경로 술어를 실현 가능하게 하는 `a`와 `b`의 값을 찾을 수 있다면, 오버플로우를 찾았다는 의미입니다. 예를 들어, 솔버는 `a = 10 , b = MAXUINT256` 입력을 생성할 수 있습니다. + +수정된 버전을 고려해 보겠습니다. + +```solidity +function safe_add(uint a, uint b) returns(uint c){ + c = a + b; + require(c>=a); + require(c>=b); + return c; +} +``` + +오버플로우 검사와 관련된 공식은 다음과 같습니다. + +- `c = a + b AND (c >= a) AND (c=>b) AND (c < a OR c < b)` + +이 공식은 풀 수 없습니다. 다시 말해, 이것은 `safe_add`에서 `c`가 항상 증가한다는 증명입니다. + +따라서 DSE는 코드에 대한 임의의 제약 조건을 확인할 수 있는 강력한 도구입니다. + +## Manticore에서 실행하기 {#running-under-manticore} + +Manticore API를 사용하여 스마트 계약을 탐색하는 방법을 살펴보겠습니다. 대상은 다음 스마트 계약 [`example.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example.sol)입니다. + +```solidity +pragma solidity >=0.4.24 <0.6.0; + +contract Simple { + function f(uint a) payable public{ + if (a == 65) { + revert(); + } + } +} +``` + +### 독립 실행형 탐색 실행 {#run-a-standalone-exploration} + +다음 명령을 사용하여 스마트 계약에서 직접 Manticore를 실행할 수 있습니다(`project`는 솔리디티 파일 또는 프로젝트 디렉터리가 될 수 있음): + +```bash +$ manticore project +``` + +다음과 같은 테스트 케이스의 출력을 얻게 됩니다(순서는 변경될 수 있음): + +``` +... +... m.c.manticore:INFO: Generated testcase No. 0 - STOP +... m.c.manticore:INFO: Generated testcase No. 1 - REVERT +... m.c.manticore:INFO: Generated testcase No. 2 - RETURN +... m.c.manticore:INFO: Generated testcase No. 3 - REVERT +... m.c.manticore:INFO: Generated testcase No. 4 - STOP +... m.c.manticore:INFO: Generated testcase No. 5 - REVERT +... m.c.manticore:INFO: Generated testcase No. 6 - REVERT +... m.c.manticore:INFO: Results in /home/ethsec/workshops/Automated Smart Contracts Audit - TruffleCon 2018/manticore/examples/mcore_t6vi6ij3 +... +``` + +추가 정보가 없으면 Manticore는 계약에서 새로운 경로를 탐색하지 않을 때까지 새로운 심볼릭 +트랜잭션으로 계약을 탐색합니다. Manticore는 실패한 트랜잭션(예: revert 후) 다음에는 새로운 트랜잭션을 실행하지 않습니다. + +Manticore는 `mcore_*` 디렉터리에 정보를 출력합니다. 무엇보다도 이 디렉터리에서 다음을 찾을 수 있습니다. + +- `global.summary`: 커버리지 및 컴파일러 경고 +- `test_XXXXX.summary`: 커버리지, 마지막 지침, 테스트 케이스당 계정 잔액 +- `test_XXXXX.tx`: 테스트 케이스당 트랜잭션의 상세 목록 + +여기서 Manticore는 7개의 테스트 케이스를 찾았으며, 이는 다음에 해당합니다(파일 이름 순서는 변경될 수 있음): + +| | 트랜잭션 0 | 트랜잭션 1 | 트랜잭션 2 | 결과 | +| :-------------------------------------------------------: | :----: | :------------------------: | -------------------------- | :----: | +| **test_00000000.tx** | 계약 생성 | f(!=65) | f(!=65) | STOP | +| **test_00000001.tx** | 계약 생성 | 폴백 함수 | | REVERT | +| **test_00000002.tx** | 계약 생성 | | | RETURN | +| **test_00000003.tx** | 계약 생성 | f(65) | | REVERT | +| **test_00000004.tx** | 계약 생성 | f(!=65) | | STOP | +| **test_00000005.tx** | 계약 생성 | f(!=65) | f(65) | REVERT | +| **test_00000006.tx** | 계약 생성 | f(!=65) | 폴백 함수 | REVERT | + +_탐색 요약에서 f(!=65)는 65와 다른 임의의 값으로 f가 호출되었음을 나타냅니다._ + +보시다시피 Manticore는 성공하거나 되돌려진 모든 트랜잭션에 대해 고유한 테스트 케이스를 생성합니다. + +빠른 코드 탐색을 원한다면 `--quick-mode` 플래그를 사용하세요(버그 탐지기, 가스 계산 등을 비활성화합니다). + +### API를 통해 스마트 계약 조작하기 {#manipulate-a-smart-contract-through-the-api} + +이 섹션에서는 Manticore Python API를 통해 스마트 계약을 조작하는 방법을 자세히 설명합니다. python 확장자 `*.py`로 새 파일을 만들고 이 파일에 API 명령(기본 사항은 아래에서 설명)을 추가하여 필요한 코드를 작성한 다음 `$ python3 *.py` 명령으로 실행할 수 있습니다. 또한 아래 명령을 python 콘솔에서 직접 실행할 수 있습니다. 콘솔을 실행하려면 `$ python3` 명령을 사용하세요. + +### 계정 생성 {#creating-accounts} + +가장 먼저 해야 할 일은 다음 명령으로 새 블록체인을 시작하는 것입니다. + +```python +from manticore.ethereum import ManticoreEVM + +m = ManticoreEVM() +``` + +[m.create_account](https://manticore.readthedocs.io/en/latest/evm.html?highlight=create_account#manticore.ethereum.ManticoreEVM.create_account)를 사용하여 비계약 계정을 생성합니다. + +```python +user_account = m.create_account(balance=1000) +``` + +[m.solidity_create_contract](https://manticore.readthedocs.io/en/latest/evm.html?highlight=solidity_create#manticore.ethereum.ManticoreEVM.create_contract)를 사용하여 솔리디티 계약을 배포할 수 있습니다. + +```solidity +source_code = ''' +pragma solidity >=0.4.24 <0.6.0; +contract Simple { + function f(uint a) payable public{ + if (a == 65) { + revert(); + } + } +} +''' +# 계약 초기화 +contract_account = m.solidity_create_contract(source_code, owner=user_account) +``` + +#### 요약 {#summary} + +- [m.create_account](https://manticore.readthedocs.io/en/latest/evm.html?highlight=create_account#manticore.ethereum.ManticoreEVM.create_account) 및 [m.solidity_create_contract](https://manticore.readthedocs.io/en/latest/evm.html?highlight=solidity_create#manticore.ethereum.ManticoreEVM.create_contract)를 사용하여 사용자 계정과 계약 계정을 생성할 수 있습니다. + +### 트랜잭션 실행 {#executing-transactions} + +Manticore는 두 가지 유형의 트랜잭션을 지원합니다. + +- 원시 트랜잭션: 모든 함수를 탐색합니다. +- 명명된 트랜잭션: 하나의 함수만 탐색합니다. + +#### 원시 트랜잭션 {#raw-transaction} + +원시 트랜잭션은 [m.transaction](https://manticore.readthedocs.io/en/latest/evm.html?highlight=transaction#manticore.ethereum.ManticoreEVM.transaction)을 사용하여 실행됩니다. + +```python +m.transaction(caller=user_account, + address=contract_account, + data=data, + value=value) +``` + +트랜잭션의 발신자, 주소, 데이터 또는 값은 구체적이거나 심볼릭일 수 있습니다. + +- [m.make_symbolic_value](https://manticore.readthedocs.io/en/latest/evm.html?highlight=make_symbolic_value#manticore.ethereum.ManticoreEVM.make_symbolic_value)는 심볼릭 값을 생성합니다. +- [m.make_symbolic_buffer(size)](https://manticore.readthedocs.io/en/latest/evm.html?highlight=make_symbolic_buffer#manticore.ethereum.ManticoreEVM.make_symbolic_buffer)는 심볼릭 바이트 배열을 생성합니다. + +예를 들어, + +```python +symbolic_value = m.make_symbolic_value() +symbolic_data = m.make_symbolic_buffer(320) +m.transaction(caller=user_account, + address=contract_address, + data=symbolic_data, + value=symbolic_value) +``` + +데이터가 심볼릭인 경우, Manticore는 트랜잭션 실행 중에 계약의 모든 함수를 탐색합니다. 함수 선택이 어떻게 작동하는지 이해하려면 [Hands on the Ethernaut CTF](https://blog.trailofbits.com/2017/11/06/hands-on-the-ethernaut-ctf/) 기사의 폴백 함수 설명을 참조하면 도움이 됩니다. + +#### 명명된 트랜잭션 {#named-transaction} + +함수는 이름을 통해 실행할 수 있습니다. +`f(uint var)`를 심볼릭 값, user_account에서 0 이더로 실행하려면 다음을 사용합니다. + +```python +symbolic_var = m.make_symbolic_value() +contract_account.f(symbolic_var, caller=user_account, value=0) +``` + +트랜잭션의 `value`가 지정되지 않은 경우 기본값은 0입니다. + +#### 요약 {#summary-1} + +- 트랜잭션의 인수는 구체적이거나 심볼릭일 수 있습니다. +- 원시 트랜잭션은 모든 함수를 탐색합니다. +- 함수는 이름으로 호출할 수 있습니다. + +### 작업 공간 {#workspace} + +`m.workspace`는 생성된 모든 파일의 출력 디렉터리로 사용되는 디렉터리입니다. + +```python +print("결과는 {}에 있습니다".format(m.workspace)) +``` + +### 탐색 종료 {#terminate-the-exploration} + +탐색을 중지하려면 [m.finalize()](https://manticore.readthedocs.io/en/latest/evm.html?highlight=finalize#manticore.ethereum.ManticoreEVM.finalize)를 사용합니다. 이 메서드가 호출되면 더 이상 트랜잭션을 보내서는 안 되며, Manticore는 탐색된 각 경로에 대한 테스트 케이스를 생성합니다. + +### 요약: Manticore에서 실행하기 {#summary-running-under-manticore} + +이전의 모든 단계를 종합하면 다음과 같습니다. + +```python +from manticore.ethereum import ManticoreEVM + +m = ManticoreEVM() + +with open('example.sol') as f: + source_code = f.read() + +user_account = m.create_account(balance=1000) +contract_account = m.solidity_create_contract(source_code, owner=user_account) + +symbolic_var = m.make_symbolic_value() +contract_account.f(symbolic_var) + +print("결과는 {}에 있습니다".format(m.workspace)) +m.finalize() # 탐색 중지 +``` + +위의 모든 코드는 [`example_run.py`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example_run.py)에서 찾을 수 있습니다. + +## 오류 발생 경로 가져오기 {#getting-throwing-paths} + +이제 `f()`에서 예외를 발생시키는 경로에 대한 특정 입력을 생성합니다. 대상은 여전히 다음 스마트 계약 [`example.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example.sol)입니다. + +```solidity +pragma solidity >=0.4.24 <0.6.0; +contract Simple { + function f(uint a) payable public{ + if (a == 65) { + revert(); + } + } +} +``` + +### 상태 정보 사용 {#using-state-information} + +실행된 각 경로에는 블록체인의 상태가 있습니다. 상태는 준비되었거나 종료되었으며, 이는 THROW 또는 REVERT 명령에 도달했음을 의미합니다. + +- [m.ready_states](https://manticore.readthedocs.io/en/latest/states.html#accessing): 준비된 상태(REVERT/INVALID를 실행하지 않음)의 목록 +- [m.killed_states](https://manticore.readthedocs.io/en/latest/states.html#accessings): 종료된 상태의 목록 +- [m.all_states](https://manticore.readthedocs.io/en/latest/states.html#accessings): 모든 상태 + +```python +for state in m.all_states: + # 상태로 무언가를 수행 +``` + +상태 정보에 액세스할 수 있습니다. 예를 들어, + +- `state.platform.get_balance(account.address)`: 계정의 잔액 +- `state.platform.transactions`: 트랜잭션 목록 +- `state.platform.transactions[-1].return_data`: 마지막 트랜잭션에서 반환된 데이터 + +마지막 트랜잭션에서 반환된 데이터는 배열이며, 예를 들어 ABI.deserialize를 사용하여 값으로 변환할 수 있습니다. + +```python +data = state.platform.transactions[0].return_data +data = ABI.deserialize("uint", data) +``` + +### 테스트 케이스 생성 방법 {#how-to-generate-testcase} + +[m.generate_testcase(state, name)](https://manticore.readthedocs.io/en/latest/evm.html?highlight=generate_testcase#manticore.ethereum.ManticoreEVM.generate_testcase)를 사용하여 테스트 케이스를 생성합니다. + +```python +m.generate_testcase(state, 'BugFound') +``` + +### 요약 {#summary-2} + +- m.all_states로 상태를 반복할 수 있습니다. +- `state.platform.get_balance(account.address)`는 계정의 잔액을 반환합니다. +- `state.platform.transactions`는 트랜잭션 목록을 반환합니다. +- `transaction.return_data`는 반환된 데이터입니다. +- `m.generate_testcase(state, name)`은 상태에 대한 입력을 생성합니다. + +### 요약: 오류 발생 경로 가져오기 {#summary-getting-throwing-path} + +```python +from manticore.ethereum import ManticoreEVM + +m = ManticoreEVM() + +with open('example.sol') as f: + source_code = f.read() + +user_account = m.create_account(balance=1000) +contract_account = m.solidity_create_contract(source_code, owner=user_account) + +symbolic_var = m.make_symbolic_value() +contract_account.f(symbolic_var) + +## 실행이 REVERT 또는 INVALID로 끝나는지 확인 + +for state in m.terminated_states: + last_tx = state.platform.transactions[-1] + if last_tx.result in ['REVERT', 'INVALID']: + print('오류 발견 {}'.format(m.workspace)) + m.generate_testcase(state, 'ThrowFound') +``` + +위의 모든 코드는 [`example_run.py`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example_run.py)에서 찾을 수 있습니다. + +_참고: terminated_state에서 반환된 모든 상태의 결과에 REVERT 또는 INVALID가 있으므로 훨씬 더 간단한 스크립트를 생성할 수 있었습니다. 이 예시는 API 조작 방법을 보여주기 위한 것입니다._ + +## 제약 조건 추가 {#adding-constraints} + +탐색을 제한하는 방법을 살펴보겠습니다. `f()`의 개발문서에 `a == 65`로 함수가 호출되지 않는다고 명시되어 있다고 가정합니다. +따라서 `a == 65`인 버그는 실제 버그가 아닙니다. 대상은 여전히 다음 스마트 계약 [`example.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example.sol)입니다. + +```solidity +pragma solidity >=0.4.24 <0.6.0; +contract Simple { + function f(uint a) payable public{ + if (a == 65) { + revert(); + } + } +} +``` + +### 연산자 {#operators} + +[Operators](https://github.com/trailofbits/manticore/blob/master/manticore/core/smtlib/operators.py) 모듈은 제약 조건 조작을 용이하게 하며, 무엇보다도 다음을 제공합니다. + +- Operators.AND, +- Operators.OR, +- Operators.UGT (부호 없는 초과), +- Operators.UGE (부호 없는 이상), +- Operators.ULT (부호 없는 미만), +- Operators.ULE (부호 없는 이하). + +모듈을 가져오려면 다음을 사용합니다. + +```python +from manticore.core.smtlib import Operators +``` + +`Operators.CONCAT`는 배열을 값에 연결하는 데 사용됩니다. 예를 들어, 트랜잭션의 return_data를 다른 값과 비교하려면 값으로 변경해야 합니다. + +```python +last_return = Operators.CONCAT(256, *last_return) +``` + +### 제약 조건 {#state-constraint} + +제약 조건을 전역적으로 또는 특정 상태에 사용할 수 있습니다. + +#### 전역 제약 조건 {#state-constraint} + +`m.constrain(constraint)`를 사용하여 전역 제약 조건을 추가합니다. +예를 들어, 심볼릭 주소에서 계약을 호출하고 이 주소를 특정 값으로 제한할 수 있습니다. + +```python +symbolic_address = m.make_symbolic_value() +m.constraint(Operators.OR(symbolic == 0x41, symbolic_address == 0x42)) +m.transaction(caller=user_account, + address=contract_account, + data=m.make_symbolic_buffer(320), + value=0) +``` + +#### 상태 제약 조건 {#state-constraint} + +[state.constrain(constraint)](https://manticore.readthedocs.io/en/latest/states.html?highlight=StateBase#manticore.core.state.StateBase.constrain)를 사용하여 특정 상태에 제약 조건을 추가합니다. +탐색 후 상태를 제한하여 속성을 확인하는 데 사용할 수 있습니다. + +### 제약 조건 확인 {#checking-constraint} + +`solver.check(state.constraints)`를 사용하여 제약 조건이 여전히 실현 가능한지 확인합니다. +예를 들어, 다음은 symbolic_value를 65와 다르게 제약하고 상태가 여전히 실현 가능한지 확인합니다. + +```python +state.constrain(symbolic_var != 65) +if solver.check(state.constraints): + # 상태가 실현 가능함 +``` + +### 요약: 제약 조건 추가 {#summary-adding-constraints} + +이전 코드에 제약 조건을 추가하면 다음과 같습니다. + +```python +from manticore.ethereum import ManticoreEVM +from manticore.core.smtlib.solver import Z3Solver + +solver = Z3Solver.instance() + +m = ManticoreEVM() + +with open("example.sol") as f: + source_code = f.read() + +user_account = m.create_account(balance=1000) +contract_account = m.solidity_create_contract(source_code, owner=user_account) + +symbolic_var = m.make_symbolic_value() +contract_account.f(symbolic_var) + +no_bug_found = True + +## 실행이 REVERT 또는 INVALID로 끝나는지 확인 + +for state in m.terminated_states: + last_tx = state.platform.transactions[-1] + if last_tx.result in ['REVERT', 'INVALID']: + # a == 65인 경로는 고려하지 않음 + condition = symbolic_var != 65 + if m.generate_testcase(state, name="BugFound", only_if=condition): + print(f'버그를 찾았으며, 결과는 {m.workspace}에 있습니다') + no_bug_found = False + +if no_bug_found: + print(f'버그를 찾지 못했습니다') +``` + +위의 모든 코드는 [`example_run.py`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example_run.py)에서 찾을 수 있습니다. diff --git a/public/content/translations/ko/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/index.md b/public/content/translations/ko/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/index.md new file mode 100644 index 00000000000..1e915156ec5 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/index.md @@ -0,0 +1,233 @@ +--- +title: "Slither를 사용하여 스마트 계약 버그를 찾는 방법" +description: "Slither를 사용하여 스마트 계약에서 자동으로 버그를 찾는 방법" +author: Trailofbits +lang: ko +tags: [ "Solidity", "스마트 계약", "보안", "테스트" ] +skill: advanced +published: 2020-06-09 +source: Building secure contracts +sourceUrl: https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/slither +--- + +## Slither 사용 방법 {#how-to-use-slither} + +이 튜토리얼의 목표는 Slither를 사용하여 스마트 계약에서 자동으로 버그를 찾는 방법을 보여주는 것입니다. + +- [설치](#installation) +- [커맨드 라인 사용법](#command-line) +- [정적 분석 소개](#static-analysis): 정적 분석에 대한 간략한 소개 +- [API](#api-basics): Python API 설명 + +## 설치 {#installation} + +Slither에는 Python 3.6 이상이 필요합니다. pip를 통해 설치하거나 docker를 사용하여 설치할 수 있습니다. + +pip를 통한 Slither: + +```bash +pip3 install --user slither-analyzer +``` + +docker를 통한 Slither: + +```bash +docker pull trailofbits/eth-security-toolbox +docker run -it -v "$PWD":/home/trufflecon trailofbits/eth-security-toolbox +``` + +_마지막 명령어는 현재 디렉터리에 액세스할 수 있는 docker에서 eth-security-toolbox를 실행합니다. 호스트에서 파일을 변경하고 docker의 파일에서 도구를 실행할 수 있습니다_ + +docker 내부에서 다음을 실행합니다. + +```bash +solc-select 0.5.11 +cd /home/trufflecon/ +``` + +### 스크립트 실행 {#running-a-script} + +python 3로 python 스크립트를 실행하려면: + +```bash +python3 script.py +``` + +### 커맨드 라인 {#command-line} + +**커맨드 라인 대 사용자 정의 스크립트.** Slither는 많은 일반적인 버그를 찾는 사전 정의된 감지기 세트와 함께 제공됩니다. 커맨드 라인에서 Slither를 호출하면 모든 감지기가 실행되며 정적 분석에 대한 자세한 지식이 필요하지 않습니다. + +```bash +slither project_paths +``` + +감지기 외에도 Slither는 [프린터](https://github.com/crytic/slither#printers) 및 [도구](https://github.com/crytic/slither#tools)를 통해 코드 검토 기능을 제공합니다. + +[crytic.io](https://github.com/crytic)를 사용하여 비공개 감지기 및 GitHub 통합에 액세스하세요. + +## 정적 분석 {#static-analysis} + +Slither 정적 분석 프레임워크의 기능과 디자인은 블로그 게시물([1](https://blog.trailofbits.com/2018/10/19/slither-a-solidity-static-analysis-framework/), [2](https://blog.trailofbits.com/2019/05/27/slither-the-leading-static-analyzer-for-smart-contracts/)) 및 [학술 논문](https://github.com/trailofbits/publications/blob/master/papers/wetseb19.pdf)에 설명되어 있습니다. + +정적 분석은 다양한 형태로 존재합니다. 아마도 [clang](https://clang-analyzer.llvm.org/) 및 [gcc](https://lwn.net/Articles/806099/)와 같은 컴파일러가 이러한 연구 기술에 의존한다는 것을 알고 계실 것입니다. 그러나 이는 ([Infer](https://fbinfer.com/), [CodeClimate](https://codeclimate.com/), [FindBugs](http://findbugs.sourceforge.net/) 및 [Frama-C](https://frama-c.com/) 및 [Polyspace](https://www.mathworks.com/products/polyspace.html)와 같은 형식적 방법에 기반한 도구)의 기반이 되기도 합니다. + +여기서 정적 분석 기법과 연구자를 철저하게 검토하지는 않을 것입니다. 대신 Slither가 작동하는 방식을 이해하는 데 필요한 것에 초점을 맞춰 버그를 찾고 코드를 이해하는 데 더 효과적으로 사용할 수 있도록 할 것입니다. + +- [코드 표현](#code-representation) +- [코드 분석](#analysis) +- [중간 표현](#intermediate-representation) + +### 코드 표현 {#code-representation} + +단일 실행 경로에 대해 추론하는 동적 분석과 달리 정적 분석은 모든 경로에 대해 한 번에 추론합니다. 이를 위해 다른 코드 표현에 의존합니다. 가장 일반적인 두 가지는 추상 구문 트리(AST)와 제어 흐름 그래프(CFG)입니다. + +### 추상 구문 트리(AST) {#abstract-syntax-trees-ast} + +AST는 컴파일러가 코드를 구문 분석할 때마다 사용됩니다. 이는 아마도 정적 분석을 수행할 수 있는 가장 기본적인 구조일 것입니다. + +간단히 말해, AST는 일반적으로 각 리프가 변수 또는 상수를 포함하고 내부 노드가 피연산자 또는 제어 흐름 작업인 구조화된 트리입니다. 다음 코드를 고려하십시오. + +```solidity +function safeAdd(uint a, uint b) pure internal returns(uint){ + if(a + b <= a){ + revert(); + } + return a + b; +} +``` + +해당 AST는 다음에 표시됩니다. + +![AST](./ast.png) + +Slither는 solc에서 내보낸 AST를 사용합니다. + +빌드하기는 간단하지만 AST는 중첩된 구조입니다. 때로는 이것이 분석하기에 가장 간단하지 않습니다. `a + b <= a` 표현식에서 사용되는 연산을 식별하려면 먼저 `<=`를 분석한 다음 `+`를 분석해야 합니다. 일반적인 접근 방식은 소위 방문자 패턴을 사용하는 것인데, 이는 트리를 재귀적으로 탐색합니다. Slither는 [`ExpressionVisitor`](https://github.com/crytic/slither/blob/master/slither/visitors/expression/expression.py)에 일반 방문자를 포함합니다. + +다음 코드는 `ExpressionVisitor`를 사용하여 표현식에 덧셈이 포함되어 있는지 감지합니다. + +```python +from slither.visitors.expression.expression import ExpressionVisitor +from slither.core.expressions.binary_operation import BinaryOperationType + +class HasAddition(ExpressionVisitor): + + def result(self): + return self._result + + def _post_binary_operation(self, expression): + if expression.type == BinaryOperationType.ADDITION: + self._result = True + +visitor = HasAddition(expression) # expression은 테스트할 표현식입니다 +print(f'표현식 {expression}에 덧셈이 있습니다: {visitor.result()}') +``` + +### 제어 흐름 그래프(CFG) {#control-flow-graph-cfg} + +두 번째로 흔한 코드 표현은 제어 흐름 그래프(CFG)입니다. 이름에서 알 수 있듯이 모든 실행 경로를 노출하는 그래프 기반 표현입니다. 각 노드에는 하나 또는 여러 개의 명령이 포함됩니다. 그래프의 에지는 제어 흐름 연산(if/then/else, loop 등)을 나타냅니다. 이전 예제의 CFG는 다음과 같습니다. + +![CFG](./cfg.png) + +CFG는 대부분의 분석이 구축되는 기반 표현입니다. + +다른 많은 코드 표현이 존재합니다. 각 표현은 수행하려는 분석에 따라 장단점이 있습니다. + +### 분석 {#analysis} + +Slither로 수행할 수 있는 가장 간단한 분석 유형은 구문 분석입니다. + +### 구문 분석 {#syntax-analysis} + +Slither는 패턴 매칭과 유사한 접근 방식을 사용하여 코드의 다양한 구성 요소와 그 표현을 탐색하여 불일치와 결함을 찾을 수 있습니다. + +예를 들어 다음 감지기는 구문 관련 문제를 찾습니다. + +- [상태 변수 섀도잉](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing): 모든 상태 변수를 반복하고 상속된 계약의 변수를 섀도잉하는지 확인합니다([state.py#L51-L62](https://github.com/crytic/slither/blob/0441338e055ab7151b30ca69258561a5a793f8ba/slither/detectors/shadowing/state.py#L51-L62)) + +- [잘못된 ERC20 인터페이스](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface): 잘못된 ERC20 함수 시그니처를 찾습니다([incorrect_erc20_interface.py#L34-L55](https://github.com/crytic/slither/blob/0441338e055ab7151b30ca69258561a5a793f8ba/slither/detectors/erc/incorrect_erc20_interface.py#L34-L55)) + +### 시맨틱 분석 {#semantic-analysis} + +구문 분석과 대조적으로, 시맨틱 분석은 더 깊이 들어가 코드의 '의미'를 분석합니다. 이 계열에는 몇 가지 광범위한 유형의 분석이 포함됩니다. 이는 더 강력하고 유용한 결과로 이어지지만 작성하기는 더 복잡합니다. + +시맨틱 분석은 가장 진보된 취약점 탐지에 사용됩니다. + +#### 데이터 종속성 분석 {#fixed-point-computation} + +`variable_a`의 값이 `variable_b`의 영향을 받는 경로가 있는 경우 `variable_a` 변수는 `variable_b`에 데이터 종속적이라고 합니다. + +다음 코드에서 `variable_a`는 `variable_b`에 종속됩니다. + +```solidity +// ... +variable_a = variable_b + 1; +``` + +Slither는 중간 표현(이후 섹션에서 논의) 덕분에 내장된 [데이터 종속성](https://github.com/crytic/slither/wiki/data-dependency) 기능을 제공합니다. + +데이터 종속성 사용의 예는 [위험한 엄격한 동등성 감지기](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities)에서 찾을 수 있습니다. 여기서 Slither는 위험한 값에 대한 엄격한 동등성 비교를 찾고([incorrect_strict_equality.py#L86-L87](https://github.com/crytic/slither/blob/6d86220a53603476f9567c3358524ea4db07fb25/slither/detectors/statements/incorrect_strict_equality.py#L86-L87)), 공격자가 계약을 함정에 빠뜨리는 것을 방지하기 위해 `==` 대신 `>=` 또는 `<=`를 사용해야 한다고 사용자에게 알립니다. 무엇보다도 감지기는 `balanceOf(address)` 호출의 반환 값을 위험한 것으로 간주하고([incorrect_strict_equality.py#L63-L64](https://github.com/crytic/slither/blob/6d86220a53603476f9567c3358524ea4db07fb25/slither/detectors/statements/incorrect_strict_equality.py#L63-L64)), 데이터 종속성 엔진을 사용하여 그 사용을 추적합니다. + +#### 고정 소수점 계산 {#fixed-point-computation} + +분석이 CFG를 탐색하고 에지를 따라가면 이미 방문한 노드를 볼 가능성이 높습니다. 예를 들어, 아래와 같이 루프가 표시되는 경우: + +```solidity +for(uint i; i < range; ++){ + variable_a += 1 +} +``` + +분석은 언제 중지해야 하는지 알아야 합니다. 여기에는 두 가지 주요 전략이 있습니다: (1) 각 노드에서 유한한 횟수만큼 반복, (2) 소위 _고정점_ 계산. 고정점은 기본적으로 이 노드를 분석해도 의미 있는 정보가 제공되지 않음을 의미합니다. + +사용된 고정점의 예는 재진입 감지기에서 찾을 수 있습니다. Slither는 노드를 탐색하고 외부 호출, 저장 공간에 대한 쓰기 및 읽기를 찾습니다. 고정점에 도달하면([reentrancy.py#L125-L131](https://github.com/crytic/slither/blob/master/slither/detectors/reentrancy/reentrancy.py#L125-L131)), 탐색을 중지하고 결과를 분석하여 다양한 재진입 패턴([reentrancy_benign.py](https://github.com/crytic/slither/blob/b275bcc824b1b932310cf03b6bfb1a1fef0ebae1/slither/detectors/reentrancy/reentrancy_benign.py), [reentrancy_read_before_write.py](https://github.com/crytic/slither/blob/b275bcc824b1b932310cf03b6bfb1a1fef0ebae1/slither/detectors/reentrancy/reentrancy_read_before_write.py), [reentrancy_eth.py](https://github.com/crytic/slither/blob/b275bcc824b1b932310cf03b6bfb1a1fef0ebae1/slither/detectors/reentrancy/reentrancy_eth.py))을 통해 재진입이 있는지 확인합니다. + +효율적인 고정 소수점 계산을 사용하여 분석을 작성하려면 분석이 정보를 전파하는 방식에 대한 충분한 이해가 필요합니다. + +### 중간 표현 {#intermediate-representation} + +중간 표현(IR)은 원래 언어보다 정적 분석에 더 적합하도록 만들어진 언어입니다. Slither는 솔리디티를 자체 IR인 [SlithIR](https://github.com/crytic/slither/wiki/SlithIR)로 변환합니다. + +기본적인 검사만 작성하려는 경우 SlithIR을 이해할 필요는 없습니다. 그러나 고급 시맨틱 분석을 작성하려는 경우 유용할 것입니다. [SlithIR](https://github.com/crytic/slither/wiki/Printer-documentation#slithir) 및 [SSA](https://github.com/crytic/slither/wiki/Printer-documentation#slithir-ssa) 프린터는 코드가 어떻게 변환되는지 이해하는 데 도움이 됩니다. + +## API 기본 {#api-basics} + +Slither에는 계약 및 해당 기능의 기본 속성을 탐색할 수 있는 API가 있습니다. + +코드베이스를 로드하려면: + +```python +from slither import Slither +slither = Slither('/path/to/project') + +``` + +### 계약 및 함수 탐색 {#exploring-contracts-and-functions} + +`Slither` 객체에는 다음이 있습니다. + +- `contracts (list(Contract)`: 계약 목록 +- `contracts_derived (list(Contract)`: 다른 계약에 의해 상속되지 않은 계약 목록(계약의 하위 집합) +- `get_contract_from_name (str)`: 이름으로 계약 반환 + +`Contract` 객체에는 다음이 있습니다. + +- `name (str)`: 계약의 이름 +- `functions (list(Function))`: 함수 목록 +- `modifiers (list(Modifier))`: 수정자 목록 +- `all_functions_called (list(Function/Modifier))`: 계약에서 도달할 수 있는 모든 내부 함수 목록 +- `inheritance (list(Contract))`: 상속된 계약 목록 +- `get_function_from_signature (str)`: 시그니처에서 함수 반환 +- `get_modifier_from_signature (str)`: 시그니처에서 수정자 반환 +- `get_state_variable_from_name (str)`: 이름으로 상태 변수 반환 + +`Function` 또는 `Modifier` 객체에는 다음이 있습니다. + +- `name (str)`: 함수의 이름 +- `contract (contract)`: 함수가 선언된 계약 +- `nodes (list(Node))`: 함수/수정자의 CFG를 구성하는 노드 목록 +- `entry_point (Node)`: CFG의 진입점 +- `variables_read (list(Variable))`: 읽은 변수 목록 +- `variables_written (list(Variable))`: 쓴 변수 목록 +- `state_variables_read (list(StateVariable))`: 읽은 상태 변수 목록(variables`read의 하위 집합) +- `state_variables_written (list(StateVariable))`: 쓴 상태 변수 목록(variables`written의 하위 집합) diff --git a/public/content/translations/ko/developers/tutorials/how-to-use-tellor-as-your-oracle/index.md b/public/content/translations/ko/developers/tutorials/how-to-use-tellor-as-your-oracle/index.md new file mode 100644 index 00000000000..fee4e0a38bf --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/how-to-use-tellor-as-your-oracle/index.md @@ -0,0 +1,81 @@ +--- +title: "Tellor를 오라클로 설정하는 방법" +description: "Tellor 오라클을 프로토콜에 통합하는 시작 가이드" +author: "Tellor" +lang: ko +tags: [ "Solidity", "스마트 계약", "오라클" ] +skill: beginner +published: 2021-06-29 +source: Tellor Docs +sourceUrl: https://docs.tellor.io/tellor/ +--- + +깜짝 퀴즈: 프로토콜이 거의 완성되었지만, 오프체인 데이터에 접근하기 위해 오라클이 필요합니다... 어떻게 해야 할까요? + +## (소프트) 선수 요건 {#soft-prerequisites} + +이 게시물은 오라클 피드에 최대한 간단하고 직관적으로 접근할 수 있도록 하는 것을 목표로 합니다. 즉, 오라클 측면에 집중하기 위해 여러분의 코딩 기술 수준에 대해 다음과 같이 가정합니다. + +가정 사항: + +- 터미널을 탐색할 수 있습니다 +- npm이 설치되어 있습니다 +- npm을 사용하여 종속성을 관리하는 방법을 알고 있습니다 + +Tellor는 구현 준비가 된 실시간 오픈소스 오라클입니다. 이 초보자 가이드는 Tellor를 얼마나 쉽게 시작하고 실행할 수 있는지 보여주기 위한 것으로, 프로젝트에 완전히 탈중앙화되고 검열 저항적인 오라클을 제공합니다. + +## 개요 {#overview} + +Tellor는 당사자들이 오프체인 데이터 포인트(예: BTC/USD)의 값을 요청하고, 보고자들이 이 값을 온체인 데이터 뱅크에 추가하기 위해 경쟁하는 오라클 시스템으로, 모든 이더리움 스마트 계약에서 접근할 수 있습니다. 이 데이터 뱅크에 대한 입력은 스테이킹된 보고자들의 네트워크에 의해 보호됩니다. Tellor는 암호 경제학적 인센티브 메커니즘을 활용하여 보고자들의 정직한 데이터 제출에 보상하고, Tellor의 토큰인 Tributes(TRB) 발행과 분쟁 메커니즘을 통해 악의적인 행위자를 처벌합니다. + +이 튜토리얼에서는 다음을 다룰 것입니다: + +- 시작하고 실행하는 데 필요한 초기 툴킷 설정. +- 간단한 예제를 살펴봅니다. +- 현재 Tellor를 테스트할 수 있는 네트워크의 테스트넷 주소를 나열합니다. + +## UsingTellor {#usingtellor} + +가장 먼저 해야 할 일은 Tellor를 오라클로 사용하는 데 필요한 기본 도구를 설치하는 것입니다. [이 패키지](https://github.com/tellor-io/usingtellor)를 사용하여 Tellor 사용자 계약을 설치하세요: + +`npm install usingtellor` + +설치가 완료되면 계약이 'UsingTellor' 계약에서 함수를 상속받을 수 있게 됩니다. + +좋습니다! 이제 도구가 준비되었으니, 비트코인 가격을 검색하는 간단한 연습을 해보겠습니다: + +### BTC/USD 예제 {#btcusd-example} + +Tellor 주소를 생성자 인수로 전달하여 UsingTellor 계약을 상속합니다: + +예시는 다음과 같습니다. + +```solidity +import "usingtellor/contracts/UsingTellor.sol"; + +contract PriceContract is UsingTellor { + uint256 public btcPrice; + + //이 계약은 이제 UsingTellor의 모든 함수에 접근할 수 있습니다 + +constructor(address payable _tellorAddress) UsingTellor(_tellorAddress) public {} + +function setBtcPrice() public { + bytes memory _b = abi.encode("SpotPrice",abi.encode("btc","usd")); + bytes32 _queryId = keccak256(_b); + + uint256 _timestamp; + bytes _value; + + (_value, _timestamp) = getDataBefore(_queryId, block.timestamp - 15 minutes); + + btcPrice = abi.decode(_value,(uint256)); + } +} +``` + +전체 계약 주소 목록은 [여기](https://docs.tellor.io/tellor/the-basics/contracts-reference)를 참조하세요. + +사용 편의성을 위해 UsingTellor 리포지토리는 더 쉬운 통합을 위해 [Tellor Playground](https://github.com/tellor-io/TellorPlayground) 계약 버전을 함께 제공합니다. 유용한 함수 목록은 [여기](https://github.com/tellor-io/sampleUsingTellor#tellor-playground)를 참조하세요. + +Tellor 오라클의 더 강력한 구현을 보려면 [여기](https://github.com/tellor-io/usingtellor/blob/master/README.md)에서 사용 가능한 전체 함수 목록을 확인하세요. diff --git a/public/content/translations/ko/developers/tutorials/how-to-view-nft-in-metamask/index.md b/public/content/translations/ko/developers/tutorials/how-to-view-nft-in-metamask/index.md new file mode 100644 index 00000000000..c0bdfe1c8d1 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/how-to-view-nft-in-metamask/index.md @@ -0,0 +1,33 @@ +--- +title: "지갑에서 자신의 NFT를 보는 방법 (NFT 튜토리얼 시리즈 3/3부)" +description: "이 튜토리얼은 MetaMask에서 기존 NFT를 보는 방법을 설명합니다!" +author: "Sumi Mudgil" +tags: [ "ERC-721", "Alchemy", "Solidity" ] +skill: beginner +lang: ko +published: 2021-04-22 +--- + +이 튜토리얼은 NFT 튜토리얼 시리즈의 3부 중 3부로, 새로 민팅한 NFT를 확인하는 방법을 다룹니다. 하지만 메인넷이나 모든 테스트넷을 포함하여 MetaMask를 사용하는 모든 ERC-721 토큰에 이 일반 튜토리얼을 사용할 수 있습니다. 이더리움에서 자신만의 NFT를 민팅하는 방법을 배우고 싶다면 [1부: NFT 스마트 계약 작성 및 배포 방법](/developers/tutorials/how-to-write-and-deploy-an-nft)을 확인하세요! + +축하해요! NFT 튜토리얼 시리즈에서 가장 짧고 간단한 부분에 도달했습니다. 바로 가상 지갑에서 새로 민팅한 NFT를 확인하는 방법입니다. 이전 두 파트에서 사용했던 MetaMask를 이 예시에서도 사용하겠습니다. + +사전 조건으로, 모바일에 MetaMask가 이미 설치되어 있어야 하며 NFT를 민팅한 계정이 포함되어 있어야 합니다. [iOS](https://apps.apple.com/us/app/metamask-blockchain-wallet/id1438144202) 또는 [Android](https://play.google.com/store/apps/details?id=io.metamask&hl=en_US&gl=US)에서 앱을 무료로 다운로드할 수 있습니다. + +## 1단계: 네트워크를 세폴리아(Sepolia)로 설정하기 {#set-network-to-sepolia} + +앱 상단의 '지갑' 버튼을 누르면 네트워크를 선택하라는 메시지가 표시됩니다. NFT는 세폴리아(Sepolia) 네트워크에서 민팅되었으므로 네트워크로 세폴리아(Sepolia)를 선택해야 합니다. + +![MetaMask 모바일에서 세폴리아(Sepolia)를 네트워크로 설정하는 방법](./goerliMetamask.gif) + +## 2단계: MetaMask에 수집품 추가하기 {#add-nft-to-metamask} + +세폴리아(Sepolia) 네트워크에 접속한 후, 오른쪽의 '수집품' 탭을 선택하고 NFT 스마트 계약 주소와 NFT의 ERC-721 토큰 ID를 추가하세요. 이 정보는 튜토리얼 2부에서 배포한 NFT의 트랜잭션 해시를 기반으로 Etherscan에서 찾을 수 있습니다. + +![트랜잭션 해시와 ERC-721 토큰 ID를 찾는 방법](./findNFTEtherscan.png) + +NFT를 보려면 몇 번 새로고침해야 할 수도 있습니다. 하지만 걱정마세요, 곧 나타날 겁니다 ! + +![MetaMask에 NFT를 업로드하는 방법](./findNFTMetamask.gif) + +축하해요! 이제 성공적으로 NFT를 민팅했으며, 바로 확인할 수 있습니다! 여러분이 NFT 세계를 어떻게 뒤흔들지 정말 기대됩니다! diff --git a/public/content/translations/ko/developers/tutorials/how-to-write-and-deploy-an-nft/index.md b/public/content/translations/ko/developers/tutorials/how-to-write-and-deploy-an-nft/index.md new file mode 100644 index 00000000000..48cd861aa05 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/how-to-write-and-deploy-an-nft/index.md @@ -0,0 +1,380 @@ +--- +title: "NFT 작성 및 배포 방법(NFT 튜토리얼 시리즈 1/3부)" +description: "이 튜토리얼은 NFT 시리즈의 1부이며, 이더리움과 IPFS(Inter Planetary File System)를 사용하여 대체 불가능 토큰(ERC-721 토큰) 스마트 계약을 작성하고 배포하는 방법을 단계별로 안내합니다." +author: "Sumi Mudgil" +tags: [ "ERC-721", "Alchemy", "Solidity", "스마트 컨트랙트" ] +skill: beginner +lang: ko +published: 2021-04-22 +--- + +NFT 덕분에 블록체인이 대중의 주목을 받게 되면서, 이제 이더리움 블록체인에 자신만의 NFT 계약(ERC-721 토큰)을 게시하여 직접 그 열풍을 이해해 볼 아주 좋은 기회입니다! + +Alchemy는 Makersplace(최근 크리스티 경매에서 6,900만 달러에 디지털 아트워크 판매 기록을 세움), Dapper Labs(NBA Top Shot & Crypto Kitties 제작사), OpenSea(세계 최대 NFT 마켓플레이스), Zora, Super Rare, NFTfi, Foundation, Enjin, Origin Protocol, Immutable 등 NFT 분야의 가장 큰 기업들을 지원하는 것을 매우 자랑스럽게 생각합니다. + +이 튜토리얼에서는 [MetaMask](https://metamask.io/), [Solidity](https://docs.soliditylang.org/en/v0.8.0/), [Hardhat](https://hardhat.org/), [Pinata](https://pinata.cloud/) 및 [Alchemy](https://alchemy.com/signup/eth)를 사용하여 Sepolia 테스트넷에 ERC-721 스마트 계약을 생성하고 배포하는 과정을 안내합니다(아직 이 내용이 무엇을 의미하는지 이해하지 못하더라도 걱정하지 마세요. 저희가 설명해 드릴 것입니다!). + +이 튜토리얼 2부에서는 스마트 계약을 사용해 NFT를 발행하는 방법을 살펴보고, 3부에서는 MetaMask에서 자신의 NFT를 확인하는 방법을 설명합니다. + +물론, 언제든지 질문이 있으시면 주저하지 마시고 [Alchemy Discord](https://discord.gg/gWuC7zB)에 문의하시거나 [Alchemy의 NFT API 문서](https://docs.alchemy.com/alchemy/enhanced-apis/nft-api)를 방문해주세요! + +## 1단계: 이더리움 네트워크에 연결하기 {#connect-to-ethereum} + +이더리움 블록체인에 요청하는 방법은 여러 가지가 있지만, 편의를 위해 블록체인 개발자 플랫폼 및 API인 [Alchemy](https://alchemy.com/signup/eth)의 무료 계정을 사용하겠습니다. 이를 통해 자체 노드를 실행하지 않고도 이더리움 체인과 통신할 수 있습니다. + +또한 이 튜토리얼에서는 스마트 계약 배포의 내부에서 어떤 일이 일어나는지 이해하기 위해 Alchemy의 모니터링 및 분석용 개발자 도구를 활용할 것입니다. 아직 Alchemy 계정이 없다면 [여기](https://alchemy.com/signup/eth)에서 무료로 가입할 수 있습니다. + +## 2단계: 앱(및 API 키) 만들기 {#make-api-key} + +Alchemy 계정을 생성한 후에는 앱을 생성하여 API 키를 생성할 수 있습니다. 이를 통해 Sepolia 테스트넷에 요청을 보낼 수 있습니다. 테스트넷에 대해 더 자세히 알고 싶으시면 [이 가이드](https://docs.alchemyapi.io/guides/choosing-a-network)를 확인하세요. + +1. 네비게이션 바의 "Apps" 위에 마우스를 놓고 "Create App"을 클릭하여 Alchemy 대시보드의 "Create App" 페이지로 이동합니다. + +![앱 만들기](./create-your-app.png) + +2. 앱 이름을 지정하고(저희는 “My First NFT!”로 정했습니다), 간단한 설명을 입력한 다음, 체인으로 “Ethereum”을, 네트워크로 “Sepolia”를 선택하세요. 병합 이후 다른 테스트넷은 지원이 중단되었습니다. + +![앱 구성 및 게시](./alchemy-explorer-sepolia.png) + +3. "Create app" 을 클릭하세요. 당신의 앱이 아래 테이블에 나타날겁니다! + +## 3단계: 이더리움 계정 생성(주소) {#create-eth-address} + +거래를 보내고 받기 위해서는 이더리움 계정이 필요합니다. 이 튜토리얼에서는 이더리움 계정 주소를 관리하는 데 사용되는 브라우저의 가상 지갑인 MetaMask를 사용합니다. 이더리움의 트랜잭션 작동 방식에 대해 더 자세히 알아보려면 이더리움 재단의 [이 페이지](/developers/docs/transactions/)를 확인하세요. + +[여기](https://metamask.io/download)에서 MetaMask 계정을 무료로 다운로드하고 생성할 수 있습니다. 계정을 생성하거나 이미 계정이 있는 경우, 오른쪽 상단의 “Sepolia 테스트넷”으로 전환해야 합니다(실제 돈을 다루지 않도록 하기 위함입니다). + +![Sepolia를 네트워크로 설정](./metamask-goerli.png) + +## 4단계: 파우셋에서 이더 추가하기 {#step-4-add-ether-from-a-faucet} + +스마트 컨트랙트를 테스트 네트워크에 배포하려면 가짜 ETH가 필요합니다. ETH를 받으려면 Alchemy에서 호스팅하는 [Sepolia 파우셋](https://sepoliafaucet.com/)으로 이동하여 로그인하고 계정 주소를 입력한 다음 “Send Me ETH”를 클릭하세요. 조금만 기다리면 곧 MetaMask 계정에 ETH가 표시됩니다! + +## 5단계: 잔액 확인하기 {#check-balance} + +잔액이 있는지 다시 확인하기 위해 [Alchemy의 composer 도구](https://composer.alchemyapi.io?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D)를 사용하여 [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) 요청을 해봅시다. 이것은 지갑에 있는 ETH의 양을 반환할 것입니다. MetaMask 계정 주소를 입력하고 "Send Request"를 클릭하면 다음과 같은 응답이 표시됩니다. + + ``` + `{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"}` + ``` + +> **참고** 이 결과는 ETH가 아닌 wei 단위입니다. Wei는 ether의 최소 단위로 사용됩니다. wei에서 ETH로 변환하면 1 eth = 1018 wei입니다. 따라서 0xde0b6b3a7640000을 10진수로 변환하면 1\*1018 wei, 즉 1 ETH가 됩니다. + +휴! 우리의 가짜 돈이 다 있군요. + +## 6단계: 프로젝트 초기화하기 {#initialize-project} + +먼저 프로젝트를 위한 폴더를 만들어야 합니다. 커맨드 라인으로 이동하여 다음을 입력합니다. + + ``` + mkdir my-nft + cd my-nft + ``` + +이제 프로젝트 폴더 안에 있으므로 npm init를 사용하여 프로젝트를 초기화합니다. npm이 아직 설치되지 않았다면 [이 지침](https://docs.alchemyapi.io/alchemy/guides/alchemy-for-macs#1-install-nodejs-and-npm)을 따르세요([Node.js](https://nodejs.org/en/download/)도 필요하니 함께 다운로드하세요!). + + ``` + npm init + ``` + +설치 질문에 어떻게 답하는지는 중요하지 않습니다. 참고로 저희는 다음과 같이 진행했습니다. + +```json + package name: (my-nft) + version: (1.0.0) + description: 나의 첫 NFT! + entry point: (index.js) + test command: + git repository: + keywords: + author: + license: (ISC) + About to write to /Users/thesuperb1/Desktop/my-nft/package.json: + + { + "name": "my-nft", + "version": "1.0.0", + "description": "나의 첫 NFT!", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" + } +``` + +package.json을 승인하면 준비가 끝납니다! + +## 7단계: [Hardhat](https://hardhat.org/getting-started/#overview) 설치하기 {#install-hardhat} + +Hardhat은 이더리움 소프트웨어를 컴파일, 배포, 테스트 및 디버그하기 위한 개발 환경입니다. 실제 블록체인에 배포하기 전에 로컬에서 스마트 컨트랙트 및 dApp을 구축할 때 사용됩니다. + +my-nft 프로젝트 내에서 다음을 실행합니다. + + ``` + npm install --save-dev hardhat + ``` + +설치 지침에 대한 자세한 내용은 [이 페이지](https://hardhat.org/getting-started/#overview)를 확인하세요. + +## 8단계: Hardhat 프로젝트 생성하기 {#create-hardhat-project} + +프로젝트 폴더 내에서 다음을 실행합니다. + + ``` + npx hardhat + ``` + +그러면 환영 메시지와 원하는 작업을 선택할 수 있는 옵션이 표시됩니다. "create an empty hardhat.config.js"를 선택합니다. + + ``` + 888 888 888 888 888 + 888 888 888 888 888 + 888 888 888 888 888 + 8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 + 888 888 "88b 888P" d88" 888 888 "88b "88b 888 + 888 888 .d888888 888 888 888 888 888 .d888888 888 + 888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. + 888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 + 👷 Hardhat v2.0.11에 오신 것을 환영합니다 👷‍ + ? 무엇을 하시겠습니까? … + 샘플 프로젝트 생성 + ❯ 빈 hardhat.config.js 생성 + 종료 + ``` + +그러면 hardhat.config.js 파일이 생성되며, 여기에 프로젝트의 모든 설정을 명시할 것입니다(13단계에서). + +## 9단계: 프로젝트 폴더 추가하기 {#add-project-folders} + +프로젝트를 체계적으로 정리하기 위해 두 개의 새 폴더를 만들겠습니다. 명령줄에서 프로젝트의 루트 디렉터리로 이동하고 다음을 입력합니다. + + ``` + mkdir contracts + mkdir scripts + ``` + +- contracts/는 NFT 스마트 계약 코드를 보관할 곳입니다. + +- scripts/는 스마트 계약을 배포하고 상호 작용하는 스크립트를 보관할 곳입니다. + +## 10단계: 계약 작성하기 {#write-contract} + +이제 환경 설정이 끝났으니 더 흥미로운 작업, 즉 스마트 계약 코드 작성을 시작하겠습니다! + +자주 사용하는 편집기에서 my-nft 프로젝트를 여세요(저희는 [VSCode](https://code.visualstudio.com/)를 선호합니다). 스마트 계약은 MyNFT.sol 스마트 계약을 작성하는 데 사용할 Solidity라는 언어로 작성됩니다.‌ + +1. `contracts` 폴더로 이동하여 MyNFT.sol이라는 새 파일을 만듭니다. + +2. 아래는 [OpenZeppelin](https://docs.openzeppelin.com/contracts/3.x/erc721) 라이브러리의 ERC-721 구현을 기반으로 한 저희의 NFT 스마트 계약 코드입니다. 아래 내용을 복사하여 MyNFT.sol 파일에 붙여넣습니다. + + ```solidity + //[https://docs.openzeppelin.com/contracts/3.x/erc721](https://docs.openzeppelin.com/contracts/3.x/erc721) 기반 계약 + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0; + + import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; + import "@openzeppelin/contracts/utils/Counters.sol"; + import "@openzeppelin/contracts/access/Ownable.sol"; + import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; + + contract MyNFT is ERC721URIStorage, Ownable { + using Counters for Counters.Counter; + Counters.Counter private _tokenIds; + + constructor() ERC721("MyNFT", "NFT") {} + + function mintNFT(address recipient, string memory tokenURI) + public onlyOwner + returns (uint256) + { + _tokenIds.increment(); + + uint256 newItemId = _tokenIds.current(); + _mint(recipient, newItemId); + _setTokenURI(newItemId, tokenURI); + + return newItemId; + } + } + ``` + +3. OpenZeppelin 계약 라이브러리에서 클래스를 상속하므로, 명령줄에서 `npm install @openzeppelin/contracts^4.0.0`을 실행하여 라이브러리를 우리 폴더에 설치합니다. + +그렇다면 이 코드는 정확히 어떤 역할을 할까요? 한 줄씩 분석해 보겠습니다. + +스마트 계약의 맨 위에서 세 개의 [OpenZeppelin](https://openzeppelin.com/) 스마트 계약 클래스를 가져옵니다. + +- @openzeppelin/contracts/token/ERC721/ERC721.sol은 우리의 NFT 스마트 계약이 상속할 ERC-721 표준의 구현을 포함합니다. (유효한 NFT가 되려면 스마트 계약이 ERC-721 표준의 모든 메서드를 구현해야 합니다.) 상속된 ERC-721 함수에 대해 더 자세히 알아보려면 [여기](https://eips.ethereum.org/EIPS/eip-721)에서 인터페이스 정의를 확인하세요. + +- @openzeppelin/contracts/utils/Counters.sol은 1씩만 증가하거나 감소할 수 있는 카운터를 제공합니다. 우리의 스마트 계약은 카운터를 사용하여 발행된 총 NFT 수를 추적하고 새로운 NFT에 고유 ID를 설정합니다. (스마트 계약을 사용하여 발행된 각 NFT에는 고유 ID가 할당되어야 합니다. 여기서 우리의 고유 ID는 단순히 현존하는 총 NFT 수에 따라 결정됩니다. 예를 들어, 스마트 계약으로 발행하는 첫 번째 NFT의 ID는 "1"이고, 두 번째 NFT의 ID는 "2"가 되는 식입니다.) + +- @openzeppelin/contracts/access/Ownable.sol은 스마트 계약에 [접근 제어](https://docs.openzeppelin.com/contracts/3.x/access-control)를 설정하여, 스마트 계약의 소유자(사용자 본인)만 NFT를 발행할 수 있도록 합니다. (참고로, 접근 제어를 포함하는 것은 전적으로 선택 사항입니다. 누구나 스마트 계약을 사용하여 NFT를 발행할 수 있게 하려면 10행의 Ownable과 17행의 onlyOwner를 제거하세요.) + +가져오기(import)문 다음에는 우리의 맞춤형 NFT 스마트 계약이 있는데, 이는 놀랍도록 짧습니다. 카운터, 생성자, 그리고 단일 함수만 포함되어 있습니다! 이는 우리가 상속한 OpenZeppelin 계약 덕분인데, 여기에는 NFT 소유자를 반환하는 `ownerOf`, 한 계정에서 다른 계정으로 NFT 소유권을 이전하는 `transferFrom`과 같이 NFT를 생성하는 데 필요한 대부분의 메서드가 구현되어 있습니다. + +ERC-721 생성자에서 “MyNFT”와 “NFT”라는 두 개의 문자열을 전달하는 것을 볼 수 있습니다. 첫 번째 변수는 스마트 계약의 이름이고 두 번째 변수는 심볼입니다. 이 변수들의 이름은 원하는 대로 지정할 수 있습니다! + +마지막으로 NFT를 발행할 수 있게 해주는 `mintNFT(address recipient, string memory tokenURI)` 함수가 있습니다! 이 함수는 두 개의 변수를 사용합니다. + +- `address recipient`는 새로 발행된 NFT를 받을 주소를 지정합니다. + +- `string memory tokenURI`는 NFT의 메타데이터를 설명하는 JSON 문서로 확인되어야 하는 문자열입니다. NFT의 메타데이터는 이름, 설명, 이미지 및 기타 속성과 같은 구성 가능한 속성을 가질 수 있도록 하여 생명을 불어넣는 역할을 합니다. 이 튜토리얼 2부에서는 이 메타데이터를 구성하는 방법을 설명합니다. + +`mintNFT`는 상속된 ERC-721 라이브러리에서 일부 메서드를 호출하며, 궁극적으로 새로 발행된 NFT의 ID를 나타내는 숫자를 반환합니다. + +## 11단계: MetaMask 및 Alchemy를 프로젝트에 연결하기 {#connect-metamask-and-alchemy} + +이제 MetaMask 지갑과 Alchemy 계정을 만들고 스마트 계약을 작성했으니, 이 세 가지를 연결할 차례입니다. + +디지털 지갑에서 전송되는 모든 거래에는 고유한 개인 키를 사용하는 서명이 필요합니다. 프로그램에 이 권한을 제공하기 위해 개인 키(및 Alchemy API 키) 를 환경 파일에 안전하게 저장할 수 있습니다. + +트랜잭션 전송에 대해 더 자세히 알아보려면 web3를 사용하여 트랜잭션을 전송하는 [이 튜토리얼](/developers/tutorials/sending-transactions-using-web3-and-alchemy/)을 확인하세요. + +먼저 프로젝트 디렉터리에 dotenv 패키지를 설치합니다. + + ``` + npm install dotenv --save + ``` + +그런 다음 프로젝트의 루트 디렉터리에 `.env` 파일을 만들고 여기에 MetaMask 개인 키와 HTTP Alchemy API URL을 추가합니다. + +- MetaMask에서 개인 키를 내보내려면 [이 지침](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key)을 따르세요. + +- 아래에서 HTTP Alchemy API URL을 확인하고 클립보드에 복사하세요. + +![Alchemy API URL 복사](./copy-alchemy-api-url.gif) + +이제 `.env`는 다음과 같이 보일 것입니다. + + ``` + API_URL="https://eth-sepolia.g.alchemy.com/v2/your-api-key" + PRIVATE_KEY="your-metamask-private-key" + ``` + +이것들을 코드에 실제로 연결하기 위해 13단계에서 hardhat.config.js 파일의 이 변수들을 참조할 것입니다. + + + +## 12단계: Ethers.js 설치하기 {#install-ethers} + +Ethers.js는 [표준 JSON-RPC 메서드](/developers/docs/apis/json-rpc/)를 더 사용자 친화적인 메서드로 래핑하여 이더리움과 더 쉽게 상호 작용하고 요청할 수 있게 해주는 라이브러리입니다. + +Hardhat을 사용하면 추가 도구 및 확장된 기능을 위해 [플러그인](https://hardhat.org/plugins/)을 매우 쉽게 통합할 수 있습니다. 계약 배포를 위해 [Ethers 플러그인](https://hardhat.org/docs/plugins/official-plugins#hardhat-ethers)을 활용할 것입니다([Ethers.js](https://github.com/ethers-io/ethers.js/)는 매우 깔끔한 계약 배포 방법을 제공합니다). + +프로젝트 디렉토리에 다음을 입력합니다. + + ``` + npm install --save-dev @nomiclabs/hardhat-ethers ethers@^5.0.0 + ``` + +다음 단계에서 hardhat.config.js에도 ether가 필요합니다. + +## 13단계: hardhat.config.js 업데이트하기 {#update-hardhat-config} + +지금까지 여러 종속성 및 플러그인을 추가했습니다. 이제 프로젝트에서 모든 항목에 대해 알 수 있도록 hardhat.config.js를 업데이트해야 합니다. + +hardhat.config.js를 다음과 같이 업데이트합니다. + +```js + /** + * @type import('hardhat/config').HardhatUserConfig + */ + require('dotenv').config(); + require("@nomiclabs/hardhat-ethers"); + const { API_URL, PRIVATE_KEY } = process.env; + module.exports = { + solidity: "0.8.1", + defaultNetwork: "sepolia", + networks: { + hardhat: {}, + sepolia: { + url: API_URL, + accounts: [`0x${PRIVATE_KEY}`] + } + }, + } +``` + +## 14단계: 계약 컴파일하기 {#compile-contract} + +지금까지 모든 것이 제대로 작동하는지 확인하기 위해 스마트 컨트랙트를 컴파일해 보겠습니다. compile 작업은 내장된 hardhat 작업 중 하나입니다. + +명령줄에서 다음을 실행합니다. + + ``` + npx hardhat compile + ``` + +PDX license identifier not provided in source file 에 대한 경고가 표시될 수 있지만 그것에 대해 걱정할 필요는 없습니다. 그 외의 것들은 잘 보이길 바랍니다! 그렇지 않은 경우 언제든지 [Alchemy discord](https://discord.gg/u72VCg3)로 메시지를 보내주세요. + +## 15단계: 배포 스크립트 작성하기 {#write-deploy} + +이제 스마트 컨트랙트가 작성되고 설정 파일을 사용할 수 있으므로 스마트 컨트랙트 배포 스크립트를 작성할 차례입니다. + +`scripts/` 폴더로 이동하여 `deploy.js`라는 새 파일을 만들고 다음 내용을 추가합니다. + +```js +async function main() { + const MyNFT = await ethers.getContractFactory("MyNFT") + + // 배포를 시작하고, 계약 객체로 확인되는 프로미스를 반환합니다. + const myNFT = await MyNFT.deploy() + await myNFT.deployed() + console.log("Contract deployed to address:", myNFT.address) +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error) + process.exit(1) + }) +``` + +Hardhat은 [계약 튜토리얼](https://hardhat.org/tutorial/testing-contracts.html#writing-tests)에서 각 코드 라인이 무엇을 하는지 훌륭하게 설명하고 있으며, 저희는 그 설명을 여기에 채택했습니다. + + ``` + const MyNFT = await ethers.getContractFactory("MyNFT"); + ``` + +ethers.js의 ContractFactory는 새로운 스마트 계약을 배포하는 데 사용되는 추상화이므로, 여기서 MyNFT는 NFT 계약 인스턴스를 위한 팩토리입니다. hardhat-ethers 플러그인을 사용할 때 ContractFactory 및 Contract 인스턴스는 기본적으로 첫 번째 서명자에게 연결됩니다. + + ``` + const myNFT = await MyNFT.deploy(); + ``` + +ContractFactory에서 deploy()를 호출하면 배포가 시작되고 Contract로 해석되는 Promise가 반환됩니다. 이것은 각 스마트 컨트랙트 기능에 대한 메소드가 있는 개체입니다. + +## 16단계: 계약 배포하기 {#deploy-contract} + +마침내 스마트 컨트랙트를 배포할 준비가 되었습니다! 프로젝트 디렉터리의 루트로 다시 이동하여 명령줄에서 다음을 실행합니다. + + ``` + npx hardhat --network sepolia run scripts/deploy.js + ``` + +그러면 다음과 같은 내용이 표시됩니다. + + ``` + 배포된 계약 주소: 0x4C5266cCc4b3F426965d2f51b6D910325a0E7650 + ``` + +[Sepolia etherscan](https://sepolia.etherscan.io/)으로 이동하여 계약 주소를 검색하면 성공적으로 배포되었음을 확인할 수 있습니다. 바로 보이지 않으면 시간이 걸릴 수 있으니 잠시 기다려주세요. 트랜잭션은 다음과 같습니다. + +![Etherscan에서 트랜잭션 주소 보기](./etherscan-sepoila-contract-creation.png) + +From 주소는 MetaMask 계정 주소와 일치해야 하며 To 주소는 “Contract Creation”이라고 표시됩니다. 트랜잭션을 클릭하면 To 필드에 계약 주소가 표시됩니다. + +![Etherscan에서 계약 주소 보기](./etherscan-sepolia-tx-details.png) + +성공입니다! 방금 이더리움(테스트넷) 체인에 NFT 스마트 계약을 배포했습니다! + +내부에서 무슨 일이 일어나고 있는지 이해하기 위해 [Alchemy 대시보드](https://dashboard.alchemyapi.io/explorer)의 Explorer 탭으로 이동해 보겠습니다. Alchemy 앱이 여러 개 있는 경우 앱별로 필터링하고 “MyNFT”를 선택해야 합니다. + +![Alchemy의 Explorer 대시보드를 통해 “내부적으로” 이루어진 호출 보기](./alchemy-explorer-goerli.png) + +여기에서 우리가 .deploy() 함수를 호출할 때 Hardhat/Ethers가 우리를 위해 만든 여러 개의 JSON-RPC 호출을 볼 수 있습니다. 여기서 주목해야 할 두 가지 중요한 것은 실제로 Sepolia 체인에 스마트 계약을 작성하는 요청인 [eth_sendRawTransaction](/developers/docs/apis/json-rpc/#eth_sendrawtransaction)과 해시가 주어졌을 때 트랜잭션에 대한 정보를 읽는 요청인 [eth_getTransactionByHash](/developers/docs/apis/json-rpc/#eth_gettransactionbyhash)입니다(트랜잭션을 보낼 때의 일반적인 패턴). 트랜잭션 전송에 대해 더 자세히 알아보려면 [Web3를 사용하여 트랜잭션 전송하기](/developers/tutorials/sending-transactions-using-web3-and-alchemy/)에 대한 이 튜토리얼을 확인하세요. + +이것으로 이 튜토리얼의 1부를 마칩니다. [2부에서는 NFT를 발행하여 스마트 계약과 실제로 상호 작용하고](/developers/tutorials/how-to-mint-an-nft/), [3부에서는 이더리움 지갑에서 NFT를 확인하는 방법을 보여드립니다](/developers/tutorials/how-to-view-nft-in-metamask/)! diff --git a/public/content/translations/ko/developers/tutorials/interact-with-other-contracts-from-solidity/index.md b/public/content/translations/ko/developers/tutorials/interact-with-other-contracts-from-solidity/index.md new file mode 100644 index 00000000000..77535ce399e --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/interact-with-other-contracts-from-solidity/index.md @@ -0,0 +1,172 @@ +--- +title: "솔리디티에서 다른 계약과 상호작용하기" +description: "기존 계약에서 스마트 계약을 배포하고 상호작용하는 방법" +author: "jdourlens" +tags: [ "스마트 계약", "Solidity", "Remix", "배포하기", "결합성" ] +skill: advanced +lang: ko +published: 2020-04-05 +source: EthereumDev +sourceUrl: https://ethereumdev.io/interact-with-other-contracts-from-solidity/ +address: "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE" +--- + +이전 튜토리얼에서는 [첫 스마트 계약 배포하기](/developers/tutorials/deploying-your-first-smart-contract/) 방법을 배우고, [수식어를 사용한 스마트 계약 접근 제어](https://ethereumdev.io/organize-your-code-and-control-access-to-your-smart-contract-with-modifiers/)나 [Solidity에서 오류 처리하기](https://ethereumdev.io/handle-errors-in-solidity-with-require-and-revert/)와 같은 기능을 추가했습니다. 이번 튜토리얼에서는 기존 계약에서 스마트 계약을 배포하고 상호작용하는 방법을 배워보겠습니다. + +`CounterFactory`라는 이름의 팩토리를 생성하여 누구나 자신만의 `Counter` 스마트 계약을 가질 수 있도록 하는 계약을 만들 것입니다. 먼저, 초기 `Counter` 스마트 계약의 코드는 다음과 같습니다. + +```solidity +pragma solidity 0.5.17; + +contract Counter { + + uint256 private _count; + address private _owner; + address private _factory; + + + modifier onlyOwner(address caller) { + require(caller == _owner, "귀하는 계약의 소유자가 아닙니다"); + _; + } + + modifier onlyFactory() { + require(msg.sender == _factory, "팩토리를 사용해야 합니다"); + _; + } + + constructor(address owner) public { + _owner = owner; + _factory = msg.sender; + } + + function getCount() public view returns (uint256) { + return _count; + } + + function increment(address caller) public onlyFactory onlyOwner(caller) { + _count++; + } + +} +``` + +참고로, 저희는 팩토리의 주소와 계약 소유자의 주소를 추적하기 위해 계약 코드를 약간 수정했습니다. 다른 계약에서 계약 코드를 호출하면, msg.sender는 계약 팩토리의 주소를 참조하게 됩니다. 계약을 사용하여 다른 계약과 상호작용하는 것은 일반적인 관행이므로, 이것은 반드시 이해해야 할 매우 중요한 점입니다. 따라서 복잡한 경우에는 발신자가 누구인지 주의해야 합니다. + +이를 위해 상태 변경 함수가 팩토리에 의해서만 호출되도록 보장하는 `onlyFactory` 수식어를 추가했으며, 이때 팩토리는 원래 호출자를 매개변수로 전달합니다. + +다른 모든 Counter를 관리할 새로운 `CounterFactory` 내부에, 소유자와 해당 카운터 계약 주소를 연결하는 매핑을 추가할 것입니다. + +```solidity +mapping(address => Counter) _counters; +``` + +이더리움에서 매핑은 자바스크립트의 객체와 동일하며, A 유형의 키를 B 유형의 값에 매핑할 수 있게 해줍니다. 이 경우, 우리는 소유자의 주소를 해당 Counter의 인스턴스와 매핑합니다. + +누군가를 위해 새로운 Counter를 인스턴스화하는 것은 다음과 같습니다. + +```solidity + function createCounter() public { + require (_counters[msg.sender] == Counter(0)); + _counters[msg.sender] = new Counter(msg.sender); + } +``` + +먼저 해당 사용자가 이미 카운터를 소유하고 있는지 확인합니다. 카운터를 소유하고 있지 않다면, 해당 주소를 `Counter` 생성자에 전달하여 새로운 카운터를 인스턴스화하고 새로 생성된 인스턴스를 매핑에 할당합니다. + +특정 Counter의 개수를 가져오는 코드는 다음과 같습니다. + +```solidity +function getCount(address account) public view returns (uint256) { + require (_counters[account] != Counter(0)); + return (_counters[account].getCount()); +} + +function getMyCount() public view returns (uint256) { + return (getCount(msg.sender)); +} +``` + +첫 번째 함수는 주어진 주소에 대한 Counter 계약이 존재하는지 확인한 다음, 인스턴스에서 `getCount` 메서드를 호출합니다. 두 번째 함수인 `getMyCount`는 msg.sender를 `getCount` 함수에 직접 전달하기 위한 편의 함수입니다. + +`increment` 함수도 매우 유사하지만, 원래 트랜잭션 발신자를 `Counter` 계약으로 전달합니다. + +```solidity +function increment() public { + require (_counters[msg.sender] != Counter(0)); + Counter(_counters[msg.sender]).increment(msg.sender); + } +``` + +너무 많이 호출되면 카운터에서 오버플로우가 발생할 수 있다는 점에 유의하세요. 이러한 경우를 방지하려면 [SafeMath 라이브러리](https://ethereumdev.io/using-safe-math-library-to-prevent-from-overflows/)를 최대한 활용해야 합니다. + +계약을 배포하려면 `CounterFactory`와 `Counter`의 코드를 모두 제공해야 합니다. 예를 들어 Remix에서 배포할 때, CounterFactory를 선택해야 합니다. + +전체 코드는 다음과 같습니다. + +```solidity +pragma solidity 0.5.17; + +contract Counter { + + uint256 private _count; + address private _owner; + address private _factory; + + + modifier onlyOwner(address caller) { + require(caller == _owner, "귀하는 계약의 소유자가 아닙니다"); + _; + } + + modifier onlyFactory() { + require(msg.sender == _factory, "팩토리를 사용해야 합니다"); + _; + } + + constructor(address owner) public { + _owner = owner; + _factory = msg.sender; + } + + function getCount() public view returns (uint256) { + return _count; + } + + function increment(address caller) public onlyFactory onlyOwner(caller) { + _count++; + } + +} + +contract CounterFactory { + + mapping(address => Counter) _counters; + + function createCounter() public { + require (_counters[msg.sender] == Counter(0)); + _counters[msg.sender] = new Counter(msg.sender); + } + + function increment() public { + require (_counters[msg.sender] != Counter(0)); + Counter(_counters[msg.sender]).increment(msg.sender); + } + + function getCount(address account) public view returns (uint256) { + require (_counters[account] != Counter(0)); + return (_counters[account].getCount()); + } + + function getMyCount() public view returns (uint256) { + return (getCount(msg.sender)); + } + +} +``` + +컴파일 후, Remix 배포 섹션에서 배포할 팩토리를 선택합니다. + +![Remix에서 배포할 팩토리 선택](./counterfactory-deploy.png) + +그런 다음 계약 팩토리를 테스트하며 값이 변경되는 것을 확인할 수 있습니다. 다른 주소에서 스마트 계약을 호출하려면 Remix의 계정 선택 메뉴에서 주소를 변경해야 합니다. diff --git a/public/content/translations/ko/developers/tutorials/ipfs-decentralized-ui/index.md b/public/content/translations/ko/developers/tutorials/ipfs-decentralized-ui/index.md new file mode 100644 index 00000000000..893ac375e86 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/ipfs-decentralized-ui/index.md @@ -0,0 +1,73 @@ +--- +title: "탈중앙화된 사용자 인터페이스를 위한 IPFS" +description: "이 튜토리얼은 탈중앙화앱의 사용자 인터페이스를 저장하기 위해 IPFS를 사용하는 방법을 설명합니다. 애플리케이션의 데이터와 비즈니스 로직이 탈중앙화되어 있더라도, 검열 저항성 사용자 인터페이스가 없으면 사용자는 결국 액세스 권한을 잃을 수 있습니다." +author: Ori Pomerantz +tags: [ "ipfs" ] +skill: beginner +lang: ko +published: 2024-06-29 +--- + +여러분은 놀라운 새 탈중앙화앱을 작성했습니다. 심지어 [사용자 인터페이스](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/)도 작성했습니다. 하지만 클라우드에 있는 단 하나의 서버일 뿐인 여러분의 사용자 인터페이스를 누군가가 다운시켜 검열할까 봐 걱정됩니다. 이 튜토리얼에서는 사용자 인터페이스를 [인터플래네터리 파일 시스템(IPFS)](https://ipfs.tech/developers/)에 올려 검열을 피하는 방법을 배웁니다. 그러면 관심 있는 사람은 누구나 나중에 액세스할 수 있도록 서버에 고정할 수 있습니다. + +[Fleek](https://resources.fleek.xyz/docs/)과 같은 타사 서비스를 사용하여 모든 작업을 수행할 수 있습니다. 이 튜토리얼은 일이 더 많더라도 자신이 무엇을 하고 있는지 이해할 수 있을 만큼 충분히 하고 싶은 사람들을 위한 것입니다. + +## 로컬에서 시작하기 {#getting-started-locally} + +여러 [타사 IPFS 공급자](https://docs.ipfs.tech/how-to/work-with-pinning-services/#use-a-third-party-pinning-service)가 있지만, 테스트를 위해 로컬에서 IPFS를 실행하여 시작하는 것이 가장 좋습니다. + +1. [IPFS 사용자 인터페이스](https://docs.ipfs.tech/install/ipfs-desktop/#install-instructions)를 설치합니다. + +2. 웹 사이트가 있는 디렉토리를 만듭니다. [Vite](https://vite.dev/)를 사용하는 경우 다음 명령을 사용합니다. + + ```sh + pnpm vite build + ``` + +3. IPFS 데스크톱에서 가져오기 > 폴더를 클릭하고 이전 단계에서 만든 디렉토리를 선택합니다. + +4. 방금 업로드한 폴더를 선택하고 이름 바꾸기를 클릭합니다. 더 의미 있는 이름을 지정합니다. + +5. 다시 선택하고 링크 공유를 클릭합니다. URL을 클립보드에 복사합니다. 링크는 `https://ipfs.io/ipfs/QmaCuQ7yN6iyBjLmLGe8YiFuCwnePoKfVu6ue8vLBsLJQJ`와 유사합니다. + +6. 상태를 클릭합니다. **고급** 탭을 확장하여 게이트웨이 주소를 확인합니다. 예를 들어, 제 시스템의 주소는 `http://127.0.0.1:8080`입니다. + +7. 링크 단계의 경로와 게이트웨이 주소를 결합하여 자신의 주소를 찾습니다. 예를 들어 위 예시의 URL은 `http://127.0.0.1:8080/ipfs/QmaCuQ7yN6iyBjLmLGe8YiFuCwnePoKfVu6ue8vLBsLJQJ`입니다. 브라우저에서 해당 URL을 열어 사이트를 확인합니다. + +## 업로드 {#uploading} + +이제 IPFS를 사용하여 로컬에서 파일을 제공할 수 있지만, 이는 그리 흥미로운 일은 아닙니다. 다음 단계는 여러분이 오프라인일 때도 전 세계에서 사용할 수 있도록 하는 것입니다. + +잘 알려진 여러 [고정 서비스](https://docs.ipfs.tech/concepts/persistence/#pinning-services)가 있습니다. 그중 하나를 선택합니다. 어떤 서비스를 사용하든 계정을 만들고 IPFS 데스크톱에 있는 콘텐츠 식별자(CID)를 제공해야 합니다. + +개인적으로 [4EVERLAND](https://docs.4everland.org/storage/4ever-pin/guides)가 가장 사용하기 쉽다고 생각합니다. 사용 방법은 다음과 같습니다. + +1. [대시보드](https://dashboard.4everland.org/overview)로 이동하여 지갑으로 로그인합니다. + +2. 왼쪽 사이드바에서 Storage > 4EVER Pin을 클릭합니다. + +3. Upload > Selected CID를 클릭합니다. 콘텐츠에 이름을 지정하고 IPFS 데스크톱의 CID를 제공합니다. 현재 CID는 `Qm`으로 시작하고 44개의 문자와 숫자가 뒤따르는 문자열로, `QmaCuQ7yN6iyBjLmLGe8YiFuCwnePoKfVu6ue8vLBsLJQJ`와 같이 [base-58로 인코딩된](https://medium.com/bootdotdev/base64-vs-base58-encoding-c25553ff4524) 해시를 나타내지만, [이는 변경될 가능성이 있습니다](https://docs.ipfs.tech/concepts/content-addressing/#version-1-v1). + +4. 초기 상태는 대기열에 추가됨(Queued)입니다. 고정됨(Pinned)으로 변경될 때까지 새로 고칩니다. + +5. CID를 클릭하여 링크를 가져옵니다. 제 애플리케이션은 [여기](https://bafybeifqka2odrne5b6l5guthqvbxu4pujko2i6rx2zslvr3qxs6u5o7im/)에서 볼 수 있습니다. + +6. 한 달 이상 고정하려면 계정을 활성화해야 할 수 있습니다. 계정 활성화 비용은 약 1달러입니다. 창을 닫았다면, 로그아웃한 후 다시 로그인하면 활성화하라는 메시지가 다시 표시됩니다. + +## IPFS에서 사용하기 {#using-from-ipfs} + +이 시점에서 여러분은 IPFS 콘텐츠를 제공하는 중앙화된 게이트웨이 링크를 갖게 됩니다. 요컨대, 사용자 인터페이스가 조금 더 안전해졌을지는 모르지만 여전히 검열 저항성이 있는 것은 아닙니다. 진정한 검열 저항성을 위해서는 사용자가 [브라우저에서 직접](https://docs.ipfs.tech/install/ipfs-companion/#prerequisites) IPFS를 사용해야 합니다. + +일단 설치하고(데스크톱 IPFS가 작동하면) 모든 사이트에서 [/ipfs/``](https://any.site/ipfs/bafybeifqka2odrne5b6l5guthqvbxu4pujko2i6rx2zslvr3qxs6u5o7im)로 이동하여 탈중앙화된 방식으로 제공되는 해당 콘텐츠를 얻을 수 있습니다. + +## 단점 {#drawbacks} + +IPFS 파일은 안정적으로 삭제할 수 없으므로, 사용자 인터페이스를 수정하는 동안에는 중앙화된 상태로 두거나 IPFS 위에 가변성을 제공하는 시스템인 [인터플래네터리 네임 시스템(IPNS)](https://docs.ipfs.tech/concepts/ipns/#mutability-in-ipfs)을 사용하는 것이 가장 좋습니다. 물론 변경 가능한 모든 것은 검열될 수 있으며, IPNS의 경우 해당하는 개인 키를 가진 사람에게 압력을 가함으로써 검열이 가능합니다. + +또한 일부 패키지는 IPFS와 문제가 있으므로 웹 사이트가 매우 복잡한 경우 좋은 해결책이 아닐 수 있습니다. 물론, 클라이언트 측을 IPFS에 두는 것만으로 서버 통합에 의존하는 모든 것을 탈중앙화할 수는 없습니다. + +## 결론 {#conclusion} + +이더리움이 탈중앙화앱의 데이터베이스 및 비즈니스 로직 측면을 탈중앙화할 수 있게 해주는 것처럼, IPFS는 사용자 인터페이스를 탈중앙화할 수 있게 해줍니다. 이를 통해 여러분의 탈중앙화앱에 대한 또 다른 공격 벡터를 차단할 수 있습니다. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). diff --git a/public/content/translations/ko/developers/tutorials/kickstart-your-dapp-frontend-development-with-create-eth-app/index.md b/public/content/translations/ko/developers/tutorials/kickstart-your-dapp-frontend-development-with-create-eth-app/index.md new file mode 100644 index 00000000000..da1d417d38d --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/kickstart-your-dapp-frontend-development-with-create-eth-app/index.md @@ -0,0 +1,104 @@ +--- +title: "create-eth-app으로 탈중앙화앱 프론트엔드 개발 시작하기" +description: "create-eth-app 사용 방법 및 기능 개요" +author: "Markus Waas" +tags: [ "프론트엔드", "JavaScript", "ethers.js", "the graph", "디파이" ] +skill: beginner +lang: ko +published: 2020-04-27 +source: soliditydeveloper.com +sourceUrl: https://soliditydeveloper.com/create-eth-app +--- + +지난번에 우리는 [솔리디티의 큰 그림](https://soliditydeveloper.com/solidity-overview-2020)을 살펴보고 [create-eth-app](https://github.com/PaulRBerg/create-eth-app)에 대해 이미 언급했습니다. 이제부터 사용 방법, 통합된 기능, 그리고 이를 확장하기 위한 추가적인 아이디어에 대해 알아보겠습니다. [Sablier](http://sablier.com/)의 창립자인 Paul Razvan Berg가 시작한 이 앱은 프론트엔드 개발을 시작하는 데 도움을 주며, 선택할 수 있는 몇 가지 선택적 통합 기능을 제공합니다. + +## 설치 {#installation} + +설치를 위해서는 Yarn 0.25 이상이 필요합니다(`npm install yarn --global`). 다음과 같이 간단하게 실행할 수 있습니다: + +```bash +yarn create eth-app my-eth-app +cd my-eth-app +yarn react-app:start +``` + +내부적으로 [create-react-app](https://github.com/facebook/create-react-app)을 사용합니다. 앱을 보려면 `http://localhost:3000/`을 여세요. 프로덕션에 배포할 준비가 되면, yarn build를 사용하여 축소된 번들을 생성하세요. 이를 호스팅하는 한 가지 쉬운 방법은 [Netlify](https://www.netlify.com/)입니다. GitHub 저장소를 만들고 Netlify에 추가한 다음 빌드 명령을 설정하면 끝입니다! 앱이 호스팅되어 모든 사람이 사용할 수 있게 됩니다. 이 모든 것이 무료입니다. + +## 기능 {#features} + +### React & create-react-app {#react--create-react-app} + +무엇보다도 이 앱의 핵심은 React와 create-react-app이 제공하는 모든 추가 기능입니다. 이더리움을 통합하고 싶지 않다면 이것만 사용하는 것도 좋은 방법입니다. [React](https://react.dev/) 자체는 인터랙티브 UI를 정말 쉽게 구축할 수 있도록 해줍니다. [Vue](https://vuejs.org/)만큼 초보자에게 친숙하지는 않을 수 있지만, 여전히 가장 많이 사용되며 더 많은 기능을 갖추고 있으며, 무엇보다도 선택할 수 있는 수천 개의 추가 라이브러리가 있습니다. create-react-app은 시작을 정말 쉽게 만들어주며 다음을 포함합니다: + +- React, JSX, ES6, TypeScript, Flow 구문 지원. +- 객체 전개 연산자와 같은 ES6 이상의 언어 추가 기능. +- 자동으로 접두사가 붙는 CSS이므로 -webkit- 또는 다른 접두사가 필요하지 않습니다. +- 커버리지 보고를 위한 내장 지원 기능이 있는 빠른 대화형 단위 테스트 실행기. +- 일반적인 실수에 대해 경고하는 라이브 개발 서버. +- 프로덕션을 위해 JS, CSS, 이미지를 해시 및 소스맵과 함께 번들로 묶는 빌드 스크립트. + +특히 create-eth-app은 새로운 [훅 효과](https://legacy.reactjs.org/docs/hooks-effect.html)를 사용하고 있습니다. 강력하면서도 매우 작은 소위 함수형 컴포넌트를 작성하는 방법입니다. create-eth-app에서 어떻게 사용되는지에 대해서는 아래의 Apollo 섹션을 참조하세요. + +### Yarn Workspaces {#yarn-workspaces} + +[Yarn Workspaces](https://classic.yarnpkg.com/en/docs/workspaces/)를 사용하면 여러 패키지를 가질 수 있지만, 루트 폴더에서 모든 패키지를 관리하고 `yarn install`을 사용하여 모든 종속성을 한 번에 설치할 수 있습니다. 이는 특히 스마트 계약 주소/ABI 관리(어떤 스마트 계약을 어디에 배포했는지, 그리고 어떻게 통신하는지에 대한 정보)나 그래프 통합과 같은 `create-eth-app`의 일부인 더 작은 추가 패키지에 특히 유용합니다. + +### ethers.js {#ethersjs} + +[Web3](https://docs.web3js.org/)가 여전히 주로 사용되지만, [ethers.js](https://docs.ethers.io/)는 지난 한 해 동안 대안으로 많은 주목을 받았으며 create-eth-app에 통합된 라이브러리입니다. 이것으로 작업하거나 Web3로 변경하거나 베타 테스트가 거의 끝난 [ethers.js v5](https://docs.ethers.org/v5/)로 업그레이드하는 것을 고려할 수 있습니다. + +### The Graph {#the-graph} + +[GraphQL](https://graphql.org/)은 [Restful API](https://restfulapi.net/)에 비해 데이터를 처리하는 대안적인 방법입니다. Restful API에 비해 몇 가지 장점이 있으며, 특히 탈중앙화 블록체인 데이터에 유용합니다. 이러한 이유에 관심이 있다면 [GraphQL Will Power the Decentralized Web](https://medium.com/graphprotocol/graphql-will-power-the-decentralized-web-d7443a69c69a)을 살펴보세요. + +일반적으로 스마트 계약에서 직접 데이터를 가져옵니다. 최신 거래 시간을 읽고 싶으신가요? 이더리움 노드에서 탈중앙화앱으로 데이터를 가져오는 `MyContract.methods.latestTradeTime().call()`을 호출하기만 하면 됩니다. 하지만 수백 개의 다른 데이터 포인트가 필요하다면 어떨까요? 이는 노드로 수백 번의 데이터 가져오기를 초래하며, 매번 [RTT](https://wikipedia.org/wiki/Round-trip_delay_time)가 필요하여 탈중앙화앱이 느리고 비효율적으로 됩니다. 한 가지 해결 방법은 계약 내에서 여러 데이터를 한 번에 반환하는 페처 호출 함수를 사용하는 것입니다. 하지만 이것이 항상 이상적인 것은 아닙니다. + +그리고 과거 데이터에도 관심이 있을 수 있습니다. 마지막 거래 시간뿐만 아니라 직접 했던 모든 거래의 시간도 알고 싶을 것입니다. _create-eth-app_ 서브그래프 패키지를 사용하고, [문서](https://thegraph.com/docs/en/subgraphs/developing/creating/starting-your-subgraph)를 읽고 자신의 계약에 맞게 수정하세요. 유명한 스마트 계약을 찾고 있다면 이미 서브그래프가 있을 수도 있습니다. [서브그래프 탐색기](https://thegraph.com/explorer/)를 확인해 보세요. + +서브그래프가 있으면, 탈중앙화앱에서 필요한 과거 데이터를 포함한 모든 중요한 블록체인 데이터를 검색하는 간단한 쿼리 하나를 작성할 수 있으며, 한 번의 가져오기만 필요합니다. + +### Apollo {#apollo} + +[Apollo Boost](https://www.apollographql.com/docs/react/get-started/) 통합 덕분에 React 탈중앙화앱에 그래프를 쉽게 통합할 수 있습니다. 특히 [React 훅과 Apollo](https://www.apollographql.com/blog/apollo-client-now-with-react-hooks)를 사용할 때, 데이터를 가져오는 것은 컴포넌트에 단일 GraphQL 쿼리를 작성하는 것만큼 간단합니다: + +```js +const { loading, error, data } = useQuery(myGraphQlQuery) + +React.useEffect(() => { + if (!loading && !error && data) { + console.log({ data }) + } +}, [loading, error, data]) +``` + +## 템플릿 {#templates} + +게다가 여러 다른 템플릿 중에서 선택할 수 있습니다. 지금까지 Aave, Compound, UniSwap 또는 sablier 통합을 사용할 수 있습니다. 이들은 모두 미리 만들어진 서브그래프 통합과 함께 중요한 서비스 스마트 계약 주소를 추가합니다. `yarn create eth-app my-eth-app --with-template aave`와 같이 생성 명령어에 템플릿을 추가하기만 하면 됩니다. + +### Aave {#aave} + +[Aave](https://aave.com/)는 탈중앙화 대출 시장입니다. 예금자는 시장에 유동성을 공급하여 패시브 인컴을 얻고, 대출자는 담보를 사용하여 대출할 수 있습니다. Aave의 독특한 기능 중 하나는 [플래시 론](https://aave.com/docs/developers/flash-loans)으로, 하나의 트랜잭션 내에서 대출을 상환하는 한 담보 없이 돈을 빌릴 수 있습니다. 예를 들어, 이는 차익 거래 시 추가 현금을 확보하는 데 유용할 수 있습니다. + +이자를 버는 거래 토큰을 aToken이라고 합니다. + +create-eth-app에 Aave를 통합하도록 선택하면 [서브그래프 통합](https://docs.aave.com/developers/getting-started/using-graphql)을 얻게 됩니다. Aave는 The Graph를 사용하며 [Ropsten](https://thegraph.com/explorer/subgraph/aave/protocol-ropsten)과 [메인넷](https://thegraph.com/explorer/subgraph/aave/protocol)에서 [원시(raw)](https://thegraph.com/explorer/subgraph/aave/protocol-raw) 또는 [형식이 지정된(formatted)](https://thegraph.com/explorer/subgraph/aave/protocol) 형태로 바로 사용할 수 있는 여러 서브그래프를 이미 제공합니다. + +![Aave 플래시 론 밈 – "네, 플래시 론을 한 트랜잭션보다 오래 유지할 수 있다면 정말 좋겠네요"](./flashloan-meme.png) + +### Compound {#compound} + +[Compound](https://compound.finance/)는 Aave와 유사합니다. 이 통합에는 이미 새로운 [Compound v2 서브그래프](https://medium.com/graphprotocol/https-medium-com-graphprotocol-compound-v2-subgraph-highlight-a5f38f094195)가 포함되어 있습니다. 여기서 이자를 버는 토큰은 놀랍게도 cToken이라고 불립니다. + +### Uniswap {#uniswap} + +[Uniswap](https://uniswap.exchange/)은 탈중앙화 거래소(DEX)입니다. 유동성 공급자는 거래의 양쪽에 필요한 토큰이나 이더를 제공하여 수수료를 벌 수 있습니다. 이는 널리 사용되므로 매우 광범위한 토큰에 대해 가장 높은 유동성 중 하나를 가지고 있습니다. 예를 들어, 사용자가 ETH를 DAI로 교환할 수 있도록 탈중앙화앱에 쉽게 통합할 수 있습니다. + +안타깝게도, 이 글을 쓰는 시점에서 이 통합은 Uniswap v1만을 위한 것이며, [막 출시된 v2](https://uniswap.org/blog/uniswap-v2/)는 지원하지 않습니다. + +### Sablier {#sablier} + +[Sablier](https://sablier.com/)는 사용자가 스트리밍 방식으로 자금을 결제할 수 있도록 합니다. 한 번의 월급날 대신, 초기 설정 후 추가적인 관리 없이 지속적으로 돈을 받을 수 있습니다. 이 통합에는 [자체 서브그래프](https://thegraph.com/explorer/subgraph/sablierhq/sablier)가 포함됩니다. + +## 다음 단계는 무엇일까요? {#whats-next} + +create-eth-app에 대해 질문이 있다면 [Sablier 커뮤니티 서버](https://discord.gg/bsS8T47)로 가서 create-eth-app의 저자들과 연락할 수 있습니다. 다음 초기 단계로 [Material UI](https://mui.com/material-ui/)와 같은 UI 프레임워크를 통합하고, 실제로 필요한 데이터에 대한 GraphQL 쿼리를 작성하고, 배포를 설정할 수 있습니다. diff --git a/public/content/translations/ko/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md b/public/content/translations/ko/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md new file mode 100644 index 00000000000..c0dde5db16e --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md @@ -0,0 +1,269 @@ +--- +title: "SQL로 이더리움 기초 주제 알아보기" +description: "이 튜토리얼은 구조화된 쿼리 언어(SQL)로 온체인 데이터를 쿼리하여 독자들이 트랜잭션, 블록, 가스를 포함한 이더리움의 기본 개념을 이해하도록 돕습니다." +author: "Paul Apivat" +tags: [ "SQL", "쿼리", "트랜잭션" ] +skill: beginner +lang: ko +published: 2021-05-11 +source: paulapivat.com +sourceUrl: https://paulapivat.com/post/query_ethereum/ +--- + +많은 이더리움 튜토리얼이 개발자를 대상으로 하지만, 데이터 분석가나 클라이언트 또는 노드를 실행하지 않고 온체인 데이터를 보고 싶어 하는 사람들을 위한 교육 자료는 부족합니다. + +이 튜토리얼은 [Dune Analytics](https://dune.com/)에서 제공하는 인터페이스를 통해 구조화된 쿼리 언어(SQL)로 온체인 데이터를 쿼리하여 독자들이 트랜잭션, 블록, 가스 등 이더리움의 기본 개념을 이해하도록 돕습니다. + +온체인 데이터는 이더리움, 네트워크, 그리고 컴퓨팅 파워를 위한 경제를 이해하는 데 도움이 될 수 있으며, 오늘날 이더리움이 직면한 과제(예: 가스 가격 상승)와 더 중요하게는 확장 솔루션에 대한 논의를 이해하기 위한 기초가 되어야 합니다. + +### 트랜잭션 {#transactions} + +이더리움에서 사용자의 여정은 ETH 잔액이 있는 사용자 제어 계정 또는 엔티티를 초기화하는 것에서 시작됩니다. 계정 유형에는 사용자 제어 계정 또는 스마트 계약의 두 가지가 있습니다([ethereum.org](/developers/docs/accounts/) 참조). + +[Etherscan](https://etherscan.io/) 또는 [Blockscout](https://eth.blockscout.com/)과 같은 블록 탐색기에서 모든 계정을 볼 수 있습니다. 블록 탐색기는 이더리움 데이터로 가는 포털입니다. 블록, 트랜잭션, 채굴자, 계정 및 기타 온체인 활동에 대한 데이터를 실시간으로 표시합니다([여기](/developers/docs/data-and-analytics/block-explorers/) 참조). + +그러나 사용자는 외부 블록 탐색기에서 제공하는 정보를 조정하기 위해 데이터를 직접 쿼리하고자 할 수 있습니다. [Dune Analytics](https://dune.com/)는 SQL에 대한 약간의 지식이 있는 모든 사람에게 이 기능을 제공합니다. + +참고로 이더리움 재단(EF)의 스마트 계약 계정은 [Blockscout](https://eth.blockscout.com/address/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe)에서 볼 수 있습니다. + +한 가지 주목할 점은 EF를 포함한 모든 계정에는 트랜잭션을 보내고 받는 데 사용할 수 있는 공개 주소가 있다는 것입니다. + +Etherscan의 계정 잔액은 일반 트랜잭션과 내부 트랜잭션으로 구성됩니다. 내부 트랜잭션은 이름에도 불구하고 체인의 상태를 변경하는 _실제_ 트랜잭션이 아닙니다. 계약 실행으로 시작된 가치 전송입니다([출처](https://ethereum.stackexchange.com/questions/3417/how-to-get-contract-internal-transactions)). 내부 트랜잭션에는 서명이 없으므로 **블록체인에 포함되지 않으며** Dune Analytics로 쿼리할 수 없습니다. + +따라서 이 튜토리얼에서는 일반 트랜잭션에 중점을 둘 것입니다. 다음과 같이 쿼리할 수 있습니다. + +```sql +WITH temp_table AS ( +SELECT + hash, + block_number, + block_time, + "from", + "to", + value / 1e18 AS ether, + gas_used, + gas_price / 1e9 AS gas_price_gwei +FROM ethereum."transactions" +WHERE "to" = '\xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe' +ORDER BY block_time DESC +) +SELECT + hash, + block_number, + block_time, + "from", + "to", + ether, + (gas_used * gas_price_gwei) / 1e9 AS txn_fee +FROM temp_table +``` + +이렇게 하면 Etherscan의 트랜잭션 페이지에 제공된 것과 동일한 정보가 생성됩니다. 비교를 위해 두 가지 출처는 다음과 같습니다. + +#### Etherscan {#etherscan} + +![](./etherscan_view.png) + +[Blockscout의 EF 계약 페이지](https://eth.blockscout.com/address/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe). + +#### Dune Analytics {#dune-analytics} + +![](./dune_view.png) + +대시보드는 [여기](https://dune.com/paulapivat/Learn-Ethereum)에서 찾을 수 있습니다. 표를 클릭하면 쿼리를 볼 수 있습니다(위 내용도 참조). + +### 트랜잭션 분석 {#breaking_down_transactions} + +제출된 트랜잭션에는 다음을 포함한 몇 가지 정보가 포함됩니다([출처](/developers/docs/transactions/)). + +- **수신자**: 수신 주소(\"to\"로 쿼리됨) +- **서명**: 발신자의 개인 키가 트랜잭션에 서명하지만, SQL로 쿼리할 수 있는 것은 발신자의 공개 주소(\"from\")입니다. +- **가치**: 전송된 ETH의 양입니다(`ether` 열 참조). +- **데이터**: 해시된 임의의 데이터입니다(`data` 열 참조) +- **gasLimit** – 트랜잭션이 소비할 수 있는 가스 단위의 최대량입니다. 가스 단위는 계산 단계를 나타냅니다 +- **maxPriorityFeePerGas** - 채굴자에게 팁으로 포함될 가스의 최대량 +- **maxFeePerGas** - 트랜잭션에 대해 지불할 의사가 있는 최대 가스량(baseFeePerGas 및 maxPriorityFeePerGas 포함) + +이더리움 재단 공개 주소로의 트랜잭션에 대한 이러한 특정 정보를 쿼리할 수 있습니다. + +```sql +SELECT + "to", + "from", + value / 1e18 AS ether, + data, + gas_limit, + gas_price / 1e9 AS gas_price_gwei, + gas_used, + ROUND(((gas_used / gas_limit) * 100),2) AS gas_used_pct +FROM ethereum."transactions" +WHERE "to" = '\xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe' +ORDER BY block_time DESC +``` + +### 블록 {#blocks} + +각 트랜잭션은 이더리움 가상 머신([EVM](/developers/docs/evm/))의 상태를 변경합니다([출처](/developers/docs/transactions/)). 트랜잭션은 검증을 거쳐 블록에 포함되기 위해 네트워크에 브로드캐스팅됩니다. 각 트랜잭션은 블록 번호와 연결됩니다. 데이터를 보려면 특정 블록 번호인 12396854(이 글을 쓰는 시점, 21년 5월 11일 기준 이더리움 재단 트랜잭션 중 가장 최근 블록)를 쿼리할 수 있습니다. + +또한 다음 두 블록을 쿼리하면 각 블록에 이전 블록의 해시(즉, 부모 해시)가 포함되어 있어 블록체인이 어떻게 형성되는지 알 수 있습니다. + +각 블록에는 부모 블록에 대한 참조가 포함되어 있습니다. `hash` 열과 `parent_hash` 열 사이에서 아래와 같이 표시됩니다([출처](/developers/docs/blocks/)). + +![parent_hash](./parent_hash.png) + +Dune Analytics의 [쿼리](https://dune.com/queries/44856/88292)는 다음과 같습니다. + +```sql +SELECT + time, + number, + hash, + parent_hash, + nonce +FROM ethereum."blocks" +WHERE "number" = 12396854 OR "number" = 12396855 OR "number" = 12396856 +LIMIT 10 +``` + +시간, 블록 번호, 난이도, 해시, 부모 해시, 논스(nonce)를 쿼리하여 블록을 검사할 수 있습니다. + +이 쿼리에서 다루지 않는 유일한 것은 아래에 별도의 쿼리가 필요한 트랜잭션 목록상태 루트입니다. 전체 또는 아카이브 노드는 모든 트랜잭션과 상태 전환을 저장하므로 클라이언트는 언제든지 체인의 상태를 쿼리할 수 있습니다. 이 작업에는 큰 저장 공간이 필요하므로 체인 데이터와 상태 데이터를 분리할 수 있습니다. + +- 체인 데이터(블록, 트랜잭션 목록) +- 상태 데이터(각 트랜잭션의 상태 전환 결과) + +상태 루트는 후자에 속하며 _암시적_ 데이터(온체인에 저장되지 않음)인 반면, 체인 데이터는 명시적이며 체인 자체에 저장됩니다([출처](https://ethereum.stackexchange.com/questions/359/where-is-the-state-data-stored)). + +이 튜토리얼에서는 Dune Analytics를 통해 SQL로 쿼리할 _수 있는_ 온체인 데이터에 중점을 둘 것입니다. + +위에서 언급했듯이 각 블록에는 트랜잭션 목록이 포함되어 있으며, 특정 블록을 필터링하여 이를 쿼리할 수 있습니다. 가장 최근 블록인 12396854를 시도해 보겠습니다. + +```sql +SELECT * FROM ethereum."transactions" +WHERE block_number = 12396854 +ORDER BY block_time DESC` +``` + +Dune의 SQL 출력은 다음과 같습니다. + +![](./list_of_txn.png) + +체인에 추가되는 이 단일 블록은 이더리움 가상 머신([EVM](/developers/docs/evm/))의 상태를 변경합니다. 수십, 때로는 수백 개의 트랜잭션이 한 번에 검증됩니다. 이 특정 경우에는 222개의 트랜잭션이 포함되었습니다. + +실제로 성공한 트랜잭션 수를 확인하려면 성공한 트랜잭션 수를 계산하는 필터를 하나 더 추가합니다. + +```sql +WITH temp_table AS ( + SELECT * FROM ethereum."transactions" + WHERE block_number = 12396854 AND success = true + ORDER BY block_time DESC +) +SELECT + COUNT(success) AS num_successful_txn +FROM temp_table +``` + +블록 12396854의 경우, 총 222개의 트랜잭션 중 204개가 성공적으로 검증되었습니다. + +![](./successful_txn.png) + +트랜잭션 요청은 초당 수십 번 발생하지만 블록은 약 15초에 한 번씩 커밋됩니다([출처](/developers/docs/blocks/)). + +약 15초마다 하나의 블록이 생성된다는 것을 확인하기 위해 하루의 초(86400)를 15로 나누어 하루 평균 블록 수(약 5760개)를 추정할 수 있습니다. + +하루에 생성되는 이더리움 블록 차트(2016년 - 현재)는 다음과 같습니다. + +![](./daily_blocks.png) + +이 기간 동안 매일 생성되는 평균 블록 수는 약 5,874개입니다. + +![](./avg_daily_blocks.png) + +쿼리는 다음과 같습니다. + +```sql +# 2016년부터 매일 생성된 블록 수를 시각화하는 쿼리 + +SELECT + DATE_TRUNC('day', time) AS dt, + COUNT(*) AS block_count +FROM ethereum."blocks" +GROUP BY dt +OFFSET 1 + +# 하루에 생성된 평균 블록 수 + +WITH temp_table AS ( +SELECT + DATE_TRUNC('day', time) AS dt, + COUNT(*) AS block_count +FROM ethereum."blocks" +GROUP BY dt +OFFSET 1 +) +SELECT + AVG(block_count) AS avg_block_count +FROM temp_table +``` + +2016년 이후 하루에 생성된 평균 블록 수는 5,874개로 그 숫자보다 약간 높습니다. 또는 86400초를 평균 5874블록으로 나누면 14.7초, 즉 약 15초마다 블록 하나가 나옵니다. + +### 가스 {#gas} + +블록은 크기가 제한되어 있습니다. 최대 블록 크기는 동적이며 네트워크 수요에 따라 12,500,000에서 25,000,000 단위 사이에서 달라집니다. 임의로 큰 블록 크기가 디스크 공간 및 속도 요구 사항 측면에서 전체 노드에 부담을 주는 것을 방지하기 위해 제한이 필요합니다([출처](/developers/docs/blocks/)). + +블록 가스 한도를 개념화하는 한 가지 방법은 트랜잭션을 일괄 처리할 수 있는 사용 가능한 블록 공간의 공급으로 생각하는 것입니다. 블록 가스 한도는 2016년부터 현재까지 쿼리하고 시각화할 수 있습니다. + +![](./avg_gas_limit.png) + +```sql +SELECT + DATE_TRUNC('day', time) AS dt, + AVG(gas_limit) AS avg_block_gas_limit +FROM ethereum."blocks" +GROUP BY dt +OFFSET 1 +``` + +그런 다음 이더리움 체인에서 수행되는 컴퓨팅(즉, 트랜잭션 전송, 스마트 계약 호출, NFT 발행) 비용을 지불하기 위해 매일 사용되는 실제 가스가 있습니다. 이것이 사용 가능한 이더리움 블록 공간에 대한 수요입니다. + +![](./daily_gas_used.png) + +```sql +SELECT + DATE_TRUNC('day', time) AS dt, + AVG(gas_used) AS avg_block_gas_used +FROM ethereum."blocks" +GROUP BY dt +OFFSET 1 +``` + +또한 이 두 차트를 함께 배치하여 수요와 공급이 어떻게 일치하는지 확인할 수 있습니다. + +![gas_demand_supply](./gas_demand_supply.png) + +따라서 가스 가격은 사용 가능한 공급이 주어졌을 때 이더리움 블록 공간에 대한 수요의 함수로 이해할 수 있습니다. + +마지막으로 이더리움 체인의 일일 평균 가스 가격을 쿼리하고 싶을 수 있지만, 그렇게 하면 쿼리 시간이 특히 길어지므로 쿼리를 이더리움 재단에서 트랜잭션당 지불하는 평균 가스량으로 필터링하겠습니다. + +![](./ef_daily_gas.png) + +수년에 걸쳐 이더리움 재단 주소로 이루어진 모든 트랜잭션에 대해 지불된 가스 가격을 볼 수 있습니다. 쿼리는 다음과 같습니다. + +```sql +SELECT + block_time, + gas_price / 1e9 AS gas_price_gwei, + value / 1e18 AS eth_sent +FROM ethereum."transactions" +WHERE "to" = '\xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe' +ORDER BY block_time DESC +``` + +### 요약 {#summary} + +이 튜토리얼을 통해 온체인 데이터를 쿼리하고 경험함으로써 이더리움의 기본 개념과 이더리움 블록체인의 작동 방식을 이해합니다. + +이 튜토리얼에 사용된 모든 코드가 포함된 대시보드는 [여기](https://dune.com/paulapivat/Learn-Ethereum)에서 찾을 수 있습니다. + +데이터를 사용하여 웹3를 탐색하는 방법에 대해 더 알아보려면 [Twitter에서 저를 찾아주세요](https://twitter.com/paulapivat). diff --git a/public/content/translations/ko/developers/tutorials/logging-events-smart-contracts/index.md b/public/content/translations/ko/developers/tutorials/logging-events-smart-contracts/index.md new file mode 100644 index 00000000000..2cd8db93b49 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/logging-events-smart-contracts/index.md @@ -0,0 +1,62 @@ +--- +title: "이벤트를 사용하여 스마트 계약 데이터를 기록하기" +description: "스마트 계약 이벤트 소개 및 이를 데이터 기록에 사용하는 방법" +author: "jdourlens" +tags: [ "스마트 계약", "Remix", "Solidity", "이벤트" ] +skill: intermediate +lang: ko +published: 2020-04-03 +source: EthereumDev +sourceUrl: https://ethereumdev.io/logging-data-with-events/ +address: "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE" +--- + +Solidity에서 [이벤트](/developers/docs/smart-contracts/anatomy/#events-and-logs)는 스마트 계약이 발생시킬 수 있는 디스패치된 신호입니다. 탈중앙화앱 또는 이더리움 JSON-RPC API에 연결된 모든 것은 이러한 이벤트를 수신하고 그에 따라 작동할 수 있습니다. 이벤트는 나중에 이벤트 기록을 검색할 수 있도록 인덱싱될 수도 있습니다. + +## 이벤트 {#events} + +이 글을 작성하는 시점에서 이더리움 블록체인에서 가장 흔한 이벤트는 누군가 토큰을 전송할 때 ERC20 토큰에 의해 발생하는 Transfer 이벤트입니다. + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value); +``` + +이벤트 서명은 계약 코드 내부에 선언되며 emit 키워드를 사용하여 발생시킬 수 있습니다. 예를 들어, transfer 이벤트는 누가 전송했는지(_from_), 누구에게(_to_), 그리고 얼마만큼의 토큰이 전송되었는지(_value_)를 기록합니다. + +Counter 스마트 계약으로 돌아가서 값이 변경될 때마다 기록을 남긴다고 해봅시다. 이 계약은 배포를 위한 것이 아니라 다른 계약을 확장하여 구축하기 위한 기반 역할을 하므로, 추상 계약이라고 합니다. 카운터 예시의 경우 다음과 같습니다: + +```solidity +pragma solidity 0.5.17; + +contract Counter { + + event ValueChanged(uint oldValue, uint256 newValue); + + // 카운트 수를 유지하기 위한 부호 없는 정수 유형의 비공개 변수 + uint256 private count = 0; + + // 카운터를 증가시키는 함수 + function increment() public { + count += 1; + emit ValueChanged(count - 1, count); + } + + // 카운트 값을 가져오는 getter + function getCount() public view returns (uint256) { + return count; + } + +} +``` + +다음 사항을 참고하세요: + +- **5행**: 이벤트를 선언하고 이벤트에 포함될 내용인 이전 값과 새 값을 정의합니다. + +- **13행**: count 변수를 증가시킬 때 이벤트를 발생시킵니다. + +이제 계약을 배포하고 increment 함수를 호출하면, logs라는 이름의 배열 내에서 새 트랜잭션을 클릭했을 때 Remix가 자동으로 이를 표시하는 것을 볼 수 있습니다. + +![Remix 스크린샷](./remix-screenshot.png) + +로그는 스마트 계약을 디버깅하는 데 매우 유용합니다. 또한 여러 사람이 사용하는 애플리케이션을 구축하는 경우, 스마트 계약의 사용 방식을 추적하고 이해하기 위한 분석을 용이하게 해주므로 중요합니다. 트랜잭션으로 생성된 로그는 인기 있는 블록 탐색기에 표시되며, 이를 사용하여 특정 이벤트를 수신하고 이벤트 발생 시 조치를 취하는 오프체인 스크립트를 생성할 수도 있습니다. diff --git a/public/content/translations/ko/developers/tutorials/merkle-proofs-for-offline-data-integrity/index.md b/public/content/translations/ko/developers/tutorials/merkle-proofs-for-offline-data-integrity/index.md new file mode 100644 index 00000000000..80d63efdd7e --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/merkle-proofs-for-offline-data-integrity/index.md @@ -0,0 +1,246 @@ +--- +title: "오프라인 데이터 무결성을 위한 머클 증명" +description: "대부분 오프체인에 저장되는 데이터의 온체인 데이터 무결성 보장" +author: Ori Pomerantz +tags: [ "저장 공간" ] +skill: advanced +lang: ko +published: 2021-12-30 +--- + +## 소개 {#introduction} + +이상적으로는 모든 것을 수천 대의 컴퓨터에 저장되고 가용성이 매우 높으며(데이터 검열 불가) 무결성을(권한 없는 방식으로 데이터 수정 불가) 갖춘 이더리움 저장 공간에 저장하고 싶겠지만, 32바이트 워드를 저장하는 데는 일반적으로 20,000 가스가 소요됩니다. 이 글을 쓰는 시점에서 그 비용은 6.60달러에 해당합니다. 바이트당 21센트의 비용은 많은 용도로 사용하기에는 너무 비쌉니다. + +이 문제를 해결하기 위해 이더리움 생태계는 [탈중앙화된 방식으로 데이터를 저장하는 다양한 대체 방법](/developers/docs/storage/)을 개발했습니다. 일반적으로 가용성과 가격 간의 절충이 필요합니다. 하지만 무결성은 일반적으로 보장됩니다. + +이 글에서는 [머클 증명](https://computersciencewiki.org/index.php/Merkle_proof)을 사용하여 블록체인에 데이터를 저장하지 않고 데이터 무결성을 보장하는 방법을 배웁니다. + +## 어떻게 작동하나요? {#how-does-it-work} + +이론적으로 데이터의 해시를 온체인에 저장하고, 데이터가 필요한 트랜잭션에 모든 데이터를 보낼 수 있습니다. 하지만 이 방법 역시 비용이 너무 많이 듭니다. 트랜잭션에 1바이트의 데이터를 전송하는 데는 약 16가스가 소모되며, 이는 현재 약 0.5센트, 킬로바이트당 약 5달러에 해당합니다. 메가바이트당 5,000달러의 비용은 데이터를 해싱하는 추가 비용을 고려하지 않더라도 여전히 많은 용도로 사용하기에 너무 비쌉니다. + +해결책은 데이터의 여러 하위 집합을 반복적으로 해시하여, 보낼 필요가 없는 데이터에 대해서는 해시만 보내는 것입니다. 이는 각 노드가 그 아래 노드들의 해시인 트리 데이터 구조인 머클 트리를 사용하여 수행합니다. + +![머클 트리](tree.png) + +루트 해시는 온체인에 저장해야 하는 유일한 부분입니다. 특정 값을 증명하기 위해, 그 값과 결합하여 루트를 얻는 데 필요한 모든 해시를 제공해야 합니다. 예를 들어, `C`를 증명하려면 `D`, `H(A-B)`, `H(E-H)`를 제공합니다. + +![C 값의 증명](proof-c.png) + +## 구현 {#implementation} + +[샘플 코드는 여기에서 제공됩니다](https://github.com/qbzzt/merkle-proofs-for-offline-data-integrity). + +### 오프체인 코드 {#offchain-code} + +이 글에서는 오프체인 계산에 JavaScript를 사용합니다. 대부분의 탈중앙화 애플리케이션은 JavaScript로 된 오프체인 구성 요소를 가지고 있습니다. + +#### 머클 루트 생성 {#creating-the-merkle-root} + +먼저 머클 루트를 체인에 제공해야 합니다. + +```javascript +const ethers = require("ethers") +``` + +[ethers 패키지의 해시 함수를 사용합니다](https://docs.ethers.io/v5/api/utils/hashing/#utils-keccak256). + +```javascript +// 무결성을 검증해야 하는 원시 데이터입니다. 처음 두 바이트는 +// 사용자 식별자이고, 마지막 두 바이트는 현재 사용자가 소유한 토큰의 +// 양입니다. +const dataArray = [ + 0x0bad0010, 0x60a70020, 0xbeef0030, 0xdead0040, 0xca110050, 0x0e660060, + 0xface0070, 0xbad00080, 0x060d0091, +] +``` + +각 항목을 단일 256비트 정수로 인코딩하면 예를 들어 JSON을 사용하는 것보다 코드 가독성이 떨어집니다. 하지만 이는 컨트랙트에서 데이터를 검색하기 위한 처리가 훨씬 적어짐을 의미하므로 가스 비용이 훨씬 저렴해집니다. [온체인에서 JSON을 읽을 수 있지만](https://github.com/chrisdotn/jsmnSol) 피할 수 있다면 좋은 생각은 아닙니다. + +```javascript +// BigInts로서의 해시 값 배열 +const hashArray = dataArray +``` + +이 경우 데이터는 처음부터 256비트 값이므로 처리가 필요하지 않습니다. 문자열과 같이 더 복잡한 데이터 구조를 사용하는 경우 해시 배열을 얻으려면 먼저 데이터를 해시해야 합니다. 이는 또한 사용자가 다른 사용자의 정보를 아는 것을 신경 쓰지 않기 때문입니다. 그렇지 않았다면 사용자 1이 사용자 0의 값을 알지 못하도록, 사용자 2가 사용자 3의 값을 알지 못하도록 하는 등 해시를 해야 했을 것입니다. + +```javascript +// 해시 함수가 예상하는 문자열과 +// 다른 모든 곳에서 사용하는 BigInt 사이를 변환합니다. +const hash = (x) => + BigInt(ethers.utils.keccak256("0x" + x.toString(16).padStart(64, 0))) +``` + +ethers 해시 함수는 `0x60A7`과 같은 16진수 숫자가 포함된 JavaScript 문자열을 예상하며 동일한 구조의 다른 문자열로 응답합니다. 하지만 나머지 코드에서는 `BigInt`를 사용하는 것이 더 쉬우므로 16진수 문자열로 변환했다가 다시 되돌립니다. + +```javascript +// 순서가 바뀌어도 상관없도록 쌍의 대칭 해시입니다. +const pairHash = (a, b) => hash(hash(a) ^ hash(b)) +``` + +이 함수는 대칭적입니다(a와 b의 [xor](https://en.wikipedia.org/wiki/Exclusive_or) 해시). 이는 머클 증명을 확인할 때 증명의 값을 계산된 값의 앞이나 뒤에 놓을지 걱정할 필요가 없다는 것을 의미합니다. 머클 증명 확인은 온체인에서 수행되므로 거기서 해야 할 일이 적을수록 좋습니다. + +경고: +암호학은 보기보다 어렵습니다. +이 글의 초기 버전에는 `hash(a^b)` 해시 함수가 있었습니다. +이는 `a`와 `b`의 정당한 값을 알고 있다면 `b' = a^b^a'`를 사용하여 원하는 `a'` 값을 증명할 수 있다는 것을 의미했기 때문에 **나쁜** 생각이었습니다. +이 함수를 사용하면 `hash(a') ^ hash(b')`가 알려진 값(루트로 가는 다음 분기)과 같도록 `b'`를 계산해야 하는데, 이는 훨씬 더 어렵습니다. + +```javascript +// 특정 분기가 비어 있고 값이 없음을 +// 나타내는 값 +const empty = 0n +``` + +값의 개수가 2의 정수 거듭제곱이 아닐 때 빈 분기를 처리해야 합니다. 이 프로그램은 0을 자리 표시자로 사용하여 이를 처리합니다. + +![분기가 누락된 머클 트리](merkle-empty-hash.png) + +```javascript +// 각 쌍을 순서대로 해시하여 해시 배열의 트리에서 한 수준 위를 +// 계산합니다. +const oneLevelUp = (inputArray) => { + var result = [] + var inp = [...inputArray] // 입력을 덮어쓰는 것을 방지하기 위해 // 필요한 경우 빈 값을 추가합니다(모든 리프가 // 쌍을 이루어야 함) + + if (inp.length % 2 === 1) inp.push(empty) + + for (var i = 0; i < inp.length; i += 2) + result.push(pairHash(inp[i], inp[i + 1])) + + return result +} // oneLevelUp +``` + +이 함수는 현재 레이어의 값 쌍을 해시하여 머클 트리에서 한 수준을 "올라갑니다". 이는 가장 효율적인 구현이 아닙니다. 입력을 복사하는 대신 루프에서 적절할 때 `hashEmpty`를 추가할 수 있었지만 이 코드는 가독성을 위해 최적화되었습니다. + +```javascript +const getMerkleRoot = (inputArray) => { + var result + + result = [...inputArray] // 값이 하나만 남을 때까지 트리를 올라갑니다. 그것이 // 루트입니다. // // 레이어에 홀수 개의 항목이 있으면 // oneLevelUp의 코드가 빈 값을 추가하므로 예를 들어, // 10개의 리프가 있으면 두 번째 레이어에 5개의 분기, 세 번째에 3개, // 네 번째에 2개의 분기가 있고 루트가 다섯 번째가 됩니다. + + while (result.length > 1) result = oneLevelUp(result) + + return result[0] +} +``` + +루트를 얻으려면 값이 하나만 남을 때까지 올라갑니다. + +#### 머클 증명 생성 {#creating-a-merkle-proof} + +머클 증명은 증명되는 값과 함께 해시하여 머클 루트를 다시 얻는 값입니다. 증명할 값은 종종 다른 데이터에서 사용할 수 있으므로 코드의 일부가 아닌 별도로 제공하는 것을 선호합니다. + +```javascript +// 머클 증명은 함께 해시할 항목 목록의 +// 값으로 구성됩니다. 대칭 해시 함수를 사용하므로 증명을 +// 확인하기 위해 항목의 위치가 필요하지 않으며 생성할 때만 필요합니다. +const getMerkleProof = (inputArray, n) => { +    var result = [], currentLayer = [...inputArray], currentN = n + +    // 맨 위에 도달할 때까지 +    while (currentLayer.length > 1) { +        // 홀수 길이 레이어 없음 +        if (currentLayer.length % 2) +            currentLayer.push(empty) + +        result.push(currentN % 2 +               // currentN이 홀수이면 이전 값을 증명에 추가합니다. +            ? currentLayer[currentN-1] +               // 짝수이면 다음 값을 추가합니다. +            : currentLayer[currentN+1]) + +``` + +`(v[0],v[1])`, `(v[2],v[3])` 등을 해시합니다. 따라서 짝수 값에는 다음 값이 필요하고 홀수 값에는 이전 값이 필요합니다. + +```javascript +        // 다음 상위 레이어로 이동 +        currentN = Math.floor(currentN/2) +        currentLayer = oneLevelUp(currentLayer) +    }   // while currentLayer.length > 1 + +    return result +}   // getMerkleProof +``` + +### 온체인 코드 {#onchain-code} + +마지막으로 증명을 확인하는 코드가 있습니다. 온체인 코드는 [Solidity](https://docs.soliditylang.org/en/v0.8.11/)로 작성되었습니다. 가스가 상대적으로 비싸기 때문에 여기서는 최적화가 훨씬 더 중요합니다. + +```solidity +//SPDX-License-Identifier: Public Domain +pragma solidity ^0.8.0; + +import "hardhat/console.sol"; +``` + +저는 [Hardhat 개발 환경](https://hardhat.org/)을 사용하여 이것을 작성했으며, 이를 통해 개발 중에 [Solidity에서 콘솔 출력](https://hardhat.org/docs/cookbook/debug-logs)을 할 수 있습니다. + +```solidity + +contract MerkleProof { +    uint merkleRoot; + +    function getRoot() public view returns (uint) { +      return merkleRoot; +    } + +    // 매우 안전하지 않으므로, 프로덕션 코드에서 이 함수에 대한 +    // 접근은 소유자에게로 +    // 엄격히 제한되어야 합니다. +    function setRoot(uint _merkleRoot) external { +      merkleRoot = _merkleRoot; +    }   // setRoot +``` + +머클 루트를 위한 설정 및 가져오기 함수입니다. 모든 사람이 머클 루트를 업데이트할 수 있도록 하는 것은 프로덕션 시스템에서 매우 나쁜 생각입니다. 여기서는 샘플 코드의 단순성을 위해 그렇게 합니다. **데이터 무결성이 실제로 중요한 시스템에서는 그렇게 하지 마세요**. + +```solidity +    function hash(uint _a) internal pure returns(uint) { +      return uint(keccak256(abi.encode(_a))); +    } + +    function pairHash(uint _a, uint _b) internal pure returns(uint) { +      return hash(hash(_a) ^ hash(_b)); +    } +``` + +이 함수는 쌍 해시를 생성합니다. 이는 `hash` 및 `pairHash`에 대한 JavaScript 코드의 Solidity 번역일 뿐입니다. + +**참고:** 이것은 가독성을 위한 최적화의 또 다른 경우입니다. [함수 정의](https://www.tutorialspoint.com/solidity/solidity_cryptographic_functions.htm)에 따르면 데이터를 [`bytes32`](https://docs.soliditylang.org/en/v0.5.3/types.html#fixed-size-byte-arrays) 값으로 저장하고 변환을 피할 수 있습니다. + +```solidity +    // 머클 증명 확인 +    function verifyProof(uint _value, uint[] calldata _proof) +        public view returns (bool) { +      uint temp = _value; +      uint i; + +      for(i=0; i<_proof.length; i++) { +        temp = pairHash(temp, _proof[i]); +      } + +      return temp == merkleRoot; +    } + +}  // MarkleProof +``` + +수학적 표기법에서 머클 증명 확인은 다음과 같습니다: `H(proof_n, H(proof_n-1, H(proof_n-2, ...` H(proof_1, H(proof_0, value))...)))`. 이 코드는 이를 구현합니다. + +## 머클 증명과 롤업은 잘 맞지 않습니다 {#merkle-proofs-and-rollups} + +머클 증명은 [롤업](/developers/docs/scaling/#rollups)과 잘 작동하지 않습니다. 그 이유는 롤업이 모든 트랜잭션 데이터를 L1에 기록하지만 L2에서 처리하기 때문입니다. 트랜잭션으로 머클 증명을 보내는 비용은 레이어당 평균 638 가스입니다(현재 호출 데이터의 바이트는 0이 아니면 16 가스, 0이면 4 가스가 소요됩니다). 1024 단어의 데이터가 있는 경우 머클 증명에는 10개의 레이어가 필요하며 총 6380 가스가 소요됩니다. + +예를 들어 [Optimism](https://public-grafana.optimism.io/d/9hkhMxn7z/public-dashboard?orgId=1&refresh=5m)을 보면, L1 가스 작성 비용은 약 100gwei이고 L2 가스 비용은 0.001gwei입니다(이는 정상 가격이며 혼잡에 따라 상승할 수 있습니다). 따라서 1 L1 가스 비용으로 L2 처리에서 10만 가스를 사용할 수 있습니다. 저장 공간을 덮어쓰지 않는다고 가정하면, 이는 1 L1 가스 가격으로 L2의 저장 공간에 약 5개의 단어를 쓸 수 있다는 의미입니다. 단일 머클 증명의 경우, (처음부터 트랜잭션으로 제공되는 것이 아니라 온체인에서 계산될 수 있다고 가정하면) 1024 단어 전체를 저장 공간에 쓸 수 있으며 그래도 대부분의 가스가 남습니다. + +## 결론 {#conclusion} + +실생활에서 직접 머클 트리를 구현할 일은 없을 수도 있습니다. 사용할 수 있는 잘 알려져 있고 감사된 라이브러리가 있으며, 일반적으로 암호화 기본 요소를 직접 구현하지 않는 것이 가장 좋습니다. 하지만 이제 머클 증명을 더 잘 이해하고 언제 사용할 가치가 있는지 결정할 수 있기를 바랍니다. + +머클 증명은 무결성은 보존하지만 가용성은 보존하지 않는다는 점에 유의하세요. 다른 사람이 내 자산을 가져갈 수 없다는 것을 아는 것은 데이터 저장 공간이 접근을 허용하지 않기로 결정하고 자산에 접근하기 위해 머클 트리를 구성할 수도 없다면 작은 위안에 불과합니다. 따라서 머클 트리는 IPFS와 같은 일종의 탈중앙화 저장 공간과 함께 사용하는 것이 가장 좋습니다. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). diff --git a/public/content/translations/ko/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md b/public/content/translations/ko/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md new file mode 100644 index 00000000000..359bff812d7 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md @@ -0,0 +1,151 @@ +--- +title: "InfluxDB와 Grafana를 사용하여 Geth 모니터링하기" +description: "InfluxDB와 Grafana를 사용하여 Geth 노드에 대한 모니터링을 설정하여 성능을 추적하고 문제를 식별합니다." +author: "Mario Havel" +tags: [ "클라이언트", "노드" ] +skill: intermediate +lang: ko +published: 2021-01-13 +--- + +이 튜토리얼은 Geth 노드의 성능을 더 잘 이해하고 잠재적인 문제를 식별할 수 있도록 모니터링을 설정하는 데 도움이 됩니다. + +## 필수 구성 요소 {#prerequisites} + +- Geth 인스턴스를 이미 실행 중이어야 합니다. +- 대부분의 단계와 예시는 Linux 환경을 위한 것이므로, 기본적인 터미널 지식이 도움이 될 것입니다. +- Geth의 메트릭 제품군에 대한 이 비디오 개요를 확인하세요: [Péter Szilágyi의 이더리움 인프라 모니터링](https://www.youtube.com/watch?v=cOBab8IJMYI). + +## 모니터링 스택 {#monitoring-stack} + +이더리움 클라이언트는 시간순 데이터베이스 형식으로 읽을 수 있는 많은 데이터를 수집합니다. 모니터링을 더 쉽게 하기 위해 이 데이터를 데이터 시각화 소프트웨어에 입력할 수 있습니다. 사용 가능한 여러 옵션이 있습니다: + +- [Prometheus](https://prometheus.io/) (풀 모델) +- [InfluxDB](https://www.influxdata.com/get-influxdb/) (푸시 모델) +- [Telegraf](https://www.influxdata.com/get-influxdb/) +- [Grafana](https://www.grafana.com/) +- [Datadog](https://www.datadoghq.com/) +- [Chronograf](https://www.influxdata.com/time-series-platform/chronograf/) + +InfluxDB 및 Grafana로 사전 구성된 옵션인 [Geth Prometheus Exporter](https://github.com/hunterlong/gethexporter)도 있습니다. + +이 튜토리얼에서는 Geth 클라이언트가 데이터를 InfluxDB로 푸시하여 데이터베이스를 생성하고, Grafana가 데이터의 그래프 시각화를 생성하도록 설정할 것입니다. 수동으로 수행하면 프로세스를 더 잘 이해하고, 변경하며, 다른 환경에 배포하는 데 도움이 됩니다. + +## InfluxDB 설정 {#setting-up-influxdb} + +먼저, InfluxDB를 다운로드하고 설치해 보겠습니다. 다양한 다운로드 옵션은 [Influxdata 릴리스 페이지](https://portal.influxdata.com/downloads/)에서 찾을 수 있습니다. 사용자의 환경에 맞는 것을 선택하세요. +[리포지토리](https://repos.influxdata.com/)에서도 설치할 수 있습니다. 예를 들어 Debian 기반 배포판에서는 다음과 같습니다: + +``` +curl -tlsv1.3 --proto =https -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add +source /etc/lsb-release +echo "deb https://repos.influxdata.com/${DISTRIB_ID,,} ${DISTRIB_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/influxdb.list +sudo apt update +sudo apt install influxdb -y +sudo systemctl enable influxdb +sudo systemctl start influxdb +sudo apt install influxdb-client +``` + +InfluxDB를 성공적으로 설치한 후, 백그라운드에서 실행되고 있는지 확인하세요. 기본적으로 `localhost:8086`에서 연결할 수 있습니다. +`influx` 클라이언트를 사용하기 전에 관리자 권한을 가진 새 사용자를 만들어야 합니다. 이 사용자는 상위 수준 관리, 데이터베이스 및 사용자 생성에 사용됩니다. + +``` +curl -XPOST "http://localhost:8086/query" --data-urlencode "q=CREATE USER username WITH PASSWORD 'password' WITH ALL PRIVILEGES" +``` + +이제 influx 클라이언트를 사용하여 이 사용자로 [InfluxDB 셸](https://docs.influxdata.com/influxdb/v1.8/tools/shell/)에 들어갈 수 있습니다. + +``` +influx -username 'username' -password 'password' +``` + +셸에서 InfluxDB와 직접 통신하여 Geth 메트릭을 위한 데이터베이스와 사용자를 생성할 수 있습니다. + +``` +create database geth +create user geth with password choosepassword +``` + +다음을 통해 생성된 항목을 확인합니다: + +``` +show databases +show users +``` + +InfluxDB 셸을 나갑니다. + +``` +exit +``` + +InfluxDB가 실행 중이며 Geth의 메트릭을 저장하도록 구성되었습니다. + +## Geth 준비하기 {#preparing-geth} + +데이터베이스를 설정한 후, Geth에서 메트릭 수집을 활성화해야 합니다. `geth --help`에서 `METRICS AND STATS OPTIONS`에 주의하세요. 여기서 여러 옵션을 찾을 수 있는데, 이 경우 Geth가 데이터를 InfluxDB로 푸시하도록 하려고 합니다. +기본 설정은 InfluxDB에 연결할 수 있는 엔드포인트와 데이터베이스에 대한 인증을 지정합니다. + +``` +geth --metrics --metrics.influxdb --metrics.influxdb.endpoint "http://0.0.0.0:8086" --metrics.influxdb.username "geth" --metrics.influxdb.password "chosenpassword" +``` + +이 플래그들은 클라이언트를 시작하는 명령어에 추가하거나 구성 파일에 저장할 수 있습니다. + +예를 들어, 데이터베이스의 메트릭을 나열하여 Geth가 데이터를 성공적으로 푸시하고 있는지 확인할 수 있습니다. InfluxDB 셸에서: + +``` +use geth +show measurements +``` + +## Grafana 설정 {#setting-up-grafana} + +다음 단계는 데이터를 그래픽으로 해석할 Grafana를 설치하는 것입니다. Grafana 개발문서에서 사용자 환경에 맞는 설치 과정을 따르세요. 달리 원하지 않는 경우 OSS 버전을 설치해야 합니다. +리포지토리를 사용하는 Debian 배포판의 설치 예시는 다음과 같습니다: + +``` +curl -tlsv1.3 --proto =https -sL https://packages.grafana.com/gpg.key | sudo apt-key add - +echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list +sudo apt update +sudo apt install grafana +sudo systemctl enable grafana-server +sudo systemctl start grafana-server +``` + +Grafana가 실행되면 `localhost:3000`에서 연결할 수 있습니다. +선호하는 브라우저를 사용하여 이 경로에 접속한 다음 기본 자격 증명(사용자: `admin`, 암호: `admin`)으로 로그인하세요. 메시지가 표시되면 기본 암호를 변경하고 저장하세요. + +![](./grafana1.png) + +Grafana 홈 페이지로 리디렉션됩니다. 먼저, 소스 데이터를 설정하세요. 왼쪽 막대에서 구성 아이콘을 클릭하고 "Data sources"를 선택하세요. + +![](./grafana2.png) + +아직 생성된 데이터 소스가 없습니다. "Add data source"를 클릭하여 하나를 정의하세요. + +![](./grafana3.png) + +이 설정에서는 "InfluxDB"를 선택하고 진행하세요. + +![](./grafana4.png) + +동일한 컴퓨터에서 도구를 실행하는 경우 데이터 소스 구성은 매우 간단합니다. InfluxDB 주소와 데이터베이스 액세스에 대한 세부 정보를 설정해야 합니다. 아래 그림을 참조하세요. + +![](./grafana5.png) + +모든 것이 완료되고 InfluxDB에 연결할 수 있으면 "Save and test"를 클릭하고 확인 메시지가 나타날 때까지 기다리세요. + +![](./grafana6.png) + +이제 Grafana가 InfluxDB에서 데이터를 읽도록 설정되었습니다. 이제 데이터를 해석하고 표시할 대시보드를 생성해야 합니다. 대시보드 속성은 누구나 생성하고 쉽게 가져올 수 있는 JSON 파일로 인코딩됩니다. 왼쪽 막대에서 "Create and Import"를 클릭하세요. + +![](./grafana7.png) + +Geth 모니터링 대시보드의 경우, [이 대시보드](https://grafana.com/grafana/dashboards/13877/)의 ID를 복사하여 Grafana의 "Import page"에 붙여넣으세요. 대시보드를 저장하면 다음과 같이 보일 것입니다: + +![](./grafana8.png) + +대시보드를 수정할 수 있습니다. 각 패널은 편집, 이동, 제거 또는 추가할 수 있습니다. 구성을 변경할 수 있습니다. 당신에게 달려 있습니다! 대시보드 작동 방식에 대해 더 자세히 알아보려면 [Grafana의 개발문서](https://grafana.com/docs/grafana/latest/dashboards/)를 참조하세요. +[알림](https://grafana.com/docs/grafana/latest/alerting/)에도 관심이 있을 수 있습니다. 이를 통해 메트릭이 특정 값에 도달했을 때 알림을 설정할 수 있습니다. 다양한 통신 채널이 지원됩니다. diff --git a/public/content/translations/ko/developers/tutorials/nft-minter/index.md b/public/content/translations/ko/developers/tutorials/nft-minter/index.md new file mode 100644 index 00000000000..abd05f84b13 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/nft-minter/index.md @@ -0,0 +1,874 @@ +--- +title: "NFT 민터 튜토리얼" +description: "이 튜토리얼에서는 NFT 민터를 구축하고 MetaMask 및 웹3 도구를 사용하여 스마트 계약을 React 프런트엔드에 연결하여 풀스택 탈중앙화앱을 만드는 방법을 알아봅니다." +author: "smudgil" +tags: + [ + "솔리디티", + "NFT", + "alchemy", + "스마트 컨트랙트", + "프론트엔드", + "Pinata" + ] +skill: intermediate +lang: ko +published: 2021-10-06 +--- + +Web2 배경을 가진 개발자에게 가장 큰 과제 중 하나는 스마트 계약을 프런트엔드 프로젝트에 연결하고 상호 작용하는 방법을 알아내는 것입니다. + +디지털 자산에 대한 링크, 제목, 설명을 입력할 수 있는 간단한 UI인 NFT 민터를 구축하여 다음 방법을 배우게 됩니다. + +- 프런트엔드 프로젝트를 통해 MetaMask에 연결하기 +- 프런트엔드에서 스마트 계약 메서드 호출하기 +- MetaMask를 사용하여 트랜잭션에 서명하기 + +이 튜토리얼에서는 프런트엔드 프레임워크로 [React](https://react.dev/)를 사용할 것입니다. 이 튜토리얼은 주로 웹3 개발에 중점을 두므로 React 기본 사항을 분석하는 데 많은 시간을 할애하지는 않을 것입니다. 대신, 프로젝트에 기능을 추가하는 데 중점을 둘 것입니다. + +사전 조건으로 컴포넌트, props, useState/useEffect 및 기본 함수 호출이 어떻게 작동하는지 아는 등 React에 대한 초급 수준의 이해가 있어야 합니다. 이전에 이러한 용어를 들어본 적이 없다면, 이 [React 입문 튜토리얼](https://react.dev/learn/tutorial-tic-tac-toe)을 확인해 보세요. 시각적 학습자의 경우, Net Ninja의 우수한 [최신 React 전체 튜토리얼](https://www.youtube.com/playlist?list=PL4cUxeGkcC9gZD-Tvwfod2gaISzfRiP9d) 동영상 시리즈를 적극 권장합니다. + +아직 계정이 없다면 이 튜토리얼을 완료하고 블록체인에서 무엇이든 빌드하려면 Alchemy 계정이 반드시 필요합니다. [여기](https://alchemy.com/)에서 무료 계정에 가입하세요. + +자, 이제 시작해 봅시다! + +## NFT 만들기 101 {#making-nfts-101} + +코드를 살펴보기 전에 NFT가 어떻게 만들어지는지 이해하는 것이 중요합니다. 두 단계로 구성됩니다. + +### 이더리움 블록체인에 NFT 스마트 계약 게시하기 {#publish-nft} + +두 NFT 스마트 계약 표준의 가장 큰 차이점은 ERC-1155는 다중 토큰 표준이며 일괄 처리 기능을 포함하는 반면 ERC-721은 단일 토큰 표준이므로 한 번에 하나의 토큰만 전송할 수 있다는 점입니다. + +### 민팅 함수 호출 {#minting-function} + +일반적으로 이 민팅 함수는 두 개의 변수를 매개변수로 전달해야 합니다. 첫 번째는 새로 민팅된 NFT를 받을 주소를 지정하는 `recipient`이고, 두 번째는 NFT의 메타데이터를 설명하는 JSON 문서로 확인되는 문자열인 NFT의 `tokenURI`입니다. + +NFT의 메타데이터는 이름, 설명, 이미지(또는 다른 디지털 자산) 및 기타 속성과 같은 속성을 갖도록 하여 NFT에 생명을 불어넣는 것입니다. 다음은 NFT의 메타데이터를 포함하는 [tokenURI의 예](https://gateway.pinata.cloud/ipfs/QmSvBcb4tjdFpajGJhbFAWeK3JAxCdNQLQtr6ZdiSi42V2)입니다. + +이 튜토리얼에서는 React UI를 사용하여 기존 NFT의 스마트 계약 민팅 함수를 호출하는 2부에 중점을 둘 것입니다. + +이 튜토리얼에서 호출할 ERC-721 NFT 스마트 계약에 대한 [링크는 여기](https://ropsten.etherscan.io/address/0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE)에 있습니다. 어떻게 만들었는지 알고 싶다면 다른 튜토리얼인 ["NFT 만드는 방법"](https://www.alchemy.com/docs/how-to-create-an-nft)을 확인하는 것을 적극 권장합니다. + +좋습니다. 이제 NFT가 어떻게 작동하는지 이해했으니 스타터 파일을 복제해 봅시다! + +## 스타터 파일 복제하기 {#clone-the-starter-files} + +먼저, [nft-minter-tutorial GitHub 저장소](https://github.com/alchemyplatform/nft-minter-tutorial)로 이동하여 이 프로젝트의 스타터 파일을 가져옵니다. 이 저장소를 로컬 환경에 복제하세요. + +복제된 `nft-minter-tutorial` 저장소를 열면 `minter-starter-files`와 `nft-minter`라는 두 개의 폴더가 있는 것을 확인할 수 있습니다. + +- `minter-starter-files`는 이 프로젝트의 스타터 파일(기본적으로 React UI)을 포함합니다. 이 튜토리얼에서는 이더리움 지갑과 NFT 스마트 계약에 연결하여 이 UI에 생명을 불어넣는 방법을 배우면서 **이 디렉터리에서 작업할 것입니다.** +- `nft-minter`는 전체 튜토리얼을 포함하며 막혔을 때를 위한 참조용입니다. + +다음으로, 코드 편집기에서 `minter-starter-files` 사본을 열고 `src` 폴더로 이동합니다. + +우리가 작성할 모든 코드는 `src` 폴더 아래에 위치하게 됩니다. `Minter.js` 컴포넌트를 편집하고 추가 자바스크립트 파일을 작성하여 프로젝트에 웹3 기능을 부여할 것입니다. + +## 2단계: 스타터 파일 확인하기 {#step-2-check-out-our-starter-files} + +코딩을 시작하기 전에 스타터 파일에 이미 제공된 내용을 확인하는 것이 중요합니다. + +### React 프로젝트 실행하기 {#get-your-react-project-running} + +먼저 브라우저에서 React 프로젝트를 실행해 봅시다. React의 장점은 일단 브라우저에서 프로젝트가 실행되면, 저장하는 모든 변경 사항이 브라우저에 실시간으로 업데이트된다는 것입니다. + +프로젝트를 실행하려면 `minter-starter-files` 폴더의 루트 디렉터리로 이동한 다음 터미널에서 `npm install`을 실행하여 프로젝트의 종속성을 설치합니다: + +```bash +cd minter-starter-files +npm install +``` + +설치가 완료되면 터미널에서 `npm start`를 실행합니다: + +```bash +npm start +``` + +이렇게 하면 브라우저에서 http://localhost:3000/이 열리고 프로젝트의 프런트엔드가 표시됩니다. 3개의 필드로 구성되어야 합니다: NFT 자산 링크 입력, NFT 이름 입력, 설명 제공. + +만약 "지갑 연결" 또는 "NFT 민팅" 버튼을 클릭해 보면 작동하지 않는 것을 알 수 있습니다. 이는 우리가 아직 그 기능을 프로그래밍해야 하기 때문입니다! :\) + +### Minter.js 컴포넌트 {#minter-js} + +**참고:** `nft-minter` 폴더가 아닌 `minter-starter-files` 폴더에 있는지 확인하세요! + +편집기의 `src` 폴더로 돌아가서 `Minter.js` 파일을 엽시다. 이 파일은 우리가 작업할 기본 React 컴포넌트이므로 파일의 모든 내용을 이해하는 것이 매우 중요합니다. + +이 파일의 맨 위에는 특정 이벤트 후에 업데이트할 상태 변수가 있습니다. + +```javascript +//상태 변수 +const [walletAddress, setWallet] = useState("") +const [status, setStatus] = useState("") +const [name, setName] = useState("") +const [description, setDescription] = useState("") +const [url, setURL] = useState("") +``` + +React 상태 변수나 상태 훅에 대해 들어본 적이 없나요? [이](https://legacy.reactjs.org/docs/hooks-state.html) 문서를 확인해 보세요. + +각 변수가 나타내는 내용은 다음과 같습니다: + +- `walletAddress` - 사용자의 지갑 주소를 저장하는 문자열 +- `status` - UI 하단에 표시할 메시지를 포함하는 문자열 +- `name` - NFT의 이름을 저장하는 문자열 +- `description` - NFT의 설명을 저장하는 문자열 +- `url` - NFT의 디지털 자산에 대한 링크인 문자열 + +상태 변수 다음에는 `useEffect`, `connectWalletPressed`, `onMintPressed`라는 세 개의 미구현 함수가 표시됩니다. 이 모든 함수가 `async`라는 것을 알 수 있는데, 이는 우리가 그 안에서 비동기 API 호출을 할 것이기 때문입니다! 그 이름들은 기능과 동일한 이름입니다. + +```javascript +useEffect(async () => { + //TODO: 구현 +}, []) + +const connectWalletPressed = async () => { + //TODO: 구현 +} + +const onMintPressed = async () => { + //TODO: 구현 +} +``` + +- [`useEffect`](https://legacy.reactjs.org/docs/hooks-effect.html) - 컴포넌트가 렌더링된 후 호출되는 React 훅입니다. 빈 배열 `[]` prop이 전달되므로(3번째 줄 참조), 컴포넌트의 _첫 번째_ 렌더링에서만 호출됩니다. 여기서는 지갑 리스너와 다른 지갑 함수를 호출하여 지갑이 이미 연결되었는지 여부를 UI에 반영하도록 업데이트합니다. +- `connectWalletPressed` - 이 함수는 사용자의 MetaMask 지갑을 탈중앙화앱에 연결하기 위해 호출됩니다. +- `onMintPressed` - 이 함수는 사용자의 NFT를 민팅하기 위해 호출됩니다. + +이 파일의 끝부분에는 컴포넌트의 UI가 있습니다. 이 코드를 자세히 살펴보면 해당 텍스트 필드의 입력이 변경될 때 `url`, `name`, `description` 상태 변수를 업데이트하는 것을 알 수 있습니다. + +또한 `mintButton` 및 `walletButton` ID가 있는 버튼을 각각 클릭하면 `connectWalletPressed` 및 `onMintPressed`가 호출되는 것을 볼 수 있습니다. + +```javascript +//우리 컴포넌트의 UI +return ( +
+ + +

+

🧙‍♂️ Alchemy NFT 민터

+

+ 자산의 링크, 이름, 설명을 추가한 후 "민팅"을 누르세요. +

+
+

🖼 자산 링크:

+ setURL(event.target.value)} + /> +

🤔 이름:

+ setName(event.target.value)} + /> +

✍️ 설명:

+ setDescription(event.target.value)} + /> +
+ +

{status}

+
+) +``` + +마지막으로 이 Minter 컴포넌트가 어디에 추가되는지 살펴보겠습니다. + +다른 모든 컴포넌트의 컨테이너 역할을 하는 React의 기본 컴포넌트인 `App.js` 파일로 이동하면 7번 줄에 Minter 컴포넌트가 삽입된 것을 볼 수 있습니다. + +**이 튜토리얼에서는 `Minter.js 파일`을 편집하고 `src` 폴더에 파일을 추가하기만 합니다.** + +이제 무엇을 다루는지 이해했으니 이더리움 지갑을 설정해 봅시다! + +## 이더리움 지갑 설정하기 {#set-up-your-ethereum-wallet} + +사용자가 스마트 계약과 상호 작용하려면 이더리움 지갑을 탈중앙화앱에 연결해야 합니다. + +### MetaMask 다운로드하기 {#download-metamask} + +이 튜토리얼에서는 이더리움 계정 주소를 관리하는 데 사용되는 브라우저의 가상 지갑인 MetaMask를 사용합니다. 이더리움의 트랜잭션 작동 방식에 대해 더 자세히 알아보려면 [이 페이지](/developers/docs/transactions/)를 확인하세요. + +[여기](https://metamask.io/download)에서 MetaMask 계정을 무료로 다운로드하고 생성할 수 있습니다. 계정을 생성하거나 이미 계정이 있는 경우 오른쪽 상단에서 “Ropsten 테스트 네트워크”로 전환해야 합니다\(실제 돈을 다루지 않도록 하기 위함입니다\). + +### 파우셋(Faucet)에서 이더 추가하기 {#add-ether-from-faucet} + +NFT를 민팅하거나 이더리움 블록체인에서 트랜잭션에 서명하려면 가짜 Eth가 필요합니다. Eth를 받으려면 [Ropsten 파우셋](https://faucet.ropsten.be/)으로 이동하여 Ropsten 계정 주소를 입력한 다음 “Send Ropsten Eth”를 클릭하세요. 곧 MetaMask 계정에서 Eth를 볼 수 있을 것입니다! + +### 잔액 확인하기 {#check-your-balance} + +잔액이 있는지 다시 확인하기 위해 [Alchemy의 컴포저 도구](https://composer.alchemyapi.io/?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D)를 사용하여 [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) 요청을 해봅시다. 그러면 지갑에 있는 Eth의 양이 반환됩니다. MetaMask 계정 주소를 입력하고 "Send Request"를 클릭하면 다음과 같은 응답이 표시됩니다. + +```text +{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"} +``` + +**참고:** 이 결과는 eth가 아닌 wei 단위입니다. Wei는 ether의 최소 단위로 사용됩니다. wei에서 eth로의 변환은 1 eth = 10¹⁸ wei입니다. 따라서 0xde0b6b3a7640000을 10진수로 변환하면 1\*10¹⁸이 되고 이는 1eth와 같습니다. + +휴! 우리의 가짜 돈이 다 있군요! + +## MetaMask를 UI에 연결하기 {#connect-metamask-to-your-UI} + +이제 MetaMask 지갑이 설정되었으니, 탈중앙화앱을 연결해 봅시다! + +우리는 [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) 패러다임을 따르고자 하므로, 탈중앙화앱의 로직, 데이터, 규칙을 관리하는 함수를 포함하는 별도의 파일을 만들고, 그 함수들을 프런트엔드(Minter.js 컴포넌트)에 전달할 것입니다. + +### `connectWallet` 함수 {#connect-wallet-function} + +이를 위해 `src` 디렉터리에 `utils`라는 새 폴더를 만들고 그 안에 `interact.js`라는 파일을 추가합니다. 이 파일에는 모든 지갑 및 스마트 계약 상호 작용 함수가 포함됩니다. + +`interact.js` 파일에 `connectWallet` 함수를 작성한 다음, `Minter.js` 컴포넌트에서 이 함수를 가져와 호출할 것입니다. + +`interact.js` 파일에 다음을 추가하세요. + +```javascript +export const connectWallet = async () => { + if (window.ethereum) { + try { + const addressArray = await window.ethereum.request({ + method: "eth_requestAccounts", + }) + const obj = { + status: "👆🏽 위 텍스트 필드에 메시지를 작성하세요.", + address: addressArray[0], + } + return obj + } catch (err) { + return { + address: "", + status: "😥 " + err.message, + } + } + } else { + return { + address: "", + status: ( + +

+ {" "} + 🦊 + 브라우저에 가상 이더리움 지갑인 MetaMask를 설치해야 합니다. + +

+
+ ), + } + } +} +``` + +이 코드가 무엇을 하는지 분석해 봅시다: + +먼저, 함수는 브라우저에서 `window.ethereum`이 활성화되어 있는지 확인합니다. + +`window.ethereum`은 MetaMask 및 기타 지갑 제공업체에서 주입하는 글로벌 API로, 웹사이트가 사용자의 이더리움 계정을 요청할 수 있도록 합니다. 승인되면 사용자가 연결된 블록체인에서 데이터를 읽고 사용자에게 메시지 및 트랜잭션에 서명하도록 제안할 수 있습니다. 자세한 내용은 [MetaMask 문서](https://docs.metamask.io/guide/ethereum-provider.html#table-of-contents)를 확인하세요! + +`window.ethereum`이 _없으면_ MetaMask가 설치되지 않았다는 의미입니다. 그러면 `address`가 빈 문자열로 반환되고 `status` JSX 객체는 사용자가 MetaMask를 설치해야 한다는 것을 전달하는 JSON 객체가 반환됩니다. + +**우리가 작성하는 대부분의 함수는 상태 변수와 UI를 업데이트하는 데 사용할 수 있는 JSON 객체를 반환할 것입니다.** + +이제 `window.ethereum`이 _있으면_ 상황이 흥미로워집니다. + +try/catch 루프를 사용하여 [`window.ethereum.request({ method: "eth_requestAccounts" });`](https://docs.metamask.io/guide/rpc-api.html#eth-requestaccounts)를 호출하여 MetaMask에 연결을 시도합니다. 이 함수를 호출하면 브라우저에서 MetaMask가 열리고 사용자에게 지갑을 탈중앙화앱에 연결하라는 메시지가 표시됩니다. + +- 사용자가 연결을 선택하면 `method: "eth_requestAccounts"`는 탈중앙화앱에 연결된 사용자의 모든 계정 주소를 포함하는 배열을 반환합니다. 전체적으로 `connectWallet` 함수는 이 배열의 _첫 번째_ `address`\(9번째 줄 참조\)와 사용자에게 스마트 계약에 메시지를 작성하라는 `status` 메시지를 포함하는 JSON 객체를 반환합니다. +- 사용자가 연결을 거부하면 JSON 객체는 반환된 `address`에 대해 빈 문자열을 포함하고 사용자가 연결을 거부했음을 반영하는 `status` 메시지를 포함합니다. + +### Minter.js UI 컴포넌트에 connectWallet 함수 추가하기 {#add-connect-wallet} + +이제 `connectWallet` 함수를 작성했으므로 `Minter.js` 컴포넌트에 연결해 봅시다. + +먼저 `Minter.js` 파일 상단에 `import { connectWallet } from "./utils/interact.js";`를 추가하여 함수를 `Minter.js` 파일로 가져와야 합니다. `Minter.js`의 처음 11줄은 이제 다음과 같아야 합니다. + +```javascript +import { useEffect, useState } from "react"; +import { connectWallet } from "./utils/interact.js"; + +const Minter = (props) => { + + //상태 변수 + const [walletAddress, setWallet] = useState(""); + const [status, setStatus] = useState(""); + const [name, setName] = useState(""); + const [description, setDescription] = useState(""); + const [url, setURL] = useState(""); +``` + +그런 다음 `connectWalletPressed` 함수 내에서 가져온 `connectWallet` 함수를 다음과 같이 호출합니다. + +```javascript +const connectWalletPressed = async () => { + const walletResponse = await connectWallet() + setStatus(walletResponse.status) + setWallet(walletResponse.address) +} +``` + +`interact.js` 파일에서 `Minter.js` 컴포넌트의 기능 대부분이 추상화된 것을 눈치채셨나요? 이것은 M-V-C 패러다임을 준수하기 위함입니다! + +`connectWalletPressed`에서 가져온 `connectWallet` 함수를 await 호출하고, 그 응답을 사용하여 상태 훅을 통해 `status` 및 `walletAddress` 변수를 업데이트합니다. + +이제 `Minter.js`와 `interact.js` 두 파일을 모두 저장하고 지금까지의 UI를 테스트해 봅시다. + +localhost:3000에서 브라우저를 열고 페이지 오른쪽 상단의 "지갑 연결" 버튼을 누릅니다. + +MetaMask가 설치되어 있다면, 지갑을 탈중앙화앱에 연결하라는 메시지가 표시됩니다. 연결 초대를 수락합니다. + +지갑 버튼에 주소가 연결되었음을 나타내는 것을 볼 수 있습니다. + +다음으로, 페이지를 새로고침해 보세요... 이상하네요. 지갑이 이미 연결되어 있음에도 불구하고 지갑 버튼은 MetaMask에 연결하라는 메시지를 표시합니다... + +하지만 걱정하지 마세요! 주소가 이미 탈중앙화앱에 연결되어 있는지 확인하고 그에 따라 UI를 업데이트하는 `getCurrentWalletConnected`라는 함수를 구현하여 이 문제를 쉽게 해결할 수 있습니다! + +### getCurrentWalletConnected 함수 {#get-current-wallet} + +`interact.js` 파일에 다음과 같은 `getCurrentWalletConnected` 함수를 추가하세요: + +```javascript +export const getCurrentWalletConnected = async () => { + if (window.ethereum) { + try { + const addressArray = await window.ethereum.request({ + method: "eth_accounts", + }) + if (addressArray.length > 0) { + return { + address: addressArray[0], + status: "👆🏽 위 텍스트 필드에 메시지를 작성하세요.", + } + } else { + return { + address: "", + status: "🦊 오른쪽 상단 버튼을 사용하여 MetaMask에 연결하세요.", + } + } + } catch (err) { + return { + address: "", + status: "😥 " + err.message, + } + } + } else { + return { + address: "", + status: ( + +

+ {" "} + 🦊 + 브라우저에 가상 이더리움 지갑인 MetaMask를 설치해야 합니다. + +

+
+ ), + } + } +} +``` + +이 코드는 이전에 작성한 `connectWallet` 함수와 _매우_ 유사합니다. + +주요 차이점은 사용자가 지갑을 연결하기 위해 MetaMask를 여는 `eth_requestAccounts` 메서드를 호출하는 대신, 여기서는 현재 탈중앙화앱에 연결된 MetaMask 주소를 포함하는 배열을 반환하는 `eth_accounts` 메서드를 호출한다는 것입니다. + +이 함수가 어떻게 작동하는지 보려면, `Minter.js` 컴포넌트의 `useEffect` 함수에서 이 함수를 호출해 봅시다. + +`connectWallet`에서 했던 것처럼 `interact.js` 파일에서 이 함수를 `Minter.js` 파일로 다음과 같이 가져와야 합니다. + +```javascript +import { useEffect, useState } from "react" +import { + connectWallet, + getCurrentWalletConnected, //여기서 가져오기 +} from "./utils/interact.js" +``` + +이제 `useEffect` 함수에서 간단히 호출합니다. + +```javascript +useEffect(async () => { + const { address, status } = await getCurrentWalletConnected() + setWallet(address) + setStatus(status) +}, []) +``` + +`getCurrentWalletConnected` 호출의 응답을 사용하여 `walletAddress`와 `status` 상태 변수를 업데이트하는 것을 확인하세요. + +이 코드를 추가한 후 브라우저 창을 새로고침해 보세요. 버튼에는 연결되었다고 표시되고 연결된 지갑 주소의 미리보기가 표시되어야 합니다 - 새로고침 후에도 말이죠! + +### addWalletListener 구현하기 {#implement-add-wallet-listener} + +탈중앙화앱 지갑 설정의 마지막 단계는 사용자가 연결을 끊거나 계정을 전환할 때와 같이 지갑의 상태가 변경될 때 UI가 업데이트되도록 지갑 리스너를 구현하는 것입니다. + +`Minter.js` 파일에 다음과 같은 `addWalletListener` 함수를 추가하세요: + +```javascript +function addWalletListener() { + if (window.ethereum) { + window.ethereum.on("accountsChanged", (accounts) => { + if (accounts.length > 0) { + setWallet(accounts[0]) + setStatus("👆🏽 위 텍스트 필드에 메시지를 작성하세요.") + } else { + setWallet("") + setStatus("🦊 오른쪽 상단 버튼을 사용하여 MetaMask에 연결하세요.") + } + }) + } else { + setStatus( +

+ {" "} + 🦊 + 브라우저에 가상 이더리움 지갑인 MetaMask를 설치해야 합니다. + +

+ ) + } +} +``` + +여기서 무슨 일이 일어나는지 간단히 살펴보겠습니다. + +- 먼저, 함수는 `window.ethereum`이 활성화되어 있는지(즉, MetaMask가 설치되어 있는지) 확인합니다. + - 그렇지 않다면, `status` 상태 변수를 사용자가 MetaMask를 설치하도록 유도하는 JSX 문자열로 설정합니다. + - 활성화된 경우, 3번째 줄에서 `window.ethereum.on("accountsChanged")` 리스너를 설정하여 사용자가 탈중앙화앱에 추가 계정을 연결하거나 계정을 전환하거나 계정 연결을 끊는 등 MetaMask 지갑의 상태 변화를 수신합니다. 연결된 계정이 하나 이상 있는 경우, `walletAddress` 상태 변수는 리스너가 반환한 `accounts` 배열의 첫 번째 계정으로 업데이트됩니다. 그렇지 않으면 `walletAddress`는 빈 문자열로 설정됩니다. + +마지막으로 `useEffect` 함수에서 호출해야 합니다. + +```javascript +useEffect(async () => { + const { address, status } = await getCurrentWalletConnected() + setWallet(address) + setStatus(status) + + addWalletListener() +}, []) +``` + +그리고 짜잔! 모든 지갑 기능 프로그래밍을 완료했습니다! 이제 지갑이 설정되었으니, NFT를 어떻게 민팅할지 알아봅시다! + +## NFT 메타데이터 101 {#nft-metadata-101} + +이 튜토리얼의 0단계에서 방금 이야기한 NFT 메타데이터를 기억하시나요? 이 메타데이터는 디지털 자산, 이름, 설명 및 기타 속성과 같은 속성을 가질 수 있도록 하여 NFT에 생명을 불어넣습니다. + +이 메타데이터를 JSON 객체로 구성하여 저장해야 스마트 계약의 `mintNFT` 함수를 호출할 때 `tokenURI` 매개변수로 전달할 수 있습니다. + +"자산 링크", "이름", "설명" 필드의 텍스트는 NFT 메타데이터의 다양한 속성을 구성합니다. 이 메타데이터를 JSON 객체로 포맷할 것이지만, 이 JSON 객체를 저장할 수 있는 몇 가지 옵션이 있습니다. + +- 이더리움 블록체인에 저장할 수 있지만, 그렇게 하면 비용이 매우 많이 들 것입니다. +- AWS나 Firebase와 같은 중앙화된 서버에 저장할 수도 있습니다. 하지만 그것은 우리의 탈중앙화 정신에 어긋납니다. +- 분산 파일 시스템에서 데이터를 저장하고 공유하기 위한 탈중앙화 프로토콜 및 P2P 네트워크인 IPFS를 사용할 수 있습니다. 이 프로토콜은 탈중앙화되어 있고 무료이므로 최선의 선택입니다! + +메타데이터를 IPFS에 저장하기 위해 편리한 IPFS API 및 툴킷인 [Pinata](https://pinata.cloud/)를 사용할 것입니다. 다음 단계에서 정확히 어떻게 하는지 설명하겠습니다! + +## Pinata를 사용하여 메타데이터를 IPFS에 고정하기 {#use-pinata-to-pin-your-metadata-to-IPFS} + +[Pinata](https://pinata.cloud/) 계정이 없다면 [여기](https://app.pinata.cloud/auth/signup)에서 무료 계정에 가입하고 이메일과 계정 확인 단계를 완료하세요. + +### Pinata API 키 만들기 {#create-pinata-api-key} + +[https://pinata.cloud/keys](https://pinata.cloud/keys) 페이지로 이동한 다음 상단의 "새 키" 버튼을 선택하고 관리자 위젯을 활성화로 설정한 후 키의 이름을 지정합니다. + +그러면 API 정보가 포함된 팝업이 표시됩니다. 안전한 곳에 보관해야 합니다. + +이제 키가 설정되었으므로 프로젝트에 추가하여 사용할 수 있도록 합시다. + +### .env 파일 만들기 {#create-a-env} + +Pinata 키와 시크릿을 환경 파일에 안전하게 저장할 수 있습니다. 프로젝트 디렉터리에 [dotenv 패키지](https://www.npmjs.com/package/dotenv)를 설치해 봅시다. + +터미널에서 새 탭을 열고(로컬 호스트를 실행하는 탭과 별개로) `minter-starter-files` 폴더에 있는지 확인한 다음 터미널에서 다음 명령을 실행합니다. + +```text +npm install dotenv --save +``` + +다음으로, 명령줄에 다음을 입력하여 `minter-starter-files`의 루트 디렉터리에 `.env` 파일을 만듭니다. + +```javascript +vim.env +``` + +이렇게 하면 vim(텍스트 편집기)에서 `.env` 파일이 열립니다. 저장하려면 키보드에서 "esc" + ":" + "q"를 순서대로 누릅니다. + +다음으로, VSCode에서 `.env` 파일로 이동하여 다음과 같이 Pinata API 키와 API 시크릿을 추가합니다. + +```text +REACT_APP_PINATA_KEY = +REACT_APP_PINATA_SECRET = +``` + +파일을 저장하면 JSON 메타데이터를 IPFS에 업로드하는 함수를 작성할 준비가 된 것입니다! + +### pinJSONToIPFS 구현하기 {#pin-json-to-ipfs} + +다행히 Pinata에는 [JSON 데이터를 IPFS에 업로드하기 위한 API](https://docs.pinata.cloud/api-reference/endpoint/ipfs/pin-json-to-ipfs#pin-json)와 약간의 수정을 통해 사용할 수 있는 편리한 axios가 포함된 JavaScript 예제가 있습니다. + +`utils` 폴더에 `pinata.js`라는 다른 파일을 만들고 다음과 같이 .env 파일에서 Pinata 시크릿과 키를 가져옵시다. + +```javascript +require("dotenv").config() +const key = process.env.REACT_APP_PINATA_KEY +const secret = process.env.REACT_APP_PINATA_SECRET +``` + +다음으로 아래의 추가 코드를 `pinata.js` 파일에 붙여넣습니다. 걱정 마세요. 모든 것이 무엇을 의미하는지 설명해 드리겠습니다! + +```javascript +require("dotenv").config() +const key = process.env.REACT_APP_PINATA_KEY +const secret = process.env.REACT_APP_PINATA_SECRET + +const axios = require("axios") + +export const pinJSONToIPFS = async (JSONBody) => { + const url = `https://api.pinata.cloud/pinning/pinJSONToIPFS` + //axios POST 요청을 Pinata에 보내기 ⬇️ + return axios + .post(url, JSONBody, { + headers: { + pinata_api_key: key, + pinata_secret_api_key: secret, + }, + }) + .then(function (response) { + return { + success: true, + pinataUrl: + "https://gateway.pinata.cloud/ipfs/" + response.data.IpfsHash, + } + }) + .catch(function (error) { + console.log(error) + return { + success: false, + message: error.message, + } + }) +} +``` + +그래서 이 코드는 정확히 무엇을 할까요? + +먼저, 브라우저와 node.js를 위한 프라미스 기반 HTTP 클라이언트인 [axios](https://www.npmjs.com/package/axios)를 가져옵니다. 이를 사용하여 Pinata에 요청할 것입니다. + +그런 다음, 입력으로 `JSONBody`를, 헤더에 Pinata API 키와 시크릿을 받는 비동기 함수 `pinJSONToIPFS`가 있습니다. 이 모든 것은 `pinJSONToIPFS` API에 POST 요청을 하기 위한 것입니다. + +- 이 POST 요청이 성공하면, 함수는 `success` 불리언이 true이고 메타데이터가 고정된 `pinataUrl`을 포함하는 JSON 객체를 반환합니다. 반환된 이 `pinataUrl`을 스마트 계약의 민팅 함수에 대한 `tokenURI` 입력으로 사용할 것입니다. +- 이 게시물 요청이 실패하면, 함수는 `success` 불리언이 false이고 오류를 전달하는 `message` 문자열을 포함하는 JSON 객체를 반환합니다. + +`connectWallet` 함수 반환 유형과 마찬가지로, 매개변수를 사용하여 상태 변수와 UI를 업데이트할 수 있도록 JSON 객체를 반환합니다. + +## 스마트 계약 로드하기 {#load-your-smart-contract} + +이제 `pinJSONToIPFS` 함수를 통해 NFT 메타데이터를 IPFS에 업로드할 방법이 생겼으므로, `mintNFT` 함수를 호출할 수 있도록 스마트 계약의 인스턴스를 로드할 방법이 필요합니다. + +앞서 언급했듯이 이 튜토리얼에서는 [기존 NFT 스마트 계약](https://ropsten.etherscan.io/address/0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE)을 사용할 것입니다. 그러나 어떻게 만들었는지 배우거나 직접 만들고 싶다면 다른 튜토리얼인 ["NFT 만드는 방법"](https://www.alchemy.com/docs/how-to-create-an-nft)을 확인하는 것을 적극 권장합니다. + +### 계약 ABI {#contract-abi} + +파일을 자세히 살펴보셨다면 `src` 디렉터리에 `contract-abi.json` 파일이 있다는 것을 눈치채셨을 것입니다. ABI는 계약이 어떤 함수를 호출할지 지정하고 함수가 예상하는 형식으로 데이터를 반환하도록 보장하는 데 필요합니다. + +또한 이더리움 블록체인에 연결하고 스마트 계약을 로드하려면 Alchemy API 키와 Alchemy Web3 API가 필요합니다. + +### Alchemy API 키 만들기 {#create-alchemy-api} + +아직 Alchemy 계정이 없다면, [여기에서 무료로 가입하세요.](https://alchemy.com/?a=eth-org-nft-minter) + +Alchemy 계정을 생성한 후에는 앱을 생성하여 API 키를 생성할 수 있습니다. 이를 통해 Ropsten 테스트 네트워크에 연결할 수 있습니다. + +탐색 모음에서 “앱” 위로 마우스를 가져간 다음 “앱 만들기”를 클릭하여 Alchemy 대시보드에서 “앱 만들기” 페이지로 이동합니다. + +앱 이름을 “My First NFT!”로 지정하고 간단한 설명을 제공한 다음, 앱 기록에 사용될 환경으로 “스테이징”을 선택하고 네트워크로 “Ropsten”을 선택합니다. + +"Create app" 을 클릭하세요. 당신의 앱이 아래 테이블에 나타날겁니다! + +좋습니다. 이제 HTTP Alchemy API URL을 만들었으니 클립보드에 복사하세요... + +...그리고 `.env` 파일에 추가합시다. 전체적으로 .env 파일은 다음과 같아야 합니다. + +```text +REACT_APP_PINATA_KEY = +REACT_APP_PINATA_SECRET = +REACT_APP_ALCHEMY_KEY = https://eth-ropsten.alchemyapi.io/v2/ +``` + +이제 계약 ABI와 Alchemy API 키가 있으므로 [Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3)을 사용하여 스마트 계약을 로드할 준비가 되었습니다. + +### Alchemy Web3 엔드포인트 및 계약 설정하기 {#setup-alchemy-endpoint} + +먼저, 아직 설치하지 않았다면, 터미널에서 홈 디렉터리 `nft-minter-tutorial`로 이동하여 [Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3)을 설치해야 합니다: + +```text +cd .. +npm install @alch/alchemy-web3 +``` + +다음으로 `interact.js` 파일로 돌아갑시다. 파일 상단에 다음 코드를 추가하여 .env 파일에서 Alchemy 키를 가져오고 Alchemy Web3 엔드포인트를 설정합니다. + +```javascript +require("dotenv").config() +const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY +const { createAlchemyWeb3 } = require("@alch/alchemy-web3") +const web3 = createAlchemyWeb3(alchemyKey) +``` + +[Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3)는 [Web3.js](https://docs.web3js.org/)의 래퍼로, 향상된 API 메서드와 기타 중요한 이점을 제공하여 웹3 개발자로서의 삶을 더 쉽게 만듭니다. 최소한의 구성만으로 바로 앱에서 사용할 수 있도록 설계되었습니다! + +다음으로, 계약 ABI와 계약 주소를 파일에 추가합시다. + +```javascript +require("dotenv").config() +const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY +const { createAlchemyWeb3 } = require("@alch/alchemy-web3") +const web3 = createAlchemyWeb3(alchemyKey) + +const contractABI = require("../contract-abi.json") +const contractAddress = "0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE" +``` + +이 두 가지가 모두 준비되었으니 이제 민팅 함수 코딩을 시작할 준비가 되었습니다! + +## mintNFT 함수 구현하기 {#implement-the-mintnft-function} + +`interact.js` 파일 내에서 이름 그대로 NFT를 민팅할 `mintNFT` 함수를 정의해 봅시다. + +Pinata에 메타데이터를 고정하고, Alchemy Web3으로 스마트 계약을 로드하며, MetaMask로 트랜잭션에 서명하는 등 수많은 비동기 호출을 할 것이므로, 우리 함수도 비동기적일 것입니다. + +함수에 대한 세 가지 입력은 디지털 자산의 `url`, `name`, `description`입니다. `connectWallet` 함수 아래에 다음 함수 시그니처를 추가하세요. + +```javascript +export const mintNFT = async (url, name, description) => {} +``` + +### 입력 오류 처리 {#input-error-handling} + +당연히 함수 시작 부분에 일종의 입력 오류 처리를 두어 입력 매개변수가 올바르지 않으면 이 함수를 종료하는 것이 합리적입니다. 함수 내에 다음 코드를 추가합시다. + +```javascript +export const mintNFT = async (url, name, description) => { + //오류 처리 + if (url.trim() == "" || name.trim() == "" || description.trim() == "") { + return { + success: false, + status: "❗민팅하기 전에 모든 필드가 완료되었는지 확인하세요.", + } + } +} +``` + +기본적으로 입력 매개변수 중 하나라도 빈 문자열이면 `success` 불리언이 false이고 `status` 문자열이 UI의 모든 필드가 완료되어야 함을 전달하는 JSON 객체를 반환합니다. + +### 메타데이터를 IPFS에 업로드하기 {#upload-metadata-to-ipfs} + +메타데이터가 올바르게 포맷되었음을 확인한 후, 다음 단계는 이를 JSON 객체로 래핑하고 우리가 작성한 `pinJSONToIPFS`를 통해 IPFS에 업로드하는 것입니다! + +이를 위해 먼저 `pinJSONToIPFS` 함수를 `interact.js` 파일로 가져와야 합니다. `interact.js`의 맨 위에 다음을 추가합시다. + +```javascript +import { pinJSONToIPFS } from "./pinata.js" +``` + +`pinJSONToIPFS`가 JSON 본문을 받는다는 것을 기억하세요. 따라서 호출하기 전에 `url`, `name`, `description` 매개변수를 JSON 객체로 포맷해야 합니다. + +`metadata`라는 JSON 객체를 만들고 이 `metadata` 매개변수로 `pinJSONToIPFS`를 호출하도록 코드를 업데이트합시다. + +```javascript +export const mintNFT = async (url, name, description) => { + //오류 처리 + if (url.trim() == "" || name.trim() == "" || description.trim() == "") { + return { + success: false, + status: "❗민팅하기 전에 모든 필드가 완료되었는지 확인하세요.", + } + } + + //메타데이터 만들기 + const metadata = new Object() + metadata.name = name + metadata.image = url + metadata.description = description + + //pinata 호출 만들기 + const pinataResponse = await pinJSONToIPFS(metadata) + if (!pinataResponse.success) { + return { + success: false, + status: "😢 tokenURI를 업로드하는 동안 문제가 발생했습니다.", + } + } + const tokenURI = pinataResponse.pinataUrl +} +``` + +`pinJSONToIPFS(metadata)` 호출의 응답을 `pinataResponse` 객체에 저장하는 것을 확인하세요. 그런 다음 이 객체에서 오류를 구문 분석합니다. + +오류가 있으면 `success` 불리언이 false이고 `status` 문자열이 호출 실패를 전달하는 JSON 객체를 반환합니다. 그렇지 않으면 `pinataResponse`에서 `pinataURL`을 추출하여 `tokenURI` 변수로 저장합니다. + +이제 파일 상단에서 초기화한 Alchemy Web3 API를 사용하여 스마트 계약을 로드할 시간입니다. `mintNFT` 함수 하단에 다음 코드 줄을 추가하여 `window.contract` 전역 변수에 계약을 설정하세요. + +```javascript +window.contract = await new web3.eth.Contract(contractABI, contractAddress) +``` + +`mintNFT` 함수에 마지막으로 추가할 것은 이더리움 트랜잭션입니다. + +```javascript +//이더리움 트랜잭션 설정 +const transactionParameters = { + to: contractAddress, // 계약 게시 중을 제외하고 필수입니다. + from: window.ethereum.selectedAddress, // 사용자의 활성 주소와 일치해야 합니다. + data: window.contract.methods + .mintNFT(window.ethereum.selectedAddress, tokenURI) + .encodeABI(), //NFT 스마트 계약 호출 +} + +//MetaMask를 통해 트랜잭션 서명 +try { + const txHash = await window.ethereum.request({ + method: "eth_sendTransaction", + params: [transactionParameters], + }) + return { + success: true, + status: + "✅ Etherscan에서 트랜잭션을 확인하세요: https://ropsten.etherscan.io/tx/" + + txHash, + } +} catch (error) { + return { + success: false, + status: "😥 문제가 발생했습니다: " + error.message, + } +} +``` + +이미 이더리움 트랜잭션에 익숙하다면, 구조가 본 것과 매우 유사하다는 것을 알 수 있습니다. + +- 먼저, 트랜잭션 매개변수를 설정합니다. + - `to`는 수신자 주소(우리의 스마트 계약)를 지정합니다. + - `from`은 트랜잭션의 서명자(사용자의 MetaMask에 연결된 주소: `window.ethereum.selectedAddress`)를 지정합니다. + - `data`는 `tokenURI`와 사용자의 지갑 주소(`window.ethereum.selectedAddress`)를 입력으로 받는 스마트 계약의 `mintNFT` 메서드 호출을 포함합니다. +- 그런 다음, MetaMask에 트랜잭션 서명을 요청하는 `window.ethereum.request`를 await 호출합니다. 이 요청에서 우리는 eth 메서드(eth_SentTransaction)를 지정하고 `transactionParameters`를 전달하는 것을 확인하세요. 이 시점에서 MetaMask가 브라우저에서 열리고 사용자에게 트랜잭션에 서명하거나 거부하라는 메시지를 표시합니다. + - 트랜잭션이 성공하면 함수는 불리언 `success`가 true로 설정되고 `status` 문자열이 사용자에게 트랜잭션에 대한 자세한 정보를 Etherscan에서 확인하도록 유도하는 JSON 객체를 반환합니다. + - 트랜잭션이 실패하면 함수는 `success` 불리언이 false로 설정되고 `status` 문자열이 오류 메시지를 전달하는 JSON 객체를 반환합니다. + +전체적으로 `mintNFT` 함수는 다음과 같아야 합니다. + +```javascript +export const mintNFT = async (url, name, description) => { + //오류 처리 + if (url.trim() == "" || name.trim() == "" || description.trim() == "") { + return { + success: false, + status: "❗민팅하기 전에 모든 필드가 완료되었는지 확인하세요.", + } + } + + //메타데이터 만들기 + const metadata = new Object() + metadata.name = name + metadata.image = url + metadata.description = description + + //pinata 핀 요청 + const pinataResponse = await pinJSONToIPFS(metadata) + if (!pinataResponse.success) { + return { + success: false, + status: "😢 tokenURI를 업로드하는 동안 문제가 발생했습니다.", + } + } + const tokenURI = pinataResponse.pinataUrl + + //스마트 계약 로드 + window.contract = await new web3.eth.Contract(contractABI, contractAddress) //loadContract(); + + //이더리움 트랜잭션 설정 + const transactionParameters = { + to: contractAddress, // 계약 게시 중을 제외하고 필수입니다. + from: window.ethereum.selectedAddress, // 사용자의 활성 주소와 일치해야 합니다. + data: window.contract.methods + .mintNFT(window.ethereum.selectedAddress, tokenURI) + .encodeABI(), //NFT 스마트 계약 호출 + } + + //MetaMask를 통해 트랜잭션 서명 + try { + const txHash = await window.ethereum.request({ + method: "eth_sendTransaction", + params: [transactionParameters], + }) + return { + success: true, + status: + "✅ Etherscan에서 트랜잭션을 확인하세요: https://ropsten.etherscan.io/tx/" + + txHash, + } + } catch (error) { + return { + success: false, + status: "😥 문제가 발생했습니다: " + error.message, + } + } +} +``` + +정말 거대한 함수군요! 이제 `mintNFT` 함수를 `Minter.js` 컴포넌트에 연결하기만 하면 됩니다... + +## mintNFT를 Minter.js 프런트엔드에 연결하기 {#connect-our-frontend} + +`Minter.js` 파일을 열고 상단의 `import { connectWallet, getCurrentWalletConnected } from "./utils/interact.js";` 줄을 다음과 같이 업데이트하세요. + +```javascript +import { + connectWallet, + getCurrentWalletConnected, + mintNFT, +} from "./utils/interact.js" +``` + +마지막으로 `onMintPressed` 함수를 구현하여 가져온 `mintNFT` 함수를 await 호출하고 트랜잭션 성공 여부를 반영하도록 `status` 상태 변수를 업데이트합니다. + +```javascript +const onMintPressed = async () => { + const { status } = await mintNFT(url, name, description) + setStatus(status) +} +``` + +## NFT를 라이브 웹사이트에 배포하기 {#deploy-your-NFT} + +사용자가 상호 작용할 수 있도록 프로젝트를 라이브로 만들 준비가 되셨나요? Minter를 라이브 웹사이트에 배포하는 방법은 [이 튜토리얼](https://docs.alchemy.com/alchemy/tutorials/nft-minter/how-do-i-deploy-nfts-online)을 확인하세요. + +마지막 한 단계... + +## 블록체인 세계를 강타하세요 {#take-the-blockchain-world-by-storm} + +농담입니다. 튜토리얼의 끝까지 오셨습니다! + +요약하자면, NFT 민터를 구축함으로써 다음을 성공적으로 배웠습니다. + +- 프런트엔드 프로젝트를 통해 MetaMask에 연결하기 +- 프런트엔드에서 스마트 계약 메서드 호출하기 +- MetaMask를 사용하여 트랜잭션에 서명하기 + +아마도 탈중앙화앱을 통해 민팅된 NFT를 지갑에 표시하고 싶으실 것입니다. 그러니 [지갑에서 NFT를 보는 방법](https://www.alchemy.com/docs/how-to-view-your-nft-in-your-mobile-wallet)에 대한 빠른 튜토리얼을 꼭 확인하세요! + +그리고 언제나처럼 질문이 있으시면 [Alchemy Discord](https://discord.gg/gWuC7zB)에서 도와드리겠습니다. 이 튜토리얼의 개념을 향후 프로젝트에 어떻게 적용할지 기대됩니다! diff --git a/public/content/translations/ko/developers/tutorials/optimism-std-bridge-annotated-code/index.md b/public/content/translations/ko/developers/tutorials/optimism-std-bridge-annotated-code/index.md new file mode 100644 index 00000000000..bfc45b3090f --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/optimism-std-bridge-annotated-code/index.md @@ -0,0 +1,1352 @@ +--- +title: "Optimism 표준 브리지 컨트랙트 둘러보기" +description: "Optimism의 표준 브리지는 어떻게 작동하나요? 왜 이런 방식으로 작동하나요?" +author: Ori Pomerantz +tags: [ "Solidity", "브리지", "레이어 2" ] +skill: intermediate +published: 2022-03-30 +lang: ko +--- + +[Optimism](https://www.optimism.io/)은 [/developers/docs/scaling/optimistic-rollups/](낙관적 롤업)입니다. +낙관적 롤업은 네트워크의 모든 노드가 아닌 소수의 노드에서만 트랜잭션을 처리하기 때문에 이더리움 메인넷(레이어 1 또는 L1이라고도 함)보다 훨씬 저렴한 가격으로 트랜잭션을 처리할 수 있습니다. +동시에 모든 데이터가 L1에 기록되므로 메인넷의 모든 무결성 및 가용성 보장을 통해 모든 것을 증명하고 재구성할 수 있습니다. + +Optimism(또는 다른 L2)에서 L1 자산을 사용하려면 자산을 [/bridges/#prerequisites](브리지)해야 합니다. +이를 달성하는 한 가지 방법은 사용자가 L1에 자산(ETH 및 [/developers/docs/standards/tokens/erc-20/](ERC-20 토큰)이 가장 일반적임)을 락업하고 L2에서 사용할 수 있는 동등한 자산을 받는 것입니다. +결국, 자산을 소유하게 된 사람은 누구든 L1으로 다시 브리지하기를 원할 수 있습니다. +이때 자산은 L2에서 소각된 다음 L1에서 사용자에게 다시 릴리스됩니다. + +이것이 [Optimism 표준 브리지](https://docs.optimism.io/app-developers/bridging/standard-bridge)가 작동하는 방식입니다. +이 글에서는 해당 브리지의 소스 코드를 살펴보고 잘 작성된 Solidity 코드의 예시로써 작동 방식을 연구합니다. + +## 제어 흐름 {#control-flows} + +브리지에는 두 가지 주요 흐름이 있습니다. + +- 예치(L1에서 L2로) +- 인출(L2에서 L1로) + +### 예치 흐름 {#deposit-flow} + +#### 레이어 1 {#deposit-flow-layer-1} + +1. ERC-20을 예치하는 경우, 예치자는 예치되는 금액을 사용할 수 있는 허용량을 브리지에 부여합니다 +2. 예치자는 L1 브리지(`depositERC20`, `depositERC20To`, `depositETH` 또는 `depositETHTo`)를 호출합니다 +3. L1 브리지는 브리지된 자산의 소유권을 가져옵니다 + - ETH: 자산은 호출의 일부로 예치자에 의해 전송됩니다 + - ERC-20: 자산은 예치자가 제공한 허용량을 사용하여 브리지에 의해 자체적으로 전송됩니다 +4. L1 브리지는 교차 도메인 메시지 메커니즘을 사용하여 L2 브리지에서 `finalizeDeposit`을 호출합니다 + +#### 레이어 2 {#deposit-flow-layer-2} + +5. L2 브리지는 `finalizeDeposit` 호출이 합법적인지 확인합니다. + - 교차 도메인 메시지 컨트랙트에서 왔습니다 + - 원래 L1의 브리지에서 왔습니다 +6. L2 브리지는 L2의 ERC-20 토큰 컨트랙트가 올바른 것인지 확인합니다. + - L2 컨트랙트는 L1 대응 컨트랙트가 L1에서 토큰이 온 곳과 동일하다고 보고합니다 + - L2 컨트랙트는 올바른 인터페이스를 지원한다고 보고합니다([ERC-165 사용](https://eips.ethereum.org/EIPS/eip-165)). +7. L2 컨트랙트가 올바른 경우, 이를 호출하여 적절한 수의 토큰을 적절한 주소로 민팅합니다. 그렇지 않은 경우, 사용자가 L1에서 토큰을 청구할 수 있도록 인출 절차를 시작합니다. + +### 인출 흐름 {#withdrawal-flow} + +#### 레이어 2 {#withdrawal-flow-layer-2} + +1. 인출자는 L2 브리지(`withdraw` 또는 `withdrawTo`)를 호출합니다 +2. L2 브리지는 `msg.sender`에 속하는 적절한 수의 토큰을 소각합니다 +3. L2 브리지는 교차 도메인 메시지 메커니즘을 사용하여 L1 브리지에서 `finalizeETHWithdrawal` 또는 `finalizeERC20Withdrawal`을 호출합니다 + +#### 레이어 1 {#withdrawal-flow-layer-1} + +4. L1 브리지는 `finalizeETHWithdrawal` 또는 `finalizeERC20Withdrawal` 호출이 합법적인지 확인합니다. + - 교차 도메인 메시지 메커니즘에서 왔습니다 + - 원래 L2의 브리지에서 왔습니다 +5. L1 브리지는 적절한 자산(ETH 또는 ERC-20)을 적절한 주소로 전송합니다 + +## 레이어 1 코드 {#layer-1-code} + +이것은 L1, 즉 이더리움 메인넷에서 실행되는 코드입니다. + +### IL1ERC20Bridge {#IL1ERC20Bridge} + +[이 인터페이스는 여기에서 정의됩니다](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/IL1ERC20Bridge.sol). +여기에는 ERC-20 토큰을 브리지하는 데 필요한 함수와 정의가 포함되어 있습니다. + +```solidity +// SPDX-License-Identifier: MIT +``` + +[대부분의 Optimism 코드는 MIT 라이선스에 따라 릴리스됩니다](https://help.optimism.io/hc/en-us/articles/4411908707995-What-software-license-does-Optimism-use-). + +```solidity +pragma solidity >0.5.0 <0.9.0; +``` + +작성 시점의 최신 Solidity 버전은 0.8.12입니다. +버전 0.9.0이 릴리스될 때까지 이 코드가 해당 버전과 호환되는지 여부는 알 수 없습니다. + +```solidity +/** + * @title IL1ERC20Bridge + */ +interface IL1ERC20Bridge { + /********** + * 이벤트 * + **********/ + + event ERC20DepositInitiated( +``` + +Optimism 브리지 용어에서 예치(deposit)는 L1에서 L2로의 전송을 의미하고, 인출(withdrawal)은 L2에서 L1로의 전송을 의미합니다. + +```solidity + address indexed _l1Token, + address indexed _l2Token, +``` + +대부분의 경우 L1의 ERC-20 주소는 L2의 동등한 ERC-20 주소와 다릅니다. +[여기에서 토큰 주소 목록을 볼 수 있습니다](https://static.optimism.io/optimism.tokenlist.json). +`chainId` 1인 주소는 L1(메인넷)에 있고, `chainId` 10인 주소는 L2(Optimism)에 있습니다. +다른 두 `chainId` 값은 Kovan 테스트 네트워크(42)와 Optimistic Kovan 테스트 네트워크(69)에 대한 것입니다. + +```solidity + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); +``` + +전송에 메모를 추가할 수 있으며, 이 경우 이를 보고하는 이벤트에 추가됩니다. + +```solidity + event ERC20WithdrawalFinalized( + address indexed _l1Token, + address indexed _l2Token, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); +``` + +동일한 브리지 컨트랙트가 양방향 전송을 처리합니다. +L1 브리지의 경우, 이는 예치의 시작과 인출의 완료를 의미합니다. + +```solidity + + /******************** + * 공개 함수 * + ********************/ + + /** + * @dev 해당하는 L2 브리지 컨트랙트의 주소를 가져옵니다. + * @return 해당하는 L2 브리지 컨트랙트의 주소입니다. + */ + function l2TokenBridge() external returns (address); +``` + +이 함수는 실제로 필요하지 않습니다. L2에서는 사전 배포된 컨트랙트이므로 항상 주소 `0x4200000000000000000000000000000000000010`에 있기 때문입니다. +L1 브리지의 주소는 알기 _쉽지 않기 때문에_ L2 브리지와의 대칭성을 위해 여기에 있습니다. + +```solidity + /** + * @dev ERC20의 일정 금액을 L2의 호출자 잔액으로 예치합니다. + * @param _l1Token 우리가 예치하는 L1 ERC20의 주소 + * @param _l2Token 해당 L2 ERC20의 주소 + * @param _amount 예치할 ERC20의 금액 + * @param _l2Gas L2에서 예치를 완료하는 데 필요한 가스 한도 + * @param _data L2로 전달할 선택적 데이터. 이 데이터는 + * 외부 컨트랙트의 편의를 위해서만 제공됩니다. 최대 + * 길이를 강제하는 것 외에, 이 컨트랙트는 내용에 대한 어떠한 보증도 제공하지 않습니다. + */ + function depositERC20( + address _l1Token, + address _l2Token, + uint256 _amount, + uint32 _l2Gas, + bytes calldata _data + ) external; +``` + +`_l2Gas` 매개변수는 트랜잭션이 사용할 수 있는 L2 가스의 양입니다. +[특정(높은) 한도까지는 무료이므로](https://community.optimism.io/docs/developers/bridge/messaging/#for-l1-%E2%87%92-l2-transactions-2), ERC-20 컨트랙트가 민팅 시 정말 이상한 작업을 하지 않는 한 문제가 되지 않습니다. +이 함수는 사용자가 다른 블록체인의 동일한 주소로 자산을 브리지하는 일반적인 시나리오를 처리합니다. + +```solidity + /** + * @dev ERC20의 일정 금액을 L2의 수신자 잔액으로 예치합니다. + * @param _l1Token 우리가 예치하는 L1 ERC20의 주소 + * @param _l2Token 해당 L2 ERC20의 주소 + * @param _to 인출을 입금할 L2 주소. + * @param _amount 예치할 ERC20의 금액. + * @param _l2Gas L2에서 예치를 완료하는 데 필요한 가스 한도. + * @param _data L2로 전달할 선택적 데이터. 이 데이터는 + * 외부 컨트랙트의 편의를 위해서만 제공됩니다. 최대 + * 길이를 강제하는 것 외에, 이 컨트랙트는 내용에 대한 어떠한 보증도 제공하지 않습니다. + */ + function depositERC20To( + address _l1Token, + address _l2Token, + address _to, + uint256 _amount, + uint32 _l2Gas, + bytes calldata _data + ) external; +``` + +이 함수는 `depositERC20`과 거의 동일하지만 ERC-20을 다른 주소로 보낼 수 있습니다. + +```solidity + /************************* + * 교차 체인 함수 * + *************************/ + + /** + * @dev L2에서 L1으로의 인출을 완료하고, 수신자의 + * L1 ERC20 토큰 잔액에 자금을 입금합니다. + * 이 호출은 L2에서 시작된 인출이 완료되지 않은 경우 실패합니다. + * + * @param _l1Token finalizeWithdrawal을 수행할 L1 토큰의 주소. + * @param _l2Token 인출이 시작된 L2 토큰의 주소. + * @param _from 전송을 시작하는 L2 주소. + * @param _to 인출을 입금할 L1 주소. + * @param _amount 예치할 ERC20의 금액. + * @param _data L2의 발신자가 제공한 데이터. 이 데이터는 + * 외부 컨트랙트의 편의를 위해서만 제공됩니다. 최대 + * 길이를 강제하는 것 외에, 이 컨트랙트는 내용에 대한 어떠한 보증도 제공하지 않습니다. + */ + function finalizeERC20Withdrawal( + address _l1Token, + address _l2Token, + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) external; +} +``` + +Optimism에서 인출(및 L2에서 L1으로의 다른 메시지)은 두 단계 과정입니다. + +1. L2에서의 시작 트랜잭션. +2. L1에서의 완료 또는 청구 트랜잭션. + 이 트랜잭션은 L2 트랜잭션에 대한 [결함 챌린지 기간](https://community.optimism.io/docs/how-optimism-works/#fault-proofs)이 끝난 후에 발생해야 합니다. + +### IL1StandardBridge {#il1standardbridge} + +[이 인터페이스는 여기에서 정의됩니다](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/IL1StandardBridge.sol). +이 파일에는 ETH에 대한 이벤트 및 함수 정의가 포함되어 있습니다. +이러한 정의는 위에서 ERC-20에 대해 정의된 `IL1ERC20Bridge`의 정의와 매우 유사합니다. + +일부 ERC-20 토큰은 사용자 지정 처리가 필요하며 표준 브리지에서 처리할 수 없기 때문에 브리지 인터페이스는 두 개의 파일로 나뉩니다. +이러한 방식으로 해당 토큰을 처리하는 사용자 지정 브리지는 `IL1ERC20Bridge`를 구현하고 ETH도 브리지할 필요가 없습니다. + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity >0.5.0 <0.9.0; + +import "./IL1ERC20Bridge.sol"; + +/** + * @title IL1StandardBridge + */ +interface IL1StandardBridge is IL1ERC20Bridge { + /********** + * 이벤트 * + **********/ + event ETHDepositInitiated( + address indexed _from, + address indexed _to, + uint256 _amount, + bytes _data + ); +``` + +이 이벤트는 L1 및 L2 토큰 주소가 없다는 점을 제외하고 ERC-20 버전(`ERC20DepositInitiated`)과 거의 동일합니다. +다른 이벤트와 함수도 마찬가지입니다. + +```solidity + event ETHWithdrawalFinalized( + . + . + . + ); + + /******************** + * 공개 함수 * + ********************/ + + /** + * @dev ETH의 일정 금액을 L2의 호출자 잔액으로 예치합니다. + . + . + . + */ + function depositETH(uint32 _l2Gas, bytes calldata _data) external payable; + + /** + * @dev ETH의 일정 금액을 L2의 수신자 잔액으로 예치합니다. + . + . + . + */ + function depositETHTo( + address _to, + uint32 _l2Gas, + bytes calldata _data + ) external payable; + + /************************* + * 교차 체인 함수 * + *************************/ + + /** + * @dev L2에서 L1으로의 인출을 완료하고, 수신자의 + * L1 ETH 토큰 잔액에 자금을 입금합니다. xDomainMessenger만이 이 함수를 호출할 수 있으므로 + * 인출이 완료되기 전에는 절대 호출되지 않습니다. + . + . + . + */ + function finalizeETHWithdrawal( + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) external; +} +``` + +### CrossDomainEnabled {#crossdomainenabled} + +[이 컨트랙트](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/bridge/CrossDomainEnabled.sol)는 두 브리지([L1](#the-l1-bridge-contract) 및 [L2](#the-l2-bridge-contract))에 의해 상속되어 다른 레이어로 메시지를 보냅니다. + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity >0.5.0 <0.9.0; + +/* 인터페이스 임포트 */ +import { ICrossDomainMessenger } from "./ICrossDomainMessenger.sol"; +``` + +[이 인터페이스](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/bridge/ICrossDomainMessenger.sol)는 컨트랙트에게 교차 도메인 메신저를 사용하여 다른 레이어로 메시지를 보내는 방법을 알려줍니다. +이 교차 도메인 메신저는 완전히 다른 시스템이며, 별도의 글에서 다룰 가치가 있습니다. 나중에 작성할 수 있기를 바랍니다. + +```solidity +/** + * @title CrossDomainEnabled + * @dev 교차 도메인 통신을 수행하는 컨트랙트를 위한 헬퍼 컨트랙트 + * + * 사용된 컴파일러: 상속하는 컨트랙트에 의해 정의됨 + */ +contract CrossDomainEnabled { + /************* + * 변수 * + *************/ + + // 다른 도메인으로부터 메시지를 보내고 받는 데 사용되는 메신저 컨트랙트. + address public messenger; + + /*************** + * 생성자 * + ***************/ + + /** + * @param _messenger 현재 레이어의 CrossDomainMessenger 주소. + */ + constructor(address _messenger) { + messenger = _messenger; + } +``` + +컨트랙트가 알아야 할 한 가지 매개변수는 이 레이어의 교차 도메인 메신저 주소입니다. +이 매개변수는 생성자에서 한 번 설정되고 절대 변경되지 않습니다. + +```solidity + + /********************** + * 함수 수정자 * + **********************/ + + /** + * 수정된 함수가 특정 교차 도메인 계정에서만 호출될 수 있도록 강제합니다. + * @param _sourceDomainAccount 이 함수를 호출할 수 있도록 + * 인증된 유일한 원래 도메인 계정입니다. + */ + modifier onlyFromCrossDomainAccount(address _sourceDomainAccount) { +``` + +교차 도메인 메시징은 실행 중인 블록체인(이더리움 메인넷 또는 Optimism)의 모든 컨트랙트에서 접근할 수 있습니다. +하지만 각 측의 브리지는 다른 쪽 브리지에서 온 경우에만 특정 메시지를 _신뢰해야_ 합니다. + +```solidity + require( + msg.sender == address(getCrossDomainMessenger()), + "OVM_XCHAIN: 메신저 컨트랙트가 인증되지 않았습니다" + ); +``` + +적절한 교차 도메인 메신저(`messenger`, 아래에서 볼 수 있음)에서 온 메시지만 신뢰할 수 있습니다. + +```solidity + + require( + getCrossDomainMessenger().xDomainMessageSender() == _sourceDomainAccount, + "OVM_XCHAIN: 교차 도메인 메시지의 발신자가 잘못되었습니다" + ); +``` + +교차 도메인 메신저가 다른 레이어에서 메시지를 보낸 주소를 제공하는 방법은 [`.xDomainMessageSender()` 함수](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol#L122-L128)입니다. +메시지에 의해 시작된 트랜잭션에서 호출되는 한 이 정보를 제공할 수 있습니다. + +우리가 받은 메시지가 다른 브리지에서 왔는지 확인해야 합니다. + +```solidity + + _; + } + + /********************** + * 내부 함수 * + **********************/ + + /** + * 일반적으로 스토리지에서 메신저를 가져옵니다. 이 함수는 자식 컨트랙트가 + * 재정의해야 할 경우를 대비하여 노출됩니다. + * @return 사용해야 할 교차 도메인 메신저 컨트랙트의 주소입니다. + */ + function getCrossDomainMessenger() internal virtual returns (ICrossDomainMessenger) { + return ICrossDomainMessenger(messenger); + } +``` + +이 함수는 교차 도메인 메신저를 반환합니다. +이 함수에서 상속하는 컨트랙트가 사용할 교차 도메인 메신저를 지정하는 알고리즘을 사용할 수 있도록 변수 `messenger` 대신 함수를 사용합니다. + +```solidity + + /** + * 다른 도메인의 계정으로 메시지를 보냅니다 + * @param _crossDomainTarget 대상 도메인의 의도된 수신자 + * @param _message 대상에게 보낼 데이터(일반적으로 + * `onlyFromCrossDomainAccount()`가 있는 함수에 대한 콜데이터) + * @param _gasLimit 대상 도메인에서 메시지를 수신하기 위한 gasLimit입니다. + */ + function sendCrossDomainMessage( + address _crossDomainTarget, + uint32 _gasLimit, + bytes memory _message +``` + +마지막으로 다른 레이어에 메시지를 보내는 함수입니다. + +```solidity + ) internal { + // slither-disable-next-line reentrancy-events, reentrancy-benign +``` + +[Slither](https://github.com/crytic/slither)는 취약점 및 기타 잠재적인 문제를 찾기 위해 모든 컨트랙트에서 실행하는 정적 분석기입니다. +이 경우 다음 줄은 두 가지 취약점을 유발합니다. + +1. [재진입 이벤트](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3) +2. [양성 재진입](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2) + +```solidity + getCrossDomainMessenger().sendMessage(_crossDomainTarget, _message, _gasLimit); + } +} +``` + +이 경우 Slither가 알 방법이 없더라도 `getCrossDomainMessenger()`가 신뢰할 수 있는 주소를 반환한다는 것을 알고 있으므로 재진입에 대해 걱정하지 않습니다. + +### L1 브리지 컨트랙트 {#the-l1-bridge-contract} + +[이 컨트랙트의 소스 코드는 여기에 있습니다](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/L1StandardBridge.sol). + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; +``` + +인터페이스는 다른 컨트랙트의 일부가 될 수 있으므로 광범위한 Solidity 버전을 지원해야 합니다. +그러나 브리지 자체는 우리의 컨트랙트이며, 사용하는 Solidity 버전에 대해 엄격할 수 있습니다. + +```solidity +/* 인터페이스 임포트 */ +import { IL1StandardBridge } from "./IL1StandardBridge.sol"; +import { IL1ERC20Bridge } from "./IL1ERC20Bridge.sol"; +``` + +[IL1ERC20Bridge](#IL1ERC20Bridge) 및 [IL1StandardBridge](#IL1StandardBridge)는 위에서 설명했습니다. + +```solidity +import { IL2ERC20Bridge } from "../../L2/messaging/IL2ERC20Bridge.sol"; +``` + +[이 인터페이스](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol)를 사용하면 L2의 표준 브리지를 제어하는 메시지를 생성할 수 있습니다. + +```solidity +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +``` + +[이 인터페이스](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol)를 사용하면 ERC-20 컨트랙트를 제어할 수 있습니다. +[여기에서 자세한 내용을 읽을 수 있습니다](/developers/tutorials/erc20-annotated-code/#the-interface). + +```solidity +/* 라이브러리 임포트 */ +import { CrossDomainEnabled } from "../../libraries/bridge/CrossDomainEnabled.sol"; +``` + +[위에서 설명했듯이](#crossdomainenabled) 이 컨트랙트는 레이어 간 메시징에 사용됩니다. + +```solidity +import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol"; +``` + +[`Lib_PredeployAddresses`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/constants/Lib_PredeployAddresses.sol)에는 항상 동일한 주소를 갖는 L2 컨트랙트의 주소가 있습니다. 여기에는 L2의 표준 브리지가 포함됩니다. + +```solidity +import { Address } from "@openzeppelin/contracts/utils/Address.sol"; +``` + +[OpenZeppelin의 주소 유틸리티](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol). 컨트랙트 주소와 외부 소유 계정(EOA)에 속한 주소를 구별하는 데 사용됩니다. + +이는 완벽한 해결책이 아니라는 점에 유의해야 합니다. 직접 호출과 컨트랙트의 생성자에서 이루어진 호출을 구별할 방법이 없기 때문입니다. 하지만 적어도 이를 통해 일반적인 사용자 오류를 식별하고 방지할 수 있습니다. + +```solidity +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +``` + +[ERC-20 표준](https://eips.ethereum.org/EIPS/eip-20)은 컨트랙트가 실패를 보고하는 두 가지 방법을 지원합니다. + +1. 되돌리기 +2. `false` 반환 + +두 경우 모두를 처리하면 코드가 더 복잡해지므로 대신 [모든 실패가 되돌리기로 이어지도록](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol#L96) 보장하는 [OpenZeppelin의 `SafeERC20`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol)을 사용합니다. + +```solidity +/** + * @title L1StandardBridge + * @dev L1 ETH 및 ERC20 브리지는 L2에서 사용 중인 예치된 L1 자금과 표준 + * 토큰을 저장하는 컨트랙트입니다. 해당하는 L2 브리지를 동기화하여 예치 정보를 알리고 + * 새로 완료된 인출을 수신합니다. + * + */ +contract L1StandardBridge is IL1StandardBridge, CrossDomainEnabled { + using SafeERC20 for IERC20; +``` + +이 줄은 `IERC20` 인터페이스를 사용할 때마다 `SafeERC20` 래퍼를 사용하도록 지정하는 방법입니다. + +```solidity + + /******************************** + * 외부 컨트랙트 참조 * + ********************************/ + + address public l2TokenBridge; +``` + +[L2StandardBridge](#the-l2-bridge-contract)의 주소. + +```solidity + + // L1 토큰을 L2 토큰에 매핑하여 예치된 L1 토큰의 잔액을 관리 + mapping(address => mapping(address => uint256)) public deposits; +``` + +이와 같은 이중 [매핑](https://www.tutorialspoint.com/solidity/solidity_mappings.htm)은 [2차원 희소 배열](https://en.wikipedia.org/wiki/Sparse_matrix)을 정의하는 방법입니다. +이 데이터 구조의 값은 `deposit[L1 토큰 주소][L2 토큰 주소]`로 식별됩니다. +기본값은 0입니다. +다른 값으로 설정된 셀만 스토리지에 기록됩니다. + +```solidity + + /*************** + * 생성자 * + ***************/ + + // 이 컨트랙트는 프록시 뒤에 존재하므로 생성자 매개변수는 사용되지 않습니다. + constructor() CrossDomainEnabled(address(0)) {} +``` + +스토리지의 모든 변수를 복사하지 않고도 이 컨트랙트를 업그레이드할 수 있기를 원합니다. +이를 위해 [`Proxy`](https://docs.openzeppelin.com/contracts/3.x/api/proxy)를 사용합니다. 프록시는 [`delegatecall`](https://solidity-by-example.org/delegatecall/)을 사용하여 프록시 컨트랙트가 저장한 주소의 별도 컨트랙트로 호출을 전송합니다(업그레이드할 때 프록시에 해당 주소를 변경하도록 지시합니다). +`delegatecall`을 사용하면 스토리지는 _호출_ 컨트랙트의 스토리지로 유지되므로 모든 컨트랙트 상태 변수의 값은 영향을 받지 않습니다. + +이 패턴의 한 가지 효과는 `delegatecall`의 _호출된_ 컨트랙트의 스토리지가 사용되지 않으므로 여기에 전달된 생성자 값은 중요하지 않다는 것입니다. +이것이 `CrossDomainEnabled` 생성자에 무의미한 값을 제공할 수 있는 이유입니다. +또한 아래 초기화가 생성자와 분리된 이유이기도 합니다. + +```solidity + /****************** + * 초기화 * + ******************/ + + /** + * @param _l1messenger 교차 체인 통신에 사용되는 L1 메신저 주소. + * @param _l2TokenBridge L2 표준 브리지 주소. + */ + // slither-disable-next-line external-function +``` + +이 [Slither 테스트](https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-external)는 컨트랙트 코드에서 호출되지 않아 `public` 대신 `external`로 선언될 수 있는 함수를 식별합니다. +`external` 함수의 가스 비용은 콜데이터에 매개변수를 제공할 수 있으므로 더 낮을 수 있습니다. +`public`으로 선언된 함수는 컨트랙트 내에서 접근할 수 있어야 합니다. +컨트랙트는 자신의 콜데이터를 수정할 수 없으므로 매개변수는 메모리에 있어야 합니다. +이러한 함수가 외부에서 호출될 때, 콜데이터를 메모리로 복사해야 하므로 가스가 소모됩니다. +이 경우 함수는 한 번만 호출되므로 비효율성은 우리에게 중요하지 않습니다. + +```solidity + function initialize(address _l1messenger, address _l2TokenBridge) public { + require(messenger == address(0), "컨트랙트가 이미 초기화되었습니다."); +``` + +`initialize` 함수는 한 번만 호출되어야 합니다. +L1 교차 도메인 메신저 또는 L2 토큰 브리지의 주소가 변경되면, 이를 호출하는 새로운 프록시와 새로운 브리지를 생성합니다. +이는 전체 시스템이 업그레이드될 때를 제외하고는 매우 드물게 발생합니다. + +이 함수에는 _누가_ 호출할 수 있는지 제한하는 메커니즘이 없다는 점에 유의해야 합니다. +이론적으로 공격자는 우리가 프록시와 브리지의 첫 번째 버전을 배포할 때까지 기다렸다가 합법적인 사용자가 `initialize` 함수에 접근하기 전에 [선행매매](https://solidity-by-example.org/hacks/front-running/)를 할 수 있습니다. 그러나 이를 방지하는 두 가지 방법이 있습니다. + +1. 컨트랙트가 EOA에 의해 직접 배포되지 않고 [다른 컨트랙트가 이를 생성하는 트랜잭션에서](https://medium.com/upstate-interactive/creating-a-contract-with-a-smart-contract-bdb67c5c8595) 배포되는 경우, 전체 프로세스는 원자적일 수 있으며 다른 트랜잭션이 실행되기 전에 완료될 수 있습니다. +2. 합법적인 `initialize` 호출이 실패하면 새로 생성된 프록시와 브리지를 무시하고 새로운 것을 생성할 수 있습니다. + +```solidity + messenger = _l1messenger; + l2TokenBridge = _l2TokenBridge; + } +``` + +이 두 가지는 브리지가 알아야 할 매개변수입니다. + +```solidity + + /************** + * 예치 * + **************/ + + /** @dev 발신자가 EOA여야 하는 수정자입니다. 이 검사는 악의적인 + * 컨트랙트가 initcode를 통해 우회할 수 있지만, 우리가 피하고자 하는 사용자 오류를 처리합니다. + */ + modifier onlyEOA() { + // 컨트랙트로부터의 예치를 중지하는 데 사용됩니다(실수로 토큰을 잃는 것을 방지) + require(!Address.isContract(msg.sender), "계정이 EOA가 아님"); + _; + } +``` + +이것이 OpenZeppelin의 `Address` 유틸리티가 필요했던 이유입니다. + +```solidity + /** + * @dev 이 함수는 데이터 없이 호출될 수 있습니다 + * ETH의 일정 금액을 L2의 호출자 잔액으로 예치합니다. + * receive 함수는 데이터를 받지 않으므로, 보수적인 + * 기본 금액이 L2로 전달됩니다. + */ + receive() external payable onlyEOA { + _initiateETHDeposit(msg.sender, msg.sender, 200_000, bytes("")); + } +``` + +이 함수는 테스트 목적으로 존재합니다. +인터페이스 정의에 나타나지 않는다는 점에 유의하세요. 일반적인 사용을 위한 것이 아닙니다. + +```solidity + /** + * @inheritdoc IL1StandardBridge + */ + function depositETH(uint32 _l2Gas, bytes calldata _data) external payable onlyEOA { + _initiateETHDeposit(msg.sender, msg.sender, _l2Gas, _data); + } + + /** + * @inheritdoc IL1StandardBridge + */ + function depositETHTo( + address _to, + uint32 _l2Gas, + bytes calldata _data + ) external payable { + _initiateETHDeposit(msg.sender, _to, _l2Gas, _data); + } +``` + +이 두 함수는 실제 ETH 예치를 처리하는 함수인 `_initiateETHDeposit`의 래퍼입니다. + +```solidity + /** + * @dev ETH를 저장하고 L2 ETH 게이트웨이에 + * 예치를 알리는 예치 로직을 수행합니다. + * @param _from L1에서 예치를 가져올 계정. + * @param _to L2에서 예치를 줄 계정. + * @param _l2Gas L2에서 예치를 완료하는 데 필요한 가스 한도. + * @param _data L2로 전달할 선택적 데이터. 이 데이터는 + * 외부 컨트랙트의 편의를 위해서만 제공됩니다. 최대 + * 길이를 강제하는 것 외에, 이 컨트랙트는 내용에 대한 어떠한 보증도 제공하지 않습니다. + */ + function _initiateETHDeposit( + address _from, + address _to, + uint32 _l2Gas, + bytes memory _data + ) internal { + // finalizeDeposit 호출을 위한 콜데이터 구성 + bytes memory message = abi.encodeWithSelector( +``` + +교차 도메인 메시지가 작동하는 방식은 대상 컨트랙트가 메시지를 콜데이터로 사용하여 호출되는 것입니다. +Solidity 컨트랙트는 항상 [ABI 사양](https://docs.soliditylang.org/en/v0.8.12/abi-spec.html)에 따라 콜데이터를 해석합니다. +Solidity 함수 [`abi.encodeWithSelector`](https://docs.soliditylang.org/en/v0.8.12/units-and-global-variables.html#abi-encoding-and-decoding-functions)는 해당 콜데이터를 생성합니다. + +```solidity + IL2ERC20Bridge.finalizeDeposit.selector, + address(0), + Lib_PredeployAddresses.OVM_ETH, + _from, + _to, + msg.value, + _data + ); +``` + +여기서 메시지는 다음 매개변수와 함께 [`finalizeDeposit` 함수](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/L2StandardBridge.sol#L141-L148)를 호출하는 것입니다. + +| 매개 변수 | 값 | 의미 | +| ------------------------------- | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | +| \_l1Token | address(0) | L1에서 ETH(ERC-20 토큰이 아님)를 나타내는 특수 값 | +| \_l2Token | Lib_PredeployAddresses.OVM_ETH | Optimism에서 ETH를 관리하는 L2 컨트랙트, `0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000` (이 컨트랙트는 Optimism 내부용으로만 사용됩니다) | +| \_from | \_from | ETH를 보내는 L1의 주소 | +| \_to | \_to | ETH를 받는 L2의 주소 | +| 금액 | msg.value | 전송된 wei의 양(이미 브리지로 전송됨) | +| \_data | \_data | 예치에 첨부할 추가 데이터 | + +```solidity + // L2로 콜데이터 전송 + // slither-disable-next-line reentrancy-events + sendCrossDomainMessage(l2TokenBridge, _l2Gas, message); +``` + +교차 도메인 메신저를 통해 메시지를 보냅니다. + +```solidity + // slither-disable-next-line reentrancy-events + emit ETHDepositInitiated(_from, _to, msg.value, _data); + } +``` + +이 전송을 수신하는 탈중앙화 애플리케이션에 알리기 위해 이벤트를 발생시킵니다. + +```solidity + /** + * @inheritdoc IL1ERC20Bridge + */ + function depositERC20( + . + . + . + ) external virtual onlyEOA { + _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, msg.sender, _amount, _l2Gas, _data); + } + + /** + * @inheritdoc IL1ERC20Bridge + */ + function depositERC20To( + . + . + . + ) external virtual { + _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, _to, _amount, _l2Gas, _data); + } +``` + +이 두 함수는 실제 ERC-20 예치를 처리하는 함수인 `_initiateERC20Deposit`의 래퍼입니다. + +```solidity + /** + * @dev L2 예치 토큰 + * 컨트랙트에 예치를 알리고 L1 자금을 락업하는 핸들러를 호출하여 예치 로직을 수행합니다. (예: transferFrom) + * + * @param _l1Token 우리가 예치하는 L1 ERC20의 주소 + * @param _l2Token 해당 L2 ERC20의 주소 + * @param _from L1에서 예치를 가져올 계정 + * @param _to L2에서 예치를 줄 계정 + * @param _amount 예치할 ERC20의 금액. + * @param _l2Gas L2에서 예치를 완료하는 데 필요한 가스 한도. + * @param _data L2로 전달할 선택적 데이터. 이 데이터는 + * 외부 컨트랙트의 편의를 위해서만 제공됩니다. 최대 + * 길이를 강제하는 것 외에, 이 컨트랙트는 내용에 대한 어떠한 보증도 제공하지 않습니다. + */ + function _initiateERC20Deposit( + address _l1Token, + address _l2Token, + address _from, + address _to, + uint256 _amount, + uint32 _l2Gas, + bytes calldata _data + ) internal { +``` + +이 함수는 위의 `_initiateETHDeposit`과 유사하지만 몇 가지 중요한 차이점이 있습니다. +첫 번째 차이점은 이 함수가 토큰 주소와 전송할 금액을 매개변수로 받는다는 것입니다. +ETH의 경우 브리지 호출에는 이미 브리지 계정으로의 자산 전송(`msg.value`)이 포함됩니다. + +```solidity + // L1에서 예치가 시작되면, L1 브리지는 미래의 + // 인출을 위해 자금을 자체적으로 전송합니다. safeTransferFrom은 또한 컨트랙트에 코드가 있는지 확인하므로 + // _from이 EOA 또는 address(0)인 경우 실패합니다. + // slither-disable-next-line reentrancy-events, reentrancy-benign + IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount); +``` + +ERC-20 토큰 전송은 ETH와 다른 프로세스를 따릅니다. + +1. 사용자(`_from`)는 적절한 토큰을 전송할 수 있도록 브리지에 허용량을 부여합니다. +2. 사용자는 토큰 컨트랙트의 주소, 금액 등을 사용하여 브리지를 호출합니다. +3. 브리지는 예치 과정의 일부로 토큰을 (자체적으로) 전송합니다. + +첫 번째 단계는 마지막 두 단계와 별도의 트랜잭션에서 발생할 수 있습니다. +그러나 `_initiateERC20Deposit`을 호출하는 두 함수(`depositERC20` 및 `depositERC20To`)는 `msg.sender`를 `_from` 매개변수로만 이 함수를 호출하기 때문에 선행매매는 문제가 되지 않습니다. + +```solidity + // _l2Token.finalizeDeposit(_to, _amount)에 대한 콜데이터 구성 + bytes memory message = abi.encodeWithSelector( + IL2ERC20Bridge.finalizeDeposit.selector, + _l1Token, + _l2Token, + _from, + _to, + _amount, + _data + ); + + // L2로 콜데이터 전송 + // slither-disable-next-line reentrancy-events, reentrancy-benign + sendCrossDomainMessage(l2TokenBridge, _l2Gas, message); + + // slither-disable-next-line reentrancy-benign + deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] + _amount; +``` + +예치된 토큰의 양을 `deposits` 데이터 구조에 추가합니다. +동일한 L1 ERC-20 토큰에 해당하는 여러 L2 주소가 있을 수 있으므로 브리지의 L1 ERC-20 토큰 잔액만으로는 예치를 추적하기에 충분하지 않습니다. + +```solidity + + // slither-disable-next-line reentrancy-events + emit ERC20DepositInitiated(_l1Token, _l2Token, _from, _to, _amount, _data); + } + + /************************* + * 교차 체인 함수 * + *************************/ + + /** + * @inheritdoc IL1StandardBridge + */ + function finalizeETHWithdrawal( + address _from, + address _to, + uint256 _amount, + bytes calldata _data +``` + +L2 브리지는 L2 교차 도메인 메신저에 메시지를 보내 L1 교차 도메인 메신저가 이 함수를 호출하도록 합니다(물론 [메시지를 완료하는 트랜잭션](https://community.optimism.io/docs/developers/bridge/messaging/#fees-for-l2-%E2%87%92-l1-transactions)이 L1에 제출된 후에). + +```solidity + ) external onlyFromCrossDomainAccount(l2TokenBridge) { +``` + +이것이 교차 도메인 메신저에서 오고 L2 토큰 브리지에서 시작된 _합법적인_ 메시지인지 확인하십시오. +이 함수는 브리지에서 ETH를 인출하는 데 사용되므로 승인된 호출자에 의해서만 호출되는지 확인해야 합니다. + +```solidity + // slither-disable-next-line reentrancy-events + (bool success, ) = _to.call{ value: _amount }(new bytes(0)); +``` + +ETH를 전송하는 방법은 `msg.value`에 wei 단위의 금액을 담아 수신자를 호출하는 것입니다. + +```solidity + require(success, "TransferHelper::safeTransferETH: ETH 전송 실패"); + + // slither-disable-next-line reentrancy-events + emit ETHWithdrawalFinalized(_from, _to, _amount, _data); +``` + +인출에 대한 이벤트를 발생시킵니다. + +```solidity + } + + /** + * @inheritdoc IL1ERC20Bridge + */ + function finalizeERC20Withdrawal( + address _l1Token, + address _l2Token, + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) external onlyFromCrossDomainAccount(l2TokenBridge) { +``` + +이 함수는 위의 `finalizeETHWithdrawal`과 유사하며 ERC-20 토큰에 필요한 변경 사항이 있습니다. + +```solidity + deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] - _amount; +``` + +`deposits` 데이터 구조를 업데이트합니다. + +```solidity + + // L1에서 인출이 완료되면 L1 브리지는 자금을 인출자에게 전송합니다 + // slither-disable-next-line reentrancy-events + IERC20(_l1Token).safeTransfer(_to, _amount); + + // slither-disable-next-line reentrancy-events + emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); + } + + + /***************************** + * 임시 - ETH 마이그레이션 * + *****************************/ + + /** + * @dev 계정에 ETH 잔액을 추가합니다. 이는 ETH가 + * 이전 게이트웨이에서 새 게이트웨이로 마이그레이션될 수 있도록 하기 위한 것입니다. + * 참고: 이전 컨트랙트에서 마이그레이션된 ETH를 받을 수 있도록 + * 한 번의 업그레이드에만 남겨둡니다 + */ + function donateETH() external payable {} +} +``` + +브리지의 이전 구현이 있었습니다. +구현에서 이 구현으로 옮길 때 모든 자산을 옮겨야 했습니다. +ERC-20 토큰은 그냥 옮길 수 있습니다. +하지만 컨트랙트로 ETH를 전송하려면 해당 컨트랙트의 승인이 필요한데, 이것이 바로 `donateETH`가 제공하는 기능입니다. + +## L2의 ERC-20 토큰 {#erc-20-tokens-on-l2} + +ERC-20 토큰이 표준 브리지에 맞으려면 표준 브리지, 그리고 _오직_ 표준 브리지만 토큰을 민팅할 수 있도록 허용해야 합니다. +이는 브리지가 Optimism에서 유통되는 토큰의 수가 L1 브리지 컨트랙트 내에 락업된 토큰의 수와 같도록 보장해야 하기 때문에 필요합니다. +L2에 토큰이 너무 많으면 일부 사용자는 자산을 L1으로 다시 브리지할 수 없게 됩니다. +신뢰할 수 있는 브리지 대신, 우리는 본질적으로 [부분 지급 준비금 제도](https://www.investopedia.com/terms/f/fractionalreservebanking.asp)를 재현하게 될 것입니다. +L1에 토큰이 너무 많으면 L2 토큰을 소각하지 않고는 릴리스할 방법이 없기 때문에 일부 토큰은 브리지 컨트랙트 내에 영원히 락업됩니다. + +### IL2StandardERC20 {#il2standarderc20} + +표준 브리지를 사용하는 L2의 모든 ERC-20 토큰은 표준 브리지에 필요한 함수와 이벤트가 있는 [이 인터페이스](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/standards/IL2StandardERC20.sol)를 제공해야 합니다. + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +``` + +[표준 ERC-20 인터페이스](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol)에는 `mint` 및 `burn` 함수가 포함되어 있지 않습니다. +이러한 메서드는 [ERC-20 표준](https://eips.ethereum.org/EIPS/eip-20)에서 요구하지 않으며, 토큰을 생성하고 파괴하는 메커니즘을 명시하지 않습니다. + +```solidity +import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +``` + +[ERC-165 인터페이스](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/IERC165.sol)는 컨트랙트가 제공하는 함수를 지정하는 데 사용됩니다. +[여기에서 표준을 읽을 수 있습니다](https://eips.ethereum.org/EIPS/eip-165). + +```solidity +interface IL2StandardERC20 is IERC20, IERC165 { + function l1Token() external returns (address); +``` + +이 함수는 이 컨트랙트로 브리지된 L1 토큰의 주소를 제공합니다. +반대 방향으로 유사한 함수가 없다는 점에 유의하십시오. +구현 시 L2 지원이 계획되었는지 여부에 관계없이 모든 L1 토큰을 브리지할 수 있어야 합니다. + +```solidity + + function mint(address _to, uint256 _amount) external; + + function burn(address _from, uint256 _amount) external; + + event Mint(address indexed _account, uint256 _amount); + event Burn(address indexed _account, uint256 _amount); +} +``` + +토큰을 민팅(생성)하고 소각(파괴)하는 함수 및 이벤트. +토큰의 수가 정확하도록(L1에 락업된 토큰의 수와 동일) 보장하기 위해 브리지는 이러한 함수를 실행할 수 있는 유일한 엔터티여야 합니다. + +### L2StandardERC20 {#L2StandardERC20} + +[이것은 `IL2StandardERC20` 인터페이스의 구현입니다](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/standards/L2StandardERC20.sol). +사용자 지정 로직이 필요하지 않은 경우 이것을 사용해야 합니다. + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +``` + +[OpenZeppelin ERC-20 컨트랙트](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol). +Optimism은 바퀴를 재발명하는 것을 믿지 않으며, 특히 바퀴가 잘 감사되고 자산을 보유할 만큼 신뢰할 수 있어야 할 때는 더욱 그렇습니다. + +```solidity +import "./IL2StandardERC20.sol"; + +contract L2StandardERC20 is IL2StandardERC20, ERC20 { + address public l1Token; + address public l2Bridge; +``` + +이것은 ERC-20이 일반적으로 요구하지 않는 우리가 요구하는 두 가지 추가 구성 매개변수입니다. + +```solidity + + /** + * @param _l2Bridge L2 표준 브리지의 주소. + * @param _l1Token 해당하는 L1 토큰의 주소. + * @param _name ERC20 이름. + * @param _symbol ERC20 기호. + */ + constructor( + address _l2Bridge, + address _l1Token, + string memory _name, + string memory _symbol + ) ERC20(_name, _symbol) { + l1Token = _l1Token; + l2Bridge = _l2Bridge; + } +``` + +먼저 상속하는 컨트랙트의 생성자(`ERC20(_name, _symbol)`)를 호출한 다음 우리 자신의 변수를 설정합니다. + +```solidity + + modifier onlyL2Bridge() { + require(msg.sender == l2Bridge, "L2 브리지만 민팅 및 소각 가능"); + _; + } + + + // slither-disable-next-line external-function + function supportsInterface(bytes4 _interfaceId) public pure returns (bool) { + bytes4 firstSupportedInterface = bytes4(keccak256("supportsInterface(bytes4)")); // ERC165 + bytes4 secondSupportedInterface = IL2StandardERC20.l1Token.selector ^ + IL2StandardERC20.mint.selector ^ + IL2StandardERC20.burn.selector; + return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface; + } +``` + +이것이 [ERC-165](https://eips.ethereum.org/EIPS/eip-165)가 작동하는 방식입니다. +모든 인터페이스는 여러 지원되는 함수로 구성되며, 해당 함수의 [ABI 함수 선택자](https://docs.soliditylang.org/en/v0.8.12/abi-spec.html)의 [배타적 논리합](https://en.wikipedia.org/wiki/Exclusive_or)으로 식별됩니다. + +L2 브리지는 ERC-165를 사용하여 자산을 보내는 ERC-20 컨트랙트가 `IL2StandardERC20`인지 확인하는 온전성 검사를 수행합니다. + +**참고:** 악의적인 컨트랙트가 `supportsInterface`에 대해 거짓 답변을 제공하는 것을 막을 방법은 없으므로, 이는 온전성 검사 메커니즘이지 보안 메커니즘이 _아닙니다_. + +```solidity + // slither-disable-next-line external-function + function mint(address _to, uint256 _amount) public virtual onlyL2Bridge { + _mint(_to, _amount); + + emit Mint(_to, _amount); + } + + // slither-disable-next-line external-function + function burn(address _from, uint256 _amount) public virtual onlyL2Bridge { + _burn(_from, _amount); + + emit Burn(_from, _amount); + } +} +``` + +L2 브리지만 자산을 민팅하고 소각할 수 있습니다. + +`_mint`와 `_burn`은 실제로 [OpenZeppelin ERC-20 컨트랙트](/developers/tutorials/erc20-annotated-code/#the-_mint-and-_burn-functions-_mint-and-_burn)에 정의되어 있습니다. +해당 컨트랙트는 토큰을 민팅하고 소각하는 조건이 ERC-20을 사용하는 방법만큼 다양하기 때문에 외부적으로 노출하지 않습니다. + +## L2 브리지 코드 {#l2-bridge-code} + +이것은 Optimism에서 브리지를 실행하는 코드입니다. +[이 컨트랙트의 소스는 여기에 있습니다](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/L2StandardBridge.sol). + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/* 인터페이스 임포트 */ +import { IL1StandardBridge } from "../../L1/messaging/IL1StandardBridge.sol"; +import { IL1ERC20Bridge } from "../../L1/messaging/IL1ERC20Bridge.sol"; +import { IL2ERC20Bridge } from "./IL2ERC20Bridge.sol"; +``` + +[IL2ERC20Bridge](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol) 인터페이스는 위에서 본 [L1 등가물](#IL1ERC20Bridge)과 매우 유사합니다. +두 가지 중요한 차이점이 있습니다. + +1. L1에서는 예치를 시작하고 인출을 완료합니다. + 여기서는 인출을 시작하고 예치를 완료합니다. +2. L1에서는 ETH와 ERC-20 토큰을 구별해야 합니다. + L2에서는 Optimism의 내부 ETH 잔액이 주소 [0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000](https://explorer.optimism.io/address/0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000)를 가진 ERC-20 토큰으로 처리되기 때문에 둘 다 동일한 함수를 사용할 수 있습니다. + +```solidity +/* 라이브러리 임포트 */ +import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import { CrossDomainEnabled } from "../../libraries/bridge/CrossDomainEnabled.sol"; +import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol"; + +/* 컨트랙트 임포트 */ +import { IL2StandardERC20 } from "../../standards/IL2StandardERC20.sol"; + +/** + * @title L2StandardBridge + * @dev L2 표준 브리지는 L1 표준 브리지와 함께 작동하여 L1과 L2 간의 ETH 및 ERC20 전환을 가능하게 하는 컨트랙트입니다. + * 이 컨트랙트는 L1 표준 브리지에 예치된 내역을 들었을 때 새 토큰의 민팅자 역할을 합니다. + * 이 컨트랙트는 또한 인출을 목적으로 하는 토큰의 소각자 역할을 하여 L1 브리지에 L1 자금을 릴리스하도록 알립니다. + */ +contract L2StandardBridge is IL2ERC20Bridge, CrossDomainEnabled { + /******************************** + * 외부 컨트랙트 참조 * + ********************************/ + + address public l1TokenBridge; +``` + +L1 브리지의 주소를 추적합니다. +L1 등가물과 달리 여기서는 이 변수가 필요합니다. +L1 브리지의 주소는 미리 알 수 없습니다. + +```solidity + + /*************** + * 생성자 * + ***************/ + + /** + * @param _l2CrossDomainMessenger 이 컨트랙트에서 사용하는 교차 도메인 메신저. + * @param _l1TokenBridge 메인 체인에 배포된 L1 브리지의 주소. + */ + constructor(address _l2CrossDomainMessenger, address _l1TokenBridge) + CrossDomainEnabled(_l2CrossDomainMessenger) + { + l1TokenBridge = _l1TokenBridge; + } + + /*************** + * 인출 * + ***************/ + + /** + * @inheritdoc IL2ERC20Bridge + */ + function withdraw( + address _l2Token, + uint256 _amount, + uint32 _l1Gas, + bytes calldata _data + ) external virtual { + _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _l1Gas, _data); + } + + /** + * @inheritdoc IL2ERC20Bridge + */ + function withdrawTo( + address _l2Token, + address _to, + uint256 _amount, + uint32 _l1Gas, + bytes calldata _data + ) external virtual { + _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _l1Gas, _data); + } +``` + +이 두 함수는 인출을 시작합니다. +L1 토큰 주소를 지정할 필요가 없다는 점에 유의하십시오. +L2 토큰은 L1 등가물의 주소를 알려줄 것으로 예상됩니다. + +```solidity + + /** + * @dev 토큰을 소각하고 L1 토큰 게이트웨이에 + * 인출을 알리는 인출 로직을 수행합니다. + * @param _l2Token 인출이 시작된 L2 토큰의 주소. + * @param _from L2에서 인출을 가져올 계정. + * @param _to L1에서 인출을 줄 계정. + * @param _amount 인출할 토큰의 금액. + * @param _l1Gas 사용되지 않지만 잠재적인 미래 호환성을 위해 포함됩니다. + * @param _data L1으로 전달할 선택적 데이터. 이 데이터는 + * 외부 컨트랙트의 편의를 위해서만 제공됩니다. 최대 + * 길이를 강제하는 것 외에, 이 컨트랙트는 내용에 대한 어떠한 보증도 제공하지 않습니다. + */ + function _initiateWithdrawal( + address _l2Token, + address _from, + address _to, + uint256 _amount, + uint32 _l1Gas, + bytes calldata _data + ) internal { + // 인출이 시작되면 후속 L2 사용을 방지하기 위해 인출자의 자금을 소각합니다 + // slither-disable-next-line reentrancy-events + IL2StandardERC20(_l2Token).burn(msg.sender, _amount); +``` + +`_from` 매개변수에 의존하지 않고 훨씬 더 위조하기 어려운(내가 아는 한 불가능한) `msg.sender`에 의존하고 있다는 점에 유의하십시오. + +```solidity + + // l1TokenBridge.finalizeERC20Withdrawal(_to, _amount)에 대한 콜데이터 구성 + // slither-disable-next-line reentrancy-events + address l1Token = IL2StandardERC20(_l2Token).l1Token(); + bytes memory message; + + if (_l2Token == Lib_PredeployAddresses.OVM_ETH) { +``` + +L1에서는 ETH와 ERC-20을 구별해야 합니다. + +```solidity + message = abi.encodeWithSelector( + IL1StandardBridge.finalizeETHWithdrawal.selector, + _from, + _to, + _amount, + _data + ); + } else { + message = abi.encodeWithSelector( + IL1ERC20Bridge.finalizeERC20Withdrawal.selector, + l1Token, + _l2Token, + _from, + _to, + _amount, + _data + ); + } + + // L1 브리지로 메시지 전송 + // slither-disable-next-line reentrancy-events + sendCrossDomainMessage(l1TokenBridge, _l1Gas, message); + + // slither-disable-next-line reentrancy-events + emit WithdrawalInitiated(l1Token, _l2Token, msg.sender, _to, _amount, _data); + } + + /************************************ + * 교차 체인 함수: 예치 * + ************************************/ + + /** + * @inheritdoc IL2ERC20Bridge + */ + function finalizeDeposit( + address _l1Token, + address _l2Token, + address _from, + address _to, + uint256 _amount, + bytes calldata _data +``` + +이 함수는 `L1StandardBridge`에 의해 호출됩니다. + +```solidity + ) external virtual onlyFromCrossDomainAccount(l1TokenBridge) { +``` + +메시지의 출처가 합법적인지 확인하십시오. +이 함수는 `_mint`를 호출하고 브리지가 L1에 소유한 토큰으로 커버되지 않는 토큰을 제공하는 데 사용될 수 있기 때문에 중요합니다. + +```solidity + // 대상 토큰이 규정을 준수하는지 확인하고 + // L1에 예치된 토큰이 여기의 L2 예치 토큰 표현과 일치하는지 확인합니다 + if ( + // slither-disable-next-line reentrancy-events + ERC165Checker.supportsInterface(_l2Token, 0x1d1d8b63) && + _l1Token == IL2StandardERC20(_l2Token).l1Token() +``` + +온전성 검사: + +1. 올바른 인터페이스가 지원됩니다 +2. L2 ERC-20 컨트랙트의 L1 주소가 토큰의 L1 출처와 일치합니다 + +```solidity + ) { + // 예치가 완료되면 L2의 계정에 동일한 양의 + // 토큰을 입금합니다. + // slither-disable-next-line reentrancy-events + IL2StandardERC20(_l2Token).mint(_to, _amount); + // slither-disable-next-line reentrancy-events + emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); +``` + +온전성 검사를 통과하면 예치를 완료합니다. + +1. 토큰 민팅 +2. 적절한 이벤트 발생 + +```solidity + } else { + // 예치되는 L2 토큰이 L1 토큰의 올바른 주소에 + // 동의하지 않거나 올바른 인터페이스를 지원하지 않습니다. + // 이것은 악의적인 L2 토큰이 있거나 사용자가 어떻게든 + // 잘못된 L2 토큰 주소를 지정하여 예치한 경우에만 발생해야 합니다. + // 어느 경우든 여기서 프로세스를 중지하고 인출 + // 메시지를 구성하여 사용자가 경우에 따라 자금을 꺼낼 수 있도록 합니다. + // 악의적인 토큰 컨트랙트를 완전히 막을 방법은 없지만, 이는 사용자 + // 오류를 제한하고 일부 형태의 악의적인 컨트랙트 동작을 완화합니다. +``` + +사용자가 잘못된 L2 토큰 주소를 사용하여 감지 가능한 오류를 범한 경우, 예치를 취소하고 L1에서 토큰을 반환하고 싶습니다. +L2에서 이를 수행할 수 있는 유일한 방법은 결함 챌린지 기간을 기다려야 하는 메시지를 보내는 것이지만, 이는 사용자가 토큰을 영구적으로 잃는 것보다 훨씬 낫습니다. + +```solidity + bytes memory message = abi.encodeWithSelector( + IL1ERC20Bridge.finalizeERC20Withdrawal.selector, + _l1Token, + _l2Token, + _to, // 예치를 발신자에게 반송하기 위해 여기서 _to와 _from을 바꿈 + _from, + _amount, + _data + ); + + // L1 브리지로 메시지 전송 + // slither-disable-next-line reentrancy-events + sendCrossDomainMessage(l1TokenBridge, 0, message); + // slither-disable-next-line reentrancy-events + emit DepositFailed(_l1Token, _l2Token, _from, _to, _amount, _data); + } + } +} +``` + +## 결론 {#conclusion} + +표준 브리지는 자산 전송을 위한 가장 유연한 메커니즘입니다. +그러나 너무 일반적이기 때문에 항상 사용하기 가장 쉬운 메커니즘은 아닙니다. +특히 인출의 경우, 대부분의 사용자는 챌린지 기간을 기다리지 않고 인출을 완료하기 위해 머클 증명이 필요 없는 [타사 브리지](https://optimism.io/apps#bridge)를 사용하는 것을 선호합니다. + +이러한 브리지는 일반적으로 L1에 자산을 보유하고 있어 즉시 제공하며 약간의 수수료(종종 표준 브리지 인출의 가스 비용보다 저렴함)를 받습니다. +브리지(또는 이를 운영하는 사람들)가 L1 자산이 부족할 것으로 예상하면 L2에서 충분한 자산을 전송합니다. 이는 매우 큰 인출이므로 인출 비용은 큰 금액에 걸쳐 상각되며 훨씬 작은 비율을 차지합니다. + +이 글이 레이어 2가 어떻게 작동하는지, 그리고 명확하고 안전한 Solidity 코드를 작성하는 방법에 대해 더 많이 이해하는 데 도움이 되었기를 바랍니다. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). diff --git a/public/content/translations/ko/developers/tutorials/reverse-engineering-a-contract/index.md b/public/content/translations/ko/developers/tutorials/reverse-engineering-a-contract/index.md new file mode 100644 index 00000000000..ff4540b96dd --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/reverse-engineering-a-contract/index.md @@ -0,0 +1,744 @@ +--- +title: "계약 리버스 엔지니어링" +description: "소스 코드가 없을 때 계약을 이해하는 방법" +author: Ori Pomerantz +lang: ko +tags: [ "evm", "연산 부호" ] +skill: advanced +published: 2021-12-30 +--- + +## 소개 {#introduction} + +_블록체인에는 비밀이 없으며_, 발생하는 모든 일은 일관되고 검증 가능하며 공개적으로 이용 가능합니다. 이상적으로 [계약은 소스 코드를 Etherscan에 게시하고 확인해야 합니다](https://etherscan.io/address/0xb8901acb165ed027e32754e0ffe830802919727f#code). 그러나 [항상 그런 것은 아닙니다](https://etherscan.io/address/0x2510c039cc3b061d79e564b38836da87e31b342f#code). 이 글에서는 소스 코드 없이 [`0x2510c039cc3b061d79e564b38836da87e31b342f`](https://etherscan.io/address/0x2510c039cc3b061d79e564b38836da87e31b342f) 계약을 살펴봄으로써 계약을 리버스 엔지니어링하는 방법을 배웁니다. + +리버스 컴파일러가 있지만 항상 [사용 가능한 결과](https://etherscan.io/bytecode-decompiler?a=0x2510c039cc3b061d79e564b38836da87e31b342f)를 생성하는 것은 아닙니다. 이 글에서는 [연산 부호](https://github.com/wolflo/evm-opcodes)에서 계약을 수동으로 리버스 엔지니어링하고 이해하는 방법과 디컴파일러의 결과를 해석하는 방법을 배웁니다. + +이 글을 이해하려면 EVM의 기본 사항을 이미 알고 있어야 하며 EVM 어셈블러에 어느 정도 익숙해야 합니다. [여기에서 이러한 주제에 대해 읽을 수 있습니다](https://medium.com/mycrypto/the-ethereum-virtual-machine-how-does-it-work-9abac2b7c9e). + +## 실행 코드 준비 {#prepare-the-executable-code} + +Etherscan에서 계약으로 이동하여 **계약** 탭을 클릭한 다음 연산 부호 보기로 전환을 클릭하여 연산 부호를 얻을 수 있습니다. 한 줄에 하나의 연산 부호가 표시되는 보기를 얻습니다. + +![Etherscan의 연산 부호 보기](opcode-view.png) + +그러나 점프를 이해하려면 각 연산 부호가 코드의 어디에 있는지 알아야 합니다. 그러기 위한 한 가지 방법은 구글 스프레드시트를 열고 C열에 연산 부호를 붙여넣는 것입니다. [이미 준비된 스프레드시트의 사본을 만들어 다음 단계를 건너뛸 수 있습니다](https://docs.google.com/spreadsheets/d/1tKmTJiNjUwHbW64wCKOSJxHjmh0bAUapt6btUYE7kDA/edit?usp=sharing). + +다음 단계는 점프를 이해할 수 있도록 올바른 코드 위치를 얻는 것입니다. B열에 연산 부호 크기를, A열에 위치(16진수)를 넣습니다. `B1` 셀에 이 함수를 입력한 다음 코드 끝까지 나머지 B열에 복사하여 붙여넣습니다. 이 작업을 마친 후 B열을 숨길 수 있습니다. + +``` +=1+IF(REGEXMATCH(C1,"PUSH"),REGEXEXTRACT(C1,"PUSH(\d+)"),0) +``` + +먼저 이 함수는 연산 부호 자체에 1바이트를 추가한 다음 `PUSH`를 찾습니다. 푸시 연산 부호는 푸시되는 값에 대한 추가 바이트가 필요하기 때문에 특별합니다. 연산 부호가 `PUSH`인 경우 바이트 수를 추출하여 추가합니다. + +`A1`에 첫 번째 오프셋인 0을 넣습니다. 그런 다음 `A2`에 이 함수를 넣고 나머지 A열에 다시 복사하여 붙여넣습니다. + +``` +=dec2hex(hex2dec(A1)+B1) +``` + +점프(`JUMP` 및 `JUMPI`) 전에 푸시되는 값이 16진수로 주어지기 때문에 16진수 값을 얻으려면 이 함수가 필요합니다. + +## 진입점(0x00) {#the-entry-point-0x00} + +계약은 항상 첫 번째 바이트부터 실행됩니다. 이는 코드의 초기 부분입니다: + +| 오프셋 | 연산 부호 | 스택(연산 부호 후) | +| --: | ------------ | ---------------------------------------------- | +| 0 | PUSH1 0x80 | 0x80 | +| 2 | PUSH1 0x40 | 0x40, 0x80 | +| 4 | MSTORE | 비어 있음 | +| 5 | PUSH1 0x04 | 0x04 | +| 7 | CALLDATASIZE | CALLDATASIZE 0x04 | +| 8 | LT | CALLDATASIZE\<4 | +| 9 | PUSH2 0x005e | 0x5E CALLDATASIZE\<4 | +| C | JUMPI | 비어 있음 | + +이 코드는 두 가지 작업을 수행합니다. + +1. 0x80을 32바이트 값으로 메모리 위치 0x40-0x5F에 씁니다(0x80은 0x5F에 저장되고 0x40-0x5E는 모두 0입니다). +2. 호출 데이터 크기를 읽습니다. 일반적으로 이더리움 계약의 호출 데이터는 [ABI(애플리케이션 바이너리 인터페이스)](https://docs.soliditylang.org/en/v0.8.10/abi-spec.html)를 따르며, 함수 선택기에 최소 4바이트가 필요합니다. 호출 데이터 크기가 4보다 작으면 0x5E로 점프합니다. + +![이 부분에 대한 순서도](flowchart-entry.png) + +### 0x5E의 핸들러(비 ABI 호출 데이터용) {#the-handler-at-0x5e-for-non-abi-call-data} + +| 오프셋 | 연산 부호 | +| --: | ------------ | +| 5E | JUMPDEST | +| 5F | CALLDATASIZE | +| 60 | PUSH2 0x007c | +| 63 | JUMPI | + +이 스니펫은 `JUMPDEST`로 시작합니다. EVM(이더리움 가상 머신) 프로그램은 `JUMPDEST`가 아닌 연산 부호로 점프하면 예외를 발생시킵니다. 그런 다음 CALLDATASIZE를 보고 "true"(즉, 0이 아님)이면 0x7C로 점프합니다. 아래에서 살펴보겠습니다. + +| 오프셋 | 연산 부호 | 스택(연산 부호 후) | +| --: | ---------- | -------------------------------------------------------------------------------------- | +| 64 | CALLVALUE | 호출에서 제공하는 [Wei](/glossary/#wei). Solidity에서는 `msg.value`라고 합니다 | +| 65 | PUSH1 0x06 | 6 CALLVALUE | +| 67 | PUSH1 0x00 | 0 6 CALLVALUE | +| 69 | DUP3 | CALLVALUE 0 6 CALLVALUE | +| 6A | DUP3 | 6 CALLVALUE 0 6 CALLVALUE | +| 6B | SLOAD | Storage[6] CALLVALUE 0 6 CALLVALUE | + +따라서 호출 데이터가 없으면 Storage[6]의 값을 읽습니다. 이 값이 무엇인지는 아직 모르지만, 계약이 호출 데이터 없이 수신한 트랜잭션을 찾아볼 수 있습니다. 호출 데이터 없이(따라서 메서드 없이) ETH만 전송하는 트랜잭션은 Etherscan에 `Transfer` 메서드가 있습니다. 실제로 [계약이 받은 첫 번째 트랜잭션](https://etherscan.io/tx/0xeec75287a583c36bcc7ca87685ab41603494516a0f5986d18de96c8e630762e7)은 전송입니다. + +해당 트랜잭션을 살펴보고 더 보려면 클릭을 클릭하면 입력 데이터라고 하는 호출 데이터가 실제로 비어 있음(`0x`)을 알 수 있습니다. 값이 1.559ETH라는 점도 주목하십시오. 이는 나중에 관련이 있습니다. + +![호출 데이터가 비어 있습니다](calldata-empty.png) + +다음으로 **상태** 탭을 클릭하고 리버스 엔지니어링 중인 계약(0x2510...)을 확장합니다. `Storage[6]`이 트랜잭션 중에 변경되었음을 볼 수 있으며, 16진수를 숫자로 변경하면 1,559,000,000,000,000,000, 즉 wei로 전송된 값(명확성을 위해 쉼표를 추가함)이 되어 다음 계약 값에 해당함을 볼 수 있습니다. + +![Storage[6]의 변경 사항](storage6.png) + +[동일한 기간의 다른 `전송` 트랜잭션으로 인한 상태 변경](https://etherscan.io/tx/0xf708d306de39c422472f43cb975d97b66fd5d6a6863db627067167cbf93d84d1#statechange)을 살펴보면 `Storage[6]`이 한동안 계약의 가치를 추적했음을 알 수 있습니다. 지금은 `Value*`라고 부르겠습니다. 별표(`*`)는 이 변수가 아직 무엇을 하는지 모른다는 것을 상기시켜 주지만, `ADDRESS BALANCE`를 사용하여 계정 잔액을 얻을 수 있을 때 매우 비싼 저장 공간을 사용할 필요가 없기 때문에 계약 값을 추적하는 것만으로는 충분하지 않습니다. 첫 번째 연산 부호는 계약 자체의 주소를 푸시합니다. 두 번째는 스택 맨 위에 있는 주소를 읽고 해당 주소의 잔액으로 바꿉니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------ | ------------------------------------------- | +| 6C | PUSH2 0x0075 | 0x75 Value\* CALLVALUE 0 6 CALLVALUE | +| 6F | SWAP2 | CALLVALUE Value\* 0x75 0 6 CALLVALUE | +| 70 | SWAP1 | Value\* CALLVALUE 0x75 0 6 CALLVALUE | +| 71 | PUSH2 0x01a7 | 0x01A7 Value\* CALLVALUE 0x75 0 6 CALLVALUE | +| 74 | JUMP | | + +점프 대상에서 이 코드를 계속 추적할 것입니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ---------- | ----------------------------------------------------------- | +| 1A7 | JUMPDEST | Value\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1A8 | PUSH1 0x00 | 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1AA | DUP3 | CALLVALUE 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1AB | NOT | 2^256-CALLVALUE-1 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | + +`NOT`은 비트 단위이므로 호출 값의 모든 비트 값을 반전시킵니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------ | ------------------------------------------------------------------------------------------------------ | +| 1AC | DUP3 | Value\* 2^256-CALLVALUE-1 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1AD | GT | Value\*>2^256-CALLVALUE-1 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1AE | ISZERO | Value\*\<=2^256-CALLVALUE-1 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1AF | PUSH2 0x01df | 0x01DF Value\*\<=2^256-CALLVALUE-1 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1B2 | JUMPI | | + +`Value*`가 2^256-CALLVALUE-1보다 작거나 같으면 점프합니다. 이는 오버플로우를 방지하기 위한 로직으로 보입니다. 실제로 몇 가지 무의미한 작업(예: 메모리에 쓰기 직전에 삭제됨) 후 오프셋 0x01DE에서 오버플로우가 감지되면 계약이 되돌려지며, 이는 정상적인 동작입니다. + +이러한 오버플로우는 호출 값에 `Value*`를 더한 값이 2^256 wei(약 10^59 ETH)에 필적해야 하므로 발생할 가능성이 매우 낮습니다. [작성 시점의 총 ETH 공급량은 2억 미만입니다](https://etherscan.io/stat/supply). + +| 오프셋 | 연산 부호 | 스택 | +| --: | -------- | ----------------------------------------- | +| 1DF | JUMPDEST | 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1E0 | POP | Value\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1E1 | ADD | Value\*+CALLVALUE 0x75 0 6 CALLVALUE | +| 1E2 | SWAP1 | 0x75 Value\*+CALLVALUE 0 6 CALLVALUE | +| 1E3 | JUMP | | + +여기에 도착하면 `Value* + CALLVALUE`를 가져와 오프셋 0x75로 점프합니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | -------- | ------------------------------- | +| 75 | JUMPDEST | Value\*+CALLVALUE 0 6 CALLVALUE | +| 76 | SWAP1 | 0 Value\*+CALLVALUE 6 CALLVALUE | +| 77 | SWAP2 | 6 Value\*+CALLVALUE 0 CALLVALUE | +| 78 | SSTORE | 0 CALLVALUE | + +여기에 도착하면(호출 데이터가 비어 있어야 함) `Value*`에 호출 값을 추가합니다. 이는 `전송` 트랜잭션이 수행하는 작업과 일치합니다. + +| 오프셋 | 연산 부호 | +| --: | ----- | +| 79 | POP | +| 7A | POP | +| 7B | STOP | + +마지막으로 스택을 지우고(필수는 아님) 트랜잭션이 성공적으로 끝났음을 알립니다. + +요약하자면, 다음은 초기 코드에 대한 순서도입니다. + +![진입점 순서도](flowchart-entry.png) + +## 0x7C의 핸들러 {#the-handler-at-0x7c} + +이 핸들러가 무엇을 하는지 제목에 일부러 넣지 않았습니다. 요점은 이 특정 계약이 어떻게 작동하는지 가르치는 것이 아니라 계약을 리버스 엔지니어링하는 방법을 가르치는 것입니다. 코드를 따라 제가 했던 것과 같은 방식으로 코드가 무엇을 하는지 배울 것입니다. + +우리는 여러 곳에서 여기에 도착합니다: + +- 1, 2 또는 3바이트의 호출 데이터가 있는 경우(오프셋 0x63에서) +- 메서드 서명을 알 수 없는 경우(오프셋 0x42 및 0x5D에서) + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------ | ------------------------------------------------------------------------ | +| 7C | JUMPDEST | | +| 7D | PUSH1 0x00 | 0x00 | +| 7F | PUSH2 0x009d | 0x9D 0x00 | +| 82 | PUSH1 0x03 | 0x03 0x9D 0x00 | +| 84 | SLOAD | Storage[3] 0x9D 0x00 | + +이것은 또 다른 저장 공간 셀이며, 어떤 트랜잭션에서도 찾을 수 없었기 때문에 무엇을 의미하는지 알기가 더 어렵습니다. 아래 코드를 보면 더 명확해질 것입니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| 85 | PUSH20 0xffffffffffffffffffffffffffffffffffffffff | 0xff....ff Storage[3] 0x9D 0x00 | +| 9A | AND | Storage[3]-as-address 0x9D 0x00 | + +이 연산 부호는 Storage[3]에서 읽은 값을 이더리움 주소의 길이인 160비트로 자릅니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ----- | ----------------------------------------------------------------------------------- | +| 9B | SWAP1 | 0x9D Storage[3]-as-address 0x00 | +| 9C | JUMP | Storage[3]-as-address 0x00 | + +다음 연산 부호로 이동하므로 이 점프는 불필요합니다. 이 코드는 가능한 만큼 가스 효율적이지 않습니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ---------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| 9D | JUMPDEST | Storage[3]-as-address 0x00 | +| 9E | SWAP1 | 0x00 Storage[3]-as-address | +| 9F | POP | Storage[3]-as-address | +| A0 | PUSH1 0x40 | 0x40 Storage[3]-as-address | +| A2 | MLOAD | Mem[0x40] Storage[3]-as-address | + +코드 맨 처음에 Mem[0x40]을 0x80으로 설정했습니다. 나중에 0x40을 찾아보면 변경하지 않은 것을 알 수 있으므로 0x80이라고 가정할 수 있습니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------ | ----------------------------------------------------------------------------------------------------- | +| A3 | CALLDATASIZE | CALLDATASIZE 0x80 Storage[3]-as-address | +| A4 | PUSH1 0x00 | 0x00 CALLDATASIZE 0x80 Storage[3]-as-address | +| A6 | DUP3 | 0x80 0x00 CALLDATASIZE 0x80 Storage[3]-as-address | +| A7 | CALLDATACOPY | 0x80 Storage[3]-as-address | + +모든 호출 데이터를 0x80부터 시작하여 메모리에 복사합니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| A8 | PUSH1 0x00 | 0x00 0x80 Storage[3]-as-address | +| AA | DUP1 | 0x00 0x00 0x80 Storage[3]-as-address | +| AB | CALLDATASIZE | CALLDATASIZE 0x00 0x00 0x80 Storage[3]-as-address | +| AC | DUP4 | 0x80 CALLDATASIZE 0x00 0x00 0x80 Storage[3]-as-address | +| AD | DUP6 | Storage[3]-as-address 0x80 CALLDATASIZE 0x00 0x00 0x80 Storage[3]-as-address | +| AE | GAS | GAS Storage[3]-as-address 0x80 CALLDATASIZE 0x00 0x00 0x80 Storage[3]-as-address | +| AF | DELEGATE_CALL | | + +이제 훨씬 명확해졌습니다. 이 계약은 [프록시](https://blog.openzeppelin.com/proxy-patterns/) 역할을 하여 Storage[3]의 주소를 호출하여 실제 작업을 수행할 수 있습니다. `DELEGATE_CALL`은 별도의 계약을 호출하지만 동일한 저장 공간에 머물러 있습니다. 이는 우리가 프록시인 위임된 계약이 동일한 저장 공간 공간에 액세스한다는 것을 의미합니다. 호출 매개 변수는 다음과 같습니다. + +- _가스_: 남은 모든 가스 +- _호출된 주소_: Storage[3]-as-address +- _호출 데이터_: 0x80에서 시작하는 CALLDATASIZE 바이트. 여기에 원래 호출 데이터를 넣습니다. +- _반환 데이터_: 없음(0x00 - 0x00) 다른 방법으로 반환 데이터를 얻을 것입니다(아래 참조). + +| 오프셋 | 연산 부호 | 스택 | +| --: | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| B0 | RETURNDATASIZE | RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | +| B1 | DUP1 | RETURNDATASIZE RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | +| B2 | PUSH1 0x00 | 0x00 RETURNDATASIZE RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | +| B4 | DUP5 | 0x80 0x00 RETURNDATASIZE RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | +| B5 | RETURNDATACOPY | RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | + +여기에서 모든 반환 데이터를 0x80에서 시작하는 메모리 버퍼에 복사합니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| B6 | DUP2 | (((호출 성공/실패))) RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | +| B7 | DUP1 | (((호출 성공/실패))) (((호출 성공/실패))) RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | +| B8 | ISZERO | (((호출에 실패했습니까))) (((호출 성공/실패))) RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | +| B9 | PUSH2 0x00c0 | 0xC0 (((호출에 실패했습니까))) (((호출 성공/실패))) RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | +| BC | JUMPI | (((호출 성공/실패))) RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | +| BD | DUP2 | RETURNDATASIZE (((호출 성공/실패))) RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | +| BE | DUP5 | 0x80 RETURNDATASIZE (((호출 성공/실패))) RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | +| BF | RETURN | | + +따라서 호출 후 반환 데이터를 버퍼 0x80 - 0x80+RETURNDATASIZE에 복사하고 호출이 성공하면 해당 버퍼로 `RETURN`합니다. + +### DELEGATECALL 실패 {#delegatecall-failed} + +여기 0xC0에 도착하면 우리가 호출한 계약이 되돌려졌다는 의미입니다. 우리는 해당 계약의 프록시일 뿐이므로 동일한 데이터를 반환하고 되돌리고 싶습니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| C0 | JUMPDEST | (((호출 성공/실패))) RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | +| C1 | DUP2 | RETURNDATASIZE (((호출 성공/실패))) RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | +| C2 | DUP5 | 0x80 RETURNDATASIZE (((호출 성공/실패))) RETURNDATASIZE (((호출 성공/실패))) 0x80 Storage[3]-as-address | +| C3 | REVERT | | + +따라서 이전에 `RETURN`에 사용했던 것과 동일한 버퍼로 `REVERT`합니다: 0x80 - 0x80+RETURNDATASIZE + +![프록시 호출 순서도](flowchart-proxy.png) + +## ABI 호출 {#abi-calls} + +호출 데이터 크기가 4바이트 이상이면 유효한 ABI 호출일 수 있습니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------ | --------------------------------------------------------------------------------------------------------- | +| D | PUSH1 0x00 | 0x00 | +| F | CALLDATALOAD | (((호출 데이터의 첫 단어(256비트))) | +| 10 | PUSH1 0xe0 | 0xE0 (((호출 데이터의 첫 단어(256비트))) | +| 12 | SHR | (((호출 데이터의 처음 32비트(4바이트))) | + +Etherscan은 `1C`가 알려지지 않은 연산 부호라고 알려주는데, [Etherscan이 이 기능을 작성한 후에 추가되었고](https://eips.ethereum.org/EIPS/eip-145) 업데이트되지 않았기 때문입니다. [최신 연산 부호 표](https://github.com/wolflo/evm-opcodes)를 보면 이것이 오른쪽 시프트임을 알 수 있습니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| 13 | DUP1 | (((호출 데이터의 처음 32비트(4바이트))) (((호출 데이터의 처음 32비트(4바이트))) | +| 14 | PUSH4 0x3cd8045e | 0x3CD8045E (((호출 데이터의 처음 32비트(4바이트))) (((호출 데이터의 처음 32비트(4바이트))) | +| 19 | GT | 0x3CD8045E>호출 데이터의 처음 32비트 (((호출 데이터의 처음 32비트(4바이트))) | +| 1A | PUSH2 0x0043 | 0x43 0x3CD8045E>호출 데이터의 처음 32비트 (((호출 데이터의 처음 32비트(4바이트))) | +| 1D | JUMPI | (((호출 데이터의 처음 32비트(4바이트))) | + +이처럼 메서드 서명 일치 테스트를 둘로 나누면 평균적으로 테스트의 절반을 절약할 수 있습니다. 이를 바로 뒤따르는 코드와 0x43의 코드는 동일한 패턴을 따릅니다: 호출 데이터의 처음 32비트를 `DUP1`하고, `PUSH4 (((메서드 서명))`을 실행하고, `EQ`를 실행하여 동등성을 확인한 다음, 메서드 서명이 일치하면 `JUMPI`합니다. 다음은 메서드 서명, 해당 주소, 그리고 알려진 경우 [해당 메서드 정의](https://www.4byte.directory/)입니다. + +| 메서드 | 메서드 서명 | 점프할 오프셋 | +| --------------------------------------------------------------------------------------------------------- | ---------- | ------- | +| [splitter()](https://www.4byte.directory/signatures/?bytes4_signature=0x3cd8045e) | 0x3cd8045e | 0x0103 | +| ??? | 0x81e580d3 | 0x0138 | +| [currentWindow()](https://www.4byte.directory/signatures/?bytes4_signature=0xba0bafb4) | 0xba0bafb4 | 0x0158 | +| ??? | 0x1f135823 | 0x00C4 | +| [merkleRoot()](https://www.4byte.directory/signatures/?bytes4_signature=0x2eb4a7ab) | 0x2eb4a7ab | 0x00ED | + +일치하는 항목이 없으면 코드는 프록시인 계약에 일치하는 항목이 있기를 바라며 [0x7C의 프록시 핸들러](#the-handler-at-0x7c)로 점프합니다. + +![ABI 호출 순서도](flowchart-abi.png) + +## splitter() {#splitter} + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------ | ----------------------------- | +| 103 | JUMPDEST | | +| 104 | CALLVALUE | CALLVALUE | +| 105 | DUP1 | CALLVALUE CALLVALUE | +| 106 | ISZERO | CALLVALUE==0 CALLVALUE | +| 107 | PUSH2 0x010f | 0x010F CALLVALUE==0 CALLVALUE | +| 10A | JUMPI | CALLVALUE | +| 10B | PUSH1 0x00 | 0x00 CALLVALUE | +| 10D | DUP1 | 0x00 0x00 CALLVALUE | +| 10E | REVERT | | + +이 함수가 가장 먼저 하는 일은 호출이 ETH를 보내지 않았는지 확인하는 것입니다. 이 함수는 [`payable`이 아닙니다](https://solidity-by-example.org/payable/). 누군가 우리에게 ETH를 보냈다면 그것은 실수임에 틀림없으며, 그들이 다시 돌려받을 수 없는 곳에 ETH가 있는 것을 피하기 위해 `REVERT`하고 싶습니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 10F | JUMPDEST | | +| 110 | POP | | +| 111 | PUSH1 0x03 | 0x03 | +| 113 | SLOAD | (((Storage[3], 즉 우리가 프록시인 계약))) | +| 114 | PUSH1 0x40 | 0x40 (((Storage[3], 즉 우리가 프록시인 계약))) | +| 116 | MLOAD | 0x80 (((Storage[3], 즉 우리가 프록시인 계약))) | +| 117 | PUSH20 0xffffffffffffffffffffffffffffffffffffffff | 0xFF...FF 0x80 (((Storage[3], 즉 우리가 프록시인 계약))) | +| 12C | SWAP1 | 0x80 0xFF...FF (((Storage[3], 즉 우리가 프록시인 계약))) | +| 12D | SWAP2 | (((Storage[3], 즉 우리가 프록시인 계약))) 0xFF...FF 0x80 | +| 12E | AND | ProxyAddr 0x80 | +| 12F | DUP2 | 0x80 ProxyAddr 0x80 | +| 130 | MSTORE | 0x80 | + +그리고 0x80은 이제 프록시 주소를 포함합니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------ | --------- | +| 131 | PUSH1 0x20 | 0x20 0x80 | +| 133 | ADD | 0xA0 | +| 134 | PUSH2 0x00e4 | 0xE4 0xA0 | +| 137 | JUMP | 0xA0 | + +### E4 코드 {#the-e4-code} + +이 줄은 처음 보지만 다른 메서드와 공유됩니다(아래 참조). 따라서 스택의 값을 X라고 부르고, `splitter()`에서 이 X의 값이 0xA0이라는 것을 기억하십시오. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ---------- | ----------- | +| E4 | JUMPDEST | X | +| E5 | PUSH1 0x40 | 0x40 X | +| E7 | MLOAD | 0x80 X | +| E8 | DUP1 | 0x80 0x80 X | +| E9 | SWAP2 | X 0x80 0x80 | +| EA | SUB | X-0x80 0x80 | +| EB | SWAP1 | 0x80 X-0x80 | +| EC | RETURN | | + +따라서 이 코드는 스택(X)에서 메모리 포인터를 수신하고 계약이 0x80 - X인 버퍼로 `RETURN`하도록 합니다. + +`splitter()`의 경우, 이는 우리가 프록시인 주소를 반환합니다. `RETURN`은 0x80-0x9F의 버퍼를 반환하며, 여기에 이 데이터를 썼습니다(위 오프셋 0x130). + +## currentWindow() {#currentwindow} + +오프셋 0x158-0x163의 코드는 `splitter()`의 0x103-0x10E에서 본 것과 동일하므로(`JUMPI` 대상 제외), `currentWindow()`도 `payable`이 아님을 알 수 있습니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------ | ------------------------------------------------------------------------ | +| 164 | JUMPDEST | | +| 165 | POP | | +| 166 | PUSH2 0x00da | 0xDA | +| 169 | PUSH1 0x01 | 0x01 0xDA | +| 16B | SLOAD | Storage[1] 0xDA | +| 16C | DUP2 | 0xDA Storage[1] 0xDA | +| 16D | JUMP | Storage[1] 0xDA | + +### DA 코드 {#the-da-code} + +이 코드는 다른 메서드와도 공유됩니다. 따라서 스택의 값을 Y라고 부르고, `currentWindow()`에서 이 Y의 값이 Storage[1]이라는 것을 기억하십시오. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ---------- | ---------------- | +| DA | JUMPDEST | Y 0xDA | +| DB | PUSH1 0x40 | 0x40 Y 0xDA | +| DD | MLOAD | 0x80 Y 0xDA | +| DE | SWAP1 | Y 0x80 0xDA | +| DF | DUP2 | 0x80 Y 0x80 0xDA | +| E0 | MSTORE | 0x80 0xDA | + +Y를 0x80-0x9F에 씁니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ---------- | -------------- | +| E1 | PUSH1 0x20 | 0x20 0x80 0xDA | +| E3 | ADD | 0xA0 0xDA | + +그리고 나머지는 이미 [위에서](#the-e4-code) 설명했습니다. 따라서 0xDA로 점프하면 스택 맨 위(Y)를 0x80-0x9F에 쓰고 해당 값을 반환합니다. `currentWindow()`의 경우 Storage[1]을 반환합니다. + +## merkleRoot() {#merkleroot} + +오프셋 0xED-0xF8의 코드는 `splitter()`의 0x103-0x10E에서 본 것과 동일하므로(`JUMPI` 대상 제외), `merkleRoot()`도 `payable`이 아님을 알 수 있습니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------ | ------------------------------------------------------------------------ | +| F9 | JUMPDEST | | +| FA | POP | | +| FB | PUSH2 0x00da | 0xDA | +| FE | PUSH1 0x00 | 0x00 0xDA | +| 100 | SLOAD | Storage[0] 0xDA | +| 101 | DUP2 | 0xDA Storage[0] 0xDA | +| 102 | JUMP | Storage[0] 0xDA | + +점프 후에 일어나는 일은 [이미 알아냈습니다](#the-da-code). 따라서 `merkleRoot()`는 Storage[0]을 반환합니다. + +## 0x81e580d3 {#0x81e580d3} + +오프셋 0x138-0x143의 코드는 `splitter()`의 0x103-0x10E에서 본 것과 동일하므로(`JUMPI` 대상 제외), 이 함수도 `payable`이 아님을 알 수 있습니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------ | ------------------------------------------------------------------------------- | +| 144 | JUMPDEST | | +| 145 | POP | | +| 146 | PUSH2 0x00da | 0xDA | +| 149 | PUSH2 0x0153 | 0x0153 0xDA | +| 14C | CALLDATASIZE | CALLDATASIZE 0x0153 0xDA | +| 14D | PUSH1 0x04 | 0x04 CALLDATASIZE 0x0153 0xDA | +| 14F | PUSH2 0x018f | 0x018F 0x04 CALLDATASIZE 0x0153 0xDA | +| 152 | JUMP | 0x04 CALLDATASIZE 0x0153 0xDA | +| 18F | JUMPDEST | 0x04 CALLDATASIZE 0x0153 0xDA | +| 190 | PUSH1 0x00 | 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 192 | PUSH1 0x20 | 0x20 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 194 | DUP3 | 0x04 0x20 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 195 | DUP5 | CALLDATASIZE 0x04 0x20 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 196 | SUB | CALLDATASIZE-4 0x20 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 197 | SLT | CALLDATASIZE-4\<32 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 198 | ISZERO | CALLDATASIZE-4>=32 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 199 | PUSH2 0x01a0 | 0x01A0 CALLDATASIZE-4>=32 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 19C | JUMPI | 0x00 0x04 CALLDATASIZE 0x0153 0xDA | + +이 함수는 최소 32바이트(한 단어)의 호출 데이터를 사용하는 것 같습니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------ | -------------------------------------------- | +| 19D | DUP1 | 0x00 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 19E | DUP2 | 0x00 0x00 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 19F | REVERT | | + +호출 데이터를 얻지 못하면 트랜잭션은 반환 데이터 없이 되돌려집니다. + +함수가 필요한 호출 데이터를 _얻을_ 경우 어떻게 되는지 봅시다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------ | ----------------------------------------------------------- | +| 1A0 | JUMPDEST | 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 1A1 | POP | 0x04 CALLDATASIZE 0x0153 0xDA | +| 1A2 | CALLDATALOAD | calldataload(4) CALLDATASIZE 0x0153 0xDA | + +`calldataload(4)`는 메서드 서명 의 호출 데이터의 첫 단어입니다. + +| 오프셋 | 연산 부호 | 스택 | +| --: | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1A3 | SWAP2 | 0x0153 CALLDATASIZE calldataload(4) 0xDA | +| 1A4 | SWAP1 | CALLDATASIZE 0x0153 calldataload(4) 0xDA | +| 1A5 | POP | 0x0153 calldataload(4) 0xDA | +| 1A6 | JUMP | calldataload(4) 0xDA | +| 153 | JUMPDEST | calldataload(4) 0xDA | +| 154 | PUSH2 0x016e | 0x016E calldataload(4) 0xDA | +| 157 | JUMP | calldataload(4) 0xDA | +| 16E | JUMPDEST | calldataload(4) 0xDA | +| 16F | PUSH1 0x04 | 0x04 calldataload(4) 0xDA | +| 171 | DUP2 | calldataload(4) 0x04 calldataload(4) 0xDA | +| 172 | DUP2 | 0x04 calldataload(4) 0x04 calldataload(4) 0xDA | +| 173 | SLOAD | Storage[4] calldataload(4) 0x04 calldataload(4) 0xDA | +| 174 | DUP2 | calldataload(4) Storage[4] calldataload(4) 0x04 calldataload(4) 0xDA | +| 175 | LT | calldataload(4)\)`이고 다른 하나는 `isClaimed()`이므로 에어드랍 계약으로 보입니다. 나머지 연산 부호를 하나씩 살펴보는 대신, 이 계약의 세 함수에 대해 사용 가능한 결과를 생성하는 [디컴파일러를 사용해 볼 수 있습니다](https://etherscan.io/bytecode-decompiler?a=0x2f81e57ff4f4d83b40a9f719fd892d8e806e0761). 다른 것들을 리버스 엔지니어링하는 것은 독자의 연습 과제로 남겨둡니다. + +### scaleAmountByPercentage {#scaleamountbypercentage} + +이것이 이 함수에 대해 디컴파일러가 제공하는 것입니다. + +```python +def unknown8ffb5c97(uint256 _param1, uint256 _param2) payable: + require calldata.size - 4 >=′ 64 + if _param1 and _param2 > -1 / _param1: + revert with 0, 17 + return (_param1 * _param2 / 100 * 10^6) +``` + +첫 번째 `require`는 호출 데이터가 함수 서명의 4바이트 외에 두 매개 변수에 충분한 최소 64바이트를 가지고 있는지 테스트합니다. 그렇지 않다면 분명히 뭔가 잘못된 것입니다. + +`if` 문은 `_param1`이 0이 아니고 `_param1 * _param2`가 음수가 아님을 확인하는 것으로 보입니다. 아마도 랩 어라운드(wrap around) 사례를 방지하기 위함일 것입니다. + +마지막으로 함수는 확장된 값을 반환합니다. + +### claim {#claim} + +디컴파일러가 생성하는 코드는 복잡하며, 모든 것이 우리와 관련이 있는 것은 아닙니다. 유용한 정보를 제공한다고 생각되는 줄에 집중하기 위해 일부를 건너뛸 것입니다. + +```python +def unknown2e7ba6ef(uint256 _param1, uint256 _param2, uint256 _param3, array _param4) payable: + ... + require _param2 == addr(_param2) + ... + if currentWindow <= _param1: + revert with 0, '미래 창에 대한 클레임 불가' +``` + +여기서 두 가지 중요한 것을 알 수 있습니다. + +- `_param2`는 `uint256`으로 선언되었지만 실제로는 주소입니다. +- `_param1`은 클레임되는 창이며, `currentWindow` 또는 그 이전이어야 합니다. + +```python + ... + if stor5[_claimWindow][addr(_claimFor)]: + revert with 0, '계정이 이미 해당 창을 클레임했습니다' +``` + +이제 Storage[5]가 창과 주소의 배열이며, 해당 주소가 해당 창에 대한 보상을 클레임했는지 여부를 알 수 있습니다. + +```python + ... + idx = 0 + s = 0 + while idx < _param4.length: + ... + if s + sha3(mem[(32 * _param4.length) + 328 len mem[(32 * _param4.length) + 296]]) > mem[(32 * idx) + 296]: + mem[mem[64] + 32] = mem[(32 * idx) + 296] + ... + s = sha3(mem[_62 + 32 len mem[_62]]) + continue + ... + s = sha3(mem[_66 + 32 len mem[_66]]) + continue + if unknown2eb4a7ab != s: + revert with 0, '잘못된 증명' +``` + +우리는 `unknown2eb4a7ab`가 실제로는 `merkleRoot()` 함수라는 것을 알고 있으므로, 이 코드는 [머클 증명](https://medium.com/crypto-0-nite/merkle-proofs-explained-6dd429623dc5)을 검증하는 것으로 보입니다. 이는 `_param4`가 머클 증명임을 의미합니다. + +```python + call addr(_param2) with: + value unknown81e580d3[_param1] * _param3 / 100 * 10^6 wei + gas 30000 wei +``` + +이것이 계약이 자체 ETH를 다른 주소(계약 또는 외부 소유)로 전송하는 방법입니다. 전송할 금액인 값으로 호출합니다. 따라서 이것은 ETH의 에어드랍으로 보입니다. + +```python + if not return_data.size: + if not ext_call.success: + require ext_code.size(stor2) + call stor2.deposit() with: + value unknown81e580d3[_param1] * _param3 / 100 * 10^6 wei +``` + +아래 두 줄은 Storage[2]도 우리가 호출하는 계약임을 알려줍니다. [생성자 트랜잭션을 살펴보면](https://etherscan.io/tx/0xa1ea0549fb349eb7d3aff90e1d6ce7469fdfdcd59a2fd9b8d1f5e420c0d05b58#statechange) 이 계약이 [0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2](https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2)인 래핑된 이더 계약이며 [소스 코드가 Etherscan에 업로드된](https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code) 것을 알 수 있습니다. + +따라서 계약이 ETH를 `_param2`로 보내려고 시도하는 것으로 보입니다. 할 수 있다면 좋습니다. 그렇지 않으면 [WETH](https://weth.tkn.eth.limo/)를 보내려고 시도합니다. `_param2`가 외부 소유 계정(EOA)인 경우 항상 ETH를 수신할 수 있지만 계약은 ETH 수신을 거부할 수 있습니다. 그러나 WETH는 ERC-20이며 계약은 이를 수락하는 것을 거부할 수 없습니다. + +```python + ... + log 0xdbd5389f: addr(_param2), unknown81e580d3[_param1] * _param3 / 100 * 10^6, bool(ext_call.success) +``` + +함수 끝에서 로그 항목이 생성되는 것을 볼 수 있습니다. [생성된 로그 항목을 보고](https://etherscan.io/address/0x2510c039cc3b061d79e564b38836da87e31b342f#events) `0xdbd5...`로 시작하는 주제를 필터링합니다. [이러한 항목을 생성한 트랜잭션 중 하나를 클릭하면](https://etherscan.io/tx/0xe7d3b7e00f645af17dfbbd010478ef4af235896c65b6548def1fe95b3b7d2274) 실제로 클레임처럼 보이는 것을 알 수 있습니다. 계정은 리버스 엔지니어링 중인 계약에 메시지를 보냈고, 그 대가로 ETH를 받았습니다. + +![클레임 트랜잭션](claim-tx.png) + +### 1e7df9d3 {#1e7df9d3} + +이 함수는 위의 [`claim`](#claim)과 매우 유사합니다. 또한 머클 증명을 확인하고, ETH를 첫 번째로 전송하려고 시도하며, 동일한 유형의 로그 항목을 생성합니다. + +```python +def unknown1e7df9d3(uint256 _param1, uint256 _param2, array _param3) payable: + ... + idx = 0 + s = 0 + while idx < _param3.length: + if idx >= mem[96]: + revert with 0, 50 + _55 = mem[(32 * idx) + 128] + if s + sha3(mem[(32 * _param3.length) + 160 len mem[(32 * _param3.length) + 128]]) > mem[(32 * idx) + 128]: + ... + s = sha3(mem[_58 + 32 len mem[_58]]) + continue + mem[mem[64] + 32] = s + sha3(mem[(32 * _param3.length) + 160 len mem[(32 * _param3.length) + 128]]) + ... + if unknown2eb4a7ab != s: + revert with 0, '잘못된 증명' + ... + call addr(_param1) with: + value s wei + gas 30000 wei + if not return_data.size: + if not ext_call.success: + require ext_code.size(stor2) + call stor2.deposit() with: + value s wei + gas gas_remaining wei + ... + log 0xdbd5389f: addr(_param1), s, bool(ext_call.success) +``` + +주요 차이점은 첫 번째 매개 변수인 인출할 창이 없다는 것입니다. 대신 클레임할 수 있는 모든 창을 순회하는 루프가 있습니다. + +```python + idx = 0 + s = 0 + while idx < currentWindow: + ... + if stor5[mem[0]]: + if idx == -1: + revert with 0, 17 + idx = idx + 1 + s = s + continue + ... + stor5[idx][addr(_param1)] = 1 + if idx >= unknown81e580d3.length: + revert with 0, 50 + mem[0] = 4 + if unknown81e580d3[idx] and _param2 > -1 / unknown81e580d3[idx]: + revert with 0, 17 + if s > !(unknown81e580d3[idx] * _param2 / 100 * 10^6): + revert with 0, 17 + if idx == -1: + revert with 0, 17 + idx = idx + 1 + s = s + (unknown81e580d3[idx] * _param2 / 100 * 10^6) + continue +``` + +따라서 모든 창을 클레임하는 `claim` 변형으로 보입니다. + +## 결론 {#conclusion} + +이제 연산 부호 또는 (작동하는 경우) 디컴파일러를 사용하여 소스 코드를 사용할 수 없는 계약을 이해하는 방법을 알아야 합니다. 이 글의 길이에서 알 수 있듯이, 계약을 리버스 엔지니어링하는 것은 사소한 일이 아니지만, 보안이 필수적인 시스템에서는 계약이 약속대로 작동하는지 확인할 수 있는 중요한 기술입니다. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). diff --git a/public/content/translations/ko/developers/tutorials/run-node-raspberry-pi/index.md b/public/content/translations/ko/developers/tutorials/run-node-raspberry-pi/index.md new file mode 100644 index 00000000000..3886f506c97 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/run-node-raspberry-pi/index.md @@ -0,0 +1,184 @@ +--- +title: "Raspberry Pi 4에서 이더리움 노드 실행하기" +description: "Raspberry Pi 4를 플래시하고, 이더넷 케이블을 꽂고, SSD 디스크를 연결하고, 장치에 전원을 공급하여 Raspberry Pi 4를 완전한 이더리움 노드 + 검증자로 바꾸세요" +author: "EthereumOnArm" +tags: [ "클라이언트", "실행 레이어", "합의 레이어", "노드" ] +lang: ko +skill: intermediate +published: 2022-06-10 +source: Ethereum on ARM +sourceUrl: https://ethereum-on-arm-documentation.readthedocs.io/en/latest/ +--- + +**Ethereum on Arm은 라즈베리 파이를 이더리움 노드로 전환할 수 있는 맞춤형 리눅스 이미지입니다.** + +Ethereum on Arm을 사용하여 라즈베리 파이를 이더리움 노드로 전환하려면 다음과 같은 하웨어가 권장됩니다. + +- Raspberry 4 (B 모델 8GB), Odroid M1 또는 Rock 5B (8GB/16GB RAM) 보드 +- 마이크로SD 카드(최소 16GB 클래스 10) +- 최소 2TB SSD USB 3.0 디스크 또는 USB-SATA 케이스가 있는 SSD. +- 전원 공급 장치 +- 이더넷 케이블 +- 포트 포워딩(자세한 내용은 클라이언트를 참조하세요) +- 방열판과 팬이 있는 케이스 +- USB 키보드, 모니터 및 HDMI 케이블(마이크로-HDMI)(선택 사항) + +## ARM에서 이더리움을 실행해야 하는 이유 {#why-run-ethereum-on-arm} + +ARM 보드는 매우 저렴하고 유연한 소형 컴퓨터입니다. 저렴하게 구입할 수 있고, 모든 자원을 노드에만 집중하도록 구성하여 효율적이고, 전력 소비가 적으며, 물리적으로 작아 어느 집에나 눈에 띄지 않게 설치할 수 있으므로 이더리움 노드를 실행하기에 좋은 선택입니다. 또한 Raspberry Pi의 MicroSD는 사전 빌드된 이미지로 간단히 플래시할 수 있어 소프트웨어를 다운로드하거나 빌드할 필요가 없으므로 노드를 매우 쉽게 가동할 수 있습니다. + +## 어떻게 작동하나요? {#how-does-it-work} + +Raspberry Pi의 메모리 카드는 사전 빌드된 이미지로 플래시됩니다. 이 이미지에는 이더리움 노드를 실행하는 데 필요한 모든 것이 포함되어 있습니다. 플래시된 카드를 사용하면 사용자는 Raspberry Pi의 전원을 켜기만 하면 됩니다. 노드를 실행하는 데 필요한 모든 프로세스가 자동으로 시작됩니다. 이는 메모리 카드에 리눅스 기반 운영 체제(OS)가 포함되어 있고, 그 위에서 시스템 수준의 프로세스가 자동으로 실행되어 장치를 이더리움 노드로 전환하기 때문에 가능합니다. + +Raspbian은 여전히 32비트 아키텍처를 사용하기 때문에 이더리움 사용자가 메모리 문제에 직면하고 합의 클라이언트가 32비트 바이너리를 지원하지 않으므로, 널리 사용되는 Raspberry Pi Linux OS "Raspbian"을 사용하여 이더리움을 실행할 수 없습니다. 이를 극복하기 위해 Ethereum on Arm 팀은 "Armbian"이라는 네이티브 64비트 OS로 마이그레이션했습니다. + +**이미지는 환경 설정과 SSD 디스크 포맷부터 이더리움 소프트웨어 설치 및 실행, 블록체인 동기화 시작까지 모든 필요한 단계를 처리합니다.** + +## 실행 및 합의 클라이언트에 대한 참고 사항 {#note-on-execution-and-consensus-clients} + +Ethereum on Arm 이미지에는 사전 빌드된 실행 및 합의 클라이언트가 서비스로 포함되어 있습니다. 이더리움 노드는 두 클라이언트가 모두 동기화되고 실행되어야 합니다. 이미지를 다운로드하고 플래시한 다음 서비스를 시작하기만 하면 됩니다. 이미지에는 다음과 같은 실행 클라이언트가 사전 로드되어 있습니다. + +- Geth +- Nethermind +- Besu + +그리고 다음 합의 클라이언트가 포함됩니다: + +- Lighthouse +- Nimbus +- Prysm +- Teku + +각각 하나씩 선택하여 실행해야 합니다. 모든 실행 클라이언트는 모든 합의 클라이언트와 호환됩니다. 클라이언트를 명시적으로 선택하지 않으면 노드는 기본값인 Geth와 Lighthouse로 대체되고 보드에 전원이 공급될 때 자동으로 실행됩니다. Geth가 피어를 찾아 연결할 수 있도록 라우터에서 30303 포트를 열어야 합니다. + +## 이미지 다운로드하기 {#downloading-the-image} + +Raspberry Pi 4 이더리움 이미지는 실행 클라이언트와 합의 클라이언트를 모두 자동으로 설치 및 설정하고, 서로 통신하고 이더리움 네트워크에 연결하도록 구성하는 "플러그 앤 플레이" 이미지입니다. 사용자는 간단한 명령을 사용하여 프로세스를 시작하기만 하면 됩니다. + +[Ethereum on Arm](https://ethereumonarm-my.sharepoint.com/:u:/p/dlosada/Ec_VmUvr80VFjf3RYSU-NzkBmj2JOteDECj8Bibde929Gw?download=1)에서 라즈베리 파이 이미지를 다운로드하고 SHA256 해시를 확인하세요: + +```sh +# 다운로드한 이미지가 포함된 디렉터리에서 +shasum -a 256 ethonarm_22.04.00.img.zip +# 해시 출력: fb497e8f8a7388b62d6e1efbc406b9558bee7ef46ec7e53083630029c117444f +``` + +Rock 5B 및 Odroid M1 보드용 이미지는 Ethereum-on-Arm [다운로드 페이지](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/quick-guide/download-and-install.html)에서 사용할 수 있습니다. + +## MicroSD 플래시하기 {#flashing-the-microsd} + +Raspberry Pi에 사용할 MicroSD 카드는 먼저 데스크톱이나 노트북에 삽입하여 플래시해야 합니다. 그런 다음 다음 터미널 명령을 사용하여 다운로드한 이미지를 SD 카드에 플래시합니다: + +```shell +# MicroSD 카드 이름 확인 +sudo fdisk -l + +>> sdxxx +``` + +다음 명령에 카드의 기존 콘텐츠를 완전히 지우고 이미지를 푸시하는 `dd`가 포함되어 있으므로 이름을 올바르게 지정하는 것이 매우 중요합니다. 계속하려면 압축된 이미지가 포함된 디렉터리로 이동하세요: + +```shell +# 이미지 압축 해제 및 플래시 +unzip ethonarm_22.04.00.img.zip +sudo dd bs=1M if=ethonarm_22.04.00.img of=/dev/ conv=fdatasync status=progress +``` + +이제 카드가 플래시되었으므로 Raspberry Pi에 삽입할 수 있습니다. + +## 노드 시작하기 {#start-the-node} + +SD 카드를 Raspberry Pi에 삽입한 상태에서 이더넷 케이블과 SSD를 연결한 다음 전원을 켭니다. OS가 부팅되고 클라이언트 소프트웨어 설치 및 빌드를 포함하여 Raspberry Pi를 이더리움 노드로 전환하는 사전 구성된 작업을 자동으로 수행하기 시작합니다. 이 과정은 10\~15분 정도 소요될 수 있습니다. + +모든 것이 설치 및 구성되면 ssh 연결을 통해 장치에 로그인하거나 모니터와 키보드가 보드에 연결되어 있는 경우 터미널을 직접 사용하여 로그인합니다. `ethereum` 계정은 노드를 시작하는 데 필요한 권한을 가지고 있으므로 이 계정을 사용하여 로그인하세요. + +```shell +사용자: ethereum +비밀번호: ethereum +``` + +기본 실행 클라이언트인 Geth가 자동으로 시작됩니다. 다음 터미널 명령을 사용하여 로그를 확인하여 이를 확인할 수 있습니다. + +```sh +sudo journalctl -u geth -f +``` + +합의 클라이언트는 명시적으로 시작해야 합니다. 이렇게 하려면 먼저 라우터에서 9000 포트를 열어 Lighthouse가 피어를 찾아 연결할 수 있도록 하세요. 그런 다음 lighthouse 서비스를 활성화하고 시작합니다. + +```sh +sudo systemctl enable lighthouse-beacon +sudo systemctl start lighthouse-beacon +``` + +로그를 사용하여 클라이언트를 확인합니다. + +```sh +sudo journalctl -u lighthouse-beacon +``` + +합의 클라이언트는 체크포인트 동기화를 사용하므로 몇 분 안에 동기화됩니다. 실행 클라이언트는 더 오래 걸릴 수 있으며(몇 시간이 걸릴 수 있음) 합의 클라이언트가 이미 동기화를 마칠 때까지 시작되지 않습니다(이는 실행 클라이언트가 동기화할 대상이 필요하며 동기화된 합의 클라이언트가 이를 제공하기 때문입니다). + +Geth 및 Lighthouse 서비스가 실행되고 동기화되면 이제 Raspberry Pi는 이더리움 노드가 됩니다! 8545 포트의 Geth 클라이언트에 연결할 수 있는 Geth의 자바스크립트 콘솔을 사용하여 이더리움 네트워크와 상호 작용하는 것이 가장 일반적입니다. Curl과 같은 요청 도구를 사용하여 JSON 객체로 형식화된 명령을 제출할 수도 있습니다. [Geth 개발문서](https://geth.ethereum.org/)에서 자세한 내용을 확인하세요. + +Geth는 브라우저에서 볼 수 있는 Grafana 대시보드에 메트릭을 보고하도록 사전 구성되어 있습니다. 고급 사용자는 `ipaddress:3000`으로 이동하여 `user: admin` 및 `passwd: ethereum`을 전달하여 이 기능을 사용하여 노드의 상태를 모니터링할 수 있습니다. + +## 검증자 {#validators} + +합의 클라이언트에 검증자를 선택적으로 추가할 수도 있습니다. 검증자 소프트웨어를 사용하면 노드가 합의에 적극적으로 참여할 수 있으며 네트워크에 암호경제학적 보안을 제공합니다. 이 작업에 대한 보상으로 ETH를 받습니다. 검증자를 실행하려면 먼저 32 ETH가 있어야 하며, 이는 예금 계약에 예치되어야 합니다. [런치패드](https://launchpad.ethereum.org/)의 단계별 가이드를 따라 예치할 수 있습니다. 이 작업은 데스크톱/노트북에서 수행하지만 키는 생성하지 마세요. 이 작업은 Raspberry Pi에서 직접 수행할 수 있습니다. + +Raspberry Pi에서 터미널을 열고 다음 명령을 실행하여 예금 키를 생성합니다. + +``` +sudo apt-get update +sudo apt-get install staking-deposit-cli +cd && deposit new-mnemonic --num_validators 1 +``` + +(또는 에어갭 머신에서 실행하기 위해 [staking-deposit-cli](https://github.com/ethereum/staking-deposit-cli)를 다운로드하고 `deposit new-mnemnonic` 명령을 실행) + +니모닉 문구를 안전하게 보관하세요! 위의 명령은 노드의 키스토어에 두 개의 파일, 즉 검증자 키와 예금 데이터 파일을 생성했습니다. 예금 데이터를 런치패드에 업로드해야 하므로 Raspberry Pi에서 데스크톱/노트북으로 복사해야 합니다. 이 작업은 ssh 연결 또는 다른 복사/붙여넣기 방법을 사용하여 수행할 수 있습니다. + +예금 데이터 파일이 런치패드를 실행하는 컴퓨터에서 사용 가능해지면 런치패드 화면의 `+` 위로 끌어다 놓을 수 있습니다. 화면의 지시에 따라 예금 계약에 트랜잭션을 보냅니다. + +Raspberry Pi로 돌아가서 검증자를 시작할 수 있습니다. 이를 위해서는 검증자 키를 가져오고, 보상을 수집할 주소를 설정한 다음, 사전 구성된 검증자 프로세스를 시작해야 합니다. 아래 예시는 Lighthouse에 대한 것입니다. 다른 합의 클라이언트에 대한 지침은 [Ethereum on Arm 문서](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/)에서 확인할 수 있습니다. + +```shell +# 검증자 키 가져오기 +lighthouse account validator import --directory=/home/ethereum/validator_keys + +# 보상 주소 설정 +sudo sed -i 's/' /etc/ethereum/lighthouse-validator.conf + +# 검증자 시작 +sudo systemctl start lighthouse-validator +``` + +축하합니다! 이제 Raspberry Pi에서 완전한 이더리움 노드와 검증자를 실행하고 있습니다! + +## 자세한 내용 {#more-details} + +이 페이지에서는 Raspberry Pi를 사용하여 Geth-Lighthouse 노드 및 검증자를 설정하는 방법에 대한 개요를 제공했습니다. 더 자세한 지침은 [Ethereum-on-Arm 웹사이트](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/index.html)에서 확인할 수 있습니다. + +## 피드백을 기다립니다 {#feedback-appreciated} + +저희는 Raspberry Pi가 이더리움 네트워크의 건전성에 매우 긍정적인 영향을 미칠 수 있는 거대한 사용자 기반을 가지고 있다는 것을 알고 있습니다. +이 튜토리얼의 세부 사항을 자세히 살펴보고, 테스트넷에서 실행해보고, Ethereum on Arm GitHub를 확인하고, 피드백을 제공하고, 이슈와 풀 리퀘스트를 제기하여 기술과 개발문서를 발전시키는 데 도움을 주세요! + +## 참고 자료 {#references} + +1. https://ubuntu.com/download/raspberry-pi +2. https://wikipedia.org/wiki/Port_forwarding +3. https://prometheus.io +4. https://grafana.com +5. https://forum.armbian.com/topic/5565-zram-vs-swap/ +6. https://geth.ethereum.org +7. https://nethermind.io +8. https://www.hyperledger.org/projects/besu +9. https://github.com/prysmaticlabs/prysm +10. https://lighthouse.sigmaprime.io +11. https://ethersphere.github.io/swarm-home +12. https://raiden.network +13. https://ipfs.io +14. https://status.im +15. https://vipnode.org diff --git a/public/content/translations/ko/developers/tutorials/scam-token-tricks/index.md b/public/content/translations/ko/developers/tutorials/scam-token-tricks/index.md new file mode 100644 index 00000000000..0ce76115ac8 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/scam-token-tricks/index.md @@ -0,0 +1,463 @@ +--- +title: "스캠 토큰에 사용되는 몇 가지 속임수와 탐지 방법" +description: "이 튜토리얼에서는 스캠 토큰을 분석하여 사기꾼들이 사용하는 몇 가지 속임수, 구현 방법, 그리고 탐지 방법을 알아봅니다." +author: Ori Pomerantz +tags: [ "스캠", "Solidity", "erc-20", "JavaScript", "TypeScript" ] +skill: intermediate +published: 2023-09-15 +lang: ko +--- + +이 튜토리얼에서는 [스캠 토큰](https://etherscan.io/token/0xb047c8032b99841713b8e3872f06cf32beb27b82#code)을 분석하여 사기꾼들이 사용하는 몇 가지 속임수와 그 구현 방법을 살펴봅니다. 튜토리얼을 마치면 ERC-20 토큰 컨트랙트, 그 기능, 그리고 회의적인 시각이 필요한 이유에 대해 더 포괄적으로 이해하게 될 것입니다. 그런 다음 해당 스캠 토큰에서 발생된 이벤트를 살펴보고, 그것이 정당하지 않다는 것을 자동으로 식별하는 방법을 알아봅니다. + +## 스캠 토큰 - 정의, 사기 이유 및 방지 방법 {#scam-tokens} + +이더리움이 사용되는 대표적인 곳 중 하나는 거래 가능한 토큰을 만드는 그룹입니다. 거래 가능한 토큰은 자체 통화라고도 불립니다. 그렇지만 정당한 방법으로 값어치를 창출해낸 활용 사례가 있더라도 그 가치마저 가로채려는 범죄자들도 존재합니다. + +사용자 관점에서 이 주제에 대한 자세한 내용은 [ethereum.org의 다른 곳](/guides/how-to-id-scam-tokens/)에서 확인할 수 있습니다. 이 튜토리얼은 스캠 토큰을 분석하여 그 수법과 탐지 방법을 알아보는 데 중점을 둡니다. + +### wARB가 스캠이라는 것을 어떻게 알 수 있나요? {#warb-scam} + +분석할 토큰은 [wARB](https://etherscan.io/token/0xb047c8032b99841713b8e3872f06cf32beb27b82#code)이며, 이는 합법적인 [ARB 토큰](https://etherscan.io/token/0xb50721bcf8d664c30412cfbc6cf7a15145234ad1)과 동일한 것처럼 위장합니다. + +어떤 것이 합법적인 토큰인지 아는 가장 쉬운 방법은 발행 기관인 [Arbitrum](https://arbitrum.foundation/)을 확인하는 것입니다. 합법적인 주소는 [개발문서](https://docs.arbitrum.foundation/deployment-addresses#token)에 명시되어 있습니다. + +### 소스 코드는 왜 공개되어 있나요? {#why-source} + +일반적으로 다른 사람을 속이려는 사람들은 비밀스러울 것이라고 예상하며, 실제로 많은 스캠 토큰은 코드를 공개하지 않습니다(예: [이 토큰](https://optimistic.etherscan.io/token/0x15992f382d8c46d667b10dc8456dc36651af1452#code)과 [이 토큰](https://optimistic.etherscan.io/token/0x026b623eb4aada7de37ef25256854f9235207178#code)). + +그러나 합법적인 토큰은 일반적으로 소스 코드를 공개하므로, 합법적으로 보이기 위해 스캠 토큰 제작자들도 때때로 같은 방법을 사용합니다. [wARB](https://etherscan.io/token/0xb047c8032b99841713b8e3872f06cf32beb27b82#code)는 소스 코드가 공개된 토큰 중 하나이며, 덕분에 더 쉽게 이해할 수 있습니다. + +컨트랙트 배포자는 소스 코드를 공개할지 여부를 선택할 수 있지만, 잘못된 소스 코드를 공개할 수는 _없습니다_. 블록 탐색기는 제공된 소스 코드를 독립적으로 컴파일하며, 정확히 동일한 바이트코드를 얻지 못하면 해당 소스 코드를 거부합니다. [이에 대한 자세한 내용은 Etherscan 사이트에서 확인할 수 있습니다](https://etherscan.io/verifyContract). + +## 합법적인 ERC-20 토큰과의 비교 {#compare-legit-erc20} + +이 토큰을 합법적인 ERC-20 토큰과 비교해 보겠습니다. 합법적인 ERC-20 토큰이 일반적으로 어떻게 작성되는지 잘 모른다면 [이 튜토리얼](/developers/tutorials/erc20-annotated-code/)을 참조하세요. + +### 특권 주소에 대한 상수 {#constants-for-privileged-addresses} + +컨트랙트에는 때때로 특권 주소가 필요합니다. 장기적인 사용을 위해 설계된 컨트랙트는 새로운 멀티시그(multisig) 컨트랙트 사용을 활성화하는 등 일부 특권 주소가 해당 주소를 변경할 수 있도록 허용합니다. 이를 수행하는 데에는 몇 가지 방법이 있습니다. + +[`HOP` 토큰 컨트랙트](https://etherscan.io/address/0xc5102fe9359fd9a28f877a67e36b0f050d81a3cc#code)는 [`Ownable`](https://docs.openzeppelin.com/contracts/2.x/access-control#ownership-and-ownable) 패턴을 사용합니다. 특권 주소는 저장 공간의 `_owner`라는 필드에 보관됩니다(세 번째 파일 `Ownable.sol` 참조). + +```solidity +abstract contract Ownable is Context { + address private _owner; + . + . + . +} +``` + +[`ARB` 토큰 컨트랙트](https://etherscan.io/address/0xad0c361ef902a7d9851ca7dcc85535da2d3c6fc7#code)에는 특권 주소가 직접적으로 존재하지 않습니다. 하지만 필요하지 않습니다. 이것은 [주소 `0xb50721bcf8d664c30412cfbc6cf7a15145234ad1`](https://etherscan.io/address/0xb50721bcf8d664c30412cfbc6cf7a15145234ad1#code)에 있는 [`프록시`](https://docs.openzeppelin.com/contracts/5.x/api/proxy) 뒤에 위치합니다. 해당 컨트랙트에는 업그레이드에 사용할 수 있는 특권 주소가 있습니다(네 번째 파일 `ERC1967Upgrade.sol` 참조). + +```solidity + /** + * @dev EIP1967 관리자 슬롯에 새 주소를 저장합니다. + */ + function _setAdmin(address newAdmin) private { + require(newAdmin != address(0), "ERC1967: new admin is the zero address"); + StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; + } +``` + +반면, `wARB` 컨트랙트에는 하드코딩된 `contract_owner`가 있습니다. + +```solidity +contract WrappedArbitrum is Context, IERC20 { + . + . + . + address deployer = 0xB50721BCf8d664c30412Cfbc6cf7a15145234ad1; + address public contract_owner = 0xb40dE7b1beE84Ff2dc22B70a049A07A13a411A33; + . + . + . +} +``` + +이 컨트랙트 소유자는 다른 시점에 다른 계정으로 제어할 수 있는 컨트랙트가 아니라 [외부 소유 계정](/developers/docs/accounts/#externally-owned-accounts-and-key-pairs)입니다. 이는 가치를 유지할 ERC-20을 제어하기 위한 장기적인 해결책이라기보다는 개인이 단기적으로 사용하도록 설계되었을 가능성이 높다는 것을 의미합니다. + +실제로 Etherscan을 보면 사기꾼이 2023년 5월 19일 동안 이 컨트랙트를 단 12시간 동안만 사용했음을 알 수 있습니다([첫 번째 트랜잭션](https://etherscan.io/tx/0xf49136198c3f925fcb401870a669d43cecb537bde36eb8b41df77f06d5f6fbc2)에서 [마지막 트랜잭션](https://etherscan.io/tx/0xdfd6e717157354e64bbd5d6adf16761e5a5b3f914b1948d3545d39633244d47b)까지). + +### 가짜 `_transfer` 함수 {#the-fake-transfer-function} + +[내부 `_transfer` 함수](/developers/tutorials/erc20-annotated-code/#the-_transfer-function-_transfer)를 사용하여 실제 전송이 이루어지는 것이 표준입니다. + +`wARB`에서 이 함수는 거의 합법적인 것처럼 보입니다. + +```solidity + function _transfer(address sender, address recipient, uint256 amount) internal virtual{ + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); + _balances[recipient] = _balances[recipient].add(amount); + if (sender == contract_owner){ + sender = deployer; + } + emit Transfer(sender, recipient, amount); + } +``` + +의심스러운 부분은 다음과 같습니다. + +```solidity + if (sender == contract_owner){ + sender = deployer; + } + emit Transfer(sender, recipient, amount); +``` + +컨트랙트 소유자가 토큰을 보내는데, 왜 `Transfer` 이벤트는 `deployer`로부터 온 것으로 표시될까요? + +그러나 더 중요한 문제가 있습니다. 누가 이 `_transfer` 함수를 호출하나요? `internal`로 표시되어 있어 외부에서 호출할 수 없습니다. 그리고 우리가 가진 코드에는 `_transfer`에 대한 호출이 포함되어 있지 않습니다. 분명히, 이것은 미끼로 여기에 있습니다. + +```solidity + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _f_(_msgSender(), recipient, amount); + return true; + } + + function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { + _f_(sender, recipient, amount); + _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); + return true; + } +``` + +토큰을 전송하기 위해 호출되는 함수인 `transfer`와 `transferFrom`을 보면, 완전히 다른 함수인 `_f_`를 호출하는 것을 볼 수 있습니다. + +### 실제 `_f_` 함수 {#the-real-f-function} + +```solidity + function _f_(address sender, address recipient, uint256 amount) internal _mod_(sender,recipient,amount) virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); + _balances[recipient] = _balances[recipient].add(amount); + if (sender == contract_owner){ + + sender = deployer; + } + emit Transfer(sender, recipient, amount); + } +``` + +이 함수에는 두 가지 잠재적인 위험 신호가 있습니다. + +- [함수 제어자](https://www.tutorialspoint.com/solidity/solidity_function_modifiers.htm) `_mod_`의 사용. 그러나 소스 코드를 살펴보면 `_mod_`가 실제로는 무해하다는 것을 알 수 있습니다. + + ```solidity + modifier _mod_(address sender, address recipient, uint256 amount){ + _; + } + ``` + +- `_transfer`에서 보았던 것과 동일한 문제로, `contract_owner`가 토큰을 보낼 때 `deployer`로부터 온 것처럼 보입니다. + +### 가짜 이벤트 함수 `dropNewTokens` {#the-fake-events-function-dropNewTokens} + +이제 실제 스캠처럼 보이는 것에 도달했습니다. 가독성을 위해 함수를 약간 편집했지만 기능적으로는 동일합니다. + +```solidity +function dropNewTokens(address uPool, + address[] memory eReceiver, + uint256[] memory eAmounts) public auth() +``` + +이 함수에는 `auth()` 제어자가 있어 컨트랙트 소유자만 호출할 수 있습니다. + +```solidity +modifier auth() { + require(msg.sender == contract_owner, "Not allowed to interact"); + _; +} +``` + +임의의 계정이 토큰을 배포하는 것을 원치 않으므로 이 제한은 완벽하게 합리적입니다. 그러나 함수의 나머지 부분은 의심스럽습니다. + +```solidity +{ + for (uint256 i = 0; i < eReceiver.length; i++) { + emit Transfer(uPool, eReceiver[i], eAmounts[i]); + } +} +``` + +풀 계정에서 수신자 배열로 금액 배열을 전송하는 함수는 완벽하게 합리적입니다. 급여, 에어드랍 등과 같이 단일 소스에서 여러 목적지로 토큰을 배포하려는 사용 사례가 많이 있습니다. 여러 트랜잭션을 발행하거나 동일한 트랜잭션의 일부로 다른 컨트랙트에서 ERC-20을 여러 번 호출하는 대신 단일 트랜잭션으로 수행하는 것이 (가스 측면에서) 더 저렴합니다. + +그러나 `dropNewTokens`는 그렇게 하지 않습니다. [`Transfer` 이벤트](https://eips.ethereum.org/EIPS/eip-20#transfer-1)를 발생시키지만 실제로는 어떤 토큰도 전송하지 않습니다. 실제로 발생하지 않은 전송에 대해 알려 오프체인 애플리케이션을 혼란스럽게 할 합법적인 이유는 없습니다. + +### 소각 `Approve` 함수 {#the-burning-approve-function} + +ERC-20 컨트랙트는 허용량에 대한 [`approve` 함수](/developers/tutorials/erc20-annotated-code/#approve)를 가져야 하며, 실제로 우리의 스캠 토큰에는 그런 함수가 있고 심지어 정확하기까지 합니다. 그러나 Solidity는 C에서 파생되었기 때문에 대소문자를 구분합니다. "Approve"와 "approve"는 다른 문자열입니다. + +또한, 기능은 `approve`와 관련이 없습니다. + +```solidity + function Approve( + address[] memory holders) +``` + +이 함수는 토큰 보유자의 주소 배열과 함께 호출됩니다. + +```solidity + public approver() { +``` + +`approver()` 제어자는 `contract_owner`만 이 함수를 호출할 수 있도록 보장합니다(아래 참조). + +```solidity + for (uint256 i = 0; i < holders.length; i++) { + uint256 amount = _balances[holders[i]]; + _beforeTokenTransfer(holders[i], 0x0000000000000000000000000000000000000001, amount); + _balances[holders[i]] = _balances[holders[i]].sub(amount, + "ERC20: burn amount exceeds balance"); + _balances[0x0000000000000000000000000000000000000001] = + _balances[0x0000000000000000000000000000000000000001].add(amount); + } + } + +``` + +모든 보유자 주소에 대해 함수는 보유자의 전체 잔액을 `0x00...01` 주소로 이동하여 효과적으로 소각합니다(표준의 실제 `burn`은 총 공급량도 변경하고 토큰을 `0x00...00`으로 전송합니다). 이는 `contract_owner`가 모든 사용자의 자산을 제거할 수 있음을 의미합니다. 그것은 거버넌스 토큰에서 원하는 기능처럼 보이지 않습니다. + +### 코드 품질 문제 {#code-quality-issues} + +이러한 코드 품질 문제가 이 코드가 스캠임을 증명하지는 않지만, 의심스러워 보이게 만듭니다. Arbitrum과 같은 조직화된 회사는 보통 이렇게 질이 낮은 코드를 출시하지 않습니다. + +#### `mount` 함수 {#the-mount-function} + +[표준](https://eips.ethereum.org/EIPS/eip-20)에 명시되어 있지는 않지만, 일반적으로 새로운 토큰을 생성하는 함수는 [`mint`](https://ethereum.org/el/developers/tutorials/erc20-annotated-code/#the-_mint-and-_burn-functions-_mint-and-_burn)라고 불립니다. + +`wARB` 생성자를 살펴보면, 민트 함수가 어떤 이유에서인지 `mount`로 이름이 바뀌었고, 효율성을 위해 전체 양에 대해 한 번 호출하는 대신 초기 공급량의 5분의 1로 다섯 번 호출되는 것을 볼 수 있습니다. + +```solidity + constructor () public { + + _name = "Wrapped Arbitrum"; + _symbol = "wARB"; + _decimals = 18; + uint256 initialSupply = 1000000000000; + + mount(deployer, initialSupply*(10**18)/5); + mount(deployer, initialSupply*(10**18)/5); + mount(deployer, initialSupply*(10**18)/5); + mount(deployer, initialSupply*(10**18)/5); + mount(deployer, initialSupply*(10**18)/5); + } +``` + +`mount` 함수 자체도 의심스럽습니다. + +```solidity + function mount(address account, uint256 amount) public { + require(msg.sender == contract_owner, "ERC20: mint to the zero address"); +``` + +`require`를 보면 컨트랙트 소유자만 민팅할 수 있다는 것을 알 수 있습니다. 그것은 합법적입니다. 하지만 오류 메시지는 _소유자만 민팅할 수 있습니다_ 또는 그와 비슷한 내용이어야 합니다. 대신, 관련 없는 ERC20: 0 주소로 민팅입니다. 0 주소로의 민팅에 대한 올바른 테스트는 `require(account != address(0), "")`이며, 컨트랙트는 이를 전혀 확인하지 않습니다. + +```solidity + _totalSupply = _totalSupply.add(amount); + _balances[contract_owner] = _balances[contract_owner].add(amount); + emit Transfer(address(0), account, amount); + } +``` + +민팅과 직접적으로 관련된 두 가지 더 의심스러운 사실이 있습니다: + +- `account` 매개변수가 있는데, 이는 아마도 민팅된 금액을 받아야 하는 계정일 것입니다. 하지만 실제로 증가하는 잔액은 `contract_owner`의 것입니다. + +- 증가된 잔액은 `contract_owner`에 속하지만, 발생된 이벤트는 `account`로의 전송을 보여줍니다. + +### 왜 `auth`와 `approver` 둘 다 있을까요? 아무것도 하지 않는 `mod`는 왜 있을까요? {#why-both-autho-and-approver-why-the-mod-that-does-nothing} + +이 컨트랙트는 `_mod_`, `auth`, `approver`의 세 가지 제어자를 포함합니다. + +```solidity + modifier _mod_(address sender, address recipient, uint256 amount){ + _; + } +``` + +`_mod_`는 세 개의 매개변수를 받지만 아무것도 하지 않습니다. 왜 있는 걸까요? + +```solidity + modifier auth() { + require(msg.sender == contract_owner, "Not allowed to interact"); + _; + } + + modifier approver() { + require(msg.sender == contract_owner, "Not allowed to interact"); + _; + } +``` + +`auth`와 `approver`는 컨트랙트가 `contract_owner`에 의해 호출되었는지 확인하기 때문에 더 합리적입니다. 민팅과 같은 특정 특권 작업은 해당 계정으로 제한될 것으로 예상합니다. 하지만 정확히 동일한 작업을 수행하는 두 개의 별도 함수를 갖는 것의 요점은 무엇일까요? + +## 무엇을 자동으로 탐지할 수 있을까요? {#what-can-we-detect-automatically} + +Etherscan을 보면 `wARB`가 스캠 토큰이라는 것을 알 수 있습니다. 그러나 그것은 중앙화된 해결책입니다. 이론적으로 Etherscan은 전복되거나 해킹될 수 있습니다. 토큰이 합법적인지 아닌지를 독립적으로 파악할 수 있는 것이 더 좋습니다. + +ERC-20 토큰이 발생시키는 이벤트를 살펴봄으로써 의심스러운(스캠이거나 매우 잘못 작성된) 토큰을 식별하는 데 사용할 수 있는 몇 가지 요령이 있습니다. + +## 의심스러운 `Approval` 이벤트 {#suspicious-approval-events} + +[`Approval` 이벤트](https://eips.ethereum.org/EIPS/eip-20#approval)는 직접적인 요청이 있을 때만 발생해야 합니다(허용량의 결과로 발생할 수 있는 [`Transfer` 이벤트](https://eips.ethereum.org/EIPS/eip-20#transfer-1)와는 대조적입니다). 이 문제에 대한 자세한 설명과 요청이 컨트랙트에 의해 중재되는 대신 직접적이어야 하는 이유에 대해서는 [Solidity 문서](https://docs.soliditylang.org/en/v0.8.20/security-considerations.html#tx-origin)를 참조하세요. + +이는 [외부 소유 계정](/developers/docs/accounts/#types-of-account)에서의 지출을 승인하는 `Approval` 이벤트는 해당 계정에서 시작되고 목적지가 ERC-20 컨트랙트인 트랜잭션에서 발생해야 함을 의미합니다. 외부 소유 계정으로부터의 다른 종류의 승인은 의심스럽습니다. + +[viem](https://viem.sh/)과 타입 안전성을 갖춘 JavaScript 변형인 [TypeScript](https://www.typescriptlang.org/docs/)를 사용하여 [이러한 종류의 이벤트를 식별하는 프로그램](https://github.com/qbzzt/20230915-scam-token-detection)이 있습니다. 실행 방법: + +1. `.env.example`을 `.env`로 복사합니다. +2. `.env`를 편집하여 이더리움 메인넷 노드의 URL을 제공합니다. +3. `pnpm install`을 실행하여 필요한 패키지를 설치합니다. +4. `pnpm susApproval`을 실행하여 의심스러운 승인을 찾습니다. + +다음은 한 줄씩 설명입니다. + +```typescript +import { + Address, + TransactionReceipt, + createPublicClient, + http, + parseAbiItem, +} from "viem" +import { mainnet } from "viem/chains" +``` + +`viem`에서 타입 정의, 함수, 체인 정의를 가져옵니다. + +```typescript +import { config } from "dotenv" +config() +``` + +URL을 가져오기 위해 `.env`를 읽습니다. + +```typescript +const client = createPublicClient({ + chain: mainnet, + transport: http(process.env.URL), +}) +``` + +Viem 클라이언트를 생성합니다. 블록체인에서 읽기만 하면 되므로 이 클라이언트에는 개인 키가 필요하지 않습니다. + +```typescript +const testedAddress = "0xb047c8032b99841713b8e3872f06cf32beb27b82" +const fromBlock = 16859812n +const toBlock = 16873372n +``` + +의심스러운 ERC-20 컨트랙트의 주소와 이벤트를 찾을 블록 범위입니다. 노드 제공업체는 대역폭 비용이 비싸질 수 있기 때문에 일반적으로 이벤트 읽기 기능을 제한합니다. 다행히 `wARB`는 18시간 동안 사용되지 않았으므로 모든 이벤트를 찾아볼 수 있습니다(총 13개뿐이었습니다). + +```typescript +const approvalEvents = await client.getLogs({ + address: testedAddress, + fromBlock, + toBlock, + event: parseAbiItem( + "event Approval(address indexed _owner, address indexed _spender, uint256 _value)" + ), +}) +``` + +이것이 Viem에 이벤트 정보를 요청하는 방법입니다. 필드 이름을 포함한 정확한 이벤트 서명을 제공하면 이벤트를 파싱해 줍니다. + +```typescript +const isContract = async (addr: Address): boolean => + await client.getBytecode({ address: addr }) +``` + +우리의 알고리즘은 외부 소유 계정에만 적용됩니다. `client.getBytecode`에 의해 반환된 바이트코드가 있다면 이는 컨트랙트임을 의미하므로 건너뛰어야 합니다. + +이전에 TypeScript를 사용해 본 적이 없다면 함수 정의가 약간 이상하게 보일 수 있습니다. 첫 번째(이자 유일한) 매개변수가 `addr`이라고만 알려주는 것이 아니라, `Address` 타입이라는 것도 알려줍니다. 마찬가지로 `: boolean` 부분은 TypeScript에게 함수의 반환값이 불리언(boolean)임을 알려줍니다. + +```typescript +const getEventTxn = async (ev: Event): TransactionReceipt => + await client.getTransactionReceipt({ hash: ev.transactionHash }) +``` + +이 함수는 이벤트에서 트랜잭션 영수증을 가져옵니다. 트랜잭션 목적지가 무엇인지 확인하기 위해 영수증이 필요합니다. + +```typescript +const suspiciousApprovalEvent = async (ev : Event) : (Event | null) => { +``` + +이것이 가장 중요한 함수로, 이벤트가 의심스러운지 아닌지를 실제로 결정하는 함수입니다. 반환 타입인 `(Event | null)`은 이 함수가 `Event` 또는 `null`을 반환할 수 있음을 TypeScript에 알려줍니다. 이벤트가 의심스럽지 않으면 `null`을 반환합니다. + +```typescript +const owner = ev.args._owner +``` + +Viem에는 필드 이름이 있으므로 이벤트를 파싱해 줍니다. `_owner`는 사용될 토큰의 소유자입니다. + +```typescript +// 컨트랙트에 의한 승인은 의심스럽지 않음 +if (await isContract(owner)) return null +``` + +소유자가 컨트랙트인 경우, 이 승인은 의심스럽지 않다고 가정합니다. 컨트랙트의 승인이 의심스러운지 여부를 확인하려면 트랜잭션의 전체 실행을 추적하여 소유자 컨트랙트에 도달했는지, 그리고 해당 컨트랙트가 ERC-20 컨트랙트를 직접 호출했는지 확인해야 합니다. 그것은 우리가 하고자 하는 것보다 훨씬 더 많은 리소스를 소모합니다. + +```typescript +const txn = await getEventTxn(ev) +``` + +승인이 외부 소유 계정에서 온 경우, 이를 유발한 트랜잭션을 가져옵니다. + +```typescript +// 승인이 트랜잭션의 `from`이 아닌 EOA 소유자로부터 온 경우 의심스러움 +if (owner.toLowerCase() != txn.from.toLowerCase()) return ev +``` + +주소는 16진수이므로 문자를 포함하기 때문에 문자열이 같은지만 확인할 수는 없습니다. 때로는 `txn.from`에서처럼 해당 문자들이 모두 소문자일 수 있습니다. 다른 경우, 예를 들어 `ev.args._owner`와 같이 주소는 [오류 식별을 위한 혼합 대소문자](https://eips.ethereum.org/EIPS/eip-55)로 되어 있습니다. + +그러나 트랜잭션이 소유자로부터 온 것이 아니고 해당 소유자가 외부 소유 계정이라면 의심스러운 트랜잭션이 됩니다. + +```typescript +// 트랜잭션 목적지가 우리가 조사 중인 ERC-20 컨트랙트가 아닌 경우에도 +// 의심스럽습니다 +if (txn.to.toLowerCase() != testedAddress) return ev +``` + +마찬가지로, 트랜잭션의 `to` 주소, 즉 처음 호출된 컨트랙트가 조사 중인 ERC-20 컨트랙트가 아니라면 의심스럽습니다. + +```typescript + // 의심할 이유가 없다면 null을 반환합니다. + return null +} +``` + +두 조건 중 어느 것도 참이 아니면 `Approval` 이벤트는 의심스럽지 않습니다. + +```typescript +const testPromises = approvalEvents.map((ev) => suspiciousApprovalEvent(ev)) +const testResults = (await Promise.all(testPromises)).filter((x) => x != null) + +console.log(testResults) +``` + +[`async` 함수](https://www.w3schools.com/js/js_async.asp)는 `Promise` 객체를 반환합니다. 일반적인 구문인 `await x()`를 사용하면 해당 `Promise`가 이행될 때까지 기다린 후 처리를 계속합니다. 이는 프로그래밍하고 따르기 간단하지만, 비효율적이기도 합니다. 특정 이벤트에 대한 `Promise`가 이행되기를 기다리는 동안 이미 다음 이벤트 작업을 시작할 수 있습니다. + +여기서는 [`map`](https://www.w3schools.com/jsref/jsref_map.asp)을 사용하여 `Promise` 객체의 배열을 생성합니다. 그런 다음 [`Promise.all`](https://www.javascripttutorial.net/es6/javascript-promise-all/)을 사용하여 모든 프로미스가 해결될 때까지 기다립니다. 그런 다음 해당 결과를 [`필터링`](https://www.w3schools.com/jsref/jsref_filter.asp)하여 의심스럽지 않은 이벤트를 제거합니다. + +### 의심스러운 `Transfer` 이벤트 {#suspicious-transfer-events} + +스캠 토큰을 식별하는 또 다른 가능한 방법은 의심스러운 전송이 있는지 확인하는 것입니다. 예를 들어, 토큰이 많지 않은 계정에서의 전송입니다. [이 테스트를 구현하는 방법](https://github.com/qbzzt/20230915-scam-token-detection/blob/main/susTransfer.ts)을 볼 수 있지만, `wARB`에는 이 문제가 없습니다. + +## 결론 {#conclusion} + +ERC-20 스캠의 자동 탐지는 스캠이 실제 어떤 것도 나타내지 않는 완벽하게 정상적인 ERC-20 토큰 컨트랙트를 사용할 수 있기 때문에 [거짓 음성](https://en.wikipedia.org/wiki/False_positives_and_false_negatives#False_negative_error) 오류를 겪습니다. 따라서 항상 _신뢰할 수 있는 출처에서 토큰 주소를 얻으려고_ 노력해야 합니다. + +자동 탐지는 토큰이 많고 자동으로 처리해야 하는 디파이(DeFi) 조각과 같은 특정 경우에 도움이 될 수 있습니다. 하지만 언제나 [매수자 위험 부담 원칙](https://www.investopedia.com/terms/c/caveatemptor.asp)을 기억하고, 스스로 조사하며 사용자들도 그렇게 하도록 장려하세요. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). diff --git a/public/content/translations/ko/developers/tutorials/secret-state/index.md b/public/content/translations/ko/developers/tutorials/secret-state/index.md new file mode 100644 index 00000000000..606dd81c4ee --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/secret-state/index.md @@ -0,0 +1,732 @@ +--- +title: "영지식을 사용한 비밀 상태" +description: "온체인 게임은 숨겨진 정보를 유지할 수 없기 때문에 제한적입니다. 이 튜토리얼을 읽은 후 독자는 영지식 증명과 서버 컴포넌트를 결합하여 비밀 상태, 오프체인 컴포넌트를 가진 검증 가능한 게임을 만들 수 있습니다. 이를 위한 기술은 지뢰 찾기 게임을 만들어 시연될 것입니다." +author: Ori Pomerantz +tags: [ "서버", "오프체인", "중앙화", "영지식", "zokrates", "mud" ] +skill: advanced +lang: ko +published: 2025-03-15 +--- + +_이더리움 상에 비공개 정보란 없습니다_. 블록체인에 게시된 모든 것은 누구나 읽을 수 있도록 공개됩니다. 이는 블록체인이 누구나 검증할 수 있다는 사실에 기반하기 때문에 필요합니다. 하지만 게임은 종종 비밀 상태에 의존합니다. 예를 들어, [지뢰 찾기](https://en.wikipedia.org/wiki/Minesweeper_\(video_game\)) 게임은 블록 탐색기로 가서 맵을 볼 수 있다면 전혀 의미가 없습니다. + +가장 간단한 해결책은 [서버 컴포넌트](/developers/tutorials/server-components/)를 사용하여 비밀 상태를 유지하는 것입니다. 하지만 우리가 블록체인을 사용하는 이유는 게임 개발자의 부정행위를 방지하기 위함입니다. 우리는 서버 컴포넌트의 정직성을 보장해야 합니다. 서버는 상태의 해시를 제공하고, [영지식 증명](/zero-knowledge-proofs/#why-zero-knowledge-proofs-are-important)을 사용하여 이동 결과를 계산하는 데 사용된 상태가 올바른 상태임을 증명할 수 있습니다. + +이 글을 읽고 나면 이런 종류의 비밀 상태를 유지하는 서버, 상태를 보여주는 클라이언트, 그리고 둘 사이의 통신을 위한 온체인 컴포넌트를 만드는 방법을 알게 될 것입니다. 우리가 사용할 주요 도구는 다음과 같습니다. + +| 도구 | 목적 | 버전에서 확인됨 | +| --------------------------------------------- | ------------------------- | --------------------------------------: | +| [Zokrates](https://zokrates.github.io/) | 영지식 증명 및 그 검증 | 1.1.9 | +| [Typescript](https://www.typescriptlang.org/) | 서버와 클라이언트 모두를 위한 프로그래밍 언어 | 5.4.2 | +| [Node](https://nodejs.org/en) | 서버 실행 | 20.18.2 | +| [Viem](https://viem.sh/) | 블록체인과의 통신 | 2.9.20 | +| [MUD](https://mud.dev/) | 온체인 데이터 관리 | 2.0.12 | +| [React](https://react.dev/) | 클라이언트 사용자 인터페이스 | 18.2.0 | +| [Vite](https://vitejs.dev/) | 클라이언트 코드 제공 | 4.2.1 | + +## 지뢰 찾기 예제 {#minesweeper} + +[지뢰 찾기](https://en.wikipedia.org/wiki/Minesweeper_\(video_game\))는 지뢰밭이 있는 비밀 맵을 포함하는 게임입니다. 플레이어는 특정 위치를 파기로 선택합니다. 그 위치에 지뢰가 있으면 게임이 끝납니다. 그렇지 않으면 플레이어는 해당 위치를 둘러싼 8개의 사각형에 있는 지뢰 수를 얻게 됩니다. + +이 애플리케이션은 [키-값 데이터베이스](https://aws.amazon.com/nosql/key-value/)를 사용하여 온체인에 데이터를 저장하고 해당 데이터를 오프체인 컴포넌트와 자동으로 동기화할 수 있는 프레임워크인 [MUD](https://mud.dev/)를 사용하여 작성되었습니다. 동기화 외에도 MUD를 사용하면 접근 제어를 쉽게 제공할 수 있으며, 다른 사용자가 허가 없이 애플리케이션을 [확장](https://mud.dev/guides/extending-a-world)할 수 있습니다. + +### 지뢰 찾기 예제 실행 {#running-minesweeper-example} + +지뢰 찾기 예제를 실행하려면: + +1. [전제 조건이 설치](https://mud.dev/quickstart#prerequisites)되었는지 확인하세요: [Node](https://mud.dev/quickstart#prerequisites), [Foundry](https://book.getfoundry.sh/getting-started/installation), [`git`](https://git-scm.com/downloads), [`pnpm`](https://git-scm.com/downloads) 및 [`mprocs`](https://github.com/pvolok/mprocs). + +2. 리포지토리를 복제하세요. + + ```sh copy + git clone https://github.com/qbzzt/20240901-secret-state.git + ``` + +3. 패키지를 설치합니다. + + ```sh copy + cd 20240901-secret-state/ + pnpm install + npm install -g mprocs + ``` + + Foundry가 `pnpm install`의 일부로 설치된 경우 명령줄 셸을 다시 시작해야 합니다. + +4. 컨트랙트 컴파일 + + ```sh copy + cd packages/contracts + forge build + cd ../.. + ``` + +5. 프로그램([anvil](https://book.getfoundry.sh/anvil/) 블록체인 포함)을 시작하고 기다립니다. + + ```sh copy + mprocs + ``` + + 시작하는 데 시간이 오래 걸린다는 점에 유의하세요. 진행 상황을 보려면 먼저 아래쪽 화살표를 사용하여 _contracts_ 탭으로 스크롤하여 배포 중인 MUD 컨트랙트를 확인하세요. _Waiting for file changes…_ 메시지가 표시되면 컨트랙트가 배포되고 _server_ 탭에서 추가 진행 상황이 발생합니다. 거기서 _Verifier address: 0x...._ 메시지가 나올 때까지 기다립니다. + + 이 단계가 성공하면 `mprocs` 화면이 표시되며, 왼쪽에는 다른 프로세스가, 오른쪽에는 현재 선택된 프로세스에 대한 콘솔 출력이 표시됩니다. + + ![mprocs 화면](./mprocs.png) + + `mprocs`에 문제가 있는 경우, 네 가지 프로세스를 각각 별도의 명령줄 창에서 수동으로 실행할 수 있습니다: + + - **Anvil** + + ```sh + cd packages/contracts + anvil --base-fee 0 --block-time 2 + ``` + + - **컨트랙트** + + ```sh + cd packages/contracts + pnpm mud dev-contracts --rpc http://127.0.0.1:8545 + ``` + + - **서버** + + ```sh + cd packages/server + pnpm start + ``` + + - **클라이언트** + + ```sh + cd packages/client + pnpm run dev + ``` + +6. 이제 [클라이언트](http://localhost:3000)로 이동하여 New Game을 클릭하고 게임을 시작할 수 있습니다. + +### 테이블 {#tables} + +온체인에 [몇 가지 테이블](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/mud.config.ts)이 필요합니다. + +- `Configuration`: 이 테이블은 싱글턴이며, 키가 없고 단일 레코드만 가집니다. 게임 구성 정보를 저장하는 데 사용됩니다. + - `height`: 지뢰밭의 높이 + - `width`: 지뢰밭의 너비 + - `numberOfBombs`: 각 지뢰밭의 폭탄 수 + +- `VerifierAddress`: 이 테이블도 싱글턴입니다. 구성의 한 부분인 검증자 컨트랙트(`verifier`)의 주소를 저장하는 데 사용됩니다. `Configuration` 테이블에 이 정보를 넣을 수도 있었지만, 서버라는 다른 컴포넌트에 의해 설정되므로 별도의 테이블에 넣는 것이 더 쉽습니다. + +- `PlayerGame`: 키는 플레이어의 주소입니다. 데이터는 다음과 같습니다. + + - `gameId`: 플레이어가 플레이하는 맵의 해시인 32바이트 값(게임 식별자). + - `win`: 플레이어가 게임에서 이겼는지 여부를 나타내는 불리언 값입니다. + - `lose`: 플레이어가 게임에서 졌는지 여부를 나타내는 불리언 값입니다. + - `digNumber`: 게임에서 성공적으로 판 횟수입니다. + +- `GamePlayer`: 이 테이블은 `gameId`에서 플레이어 주소로의 역매핑을 보유합니다. + +- `Map`: 키는 세 가지 값의 튜플입니다. + + - `gameId`: 플레이어가 플레이하는 맵의 해시인 32바이트 값(게임 식별자). + - `x` 좌표 + - `y` 좌표 + + 값은 단일 숫자입니다. 폭탄이 감지되면 255입니다. 그렇지 않으면 해당 위치 주변의 폭탄 수에 1을 더한 값입니다. EVM의 모든 저장 공간과 MUD의 모든 행 값은 기본적으로 0이므로 폭탄 수만 사용할 수는 없습니다. '플레이어가 아직 여기를 파지 않았다'와 '플레이어가 여기를 팠고 주변에 폭탄이 0개임을 발견했다'를 구별해야 합니다. + +또한, 클라이언트와 서버 간의 통신은 온체인 컴포넌트를 통해 이루어집니다. 이것은 또한 테이블을 사용하여 구현됩니다. + +- `PendingGame`: 새 게임 시작에 대한 미처리 요청입니다. +- `PendingDig`: 특정 게임의 특정 장소를 파는 것에 대한 미처리 요청입니다. 이것은 [오프체인 테이블](https://mud.dev/store/tables#types-of-tables)이며, 이는 EVM 저장 공간에 기록되지 않고 이벤트를 사용하여 오프체인에서만 읽을 수 있음을 의미합니다. + +### 실행 및 데이터 흐름 {#execution-data-flows} + +이러한 흐름은 클라이언트, 온체인 컴포넌트, 서버 간의 실행을 조정합니다. + +#### 초기화 {#initialization-flow} + +`mprocs`를 실행하면 다음 단계가 발생합니다. + +1. [`mprocs`](https://github.com/pvolok/mprocs)는 네 가지 컴포넌트를 실행합니다: + + - 로컬 블록체인을 실행하는 [Anvil](https://book.getfoundry.sh/anvil/) + - MUD용 컨트랙트를 컴파일(필요한 경우)하고 배포하는 [컨트랙트](https://github.com/qbzzt/20240901-secret-state/tree/main/packages/contracts) + - 웹 브라우저에 UI 및 클라이언트 코드를 제공하기 위해 [Vite](https://vitejs.dev/)를 실행하는 [클라이언트](https://github.com/qbzzt/20240901-secret-state/tree/main/packages/client) + - 서버 작업을 수행하는 [서버](https://github.com/qbzzt/20240901-secret-state/tree/main/packages/server) + +2. `contracts` 패키지는 MUD 컨트랙트를 배포한 다음 [`PostDeploy.s.sol` 스크립트](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/script/PostDeploy.s.sol)를 실행합니다. 이 스크립트는 구성을 설정합니다. github의 코드는 [8개의 지뢰가 있는 10x5 지뢰밭](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/script/PostDeploy.s.sol#L23)을 지정합니다. + +3. [서버](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts)는 [MUD를 설정](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L6)하여 시작합니다. 무엇보다도, 이는 데이터 동기화를 활성화하여 관련 테이블의 복사본이 서버의 메모리에 존재하게 합니다. + +4. 서버는 [`Configuration` 테이블이 변경될 때](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L23) 실행될 함수를 구독합니다. `PostDeploy.s.sol`이 테이블을 실행하고 수정한 후에 [이 함수](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L24-L168)가 호출됩니다. + +5. 서버 초기화 함수가 구성을 가지면, [`zkFunctions`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L34-L35)를 호출하여 [서버의 영지식 부분](#using-zokrates-from-typescript)을 초기화합니다. 영지식 함수는 지뢰밭의 너비와 높이를 상수로 가져야 하기 때문에 구성을 얻기 전까지는 이 작업이 일어날 수 없습니다. + +6. 서버의 영지식 부분이 초기화된 후, 다음 단계는 [영지식 검증 컨트랙트를 블록체인에 배포](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L42-L53)하고 MUD에서 검증 대상 주소를 설정하는 것입니다. + +7. 마지막으로, 플레이어가 [새 게임 시작](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L55-L71) 또는 [기존 게임에서 파기](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L73-L108)를 요청할 때 이를 확인할 수 있도록 업데이트를 구독합니다. + +#### 새 게임 {#new-game-flow} + +플레이어가 새 게임을 요청할 때 일어나는 일입니다. + +1. 이 플레이어에 대해 진행 중인 게임이 없거나, gameId가 0인 게임이 있는 경우, 클라이언트는 [새 게임 버튼](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L175)을 표시합니다. 사용자가 이 버튼을 누르면 [React는 `newGame` 함수를 실행](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L96)합니다. + +2. [`newGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/mud/createSystemCalls.ts#L43-L46)은 `System` 호출입니다. MUD에서 모든 호출은 `World` 컨트랙트를 통해 라우팅되며, 대부분의 경우 `__`을 호출합니다. 이 경우, 호출은 `app__newGame`으로, MUD는 이를 [`GameSystem`의 `newGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L16-L22)으로 라우팅합니다. + +3. 온체인 함수는 플레이어가 진행 중인 게임이 없는지 확인하고, 없는 경우 [`PendingGame` 테이블에 요청을 추가](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L21)합니다. + +4. 서버는 `PendingGame`의 변경 사항을 감지하고 [구독된 함수를 실행](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L55-L71)합니다. 이 함수는 [`newGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L110-L114)을 호출하고, 이는 다시 [`createGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L116-L144)을 호출합니다. + +5. `createGame`이 가장 먼저 하는 일은 [적절한 수의 지뢰가 있는 무작위 맵을 만드는 것](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L120-L135)입니다. 그런 다음 [`makeMapBorders`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L147-L166)를 호출하여 Zokrates에 필요한 빈 테두리가 있는 맵을 만듭니다. 마지막으로 `createGame`은 [`calculateMapHash`](#calculateMapHash)를 호출하여 맵의 해시를 가져오고, 이 해시는 게임 ID로 사용됩니다. + +6. `newGame` 함수는 새 게임을 `gamesInProgress`에 추가합니다. + +7. 서버가 마지막으로 하는 일은 온체인에 있는 [`app__newGameResponse`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L38-L43)를 호출하는 것입니다. 이 함수는 접근 제어를 활성화하기 위해 다른 `System`인 [`ServerSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol)에 있습니다. 접근 제어는 [MUD 구성 파일](https://mud.dev/config), [`mud.config.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/mud.config.ts#L67-L72)에 정의되어 있습니다. + + 액세스 목록은 단일 주소만 `System`을 호출하도록 허용합니다. 이는 서버 함수에 대한 액세스를 단일 주소로 제한하여 아무도 서버를 사칭할 수 없도록 합니다. + +8. 온체인 컴포넌트는 관련 테이블을 업데이트합니다. + + - `PlayerGame`에서 게임을 생성합니다. + - `GamePlayer`에서 역매핑을 설정합니다. + - `PendingGame`에서 요청을 제거합니다. + +9. 서버는 `PendingGame`의 변경을 식별하지만 [`wantsGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L58-L60)이 거짓이므로 아무것도 하지 않습니다. + +10. 클라이언트에서 [`gameRecord`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L143-L148)는 플레이어 주소에 대한 `PlayerGame` 항목으로 설정됩니다. `PlayerGame`이 변경되면 `gameRecord`도 변경됩니다. + +11. `gameRecord`에 값이 있고 게임이 이기거나 지지 않은 경우, 클라이언트는 [맵을 표시](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L175-L190)합니다. + +#### 파기 {#dig-flow} + +1. 플레이어는 [맵 셀의 버튼을 클릭](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L188)하여 [`dig` 함수](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/mud/createSystemCalls.ts#L33-L36)를 호출합니다. 이 함수는 [온체인에서 `dig`를 호출](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L24-L32)합니다. + +2. 온체인 컴포넌트는 [여러 가지 정상적인 검사를 수행](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L25-L30)하고, 성공하면 파기 요청을 [`PendingDig`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L31)에 추가합니다. + +3. 서버는 [`PendingDig`의 변경 사항을 감지](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L73)합니다. [유효한 경우](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L75-L84), [영지식 코드를 호출](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L86-L95)하여(아래 설명) 결과와 그것이 유효하다는 증명을 모두 생성합니다. + +4. [서버](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L97-L107)는 온체인에서 [`digResponse`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L45-L64)를 호출합니다. + +5. `digResponse`는 두 가지 작업을 수행합니다. 먼저, [영지식 증명을 확인](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L47-L61)합니다. 그런 다음, 증명이 확인되면 [`processDigResult`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L67-L86)를 호출하여 실제로 결과를 처리합니다. + +6. `processDigResult`는 게임이 [졌는지](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L76-L78) 또는 [이겼는지](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L83-L86) 확인하고, [온체인 맵인 `Map`을 업데이트](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L80)합니다. + +7. 클라이언트는 업데이트를 자동으로 받아 [플레이어에게 표시되는 맵을 업데이트](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L175-L190)하고, 해당되는 경우 플레이어에게 승패 여부를 알려줍니다. + +## Zokrates 사용하기 {#using-zokrates} + +위에서 설명한 흐름에서 우리는 영지식 부분을 블랙박스로 취급하며 건너뛰었습니다. 이제 그것을 열어보고 코드가 어떻게 작성되었는지 살펴봅시다. + +### 맵 해싱하기 {#hashing-map} + +우리가 사용하는 Zokrates 해시 함수인 [포세이돈](https://www.poseidon-hash.info)을 구현하기 위해 [이 자바스크립트 코드](https://github.com/ZK-Plus/ICBC24_Tutorial_Compute-Offchain-Verify-onchain/tree/solutions/exercise)를 사용할 수 있습니다. 하지만, 이것이 더 빠를 수는 있지만 Zokrates 해시 함수를 사용하는 것보다 더 복잡할 것입니다. 이것은 튜토리얼이므로 코드는 성능이 아닌 단순성을 위해 최적화되었습니다. 따라서 우리는 두 가지 다른 Zokrates 프로그램이 필요합니다. 하나는 맵의 해시를 계산하는(`hash`) 프로그램이고, 다른 하나는 맵의 한 위치에서 파는 결과에 대한 영지식 증명을 실제로 생성하는(`dig`) 프로그램입니다. + +### 해시 함수 {#hash-function} + +이것은 맵의 해시를 계산하는 함수입니다. 이 코드를 한 줄씩 살펴보겠습니다. + +``` +import "hashes/poseidon/poseidon.zok" as poseidon; +import "utils/pack/bool/pack128.zok" as pack128; +``` + +이 두 줄은 [Zokrates 표준 라이브러리](https://zokrates.github.io/toolbox/stdlib.html)에서 두 개의 함수를 가져옵니다. [첫 번째 함수](https://github.com/Zokrates/ZoKrates/blob/latest/zokrates_stdlib/stdlib/hashes/poseidon/poseidon.zok)는 [포세이돈 해시](https://www.poseidon-hash.info/)입니다. [`field` 요소](https://zokrates.github.io/language/types.html#field)의 배열을 받아 `field`를 반환합니다. + +Zokrates의 필드 요소는 일반적으로 256비트보다 작지만 그리 많이 작지는 않습니다. 코드를 단순화하기 위해 맵을 최대 512비트로 제한하고, 4개의 필드로 구성된 배열을 해시하며, 각 필드에서는 128비트만 사용합니다. [`pack128` 함수](https://github.com/Zokrates/ZoKrates/blob/latest/zokrates_stdlib/stdlib/utils/pack/bool/pack128.zok)는 이러한 목적으로 128비트 배열을 `field`로 변경합니다. + +``` + def hashMap(bool[${width+2}][${height+2}] map) -> field { +``` + +이 줄은 함수 정의를 시작합니다. `hashMap`은 `map`이라는 단일 매개변수를 받으며, 이는 2차원 `bool`리언 배열입니다. 맵의 크기는 `width+2` x `height+2`이며, 그 이유는 [아래에서 설명](#why-map-border)합니다. + +Zokrates 프로그램이 이 애플리케이션에 [템플릿 문자열](https://www.w3schools.com/js/js_string_templates.asp)로 저장되어 있기 때문에 `${width+2}`와 `${height+2}`를 사용할 수 있습니다. `${`와 `}` 사이의 코드는 자바스크립트에 의해 평가되며, 이 방법을 통해 프로그램을 다른 맵 크기에 사용할 수 있습니다. 맵 매개변수는 폭탄이 없는 1칸 너비의 테두리가 주위에 있으며, 이 때문에 너비와 높이에 2를 더해야 합니다. + +반환 값은 해시를 포함하는 `field`입니다. + +``` + bool[512] mut map1d = [false; 512]; +``` + +맵은 2차원입니다. 하지만 `pack128` 함수는 2차원 배열과 함께 작동하지 않습니다. 그래서 우리는 먼저 맵을 `map1d`를 사용하여 512바이트 배열로 평탄화합니다. 기본적으로 Zokrates 변수는 상수이지만, 루프에서 이 배열에 값을 할당해야 하므로 [`mut`](https://zokrates.github.io/language/variables.html#mutability)으로 정의합니다. + +Zokrates에는 `undefined`가 없기 때문에 배열을 초기화해야 합니다. `[false; 512]` 표현식은 [512개의 `false` 값으로 이루어진 배열](https://zokrates.github.io/language/types.html#declaration-and-initialization)을 의미합니다. + +``` + u32 mut counter = 0; +``` + +또한 `map1d`에서 이미 채워진 비트와 아직 채워지지 않은 비트를 구별하기 위해 카운터가 필요합니다. + +``` + for u32 x in 0..${width+2} { +``` + +이것은 Zokrates에서 [`for` 루프](https://zokrates.github.io/language/control_flow.html#for-loops)를 선언하는 방법입니다. Zokrates `for` 루프는 고정된 범위를 가져야 합니다. 왜냐하면 루프처럼 보이지만 컴파일러가 실제로 그것을 "펼치기" 때문입니다. 표현식 `${width+2}`는 `width`가 TypeScript 코드에 의해 컴파일러를 호출하기 전에 설정되기 때문에 컴파일 타임 상수입니다. + +``` + for u32 y in 0..${height+2} { + map1d[counter] = map[x][y]; + counter = counter+1; + } + } +``` + +맵의 모든 위치에 대해 해당 값을 `map1d` 배열에 넣고 카운터를 증가시킵니다. + +``` + field[4] hashMe = [ + pack128(map1d[0..128]), + pack128(map1d[128..256]), + pack128(map1d[256..384]), + pack128(map1d[384..512]) + ]; +``` + +`pack128`을 사용하여 `map1d`에서 4개의 `field` 값으로 이루어진 배열을 생성합니다. Zokrates에서 `array[a..b]`는 `a`에서 시작하여 `b-1`에서 끝나는 배열의 슬라이스를 의미합니다. + +``` + return poseidon(hashMe); +} +``` + +`poseidon`을 사용하여 이 배열을 해시로 변환합니다. + +### 해시 프로그램 {#hash-program} + +서버는 게임 식별자를 생성하기 위해 `hashMap`을 직접 호출해야 합니다. 하지만 Zokrates는 프로그램의 `main` 함수만 호출하여 시작할 수 있으므로, 해시 함수를 호출하는 `main`을 가진 프로그램을 생성합니다. + +``` +${hashFragment} + +def main(bool[${width+2}][${height+2}] map) -> field { + return hashMap(map); +} +``` + +### 파기 프로그램 {#dig-program} + +이것은 애플리케이션의 영지식 부분의 핵심으로, 파기 결과를 검증하는 데 사용되는 증명을 생성하는 곳입니다. + +``` +${hashFragment} + +// 위치 (x,y)의 지뢰 수 +def map2mineCount(bool[${width+2}][${height+2}] map, u32 x, u32 y) -> u8 { + return if map[x+1][y+1] { 1 } else { 0 }; +} +``` + +#### 왜 맵 테두리인가 {#why-map-border} + +영지식 증명은 `if` 문에 대한 쉬운 등가물이 없는 [산술 회로](https://medium.com/web3studio/simple-explanations-of-arithmetic-circuits-and-zero-knowledge-proofs-806e59a79785)를 사용합니다. 대신, [조건부 연산자](https://en.wikipedia.org/wiki/Ternary_conditional_operator)의 등가물을 사용합니다. `a`가 0 또는 1일 수 있다면, `if a { b } else { c }`를 `ab+(1-a)c`로 계산할 수 있습니다. + +이 때문에 Zokrates `if` 문은 항상 두 분기를 모두 평가합니다. 예를 들어, 다음과 같은 코드가 있다면: + +``` +bool[5] arr = [false; 5]; +u32 index=10; +return if index>4 { 0 } else { arr[index] } +``` + +나중에 그 값이 0으로 곱해지더라도 `arr[10]`을 계산해야 하기 때문에 오류가 발생합니다. + +이것이 우리가 맵 주위에 1칸 너비의 테두리가 필요한 이유입니다. 우리는 한 위치 주변의 총 지뢰 수를 계산해야 하며, 이는 우리가 파고 있는 위치의 위, 아래, 왼쪽, 오른쪽 위치를 봐야 한다는 것을 의미합니다. 즉, Zokrates에 제공되는 맵 배열에 해당 위치가 존재해야 합니다. + +``` +def main(private bool[${width+2}][${height+2}] map, u32 x, u32 y) -> (field, u8) { +``` + +기본적으로 Zokrates 증명은 입력을 포함합니다. 어떤 지점 주변에 지뢰가 5개 있다는 것을 아는 것은 실제로 어떤 지점인지 알지 못하면 아무 소용이 없습니다(그리고 요청과 일치시킬 수만도 없습니다. 그러면 증명자가 다른 값을 사용하고 알려주지 않을 수도 있기 때문입니다). 하지만 우리는 Zokrates에 제공하면서 맵을 비밀로 유지해야 합니다. 해결책은 증명에 의해 _드러나지 않는_ 매개변수인 `private` 매개변수를 사용하는 것입니다. + +이것은 또 다른 남용의 여지를 엽니다. 증명자는 올바른 좌표를 사용할 수 있지만, 위치 주변에 임의의 수의 지뢰가 있는 맵을 생성하고, 심지어 위치 자체에도 지뢰를 생성할 수 있습니다. 이러한 남용을 방지하기 위해, 우리는 영지식 증명에 게임 식별자인 맵의 해시를 포함시킵니다. + +``` + return (hashMap(map), +``` + +여기서 반환 값은 맵 해시 배열과 파기 결과를 포함하는 튜플입니다. + +``` + if map2mineCount(map, x, y) > 0 { 0xFF } else { +``` + +위치 자체에 폭탄이 있는 경우 특수 값으로 255를 사용합니다. + +``` + map2mineCount(map, x-1, y-1) + map2mineCount(map, x, y-1) + map2mineCount(map, x+1, y-1) + + map2mineCount(map, x-1, y) + map2mineCount(map, x+1, y) + + map2mineCount(map, x-1, y+1) + map2mineCount(map, x, y+1) + map2mineCount(map, x+1, y+1) + } + ); +} +``` + +플레이어가 지뢰를 밟지 않았다면, 해당 위치 주변 지역의 지뢰 수를 더하여 반환합니다. + +### TypeScript에서 Zokrates 사용하기 {#using-zokrates-from-typescript} + +Zokrates에는 명령줄 인터페이스가 있지만, 이 프로그램에서는 [TypeScript 코드](https://zokrates.github.io/toolbox/zokrates_js.html)에서 사용합니다. + +Zokrates 정의를 포함하는 라이브러리는 [`zero-knowledge.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts)라고 합니다. + +```typescript +import { initialize as zokratesInitialize } from "zokrates-js" +``` + +[Zokrates 자바스크립트 바인딩](https://zokrates.github.io/toolbox/zokrates_js.html)을 가져옵니다. 모든 Zokrates 정의로 해석되는 프라미스를 반환하므로 [`initialize`](https://zokrates.github.io/toolbox/zokrates_js.html#initialize) 함수만 필요합니다. + +```typescript +export const zkFunctions = async (width: number, height: number) : Promise => { +``` + +Zokrates 자체와 유사하게, 우리도 [비동기적](https://www.w3schools.com/js/js_async.asp)인 단 하나의 함수만 내보냅니다. 결국 반환될 때 아래에서 보게 될 여러 함수를 제공합니다. + +```typescript +const zokrates = await zokratesInitialize() +``` + +Zokrates를 초기화하고, 라이브러리에서 필요한 모든 것을 가져옵니다. + +```typescript +const hashFragment = ` + import "utils/pack/bool/pack128.zok" as pack128; + import "hashes/poseidon/poseidon.zok" as poseidon; + . + . + . + } + ` + +const hashProgram = ` + ${hashFragment} + . + . + . + ` + +const digProgram = ` + ${hashFragment} + . + . + . + ` +``` + +다음으로 위에서 본 해시 함수와 두 개의 Zokrates 프로그램이 있습니다. + +```typescript +const digCompiled = zokrates.compile(digProgram) +const hashCompiled = zokrates.compile(hashProgram) +``` + +여기서 우리는 그 프로그램들을 컴파일합니다. + +```typescript +// 영지식 검증을 위한 키를 생성합니다. +// 프로덕션 시스템에서는 설정 의식을 사용하고 싶을 것입니다. +// (https://zokrates.github.io/toolbox/trusted_setup.html#initializing-a-phase-2-ceremony). +const keySetupResults = zokrates.setup(digCompiled.program, "") +const verifierKey = keySetupResults.vk +const proverKey = keySetupResults.pk +``` + +프로덕션 시스템에서는 더 복잡한 [설정 의식](https://zokrates.github.io/toolbox/trusted_setup.html#initializing-a-phase-2-ceremony)을 사용할 수 있지만, 데모용으로는 이것으로 충분합니다. 사용자가 증명자 키를 알 수 있다는 것은 문제가 되지 않습니다 - 그들은 여전히 사실이 아닌 한 그것을 사용하여 증명할 수 없습니다. 엔트로피(두 번째 매개변수, `""`)를 지정하기 때문에 결과는 항상 동일합니다. + +**참고:** Zokrates 프로그램 컴파일 및 키 생성은 느린 과정입니다. 맵 크기가 변경될 때만 반복할 필요가 있으며, 매번 반복할 필요는 없습니다. 프로덕션 시스템에서는 한 번 수행한 다음 출력을 저장합니다. 여기서 그렇게 하지 않는 유일한 이유는 단순성을 위해서입니다. + +#### `calculateMapHash` {#calculateMapHash} + +```typescript +const calculateMapHash = function (hashMe: boolean[][]): string { + return ( + "0x" + + BigInt(zokrates.computeWitness(hashCompiled, [hashMe]).output.slice(1, -1)) + .toString(16) + .padStart(64, "0") + ) +} +``` + +[`computeWitness`](https://zokrates.github.io/toolbox/zokrates_js.html#computewitnessartifacts-args-options) 함수는 실제로 Zokrates 프로그램을 실행합니다. 두 개의 필드가 있는 구조를 반환합니다: `output`은 JSON 문자열로서의 프로그램 출력이고, `witness`는 결과에 대한 영지식 증명을 생성하는 데 필요한 정보입니다. 여기서는 출력만 필요합니다. + +출력은 ` `viem`에 필요한 출력은 `0x60A7`형식의 16진수 숫자입니다. 따라서`.slice(1,-1)`를 사용하여 따옴표를 제거한 다음, `BigInt`를 사용하여 남은 문자열(10진수)을 [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)로 실행합니다. `.toString(16)`은 이 `BigInt`를 16진수 문자열로 변환하고, `"0x"+`는 16진수 숫자를 위한 마커를 추가합니다. + +```typescript +// 결과에 대한 영지식 증명을 파고 반환합니다 +// (서버 측 코드) +``` + +영지식 증명은 공개 입력(`x`와 `y`)과 결과(맵의 해시와 폭탄 수)를 포함합니다. + +```typescript + const zkDig = function(map: boolean[][], x: number, y: number) : any { + if (x<0 || x>=width || y<0 || y>=height) + throw new Error("맵 밖을 파려고 시도 중입니다") +``` + +Zokrates에서 인덱스가 범위를 벗어났는지 확인하는 것은 문제이므로 여기서 처리합니다. + +```typescript +const runResults = zokrates.computeWitness(digCompiled, [map, `${x}`, `${y}`]) +``` + +파기 프로그램을 실행합니다. + +```typescript + const proof = zokrates.generateProof( + digCompiled.program, + runResults.witness, + proverKey) + + return proof + } +``` + +[`generateProof`](https://zokrates.github.io/toolbox/zokrates_js.html#generateproofprogram-witness-provingkey-entropy)를 사용하여 증명을 반환합니다. + +```typescript +const solidityVerifier = ` + // 맵 크기: ${width} x ${height} + \n${zokrates.exportSolidityVerifier(verifierKey)} + ` +``` + +솔리디티 검증자, 블록체인에 배포하고 `digCompiled.program`에 의해 생성된 증명을 검증하는 데 사용할 수 있는 스마트 컨트랙트입니다. + +```typescript + return { + zkDig, + calculateMapHash, + solidityVerifier, + } +} +``` + +마지막으로 다른 코드에 필요할 수 있는 모든 것을 반환합니다. + +## 보안 테스트 {#security-tests} + +기능 버그는 결국 드러나기 때문에 보안 테스트는 중요합니다. 하지만 애플리케이션이 안전하지 않다면, 누군가 부정행위를 하여 다른 사람의 리소스를 빼앗아 가기 전까지는 오랫동안 숨겨져 있을 가능성이 높습니다. + +### 권한 {#permissions} + +이 게임에는 서버라는 하나의 특권 엔터티가 있습니다. [`ServerSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol)의 함수를 호출할 수 있는 유일한 사용자입니다. [`cast`](https://book.getfoundry.sh/cast/)를 사용하여 권한이 부여된 함수에 대한 호출이 서버 계정으로만 허용되는지 확인할 수 있습니다. + +[서버의 개인 키는 `setupNetwork.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/mud/setupNetwork.ts#L52)에 있습니다. + +1. `anvil`(블록체인)을 실행하는 컴퓨터에서 다음 환경 변수를 설정합니다. + + ```sh copy + WORLD_ADDRESS=0x8d8b6b8414e1e3dcfd4168561b9be6bd3bf6ec4b + UNAUTHORIZED_KEY=0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a + AUTHORIZED_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d + ``` + +2. `cast`를 사용하여 인증되지 않은 주소로 검증자 주소를 설정하려고 시도합니다. + + ```sh copy + cast send $WORLD_ADDRESS 'app__setVerifier(address)' `cast address-zero` --private-key $UNAUTHORIZED_KEY + ``` + + `cast`가 실패를 보고할 뿐만 아니라, 브라우저의 게임에서 **MUD Dev Tools**를 열고, **Tables**를 클릭한 다음, **app\_\_VerifierAddress**를 선택할 수 있습니다. 주소가 0이 아닌지 확인하세요. + +3. 검증자 주소를 서버의 주소로 설정합니다. + + ```sh copy + cast send $WORLD_ADDRESS 'app__setVerifier(address)' `cast address-zero` --private-key $AUTHORIZED_KEY + ``` + + **app\_\_VerifiedAddress**의 주소는 이제 0이어야 합니다. + +동일한 `System` 내의 모든 MUD 함수는 동일한 접근 제어를 거치므로 이 테스트는 충분하다고 생각합니다. 그렇지 않다면, [`ServerSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol)의 다른 함수들을 확인할 수 있습니다. + +### 영지식 남용 {#zero-knowledge-abuses} + +Zokrates를 검증하는 수학은 이 튜토리얼의 범위를 벗어납니다(그리고 제 능력 밖입니다). 하지만, 우리는 영지식 코드에 대한 다양한 검사를 실행하여 올바르게 수행되지 않으면 실패하는지 확인할 수 있습니다. 이러한 모든 테스트는 [`zero-knowledge.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts)를 변경하고 전체 애플리케이션을 다시 시작해야 합니다. 서버 프로세스를 다시 시작하는 것만으로는 충분하지 않습니다. 왜냐하면 이는 애플리케이션을 불가능한 상태(플레이어가 진행 중인 게임이 있지만 서버에서는 더 이상 게임을 사용할 수 없음)로 만들기 때문입니다. + +#### 잘못된 답변 {#wrong-answer} + +가장 간단한 가능성은 영지식 증명에서 잘못된 답변을 제공하는 것입니다. 이를 위해 `zkDig` 내부로 들어가서 [91번째 줄](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L91)을 수정합니다: + +```ts +proof.inputs[3] = "0x" + "1".padStart(64, "0") +``` + +이것은 올바른 답변에 관계없이 항상 폭탄이 하나 있다고 주장한다는 의미입니다. 이 버전으로 플레이해보면 `pnpm dev` 화면의 **서버** 탭에서 다음과 같은 오류가 표시됩니다. + +``` + cause: { + code: 3, + message: 'execution reverted: revert: Zero knowledge verification fail', + data: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000 +000000000000000000000000000000000000000000000000205a65726f206b6e6f776c6564676520766572696669636174696f6 +e206661696c' + }, +``` + +따라서 이런 종류의 부정 행위는 실패합니다. + +#### 잘못된 증명 {#wrong-proof} + +올바른 정보를 제공하지만 잘못된 증명 데이터를 가지고 있다면 어떻게 될까요? 이제 91번 줄을 다음과 같이 바꿉니다. + +```ts +proof.proof = { + a: ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")], + b: [ + ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")], + ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")], + ], + c: ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")], +} +``` + +여전히 실패하지만, 이제는 검증자 호출 중에 발생하기 때문에 이유 없이 실패합니다. + +### 사용자는 어떻게 제로 트러스트 코드를 검증할 수 있나요? {#user-verify-zero-trust} + +스마트 컨트랙트는 비교적 쉽게 검증할 수 있습니다. 일반적으로 개발자는 블록 탐색기에 소스 코드를 게시하고, 블록 탐색기는 소스 코드가 [컨트랙트 배포 트랜잭션](/developers/docs/smart-contracts/deploying/)의 코드로 컴파일되는지 확인합니다. MUD `System`의 경우 [약간 더 복잡](https://mud.dev/cli/verify)하지만 크게 다르지 않습니다. + +영지식으로는 더 어렵습니다. 검증자는 일부 상수를 포함하고 이에 대한 계산을 실행합니다. 이것은 무엇이 증명되고 있는지 알려주지 않습니다. + +```solidity + function verifyingKey() pure internal returns (VerifyingKey memory vk) { + vk.alpha = Pairing.G1Point(uint256(0x0f43f4fe7b5c2326fed4ac6ed2f4003ab9ab4ea6f667c2bdd77afb068617ee16), uint256(0x25a77832283f9726935219b5f4678842cda465631e72dbb24708a97ba5d0ce6f)); + vk.beta = Pairing.G2Point([uint256(0x2cebd0fbd21aca01910581537b21ae4fed46bc0e524c055059aa164ba0a6b62b), uint256(0x18fd4a7bc386cf03a95af7163d5359165acc4e7961cb46519e6d9ee4a1e2b7e9)], [uint256(0x11449dee0199ef6d8eebfe43b548e875c69e7ce37705ee9a00c81fe52f11a009), uint256(0x066d0c83b32800d3f335bb9e8ed5e2924cf00e77e6ec28178592eac9898e1a00)]); +``` + +해결책은, 적어도 블록 탐색기가 사용자 인터페이스에 Zokrates 검증을 추가하기 전까지는, 애플리케이션 개발자가 Zokrates 프로그램을 제공하고, 적어도 일부 사용자가 적절한 검증 키로 직접 컴파일하는 것입니다. + +그렇게 하려면: + +1. [Zokrates를 설치](https://zokrates.github.io/gettingstarted.html)합니다. + +2. `dig.zok`이라는 파일을 만들고 Zokrates 프로그램을 넣습니다. 아래 코드는 원래 맵 크기인 10x5를 유지했다고 가정합니다. + + ```zokrates + import "utils/pack/bool/pack128.zok" as pack128; + import "hashes/poseidon/poseidon.zok" as poseidon; + + def hashMap(bool[12][7] map) -> field { + bool[512] mut map1d = [false; 512]; + u32 mut counter = 0; + + for u32 x in 0..12 { + for u32 y in 0..7 { + map1d[counter] = map[x][y]; + counter = counter+1; + } + } + + field[4] hashMe = [ + pack128(map1d[0..128]), + pack128(map1d[128..256]), + pack128(map1d[256..384]), + pack128(map1d[384..512]) + ]; + + return poseidon(hashMe); + } + + + // 위치 (x,y)의 지뢰 수 + def map2mineCount(bool[12][7] map, u32 x, u32 y) -> u8 { + return if map[x+1][y+1] { 1 } else { 0 }; + } + + def main(private bool[12][7] map, u32 x, u32 y) -> (field, u8) { + return (hashMap(map) , + if map2mineCount(map, x, y) > 0 { 0xFF } else { + map2mineCount(map, x-1, y-1) + map2mineCount(map, x, y-1) + map2mineCount(map, x+1, y-1) + + map2mineCount(map, x-1, y) + map2mineCount(map, x+1, y) + + map2mineCount(map, x-1, y+1) + map2mineCount(map, x, y+1) + map2mineCount(map, x+1, y+1) + } + ); + } + ``` + +3. Zokrates 코드를 컴파일하고 검증 키를 만듭니다. 검증 키는 원래 서버에서 사용된 것과 동일한 엔트로피로 생성해야 합니다. [이 경우 빈 문자열](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L67)입니다. + + ```sh copy + zokrates compile --input dig.zok + zokrates setup -e "" + ``` + +4. 자신만의 솔리디티 검증자를 만들고, 블록체인에 있는 것과 기능적으로 동일한지 확인합니다(서버는 주석을 추가하지만 이는 중요하지 않습니다). + + ```sh copy + zokrates export-verifier + diff verifier.sol ~/20240901-secret-state/packages/contracts/src/verifier.sol + ``` + +## 설계 결정 {#design} + +충분히 복잡한 애플리케이션에는 절충이 필요한 경쟁적인 설계 목표가 있습니다. 몇 가지 절충안과 현재 솔루션이 다른 옵션보다 선호되는 이유를 살펴보겠습니다. + +### 왜 영지식인가 {#why-zero-knowledge} + +지뢰 찾기에는 실제로 영지식이 필요하지 않습니다. 서버는 항상 맵을 보유하고 있다가 게임이 끝나면 모든 것을 공개할 수 있습니다. 그러면 게임이 끝날 때 스마트 컨트랙트가 맵 해시를 계산하여 일치하는지 확인하고, 일치하지 않으면 서버에 페널티를 부과하거나 게임을 완전히 무시할 수 있습니다. + +이 간단한 해결책을 사용하지 않은 이유는 잘 정의된 최종 상태를 가진 짧은 게임에만 작동하기 때문입니다. 게임이 잠재적으로 무한할 경우([자율 세계](https://0xparc.org/blog/autonomous-worlds)의 경우와 같이), 상태를 _공개하지 않고_ 증명하는 해결책이 필요합니다. + +튜토리얼로서 이 글은 이해하기 쉬운 짧은 게임이 필요했지만, 이 기술은 더 긴 게임에 가장 유용합니다. + +### 왜 Zokrates인가? {#why-zokrates} + +[Zokrates](https://zokrates.github.io/)는 사용 가능한 유일한 영지식 라이브러리는 아니지만, 일반적인 [명령형](https://en.wikipedia.org/wiki/Imperative_programming) 프로그래밍 언어와 유사하며 불리언 변수를 지원합니다. + +요구 사항이 다른 애플리케이션의 경우 [Circum](https://docs.circom.io/getting-started/installation/) 또는 [Cairo](https://www.cairo-lang.org/tutorials/getting-started-with-cairo/)를 사용하는 것을 선호할 수 있습니다. + +### Zokrates를 언제 컴파일해야 하나요? {#when-compile-zokrates} + +이 프로그램에서는 [서버가 시작될 때마다](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L60-L61) Zokrates 프로그램을 컴파일합니다. 이것은 분명히 리소스 낭비이지만, 이것은 단순성을 위해 최적화된 튜토리얼입니다. + +만약 제가 프로덕션 수준의 애플리케이션을 작성한다면, 이 지뢰밭 크기의 컴파일된 Zokrates 프로그램이 있는 파일이 있는지 확인하고, 있다면 그것을 사용할 것입니다. 온체인에 검증자 컨트랙트를 배포하는 경우에도 마찬가지입니다. + +### 검증자 및 증명자 키 생성 {#key-creation} + +[키 생성](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L63-L69)은 주어진 지뢰밭 크기에 대해 한 번 이상 수행할 필요가 없는 또 다른 순수 계산입니다. 다시 말하지만, 단순성을 위해 한 번만 수행됩니다. + +또한, 우리는 [설정 의식](https://zokrates.github.io/toolbox/trusted_setup.html#initializing-a-phase-2-ceremony)을 사용할 수 있습니다. 설정 의식의 장점은 영지식 증명을 속이려면 엔트로피 또는 각 참가자의 중간 결과가 필요하다는 것입니다. 적어도 한 명의 의식 참가자가 정직하고 해당 정보를 삭제하면 영지식 증명은 특정 공격으로부터 안전합니다. 그러나 정보가 모든 곳에서 삭제되었는지 확인할 수 있는 _메커니즘은 없습니다_. 영지식 증명이 매우 중요하다면 설정 의식에 참여하고 싶을 것입니다. + +여기서는 수십 명의 참가자가 있었던 [영구적인 타우의 힘](https://github.com/privacy-scaling-explorations/perpetualpowersoftau)에 의존합니다. 아마도 충분히 안전하고 훨씬 더 간단할 것입니다. 또한 키 생성 중에 엔트로피를 추가하지 않으므로 사용자가 [영지식 구성](#user-verify-zero-trust)을 더 쉽게 확인할 수 있습니다. + +### 어디서 검증할 것인가 {#where-verification} + +영지식 증명은 온체인(가스가 비용 발생) 또는 클라이언트([`verify`](https://zokrates.github.io/toolbox/zokrates_js.html#verifyverificationkey-proof) 사용)에서 검증할 수 있습니다. 저는 첫 번째를 선택했습니다. 왜냐하면 이렇게 하면 [검증자를 한 번 검증](#user-verify-zero-trust)한 다음, 컨트랙트 주소가 동일하게 유지되는 한 변경되지 않는다고 신뢰할 수 있기 때문입니다. 클라이언트에서 검증이 수행되었다면, 클라이언트를 다운로드할 때마다 받는 코드를 확인해야 합니다. + +또한, 이 게임은 싱글 플레이어지만, 많은 블록체인 게임은 멀티플레이어입니다. 온체인 검증은 영지식 증명을 한 번만 검증한다는 것을 의미합니다. 클라이언트에서 이를 수행하려면 각 클라이언트가 독립적으로 검증해야 합니다. + +### TypeScript에서 맵을 평탄화할까요, 아니면 Zokrates에서 할까요? {#where-flatten} + +일반적으로 처리가 TypeScript 또는 Zokrates에서 수행될 수 있는 경우, 훨씬 빠르고 영지식 증명이 필요 없는 TypeScript에서 수행하는 것이 좋습니다. 이것이 예를 들어, 우리가 Zokrates에 해시를 제공하고 그것이 올바른지 확인하도록 하지 않는 이유입니다. 해싱은 Zokrates 내부에서 수행되어야 하지만, 반환된 해시와 온체인의 해시 간의 일치는 외부에서 발생할 수 있습니다. + +그러나 우리는 여전히 [Zokrates에서 맵을 평탄화](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L15-L20)하는데, TypeScript에서 할 수도 있었습니다. 그 이유는 제 생각에 다른 옵션이 더 나쁘기 때문입니다. + +- Zokrates 코드에 1차원 불리언 배열을 제공하고, `x*(height+2)\n+y`와 같은 표현식을 사용하여 2차원 맵을 얻습니다. 이렇게 하면 [코드](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L44-L47)가 다소 복잡해지므로, 튜토리얼을 위해 성능 향상이 그만한 가치가 없다고 결정했습니다. + +- Zokrates에 1차원 배열과 2차원 배열을 모두 보냅니다. 하지만 이 해결책은 우리에게 아무것도 얻을 수 없습니다. Zokrates 코드는 제공된 1차원 배열이 정말로 2차원 배열의 올바른 표현인지 확인해야 합니다. 따라서 성능 향상은 없을 것입니다. + +- Zokrates에서 2차원 배열을 평탄화합니다. 이것이 가장 간단한 옵션이므로 선택했습니다. + +### 맵을 어디에 저장할까요 {#where-store-maps} + +이 애플리케이션에서 [`gamesInProgress`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L20)는 단순히 메모리의 변수입니다. 이는 서버가 죽어서 다시 시작해야 할 경우 저장된 모든 정보가 손실된다는 것을 의미합니다. 플레이어는 게임을 계속할 수 없을 뿐만 아니라, 온체인 컴포넌트가 여전히 게임이 진행 중이라고 생각하기 때문에 새 게임을 시작할 수도 없습니다. + +이것은 프로덕션 시스템에서는 명백히 나쁜 설계이며, 이러한 정보를 데이터베이스에 저장해야 합니다. 여기서 변수를 사용한 유일한 이유는 이것이 튜토리얼이고 단순성이 주요 고려 사항이기 때문입니다. + +## 결론: 어떤 조건에서 이 기술이 적절한가요? {#conclusion} + +자, 이제 온체인에 속하지 않는 비밀 상태를 저장하는 서버로 게임을 작성하는 방법을 알게 되었습니다. 하지만 어떤 경우에 그렇게 해야 할까요? 두 가지 주요 고려 사항이 있습니다. + +- _장기 실행 게임_: [위에서 언급했듯이](#why-zero-knowledge), 짧은 게임에서는 게임이 끝나면 상태를 게시하고 모든 것을 검증할 수 있습니다. 하지만 게임이 길거나 무기한으로 지속되고 상태가 비밀로 유지되어야 하는 경우에는 해당 옵션이 아닙니다. + +- _일부 중앙화 허용_: 영지식 증명은 무결성, 즉 개체가 결과를 위조하지 않음을 검증할 수 있습니다. 그들이 할 수 없는 것은 개체가 여전히 사용 가능하고 메시지에 응답할 것이라고 보장하는 것입니다. 가용성 또한 탈중앙화되어야 하는 상황에서는 영지식 증명은 충분한 해결책이 아니며, [다자간 계산](https://en.wikipedia.org/wiki/Secure_multi-party_computation)이 필요합니다. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). + +### 감사의 말 {#acknowledgements} + +- Alvaro Alonso는 이 글의 초안을 읽고 Zokrates에 대한 저의 오해를 일부 바로잡아 주었습니다. + +남아있는 오류는 제 책임입니다. diff --git a/public/content/translations/ko/developers/tutorials/secure-development-workflow/index.md b/public/content/translations/ko/developers/tutorials/secure-development-workflow/index.md new file mode 100644 index 00000000000..36dcee241c4 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/secure-development-workflow/index.md @@ -0,0 +1,52 @@ +--- +title: "스마트 계약 보안 점검 사항" +description: "안전한 스마트 계약 작성을 위한 워크플로 제안" +author: "Trailofbits" +tags: [ "스마트 컨트랙트", "보안", "Solidity" ] +skill: intermediate +lang: ko +published: 2020-09-07 +source: Building secure contracts +sourceUrl: https://github.com/crytic/building-secure-contracts/blob/master/development-guidelines/workflow.md +--- + +## 스마트 계약 개발 체크리스트 {#smart-contract-development-checklist} + +스마트 계약을 작성할 때 따르기를 권장하는 개괄적인 절차입니다. + +알려진 보안 문제 확인: + +- [Slither](https://github.com/crytic/slither)로 계약을 검토하세요. 일반적인 취약점에 대한 40개 이상의 탐지기가 내장되어 있습니다. 새 코드를 체크인할 때마다 실행하여 깔끔한 보고서를 받도록 하세요(또는 트리아지 모드를 사용하여 특정 문제를 무시하세요). +- [Crytic](https://crytic.io/)으로 계약을 검토하세요. Slither가 확인하지 않는 50가지 문제를 확인합니다. 또한 Crytic은 GitHub의 풀 리퀘스트에서 보안 문제를 쉽게 표시하여 팀이 서로의 작업을 파악하는 데 도움을 줄 수 있습니다. + +계약의 특별한 기능 고려: + +- 계약을 업그레이드할 수 있나요? [`slither-check-upgradeability`](https://github.com/crytic/slither/wiki/Upgradeability-Checks) 또는 [Crytic](https://blog.trailofbits.com/2020/06/12/upgradeable-contracts-made-safer-with-crytic/)으로 업그레이드 가능성 코드의 결함을 검토하세요. 업그레이드가 잘못될 수 있는 17가지 방법을 문서화했습니다. +- 계약이 ERC를 준수한다고 표방합니까? [`slither-check-erc`](https://github.com/crytic/slither/wiki/ERC-Conformance)로 확인하세요. 이 도구는 6가지 일반적인 사양과의 편차를 즉시 식별합니다. +- 제3자 토큰과 통합합니까? 외부 계약에 의존하기 전에 [토큰 통합 체크리스트](/developers/tutorials/token-integration-checklist/)를 검토하세요. + +코드의 중요한 보안 기능을 시각적으로 검사: + +- Slither의 [상속 그래프](https://github.com/trailofbits/slither/wiki/Printer-documentation#inheritance-graph) 프린터를 검토하세요. 의도하지 않은 섀도잉 및 C3 선형화 문제를 방지하세요. +- Slither의 [function-summary](https://github.com/trailofbits/slither/wiki/Printer-documentation#function-summary) 프린터를 검토하세요. 함수 가시성과 접근 제어를 보고합니다. +- Slither의 [vars-and-auth](https://github.com/trailofbits/slither/wiki/Printer-documentation#variables-written-and-authorization) 프린터를 검토하세요. 상태 변수에 대한 접근 제어를 보고합니다. + +중요한 보안 속성을 문서화하고 자동화된 테스트 생성기를 사용하여 평가하세요. + +- [코드의 보안 속성을 문서화하는 방법](/developers/tutorials/guide-to-smart-contract-security-tools/)을 알아보세요. 처음에는 어렵지만, 좋은 결과를 얻기 위한 가장 중요한 단일 활동입니다. 또한 이 튜토리얼의 고급 기술을 사용하기 위한 필수 조건이기도 합니다. +- [Echidna](https://github.com/crytic/echidna) 및 [Manticore](https://manticore.readthedocs.io/en/latest/verifier.html)와 함께 사용하기 위해 Solidity에서 보안 속성을 정의하세요. 상태 머신, 접근 제어, 산술 연산, 외부 상호 작용 및 표준 준수에 집중하세요. +- [Slither의 Python API](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/)로 보안 속성을 정의하세요. 상속, 변수 종속성, 접근 제어 및 기타 구조적 문제에 집중하세요. +- [Crytic](https://crytic.io)으로 커밋할 때마다 속성 테스트를 실행하세요. Crytic은 보안 속성 테스트를 사용하고 평가할 수 있으므로 팀의 모든 사람이 GitHub에서 테스트를 통과했는지 쉽게 확인할 수 있습니다. 실패한 테스트는 커밋을 차단할 수 있습니다. + +마지막으로 자동화된 도구가 쉽게 찾을 수 없는 문제에 유의하세요. + +- 개인정보 보호 부족: 트랜잭션이 풀에서 대기하는 동안 다른 모든 사람이 트랜잭션을 볼 수 있습니다. +- 선행 매매 트랜잭션 +- 암호화 작업 +- 외부 디파이(DeFi) 구성 요소와의 위험한 상호 작용 + +## 도움 요청하기 {#ask-for-help} + +[이더리움 오피스 아워](https://calendly.com/dan-trailofbits/office-hours)는 매주 화요일 오후에 진행됩니다. 이 1시간짜리 1:1 세션은 보안에 대해 궁금한 점을 질문하고, 저희 도구를 사용하여 문제를 해결하며, 현재 접근 방식에 대해 전문가의 피드백을 받을 수 있는 기회입니다. 이 가이드를 끝까지 진행할 수 있도록 도와드리겠습니다. + +Slack에 참여하세요: [Empire Hacking](https://join.slack.com/t/empirehacking/shared_invite/zt-h97bbrj8-1jwuiU33nnzg67JcvIciUw). 궁금한 점이 있으시면 언제든지 #crytic 및 #ethereum 채널을 이용하세요. diff --git a/public/content/translations/ko/developers/tutorials/send-token-ethersjs/index.md b/public/content/translations/ko/developers/tutorials/send-token-ethersjs/index.md new file mode 100644 index 00000000000..735a64b9b50 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/send-token-ethersjs/index.md @@ -0,0 +1,210 @@ +--- +title: "ethers.js를 사용하여 토큰 전송하기" +description: "ethers.js를 사용한 토큰 전송 초보자 가이드." +author: Kim YongJun +tags: [ "ETHERS.JS", "ERC-20", "토큰" ] +skill: beginner +lang: ko +published: 2021-04-06 +--- + +## ethers.js(5.0)를 사용하여 토큰 전송하기 {#send-token} + +### 이 튜토리얼에서 배울 내용 {#you-learn-about} + +- ethers.js 가져오기 +- 토큰 전송 +- 네트워크 트래픽 상황에 따라 가스 요금 설정하기 + +### 시작하기 {#to-get-started} + +시작하려면 먼저 자바스크립트에 ethers.js 라이브러리를 가져와야 합니다. +ethers.js(5.0) 포함하기 + +### 설치하기 {#install-ethersjs} + +```shell +/home/ricmoo> npm install --save ethers +``` + +브라우저에서 ES6 사용 + +```html + +``` + +브라우저에서 ES3(UMD) 사용 + +```html + +``` + +### 매개변수 {#param} + +1. **`contract_address`**: 토큰 컨트랙트 주소(전송하려는 토큰이 이더가 아닐 경우 컨트랙트 주소가 필요합니다) +2. **`send_token_amount`**: 수신자에게 보낼 금액 +3. **`to_address`**: 수신자 주소 +4. **`send_account`**: 발신자 주소 +5. **`private_key`**: 트랜잭션에 서명하고 토큰을 실제로 전송하기 위한 발신자의 개인 키 + +## 참고 {#notice} + +`sendTransaction()`이 내부적으로 처리하므로 `signTransaction(tx)`는 제거되었습니다. + +## 전송 절차 {#procedure} + +### 1. 네트워크(테스트넷)에 연결하기 {#connect-to-network} + +#### 프로바이더(Infura) 설정 {#set-provider} + +Ropsten 테스트넷에 연결하기 + +```javascript +window.ethersProvider = new ethers.providers.InfuraProvider("ropsten") +``` + +### 2. 지갑 생성하기 {#create-wallet} + +```javascript +let wallet = new ethers.Wallet(private_key) +``` + +### 3. 지갑을 네트워크에 연결하기 {#connect-wallet-to-net} + +```javascript +let walletSigner = wallet.connect(window.ethersProvider) +``` + +### 4. 현재 가스 요금 가져오기 {#get-gas} + +```javascript +window.ethersProvider.getGasPrice() // gasPrice +``` + +### 5. 트랜잭션 정의하기 {#define-transaction} + +아래에 정의된 변수들은 `send_token()`에 의존합니다. + +### 트랜잭션 매개변수 {#transaction-params} + +1. **`send_account`**: 토큰 발신자 주소 +2. **`to_address`**: 토큰 수신자 주소 +3. **`send_token_amount`**: 전송할 토큰의 양 +4. **`gas_limit`**: 가스 한도 +5. **`gas_price`**: 가스 요금 + +[사용 방법은 아래를 참조하세요](#how-to-use) + +```javascript +const tx = { + from: send_account, + to: to_address, + value: ethers.utils.parseEther(send_token_amount), + nonce: window.ethersProvider.getTransactionCount(send_account, "latest"), + gasLimit: ethers.utils.hexlify(gas_limit), // 100000 + gasPrice: gas_price, +} +``` + +### 6. 전송 {#transfer} + +```javascript +walletSigner.sendTransaction(tx).then((transaction) => { + console.dir(transaction) + alert("전송 완료!") +}) +``` + +## 사용 방법 {#how-to-use} + +```javascript +let private_key = + "41559d28e936dc92104ff30691519693fc753ffbee6251a611b9aa1878f12a4d" +let send_token_amount = "1" +let to_address = "0x4c10D2734Fb76D3236E522509181CC3Ba8DE0e80" +let send_address = "0xda27a282B5B6c5229699891CfA6b900A716539E6" +let gas_limit = "0x100000" +let wallet = new ethers.Wallet(private_key) +let walletSigner = wallet.connect(window.ethersProvider) +let contract_address = "" +window.ethersProvider = new ethers.providers.InfuraProvider("ropsten") + +send_token( + contract_address, + send_token_amount, + to_address, + send_address, + private_key +) +``` + +### 성공! {#success} + +![성공적으로 완료된 트랜잭션 이미지](./successful-transaction.png) + +## send_token() {#send-token-method} + +```javascript +function send_token( + contract_address, + send_token_amount, + to_address, + send_account, + private_key +) { + let wallet = new ethers.Wallet(private_key) + let walletSigner = wallet.connect(window.ethersProvider) + + window.ethersProvider.getGasPrice().then((currentGasPrice) => { + let gas_price = ethers.utils.hexlify(parseInt(currentGasPrice)) + console.log(`가스 요금: ${gas_price}`) + + if (contract_address) { + // 일반 토큰 전송 + let contract = new ethers.Contract( + contract_address, + send_abi, + walletSigner + ) + + // 토큰 수량 + let numberOfTokens = ethers.utils.parseUnits(send_token_amount, 18) + console.log(`토큰 수량: ${numberOfTokens}`) + + // 토큰 전송 + contract.transfer(to_address, numberOfTokens).then((transferResult) => { + console.dir(transferResult) + alert("토큰 전송됨") + }) + } // 이더 전송 + else { + const tx = { + from: send_account, + to: to_address, + value: ethers.utils.parseEther(send_token_amount), + nonce: window.ethersProvider.getTransactionCount( + send_account, + "latest" + ), + gasLimit: ethers.utils.hexlify(gas_limit), // 100000 + gasPrice: gas_price, + } + console.dir(tx) + try { + walletSigner.sendTransaction(tx).then((transaction) => { + console.dir(transaction) + alert("전송 완료!") + }) + } catch (error) { + alert("전송 실패!!") + } + } + }) +} +``` diff --git a/public/content/translations/ko/developers/tutorials/sending-transactions-using-web3-and-alchemy/index.md b/public/content/translations/ko/developers/tutorials/sending-transactions-using-web3-and-alchemy/index.md new file mode 100644 index 00000000000..6d793e9d1fa --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/sending-transactions-using-web3-and-alchemy/index.md @@ -0,0 +1,208 @@ +--- +title: "Web3를 사용하여 트랜잭션 전송하기" +description: "이 문서는 Web3를 사용하여 이더리움 트랜잭션을 전송하는 초보자용 가이드입니다. 이더리움 블록체인으로 트랜잭션을 전송하려면 생성, 서명, 브로드캐스트의 세 가지 주요 단계가 있습니다. 이 세 가지를 모두 살펴보겠습니다." +author: "Elan Halpern" +tags: [ "트랜잭션", "web3.js", "Alchemy" ] +skill: beginner +lang: ko +published: 2020-11-04 +source: Alchemy docs +sourceUrl: https://www.alchemy.com/docs/how-to-send-transactions-on-ethereum +--- + +이 문서는 Web3를 사용하여 이더리움 트랜잭션을 전송하는 초보자용 가이드입니다. 이더리움 블록체인으로 트랜잭션을 전송하려면 생성, 서명, 브로드캐스트의 세 가지 주요 단계가 있습니다. 이 세 가지를 모두 살펴보면서 궁금한 점에 대해 답변해 드리겠습니다! 이 튜토리얼에서는 [Alchemy](https://www.alchemy.com/)를 사용하여 이더리움 체인에 트랜잭션을 전송합니다. [여기에서 무료 Alchemy 계정을 만들 수 있습니다](https://auth.alchemyapi.io/signup). + +**참고:** 이 가이드는 앱의 백엔드에서 트랜잭션에 서명하기 위한 것입니다. 프런트엔드에서 트랜잭션 서명을 통합하려면 [브라우저 공급자와 Web3 통합](https://docs.alchemy.com/reference/api-overview#with-a-browser-provider)을 확인하세요. + +## 기본 사항 {#the-basics} + +대부분의 블록체인 개발자들이 처음 시작할 때처럼, 여러분도 (매우 간단해야 할) 트랜잭션 전송 방법에 대해 조사를 하다가 서로 다른 내용을 담은 수많은 가이드를 접하고 다소 압도되고 혼란스러웠을 수 있습니다. 만약 그렇다면 걱정하지 마세요. 우리 모두 한때는 그랬으니까요! 따라서 시작하기 전에 몇 가지 사항을 명확히 짚고 넘어가겠습니다. + +### 1. Alchemy는 개인 키를 저장하지 않습니다 {#alchemy-does-not-store-your-private-keys} + +- 이는 Alchemy가 여러분을 대신하여 트랜잭션에 서명하고 전송할 수 없음을 의미합니다. 이는 보안상의 이유 때문입니다. Alchemy는 절대로 여러분의 개인 키를 공유하도록 요청하지 않으며, 호스팅된 노드(또는 다른 누구에게도)와 개인 키를 공유해서는 안 됩니다. +- Alchemy의 핵심 API를 사용하여 블록체인에서 데이터를 읽을 수는 있지만, 쓰기 위해서는 Alchemy를 통해 트랜잭션을 보내기 전에 다른 것을 사용하여 서명해야 합니다(이는 다른 [노드 서비스](/developers/docs/nodes-and-clients/nodes-as-a-service/)에서도 마찬가지입니다). + +### 2. “서명자(signer)”란 무엇인가요? {#what-is-a-signer} + +- 서명자는 여러분의 개인 키를 사용하여 트랜잭션에 서명합니다. 이 튜토리얼에서는 [Alchemy web3](https://docs.alchemyapi.io/alchemy/documentation/alchemy-web3)를 사용하여 트랜잭션에 서명하지만, 다른 web3 라이브러리를 사용할 수도 있습니다. +- 프런트엔드에서 서명자의 좋은 예는 [MetaMask](https://metamask.io/)이며, 여러분을 대신하여 트랜잭션에 서명하고 전송합니다. + +### 3. 트랜잭션에 서명해야 하는 이유는 무엇인가요? {#why-do-i-need-to-sign-my-transactions} + +- 이더리움 네트워크에서 트랜잭션을 보내려는 모든 사용자는 트랜잭션의 출처가 주장하는 바와 동일하다는 것을 검증하기 위해 (개인 키를 사용하여) 트랜잭션에 서명해야 합니다. +- 이 개인 키를 보호하는 것은 매우 중요합니다. 개인 키에 대한 액세스 권한이 있으면 이더리움 계정을 완전히 제어할 수 있게 되어, 여러분(또는 액세스 권한이 있는 모든 사람)이 대신해서 트랜잭션을 수행할 수 있기 때문입니다. + +### 4. 개인 키는 어떻게 보호하나요? {#how-do-i-protect-my-private-key} + +- 개인 키를 보호하고 트랜잭션을 보내는 데 사용하는 방법에는 여러 가지가 있습니다. 이 튜토리얼에서는 `.env` 파일을 사용할 것입니다. 하지만 개인 키를 저장하는 별도의 공급자를 사용하거나, 키스토어(keystore) 파일을 사용하거나, 다른 옵션을 사용할 수도 있습니다. + +### 5. `eth_sendTransaction`과 `eth_sendRawTransaction`의 차이점은 무엇인가요? {#difference-between-send-and-send-raw} + +`eth_sendTransaction`과 `eth_sendRawTransaction`은 모두 트랜잭션을 이더리움 네트워크에 브로드캐스트하여 향후 블록에 추가되도록 하는 이더리움 API 함수입니다. 이 둘은 트랜잭션 서명을 처리하는 방식에서 차이가 있습니다. + +- [`eth_sendTransaction`](https://docs.web3js.org/api/web3-eth/function/sendTransaction)은 _서명되지 않은_ 트랜잭션을 보내는 데 사용됩니다. 이는 전송 대상 노드가 개인 키를 관리하여 체인에 브로드캐스트하기 전에 트랜잭션에 서명할 수 있어야 함을 의미합니다. Alchemy는 사용자의 개인 키를 보관하지 않으므로 이 메서드를 지원하지 않습니다. +- [`eth_sendRawTransaction`](https://docs.alchemyapi.io/documentation/alchemy-api-reference/json-rpc#eth_sendrawtransaction)은 이미 서명된 트랜잭션을 브로드캐스트하는 데 사용됩니다. 이는 먼저 [`signTransaction(tx, private_key)`](https://docs.web3js.org/api/web3-eth-accounts/function/signTransaction)를 사용한 다음, 그 결과를 `eth_sendRawTransaction`에 전달해야 함을 의미합니다. + +web3를 사용할 때 `eth_sendRawTransaction`은 [web3.eth.sendSignedTransaction](https://docs.web3js.org/api/web3-eth/function/sendSignedTransaction) 함수를 호출하여 액세스합니다. + +이것이 이 튜토리얼에서 사용할 방법입니다. + +### 6. web3 라이브러리란 무엇인가요? {#what-is-the-web3-library} + +- Web3.js는 이더리움 개발에 흔히 사용되는 표준 JSON-RPC 호출을 감싸는 래퍼 라이브러리입니다. +- 다양한 언어를 위한 여러 web3 라이브러리가 있습니다. 이 튜토리얼에서는 JavaScript로 작성된 [Alchemy Web3](https://docs.alchemy.com/reference/api-overview)를 사용할 것입니다. [ethers.js](https://docs.ethers.org/v5/)와 같은 다른 옵션은 [여기](https://docs.alchemyapi.io/guides/getting-started#other-web3-libraries)에서 확인할 수 있습니다. + +자, 이제 몇 가지 질문들을 해결했으니 튜토리얼로 넘어가겠습니다. 언제든지 Alchemy [디스코드](https://discord.gg/gWuC7zB)에서 질문해주세요! + +### 7. 안전하고, 가스가 최적화되었으며, 비공개인 트랜잭션을 보내는 방법은 무엇인가요? {#how-to-send-secure-gas-optimized-and-private-transactions} + +- [Alchemy에는 Transact API 제품군이 있습니다](https://docs.alchemy.com/reference/transact-api-quickstart). 이를 사용하여 강화된 트랜잭션을 보내고, 트랜잭션이 발생하기 전에 시뮬레이션하고, 비공개 트랜잭션을 보내고, 가스가 최적화된 트랜잭션을 보낼 수 있습니다. +- 또한 [Notify API](https://docs.alchemy.com/docs/alchemy-notify)를 사용하여 트랜잭션이 멤풀(mempool)에서 나와 체인에 추가될 때 알림을 받을 수 있습니다. + +**참고:** 이 가이드를 따르려면 Alchemy 계정, 이더리움 주소 또는 MetaMask 지갑, Node.js 및 npm이 설치되어 있어야 합니다. 그렇지 않은 경우 다음 단계를 따르세요. + +1. [무료 Alchemy 계정 만들기](https://auth.alchemyapi.io/signup) +2. [MetaMask 계정 만들기](https://metamask.io/)(또는 이더리움 주소 받기) +3. [다음 단계에 따라 Node.js와 NPM을 설치하세요](https://docs.alchemy.com/alchemy/guides/alchemy-for-macs) + +## 트랜잭션 전송 단계 {#steps-to-sending-your-transaction} + +### 1. Sepolia 테스트넷에 Alchemy 앱 만들기 {#create-an-alchemy-app-on-the-sepolia-testnet} + +[Alchemy 대시보드](https://dashboard.alchemyapi.io/)로 이동하여 새 앱을 만들고 네트워크로 Sepolia(또는 다른 테스트넷)를 선택하세요. + +### 2. Sepolia 파우셋에서 ETH 요청하기 {#request-eth-from-sepolia-faucet} + +[Alchemy Sepolia 파우셋](https://www.sepoliafaucet.com/)의 지침에 따라 ETH를 받으세요. 다른 네트워크가 아닌 **Sepolia** 이더리움 주소(MetaMask에서)를 포함해야 합니다. 지침을 따른 후 지갑에 ETH를 받았는지 다시 확인하세요. + +### 3. 새 프로젝트 디렉터리를 만들고 `cd`로 이동하기 {#create-a-new-project-direction} + +명령줄(mac의 경우 터미널)에서 새 프로젝트 디렉터리를 만들고 그 안으로 이동합니다. + +``` +mkdir sendtx-example +cd sendtx-example +``` + +### 4. Alchemy Web3 (또는 다른 web3 라이브러리) 설치하기 {#install-alchemy-web3} + +프로젝트 디렉터리에서 다음 명령을 실행하여 [Alchemy Web3](https://docs.alchemy.com/reference/api-overview)를 설치합니다. + +참고로, ethers.js 라이브러리를 사용하고 싶다면 [여기 있는 지침을 따르세요](https://docs.alchemy.com/docs/how-to-send-transactions-on-ethereum). + +``` +npm install @alch/alchemy-web3 +``` + +### 5. dotenv 설치하기 {#install-dotenv} + +`.env` 파일을 사용하여 API 키와 개인 키를 안전하게 저장할 것입니다. + +``` +npm install dotenv --save +``` + +### 6. `.env` 파일 생성하기 {#create-the-dotenv-file} + +프로젝트 디렉터리에 `.env` 파일을 만들고 다음을 추가합니다( “`your-api-url`"과 "`your-private-key`"를 대체). + +- Alchemy API URL을 찾으려면 대시보드에서 방금 만든 앱의 세부 정보 페이지로 이동하여 오른쪽 상단의 '키 보기'를 클릭하고 HTTP URL을 가져옵니다. +- MetaMask를 사용하여 개인 키를 찾으려면 이 [가이드](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key)를 확인하세요. + +``` +API_URL = "your-api-url" +PRIVATE_KEY = "your-private-key" +``` + + + + +.env를 커밋하지 마세요! .env 파일을 다른 사람과 공유하거나 노출하지 마세요. 그렇게 하면 민감한 정보가 노출될 수 있습니다. 버전 관리 시스템을 사용하는 경우 .envgitignore 파일에 추가하세요. + + + + +### 7. `sendTx.js` 파일 만들기 {#create-sendtx-js} + +좋습니다. 이제 민감한 데이터를 `.env` 파일에 안전하게 보관했으니 코딩을 시작하겠습니다. 트랜잭션 전송 예시에서는 ETH를 Sepolia 파우셋으로 다시 보낼 것입니다. + +예제 트랜잭션을 구성하고 전송할 `sendTx.js` 파일을 만들고 다음 코드 줄을 추가하세요. + +``` +async function main() { + require('dotenv').config(); + const { API_URL, PRIVATE_KEY } = process.env; + const { createAlchemyWeb3 } = require("@alch/alchemy-web3"); + const web3 = createAlchemyWeb3(API_URL); + const myAddress = '0x610Ae88399fc1687FA7530Aac28eC2539c7d6d63' //TODO: 이 주소를 자신의 공개 주소로 바꾸세요 + + const nonce = await web3.eth.getTransactionCount(myAddress, 'latest'); // nonce는 0부터 카운트를 시작합니다 + + const transaction = { + 'to': '0x31B98D14007bDEe637298086988A0bBd31184523', // eth를 반환할 파우셋 주소 + 'value': 1000000000000000000, // 1 ETH + 'gas': 30000, + 'nonce': nonce, + // 메시지를 보내거나 스마트 계약을 실행하기 위한 선택적 데이터 필드 + }; + + const signedTx = await web3.eth.accounts.signTransaction(transaction, PRIVATE_KEY); + + web3.eth.sendSignedTransaction(signedTx.rawTransaction, function(error, hash) { + if (!error) { + console.log("🎉 트랜잭션의 해시는 다음과 같습니다: ", hash, "\n Alchemy의 멤풀에서 트랜잭션 상태를 확인하세요!"); + } else { + console.log("❗트랜잭션을 제출하는 동안 문제가 발생했습니다:", error) + } + }); +} + +main(); +``` + +6번째 줄의 주소를 자신의 공개 주소로 바꾸세요. + +이제 이 코드를 실행하기 전에 여기에 있는 몇 가지 구성 요소에 대해 이야기해 보겠습니다. + +- `nonce`: 논스(nonce) 명세는 주소에서 보낸 트랜잭션 수를 추적하는 데 사용됩니다. 이는 보안 목적과 [재전송 공격(replay attack)](https://docs.alchemyapi.io/resources/blockchain-glossary#account-nonce)을 방지하기 위해 필요합니다. 주소에서 보낸 트랜잭션 수를 얻으려면 [getTransactionCount](https://docs.alchemyapi.io/documentation/alchemy-api-reference/json-rpc#eth_gettransactioncount)를 사용합니다. +- `transaction`: 트랜잭션 객체에는 지정해야 할 몇 가지 측면이 있습니다. + - `to`: ETH를 보내고자 하는 주소입니다. 이 경우, 처음에 요청했던 [Sepolia 파우셋](https://sepoliafaucet.com/)으로 ETH를 다시 보내고 있습니다. + - `value`: 보내고자 하는 금액이며, 웨이(Wei) 단위로 지정됩니다(10^18 Wei = 1 ETH). + - `gas`: 트랜잭션에 포함할 적절한 가스 양을 결정하는 방법에는 여러 가지가 있습니다. Alchemy에는 가스 가격이 특정 임계값 내로 떨어질 때 알려주는 [가스 가격 웹훅](https://docs.alchemyapi.io/guides/alchemy-notify#address-activity-1)도 있습니다. 메인넷 트랜잭션의 경우, [ETH Gas Station](https://ethgasstation.info/)과 같은 가스 추정기를 확인하여 포함할 적절한 가스 양을 결정하는 것이 좋습니다. 21000은 이더리움에서 작업이 사용할 최소 가스 양이므로, 트랜잭션이 실행되도록 보장하기 위해 여기서는 30000을 넣습니다. + - `nonce`: 위의 논스(nonce) 정의를 참조하세요. 논스(Nonce)는 0부터 카운트를 시작합니다. + - [선택 사항] data: 전송 시 추가 정보를 보내거나 스마트 계약을 호출하는 데 사용되며, 잔액 전송에는 필요하지 않습니다. 아래 참고 사항을 확인하세요. +- `signedTx`: 트랜잭션 객체에 서명하기 위해 `PRIVATE_KEY`와 함께 `signTransaction` 메서드를 사용합니다. +- `sendSignedTransaction`: 서명된 트랜잭션이 있으면 `sendSignedTransaction`을 사용하여 후속 블록에 포함되도록 보낼 수 있습니다. + +**데이터에 대한 참고 사항** +이더리움에서 보낼 수 있는 트랜잭션에는 두 가지 주요 유형이 있습니다. + +- 잔액 전송: 한 주소에서 다른 주소로 ETH를 보냅니다. 데이터 필드는 필요하지 않지만, 트랜잭션과 함께 추가 정보를 보내고 싶다면 이 필드에 해당 정보를 16진수(HEX) 형식으로 포함할 수 있습니다. + - 예를 들어, 불변의 타임스탬프를 부여하기 위해 IPFS 문서의 해시를 이더리움 체인에 기록하고 싶다고 가정해 보겠습니다. 그러면 데이터 필드는 `data: web3.utils.toHex('IPFS 해시')`와 같이 보일 것입니다. 이제 누구나 체인을 쿼리하여 해당 문서가 언제 추가되었는지 볼 수 있습니다. +- 스마트 계약 트랜잭션: 체인에서 스마트 계약 코드를 실행합니다. 이 경우 데이터 필드에는 실행하려는 스마트 함수와 모든 매개변수가 포함되어야 합니다. + - 실용적인 예는 이 [Hello World 튜토리얼](https://docs.alchemyapi.io/alchemy/tutorials/hello-world-smart-contract#step-8-create-the-transaction)의 8단계를 확인하세요. + +### 8. `node sendTx.js`를 사용하여 코드 실행하기 {#run-the-code-using-node-sendtx-js} + +터미널이나 명령줄로 돌아가서 실행합니다. + +``` +node sendTx.js +``` + +### 9. 멤풀에서 트랜잭션 확인하기 {#see-your-transaction-in-the-mempool} + +Alchemy 대시보드에서 [멤풀 페이지](https://dashboard.alchemyapi.io/mempool)를 열고 생성한 앱으로 필터링하여 트랜잭션을 찾으세요. 여기에서 트랜잭션이 보류(pending) 상태에서 채굴(mined) 상태(성공한 경우) 또는 중단(dropped) 상태(실패한 경우)로 전환되는 것을 볼 수 있습니다. '채굴됨(mined)', '보류 중(pending)', '삭제됨(dropped)' 트랜잭션을 모두 포착하려면 '전체(All)'로 설정해야 합니다. 주소 `0x31b98d14007bdee637298086988a0bbd31184523`으로 전송된 트랜잭션을 찾아 트랜잭션을 검색할 수도 있습니다. + +트랜잭션을 찾은 후 세부 정보를 보려면 트랜잭션 해시(tx hash)를 선택하면 다음과 같은 화면으로 이동합니다. + +![멤풀 감시자 스크린샷](./mempool.png) + +거기에서 빨간색으로 동그라미 친 아이콘을 클릭하여 Etherscan에서 트랜잭션을 볼 수 있습니다! + +**야호! 방금 Alchemy를 사용하여 첫 이더리움 트랜잭션을 보냈습니다 🎉** + +_이 가이드에 대한 피드백이나 제안이 있으시면 Alchemy의 [디스코드](https://discord.gg/A39JVCM)에서 Elan에게 메시지를 보내주세요!_ + +_원문 게시처: [https://docs.alchemyapi.io/tutorials/sending-transactions-using-web3-and-alchemy](https://docs.alchemyapi.io/tutorials/sending-transactions-using-web3-and-alchemy)_ diff --git a/public/content/translations/ko/developers/tutorials/server-components/index.md b/public/content/translations/ko/developers/tutorials/server-components/index.md new file mode 100644 index 00000000000..212a41c100b --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/server-components/index.md @@ -0,0 +1,295 @@ +--- +title: "웹3 앱을 위한 서버 컴포넌트와 에이전트" +description: "이 튜토리얼을 읽고 나면, 블록체인의 이벤트를 수신하고 자체 트랜잭션으로 이에 따라 응답하는 TypeScript 서버를 작성할 수 있게 될 것입니다. 이를 통해 (서버가 단일 실패 지점이기 때문에) 중앙화된 애플리케이션을 작성할 수 있지만, 웹3 엔티티와 상호 작용할 수 있습니다. 동일한 기술을 사용하여 사람의 개입 없이 온체인 이벤트에 응답하는 에이전트를 작성할 수도 있습니다." + +author: Ori Pomerantz +lang: ko +tags: [ "에이전트", "서버", "오프체인" ] +skill: beginner +published: 2024-07-15 +--- + +## 소개 {#introduction} + +대부분의 경우 탈중앙화 앱은 서버를 사용하여 소프트웨어를 배포하지만, 실제 모든 상호 작용은 클라이언트(일반적으로 웹 브라우저)와 블록체인 사이에서 발생합니다. + +![웹 서버, 클라이언트, 블록체인 간의 일반적인 상호 작용](./fig-1.svg) + +그러나 애플리케이션이 독립적으로 실행되는 서버 컴포넌트를 가짐으로써 이점을 얻을 수 있는 경우가 있습니다. 이러한 서버는 트랜잭션을 발행함으로써 이벤트 및 API와 같은 다른 소스에서 오는 요청에 응답할 수 있습니다. + +![서버 추가 시의 상호 작용](./fig-2.svg) + +이러한 서버가 수행할 수 있는 몇 가지 가능한 작업이 있습니다. + +- 비밀 상태 보유자. 게임에서는 게임이 알고 있는 모든 정보를 플레이어가 이용할 수 없도록 하는 것이 종종 유용합니다. 하지만, _블록체인에는 비밀이 없습니다_. 블록체인에 있는 모든 정보는 누구나 쉽게 알아낼 수 있습니다. 따라서 게임 상태의 일부를 비밀로 유지하려면 다른 곳에 저장해야 합니다(그리고 해당 상태의 효과를 [영지식 증명](/zero-knowledge-proofs)을 사용하여 검증해야 할 수도 있습니다). + +- 중앙화된 오라클. 위험 부담이 충분히 낮은 경우, 온라인에서 정보를 읽어 체인에 게시하는 외부 서버를 [오라클](/developers/docs/oracles/)로 사용하기에 충분할 수 있습니다. + +- 에이전트. 블록체인에서는 그것을 활성화시키는 트랜잭션 없이는 아무 일도 일어나지 않습니다. 서버는 기회가 생겼을 때 사용자를 대신하여 [차익 거래](/developers/docs/mev/#mev-examples-dex-arbitrage)와 같은 작업을 수행할 수 있습니다. + +## 샘플 프로그램 {#sample-program} + +샘플 서버는 [github](https://github.com/qbzzt/20240715-server-component)에서 볼 수 있습니다. 이 서버는 Hardhat의 Greeter를 수정한 버전인 [이 계약](https://eth-holesky.blockscout.com/address/0xB8f6460Dc30c44401Be26B0d6eD250873d8a50A6?tab=contract_code)에서 오는 이벤트를 수신합니다. 인사가 변경되면, 서버가 이를 다시 원래대로 변경합니다. + +실행 방법: + +1. 리포지토리를 복제하세요. + + ```sh copy + git clone https://github.com/qbzzt/20240715-server-component.git + cd 20240715-server-component + ``` + +2. 필요한 패키지를 설치합니다. 아직 설치하지 않았다면, [Node를 먼저 설치하세요](https://nodejs.org/en/download/package-manager). + + ```sh copy + npm install + ``` + +3. Holesky 테스트넷에 ETH가 있는 계정의 개인 키를 지정하려면 `.env`를 편집하세요. Holesky에 ETH가 없다면 [이 파우셋을 사용하세요](https://holesky-faucet.pk910.de/). + + ```sh filename=".env" copy + PRIVATE_KEY=0x <여기에 개인 키를 입력하세요> + ``` + +4. 서버를 시작하세요. + + ```sh copy + npm start + ``` + +5. [블록 탐색기](https://eth-holesky.blockscout.com/address/0xB8f6460Dc30c44401Be26B0d6eD250873d8a50A6?tab=write_contract)로 이동하여 개인 키가 있는 주소와 다른 주소를 사용하여 인사를 수정하세요. 인사가 자동으로 다시 수정되는 것을 확인하세요. + +### 어떻게 작동하나요? {#how-it-works} + +서버 컴포넌트를 작성하는 방법을 이해하는 가장 쉬운 방법은 샘플을 한 줄씩 살펴보는 것입니다. + +#### `src/app.ts` {#src-app-ts} + +프로그램의 대부분은 [`src/app.ts`](https://github.com/qbzzt/20240715-server-component/blob/main/src/app.ts)에 포함되어 있습니다. + +##### 필수 객체 생성 + +```typescript +import { + createPublicClient, + createWalletClient, + getContract, + http, + Address, +} from "viem" +``` + +이는 우리가 필요로 하는 [Viem](https://viem.sh/) 엔티티, 함수 및 [`Address` 유형](https://viem.sh/docs/glossary/types#address)입니다. 이 서버는 JavaScript를 [강력한 형식](https://en.wikipedia.org/wiki/Strong_and_weak_typing)으로 만드는 확장 기능인 [TypeScript](https://www.typescriptlang.org/)로 작성되었습니다. + +```typescript +import { privateKeyToAccount } from "viem/accounts" +``` + +[이 함수](https://viem.sh/docs/accounts/privateKey)를 사용하면 개인 키에 해당하는 주소를 포함한 지갑 정보를 생성할 수 있습니다. + +```typescript +import { holesky } from "viem/chains" +``` + +Viem에서 블록체인을 사용하려면 해당 정의를 가져와야 합니다. 이 경우 [Holesky](https://github.com/eth-clients/holesky) 테스트 블록체인에 연결하려고 합니다. + +```typescript +// .env의 정의를 process.env에 추가하는 방법입니다. +import * as dotenv from "dotenv" +dotenv.config() +``` + +이것이 `.env`를 환경으로 읽어오는 방법입니다. 이는 개인 키에 필요합니다(나중에 설명). + +```typescript +const greeterAddress : Address = "0xB8f6460Dc30c44401Be26B0d6eD250873d8a50A6" +const greeterABI = [ + { + "inputs": [ + { + "internalType": "string", + "name": "_greeting", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + . + . + . + { + "inputs": [ + { + "internalType": "string", + "name": "_greeting", + "type": "string" + } + ], + "name": "setGreeting", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] as const +``` + +계약을 사용하려면 해당 주소와 [ABI](/glossary/#abi)가 필요합니다. 여기에서는 둘 다 제공합니다. + +JavaScript(및 TypeScript)에서는 상수에 새 값을 할당할 수는 없지만, 그 안에 저장된 객체는 수정할 _수_ 있습니다. `as const` 접미사를 사용하여 목록 자체가 상수이며 변경될 수 없음을 TypeScript에 알립니다. + +```typescript +const publicClient = createPublicClient({ + chain: holesky, + transport: http(), +}) +``` + +Viem [공개 클라이언트](https://viem.sh/docs/clients/public.html)를 생성합니다. 공개 클라이언트에는 연결된 개인 키가 없으므로 트랜잭션을 보낼 수 없습니다. [`view` 함수](https://www.tutorialspoint.com/solidity/solidity_view_functions.htm)를 호출하고, 계정 잔액을 읽는 등의 작업을 할 수 있습니다. + +```typescript +const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`) +``` + +환경 변수는 [`process.env`](https://www.totaltypescript.com/how-to-strongly-type-process-env)에서 사용할 수 있습니다. 하지만 TypeScript는 강력한 형식을 사용합니다. 환경 변수는 모든 문자열이거나 비어 있을 수 있으므로 환경 변수의 유형은 `string | undefined`입니다. 하지만 Viem에서 키는 `0x${string}`(`0x` 뒤에 문자열이 옴)으로 정의됩니다. 여기서는 `PRIVATE_KEY` 환경 변수가 해당 유형이 될 것이라고 TypeScript에 알립니다. 그렇지 않으면 런타임 오류가 발생합니다. + +그런 다음 [`privateKeyToAccount`](https://viem.sh/docs/accounts/privateKey) 함수는 이 개인 키를 사용하여 전체 계정 객체를 생성합니다. + +```typescript +const walletClient = createWalletClient({ + account, + chain: holesky, + transport: http(), +}) +``` + +다음으로 계정 객체를 사용하여 [지갑 클라이언트](https://viem.sh/docs/clients/wallet)를 만듭니다. 이 클라이언트에는 개인 키와 주소가 있으므로 트랜잭션을 보내는 데 사용할 수 있습니다. + +```typescript +const greeter = getContract({ + address: greeterAddress, + abi: greeterABI, + client: { public: publicClient, wallet: walletClient }, +}) +``` + +이제 모든 전제 조건이 갖추어졌으므로 마침내 [계약 인스턴스](https://viem.sh/docs/contract/getContract)를 만들 수 있습니다. 이 계약 인스턴스를 사용하여 온체인 계약과 통신합니다. + +##### 블록체인에서 읽기 + +```typescript +console.log(`Current greeting:`, await greeter.read.greet()) +``` + +읽기 전용인 계약 함수들([`view`](https://www.tutorialspoint.com/solidity/solidity_view_functions.htm) 및 [`pure`](https://www.tutorialspoint.com/solidity/solidity_pure_functions.htm))은 `read`에서 사용할 수 있습니다. 이 경우, 인사를 반환하는 [`greet`](https://eth-holesky.blockscout.com/address/0xB8f6460Dc30c44401Be26B0d6eD250873d8a50A6?tab=read_contract#cfae3217) 함수에 액세스하는 데 사용됩니다. + +JavaScript는 단일 스레드이므로, 장기 실행 프로세스를 시작할 때는 [비동기적으로 수행하도록 지정](https://eloquentjavascript.net/11_async.html#h-XvLsfAhtsE)해야 합니다. 읽기 전용 작업이라 할지라도 블록체인을 호출하려면 컴퓨터와 블록체인 노드 간의 왕복 통신이 필요합니다. 이것이 코드가 결과를 `await`해야 한다고 명시하는 이유입니다. + +이것이 어떻게 작동하는지 궁금하다면 [여기에서 읽어볼 수 있습니다](https://www.w3schools.com/js/js_promise.asp). 하지만 실질적으로 알아야 할 것은, 오랜 시간이 걸리는 작업을 시작하면 결과를 `await`해야 한다는 것과 이 작업을 수행하는 모든 함수는 `async`로 선언되어야 한다는 것뿐입니다. + +##### 트랜잭션 발행 + +```typescript +const setGreeting = async (greeting: string): Promise => { +``` + +이 함수는 인사를 변경하는 트랜잭션을 발행하기 위해 호출하는 함수입니다. 이는 긴 작업이므로 함수는 `async`로 선언됩니다. 내부 구현으로 인해, 모든 `async` 함수는 `Promise` 객체를 반환해야 합니다. 이 경우 `Promise`는 `Promise`에서 정확히 무엇이 반환될지 지정하지 않음을 의미합니다. + +```typescript +const txHash = await greeter.write.setGreeting([greeting]) +``` + +계약 인스턴스의 `write` 필드에는 블록체인 상태에 쓰는(트랜잭션을 보내야 하는) 모든 함수(예: [`setGreeting`](https://eth-holesky.blockscout.com/address/0xB8f6460Dc30c44401Be26B0d6eD250873d8a50A6?tab=write_contract#a4136862))가 있습니다. 매개변수가 있는 경우 목록으로 제공되며, 함수는 트랜잭션의 해시를 반환합니다. + +```typescript + console.log(`수정 작업 중, https://eth-holesky.blockscout.com/tx/${txHash} 참조`) + + return txHash +} +``` + +트랜잭션 해시를 (블록 탐색기에서 볼 수 있는 URL의 일부로) 보고하고 반환합니다. + +##### 이벤트에 응답하기 + +```typescript +greeter.watchEvent.SetGreeting({ +``` + +[`watchEvent` 함수](https://viem.sh/docs/actions/public/watchEvent)를 사용하면 이벤트가 발생했을 때 실행될 함수를 지정할 수 있습니다. 한 가지 유형의 이벤트(이 경우 `SetGreeting`)에만 관심이 있는 경우 이 구문을 사용하여 해당 이벤트 유형으로 제한할 수 있습니다. + +```typescript + onLogs: logs => { +``` + +`onLogs` 함수는 로그 항목이 있을 때 호출됩니다. 이더리움에서 '로그'와 '이벤트'는 보통 서로 바꾸어 사용할 수 있습니다. + +```typescript +console.log( + `주소 ${logs[0].args.sender}가 인사를 ${logs[0].args.greeting}(으)로 변경했습니다` +) +``` + +여러 이벤트가 있을 수 있지만, 단순화를 위해 첫 번째 이벤트에만 신경 씁니다. `logs[0].args`는 이벤트의 인자이며, 이 경우에는 `sender`와 `greeting`입니다. + +```typescript + if (logs[0].args.sender != account.address) + setGreeting(`${account.address}가 Hello!로 할 것을 고집합니다`) + } +}) +``` + +보낸 사람이 이 서버가 _아닌_ 경우, `setGreeting`을 사용하여 인사를 변경합니다. + +#### `package.json` {#package-json} + +[이 파일](https://github.com/qbzzt/20240715-server-component/blob/main/package.json)은 [Node.js](https://nodejs.org/en) 구성을 제어합니다. 이 문서에서는 중요한 정의만 설명합니다. + +```json +{ + "main": "dist/index.js", +``` + +이 정의는 실행할 JavaScript 파일을 지정합니다. + +```json + "scripts": { + "start": "tsc && node dist/app.js", + }, +``` + +스크립트는 다양한 애플리케이션 작업입니다. 이 경우, 유일한 스크립트는 `start`이며, 이는 서버를 컴파일한 다음 실행합니다. `tsc` 명령어는 `typescript` 패키지의 일부이며 TypeScript를 JavaScript로 컴파일합니다. 수동으로 실행하려면 `node_modules/.bin`에 있습니다. 두 번째 명령어는 서버를 실행합니다. + +```json + "type": "module", +``` + +JavaScript 노드 애플리케이션에는 여러 유형이 있습니다. `module` 유형을 사용하면 최상위 코드에 `await`을 사용할 수 있으며, 이는 느린(그리고 비동기적인) 작업을 수행할 때 중요합니다. + +```json + "devDependencies": { + "@types/node": "^20.14.2", + "typescript": "^5.4.5" + }, +``` + +이 패키지들은 개발에만 필요합니다. 여기서는 `typescript`가 필요하며, Node.js와 함께 사용하므로 `process`와 같은 노드 변수 및 객체에 대한 유형도 가져옵니다. [`^<버전>` 표기법](https://github.com/npm/node-semver?tab=readme-ov-file#caret-ranges-123-025-004)은 해당 버전 또는 브레이킹 체인지가 없는 상위 버전을 의미합니다. 버전 번호의 의미에 대한 자세한 내용은 [여기](https://semver.org)를 참조하세요. + +```json + "dependencies": { + "dotenv": "^16.4.5", + "viem": "2.14.1" + } +} +``` + +이는 `dist/app.js`를 실행할 때 런타임에 필요한 패키지입니다. + +## 결론 {#conclusion} + +여기서 우리가 만든 중앙화 서버는 사용자를 위한 에이전트 역할을 하는 제 역할을 합니다. 탈중앙화앱이 계속 작동하기를 원하고 가스를 기꺼이 지불하려는 다른 사람은 누구나 자신의 주소로 서버의 새 인스턴스를 실행할 수 있습니다. + +하지만 이는 중앙화된 서버의 조치를 쉽게 확인할 수 있는 경우에만 작동합니다. 중앙화된 서버가 비밀 상태 정보를 가지고 있거나 어려운 계산을 실행한다면, 이는 애플리케이션을 사용하기 위해 신뢰해야 하는 중앙화된 주체가 되며, 이는 바로 블록체인이 피하려는 것입니다. 향후 기사에서는 이 문제를 해결하기 위해 [영지식 증명](/zero-knowledge-proofs)을 사용하는 방법을 보여드릴 계획입니다. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). diff --git a/public/content/translations/ko/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/index.md b/public/content/translations/ko/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/index.md new file mode 100644 index 00000000000..abe4b6e9186 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/index.md @@ -0,0 +1,92 @@ +--- +title: "자바스크립트에서 이더리움 블록체인을 사용하기 위한 web3.js 설정하기" +description: "자바스크립트 애플리케이션에서 이더리움 블록체인과 상호작용하기 위해 web3.js 라이브러리를 설정하고 구성하는 방법을 알아보세요." +author: "jdourlens" +tags: [ "web3.js", "JavaScript" ] +skill: beginner +lang: ko +published: 2020-04-11 +source: EthereumDev +sourceUrl: https://ethereumdev.io/setup-web3js-to-use-the-ethereum-blockchain-in-javascript/ +address: "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE" +--- + +이 튜토리얼에서는 이더리움 블록체인과 상호작용하기 위해 [web3.js](https://web3js.readthedocs.io/)를 시작하는 방법을 알아봅니다. Web3.js는 프론트엔드와 백엔드 모두에서 블록체인의 데이터를 읽거나, 트랜잭션을 만들거나, 스마트 계약을 배포하는 데 사용할 수 있습니다. + +첫 번째 단계는 프로젝트에 web3.js를 포함하는 것입니다. 웹페이지에서 사용하려면 JSDeliver와 같은 CDN을 사용하여 라이브러리를 직접 가져올 수 있습니다. + +```html + +``` + +백엔드 또는 빌드 시스템을 사용하는 프론트엔드 프로젝트에서 사용하기 위해 라이브러리를 설치하려는 경우, npm으로 설치할 수 있습니다: + +```bash +npm install web3 --save +``` + +그 다음, Web3.js를 Node.js 스크립트나 Browserify 프론트엔드 프로젝트로 가져오려면 다음 자바스크립트 코드를 사용할 수 있습니다: + +```js +const Web3 = require("web3") +``` + +이제 프로젝트에 라이브러리를 포함했으니 초기화해야 합니다. 프로젝트가 블록체인과 통신할 수 있어야 합니다. 대부분의 이더리움 라이브러리는 RPC 호출을 통해 [노드](/developers/docs/nodes-and-clients/)와 통신합니다. Web3 공급자를 초기화하려면 공급자의 URL을 생성자에 전달하여 Web3 인스턴스를 생성합니다. 컴퓨터에서 실행 중인 노드나 [ganache 인스턴스](https://ethereumdev.io/testing-your-smart-contract-with-existing-protocols-ganache-fork/)가 있다면 코드는 다음과 같을 것입니다. + +```js +const web3 = new Web3("http://localhost:8545") +``` + +호스팅된 노드에 직접 액세스하려면 [서비스형 노드](/developers/docs/nodes-and-clients/nodes-as-a-service)에서 옵션을 찾을 수 있습니다. + +```js +const web3 = new Web3("https://cloudflare-eth.com") +``` + +Web3 인스턴스가 올바르게 구성되었는지 테스트하기 위해 `getBlockNumber` 함수를 사용하여 최신 블록 번호를 가져오겠습니다. 이 함수는 콜백을 매개변수로 받아 블록 번호를 정수로 반환합니다. + +```js +var Web3 = require("web3") +const web3 = new Web3("https://cloudflare-eth.com") + +web3.eth.getBlockNumber(function (error, result) { + console.log(result) +}) +``` + +이 프로그램을 실행하면 블록체인의 맨 위인 최신 블록 번호가 출력됩니다. 코드에서 콜백 중첩을 피하기 위해 `await/async` 함수 호출을 사용할 수도 있습니다. + +```js +async function getBlockNumber() { + const latestBlockNumber = await web3.eth.getBlockNumber() + console.log(latestBlockNumber) + return latestBlockNumber +} + +getBlockNumber() +``` + +[web3.js 공식 문서](https://docs.web3js.org/)에서 Web3 인스턴스에 사용 가능한 모든 함수를 확인할 수 있습니다. + +대부분의 Web3 라이브러리는 비동기식입니다. 이는 라이브러리가 백그라운드에서 노드에 JSON-RPC 호출을 하고, 노드가 그 결과를 다시 보내주기 때문입니다. + + + +브라우저에서 작업하는 경우 일부 지갑은 Web3 인스턴스를 직접 주입하며, 특히 사용자의 이더리움 주소와 상호 작용하여 트랜잭션을 생성하려는 경우 가능하면 항상 이 인스턴스를 사용하는 것이 좋습니다. + +다음은 MetaMask 지갑을 사용할 수 있는지 감지하고, 가능한 경우 활성화를 시도하는 코드 스니펫입니다. 이를 통해 나중에 사용자의 잔액을 읽고 이더리움 블록체인에서 사용자가 트랜잭션을 검증하도록 할 수 있습니다: + +```js +if (window.ethereum != null) { + state.web3 = new Web3(window.ethereum) + try { + // 필요한 경우 계정 접근 요청 + await window.ethereum.enable() + // 이제 계정이 노출됨 + } catch (error) { + // 사용자가 계정 접근을 거부함... + } +} +``` + +[Ethers.js](https://docs.ethers.io/)와 같은 web3.js의 대안도 존재하며 일반적으로 사용됩니다. 다음 튜토리얼에서는 [블록체인에서 새로 들어오는 블록을 쉽게 수신하고 그 내용을 확인하는 방법](https://ethereumdev.io/listening-to-new-transactions-happening-on-the-blockchain/)을 알아볼 것입니다. diff --git a/public/content/translations/ko/developers/tutorials/short-abi/index.md b/public/content/translations/ko/developers/tutorials/short-abi/index.md new file mode 100644 index 00000000000..cc69a8f212c --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/short-abi/index.md @@ -0,0 +1,578 @@ +--- +title: "Calldata 최적화를 위한 짧은 ABI" +description: "낙관적 롤업을 위한 스마트 계약 최적화" +author: Ori Pomerantz +lang: ko +tags: [ "레이어 2" ] +skill: intermediate +published: 2022-04-01 +--- + +## 소개 {#introduction} + +이 글에서는 [낙관적 롤업](/developers/docs/scaling/optimistic-rollups)과 해당 롤업에서의 트랜잭션 비용, 그리고 비용 구조의 차이점으로 인해 이더리움 메인넷과는 다른 것을 최적화해야 하는 이유를 알아봅니다. +또한 이 최적화를 구현하는 방법도 알아봅니다. + +### 전체 공개 {#full-disclosure} + +저는 [Optimism](https://www.optimism.io/) 정직원이므로, 이 글의 예시는 Optimism에서 실행됩니다. +하지만 여기서 설명하는 기법은 다른 롤업에서도 동일하게 작동합니다. + +### 용어 {#terminology} + +롤업을 논할 때, '레이어 1'(L1)이라는 용어는 운영 중인 이더리움 네트워크인 메인넷을 지칭하는 데 사용됩니다. +'레이어 2'(L2)라는 용어는 L1에 보안을 의존하지만 대부분의 처리를 오프체인에서 수행하는 롤업 또는 기타 시스템을 지칭하는 데 사용됩니다. + +## L2 트랜잭션 비용을 어떻게 더 줄일 수 있을까요? {#how-can-we-further-reduce-the-cost-of-L2-transactions} + +[낙관적 롤업](/developers/docs/scaling/optimistic-rollups)은 모든 과거 트랜잭션 기록을 보존해야 합니다. 그래야 누구나 이를 검토하고 현재 상태가 올바른지 확인할 수 있습니다. +이더리움 메인넷에 데이터를 저장하는 가장 저렴한 방법은 calldata로 작성하는 것입니다. +이 솔루션은 [Optimism](https://help.optimism.io/hc/en-us/articles/4413163242779-What-is-a-rollup-)과 [Arbitrum](https://developer.offchainlabs.com/docs/rollup_basics#intro-to-rollups) 모두에서 채택되었습니다. + +### L2 트랜잭션 비용 {#cost-of-l2-transactions} + +L2 트랜잭션 비용은 다음 두 가지 요소로 구성됩니다. + +1. L2 처리 비용(일반적으로 매우 저렴함) +2. L1 저장 비용(메인넷 가스 비용과 연동됨) + +이 글을 쓰는 시점에서 Optimism의 L2 가스 비용은 0.001 [Gwei](/developers/docs/gas/#pre-london)입니다. +반면에 L1 가스 비용은 약 40gwei입니다. +[여기에서 현재 가격을 확인할 수 있습니다](https://public-grafana.optimism.io/d/9hkhMxn7z/public-dashboard?orgId=1&refresh=5m). + +calldata 1바이트의 비용은 값이 0인 경우 4 가스, 다른 값인 경우 16 가스입니다. +EVM에서 가장 비싼 작업 중 하나는 저장 공간에 쓰는 것입니다. +L2 저장 공간에 32바이트 워드를 쓰는 최대 비용은 22,100 가스입니다. 현재 이는 22.1 gwei입니다. +따라서 calldata에서 0바이트 하나만 절약할 수 있다면, 저장 공간에 약 200바이트를 쓰고도 여전히 이득을 볼 수 있습니다. + +### ABI {#the-abi} + +대부분의 트랜잭션은 외부 소유 계정의 컨트랙트를 액세스한다. +대부분의 계약은 솔리디티로 작성되며 [애플리케이션 바이너리 인터페이스(ABI)](https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding)에 따라 데이터 필드를 해석합니다. + +하지만 ABI는 L1을 위해 설계되었습니다. L1에서는 calldata 1바이트 비용이 약 4번의 산술 연산과 같지만, L2에서는 1,000번 이상의 산술 연산보다 비용이 더 많이 듭니다. +calldata는 다음과 같이 나뉩니다. + +| 섹션 | 길이 | 바이트 | 낭비된 바이트 | 낭비된 가스 | 필요한 바이트 | 필요한 가스 | +| ------ | -: | ----: | ------: | -----: | ------: | -----: | +| 함수 선택자 | 4 | 0-3 | 3 | 48 | 1 | 16 | +| 0 | 12 | 4-15 | 12 | 48 | 0 | 0 | +| 목적지 주소 | 20 | 16-35 | 0 | 0 | 20 | 320 | +| 금액 | 32 | 36-67 | 17 | 64 | 15 | 240 | +| 합계 | 68 | | | 160 | | 576 | + +설명: + +- **함수 선택자**: 계약에 256개 미만의 함수가 있으므로, 단일 바이트로 구분할 수 있습니다. + 이 바이트들은 일반적으로 0이 아니므로 [16 가스가 소모됩니다](https://eips.ethereum.org/EIPS/eip-2028). +- **0**: 이 바이트들은 항상 0인데, 20바이트 주소를 담는 데 32바이트 워드가 필요하지 않기 때문입니다. + 0을 담는 바이트는 4 가스가 소모됩니다([옐로 페이퍼](https://ethereum.github.io/yellowpaper/paper.pdf), 부록 G, 27페이지, `G``txdatazero` 값 참조). +- **금액**: 이 계약에서 `decimals`가 18(일반적인 값)이고 우리가 전송할 토큰의 최대량이 1018이라고 가정하면, 최대 금액은 1036이 됩니다. + 25615 > 1036이므로 15바이트면 충분합니다. + +L1에서 160 가스가 낭비되는 것은 보통 무시할 수 있는 수준입니다. 트랜잭션에는 최소 [21,000 가스](https://yakkomajuri.medium.com/blockchain-definition-of-the-week-ethereum-gas-2f976af774ed)가 소모되므로 0.8%가 추가되는 것은 중요하지 않습니다. +하지만 L2에서는 상황이 다릅니다. 트랜잭션 비용의 거의 전부는 L1에 쓰는 데서 발생합니다. +트랜잭션 calldata 외에도 109바이트의 트랜잭션 헤더(목적지 주소, 서명 등)가 있습니다. +따라서 총비용은 `109*16+576+160=2480`이며, 이 중 약 6.5%를 낭비하고 있습니다. + +## 목적지를 제어할 수 없을 때 비용 절감하기 {#reducing-costs-when-you-dont-control-the-destination} + +목적지 계약을 제어할 수 없다고 가정하더라도 여전히 [이 솔루션](https://github.com/qbzzt/ethereum.org-20220330-shortABI)과 유사한 솔루션을 사용할 수 있습니다. +관련 파일을 살펴보겠습니다. + +### Token.sol {#token-sol} + +[이것이 목적지 계약입니다](https://github.com/qbzzt/ethereum.org-20220330-shortABI/blob/master/contracts/Token.sol). +이것은 표준 ERC-20 계약이며, 한 가지 추가 기능이 있습니다. +이 `faucet` 함수는 모든 사용자가 사용할 토큰을 얻을 수 있게 합니다. +프로덕션 ERC-20 계약에서는 쓸모없겠지만, 테스트를 용이하게 하기 위해 존재하는 ERC-20의 경우 개발을 더 쉽게 만들어 줍니다. + +```solidity + /** + * @dev 호출자에게 1,000개의 토큰을 제공합니다 + */ + function faucet() external { + _mint(msg.sender, 1000); + } // function faucet +``` + +### CalldataInterpreter.sol {#calldatainterpreter-sol} + +[이 계약은 트랜잭션이 더 짧은 calldata로 호출하도록 되어 있는 계약입니다](https://github.com/qbzzt/ethereum.org-20220330-shortABI/blob/master/contracts/CalldataInterpreter.sol). +한 줄씩 살펴보겠습니다. + +```solidity +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + + +import { OrisUselessToken } from "./Token.sol"; +``` + +호출 방법을 알기 위해 토큰 함수가 필요합니다. + +```solidity +contract CalldataInterpreter { + + OrisUselessToken public immutable token; +``` + +프록시 역할을 할 토큰의 주소입니다. + +```solidity + + /** + * @dev 토큰 주소를 지정합니다 + * @param tokenAddr_ ERC-20 계약 주소 + */ + constructor( + address tokenAddr_ + ) { + token = OrisUselessToken(tokenAddr_); + } // constructor +``` + +토큰 주소는 우리가 지정해야 하는 유일한 매개변수입니다. + +```solidity + function calldataVal(uint startByte, uint length) + private pure returns (uint) { +``` + +calldata에서 값을 읽습니다. + +```solidity + uint _retVal;\n\n require(length < 0x21,\n \"calldataVal 길이 제한은 32바이트입니다\");\n\n require(length + startByte <= msg.data.length,\n \"calldataVal calldatasize를 초과하여 읽으려고 합니다\"); +``` + +단일 32바이트(256비트) 워드를 메모리에 로드한 다음, 원하는 필드에 속하지 않는 바이트를 제거할 것입니다. +이 알고리즘은 32바이트보다 긴 값에는 작동하지 않으며, 물론 calldata의 끝을 넘어 읽을 수도 없습니다. +L1에서는 가스를 절약하기 위해 이 테스트를 건너뛰어야 할 수도 있지만, L2에서는 가스가 매우 저렴하므로 우리가 생각할 수 있는 모든 온전성 검사를 사용할 수 있습니다. + +```solidity + assembly { + _retVal := calldataload(startByte) + } +``` + +아래에서 볼 수 있듯이, `fallback()`에 대한 호출에서 데이터를 복사할 수도 있지만, EVM의 어셈블리 언어인 [Yul](https://docs.soliditylang.org/en/v0.8.12/yul.html)을 사용하는 것이 더 쉽습니다. + +여기서는 [`CALLDATALOAD` opcode](https://www.evm.codes/#35)를 사용하여 `startByte`에서 `startByte+31` 바이트를 스택으로 읽습니다. +일반적으로 Yul에서 opcode의 구문은 `(<첫 번째 스택 값, 있는 경우>,<두 번째 스택 값, 있는 경우>...)`입니다. + +```solidity + + _retVal = _retVal >> (256-length*8); +``` + +가장 중요한 `length` 바이트만 필드의 일부이므로 [오른쪽 시프트](https://en.wikipedia.org/wiki/Logical_shift)를 사용하여 다른 값을 제거합니다. +이것은 값을 필드의 오른쪽으로 이동시켜 값 자체가 256거듭제곱을 곱한 값이 아닌 값 자체가 되도록 하는 추가적인 이점이 있습니다. + +```solidity + + return _retVal; + } + + + fallback() external { +``` + +솔리디티 계약에 대한 호출이 함수 서명과 일치하지 않으면 [`fallback()` 함수](https://docs.soliditylang.org/en/v0.8.12/contracts.html#fallback-function)를 호출합니다(있는 경우). +`CalldataInterpreter`의 경우 다른 `external` 또는 `public` 함수가 없기 때문에 _모든_ 호출이 여기에 도달합니다. + +```solidity + uint _func; + + _func = calldataVal(0, 1); +``` + +calldata의 첫 번째 바이트를 읽습니다. 이 바이트는 함수를 알려줍니다. +여기서 함수를 사용할 수 없는 두 가지 이유가 있습니다. + +1. `pure` 또는 `view`인 함수는 상태를 변경하지 않고 가스를 소모하지 않습니다(오프체인에서 호출될 때). + 가스 비용을 줄이려는 시도는 의미가 없습니다. +2. [`msg.sender`](https://docs.soliditylang.org/en/v0.8.12/units-and-global-variables.html#block-and-transaction-properties)에 의존하는 함수. + `msg.sender`의 값은 호출자가 아닌 `CalldataInterpreter`의 주소가 됩니다. + +안타깝게도 [ERC-20 사양](https://eips.ethereum.org/EIPS/eip-20)을 살펴보면 `transfer`라는 함수 하나만 남습니다. +이것은 `transfer`(`transferFrom`을 호출할 수 있으므로)와 `faucet`(토큰을 우리를 호출한 사람에게 다시 전송할 수 있으므로) 두 개의 함수만 남깁니다. + +```solidity + + // calldata의 정보를 사용하여 + // 토큰의 상태 변경 메서드를 호출합니다 + + // faucet + if (_func == 1) { +``` + +매개변수가 없는 `faucet()` 호출입니다. + +```solidity + token.faucet(); + token.transfer(msg.sender, + token.balanceOf(address(this))); + } +``` + +`token.faucet()`을 호출하면 토큰을 얻습니다. 그러나 프록시 계약으로서 우리는 토큰이 **필요하지** 않습니다. +우리를 호출한 EOA(외부 소유 계정) 또는 계약에는 필요합니다. +그래서 우리는 모든 토큰을 우리를 호출한 사람에게 전송합니다. + +```solidity + // transfer(허용량이 있다고 가정) + if (_func == 2) { +``` + +토큰을 전송하려면 목적지 주소와 금액이라는 두 개의 매개변수가 필요합니다. + +```solidity + token.transferFrom( + msg.sender, +``` + +호출자가 소유한 토큰만 전송하도록 허용합니다 + +```solidity + address(uint160(calldataVal(1, 20))), +``` + +목적지 주소는 바이트 #1에서 시작합니다(바이트 #0은 함수임). +주소이므로 길이는 20바이트입니다. + +```solidity + calldataVal(21, 2) +``` + +이 특정 계약의 경우, 누구나 전송하고자 하는 최대 토큰 수가 2바이트(65536 미만)에 들어간다고 가정합니다. + +```solidity + ); + } +``` + +전체적으로 전송에는 35바이트의 calldata가 필요합니다. + +| 섹션 | 길이 | 바이트 | +| ------ | -: | ----: | +| 함수 선택자 | 1 | 0 | +| 목적지 주소 | 32 | 1-32 | +| 금액 | 2 | 33-34 | + +```solidity + } // fallback + +} // contract CalldataInterpreter +``` + +### test.js {#test-js} + +[이 JavaScript 단위 테스트](https://github.com/qbzzt/ethereum.org-20220330-shortABI/blob/master/test/test.js)는 이 메커니즘을 사용하는 방법(그리고 올바르게 작동하는지 확인하는 방법)을 보여줍니다. +저는 여러분이 [chai](https://www.chaijs.com/)와 [ethers](https://docs.ethers.io/v5/)를 이해한다고 가정하고 계약에 특별히 적용되는 부분만 설명하겠습니다. + +```js +const { expect } = require("chai"); + +describe("CalldataInterpreter", function () { + it("토큰을 사용할 수 있도록 해야 합니다", async function () { + const Token = await ethers.getContractFactory("OrisUselessToken") + const token = await Token.deploy() + await token.deployed() + console.log("Token addr:", token.address) + + const Cdi = await ethers.getContractFactory("CalldataInterpreter") + const cdi = await Cdi.deploy(token.address) + await cdi.deployed() + console.log("CalldataInterpreter addr:", cdi.address) + + const signer = await ethers.getSigner() +``` + +두 계약을 모두 배포하여 시작합니다. + +```javascript + // 가지고 놀 토큰 가져오기 + const faucetTx = { +``` + +ABI를 따르지 않기 때문에 일반적으로 사용하는 고수준 함수(예: `token.faucet()`)를 사용하여 트랜잭션을 생성할 수 없습니다. +대신 트랜잭션을 직접 만들고 전송해야 합니다. + +```javascript + to: cdi.address, + data: "0x01" +``` + +거래를 위해 제공해야 하는 두 가지 매개변수가 있습니다. + +1. `to`, 목적지 주소입니다. + 이것은 calldata 인터프리터 계약입니다. +2. `data`, 보낼 calldata입니다. + 수도꼭지 호출의 경우 데이터는 단일 바이트인 `0x01`입니다. + +```javascript + + } + await (await signer.sendTransaction(faucetTx)).wait() +``` + +이미 목적지(`faucetTx.to`)를 지정했고 트랜잭션에 서명이 필요하기 때문에 [서명자의 `sendTransaction` 메서드](https://docs.ethers.io/v5/api/signer/#Signer-sendTransaction)를 호출합니다. + +```javascript +// faucet이 토큰을 올바르게 제공하는지 확인 +expect(await token.balanceOf(signer.address)).to.equal(1000) +``` + +여기서 잔액을 확인합니다. +`view` 함수에 대한 가스를 절약할 필요가 없으므로 정상적으로 실행합니다. + +```javascript +// CDI에 허용량 부여(승인은 프록시 처리 불가) +const approveTX = await token.approve(cdi.address, 10000) +await approveTX.wait() +expect(await token.allowance(signer.address, cdi.address)).to.equal(10000) +``` + +전송을 수행할 수 있도록 calldata 인터프리터에 허용량을 부여합니다. + +```javascript +// 토큰 전송 +const destAddr = "0xf5a6ead936fb47f342bb63e676479bddf26ebe1d" +const transferTx = { + to: cdi.address, + data: "0x02" + destAddr.slice(2, 42) + "0100", +} +``` + +전송 트랜잭션을 생성합니다. 첫 번째 바이트는 "0x02"이고 그 뒤에 목적지 주소, 마지막으로 금액(0x0100, 10진수로 256)이 옵니다. + +```javascript + await (await signer.sendTransaction(transferTx)).wait() + + // 256개의 토큰이 더 적은지 확인 + expect (await token.balanceOf(signer.address)).to.equal(1000-256) + + // 그리고 목적지에서 토큰을 받았는지 확인 + expect (await token.balanceOf(destAddr)).to.equal(256) + }) // it +}) // describe +``` + +## 목적지 계약을 제어할 때 비용 절감하기 {#reducing-the-cost-when-you-do-control-the-destination-contract} + +목적지 계약을 제어할 수 있는 경우 calldata 인터프리터를 신뢰하기 때문에 `msg.sender` 검사를 우회하는 함수를 생성할 수 있습니다. +[여기에서 `control-contract` 브랜치에서 이것이 어떻게 작동하는지에 대한 예시를 볼 수 있습니다](https://github.com/qbzzt/ethereum.org-20220330-shortABI/tree/control-contract). + +계약이 외부 트랜잭션에만 응답하는 경우 계약 하나만으로도 충분할 수 있습니다. +그러나 그렇게 하면 [구성 가능성](/developers/docs/smart-contracts/composability/)이 깨질 수 있습니다. +일반적인 ERC-20 호출에 응답하는 계약과 짧은 호출 데이터가 있는 트랜잭션에 응답하는 다른 계약을 사용하는 것이 훨씬 좋습니다. + +### Token.sol {#token-sol-2} + +이 예제에서는 `Token.sol`을 수정할 수 있습니다. +이를 통해 프록시만 호출할 수 있는 여러 함수를 가질 수 있습니다. +다음은 새로운 부분입니다. + +```solidity + // CalldataInterpreter 주소를 지정할 수 있는 유일한 주소 + address owner; + + // CalldataInterpreter 주소 + address proxy = address(0); +``` + +ERC-20 계약은 승인된 프록시의 ID를 알아야 합니다. +하지만 아직 값을 모르기 때문에 생성자에서 이 변수를 설정할 수 없습니다. +프록시가 생성자에서 토큰 주소를 기대하기 때문에 이 계약이 먼저 인스턴스화됩니다. + +```solidity + /** + * @dev ERC20 생성자를 호출합니다. + */ + constructor( + ) ERC20("Oris useless token-2", "OUT-2") { + owner = msg.sender; + } +``` + +생성자의 주소(`owner`라고 함)는 프록시를 설정할 수 있는 유일한 주소이기 때문에 여기에 저장됩니다. + +```solidity + /** + * @dev 프록시(CalldataInterpreter)의 주소를 설정합니다. + * 소유자만 한 번 호출할 수 있습니다 + */ + function setProxy(address _proxy) external { + require(msg.sender == owner, "소유자만 호출할 수 있습니다"); + require(proxy == address(0), "프록시가 이미 설정되었습니다"); + + proxy = _proxy; + } // function setProxy +``` + +프록시는 보안 검사를 우회할 수 있기 때문에 특권 액세스 권한을 가집니다. +프록시를 신뢰할 수 있도록 `owner`만 이 함수를 한 번만 호출하도록 허용합니다. +`proxy`가 실제 값(0이 아님)을 가지면 해당 값은 변경할 수 없으므로 소유자가 악의적으로 변하거나 니모닉이 공개되더라도 우리는 여전히 안전합니다. + +```solidity + /** + * @dev 일부 함수는 프록시에서만 호출할 수 있습니다. + */ + modifier onlyProxy { +``` + +이것은 다른 함수의 작동 방식을 수정하는 [`제어자` 함수](https://www.tutorialspoint.com/solidity/solidity_function_modifiers.htm)입니다. + +```solidity + require(msg.sender == proxy); +``` + +먼저 프록시에서 호출했는지 확인하고 다른 사람이 호출하지 않았는지 확인합니다. +그렇지 않으면 `revert`합니다. + +```solidity + _; + } +``` + +그렇다면 수정하는 함수를 실행합니다. + +```solidity + /* 프록시가 실제로 계정을 프록시할 수 있도록 하는 함수 */ + + function transferProxy(address from, address to, uint256 amount) + public virtual onlyProxy() returns (bool) + { + _transfer(from, to, amount); + return true; + } + + function approveProxy(address from, address spender, uint256 amount) + public virtual onlyProxy() returns (bool) + { + _approve(from, spender, amount); + return true; + } + + function transferFromProxy( + address spender, + address from, + address to, + uint256 amount + ) public virtual onlyProxy() returns (bool) + { + _spendAllowance(from, spender, amount); + _transfer(from, to, amount); + return true; + } +``` + +이 세 가지 작업은 일반적으로 토큰을 전송하거나 허용량을 승인하는 주체로부터 메시지가 직접 와야 합니다. +여기에는 이러한 작업의 프록시 버전이 있습니다. + +1. `onlyProxy()`에 의해 수정되어 다른 사람이 제어할 수 없습니다. +2. 일반적으로 `msg.sender`가 될 주소를 추가 매개변수로 가져옵니다. + +### CalldataInterpreter.sol {#calldatainterpreter-sol-2} + +calldata 인터프리터는 프록시된 함수가 `msg.sender` 매개변수를 수신하고 `transfer`에 대한 허용량이 필요하지 않다는 점을 제외하고 위의 것과 거의 동일합니다. + +```solidity + // transfer (허용량 필요 없음) + if (_func == 2) { + token.transferProxy( + msg.sender, + address(uint160(calldataVal(1, 20))), + calldataVal(21, 2) + ); + } + + // approve + if (_func == 3) { + token.approveProxy( + msg.sender, + address(uint160(calldataVal(1, 20))), + calldataVal(21, 2) + ); + } + + // transferFrom + if (_func == 4) { + token.transferFromProxy( + msg.sender, + address(uint160(calldataVal( 1, 20))), + address(uint160(calldataVal(21, 20))), + calldataVal(41, 2) + ); + } +``` + +### Test.js {#test-js-2} + +이전 테스트 코드와 이 코드 사이에 몇 가지 차이점이 있습니다. + +```js +const Cdi = await ethers.getContractFactory("CalldataInterpreter") +const cdi = await Cdi.deploy(token.address) +await cdi.deployed() +await token.setProxy(cdi.address) +``` + +ERC-20 계약이 어떤 프록시를 신뢰할 지 알 수 있도록 해야합니다. + +```js +console.log("CalldataInterpreter addr:", cdi.address) + +// 허용량을 확인하기 위해 두 명의 서명자가 필요합니다 +const signers = await ethers.getSigners() +const signer = signers[0] +const poorSigner = signers[1] +``` + +`approve()` 및 `transferFrom()`을 확인하려면 두 번째 서명자가 필요합니다. +이 계정은 우리의 토큰을 받지 않기 때문에 `poorSigner`라고 부릅니다(물론 ETH는 보유해야 합니다). + +```js +// 토큰 전송 +const destAddr = "0xf5a6ead936fb47f342bb63e676479bddf26ebe1d" +const transferTx = { + to: cdi.address, + data: "0x02" + destAddr.slice(2, 42) + "0100", +} +await (await signer.sendTransaction(transferTx)).wait() +``` + +ERC-20 계약이 프록시(`cdi`)를 신뢰하기 때문에 전송을 릴레이하는 데 허용량이 필요하지 않습니다. + +```js +// approval 및 transferFrom +const approveTx = { + to: cdi.address, + data: "0x03" + poorSigner.address.slice(2, 42) + "00FF", +} +await (await signer.sendTransaction(approveTx)).wait() + +const destAddr2 = "0xE1165C689C0c3e9642cA7606F5287e708d846206" + +const transferFromTx = { + to: cdi.address, + data: "0x04" + signer.address.slice(2, 42) + destAddr2.slice(2, 42) + "00FF", +} +await (await poorSigner.sendTransaction(transferFromTx)).wait() + +// approve / transferFrom 콤보가 올바르게 수행되었는지 확인 +expect(await token.balanceOf(destAddr2)).to.equal(255) +``` + +새로운 두 함수를 테스트해 보세요. +`transferFromTx`에는 허용량을 제공하는 사람과 받는 사람의 두 가지 주소 매개변수가 필요합니다. + +## 결론 {#conclusion} + +[Optimism](https://medium.com/ethereum-optimism/the-road-to-sub-dollar-transactions-part-2-compression-edition-6bb2890e3e92)과 [Arbitrum](https://developer.offchainlabs.com/docs/special_features) 모두 L1에 기록되는 calldata의 크기를 줄여 트랜잭션 비용을 절감하는 방법을 찾고 있습니다. +그러나 일반적인 솔루션을 찾는 인프라 제공업체로서 우리의 능력은 제한적입니다. +dapp 개발자로서 여러분은 애플리케이션별 지식을 가지고 있으므로 일반적인 솔루션보다 훨씬 더 잘 calldata를 최적화할 수 있습니다. +이 글이 여러분의 필요에 맞는 이상적인 해결책을 찾는 데 도움이 되기를 바랍니다. + +[여기서 제 작업에 대한 자세한 내용을 확인하세요](https://cryptodocguy.pro/). + diff --git a/public/content/translations/ko/developers/tutorials/smart-contract-security-guidelines/index.md b/public/content/translations/ko/developers/tutorials/smart-contract-security-guidelines/index.md new file mode 100644 index 00000000000..dc66000e6af --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/smart-contract-security-guidelines/index.md @@ -0,0 +1,91 @@ +--- +title: "스마트 계약 보안 가이드라인" +description: "탈중앙화앱을 빌드할 때 고려해야 할 보안 가이드라인 체크리스트" +author: "Trailofbits" +tags: [ "Solidity", "스마트 컨트랙트", "보안" ] +skill: intermediate +lang: ko +published: 2020-09-06 +source: Building secure contracts +sourceUrl: https://github.com/crytic/building-secure-contracts/blob/master/development-guidelines/guidelines.md +--- + +더 안전한 스마트 계약을 구축하려면 다음 강력 권장 사항을 따르세요. + +## 설계 가이드라인 {#design-guidelines} + +코드를 한 줄이라도 작성하기 전에 계약 설계를 미리 논의해야 합니다. + +### 개발문서 및 사양 {#documentation-and-specifications} + +개발문서는 다양한 수준으로 작성할 수 있으며 계약을 구현하는 동안 업데이트해야 합니다. + +- 시스템에 대한 평이한 영어 설명은 계약의 기능과 코드베이스에 대한 가정을 설명합니다. +- 스키마 및 아키텍처 다이어그램은 계약 상호 작용 및 시스템의 상태 머신을 포함합니다. [Slither printers](https://github.com/crytic/slither/wiki/Printer-documentation)는 이러한 스키마를 생성하는 데 도움이 될 수 있습니다. +- **철저한 코드 개발문서**, Solidity에는 [Natspec 형식](https://docs.soliditylang.org/en/develop/natspec-format.html)을 사용할 수 있습니다. + +### 온체인 대 오프체인 계산 {#onchain-vs-offchain-computation} + +- **가능한 한 많은 코드를 오프체인에 보관하세요.** 온체인 레이어를 작게 유지하세요. 온체인 검증이 간단하도록 오프체인 코드로 데이터를 사전 처리합니다. 정렬된 목록이 필요하신가요? 목록을 오프체인에서 정렬한 다음 온체인에서 순서만 확인합니다. + +### 업그레이드 가능성 {#upgradeability} + +[블로그 게시물](https://blog.trailofbits.com/2018/09/05/contract-upgrade-anti-patterns/)에서 다양한 업그레이드 가능성 솔루션에 대해 논의했습니다. 코드를 작성하기 전에 업그레이드 가능성 지원 여부를 신중하게 선택하세요. 이 결정은 코드 구조에 영향을 미칩니다. 일반적으로 다음을 권장합니다. + +- **업그레이드 가능성보다 [계약 마이그레이션](https://blog.trailofbits.com/2018/10/29/how-contract-migration-works/)을 선호합니다.** 마이그레이션 시스템은 업그레이드 가능한 시스템과 동일한 장점을 많이 가지고 있으며 단점은 없습니다. +- **delegatecallproxy 패턴보다 데이터 분리 패턴을 사용합니다.** 프로젝트에 명확한 추상화 분리가 있는 경우 데이터 분리를 사용한 업그레이드 가능성은 몇 가지 조정만 필요합니다. delegatecallproxy는 EVM 전문 지식이 필요하며 오류가 발생하기 쉽습니다. +- **배포 전에 마이그레이션/업그레이드 절차를 문서화하세요.** 가이드라인 없이 스트레스 상황에서 대응해야 한다면 실수를 하게 될 것입니다. 미리 따라야 할 절차를 작성하세요. 여기에는 다음이 포함되어야 합니다. + - 새 계약을 시작하는 호출 + - 키가 저장된 위치와 액세스 방법 + - 배포 확인 방법! 배포 후 스크립트를 개발하고 테스트합니다. + +## 구현 가이드라인 {#implementation-guidelines} + +**단순함을 추구하세요.** 항상 목적에 맞는 가장 간단한 해결책을 사용하세요. 팀의 모든 구성원이 솔루션을 이해할 수 있어야 합니다. + +### 함수 구성 {#function-composition} + +코드베이스의 아키텍처는 코드를 쉽게 검토할 수 있도록 만들어야 합니다. 정확성을 추론하는 능력을 감소시키는 아키텍처 선택을 피하세요. + +- **시스템의 로직을 분할합니다**, 여러 계약을 통하거나 유사한 함수를 함께 그룹화(예: 인증, 산술 등)합니다. +- **명확한 목적을 가진 작은 함수를 작성하세요.** 이렇게 하면 검토가 용이해지고 개별 구성 요소를 테스트할 수 있습니다. + +### 상속 {#inheritance} + +- **상속을 관리 가능하게 유지하세요.** 상속은 로직을 나누는 데 사용되어야 하지만, 프로젝트는 상속 트리의 깊이와 너비를 최소화하는 것을 목표로 해야 합니다. +- **Slither의 [상속 프린터](https://github.com/crytic/slither/wiki/Printer-documentation#inheritance-graph)를 사용하여 계약의 계층 구조를 확인하세요.** 상속 프린터는 계층 구조의 크기를 검토하는 데 도움이 됩니다. + +### 이벤트 {#events} + +- **모든 중요한 작업을 기록하세요.** 이벤트는 개발 중 계약을 디버깅하고 배포 후 모니터링하는 데 도움이 됩니다. + +### 알려진 함정 피하기 {#avoid-known-pitfalls} + +- **가장 일반적인 보안 문제에 유의하세요.** [Ethernaut CTF](https://ethernaut.openzeppelin.com/), [Capture the Ether](https://capturetheether.com/) 또는 [Not so smart contracts](https://github.com/crytic/not-so-smart-contracts/)와 같은 일반적인 문제에 대해 배울 수 있는 많은 온라인 리소스가 있습니다. +- **[Solidity 개발문서](https://docs.soliditylang.org/en/latest/)의 경고 섹션에 유의하세요.** 경고 섹션은 언어의 명확하지 않은 동작에 대해 알려줍니다. + +### 종속성 {#dependencies} + +- **잘 테스트된 라이브러리를 사용하세요.** 잘 테스트된 라이브러리에서 코드를 가져오면 버그가 있는 코드를 작성할 가능성이 줄어듭니다. ERC20 계약을 작성하려면 [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20)을 사용하세요. +- **종속성 관리자를 사용하고 코드를 복사하여 붙여넣지 마세요.** 외부 소스에 의존하는 경우 원본 소스와 최신 상태로 유지해야 합니다. + +### 테스트 및 검증 {#testing-and-verification} + +- **철저한 단위 테스트를 작성하세요.** 광범위한 테스트 스위트는 고품질 소프트웨어를 구축하는 데 중요합니다. +- **[Slither](https://github.com/crytic/slither), [Echidna](https://github.com/crytic/echidna) 및 [Manticore](https://github.com/trailofbits/manticore) 사용자 지정 검사 및 속성을 작성하세요.** 자동화된 도구는 계약의 보안을 보장하는 데 도움이 됩니다. 효율적인 검사 및 속성을 작성하는 방법을 알아보려면 이 가이드의 나머지 부분을 검토하세요. +- **[crytic.io](https://crytic.io/)를 사용하세요.** Crytic은 GitHub와 통합되고 비공개 Slither 탐지기에 대한 액세스를 제공하며 Echidna에서 사용자 지정 속성 검사를 실행합니다. + +### 솔리디티 {#solidity} + +- **0.4 및 0.6보다 Solidity 0.5를 선호합니다.** 저희 의견으로는 Solidity 0.5가 0.4보다 더 안전하고 더 나은 내장 관행을 가지고 있습니다. Solidity 0.6은 프로덕션에 너무 불안정하여 성숙할 시간이 필요합니다. +- **안정적인 릴리스를 사용하여 컴파일하고 최신 릴리스를 사용하여 경고를 확인하세요.** 최신 컴파일러 버전에서 코드에 보고된 문제가 없는지 확인하세요. 하지만 Solidity는 릴리스 주기가 빠르고 컴파일러 버그 기록이 있으므로 배포에 최신 버전을 권장하지 않습니다(Slither의 [solc 버전 권장 사항](https://github.com/crytic/slither/wiki/Detector-Documentation#recommendation-33) 참조). +- **인라인 어셈블리를 사용하지 마세요.** 어셈블리에는 EVM 전문 지식이 필요합니다. 옐로우 페이퍼를 마스터하지 않았다면 EVM 코드를 작성하지 마세요. + +## 배포 가이드라인 {#deployment-guidelines} + +계약이 개발되고 배포되었다면 다음 사항을 따르세요. + +- **계약을 모니터링하세요.** 로그를 확인하고 계약 또는 지갑이 손상될 경우에 대비하여 대응할 준비를 하세요. +- **[blockchain-security-contacts](https://github.com/crytic/blockchain-security-contacts)에 연락처 정보를 추가하세요.** 이 목록은 보안 결함이 발견되었을 때 제3자가 귀하에게 연락하는 데 도움이 됩니다. +- **권한 있는 사용자의 지갑을 보호하세요.** 하드웨어 지갑에 키를 저장하는 경우 [모범 사례](https://blog.trailofbits.com/2018/11/27/10-rules-for-the-secure-use-of-cryptocurrency-hardware-wallets/)를 따르세요. +- **사고 대응 계획을 마련하세요.** 스마트 계약이 손상될 수 있음을 고려하세요. 계약에 버그가 없더라도 공격자가 계약 소유자의 키를 제어할 수 있습니다. diff --git a/public/content/translations/ko/developers/tutorials/stealth-addr/index.md b/public/content/translations/ko/developers/tutorials/stealth-addr/index.md new file mode 100644 index 00000000000..219bb2eb698 --- /dev/null +++ b/public/content/translations/ko/developers/tutorials/stealth-addr/index.md @@ -0,0 +1,436 @@ +--- +title: "스텔스 주소 사용하기" +description: "스텔스 주소는 사용자가 자산을 익명으로 전송할 수 있게 해줍니다. 이 기사를 읽고 나면 스텔스 주소가 무엇이며 어떻게 작동하는지 설명하고, 익명성을 유지하는 방식으로 스텔스 주소를 사용하는 방법을 이해하며, 스텔스 주소를 사용하는 웹 기반 애플리케이션을 작성할 수 있게 됩니다." +author: Ori Pomerantz +tags: [ "스텔스 주소", "개인정보 보호", "암호학", "Rust", "wasm" ] +skill: intermediate +published: 2025-11-30 +lang: ko +sidebarDepth: 3 +--- + +당신은 빌입니다. 자세한 이유는 설명하지 않겠지만, 당신은 "세계의 여왕 앨리스" 캠페인에 기부하고 싶어 합니다. 앨리스가 당신이 기부했다는 것을 알게 되면, 그녀가 승리했을 때 당신에게 보상할 것입니다. 안타깝게도, 그녀의 승리는 보장되지 않았습니다. 경쟁 캠페인으로 "태양계의 여제 캐럴"이 있습니다. 만약 캐럴이 이기고, 그녀가 당신이 앨리스에게 기부한 사실을 알게 되면, 당신은 곤경에 처하게 될 것입니다. 그래서 당신은 당신의 계정에서 앨리스의 계정으로 200 ETH를 그냥 전송할 수 없습니다. + +[ERC-5564](https://eips.ethereum.org/EIPS/eip-5564)에 해결책이 있습니다. 이 ERC는 익명 전송을 위해 [스텔스 주소](https://nerolation.github.io/stealth-utils)를 사용하는 방법을 설명합니다. + +**경고**: 스텔스 주소의 기반이 되는 암호학은 우리가 아는 한 안전합니다. 하지만 잠재적인 사이드 채널 공격이 있을 수 있습니다. 이러한 위험을 줄이기 위해 무엇을 할 수 있는지 [아래](#go-wrong)에서 확인할 수 있습니다. + +## 스텔스 주소 작동 방식 {#how} + +이 기사에서는 스텔스 주소를 두 가지 방식으로 설명합니다. 첫 번째는 [사용 방법](#how-use)입니다. 이 부분만으로도 기사의 나머지 부분을 이해하는 데 충분합니다. 그다음은 [그 배경이 되는 수학에 대한 설명](#how-math)입니다. 암호학에 관심이 있다면 이 부분도 읽어보세요. + +### 간단한 버전 (스텔스 주소 사용 방법) {#how-use} + +앨리스는 두 개의 개인 키를 생성하고 해당 공개 키를 게시합니다(이 키들은 단일 이중 길이 메타 주소로 결합될 수 있습니다). 빌도 개인 키를 생성하고 해당 공개 키를 게시합니다. + +한쪽의 공개 키와 다른 쪽의 개인 키를 사용하여 앨리스와 빌만 아는 공유 비밀을 도출할 수 있습니다(공개 키만으로는 도출할 수 없습니다). 이 공유 비밀을 사용하여 빌은 스텔스 주소를 얻고 그 주소로 자산을 보낼 수 있습니다. + +앨리스도 공유 비밀로부터 주소를 얻지만, 그녀는 자신이 게시한 공개 키에 대한 개인 키를 알고 있기 때문에 해당 주소에서 인출할 수 있는 개인 키도 얻을 수 있습니다. + +### 수학적 원리 (스텔스 주소가 이렇게 작동하는 이유) {#how-math} + +표준 스텔스 주소는 [타원 곡선 암호학(ECC)](https://blog.cloudflare.com/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography/#elliptic-curves-building-blocks-of-a-better-trapdoor)을 사용하여 더 적은 키 비트로 더 나은 성능을 얻으면서도 동일한 수준의 보안을 유지합니다. 그러나 대부분의 경우 우리는 이를 무시하고 일반적인 산술을 사용한다고 가정할 수 있습니다. + +모두가 아는 숫자, G가 있습니다. G를 곱할 수 있습니다. 하지만 ECC의 특성상 G로 나누는 것은 사실상 불가능합니다. 일반적으로 이더리움에서 공개 키 암호학이 작동하는 방식은 개인 키 Ppriv를 사용하여 트랜잭션에 서명하고, 그 후 공개 키 Ppub = GPpriv로 검증하는 것입니다. + +앨리스는 두 개의 개인 키, KprivVpriv를 생성합니다. Kpriv는 스텔스 주소에서 돈을 쓰는 데 사용되고, Vpriv는 앨리스에게 속한 주소를 보는 데 사용됩니다. 그다음 앨리스는 공개 키 Kpub = GKprivVpub = GVpriv를 게시합니다. + +빌은 세 번째 개인 키 Rpriv를 생성하고 중앙 레지스트리에 Rpub = GRpriv를 게시합니다(빌이 앨리스에게 보냈을 수도 있지만, 우리는 캐럴이 엿듣고 있다고 가정합니다). + +빌은 앨리스도 알 것이라고 예상하는 RprivVpub = GRprivVpriv를 계산합니다(아래 설명 참조). 이 값은 공유 비밀인 S라고 합니다. 이는 빌에게 공개 키 *Ppub = Kpub+G*hash(S)*를 제공합니다. 이 공개 키로부터 그는 주소를 계산하고 원하는 모든 자원을 보낼 수 있습니다. 미래에 앨리스가 이기면, 빌은 그녀에게 Rpriv를 알려주어 자원이 자신에게서 왔음을 증명할 수 있습니다. + +앨리스는 RpubVpriv = GRprivVpriv를 계산합니다. 이는 그녀에게 동일한 공유 비밀인 S를 제공합니다. 그녀는 개인 키 Kpriv를 알고 있기 때문에 Ppriv = Kpriv+hash(S)를 계산할 수 있습니다. 이 키를 통해 그녀는 *Ppub = GPpriv = GKpriv+G*hash(S) = Kpub+G*hash(S)*에서 비롯된 주소에 있는 자산에 접근할 수 있습니다. + +앨리스가 데이브의 세계 정복 캠페인 서비스에 하도급을 줄 수 있도록 별도의 보기 키가 있습니다. 앨리스는 데이브에게 공개 주소를 알리고 더 많은 돈이 생기면 알려주기를 원하지만, 그가 자신의 캠페인 자금을 쓰는 것은 원하지 않습니다. + +보기와 지출에 별도의 키를 사용하기 때문에 앨리스는 데이브에게 Vpriv를 줄 수 있습니다. 그러면 데이브는 S = RpubVpriv = GRprivVpriv를 계산하여 공개 키(_Ppub = Kpub+G*hash(S)_)를 얻을 수 있습니다. 하지만 Kpriv가 없으면 데이브는 개인 키를 얻을 수 없습니다. + +요약하자면, 다음은 각 참여자가 알고 있는 값입니다. + +| 앨리스 | 게시됨 | 빌 | 데이브 | | +| ------------------------------------------------------------------------- | ----------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------ | +| G | G | G | G | | +| _Kpriv_ | - | - | - | | +| _Vpriv_ | - | - | _Vpriv_ | | +| _Kpub = GKpriv_ | _Kpub_ | _Kpub_ | _Kpub_ | | +| _Vpub = GVpriv_ | _Vpub_ | _Vpub_ | _Vpub_ | | +| - | - | _Rpriv_ | - | | +| _Rpub_ | _Rpub_ | _Rpub = GRpriv_ | _Rpub_ | | +| _S = RpubVpriv = GRprivVpriv_ | - | _S = RprivVpub = GRprivVpriv_ | _S = _RpubVpriv_ = GRprivVpriv_ | | +| _Ppub = Kpub+G\*hash(S)_ | - | _Ppub = Kpub+G\*hash(S)_ | _Ppub = Kpub+G\*hash(S)_ | | +| _주소=f(Ppub)_ | - | _주소=f(Ppub)_ | _주소=f(Ppub)_ | _주소=f(Ppub)_ | +| _Ppriv = Kpriv+hash(S)_ | - | - | - | | + +## 스텔스 주소가 잘못될 때 {#go-wrong} + +_블록체인에는 비밀이 없습니다_. 스텔스 주소는 개인정보 보호를 제공할 수 있지만, 그 개인정보 보호는 트래픽 분석에 취약합니다. 사소한 예를 들어, 빌이 한 주소에 자금을 대고 즉시 트랜잭션을 보내 _Rpub_ 값을 게시한다고 상상해 봅시다. 앨리스의 Vpriv가 없으면 이것이 스텔스 주소인지 확신할 수 없지만, 그렇게 추측하는 것이 합리적입니다. 그다음, 해당 주소에서 앨리스의 캠페인 기금 주소로 모든 ETH를 전송하는 또 다른 트랜잭션을 보게 됩니다. 증명할 수는 없지만, 빌이 앨리스의 캠페인에 막 기부했을 가능성이 높습니다. 캐럴은 분명 그렇게 생각할 것입니다. + +빌이 스텔스 주소 자금 조달과 _Rpub_ 게시를 분리하는 것은 쉽습니다(다른 시간에, 다른 주소에서 수행). 하지만 그것만으로는 충분하지 않습니다. 캐럴이 찾는 패턴은 빌이 한 주소에 자금을 대고, 그다음 앨리스의 캠페인 기금이 그 주소에서 인출하는 것입니다. + +한 가지 해결책은 앨리스의 캠페인이 돈을 직접 인출하는 대신 제3자에게 지불하는 데 사용하는 것입니다. 앨리스의 캠페인이 데이브의 세계 정복 캠페인 서비스에 10 ETH를 보내면, 캐럴은 빌이 데이브의 고객 중 한 명에게 기부했다는 것만 알게 됩니다. 데이브에게 충분한 고객이 있다면, 캐럴은 빌이 자신과 경쟁하는 앨리스에게 기부했는지, 아니면 캐럴이 신경 쓰지 않는 아담, 앨버트, 애비게일에게 기부했는지 알 수 없을 것입니다. 앨리스는 지불금에 해시된 값을 포함시키고, 그다음 데이브에게 프리이미지를 제공하여 자신의 기부였음을 증명할 수 있습니다. 또는 위에서 언급했듯이 앨리스가 데이브에게 자신의 Vpriv를 주면, 그는 이미 그 지불이 누구로부터 왔는지 알고 있습니다. + +이 해결책의 주된 문제점은 그 비밀 유지가 빌에게 이익이 될 때 앨리스가 비밀 유지에 신경 써야 한다는 것입니다. 앨리스는 자신의 평판을 유지하여 빌의 친구 밥도 그녀에게 기부하도록 하고 싶을 수 있습니다. 하지만 그녀가 빌을 폭로하는 것을 개의치 않을 수도 있습니다. 그러면 빌은 캐럴이 이길 경우 일어날 일을 두려워하게 될 것이기 때문입니다. 빌은 결국 앨리스에게 훨씬 더 많은 지원을 제공하게 될 수도 있습니다. + +### 다중 스텔스 레이어 사용하기 {#multi-layer} + +빌의 개인정보 보호를 앨리스에게 의존하는 대신, 빌이 직접 할 수 있습니다. 그는 가상의 인물인 밥과 벨라를 위해 여러 개의 메타 주소를 생성할 수 있습니다. 그러면 빌은 밥에게 ETH를 보내고, "밥"(실제로는 빌)은 벨라에게 보냅니다. "벨라"(역시 빌)는 앨리스에게 보냅니다. + +캐럴은 여전히 트래픽 분석을 통해 빌-밥-벨라-앨리스 파이프라인을 볼 수 있습니다. 그러나 "밥"과 "벨라"가 다른 목적으로도 ETH를 사용한다면, 앨리스가 스텔스 주소에서 자신의 알려진 캠페인 주소로 즉시 인출하더라도 빌이 앨리스에게 무언가를 전송한 것처럼 보이지 않을 것입니다. + +## 스텔스 주소 애플리케이션 작성하기 {#write-app} + +이 기사에서는 [GitHub에서 사용할 수 있는](https://github.com/qbzzt/251022-stealth-addresses.git) 스텔스 주소 애플리케이션에 대해 설명합니다. + +### 도구 {#tools} + +[사용할 수 있는 타입스크립트 스텔스 주소 라이브러리](https://github.com/ScopeLift/stealth-address-sdk)가 있습니다. 그러나 암호화 작업은 CPU 집약적일 수 있습니다. 저는 [Rust](https://rust-lang.org/)와 같은 컴파일 언어로 구현하고 [WASM](https://webassembly.org/)을 사용하여 브라우저에서 코드를 실행하는 것을 선호합니다. + +우리는 [Vite](https://vite.dev/)와 [React](https://react.dev/)를 사용할 것입니다. 이것들은 업계 표준 도구입니다. 익숙하지 않다면 [이 튜토리얼](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/)을 사용할 수 있습니다. Vite를 사용하려면 Node가 필요합니다. + +### 스텔스 주소 실제 작동 보기 {#in-action} + +1. 필요한 도구 설치: [Rust](https://rust-lang.org/tools/install/) 및 [Node](https://nodejs.org/en/download). + +2. GitHub 리포지토리를 복제합니다. + + ```sh + git clone https://github.com/qbzzt/251022-stealth-addresses.git + cd 251022-stealth-addresses + ``` + +3. 전제 조건을 설치하고 Rust 코드를 컴파일합니다. + + ```sh + cd src/rust-wasm + rustup target add wasm32-unknown-unknown + cargo install wasm-pack + wasm-pack build --target web + ``` + +4. 웹 서버를 시작합니다. + + ```sh + cd ../.. + npm install + npm run dev + ``` + +5. [애플리케이션](http://localhost:5173/)으로 이동합니다. 이 애플리케이션 페이지에는 두 개의 프레임이 있습니다. 하나는 앨리스의 사용자 인터페이스용이고 다른 하나는 빌의 사용자 인터페이스용입니다. 두 프레임은 통신하지 않습니다. 편의를 위해 같은 페이지에 있을 뿐입니다. + +6. 앨리스로서 스텔스 메타 주소 생성을 클릭합니다. 이렇게 하면 새 스텔스 주소와 해당 개인 키가 표시됩니다. 스텔스 메타 주소를 클립보드에 복사합니다. + +7. 빌로서 새 스텔스 메타 주소를 붙여넣고 주소 생성을 클릭합니다. 이렇게 하면 앨리스를 위해 자금을 조달할 주소가 제공됩니다. + +8. 주소와 빌의 공개 키를 복사하여 앨리스의 사용자 인터페이스에 있는 "빌이 생성한 주소의 개인 키" 영역에 붙여넣습니다. 해당 필드를 채우면 해당 주소의 자산에 접근할 수 있는 개인 키가 표시됩니다. + +9. [온라인 계산기](https://iancoleman.net/ethereum-private-key-to-address/)를 사용하여 개인 키가 주소와 일치하는지 확인할 수 있습니다. + +### 프로그램 작동 방식 {#how-the-program-works} + +#### WASM 구성 요소 {#wasm} + +WASM으로 컴파일되는 소스 코드는 [Rust](https://rust-lang.org/)로 작성되었습니다. [`src/rust_wasm/src/lib.rs`](https://github.com/qbzzt/251022-stealth-addresses/blob/main/src/rust-wasm/src/lib.rs)에서 확인할 수 있습니다. 이 코드는 주로 JavaScript 코드와 [`eth-stealth-addresses` 라이브러리](https://github.com/kassandraoftroy/eth-stealth-addresses) 사이의 인터페이스입니다. + +**`Cargo.toml`** + +Rust의 [`Cargo.toml`](https://doc.rust-lang.org/cargo/reference/manifest.html)은 JavaScript의 [`package.json`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json)과 유사합니다. 여기에는 패키지 정보, 종속성 선언 등이 포함됩니다. + +```toml +[package] +name = "rust-wasm" +version = "0.1.0" +edition = "2024" + +[dependencies] +eth-stealth-addresses = "0.1.0" +hex = "0.4.3" +wasm-bindgen = "0.2.104" +getrandom = { version = "0.2", features = ["js"] } +``` + +[`getrandom`](https://docs.rs/getrandom/latest/getrandom/) 패키지는 임의의 값을 생성해야 합니다. 이는 순수한 알고리즘적 수단으로는 수행될 수 없으며, 엔트로피 소스로서 물리적 프로세스에 대한 접근이 필요합니다. 이 정의는 우리가 실행 중인 브라우저에 요청하여 해당 엔트로피를 얻도록 지정합니다. + +```toml +console_error_panic_hook = "0.1.7" +``` + +[이 라이브러리](https://docs.rs/console_error_panic_hook/latest/console_error_panic_hook/)는 WASM 코드가 패닉 상태에 빠져 계속할 수 없을 때 더 의미 있는 오류 메시지를 제공합니다. + +```toml +[lib] +crate-type = ["cdylib", "rlib"] +``` + +WASM 코드를 생성하는 데 필요한 출력 유형입니다. + +**`lib.rs`** + +이것이 실제 Rust 코드입니다. + +```rust +use wasm_bindgen::prelude::*; +``` + +Rust에서 WASM 패키지를 생성하기 위한 정의입니다. [여기](https://wasm-bindgen.github.io/wasm-bindgen/reference/attributes/index.html)에 문서화되어 있습니다. + +```rust +use eth_stealth_addresses::{ + generate_stealth_meta_address, + generate_stealth_address, + compute_stealth_key +}; +``` + +[`eth-stealth-addresses` 라이브러리](https://github.com/kassandraoftroy/eth-stealth-addresses)에서 필요한 함수입니다. + +```rust +use hex::{decode,encode}; +``` + +Rust는 일반적으로 값에 대해 바이트 [배열](https://doc.rust-lang.org/std/primitive.array.html)(`[u8; ]`)을 사용합니다. 그러나 JavaScript에서는 일반적으로 16진수 문자열을 사용합니다. [`hex` 라이브러리](https://docs.rs/hex/latest/hex/)는 한 표현에서 다른 표현으로 변환해 줍니다. + +```rust +#[wasm_bindgen] +``` + +JavaScript에서 이 함수를 호출할 수 있도록 WASM 바인딩을 생성합니다. + +```rust +pub fn wasm_generate_stealth_meta_address() -> String { +``` + +여러 필드가 있는 객체를 반환하는 가장 쉬운 방법은 JSON 문자열을 반환하는 것입니다. + +```rust + let (address, spend_private_key, view_private_key) = + generate_stealth_meta_address(); +``` + +[`generate_stealth_meta_address`](https://docs.rs/eth-stealth-addresses/latest/eth_stealth_addresses/fn.generate_stealth_meta_address.html)는 세 개의 필드를 반환합니다. + +- 메타 주소(_Kpub_ 및 _Vpub_) +- 보기 개인 키(_Vpriv_) +- 지출 개인 키(_Kpriv_) + +[튜플](https://doc.rust-lang.org/std/primitive.tuple.html) 구문을 사용하면 해당 값들을 다시 분리할 수 있습니다. + +```rust + format!("{{\"address\":\"{}\",\"view_private_key\":\"{}\",\"spend_private_key\":\"{}\"}}", + encode(address), + encode(view_private_key), + encode(spend_private_key) + ) +} +``` + +[`format!`](https://doc.rust-lang.org/std/fmt/index.html) 매크로를 사용하여 JSON으로 인코딩된 문자열을 생성합니다. [`hex::encode`](https://docs.rs/hex/latest/hex/fn.encode.html)를 사용하여 배열을 16진수 문자열로 변경합니다. + +```rust +fn str_to_array(s: &str) -> Option<[u8; N]> { +``` + +이 함수는 16진수 문자열(JavaScript에서 제공)을 바이트 배열로 변환합니다. JavaScript 코드로 제공된 값을 파싱하는 데 사용합니다. 이 함수는 Rust가 배열과 벡터를 처리하는 방식 때문에 복잡합니다. + +`` 표현식은 [제네릭](https://doc.rust-lang.org/book/ch10-01-syntax.html)이라고 합니다. `N`은 반환되는 배열의 길이를 제어하는 매개변수입니다. 함수는 실제로는 `str_to_array::`으로 호출되며, 여기서 `n`은 배열 길이입니다. + +반환 값은 `Option<[u8; N]>`이며, 이는 반환되는 배열이 [선택 사항](https://doc.rust-lang.org/std/option/)임을 의미합니다. 이는 실패할 수 있는 함수에 대한 Rust의 일반적인 패턴입니다. + +예를 들어, `str_to_array::10("bad060a7")`를 호출하면 함수는 10개 값의 배열을 반환해야 하지만 입력은 4바이트뿐입니다. 함수는 실패해야 하며, `None`을 반환하여 이를 수행합니다. `str_to_array::4("bad060a7")`의 반환 값은 `Some<[0xba, 0xd0, 0x60, 0xa7]>`입니다. + +```rust + // decode는 Result, _>를 반환합니다 + let vec = decode(s).ok()?; +``` + +[`hex::decode`](https://docs.rs/hex/latest/hex/fn.decode.html) 함수는 `Result, FromHexError>`를 반환합니다. [`Result`](https://doc.rust-lang.org/std/result/) 유형은 성공적인 결과(`Ok(value)`) 또는 오류(`Err(error)`)를 포함할 수 있습니다. + +`.ok()` 메서드는 `Result`를 `Option`으로 변환하며, `Option`의 값은 성공하면 `Ok()` 값이 되고, 그렇지 않으면 `None`이 됩니다. 마지막으로 [물음표 연산자](https://doc.rust-lang.org/std/option/#the-question-mark-operator-)는 `Option`이 비어 있는 경우 현재 함수를 중단하고 `None`을 반환합니다. 그렇지 않으면 값을 언래핑하여 반환합니다(이 경우 `vec`에 값을 할당하기 위해). + +이것은 오류를 처리하는 이상하게 복잡한 방법처럼 보이지만, `Result`와 `Option`은 모든 오류가 어떤 식으로든 처리되도록 보장합니다. + +```rust + if vec.len() != N { return None; } +``` + +바이트 수가 올바르지 않으면 실패이므로 `None`을 반환합니다. + +```rust + // try_into는 vec를 소비하고 [u8; N]을 만들려고 시도합니다 + let array: [u8; N] = vec.try_into().ok()?; +``` + +Rust에는 두 가지 배열 유형이 있습니다. [배열](https://doc.rust-lang.org/std/primitive.array.html)은 고정된 크기를 가집니다. [벡터](https://doc.rust-lang.org/std/vec/index.html)는 커지거나 작아질 수 있습니다. `hex::decode`는 벡터를 반환하지만, `eth_stealth_addresses` 라이브러리는 배열을 받기를 원합니다. [`.try_into()`](https://doc.rust-lang.org/std/convert/trait.TryInto.html#required-methods)는 값을 다른 유형으로 변환합니다(예: 벡터를 배열로). + +```rust + Some(array) +} +``` + +Rust에서는 함수 끝에서 값을 반환할 때 [`return`](https://doc.rust-lang.org/std/keyword.return.html) 키워드를 사용할 필요가 없습니다. + +```rust +#[wasm_bindgen] +pub fn wasm_generate_stealth_address(stealth_address: &str) -> Option { +``` + +이 함수는 VpubKpub를 모두 포함하는 공개 메타 주소를 받습니다. 이 함수는 스텔스 주소, 게시할 공개 키(_Rpub_), 그리고 게시된 주소 중 어떤 것이 앨리스에 속하는지 식별하는 속도를 높이는 1바이트 스캔 값을 반환합니다. + +스캔 값은 공유 비밀(_S = GRprivVpriv_)의 일부입니다. 이 값은 앨리스가 사용할 수 있으며, 이를 확인하는 것은 *f(Kpub+G*hash(S))\*가 게시된 주소와 같은지 확인하는 것보다 훨씬 빠릅니다. + +```rust + let (address, r_pub, scan) = + generate_stealth_address(&str_to_array::<66>(stealth_address)?); +``` + +라이브러리의 [`generate_stealth_address`](https://docs.rs/eth-stealth-addresses/latest/eth_stealth_addresses/fn.generate_stealth_address.html)를 사용합니다. + +```rust + format!("{{\"address\":\"{}\",\"rPub\":\"{}\",\"scan\":\"{}\"}}", + encode(address), + encode(r_pub), + encode(&[scan]) + ).into() +} +``` + +JSON으로 인코딩된 출력 문자열을 준비합니다. + +```rust +#[wasm_bindgen] +pub fn wasm_compute_stealth_key( + address: &str, + bill_pub_key: &str, + view_private_key: &str, + spend_private_key: &str +) -> Option { + . + . + . +} +``` + +이 함수는 라이브러리의 [`compute_stealth_key`](https://docs.rs/eth-stealth-addresses/latest/eth_stealth_addresses/fn.compute_stealth_key.html)를 사용하여 주소에서 인출할 개인 키(_Rpriv_)를 계산합니다. 이 계산에는 다음 값들이 필요합니다. + +- 주소(_주소=f(Ppub)_) +- 빌이 생성한 공개 키(_Rpub_) +- 보기 개인 키(_Vpriv_) +- 지출 개인 키(_Kpriv_) + +```rust +#[wasm_bindgen(start)] +``` + +[`#[wasm_bindgen(start)]`](https://wasm-bindgen.github.io/wasm-bindgen/reference/attributes/on-rust-exports/start.html)는 WASM 코드가 초기화될 때 함수가 실행되도록 지정합니다. + +```rust +pub fn main() { + console_error_panic_hook::set_once(); +} +``` + +이 코드는 패닉 출력이 JavaScript 콘솔로 전송되도록 지정합니다. 실제 작동을 보려면 애플리케이션을 사용하고 빌에게 잘못된 메타 주소(16진수 숫자 하나만 변경)를 제공해 보세요. JavaScript 콘솔에서 다음 오류가 표시됩니다. + +``` +rust_wasm.js:236 panicked at /home/ori/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs:701:9: +assertion `left == right` failed + left: 0 + right: 1 +``` + +뒤이어 스택 추적이 나타납니다. 그다음 빌에게 유효한 메타 주소를 주고, 앨리스에게 잘못된 주소나 잘못된 공개 키를 주세요. 다음 오류가 표시됩니다. + +``` +rust_wasm.js:236 panicked at /home/ori/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/eth-stealth-addresses-0.1.0/src/lib.rs:78:9: +keys do not generate stealth address +``` + +다시 한 번 스택 추적이 이어집니다. + +#### 사용자 인터페이스 {#ui} + +사용자 인터페이스는 [React](https://react.dev/)를 사용하여 작성되었고 [Vite](https://vite.dev/)에 의해 제공됩니다. [이 튜토리얼](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/)을 사용하여 배울 수 있습니다. 여기서는 블록체인이나 지갑과 직접 상호작용하지 않기 때문에 [WAGMI](https://wagmi.sh/)가 필요 없습니다. + +사용자 인터페이스에서 명확하지 않은 유일한 부분은 WASM 연결입니다. 작동 방식은 다음과 같습니다. + +**`vite.config.js`** + +이 파일에는 [Vite 구성](https://vite.dev/config/)이 포함되어 있습니다. + +```js +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import wasm from "vite-plugin-wasm"; + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react(), wasm()], +}) +``` + +두 가지 Vite 플러그인이 필요합니다: [react](https://www.npmjs.com/package/@vitejs/plugin-react)와 [wasm](https://github.com/Menci/vite-plugin-wasm#readme). + +**`App.jsx`** + +이 파일은 애플리케이션의 주요 구성 요소입니다. 이 컨테이너에는 `Alice`와 `Bill`이라는 두 가지 구성 요소, 즉 해당 사용자를 위한 사용자 인터페이스가 포함되어 있습니다. WASM과 관련된 부분은 초기화 코드입니다. + +```jsx +import init from './rust-wasm/pkg/rust_wasm.js' +``` + +[`wasm-pack`](https://rustwasm.github.io/docs/wasm-pack/)을 사용하면 여기서 사용하는 두 개의 파일이 생성됩니다: 실제 코드가 포함된 wasm 파일(여기서는 `src/rust-wasm/pkg/rust_wasm_bg.wasm`)과 이를 사용하기 위한 정의가 포함된 JavaScript 파일(여기서는 `src/rust-wasm/pkg/rust_wasm.js`). 해당 JavaScript 파일의 기본 내보내기는 WASM을 시작하기 위해 실행해야 하는 코드입니다. + +```jsx +function App() { + . + . + . + useEffect(() => { + const loadWasm = async () => { + try { + await init(); + setWasmReady(true) + } catch (err) { + console.error('Error loading wasm:', err) + alert("Wasm error: " + err) + } + } + + loadWasm() + }, [] + ) +``` + +[`useEffect` 훅](https://react.dev/reference/react/useEffect)을 사용하면 상태 변수가 변경될 때 실행되는 함수를 지정할 수 있습니다. 여기서 상태 변수 목록은 비어 있으므로(`[]`) 이 함수는 페이지가 로드될 때 한 번만 실행됩니다. + +이펙트 함수는 즉시 반환되어야 합니다. WASM `init`와 같은 비동기 코드를 사용하려면(이는 `.wasm` 파일을 로드해야 하므로 시간이 걸림) 내부 [`async`](https://en.wikipedia.org/wiki/Async/await) 함수를 정의하고 `await` 없이 실행합니다. + +**`Bill.jsx`** + +이것은 빌의 사용자 인터페이스입니다. 앨리스가 제공한 스텔스 메타 주소를 기반으로 주소를 생성하는 단일 작업이 있습니다. + +```jsx +import { wasm_generate_stealth_address } from './rust-wasm/pkg/rust_wasm.js' +``` + +기본 내보내기 외에도 `wasm-pack`에서 생성된 JavaScript 코드는 WASM 코드의 모든 함수에 대해 함수를 내보냅니다. + +```jsx +
diff --git a/public/content/translations/pt-br/community/research/index.md b/public/content/translations/pt-br/community/research/index.md index 9998ca7a482..580eeadf137 100644 --- a/public/content/translations/pt-br/community/research/index.md +++ b/public/content/translations/pt-br/community/research/index.md @@ -1,63 +1,63 @@ --- -title: Áreas ativas de pesquisa do Ethereum -description: Acesse diferentes áreas de pesquisa aberta e saiba como participar. +title: "Áreas ativas de pesquisa sobre o Ethereum" +description: "Acesse diferentes áreas de pesquisa aberta e saiba como participar." lang: pt-br --- -# Áreas ativas de pesquisa do Ethereum {#active-areas-of-ethereum-research} +# Áreas ativas de pesquisa sobre o Ethereum {#active-areas-of-ethereum-research} -Um dos principais pontos fortes do Ethereum é ele está sendo constantemente aprimorado por meio de uma comunidade ativa de pesquisa e engenharia. Muitas pessoas entusiasmadas e capacitadas em todo o mundo gostariam de se dedicar a questões pendentes no Ethereum, mas nem sempre é fácil descobrir quais são essas questões. Esta página descreve as principais áreas de pesquisa ativas como um guia aproximado da tecnologia de ponta do Ethereum. +Um dos principais pontos fortes do Ethereum é que ele está sendo constantemente aprimorado por meio de uma comunidade ativa de pesquisa e engenharia. Muitas pessoas entusiasmadas e capacitadas ao redor do mundo gostariam de se dedicar a questões pendentes no Ethereum, mas nem sempre é fácil descobrir quais são essas questões. Esta página descreve as principais áreas de pesquisa ativas como um guia aproximado da tecnologia de ponta do Ethereum. -## Como funciona a pesquisa no Ethereum {#how-ethereum-research-works} +## Como funciona a pesquisa sobre o Ethereum {#how-ethereum-research-works} -A pesquisa no Ethereum é aberta e transparente, e incorpora os princípios de [Ciência Descentralizada (DeSci)](https://hackernoon.com/desci-decentralized-science-as-our-chance-to-recover-the-real-science). A cultura é tornar as ferramentas e os resultados de pesquisa tão abertos e interativos quanto possível, por exemplo, por meio de notebooks executáveis. A pesquisa no Ethereum avança rapidamente, com novas constatações publicadas e discutidas abertamente em fóruns como [ethresear.ch](https://ethresear.ch/), em vez de chegar à comunidade por meio de publicações tradicionais após sessões de revisão por pares. +A pesquisa sobre o Ethereum é aberta e transparente, incorporando os princípios da [Ciência Descentralizada (DeSci)](https://hackernoon.com/desci-decentralized-science-as-our-chance-to-recover-the-real-science). A cultura consiste em tornar as ferramentas e os resultados de pesquisa tão abertos e interativos quanto possível, por exemplo, por meio de notebooks executáveis. A pesquisa sobre o Ethereum avança rapidamente, com novas descobertas publicadas e discutidas abertamente em fóruns como o [ethresear.ch](https://ethresear.ch/), em vez de chegar à comunidade por meio de publicações tradicionais após rodadas de revisão por pares. -## Recursos gerais de pesquisa {#general-research-resources} +## Recursos para pesquisa comum {#general-research-resources} -Independentemente do tópico específico, há uma riqueza de informações sobre pesquisa do Ethereum a ser descoberta em [ethresear.ch](https://ethresear.ch) e no canal [Eth R&D Discord](https://discord.gg/qGpsxSA). Esses são os principais locais onde os pesquisadores do Ethereum discutem as ideias e oportunidades mais recentes de desenvolvimento. +Independentemente do tópico específico, há uma grande quantidade de informações sobre a pesquisa sobre o Ethereum que podem ser encontradas em [ethresear.ch](https://ethresear.ch) e no [canal Eth R&D Discord](https://discord.gg/qGpsxSA). Esses são os principais locais onde os pesquisadores do Ethereum discutem as ideias e oportunidades mais recentes de desenvolvimento. -Este relatório, publicado em maio de 2022 pela [DelphiDigital](https://members.delphidigital.io/reports/the-hitchhikers-guide-to-ethereum), oferece uma boa visão geral do planejamento do Ethereum. +Esse relatório publicado em maio de 2022 pela [DelphiDigital](https://members.delphidigital.io/reports/the-hitchhikers-guide-to-ethereum) fornece uma boa visão geral sobre o plano de ação do Ethereum. ## Fontes de financiamento {#sources-of-funding} -Você pode participar da pesquisa do Ethereum e ser pago por isso! Por exemplo, a [the Ethereum Foundation](/foundation/) realizou recentemente uma [rodada de financiamento de concessões acadêmicas](https://esp.ethereum.foundation/academic-grants). Informações sobre oportunidades de financiamento ativas e futuras estão disponíveis na [página de concessões do Ethereum](/community/grants/). +Você pode participar da pesquisa sobre o Ethereum e ser pago por isso! Por exemplo, a [Ethereum Foundation](/foundation/) realizou recentemente um [ciclo de financiamento de subsídios acadêmicos](https://esp.ethereum.foundation/academic-grants). Você pode encontrar informações sobre oportunidades de financiamento ativas e futuras na [página de subsídios do Ethereum](/community/grants/). -## Pesquisa de protocolo {#protocol-research} +## Pesquisa sobre protocolos {#protocol-research} -A pesquisa de protocolo está relacionada à camada de base da Ethereum, o conjunto de regras que define como os nós se conectam, se comunicam, trocam e armazenam dados do Ethereum e chegam a um consenso sobre o estado do blockchain. A pesquisa de protocolos é dividida em duas categorias de nível superior: consenso e execução. +A pesquisa sobre protocolos está relacionada à camada de base do Ethereum, o conjunto de regras que define como os nós se conectam, se comunicam, trocam e armazenam dados do Ethereum e chegam a um consenso sobre o estado da blockchain. A pesquisa sobre protocolos é dividida em duas categorias gerais: consenso e execução. ### Consenso {#consensus} -A pesquisa de consenso é relativa ao [mecanismo de prova de participação do Ethereum](/developers/docs/consensus-mechanisms/pos/). Alguns exemplos de tópicos de pesquisa de consenso são: +A pesquisa sobre consenso está relacionada com o [mecanismo de prova de participação do Ethereum](/developers/docs/consensus-mechanisms/pos/). Alguns exemplos de tópicos de pesquisa sobre consenso são: - identificar e resolver vulnerabilidades; - quantificar a segurança criptoeconômica; -- aumentar a segurança ou desempenho de implementações do cliente; +- aumentar a segurança ou o desempenho de implementações do cliente; - e desenvolver clientes leves. -Além da pesquisa voltada para o futuro, algumas reformulações fundamentais do protocolo, como a finalidade de espaço único, estão sendo pesquisadas para permitir melhorias significativas no Ethereum. Além disso, a eficiência, a segurança e o monitoramento da rede ponto a ponto entre clientes de consenso também são importantes tópicos de pesquisa. +Além da pesquisa voltada para o futuro, algumas reformulações fundamentais do protocolo, como a finalidade de slot único, estão sendo pesquisadas para permitir melhorias significativas no Ethereum. Além disso, a eficiência, a segurança e o monitoramento da rede ponto a ponto entre clientes de consenso também são importantes tópicos de pesquisa. #### Leitura de apoio {#background-reading} - [Introdução à prova de participação](/developers/docs/consensus-mechanisms/pos/) -- [Artigo sobre o Casper-FFG](https://arxiv.org/abs/1710.09437) -- [Artigo sobre Casper-FFG](https://medium.com/unitychain/intro-to-casper-ffg-9ed944d98b2d) -- [Artigo sobre o Gasper](https://arxiv.org/abs/2003.03052) +- [Artigo Casper-FFG](https://arxiv.org/abs/1710.09437) +- [Explicando o Casper-FFG](https://medium.com/unitychain/intro-to-casper-ffg-9ed944d98b2d) +- [Artigo Gasper](https://arxiv.org/abs/2003.03052) #### Pesquisa recente {#recent-research} -- [Ethresear.ch Consensus](https://ethresear.ch/c/consensus/29) -- [Dilema disponibilidade/finalidade](https://arxiv.org/abs/2009.04987) -- [Finalidade de espaço único](https://ethresear.ch/t/a-model-for-cumulative-committee-based-finality/10259) -- [Separação de Proponente-Construtor](https://notes.ethereum.org/@vbuterin/pbs_censorship_resistance) +- [Consenso Ethresear.ch](https://ethresear.ch/c/consensus/29) +- [Dilema entre disponibilidade/finalidade](https://arxiv.org/abs/2009.04987) +- [Finalidade de slot único](https://ethresear.ch/t/a-model-for-cumulative-committee-based-finality/10259) +- [Separação proponente-construtor](https://notes.ethereum.org/@vbuterin/pbs_censorship_resistance) ### Execução {#execution} -A camada de execução se preocupa com a execução de transações, com a execução do [Máquina Virtual do Ethereum (EVM)](/developers/docs/evm/) e com a geração de cargas de execução para passar para a camada de consenso. Há muitas áreas ativas de pesquisa, incluindo: +A camada de execução é responsável pela execução de transações, pelo funcionamento da [Máquina Virtual Ethereum (EVM)](/developers/docs/evm/) e pela geração de cargas de execução para serem transferidas para a camada de consenso. Há muitas áreas ativas de pesquisa, incluindo: - desenvolvimento de suporte a cliente leve; - pesquisa de limites de gás; -- e incorporar novas estruturas de dados (por exemplo, Verkle Trees). +- e incorporando novas estruturas de dados (por exemplo, Verkle Tries). #### Leitura de apoio {#background-reading-1} @@ -66,13 +66,13 @@ A camada de execução se preocupa com a execução de transações, com a execu #### Pesquisa recente {#recent-research-1} -- [Otimizações de banco de dados](https://github.com/ledgerwatch/erigon/blob/devel/docs/programmers_guide/db_faq.md) +- [Otimizações do banco de dados](https://github.com/ledgerwatch/erigon/blob/devel/docs/programmers_guide/db_faq.md) - [Expiração do estado](https://notes.ethereum.org/@vbuterin/state_expiry_eip) - [Caminhos para a expiração do estado](https://hackmd.io/@vbuterin/state_expiry_paths) -- [Verkel e proposta de expiração de estado](https://notes.ethereum.org/@vbuterin/verkle_and_state_expiry_proposal) +- [Verkle e a proposta de expiração do estado](https://notes.ethereum.org/@vbuterin/verkle_and_state_expiry_proposal) - [Gerenciamento de histórico](https://eips.ethereum.org/EIPS/eip-4444) -- [Verkle Trees](https://vitalik.eth.limo/general/2021/06/18/verkle.html) -- [Amostragem da disponibilidade dos dados](https://github.com/ethereum/research/wiki/A-note-on-data-availability-and-erasure-coding) +- [Árvores Verkle](https://vitalik.eth.limo/general/2021/06/18/verkle.html) +- [Amostragem de disponibilidade de dados](https://github.com/ethereum/research/wiki/A-note-on-data-availability-and-erasure-coding) ## Desenvolvimento de cliente {#client-development} @@ -80,39 +80,39 @@ Os clientes Ethereum são implementações do protocolo Ethereum. O desenvolvime Um nó Ethereum é necessário para executar dois softwares: -1. um cliente de consenso para manter o controle da cabeça do blockchain, blocos de transmissão e para processar a lógica de consenso -2. um cliente de execução para oferecer suporte à Máquina Virtual do Ethereum e executar transações e contratos inteligentes +1. um cliente de consenso para manter o controle do início da blockchain, de propagar os blocos e processar a lógica de consenso +2. um cliente de execução para oferecer suporte à Máquina Virtual Ethereum e executar transações e contratos inteligentes -Consulte a [página de nós e clientes](/developers/docs/nodes-and-clients/) para obter mais detalhes sobre nós e clientes e uma lista de todas as implementações atuais de clientes. Um histórico de todas as melhorias do Ethereum também está disponível na [página de histórico](/ethereum-forks/). +Consulte a [página de nós e clientes](/developers/docs/nodes-and-clients/) para obter mais detalhes sobre nós e clientes e para obter uma lista de todas as implementações de clientes atuais. Você também pode encontrar um histórico de todas as melhorias do Ethereum na página [página Histórico](/ethereum-forks/). ### Clientes de execução {#execution-clients} - [Especificação do cliente de execução](https://github.com/ethereum/execution-specs) -- [Especificações da API de execução](https://github.com/ethereum/execution-apis) +- [Especificação da API de execução](https://github.com/ethereum/execution-apis) ### Clientes de consenso {#consensus-clients} - [Especificação do cliente de consenso](https://github.com/ethereum/consensus-specs) -- [Especificação da API Beacon](https://ethereum.github.io/beacon-APIs/#/Beacon/getStateRoot) +- [Especificação da API do Beacon](https://ethereum.github.io/beacon-APIs/#/Beacon/getStateRoot) -## Escalabilidade e desempenho {#scaling-and-performance} +## Dimensionamento e desempenho {#scaling-and-performance} -A escalabilidade do Ethereum é uma importnate área de foco dos pesquisadores Ethereum. As abordagens atuais incluem descarregar transações em rollups e torná-las o mais financeiramente acessíveis possível usando blobs de dados. Informações introdutórias sobre a escalabilidade do Ethereum estão disponíveis na nossa [página de escalabilidade](/developers/docs/scaling). +O dimensionamento do Ethereum é uma importante área de foco dos pesquisadores Ethereum. As abordagens atuais incluem descarregar transações em rollups e torná-las o mais financeiramente acessíveis possível usando blobs de dados. Informações introdutórias sobre o dimensionamento do Ethereum estão disponíveis em nossa [página Dimensionamento](/developers/docs/scaling). ### Camada 2 {#layer-2} -Atualmente, há vários protocolos de camada 2 que dimensionam o Ethereum por meio de diferentes técnicas para agrupar transações e protegê-las na camada 1 do Ethereum. Esse é um tópico de crescimento muito rápido, com muito potencial de pesquisa e desenvolvimento. +Atualmente, há vários protocolos de camada 2 que dimensionam o Ethereum por meio de diferentes técnicas para agrupar transações e protegê-las na camada 1 do Ethereum. Esse é um tópico cada vez mais relevante, com muito potencial de pesquisa e desenvolvimento. #### Leitura de apoio {#background-reading-2} - [Introdução à camada 2](/layer-2/) -- [Polynya: rollups, DA e cadeias modulares](https://polynya.medium.com/rollups-data-availability-layers-modular-blockchains-introductory-meta-post-5a1e7a60119d) +- [Polynya: Rollups, DA e cadeias modulares](https://polynya.medium.com/rollups-data-availability-layers-modular-blockchains-introductory-meta-post-5a1e7a60119d) #### Pesquisa recente {#recent-research-2} -- [Ordenação justa da Arbitrum para sequenciadores](https://eprint.iacr.org/2021/1465) -- [Camada 2 ethresear.ch](https://ethresear.ch/c/layer-2/32) -- [Roadmap centrado em rollup](https://ethereum-magicians.org/t/a-rollup-centric-ethereum-roadmap/4698) +- [Ordenação justa do Arbitrum para sequenciadores](https://eprint.iacr.org/2021/1465) +- [Ethresear.ch Layer 2](https://ethresear.ch/c/layer-2/32) +- [Roteiro centrado em rollup](https://ethereum-magicians.org/t/a-rollup-centric-ethereum-roadmap/4698) - [L2Beat](https://l2beat.com/) ### Pontes {#bridges} @@ -122,59 +122,63 @@ Uma área específica da camada 2 que exige mais pesquisa e desenvolvimento são #### Leitura de apoio {#background-reading-3} - [Introdução às pontes de blockchain](/bridges/) -- [Vitalik sobre pontes](https://old.reddit.com/r/ethereum/comments/rwojtk/ama_we_are_the_efs_research_team_pt_7_07_january/hrngyk8/) -- [Artigo de pontes de blockchain](https://medium.com/1kxnetwork/blockchain-bridges-5db6afac44f8) -- [Valor bloqueado em pontes](https://dune.com/eliasimos/Bridge-Away-(from-Ethereum)) +- [Vitalik: Sobre as pontes](https://old.reddit.com/r/ethereum/comments/rwojtk/ama_we_are_the_efs_research_team_pt_7_07_january/hrngyk8/) +- [Artigo sobre as pontes da blockchain](https://medium.com/1kxnetwork/blockchain-bridges-5db6afac44f8) +- [Valor bloqueado em pontes](https://dune.com/eliasimos/Bridge-Away-\(from-Ethereum\)) #### Pesquisa recente {#recent-research-3} - [Validação de pontes](https://stonecoldpat.github.io/images/validatingbridges.pdf) -### Fragmentação {#sharding} +### Sharding {#sharding} -A fragmentação do blockchain do Ethereum faz parte do roadmap de desenvolvimento há muito tempo. Entretanto, novas soluções de escalabilidade, como "Danksharding", atualmente ocupam o centro das atenções. +A fragmentação da blockchain Ethereum faz parte do roadmap de desenvolvimento há muito tempo. Entretanto, novas soluções de dimensionamento, como "Danksharding", ocupam atualmente o centro das atenções. + +O precursor do Danksharding completo, conhecido como Proto-Danksharding, entrou em operação com a melhoria de rede Cancun-Deneb ("Dencun"). + +[Mais informações sobre a melhoria Dencun](/roadmap/dencun/) #### Leitura de apoio {#background-reading-4} -- [Notas sobre Proto-Danksharding](https://notes.ethereum.org/@vbuterin/proto_danksharding_faq) -- [Vídeo Bankless Danksharding](https://www.youtube.com/watch?v=N5p0TB77flM) -- [Acervo de pesquisa de fragmentação do Ethereum (Ethereum Sharding Research Compendium)](https://notes.ethereum.org/@serenity/H1PGqDhpm?type=view) +- [Notas sobre o Proto-Danksharding](https://notes.ethereum.org/@vbuterin/proto_danksharding_faq) +- [Danksharding sem banco: vídeo](https://www.youtube.com/watch?v=N5p0TB77flM) +- [Compêndio de pesquisa sobre fragmentação do Ethereum](https://notes.ethereum.org/@serenity/H1PGqDhpm?type=view) - [Danksharding (Polynya)](https://polynya.medium.com/danksharding-36dc0c8067fe) #### Pesquisa recente {#recent-research-4} - [EIP-4844: Proto-Danksharding](https://eips.ethereum.org/EIPS/eip-4844) -- [Vitalik sobre amostragem de disponibilidade de dados e fragmentação](https://hackmd.io/@vbuterin/sharding_proposal) +- [Vitalik sobre sharding e amostragem de disponibilidade de dados](https://hackmd.io/@vbuterin/sharding_proposal) ### Hardware {#hardware} -[Executar nós](/developers/docs/nodes-and-clients/run-a-node/) em hardware modesto é fundamental para manter a descentralização do Ethereum. Portanto, a pesquisa ativa para minimizar os requisitos de hardware para executar os nós é uma importante área de pesquisa. +[A execução de nós](/developers/docs/nodes-and-clients/run-a-node/) em hardware modesto é fundamental para manter a descentralização do Ethereum. Portanto, a pesquisa ativa para minimizar os requisitos de hardware para executar os nós é uma importante área de pesquisa. #### Leitura de apoio {#background-reading-5} -- [Ethereum on ARM](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/) +- [Ethereum em ARM](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/) #### Pesquisa recente {#recent-research-5} -- [ecdsa em FPGAs](https://ethresear.ch/t/does-ecdsa-on-fpga-solve-the-scaling-problem/6738) +- [ecdsa sobre FPGAs](https://ethresear.ch/t/does-ecdsa-on-fpga-solve-the-scaling-problem/6738) ## Segurança {#security} -Segurança é um tópico amplo que pode incluir prevenção de spam/scam, segurança de carteira, segurança de hardware, segurança criptoeconômica, caça a bugs e testes de aplicativos e software cliente, bem como gerenciamento de chaves. Contribuir para o conhecimento nessas áreas ajudará a incentivar a adoção generalizada. +A segurança é um tópico amplo que pode incluir prevenção de spam/scam, segurança de carteira, segurança de hardware, segurança criptoeconômica, caça a bugs e testes de aplicativos e software cliente, bem como gerenciamento de chaves. Contribuir para o conhecimento nessas áreas ajudará a incentivar a adoção generalizada. -### Criptografia & ZKP {#cryptography--zkp} +### Criptografia e ZKP {#cryptography--zkp} -As provas de conhecimento zero (ZKP) e criptografia são essenciais para o desenvolvimento de privacidade e segurança no Ethereum e em seus aplicativos. O conhecimento zero é um espaço relativamente novo, mas em rápida evolução, com muitas oportunidades abertas de pesquisa e desenvolvimento. Algumas possibilidades incluem o desenvolvimento de implementações mais eficientes do [algoritmo de hash Keccak](https://hackmd.io/sK7v0lr8Txi1bgION1rRpw?view#Overview), encontrando compromissos polinomiais melhores do que os existentes ou reduzindo o custo dos circuitos de verificação de assinaturas e de geração de chaves públicas ecdsa. +As provas de conhecimento zero (ZKP) e criptografia são essenciais para o desenvolvimento de privacidade e segurança no Ethereum e em seus aplicativos. O conhecimento zero é um espaço relativamente novo, mas em rápida evolução, com muitas oportunidades abertas de pesquisa e desenvolvimento. Algumas possibilidades incluem o desenvolvimento de implementações mais eficientes do [algoritmo de hashing Keccak](https://hackmd.io/sK7v0lr8Txi1bgION1rRpw?view#Overview), a descoberta de compromissos polinomiais melhores do que os existentes atualmente ou a redução do custo dos circuitos de geração de chaves públicas e de verificação de assinaturas da ecdsa. #### Leitura de apoio {#background-reading-6} -- [Blog 0xparc](https://0xparc.org/blog) +- [Blog do 0xparc](https://0xparc.org/blog) - [zkp.science](https://zkp.science/) -- [Podcast Zero Knowledge](https://zeroknowledge.fm/) +- [Podcast da Zero Knowledge](https://zeroknowledge.fm/) #### Pesquisa recente {#recent-research-6} -- [Avanço recente na criptografia de curva elíptica](https://ethresear.ch/t/the-ec-fft-algorithm-without-elliptic-curve-and-isogenies/11346) +- [Avanços recentes na criptografia de curva elíptica](https://ethresear.ch/t/the-ec-fft-algorithm-without-elliptic-curve-and-isogenies/11346) - [Ethresear.ch ZK](https://ethresear.ch/c/zk-s-nt-arks/13) ### Carteiras {#wallets} @@ -185,98 +189,98 @@ As carteiras Ethereum podem ser extensões de navegador, aplicativos móveis e d - [Introdução às carteiras](/wallets/) - [Introdução à segurança da carteira](/security/) -- [Segurança no ethresear.ch](https://ethresear.ch/tag/security) -- [Abstração de conta EIP-2938](https://eips.ethereum.org/EIPS/eip-2938) -- [Abstração de conta EIP-4337](https://eips.ethereum.org/EIPS/eip-4337) +- [Ethresear.ch Security](https://ethresear.ch/tag/security) +- [EIP-2938: abstração de contas](https://eips.ethereum.org/EIPS/eip-2938) +- [EIP-4337: abstração de contas](https://eips.ethereum.org/EIPS/eip-4337) #### Pesquisa recente {#recent-research-7} -- [Carteiras de contratos inteligentes centradas em validação](https://ethereum-magicians.org/t/validation-focused-smart-contract-wallets/6603) +- [Carteiras de contratos inteligentes com foco em validação](https://ethereum-magicians.org/t/validation-focused-smart-contract-wallets/6603) - [O futuro das contas](https://ethereum-magicians.org/t/validation-focused-smart-contract-wallets/6603) -- [Opcodes EIP-3074 AUTH e AUTHCALL](https://eips.ethereum.org/EIPS/eip-3074) -- [Publicação de código em um endereço EOA](https://eips.ethereum.org/EIPS/eip-5003) +- [EIP-3074 AUTH e os Opcodes AUTHCALL](https://eips.ethereum.org/EIPS/eip-3074) +- [Código de publicação em um endereço EOA](https://eips.ethereum.org/EIPS/eip-5003) -## Comunidade, educação e divulgação {#community-education-and-outreach} +## Comunidade, educação e alcance {#community-education-and-outreach} -A integração de novos usuários ao Ethereum exige novos recursos educacionais e abordagens de divulgação. Isso pode incluir publicações em blogs e artigos, livros, podcasts, memes, recursos de ensino, eventos e qualquer outra atividade que desenvolva comunidades, receba novos iniciantes e eduque as pessoas sobre o Ethereum. +A integração de novos usuários ao Ethereum exige novos recursos educacionais e abordagens de divulgação. Isso pode incluir postagens e artigos de blog, livros, podcasts, memes, recursos de aprendizagem, eventos e qualquer outra coisa que crie comunidades, dê as boas-vindas a novos iniciantes e instrua as pessoas sobre o Ethereum. -### UX/UI {#uxui} +### UX/IU {#uxui} -Para atrair mais pessoas para o Ethereum, o ecossistema precisa melhorar a UX/UI. Isso exigirá que designers e especialistas de produtos reexaminem o design de carteiras e aplicativos. +Para atrair mais pessoas para o Ethereum, o ecossistema precisa melhorar a UX/IU. Isso exigirá que designers e especialistas de produtos revejam o design de carteiras e aplicativos. #### Leitura de apoio {#background-reading-8} -- [UX/UI no ethresear.ch](https://ethresear.ch/c/ui-ux/24) +- [Ethresear.ch UX/UI](https://ethresear.ch/c/ui-ux/24) #### Pesquisa recente {#recent-research-8} -- [Design Web3 no Discord](https://discord.gg/FsCFPMTSm9) -- [Princípios de Design Web3](https://www.web3designprinciples.com/) -- [Discussão sobre UX do Ethereum Magicians](https://ethereum-magicians.org/t/og-council-ux-follow-up/9032/3) +- [Web3 design no Discord](https://discord.gg/FsCFPMTSm9) +- [Princípios de design da Web3 no Discord](https://www.web3designprinciples.com/) +- [Discussão sobre o UX do Ethereum Magicians](https://ethereum-magicians.org/t/og-council-ux-follow-up/9032/3) -### Economia {#economics} +### Aspectos econômicos {#economics} -De modo geral, a pesquisa de economia no Ethereum segue duas abordagens: validar a segurança dos mecanismos que dependem de incentivos econômicos ("microeconomia") e analisar os fluxos de valor entre protocolos, aplicativos e usuários ("macroeconomia"). Há fatores criptoeconômicos complexos relacionados ao ativo nativo do Ethereum (ether) e aos tokens criados com base nele (por exemplo, NFTs e tokens ERC20). +De modo geral, a pesquisa dos aspectos econômicos no Ethereum segue duas abordagens: validar a segurança dos mecanismos que dependem de incentivos econômicos ("microeconomia") e analisar os fluxos de valor entre protocolos, aplicativos e usuários ("macroeconomia"). Há fatores criptoeconômicos complexos relacionados ao ativo nativo do Ethereum (ether) e aos tokens criados com base nele (por exemplo, NFTs e tokens ERC20). #### Leitura de apoio {#background-reading-9} -- [Grupo de incentivos eficientes](https://rig.ethereum.org/) -- [Workshop sobre ETHconomics no Devconnect](https://www.youtube.com/playlist?list=PLTLjFJ0OQOj5PHRvA2snoOKt2udVsyXEm) +- [Grupo de Incentivos Robustos](https://rig.ethereum.org/) +- [Workshop de ETHconomics na Devconnect](https://www.youtube.com/playlist?list=PLTLjFJ0OQOj5PHRvA2snoOKt2udVsyXEm) #### Pesquisa recente {#recent-research-9} - [Análise empírica do EIP1559](https://arxiv.org/abs/2201.05574) -- [Equilíbrio da oferta em circulação](https://ethresear.ch/t/circulating-supply-equilibrium-for-ethereum-and-minimum-viable-issuance-during-the-proof-of-stake-era/10954) -- [Quantificação de MEV: em que nível a floresta é escura?](https://arxiv.org/abs/2101.05511) +- [Equilíbrio de abastecimento circulante](https://ethresear.ch/t/circulating-supply-equilibrium-for-ethereum-and-minimum-viable-issuance-during-the-proof-of-stake-era/10954) +- [Quantificando o MEV: quão sombria é a floresta?](https://arxiv.org/abs/2101.05511) ### Espaço de blocos e mercados de taxas {#blockspace-fee-markets} -Os mercados de espaço de bloco regem a inclusão de transações de usuários finais, seja diretamente na Ethereum (Camada 1) ou em redes em ponte, por exemplo, rollups (Camada 2). No Ethereum, as transações são enviadas ao mercado de taxas implantado no protocolo como EIP-1559, protegendo a cadeia contra spam e congestionamento de preços. Em ambas as camadas, as transações podem produzir externalidades, conhecidas como Valor Máximo Extraível (MEV), que induzem novas estruturas de mercado para capturar ou gerenciar essas externalidades. +Os mercados de espaço de bloco regem a inclusão de transações de usuários finais, seja diretamente no Ethereum (Camada 1) ou em redes em ponte, por exemplo, rollups (Camada 2). No Ethereum, as transações são enviadas ao mercado de taxas implantado no protocolo como EIP-1559, protegendo a cadeia contra spam e congestionamento de preços. Em ambas as camadas, as transações podem produzir externalidades, conhecidas como Valor Máximo Extraível (MEV), que induzem novas estruturas de mercado para capturar ou gerenciar essas externalidades. #### Leitura de apoio {#background-reading-10} -- [Design do mecanismo da taxa de transação para Blockchain Ethereum: uma análise econômica do EIP-1559 (Tim Roughgarden, 2020)](https://timroughgarden.org/papers/eip1559.pdf) -- [Simulações do EIP-1559 (Grupo de incentivos eficientes)](https://ethereum.github.io/abm1559) +- [Design do mecanismo da taxa de transação para Blockchain Ethereum: uma análise econômica do EIP-1559 (Tim Roughgarden, 2020](https://timroughgarden.org/papers/eip1559.pdf) +- [Simulações da EIP-1559 (Grupo de Incentivos Robustos)](https://ethereum.github.io/abm1559) - [Economia de rollup a partir dos primeiros princípios](https://barnabe.substack.com/p/understanding-rollup-economics-from?utm_source=url) -- [Flash Boys 2.0: aceleração, reordenação de transações e instabilidade de consenso em corretoras descentralizadas](https://arxiv.org/abs/1904.05234) +- [Flash Boys 2.0: Frontrunning, Reordenação de Transações e Instabilidade de Consenso em Exchanges Descentralizadas](https://arxiv.org/abs/1904.05234) #### Pesquisa recente {#recent-research-10} -- [Apresentação de vídeo EIP-1559 multidimensional](https://youtu.be/QbR4MTgnCko) -- [MEV entre domínios](http://arxiv.org/abs/2112.01472) -- [Leilões de MEV](https://ethresear.ch/t/mev-auction-auctioning-transaction-ordering-rights-as-a-solution-to-miner-extractable-value/6788) +- [Apresentação em vídeo do EIP-1559 multidimensional](https://youtu.be/QbR4MTgnCko) +- [MEV de domínio cruzado](http://arxiv.org/abs/2112.01472) +- [Leilões MEV](https://ethresear.ch/t/mev-auction-auctioning-transaction-ordering-rights-as-a-solution-to-miner-extractable-value/6788) ### Incentivos de prova de participação {#proof-of-stake-incentives} -Os validadores usam o ativo nativo do Ethereum (ether) como garantia contra comportamento desonesto. As criptoeconomias disso determinam a segurança da rede. Validadores sofisticados podem ser capazes de explorar as nuances da camada de incentivo para lançar ataques explícitos. +Os validadores usam o ativo nativo do Ethereum (ether) como garantia contra comportamento desonesto. Os aspectos criptoeconômicos disso determinam a segurança da rede. Validadores sofisticados podem ser capazes de explorar as nuances da camada de incentivo para lançar ataques explícitos. #### Leitura de apoio {#background-reading-11} -- [Masterclass sobre modelo econômico e de economia Ethereum](https://github.com/CADLabs/ethereum-economic-model) -- [Simulações de incentivos PoS (Grupo de incentivos eficientes)](https://ethereum.github.io/beaconrunner/) +- [Aula magna sobre os aspectos econômicos do Ethereum e modelo econômico](https://github.com/CADLabs/ethereum-economic-model) +- [Simulações de incentivos de PoS (Grupo de Incentivos Robustos)](https://ethereum.github.io/beaconrunner/) #### Pesquisa recente {#recent-research-11} -- [Aumentar a resistência à censura de transações no âmbito da separação proponente/construtor (PBS)](https://notes.ethereum.org/s3JToeApTx6CKLJt8AbhFQ) -- [Três ataques ao PoS Ethereum](https://arxiv.org/abs/2110.10086) +- [Aumento da resistência à censura de transações sob separação entre proponente e construtor (PBS)](https://notes.ethereum.org/s3JToeApTx6CKLJt8AbhFQ) +- [Três ataques à PoS Ethereum](https://arxiv.org/abs/2110.10086) -### Liquidez de participação e derivativos {#liquid-staking-and-derivatives} +### Staking líquido e derivativos {#liquid-staking-and-derivatives} -A participação líquida permite que os usuários com menos de 32 ETH recebam rendimentos de participação ao trocar ether por um token que representa o ether participado que pode ser utilizado em DeFi. Entretanto, os incentivos e a dinâmica de mercado associados à participação líquida ainda estão sendo descobertos, bem como seu efeito na segurança do Ethereum (por exemplo, riscos de centralização). +O staking líquido permite que os usuários com menos de 32 ETH recebam rendimentos de participação ao trocar ether por um token que representa o ether participado que pode ser utilizado em DeFi. No entanto, os incentivos e a dinâmica de mercado associados ao staking líquido ainda estão sendo descobertos, bem como seu efeito na segurança do Ethereum (por exemplo, riscos de centralização). #### Leitura de apoio {#background-reading-12} -- [Participação líquida Ethresear.ch](https://ethresear.ch/search?q=liquid%20staking) -- [Lido: o caminho para a participação de Ethereum sem confiança](https://blog.lido.fi/the-road-to-trustless-ethereum-staking/) -- [Rocket Pool: introdução ao protocolo de participação](https://medium.com/rocket-pool/rocket-pool-staking-protocol-part-1-8be4859e5fbd) +- [Staking líquido em Ethresear.ch](https://ethresear.ch/search?q=liquid%20staking) +- [Lido: O caminho para o staking de Ethereum sem confiança](https://blog.lido.fi/the-road-to-trustless-ethereum-staking/) +- [Rocket Pool: Introdução ao protocolo de staking](https://medium.com/rocket-pool/rocket-pool-staking-protocol-part-1-8be4859e5fbd) #### Pesquisa recente {#recent-research-12} -- [Processar saques do Lido](https://ethresear.ch/t/handling-withdrawals-in-lidos-eth-liquid-staking-protocol/8873) +- [Tratamento de saques do Lido](https://ethresear.ch/t/handling-withdrawals-in-lidos-eth-liquid-staking-protocol/8873) - [Credenciais de saque](https://ethresear.ch/t/withdrawal-credential-rotation-from-bls-to-eth1/8722) -- [Os riscos dos derivativos de participação líquida](https://notes.ethereum.org/@djrtwo/risks-of-lsd) +- [Os riscos dos derivativos de staking líquido](https://notes.ethereum.org/@djrtwo/risks-of-lsd) -## Testando {#testing} +## Testes {#testing} ### Verificação formal {#formal-verification} @@ -290,20 +294,20 @@ A verificação formal consiste em escrever código para verificar se as especif #### Pesquisa recente {#recent-research-13} - [Verificação formal do contrato de depósito](https://github.com/runtimeverification/deposit-contract-verification) -- [Verificação formal da especificação de Beacon Chain](https://github.com/runtimeverification/deposit-contract-verification) +- [Verificação formal da especificação da Beacon Chain](https://github.com/runtimeverification/deposit-contract-verification) -## Ciência e análise de dados {#data-science-and-analytics} +## Ciência de dados e análise {#data-science-and-analytics} São necessárias mais ferramentas de análise de dados e painéis que ofereçam informações detalhadas sobre a atividade no Ethereum e a integridade da rede. ### Leitura de apoio {#background-reading-14} -- [Dune Analytics](https://dune.com/browse/dashboards) +- [Análise Dune](https://dune.com/browse/dashboards) - [Painel de diversidade do cliente](https://clientdiversity.org/) #### Pesquisa recente {#recent-research-14} -- [Análise de dados do grupo de incentivos eficientes](https://rig.ethereum.org/) +- [Análise robusta de dados do grupo de incentivos](https://rig.ethereum.org/) ## Aplicativos e ferramentas {#apps-and-tooling} @@ -311,17 +315,17 @@ A camada de aplicativos oferece suporte a um ecossistema diversificado de progra ### DeFi {#defi} -Finanças Descentralizadas (DeFi) é uma das principais classes de aplicações criadas com base no Ethereum. O objetivo da DeFi é criar "legos de dinheiro" compostos que permitam aos usuários armazenar, transferir, emprestar, tomar emprestado e investir ativos criptográficos utilizando contratos inteligentes. DeFi é um espaço em rápida evolução que está em constante atualização. Pesquisas sobre protocolos seguros, eficientes e acessíveis são continuamente necessárias. +Finanças Descentralizadas (DeFi) é uma das principais classes de aplicativos criados com base no Ethereum. O objetivo da DeFi é criar "legos de dinheiro" compostos que permitam aos usuários armazenar, transferir, emprestar, tomar emprestado e investir ativos criptográficos utilizando contratos inteligentes. DeFi é um espaço em rápida evolução que está em constante atualização. Pesquisas sobre protocolos seguros, eficientes e acessíveis são continuamente necessárias. #### Leitura de apoio {#background-reading-15} - [DeFi](/defi/) -- [Coinbase: o que é DeFi?](https://www.coinbase.com/learn/crypto-basics/what-is-defi) +- [Coinbase: O que é DeFi?](https://www.coinbase.com/learn/crypto-basics/what-is-defi) #### Pesquisa recente {#recent-research-15} -- [Finanças Descentralizadas, propriedade centralizada?](https://arxiv.org/pdf/2012.09306.pdf) -- [Optimism: o caminho para as transações abaixo do dólar](https://medium.com/ethereum-optimism/the-road-to-sub-dollar-transactions-part-2-compression-edition-6bb2890e3e92) +- [Finanças descentralizadas, propriedade centralizada?](https://arxiv.org/pdf/2012.09306.pdf) +- [Optimism: O caminho para transações por menos de um dólar](https://medium.com/ethereum-optimism/the-road-to-sub-dollar-transactions-part-2-compression-edition-6bb2890e3e92) ### DAOs {#daos} @@ -329,8 +333,8 @@ Um caso de uso de impacto para o Ethereum é a capacidade de se organizar de for #### Leitura de apoio {#background-reading-16} -- [Introdução às DAOs](/dao/) -- [Dao Collective](https://daocollective.xyz/) +- [Introdução a DAOs](/dao/) +- [Coletivo DAO](https://daocollective.xyz/) #### Pesquisa recente {#recent-research-16} @@ -342,42 +346,42 @@ As ferramentas para desenvolvedores do Ethereum têm melhorado rapidamente. Há #### Leitura de apoio {#background-reading-17} -- [Ferramental por linguagem de programação](/developers/docs/programming-languages/) -- [Frameworks do desenvolvedor](/developers/docs/frameworks/) -- [Lista de ferramentas do desenvolvedor de consenso](https://github.com/ConsenSys/ethereum-developer-tools-list) +- [Ferramentas por linguagem de programação](/developers/docs/programming-languages/) +- [Estruturas de desenvolvedor](/developers/docs/frameworks/) +- [Lista de ferramentas de desenvolvedor do consenso](https://github.com/ConsenSys/ethereum-developer-tools-list) - [Padrões de token](/developers/docs/standards/tokens/) -- [CryptoDevHub: ferramentas EVM](https://cryptodevhub.io/wiki/ethereum-virtual-machine-tools) +- [CryptoDevHub: Ferramentas EVM](https://cryptodevhub.io/wiki/ethereum-virtual-machine-tools) #### Pesquisa recente {#recent-research-17} -- [Canal de ferramental de consenso Eth P&D Discord](https://discordapp.com/channels/595666850260713488/746343380900118528) +- [Canal de ferramentas de consenso do Discord Eth R&D](https://discordapp.com/channels/595666850260713488/746343380900118528) ### Oráculos {#oracles} -Os oráculos importam dados fora da cadeia para o blockchain de uma maneira descentralizada e sem permissão. A obtenção desses dados em cadeia permite que os dApps sejam reativos a fenômenos reais, como flutuações de preço em ativos reais, eventos em aplicativos fora da cadeia ou inclusive alterações climáticas. +Os oráculos importam dados offchain para a blockchain de forma descentralizada e sem permissão. Obter esses dados onchain permite que os dapps sejam reativos a fenômenos do mundo real, como flutuações de preços em ativos do mundo real, eventos em aplicativos offchain ou até mesmo mudanças no clima. #### Leitura de apoio {#background-reading-18} -- [Introdução a oráculos](/developers/docs/oracles/) +- [Introdução aos oráculos](/developers/docs/oracles/) #### Pesquisa recente {#recent-research-18} -- [Pesquisa de oráculos no blockchain](https://arxiv.org/pdf/2004.07140.pdf) -- [Artigo técnico da Chainlink](https://chain.link/whitepaper) +- [Pesquisa sobre oráculos de blockchain](https://arxiv.org/pdf/2004.07140.pdf) +- [Whitepaper da Chainlink](https://chain.link/whitepaper) -### Segurança do aplicativo {#app-security} +### Segurança de aplicativos {#app-security} -Os hacks na Ethereum geralmente exploram vulnerabilidades em aplicativos individuais, em vez de no próprio protocolo. Os hackers e os desenvolvedores de aplicativos estão em uma luta de braço para desenvolver novos ataques e defesas. Isso significa que sempre há necessidade de pesquisa e desenvolvimento importantes para manter os aplicativos protegidos contra invasões. +Os hakeios no Ethereum geralmente exploram vulnerabilidades em aplicativos individuais, em vez de no próprio protocolo. Os hackers e os desenvolvedores de aplicativos estão em uma luta de braço para desenvolver novos ataques e defesas. Isso significa que sempre há necessidade de pesquisa e desenvolvimento importantes para manter os aplicativos protegidos contra invasões. #### Leitura de apoio {#background-reading-19} - [Relatório de exploração de wormhole](https://blog.chainalysis.com/reports/wormhole-hack-february-2022/) -- [Lista de post-mortems de hack de contratos do Ethereum](https://forum.openzeppelin.com/t/list-of-ethereum-smart-contracts-post-mortems/1191) -- [Rekt News](https://twitter.com/RektHQ?s=20&t=3otjYQdM9Bqk8k3n1a1Adg) +- [Lista de post-mortems de hackeios de contratos Ethereum](https://forum.openzeppelin.com/t/list-of-ethereum-smart-contracts-post-mortems/1191) +- [Rekt News](https://x.com/RektHQ?s=20&t=3otjYQdM9Bqk8k3n1a1Adg) #### Pesquisa recente {#recent-research-19} -- [Aplicações ethresear.ch](https://ethresear.ch/c/applications/18) +- [Ethresear.ch Applications](https://ethresear.ch/c/applications/18) ### Pilha de tecnologia {#technology-stack} @@ -385,11 +389,11 @@ A descentralização de toda a pilha de tecnologia Ethereum é uma importante á #### Leitura de apoio {#background-reading-20} -- [Pilha de Ethereum](/developers/docs/ethereum-stack/) -- [Coinbase: introdução à pilha Web3](https://blog.coinbase.com/a-simple-guide-to-the-web3-stack-785240e557f0) +- [Pilha Ethereum](/developers/docs/ethereum-stack/) +- [Coinbase: Introdução ao Web3 Stack](https://blog.coinbase.com/a-simple-guide-to-the-web3-stack-785240e557f0) - [Introdução aos contratos inteligentes](/developers/docs/smart-contracts/) - [Introdução ao armazenamento descentralizado](/developers/docs/storage/) #### Pesquisa recente {#recent-research-20} -- [Composição de contrato inteligente](/developers/docs/smart-contracts/composability/) +- [Composição de contratos inteligentes](/developers/docs/smart-contracts/composability/) diff --git a/public/content/translations/pt-br/community/support/faq/index.md b/public/content/translations/pt-br/community/support/faq/index.md new file mode 100644 index 00000000000..8be6338cbff --- /dev/null +++ b/public/content/translations/pt-br/community/support/faq/index.md @@ -0,0 +1,77 @@ +--- +title: Perguntas frequentes +description: Common Ethereum questions about wallets, transactions, staking, and more. +lang: pt-br +--- + +# Perguntas mais frequentes {#faq} + +## I sent crypto to the wrong address {#wrong-wallet} + +Uma transação enviada em Ethereum é irreversível. Unfortunately, if you sent ETH or tokens to the wrong wallet, there is no way to reverse the transaction. + +**What you can do:** + +- **If you know the owner of the address**, contact them directly and ask them to return the funds +- **If the address belongs to an exchange or known service**, contact their support team, as they may be able to help +- **If you sent tokens to a contract address**, check whether the contract has a withdrawal or recovery function (this is rare) + +In most cases, there is no way to recover the funds. No central organization, entity, or person owns Ethereum, which means no one can reverse transactions. Always double-check the recipient address before confirming. + +## I lost access to my wallet {#lost-wallet-access} + +Your recovery options depend on the type of wallet you use. + +### If you have your seed phrase (recovery phrase) + +You can restore your wallet in any compatible wallet app using your seed phrase. This is why it is critical to keep your seed phrase stored safely offline. Check your wallet provider's documentation for restore instructions. + +### If you have lost your seed phrase + +Without your seed phrase or private keys, your funds cannot be recovered. No one, including ethereum.org, can reset your password or restore access to a self-custody wallet. + +### If your account is on an exchange + +If your account is on a centralized exchange like Coinbase, Binance, or Kraken, contact the exchange's support team directly. They control accounts on their platform and may be able to help with password resets or account recovery. + + + + + + +**Never share your seed phrase with anyone** claiming to help you recover your wallet. This is one of the most common scam tactics. No legitimate service will ever ask for your seed phrase. + + + + + + How to use a wallet + + +## My transaction is stuck or pending {#stuck-transaction} + +Transactions on Ethereum can get stuck when the gas fee you set was lower than what the network currently requires. Most wallets let you fix this: + +- **Speed up:** Resubmit the same transaction with a higher gas fee +- **Cancel:** Send a 0 ETH transaction to your own address using the same nonce as the pending transaction + +### Helpful guides + +- [How to speed up or cancel a pending transaction on MetaMask](https://support.metamask.io/transactions-and-gas/transactions/how-to-speed-up-or-cancel-a-pending-transaction/) +- [Como cancelar transações pendentes do Ethereum](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) + +## Como eu posso solicitar minha doação de Ethereum? {#giveaway-scam} + +Doações/airdrops de Ethereum são golpes criados para roubar o seu ETH. Do not be tempted by offers that seem too good to be true. If you send ETH to a giveaway address, you will not receive a giveaway, and you will not be able to recover your funds. + +[Mais sobre prevenção de golpes](/security/#common-scams) + +## How do I stake ETH? {#how-to-stake} + +Para se tornar um validador, você deve participar com 32 ETH no contrato de depósito do Ethereum e configurar um nó validador. You can also participate with less ETH through staking pools. + +More information is available on our [staking pages](/staking/) and at [the staking launchpad](https://launchpad.ethereum.org/). + +## Como minero Ethereum? {#mining-ethereum} + +A mineração do Ethereum não é mais possível. Mining was switched off when Ethereum moved from [proof-of-work](/glossary/#pow) to [proof-of-stake](/glossary/#pos) during [The Merge](/roadmap/merge/) in September 2022. Agora, em vez de mineradores, o Ethereum tem validadores. Qualquer pessoa pode fazer [stake](/glossary/#staking) de ETH e receber recompensas de staking por executar o software de validador para proteger a rede. diff --git a/public/content/translations/pt-br/community/support/index.md b/public/content/translations/pt-br/community/support/index.md deleted file mode 100644 index efc1b1e6d97..00000000000 --- a/public/content/translations/pt-br/community/support/index.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: Suporte Ethereum -description: Obtenha suporte no ecossistema Ethereum. -lang: pt-br ---- - -# Suporte Ethereum {#support} - -## Suporte oficial do Ethereum {#official-support} - -Você está procurando pelo suporte oficial do Ethereum? A primeira coisa que você deve saber é que o Ethereum é descentralizado. Isso significa que nenhuma organização central, entidade ou pessoa é proprietária do Ethereum, e, por isso, não existem canais de suporte oficiais. - -Compreender a natureza descentralizada do Ethereum é vital porque qualquer pessoa que afirme ser um suporte oficial para o Ethereum está provavelmente tentando enganar você! A melhor proteção contra os golpistas é educar-se e levar a segurança a sério. - - - Segurança e prevenção de fraude do Ethereum - - - - Aprenda os conceitos básicos do Ethereum - - -Apesar da falta de suporte oficial, muitos grupos, comunidades e projetos em todo o ecossistema Ethereum estão felizes em ajudar, e você pode encontrar muitas informações e recursos úteis nesta página. Ainda tem dúvidas? Junte-se ao [Discord ethereum.org](https://discord.gg/ethereum-org) e tentaremos ajudar. - -## Suporte a carteiras {#wallet-support} - -Está tendo problemas com sua carteira? A maioria das carteiras tem equipes de suporte dedicadas que podem ajudar: - -- [MetaMask](https://metamask.zendesk.com/hc/) -- [Argent](https://support.argent.xyz/hc/) -- [MyEtherWallet](https://help.myetherwallet.com/) - -_Esta não é uma lista exaustiva. Precisa de ajuda para encontrar suporte para uma carteira específica? Una-se ao [Discord da ethereum.org](https://discord.gg/ethereum-org) e tentaremos ajudar._ - -Procurando uma carteira Ethereum? [Veja a nossa lista completa de carteiras Ethereum](/wallets/find-wallet/). - -## Criando dapps {#building-support} - -Desevolver um dapp pode ser difícil. Aqui estão alguns espaços voltados ao desenvolvimento com desenvolvedores Ethereum experientes dispostos a ajudar. - -- [Universidade Alchemy](https://university.alchemy.com/#starter_code) -- [Discord CryptoDevs](https://discord.com/invite/5W5tVb3) -- [Stackexchange do Ethereum](https://ethereum.stackexchange.com/) -- [Universidade Web3](https://www.web3.university/) -- [LearnWeb3](https://discord.com/invite/learnweb3) - -Você também pode encontrar documentação e guias de desenvolvimento em nossa seção [Recursos de desenvolvedor Ethereum](/developers/). - -### Ferramentas {#dapp-tooling} - -Sua pergunta está relacionada a uma ferramenta, projeto ou biblioteca em particular? A maioria dos projetos tem servidores de bate-papo ou fóruns dedicados a apoiar você. - -Aqui estão alguns exemplos populares: - -- [Solidity](https://app.element.io/#/room/#solidity:matrix.org) -- [ethers.js](https://discord.gg/6jyGVDK6Jx) -- [web3.js](https://discord.gg/GsABYQu4sC) -- [Hardhat](https://discord.gg/xtrMGhmbfZ) -- [Alchemy](http://alchemy.com/discord) -- [Tenderly](https://discord.gg/fBvDJYR) - -## Executando um nó {#node-support} - -Se você estiver executando um nó ou validador, aqui estão algumas comunidades que se dedicam a ajudá-lo a começar. - -- [Discord EthStaker](https://discord.gg/ethstaker) -- [Reddit EthStaker](https://www.reddit.com/r/ethstaker) - -A maioria das equipes que estão construindo clientes Ethereum também tem espaços dedicados ao público, onde você pode obter suporte e fazer perguntas. - -### Clientes de execução {#execution-clients} - -- [Geth](https://discord.gg/FqDzupGyYf) -- [Nethermind](https://discord.gg/YJx3pm8z5C) -- [Besu](https://discord.gg/p8djYngzKN) -- [Erigon](https://github.com/ledgerwatch/erigon/issues) - -### Clientes de consenso {#consensus-clients} - -- [Prysm](https://discord.gg/prysmaticlabs) -- [Nimbus](https://discord.gg/nSmEH3qgFv) -- [Lighthouse](https://discord.gg/cyAszAh) -- [Teku](https://discord.gg/7hPv2T6) -- [Lodestar](https://discord.gg/aMxzVcr) - -Você também pode [aprender a executar um nó aqui](/developers/docs/nodes-and-clients/run-a-node/). - -## Perguntas frequentes {#faq} - -### Enviei ETH para a carteira errada {#wrong-wallet} - -Uma transação enviada em Ethereum é irreversível. Infelizmente, se você enviou ETH para a carteira errada, não há como recuperar esses fundos. Nenhuma organização central, entidade ou pessoa é proprietária do Ethereum, o que significa que ninguém pode reverter transações. Portanto, é vital verificar sempre as suas transações antes de enviá-las. - -### Como eu posso solicitar minha doação de Ethereum? {#giveaway-scam} - -Doações/airdrops de Ethereum são golpes criados para roubar o seu ETH. Não se sinta tentado por ofertas que parecem boas demais para serem verdadeiras — se você enviar ETH para um endereço de doação, não receberá nenhuma doação/airdrop e não poderá recuperar seus fundos. - -[Mais sobre prevenção de fraudes](/security/#common-scams) - -### Minha transação está bloqueada {#stuck-transaction} - -Transações em Ethereum podem algumas vezes ficar bloqueadas se você tiver enviado uma taxa de transação menor do que a necessária devido à demanda na rede. Muitas carteiras oferecem uma opção para reenviar a mesma transação com uma taxa de transação maior para permitir que a transação seja processada. Como alternativa, você pode cancelar uma transação pendente enviando uma transação para seu próprio endereço e usando o mesmo nonce que a transação pendente. - -[Como acelerar ou cancelar uma transação pendente no MetaMask](https://metamask.zendesk.com/hc/en-us/articles/360015489251-How-to-speed-up-or-cancel-a-pending-transaction) - -[Como cancelar transações pendentes no Ethereum](https://info.etherscan.com/how-to-cancel-ethereum-pending-transactions/) - -### Como minero Ethereum? {#mining-ethereum} - -A mineração do Ethereum não é mais possível. A mineração foi desativada quando o Ethereum passou de prova de trabalho para prova de participação. Agora, em vez de mineradores, o Ethereum tem validadores. Os validadores participam com ETH e recebem recompensas de aposta para proteger a rede. - -### Como me torno um participante/validador? {#become-validator} - -Para se tornar um validador, você deve participar com 32 ETH no contrato de depósito do Ethereum e configurar um nó validador. Mais informações estão disponíveis em nossas [páginas de participação](/staking) e na [plataforma de lançamento de participação](https://launchpad.ethereum.org/). diff --git a/public/content/translations/pt-br/community/support/misconceptions/index.md b/public/content/translations/pt-br/community/support/misconceptions/index.md new file mode 100644 index 00000000000..997e879088f --- /dev/null +++ b/public/content/translations/pt-br/community/support/misconceptions/index.md @@ -0,0 +1,73 @@ +--- +title: Common misconceptions about Ethereum +description: Clearing up the most common misunderstandings about how Ethereum works. +lang: pt-br +--- + +# Common misconceptions about Ethereum {#misconceptions} + +## O Ethereum é uma empresa? {#not-a-company} + +Ethereum is open-source, decentralized technology maintained by thousands of contributors worldwide. There is no company called "Ethereum" that manages accounts, holds funds, or provides customer support. + +The [Ethereum Foundation](https://ethereum.foundation/) is a non-profit organization that supports Ethereum's development, but it does not own or control the network. No single entity does. + +**[ethereum.org](/)** is a community-run educational resource. It is not an exchange, wallet, or financial institution. It does not hold any user funds and cannot access any accounts. + + + O que é o Ethereum? + + +## Alguém pode recuperar ou congelar meus fundos? {#no-fund-access} + +Unlike a bank, there is no central authority on Ethereum that can freeze, seize, or recover funds. The person holding the private keys (or seed phrase) has full and sole control over a wallet. + +This means: + +- **No one can recover funds** you sent to the wrong address +- **No one can reverse** a transaction after it is confirmed +- **No one can freeze** your wallet or block your transactions +- **No one can reset your password** if you lose your seed phrase + +This is why protecting your seed phrase is critical. It is the only way to access your wallet. If it is lost or stolen, there is no recovery option. + + + Segurança e prevenção de golpes no Ethereum + + +## Ainda posso minerar Ethereum? {#no-mining} + +Ethereum switched from [proof-of-work](/glossary/#pow) to [proof-of-stake](/glossary/#pos) during [The Merge](/roadmap/merge/) in September 2022. Mining is no longer possible on Ethereum. + +The network is now secured by validators who [stake](/glossary/#staking) ETH. Anyone can participate: + +- **Solo staking:** Run your own validator with 32 ETH—[learn more](/staking/solo/) +- **Staking as a service:** Delegate node operation while keeping your keys—[learn more](/staking/saas/) +- **Pooled staking:** Stake with less than 32 ETH by joining a pool—[learn more](/staking/pools/) + + + Learn more about staking + + +## Existe uma equipe de suporte do Ethereum? {#no-support-team} + +Looking for "official Ethereum support" is similar to looking for "official internet support." This of course doesn't exist, but depending on your issue you may be able to seek out support from your internet service provider, your router hardware manufacturer, or one of the companies behind the device, app or website you're using. + +Ethereum is similar. There is no company, support team, or help desk behind Ethereum as a whole, but depending on the issue you may find help by reaching out to your _wallet provider_, _staking service_, _exchange_, _financial institution_ or the _team maintaining an app_ you're using. + +Since Ethereum is publicly transparent by default, you may also find [block explorers](/developers/docs/data-and-analytics/block-explorers/), [analytics tools](/developers/tools/analytics/), and other [online investigation resources](/community/support/scams/#analyze) useful in looking into a problem directly. + +That said, no one from Ethereum or ethereum.org will ever: + +- Contact you via direct message +- Ask for your seed phrase or private keys +- Ask you to send ETH to verify your wallet +- Offer to help you recover funds for a fee + +**Anyone doing any of the above is trying to scam you.** + +If you need help, the real communities that can assist are listed on the [support page](/community/support/). These are volunteer-run, open communities—not official support channels. + + + Segurança e prevenção de golpes no Ethereum + diff --git a/public/content/translations/pt-br/community/support/scams/index.md b/public/content/translations/pt-br/community/support/scams/index.md new file mode 100644 index 00000000000..ad5f0de0ddf --- /dev/null +++ b/public/content/translations/pt-br/community/support/scams/index.md @@ -0,0 +1,159 @@ +--- +title: Scam help & reporting +description: What to do if you have been scammed, how to secure your remaining assets, and where to report fraud. +lang: pt-br +--- + +# I was scammed or lost funds {#scam-help} + +Cryptocurrency scams target people of all experience levels, including professionals in finance and technology. You are not alone, and being here is the right first step. + + + + + + +**No one can reverse blockchain transactions.** If someone contacts you claiming they can recover your funds for a fee, that is almost certainly a second scam. See [recovery scams](#recovery-scams) below. + + + + +## Secure your remaining assets {#secure-assets} + +If you interacted with a scammer or suspect your wallet is compromised, take these steps immediately: + +1. **Move remaining funds** to a new, secure wallet that the scammer does not have access to +2. **Revoke token approvals.** Scammers often trick you into approving unlimited token spending. Revoking these permissions prevents further draining of your wallet +3. **Change passwords** on any exchange accounts that may be linked +4. **Enable two-factor authentication (2FA)** on all crypto-related accounts + +### How to revoke token approvals {#revoke-approvals} + +When you interact with a dapp or smart contract, you may have granted it permission to spend your tokens. If a scammer tricked you into approving a malicious contract, they can continue draining your tokens even after the initial scam. + +Use these tools to check and revoke approvals: + +- [Revoke.cash](https://revoke.cash/): connect your wallet to see all active approvals and revoke them +- [Revokescout](https://revoke.blockscout.com/): check and revoke approvals via Blockscout +- [Etherscan Token Approval Checker](https://etherscan.io/tokenapprovalchecker): check and revoke approvals via Etherscan + + + Step-by-step guide: How to revoke token access + + +## Report scam addresses and websites {#report} + +Reporting helps warn other users and may assist law enforcement investigations. Document everything: transaction hashes, wallet addresses, screenshots, and any communication with the scammer. + +### Report a scam address {#report-address} + +- [Chainabuse](https://www.chainabuse.com/): community-driven scam and fraud reporting database. Submit reports and search for known scam addresses +- [Etherscan report](https://info.etherscan.com/report-address/): flag an address on the most-used Ethereum block explorer +- [CryptoScamDB](https://cryptoscamdb.org/): open-source database tracking cryptocurrency scams + +### Report a scam website or social media account {#report-website} + +- [PhishTank](https://phishtank.org/): submit and verify phishing URLs +- [Google Safe Browsing](https://safebrowsing.google.com/safebrowsing/report_phish/): report phishing sites to Google so they get blocked in Chrome and other browsers +- [Netcraft](https://report.netcraft.com/report/mistake): report malicious and fraudulent websites +- Report directly on the social media platform where the scam occurred (Twitter/X, Discord, Telegram all have reporting features) + +### Report to law enforcement {#report-law-enforcement} + +- **United States:** [FBI Internet Crime Complaint Center (IC3)](https://www.ic3.gov/) +- **United Kingdom:** [Action Fraud](https://www.actionfraud.police.uk/) +- **European Union:** [Europol](https://www.europol.europa.eu/report-a-crime) +- **Other countries:** file a report with your local police. Cryptocurrency fraud is a crime in most jurisdictions + +## Analyze what happened {#analyze} + +Understanding where your funds went can help with reports and may support recovery efforts if the funds land on a centralized exchange. + +- [Blockscout](https://eth.blockscout.com/): open-source block explorer to look up any transaction hash or wallet address to see where funds were sent +- [Etherscan](https://etherscan.io/): look up any transaction hash or wallet address to see where funds were sent +- [Chainabuse lookup](https://www.chainabuse.com/): check if an address has already been reported by other victims +- [MetaSleuth](https://metasleuth.io/) by BlockSec: visual transaction tracing tool that maps fund flows + +**If funds were sent to a centralized exchange** (like Coinbase, Binance, Kraken), contact their support team immediately with the transaction details. Exchanges can sometimes freeze accounts flagged for fraud. + +## The hard truth {#hard-truth} + +Because Ethereum is decentralized, no central authority can reverse transactions or recover stolen funds. Once a transaction is confirmed on the blockchain, it is final. + +Reporting is still valuable. Reports help law enforcement track organized fraud rings, and flagging addresses on Chainabuse and Etherscan warns future potential victims. + +## Types of scams to watch for {#scam-types} + + + +Scammers create fake giveaways promising to multiply your ETH or give you free tokens. They often impersonate well-known figures like Vitalik Buterin. If you send ETH to a "giveaway" address, you will not receive anything back. + +**Remember:** Vitalik and other prominent figures will never ask you to send them ETH. + +[More on common scams](/security/#common-scams) + + + + +Scammers impersonate Ethereum team members, moderators, or support agents on Discord, Telegram, and social media. They may send you direct messages offering help or claiming there is a problem with your account. + +**Remember:** + +- There is no "Ethereum support team" +- Real moderators will never DM you first +- Never share your seed phrase or private keys with anyone, for any reason +- Never click links sent in unsolicited messages + + + + +Recovery scams specifically target people who have already lost funds. Scammers monitor social media for people talking about being scammed, then reach out posing as "blockchain investigators" or "crypto recovery experts." + +They promise to trace and recover your stolen crypto for an upfront fee. After you pay, they disappear. + +**No legitimate service can reverse blockchain transactions.** Anyone promising this is lying. This is one of the most common follow-up scams. + + + + +Phishing sites look identical to real wallet apps, exchanges, or DeFi platforms. They trick you into entering your seed phrase or connecting your wallet, then drain your funds. + +**Protect yourself:** + +- Always verify the URL before connecting your wallet +- Bookmark the official sites you use regularly +- Never enter your seed phrase on any website. Legitimate apps never ask for it +- Use [PhishTank](https://phishtank.org/) to check suspicious URLs + + + How to identify scam tokens + + + + + Full guide to Ethereum security and scam prevention + diff --git a/public/content/translations/pt-br/contributing/adding-desci-projects/index.md b/public/content/translations/pt-br/contributing/adding-desci-projects/index.md index 00f715196d2..19506e324fc 100644 --- a/public/content/translations/pt-br/contributing/adding-desci-projects/index.md +++ b/public/content/translations/pt-br/contributing/adding-desci-projects/index.md @@ -1,6 +1,6 @@ --- title: Adicionando projetos DeSci -description: A política que usamos ao adicionar links para projetos na página DeSci no ethereum.org +description: "A política que usamos ao adicionar um link para projetos na página DeSci em ethereum.org" lang: pt-br --- @@ -10,25 +10,25 @@ Queremos ter certeza de que mostraremos uma variedade de projetos e oferecemos u Qualquer um pode sugerir um projeto para listar na página DeSci no ethereum.org. Igualmente, qualquer pessoa que veja um projeto que não é mais relevante ou não atende aos nossos critérios de elegibilidade pode sugerir a remoção dele. -## A estrutura de decisão {#the-decision-framework} +## O framework de decisão {#the-decision-framework} -### Critérios para inclusão: os obrigatórios {#the-must-haves} +### Critérios para inclusão: os requisitos obrigatórios {#the-must-haves} -- **Código fonte/dados abertos** — a abertura do código e dos dados é um princípio fundamental do DeSci, portanto, os projetos DeSci não devem ser de código fechado. A base de código deveria ser acessível e idealmente aberta para PRs (solicitações de pull). -- **Os projetos DeSci deveriam ser comprovadamente descentralizados** — isso poderia incluir ser governado por um DAO ou ser construído com uma pilha de tecnologia descentralizada, incluindo carteiras sem custódia. Provavelmente, isso envolve contratos inteligentes auditáveis no Ethereum. -- **Informação de listagem honesta e precisa** - é esperado que as informações de listagem sugeridas dos projetos sejam honestas e precisas. Produtos que falsificam informações de listagem, como declarar que seu produto é de "código aberto" quando não é, serão removidos. -- **Comprometimento demonstrável para ampliar o acesso à ciência** — um projeto DeSci deve ser capaz de articular como eles ampliam a participação na ciência para o público em geral, não apenas para detentores de tokens/NFT. -- **Acessível globalmente** - seu projeto não contém limitações geográficas ou requisitos KYC (conheça seu cliente) que não permitam que ele seja acessado por certas pessoas. -- **Site Web e documentação instrutivos** - é importante que as pessoas que acessem o site do projeto possam entender o objetivo do projeto, como ele contribui para a descentralização da infraestrutura da ciência e como é possível participar. -- **O projeto deve fazer parte do ecossistema Ethereum** — no ethereum.org, acreditamos que o Ethereum (e sua camada 2) seja a camada base apropriada para o movimento DeSci. -- **O projeto está razoavelmente bem estabelecido** — o projeto tem usuários reais que puderam acessar os serviços do projeto por vários meses. +- **Código-fonte/dados abertos** - A abertura do código e dos dados é um princípio central da DeSci, então os projetos DeSci não devem ter o código fechado. A base de código deveria ser acessível e idealmente aberta para PRs (solicitações de pull). +- **Os projetos DeSci devem ser comprovadamente descentralizados** - Isso pode incluir ser governado por uma DAO ou construído com uma pilha de tecnologia descentralizada, incluindo carteiras sem custódia. Provavelmente, isso envolve contratos inteligentes auditáveis no Ethereum. +- **Informações de listagem honestas e precisas** - Espera-se que quaisquer sugestões de listagens de projetos venham com informações honestas e precisas. Produtos que falsificam informações de listagem, como declarar que seu produto é de "código aberto" quando não é, serão removidos. +- **Compromisso demonstrável em ampliar o acesso à ciência** - Um projeto DeSci deve ser capaz de articular como ele amplia a participação na ciência para o público em geral, e não apenas para detentores de tokens/NFT. +- **Acessível globalmente** - Seu projeto não tem limitações geográficas ou requisitos de KYC que excluam certas pessoas de acessar seu serviço. +- **Site e documentação informativos** - É importante que os visitantes do site do projeto possam entender o que o projeto realmente faz, como ele contribui para a descentralização da infraestrutura científica e como participar. +- **O projeto deve fazer parte do ecossistema Ethereum** - No ethereum.org, acreditamos que o Ethereum (e suas Camadas 2) é a camada de base apropriada para o movimento DeSci. +- **O projeto está razoavelmente bem estabelecido** - O projeto tem usuários reais que conseguem acessar os serviços do projeto há vários meses. ### Critérios opcionais -- **Disponível em vários idiomas** - seu projeto é traduzido em vários idiomas, permitindo que usuários ao redor do mundo o acessem. -- **Recursos educacionais** - seu produto deveria apresentar uma experiência de integração bem planejada para ajudar e informar os usuários. Ou então, oferecer conteúdo prático como artigos e vídeos. -- **Auditorias de terceiros** - uma empresa especializada confiável realizou uma auditoria em seu produto para detectar vulnerabilidades. -- **Ponto de contato** — um ponto de contato para o projeto (isto pode ser um representante de uma DAO ou comunidade) nos ajudará muito a obter informações precisas quando as alterações forem feitas. Isso manterá a atualização do ethereum.org gerenciável ao reunir informações futuras. +- **Disponível em vários idiomas** - Seu projeto é traduzido para vários idiomas, permitindo que usuários do mundo todo o acessem. +- **Recursos educacionais** - Seu produto deve ter uma experiência de integração bem projetada para ajudar e educar os usuários. Ou então, oferecer conteúdo prático como artigos e vídeos. +- **Auditorias de terceiros** - Seu produto foi auditado profissionalmente em busca de vulnerabilidades por um terceiro de confiança. +- **Ponto de contato** - Um ponto de contato para o projeto (que pode ser um representante de uma DAO ou comunidade) nos ajudará muito a obter informações precisas quando forem feitas alterações. Isso manterá a atualização do ethereum.org gerenciável ao reunir informações futuras. ## Manutenção {#maintenance} @@ -37,8 +37,8 @@ O Ethereum é fluido por natureza, por isso, suas equipes e produtos vêm e vão - Assegurar que todos os projetos listados cumpram com nossos critérios - Verificar que não existam produtos que cumpram mais critérios do que os atualmente listados -O ethereum.org é mantido pela comunidade de código aberto e dependemos da comunidade para ajudar a mantê-lo atualizado. Se você notar alguma informação sobre projetos listados que precisam ser atualizados, abra um tíquete ou uma solicitação de pull em nosso repositório do GitHub. +O ethereum.org é mantido pela comunidade de código aberto e contamos com a comunidade para ajudar a mantê-lo atualizado. Se você notar alguma informação sobre projetos listados que precisam ser atualizados, abra um tíquete ou uma solicitação de pull em nosso repositório do GitHub. ## Termos de uso {#terms-of-use} -Consulte também nossos [termos de uso](/terms-of-use/). Informações sobre o ethereum.org são fornecidas exclusivamente para fins de informação geral. +Consulte também nossos [termos de uso](/terms-of-use/). Informações sobre o ethereum.org são fornecidas exclusivamente para fins de informação geral. diff --git a/public/content/translations/pt-br/contributing/adding-developer-tools/index.md b/public/content/translations/pt-br/contributing/adding-developer-tools/index.md index ceade2cb367..76f064bf993 100644 --- a/public/content/translations/pt-br/contributing/adding-developer-tools/index.md +++ b/public/content/translations/pt-br/contributing/adding-developer-tools/index.md @@ -1,7 +1,7 @@ --- title: Adicionando ferramentas de desenvolvedor lang: pt-br -description: Nossos critérios para listar ferramentas de desenvolvedor no ethereum.org +description: "Nossos critérios para listar ferramentas de desenvolvedor no ethereum.org" --- # Adicionando ferramentas de desenvolvedor {#contributing-to-ethereumorg-} @@ -10,7 +10,7 @@ Queremos ter certeza de que listamos os melhores recursos de desenvolvedor poss Se nos esquecermos de alguma ferramenta de desenvolvedor útil, não hesite em nos sugeri-la por meio de um canal adequado. -Atualmente, listamos as ferramentas de desenvolvedor por meio do nosso [portal do desenvolvedor](/developers/). +Atualmente, listamos ferramentas de desenvolvedor em todo o nosso [portal do desenvolvedor](/developers/). **Não hesite em nos sugerir novas adições às páginas apropriadas.** @@ -46,7 +46,7 @@ Muitos projetos no espaço Ethereum são de código aberto. É mais provável qu --- -## Ordenação dos produtos {#product-ordering} +## Ordenação de Produtos {#product-ordering} A menos que os produtos sejam ordenados especificamente de outra forma, como em ordem alfabética, os produtos serão exibidos dos mais antigos aos mais recentes adicionados à página. Em outras palavras, os produtos mais recentes são adicionados ao final da lista. @@ -57,5 +57,5 @@ A menos que os produtos sejam ordenados especificamente de outra forma, como em Se você deseja adicionar uma ferramenta de desenvolvedor ao ethereum.org que atende aos critérios, crie um tíquete no GitHub. - Criar tíquete + Abrir chamado diff --git a/public/content/translations/pt-br/contributing/adding-exchanges/index.md b/public/content/translations/pt-br/contributing/adding-exchanges/index.md index 56796081355..bfce33c07a7 100644 --- a/public/content/translations/pt-br/contributing/adding-exchanges/index.md +++ b/public/content/translations/pt-br/contributing/adding-exchanges/index.md @@ -1,10 +1,10 @@ --- -title: Adicionar câmbios -description: A política que usamos ao adicionar câmbios ao ethereum.org +title: "Adicionar câmbios" +description: "A política que usamos ao adicionar câmbios ao ethereum.org" lang: pt-br --- -# Adicionar câmbios ao Ethereum {#adding-ethereum-exchanges} +# Adicionando corretoras Ethereum {#adding-ethereum-exchanges} Qualquer pessoa pode sugerir novos câmbios no ethereum.org. @@ -16,7 +16,7 @@ Esta página permite ao usuário inserir onde mora e ver quais câmbios pode usa Devido a esse contexto, precisaremos de algumas informações específicas quando você sugerir um câmbio. -**NOTA:** Se você quiser adicionar um câmbio descentralizado, confira nossa [política para adicionar carteiras e dapps](/contributing/adding-products/). +**OBSERVAÇÃO:** Se você quiser listar uma corretora descentralizada, dê uma olhada em nossa [política para listar carteiras e dapps](/contributing/adding-products/). ## Do que precisamos {#what-we-need} @@ -25,16 +25,16 @@ Devido a esse contexto, precisaremos de algumas informações específicas quand - Prova de que a agência de câmbio é uma empresa comercial legítima - Qualquer informação adicional que você tenha: podem ser informações sobre a empresa, como anos de operação, apoio financeiro, etc. -Precisamos dessas informações para poder [ajudar usuários a encontrar uma agência de câmbio que possam usar](/get-eth/#country-picker). +Precisamos dessas informações para que possamos, com precisão, [ajudar os usuários a encontrar uma corretora que possam usar](/get-eth/#country-picker). E para que o ethereum.org possa confiar na legitimidade e segurança dos serviços fornecidos pela agência de câmbio. --- -## Adicionar sua agência de câmbio {#add-exchange} +## Adicione sua corretora {#add-exchange} Se você deseja adicionar uma agência de câmbio no ethereum.org, crie um tíquete no GitHub. - Criar tíquete +Abrir chamado diff --git a/public/content/translations/pt-br/contributing/adding-glossary-terms/index.md b/public/content/translations/pt-br/contributing/adding-glossary-terms/index.md index 6f5a315b1a9..c3e66e41703 100644 --- a/public/content/translations/pt-br/contributing/adding-glossary-terms/index.md +++ b/public/content/translations/pt-br/contributing/adding-glossary-terms/index.md @@ -1,12 +1,12 @@ --- -title: Adicionar termos ao glossário +title: "Adicionar termos ao glossário" lang: pt-br -description: Nossos critérios para adicionar novos termos ao glossário do ethereum.org +description: "Nossos critérios para adicionar novos termos ao glossário do ethereum.org" --- # Adicionando termos ao glossário {#contributing-to-ethereumorg-} -Esse espaço passa por mudanças diárias. Novos termos estão constantemente entrando no léxico dos usuários do Ethereum, e precisamos da sua ajuda para fornecer referências atualizadas e precisas para tudo o que diz respeito ao Ethereum. Confira o [glossário](/glossary/) e veja abaixo se você deseja ajudar! +Esse espaço passa por mudanças diárias. Novos termos estão constantemente entrando no léxico dos usuários do Ethereum, e precisamos da sua ajuda para fornecer referências atualizadas e precisas para tudo o que diz respeito ao Ethereum. Confira o [glossário](/glossary/) atual e veja abaixo se quiser ajudar! ## Critérios {#criteria} @@ -23,4 +23,4 @@ Novos termos inseridos no glossário serão avaliados pelos seguintes critérios ## Adicione seu termo {#how-decisions-about-the-site-are-made} -Se você quiser adicionar um termo ao glossário no ethereum.org que atenda aos critérios, [abra um tíquete no GitHub](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=feature+%3Asparkles%3A%2Ccontent+%3Afountain_pen%3A&template=suggest_glossary_term.yaml). +Se você quiser adicionar um termo do glossário ao ethereum.org e ele atender aos critérios, [crie um problema no GitHub](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=feature+%3Asparkles%3A%2Ccontent+%3Afountain_pen%3A&template=suggest_glossary_term.yaml). diff --git a/public/content/translations/pt-br/contributing/adding-layer-2s/index.md b/public/content/translations/pt-br/contributing/adding-layer-2s/index.md index c465ca5edd4..1c63b404dfd 100644 --- a/public/content/translations/pt-br/contributing/adding-layer-2s/index.md +++ b/public/content/translations/pt-br/contributing/adding-layer-2s/index.md @@ -1,31 +1,31 @@ --- title: Adicionando Camada 2S -description: A política que usamos ao adicionar uma camada 2 ao ethereum.org +description: "A política que usamos ao adicionar uma camada 2 ao ethereum.org" lang: pt-br --- -# Adicionando Camada 2S {#adding-layer-2} +# Adicionando camadas 2 {#adding-layer-2} Queremos garantir que listamos os melhores recursos possíveis para que os usuários possam navegar no espaço da camada 2 de maneira segura e confiante. -Qualquer pessoa pode sugerir a adição de uma camada 2 no ethereum.org. Se houver alguma camada 2 que esquecemos, **[sugira uma](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=feature+%3Asparkles%3A%2Ccontent+%3Afountain_pen%3A&template=suggest_layer2.yaml)!** +Qualquer pessoa pode sugerir a adição de uma camada 2 no ethereum.org. Se houver uma camada 2 que não incluímos, **[por favor, sugira](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=feature+%3Asparkles%3A%2Ccontent+%3Afountain_pen%3A&template=suggest_layer2.yaml)!** Atualmente, listamos as 2LS nas seguintes páginas: -- [Acumulação otimista](/developers/docs/scaling/optimistic-rollups/) -- [Acumulação de conhecimento zero](/developers/docs/scaling/zk-rollups/) +- [Optimistic rollups](/developers/docs/scaling/optimistic-rollups/) +- [Rollups de conhecimento zero](/developers/docs/scaling/zk-rollups/) - [Camada 2](/layer-2/) Camada 2 é um paradigma relativamente novo e empolgante para o Ethereum. Tentamos criar uma estrutura justa a ser considerada no ethereum.org, mas os critérios listados mudarão e evoluirão com o tempo. -## A estrutura de decisão {#decision-framework} +## O framework de decisão {#decision-framework} -### Critérios para inclusão: os obrigatórios {#criteria-for-inclusion-the-must-haves} +### Critérios de inclusão: os obrigatórios {#criteria-for-inclusion-the-must-haves} **Listando na L2BEAT** -- Para ser considerado, esse projeto deve estar listado na [L2BEAT](https://l2beat.com). A L2BEAT fornece uma avaliação de riscos sólida de projetos da camada 2 que apoiamos para avaliar projetos de L2. **Se o projeto não for apresentado na L2BEAT, não o listaremos como L2 no ethereum.org.** -- [ Saiba como adicionar seu projeto L2 à L2BEAT](https://github.com/l2beat/l2beat/blob/master/CONTRIBUTING.md). +- Para ser considerado, este projeto deve estar listado no [L2BEAT](https://l2beat.com). A L2BEAT fornece uma avaliação de riscos sólida de projetos da camada 2 que apoiamos para avaliar projetos de L2. **Se o projeto não for apresentado na L2BEAT, não o listaremos como L2 no ethereum.org.** +- [Saiba como adicionar seu projeto L2 ao L2BEAT](https://github.com/l2beat/l2beat/blob/master/CONTRIBUTING.md). **Código aberto** @@ -38,11 +38,11 @@ Atualmente, consideramos as seguintes soluções para camada 2: - Acúmulo otimista - Acúmulo de conhecimento zero -_Não consideramos outras soluções de dimensionamento que não usam o Ethereum para disponibilidade de dados ou segurança para a camada 2._ +_Não consideramos outras soluções de escalabilidade que não usam o Ethereum para disponibilidade de dados ou segurança como sendo camada 2._ **Ethereum para disponibilidade de dados** -- A disponibilidade de dados é um importante fator de diferenciação entre outras soluções de dimensionamento e a camada 2. Um projeto **deve** usar a Rede principal do Ethereum para que a disponibilidade de dados seja considerada para listagem. +- A disponibilidade de dados é um importante fator de diferenciação entre outras soluções de dimensionamento e a camada 2. Um projeto **deve** usar a Rede Principal do Ethereum para que a disponibilidade de dados seja considerada para listagem. **Pontes** @@ -56,7 +56,7 @@ _Não consideramos outras soluções de dimensionamento que não usam o Ethereum **Auditoria de segurança externa** -- Seja por meio de auditoria, uma equipe de segurança interna ou algum outro método, a segurança do seu produto deve ser testada de forma confiável. Isso reduz o risco para nossos usuários e demonstra que você leva a segurança a sério. +- Seja por meio de auditoria, uma equipe de segurança interna ou algum outro método, a segurança do seu produto deve ser testada de forma confiável. Isso reduz o risco para nossos usuários e nos mostra que você leva a segurança a sério. **Base de usuários sustentável** @@ -70,7 +70,7 @@ _Não consideramos outras soluções de dimensionamento que não usam o Ethereum - Os projetos listados exigem um explorador de blocos de trabalho para permitir aos usuários navegar facilmente pela cadeia. -### Outros critérios: o que é importante ter {#nice-to-haves} +### Outros critérios: os desejáveis {#nice-to-haves} **Suporte ao câmbio para o projeto** @@ -78,7 +78,7 @@ _Não consideramos outras soluções de dimensionamento que não usam o Ethereum **Links para dapps no ecossistema da camada 2** -- Queremos ser capazes de fornecer informações sobre o que os usuários podem esperar fazer nessa camada 2. (por exemplo, https://portal.arbitrum.io/, https://www.optimism.io/apps) +- Queremos ser capazes de fornecer informações sobre o que os usuários podem esperar fazer nessa camada 2. (p. ex., https://portal.arbitrum.io/, https://www.optimism.io/apps) **Listas de contratos de token** @@ -90,8 +90,8 @@ _Não consideramos outras soluções de dimensionamento que não usam o Ethereum ## Adicione sua camada 2 {#add-exchange} -Se você quiser adicionar uma camada 2 ao ethereum.org, abra um tíquete no Github. +Se você quiser adicionar uma camada 2 ao ethereum.org, abra um tíquete no GitHub. - Crie um ticket +Abrir chamado diff --git a/public/content/translations/pt-br/contributing/adding-products/index.md b/public/content/translations/pt-br/contributing/adding-products/index.md index 48b8219cc35..a1594236f1c 100644 --- a/public/content/translations/pt-br/contributing/adding-products/index.md +++ b/public/content/translations/pt-br/contributing/adding-products/index.md @@ -1,6 +1,6 @@ --- title: Adicionando produtos -description: A política que usamos ao adicionar dapps ao ethereum.org +description: "A política que usamos ao adicionar dapps ao ethereum.org" lang: pt-br --- @@ -17,11 +17,11 @@ Atualmente, os dapps estão listados em: Embora novas adições sejam bem-vindas, escolhemos os dapps atuais baseados na experiência que estamos tentando criar aos nossos usuários. Eles são baseados em alguns dos nossos princípios de design: -- _Inspirador_: qualquer dado no ethereum.org deve oferecer algo novo para seus usuários -- _Uma boa história_: o que está listado deve proporcionar um momento "aha!" -- _Credível_: todos os negócios/projetos devem ser legítimos para minimizar o risco do usuário +- _Inspiracional_: tudo no ethereum.org deve oferecer algo novo aos usuários +- _Uma boa história_: o que está listado deve proporcionar um momento "aha" +- _Confiável_: todos os negócios/projetos devem ser legítimos para minimizar riscos aos usuários -Em geral, o **ethereum.org quer proporcionar uma "experiência de integração ininterrupta" para novos usuários**. Por essa razão, adicionamos dapps baseados em: +No geral, o **ethereum.org quer fornecer uma "experiência de integração contínua" para novos usuários**. Por essa razão, adicionamos dapps baseados em: - facilidade de uso - interoperabilidade com outros produtos @@ -30,28 +30,28 @@ Em geral, o **ethereum.org quer proporcionar uma "experiência de integração i Aqui está a nossa estrutura de decisão em mais detalhes. Não hesite em comentar ou sugerir modificações. -## A estrutura de decisão {#decision-framework} +## O framework de decisão {#decision-framework} -### Critérios para inclusão: os obrigatórios {#criteria-for-inclusion-the-must-haves} +### Critérios de inclusão: os obrigatórios {#criteria-for-inclusion-the-must-haves} -- **Um produto seguro e testado** — seja por auditoria, uma equipe interna de segurança ou outro método, a segurança do seu produto deve ser testada de forma confiável. Isso reduz o risco para nossos usuários e demonstra que você leva a segurança a sério. -- **Um produto está "ativo" por mais de 6 meses** — este é outro sinal de segurança. 6 meses é um bom prazo para encontrar erros críticos e explorações abusivas. -- **Time ativo no projeto** — Isso ajuda a garantir qualidade e suporte ao usuário para suas dúvidas. -- **Informações de listagem corretas e precisas** — espera-se que todas as listagens sugeridas de projetos venham com informações precisas e íntegras. Produtos que falsificam informações de listagem, como declarar que seu produto é de código aberto quando não é, serão removidos. +- **Um produto seguro e testado** – seja por meio de auditoria, uma equipe de segurança interna ou algum outro método, a segurança do seu produto deve ser testada de forma confiável. Isso reduz o risco para nossos usuários e nos mostra que você leva a segurança a sério. +- **Um produto que está "no ar" há mais de 6 meses** – esta é outra indicação de segurança. 6 meses é um bom prazo para encontrar erros críticos e explorações abusivas. +- **Mantido por uma equipe ativa** – isso ajuda a garantir a qualidade e que um usuário receberá suporte para suas dúvidas. +- **Informações de listagem honestas e precisas** - espera-se que quaisquer listagens sugeridas de projetos venham com informações honestas e precisas. Produtos que falsificam informações de listagem, como declarar que seu produto é de código aberto quando não é, serão removidos. -### Critérios de classificação: os aspectos desejáveis {#criteria-for-ranking-the-nice-to-haves} +### Critérios de classificação: os desejáveis {#criteria-for-ranking-the-nice-to-haves} Seu dapp ou carteira podem não ser listados no ethereum.org com tanto destaque quanto os outros devido aos seguintes critérios. **Dapps** -- **Você pode acessá-lo pela maioria das carteiras listadas** — os dapps devem funcionar com a maioria das carteiras listadas no ethereum.org. -- **Os usuários podem experimentar por conta própria** — um usuário individual deve conseguir utilizar seu dapp e alcançar algo tangível. -- **Integração** — seu produto deve ter uma experiência de integração bem projetada para auxiliar e instruir usuários. Ou então, oferecer conteúdo prático como artigos e vídeos. -- **Sem custódia** — os usuários controlam seus fundos. Se o seu produto desaparecer, os usuários ainda poderão acessar e movimentar seus fundos. -- **Globalmente acessível** — seu produto não tem limitações geográficas ou requisitos do tipo "conheça seu cliente" (KYC), que excluem certas pessoas de acessar seu serviço. -- **Código aberto** — seu código deve ser acessível e deve aceitar solicitações de pull (PR) da comunidade em geral. -- **Comunidade** — você tem uma comunidade dedicada, talvez no Discord, na qual os usuários podem interagir com sua equipe para receber auxílio ou sugerir novos recursos. +- **Você pode acessá-lo através da maioria das carteiras listadas** – os dapps devem funcionar com a maioria das carteiras listadas no ethereum.org. +- **Os usuários podem experimentar por si mesmos –** um usuário individual deve ser capaz de usar seu dapp e alcançar algo tangível. +- **Integração** – seu produto deve ter uma experiência de integração bem projetada para ajudar e educar os usuários. Ou então, oferecer conteúdo prático como artigos e vídeos. +- **Sem custódia** – os usuários controlam seus próprios fundos. Se o seu produto desaparecer, os usuários ainda poderão acessar e movimentar seus fundos. +- **Acessível globalmente** – seu produto não tem limitações geográficas ou requisitos de KYC que excluam certas pessoas de acessar seu serviço. +- **Código aberto** – seu código deve ser acessível e você deve aceitar PRs da comunidade em geral. +- **Comunidade** – você tem uma comunidade dedicada, talvez um Discord, onde os usuários podem interagir com sua equipe para obter ajuda ou sugerir novos recursos. ## Critérios na prática {#criteria-in-practice} @@ -70,13 +70,13 @@ Essa é uma decisão de design pela qual o ethereum.org é responsável. Mas fique tranquilo, **haverá links para outros sites que classificam mais dapps** -### Ordenação dos Produtos {#product-ordering} +### Ordenação de Produtos {#product-ordering} A menos que os produtos sejam ordenados especificamente de outra forma, como em ordem alfabética, os produtos serão exibidos dos mais antigos aos mais recentes adicionados à página. Em outras palavras, os produtos mais recentes são adicionados ao final da lista. -### Termos de Uso {#terms-of-use} +### Termos de uso {#terms-of-use} -Consulte também os nossos [termos de uso](/terms-of-use/). Informações sobre o ethereum.org são fornecidas exclusivamente para fins de informação geral. +Consulte também nossos [termos de uso](/terms-of-use/). Informações sobre o ethereum.org são fornecidas exclusivamente para fins de informação geral. ## Manutenção {#maintenance} @@ -85,7 +85,7 @@ O Ethereum é fluido por natureza, por isso, suas equipes e produtos vêm e vão - garantir que todos os dapps listados ainda atendam aos nossos critérios - verificar se não há produtos sugeridos que atendam mais aos nossos critérios do que os atualmente listados -Você pode nos ajudar com isso, verificando e nos informando. [Abra um tíquete](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=Type%3A+Feature&template=feature_request.yaml&title=) ou envie um e-mail para[website@ethereum.org](mailto:website@ethereum.org) +Você pode nos ajudar com isso, verificando e nos informando. [Sugira uma alteração](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=Type%3A+Feature&template=feature_request.yaml&title=) ou envie um email para [website@ethereum.org](mailto:website@ethereum.org) _Estamos também investigando opções de votação para que a comunidade possa indicar suas preferências e destacar os melhores produtos disponíveis para recomendarmos._ @@ -93,8 +93,8 @@ _Estamos também investigando opções de votação para que a comunidade possa ## Adicione seu produto {#add-your-product} -Se você quiser adicionar um dapp ao ethereum.org e ele atender aos critérios, abra um tíquete no GitHub. +Se você deseja adicionar um dapp ao ethereum.org e ele atende aos critérios, entre em contato conosco. - Criar um novo problema + Sugerir um aplicativo diff --git a/public/content/translations/pt-br/contributing/adding-resources/index.md b/public/content/translations/pt-br/contributing/adding-resources/index.md new file mode 100644 index 00000000000..02abe68a737 --- /dev/null +++ b/public/content/translations/pt-br/contributing/adding-resources/index.md @@ -0,0 +1,53 @@ +--- +title: Adicionando Recursos +description: "A política que usamos ao adicionar recursos ao ethereum.org" +lang: pt-br +--- + +# Adicionando Recursos {#adding-resources} + +Queremos ter certeza de que listamos os melhores recursos possíveis, mantendo os usuários seguros e confiantes. + +Qualquer pessoa pode sugerir novos recursos para adicionar ao painel de recursos no ethereum.org, disponível atualmente em [ethereum.org/resources](/resources/). + +Embora recebamos bem novas adições, os recursos atuais foram escolhidos com base na experiência que estamos tentando criar para nossos usuários. Eles são baseados em alguns dos nossos princípios de design: + +- _Inspiracional_: tudo no ethereum.org deve oferecer algo novo aos usuários +- _Uma boa história_: o que está listado deve proporcionar um momento "aha" +- _Confiável_: todos os negócios/projetos devem ser legítimos para minimizar riscos aos usuários + +De modo geral, **ethereum.org visa proporcionar uma experiência de integração fluida para novos usuários**. Por essa razão, adicionamos recursos com base em: + +- facilidade de uso +- precisão +- manutenção + +## O framework de decisão {#decision-framework} + +### Critérios {#criteria} + +- **Informações de listagem honestas e precisas** - Todas as sugestões de listagem devem vir com informações honestas e precisas. Produtos que falsificam informações serão removidos. +- **Projeto ativo** – O recurso deve ser mantido por uma equipe ativa para garantir qualidade e suporte aos usuários. Recursos desatualizados estão sujeitos à remoção. + +### Ordenação de Produtos {#product-ordering} + +Reservamo-nos o direito de ordenar os produtos com base em seu impacto. Novos produtos serão geralmente adicionados ao final da lista, a menos que especificado de outra forma. + +## Manutenção {#maintenance} + +À medida que o ecossistema Ethereum evolui, verificaremos nosso conteúdo rotineiramente para: + +- Garantir que todos os recursos listados ainda cumpram nossos critérios +- Verificar que não existam produtos que cumpram mais critérios do que os atualmente listados + +Você pode nos ajudar com isso, verificando e nos informando. [Sugira uma alteração](https://github.com/ethereum/ethereum-org-website/issues/new?template=bug_report.yaml) ou envie um email para [website@ethereum.org](mailto:website@ethereum.org). + +--- + +## Adicione seu recurso {#add-your-resource} + +Se você deseja adicionar um recurso que atenda aos critérios ao ethereum.org, abra um chamado no GitHub. + + +Abrir chamado + diff --git a/public/content/translations/pt-br/contributing/adding-staking-products/index.md b/public/content/translations/pt-br/contributing/adding-staking-products/index.md index 6b101be5c3b..d1b77e9b35f 100644 --- a/public/content/translations/pt-br/contributing/adding-staking-products/index.md +++ b/public/content/translations/pt-br/contributing/adding-staking-products/index.md @@ -1,20 +1,20 @@ --- -title: Adicionando participação em produtos e serviços -description: A política que usamos ao adicionar participações em produtos e serviços no ethereum.org +title: "Adicionando participação em produtos e serviços" +description: "A política que usamos ao adicionar participações em produtos e serviços no ethereum.org" lang: pt-br --- -# Adicionando participação em produtos e serviços {#adding-staking-products-or-services} +# Adicionar produtos ou serviços de staking {#adding-staking-products-or-services} Queremos ter certeza de que listamos os melhores recursos possíveis, mantendo os usuários seguros e confiantes. -Qualquer pessoa é livre para sugerir a adição de participações em produtos ou serviços no ethereum.org. Se houver algum de que esquecemos, **[sugira aqui](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=feature+%3Asparkles%3A%2Ccontent+%3Afountain_pen%3A&template=suggest_staking_product.yaml)!** +Qualquer pessoa é livre para sugerir a adição de participações em produtos ou serviços no ethereum.org. Se houver algum que tenhamos esquecido, **[por favor, sugira-o](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=feature+%3Asparkles%3A%2Ccontent+%3Afountain_pen%3A&template=suggest_staking_product.yaml)!** Atualmente, listamos participações em produtos e serviços nas seguintes páginas: -- [Participação Individual](/staking/solo/) -- [Participação sobre Serviço](/staking/saas/) -- [Pools de participação (staking)](/staking/pools/) +- [Participação individual](/staking/solo/) +- [Participação como serviço](/staking/saas/) +- [Pools de participação](/staking/pools/) A prova de participação na Beacon Chain está ativa desde 1 de dezembro de 2020. Embora fazer participações (staking) seja algo relativamente novo, tentamos criar uma estrutura justa e transparente a ser considerada no ethereum.org, porém, os critérios de listagem vão mudar e evoluir com o tempo e, em última análise, ficarão a critério da equipe do ethereum.org. @@ -26,12 +26,12 @@ A decisão de listar um produto no ethereum.org não depende de um único fator. - Ferramenta de nó ou cliente - Gerenciamento de chaves -- Participação como Serviço (SaaS) +- Staking como Serviço (SaaS) - Pool de participação (staking) Atualmente, estamos apenas listando produtos ou serviços nessas categorias. -### Critérios para inclusão {#criteria-for-inclusion} +### Critérios de inclusão {#criteria-for-inclusion} As submissões de produtos ou serviços de participação serão avaliadas pelos seguintes critérios: @@ -59,7 +59,7 @@ As submissões de produtos ou serviços de participação serão avaliadas pelos - ou seja, Linux, macOS, Windows, iOS, Android -#### Sistemas e contratos Inteligentes {#software-and-smart-contracts} +#### Software e contratos inteligentes {#software-and-smart-contracts} Para qualquer sistema personalizado ou contrato inteligente envolvido: @@ -68,7 +68,7 @@ Para qualquer sistema personalizado ou contrato inteligente envolvido: - Projetos de código aberto devem ter um repositório de código-fonte disponível publicamente - Isso é usado para determinar a pontuação de "código aberto" dos produtos. -**O produto está fora do desenvolvimento de uma versão _beta_?** +**O produto já saiu do desenvolvimento _beta_?** - Onde se encontra o produto em seu ciclo de desenvolvimento? - Os produtos na fase beta não são considerados para inclusão no ethereum.org @@ -83,18 +83,18 @@ Para qualquer sistema personalizado ou contrato inteligente envolvido: - Caso contrário, há planos para criar uma recompensa por bugs na segurança? - Isso é usado para determinar a pontuação de "recompensa por bugs encontrados" dos produtos. -#### Ferramenta de nó ou cliente {#node-or-client-tooling} +#### Ferramentas de nó ou cliente {#node-or-client-tooling} Para produtos de software relacionados à configuração de nó ou cliente, gerenciamento ou migração: -**Quais clientes da camada de consenso (como Lighthouse, Teku, Nimbus, Prysm, Grandine) são suportados?** +**Quais clientes da camada de consenso (ou seja, Lighthouse, Teku, Nimbus, Prysm, Grandine) são suportados?** - Quais clientes são suportados? O usuário pode escolher? - Isso é usado para determinar a pontuação dos produtos "multicliente". -#### Participação sobre Serviço {#staking-as-a-service} +#### Participação como serviço {#staking-as-a-service} -Para [listagens de staking-as-a-service](/staking/saas/) (ou seja, operação de nó delegada): +Para [listagens de participação como serviço](/staking/saas/) (ou seja, operação de nó delegada): **Quais são as taxas associadas ao uso do serviço?** @@ -117,11 +117,11 @@ Para [listagens de staking-as-a-service](/staking/saas/) (ou seja, operação de - Na última edição, o Prysm é o cliente da camada de consenso executado pela maioria dos nós operadores, o que é perigoso para a rede. Se um cliente atualmente estiver usando mais de 33% da rede, solicitamos os dados relacionados a esse uso. - Isso é usado para determinar a pontuação de “diversidade de clientes” dos produtos. -#### Pool de Participação {#staking-pool} +#### Pool de participação {#staking-pool} -Para [serviços de participação (stake) em pool](/staking/pools/): +Para [serviços de participação em pool](/staking/pools/): -**Qual é o mínimo de ETH necessário para colocar em participação (stake)?** +**Qual é o mínimo de ETH necessário para colocar em participação?** - por exemplo, 0,01 ETH @@ -147,11 +147,11 @@ Para [serviços de participação (stake) em pool](/staking/pools/): - Na última edição, o Prysm é o cliente da camada de consenso executado pela maioria dos nós operadores, o que é perigoso para a rede. Se um cliente atualmente estiver usando mais de 33% da rede, solicitamos os dados relacionados a esse uso. - Isso é usado para determinar a pontuação de “diversidade de clientes” dos produtos. -### Outros critérios: os bons para ter {#other-criteria} +### Outros critérios: os desejáveis {#other-criteria} **Quais interfaces de usuário são suportadas?** -- ou seja, Aplicativos de navegador, desktop, mobile ou CLI +- ou seja, aplicativo de navegador, aplicativo de desktop, aplicativo móvel, CLI **Para ferramentas de nós, o software fornece uma maneira fácil de alternar entre clientes?** @@ -163,14 +163,14 @@ Para [serviços de participação (stake) em pool](/staking/pools/): ## Como exibimos os resultados {#product-ordering} -Os [critérios de inclusão](#criteria-for-inclusion) acima são usados para calcular a pontuação acumulada para cada produto ou serviço. Isso é usado como meio de classificação e apresentação de produtos que atendem a determinados critérios objetivos. Quanto mais critérios forem fornecidos para essa evidência, maior será a classificação de um produto, com ligações exibidas aleatoriamente durante o carregamento. +Os [critérios de inclusão](#criteria-for-inclusion) acima são usados para calcular uma pontuação cumulativa para cada produto ou serviço. Isso é usado como meio de classificação e apresentação de produtos que atendem a determinados critérios objetivos. Quanto mais critérios forem fornecidos para essa evidência, maior será a classificação de um produto, com ligações exibidas aleatoriamente durante o carregamento. -Atualmente, a lógica e os valores do código para esses critérios estão contidos [neste componente JavaScript](https://github.com/ethereum/ethereum-org-website/blob/dev/src/components/Staking/StakingProductsCardGrid/index.tsx#L350) em nosso repositório. +A lógica do código e os pesos para esses critérios estão atualmente contidos [neste componente JavaScript](https://github.com/ethereum/ethereum-org-website/blob/dev/src/components/Staking/StakingProductsCardGrid.js#L350) em nosso repositório. ## Adicione seu produto ou serviço {#add-product} -Se você quiser adicionar uma participação (stake) de produto ou serviço ao ethereum.org, crie um tíquete no Github. +Se você quiser adicionar uma participação (stake) de produto ou serviço ao ethereum.org, crie um tíquete no GitHub. - Crie um ticket +Abrir chamado diff --git a/public/content/translations/pt-br/contributing/adding-wallets/index.md b/public/content/translations/pt-br/contributing/adding-wallets/index.md index 5eea27d4ba7..6d6a4103d54 100644 --- a/public/content/translations/pt-br/contributing/adding-wallets/index.md +++ b/public/content/translations/pt-br/contributing/adding-wallets/index.md @@ -1,6 +1,6 @@ --- title: Adicionando carteiras -description: A política que usamos ao adicionar uma carteira ao ethereum.org +description: "A política que usamos ao adicionar uma carteira ao ethereum.org" lang: pt-br --- @@ -12,57 +12,58 @@ Qualquer pessoa pode sugerir a adição de uma carteira no ethereum.org. Se houv As carteiras atualmente listadas estão em: -- [ethereum.org/pt-br/wallets/find-wallet/](/wallets/find-wallet/) +- [ethereum.org/wallets/find-wallet/](/wallets/find-wallet/) As carteiras estão mudando rapidamente no Ethereum. Tentamos criar uma estrutura justa a ser considerada no ethereum.org, mas os critérios listados mudarão e evoluirão com o tempo. -## A estrutura de decisão {#the-decision-framework} +## O framework de decisão {#the-decision-framework} -### Critérios para inclusão: os obrigatórios {#the-must-haves} +### Critérios para inclusão: os requisitos obrigatórios {#the-must-haves} -- **Um produto com segurança testada** — seja por meio de auditoria, equipe interna de segurança, codificação de código aberto ou algum outro método — a segurança de sua carteira deve ser confiável. Isso reduz o risco para nossos usuários e demonstra que você leva a segurança a sério. -- **Uma carteira que esteja em "atividade" há mais de seis meses OU que tenha sido lançada por um grupo com um histórico de reputação** representa mais uma indicação de segurança. Seis meses é um bom período de tempo para que bugs críticos e explorações tenham sido encontrados. Pedimos seis meses para ajudar a filtrar bifurcações (forks) que são rapidamente abandonados como projetos. -- **Trabalhado por uma equipe ativa** — isso ajuda a garantir a qualidade e que um usuário receba suporte para suas consultas. -- **Informações de listagem corretas e precisas** — espera-se que todas as listagens sugeridas de projetos venham com informações precisas e íntegras. Produtos que falsificam informações de listagem, como declarar que seu produto é de "código aberto" quando não é, serão removidos. -- **Ponto de contato** — Um ponto de contato para a carteira nos ajudará muito a obter informações precisas quando houver mudanças. Isso manterá a atualização do ethereum.org gerenciável ao reunir informações futuras. -- **Transações EIP-1559 (tipo 2)** - sua carteira precisa estar habilitada para transações EIP-1559 (tipo 2) para fazer transações na rede principal do Ethereum. -- **Boa experiência de usuário** - Mesmo que a experiência do usuário seja subjetiva, se vários membros da equipe principal testarem o produto e encontrarem dificuldade em utilizá-lo, nos reservaremos o direito de recusar a carteira e, em vez disso, fornecer sugestões úteis para melhorá-la. Isso é feito para proteger nossa base de usuários, formada principalmente de iniciantes. +- **Um produto com segurança testada** — seja por meio de auditoria, uma equipe de segurança interna, código de fonte aberta ou algum outro método, a segurança da sua carteira deve ser confiável. Isso reduz o risco para nossos usuários e nos mostra que você leva a segurança a sério. +- **Uma carteira que está “no ar” há mais de seis meses OU foi lançada por um grupo com um histórico de boa reputação** — esta é outra indicação de segurança. Seis meses é um bom período de tempo para que bugs críticos e explorações tenham sido encontrados. Pedimos seis meses para ajudar a filtrar bifurcações (forks) que são rapidamente abandonados como projetos. +- **Desenvolvida por uma equipe ativa** — isso ajuda a garantir a qualidade e que o usuário receberá suporte para suas dúvidas. +- **Informações de listagem honestas e precisas** - espera-se que quaisquer listagens sugeridas de projetos venham com informações honestas e precisas. Produtos que falsificam informações de listagem, como declarar que seu produto é de "código aberto" quando não é, serão removidos. +- **Ponto de contato** — um ponto de contato para a carteira nos ajudará muito a obter informações precisas quando forem feitas alterações. Isso manterá a atualização do ethereum.org gerenciável ao reunir informações futuras. +- **Transações EIP-1559 (tipo 2)** — sua carteira deve suportar transações EIP-1559 (tipo 2) para transações na Mainnet do Ethereum. +- **Boa experiência do usuário** — embora a UX seja subjetiva, se vários membros da equipe principal testarem o produto e o considerarem difícil de usar, nos reservamos o direito de rejeitar a carteira e, em vez disso, forneceremos sugestões úteis para melhorias. Isso é feito para proteger nossa base de usuários, formada principalmente de iniciantes. +- **Focada em Ethereum** — uma carteira deve fornecer uma experiência primariamente focada em Ethereum. Isso significa que o Ethereum (ou qualquer L2) é definido como a rede padrão, os ativos ERC são devidamente suportados e os recursos estão alinhados com o ecossistema Ethereum. Carteiras que priorizam na interface de usuário (UI) camadas 1 alternativas não serão listadas. -### Remoções de produto {#product-removals} +### Remoções de produtos {#product-removals} -- **Informação atualizada** - fornecedores de carteira são responsáveis por reenviar a informação sobre suas carteiras a cada 6 meses para assegurar a validade e relevância da informação fornecida (mesmo que não haja mudanças em seus produtos). Se a equipe de produtos não fizer isso, então ethereum.org poderá remover o projeto da página. +- **Informações atualizadas** — os provedores de carteiras são responsáveis por reenviar as informações de suas carteiras a cada 6 meses para garantir a validade e a relevância das informações fornecidas (mesmo que não haja alterações em seu produto). Se a equipe de produtos não fizer isso, então ethereum.org poderá remover o projeto da página. -### Outros critérios: o que é importante ter {#the-nice-to-haves} +### Outros critérios: os diferenciais {#the-nice-to-haves} -- **Globalmente acessível** — sua carteira não possui limitações geográficas ou requisitos de KYC que excluam certas pessoas de acessar seu serviço. -- **Disponível em vários idiomas** — sua carteira é traduzida em vários idiomas, permitindo que usuários ao redor do mundo a acessem. -- **Código aberto** — todo o código de sua projeto (não apenas módulos) deve ser acessível e você deve aceitar as PRs da comunidade em geral. -- **Sem custódia** — os usuários controlam seus fundos. Se o seu produto desaparecer, os usuários ainda poderão acessar e movimentar seus fundos. -- **Suporte à carteira de hardware** — os usuários podem conectar sua carteira de hardware para assinar transações. +- **Acessível globalmente** — sua carteira não tem limitações geográficas ou requisitos de KYC que impeçam certas pessoas de acessar seu serviço. +- **Disponível em vários idiomas** — sua carteira é traduzida para vários idiomas, permitindo que usuários de todo o mundo a acessem. +- **Código aberto** — a base de código de todo o seu projeto (não apenas os módulos) deve ser acessível e você deve aceitar PRs da comunidade em geral. +- **Não custodial** — os usuários controlam seus próprios fundos. Se o seu produto desaparecer, os usuários ainda poderão acessar e movimentar seus fundos. +- **Suporte para carteira de hardware** — os usuários podem conectar sua carteira de hardware para assinar transações. - **WalletConnect** — os usuários podem se conectar a dapps usando o WalletConnect. -- **Importação de endpoints Ethereum RPC** — os usuários podem importar dados do RPC do nó, permitindo que se conectem a um nó de sua escolha ou a outras redes compatíveis com o EVM. +- **Importação de endpoints de RPC do Ethereum** — os usuários podem importar dados de RPC do nó, o que lhes permite conectar a um nó de sua escolha ou a outras redes compatíveis com a EVM. - **NFTs** — os usuários podem visualizar e interagir com seus NFTs na carteira. - **Conectar-se a aplicativos do Ethereum** — os usuários podem se conectar e usar aplicativos do Ethereum. -- **Staking (Participações)** — os usuários podem participar (fazer staking) diretamente pela carteira. -- **Swaps (Trocas)** — os usuários podem trocar tokens pela carteira. -- **Redes Multicadeias** — sua carteira oferece suporte ao acesso de usuários a várias redes de blockchain por padrão. -- **Redes de Camada 2** — sua carteira oferece suporte ao acesso de usuários a redes de camada 2 por padrão. -- **Personalizar taxas de gás** — sua carteira permite que os usuários personalizem as taxas de gás de suas transações (taxa base, taxa prioritária, taxa máxima). -- **Suporte ENS** — sua carteira permite que os usuários enviem transações para nomes ENS. -- **Suporte a ERC-20** — sua carteira permite que os usuários importem contratos de tokens ERC-20 ou exibe automaticamente os tokens ERC-20. -- **Compre criptomoedas** — sua carteira suporta a compra direta de criptomoedas e a introdução de usuários a criptomoedas. -- **Venda para valor legal** — sua carteira dá suporte a usuários que vendam e saquem em valor legal diretamente para cartão ou conta bancária. -- **Multisig** — sua carteira suporta várias assinaturas para assinar uma transação. -- **Recuperação social** — sua carteira oferece suporte a guardiões e um usuário pode recuperar sua carteira se perder sua frase de recuperação usando esses guardiões. -- **Equipe de suporte dedicada** — sua carteira possui uma equipe de suporte dedicada à qual os usuários podem recorrer em caso de problemas. -- **Recursos de educação/documentação** — seu produto deve ter uma experiência de incorporação bem projetada para ajudar e educar os usuários. Ou então, oferecer conteúdo prático como artigos e vídeos. +- **Staking** — os usuários conseguem fazer stake diretamente pela carteira. +- **Swaps** — os usuários podem trocar tokens pela carteira. +- **Redes multichain** — sua carteira oferece suporte para que usuários acessem múltiplas redes blockchain por padrão. +- **Redes de Camada 2** — sua carteira oferece suporte para que usuários acessem redes de camada 2 por padrão. +- **Personalizar taxas de gás** — sua carteira permite que os usuários personalizem suas taxas de gás da transação (taxa base, taxa de prioridade, taxa máxima). +- **Suporte a ENS** — sua carteira permite que os usuários enviem transações para nomes ENS. +- **Suporte a ERC-20** — sua carteira permite que os usuários importem contratos de token ERC-20 ou consulta e exibe automaticamente os tokens ERC-20. +- **Comprar cripto** — sua carteira permite que os usuários comprem e iniciem no mundo cripto diretamente. +- **Vender por fiduciária** — sua carteira permite que usuários vendam e saquem para moeda fiduciária diretamente para o cartão ou conta bancária. +- **Multisig** — sua carteira suporta múltiplas assinaturas para assinar uma transação. +- **Recuperação social** — sua carteira suporta guardiões, e um usuário pode recuperar sua carteira se perder sua frase semente usando esses guardiões. +- **Equipe de suporte dedicada** — sua carteira tem uma equipe de suporte dedicada a qual os usuários podem recorrer quando tiverem problemas. +- **Recursos educacionais/documentação** — seu produto deve ter uma experiência de integração bem projetada para ajudar e educar os usuários. Ou então, oferecer conteúdo prático como artigos e vídeos. ## Adicionando uma carteira {#adding-a-wallet} Se você deseja adicionar uma carteira ao ethereum.org, crie um tíquete no GitHub. - Criar tíquete +Abrir chamado ## Manutenção {#maintenance} @@ -72,9 +73,8 @@ O Ethereum é fluido por natureza, por isso, suas equipes e produtos vêm e vão - garantir que todas as carteiras e dapps listados ainda atendam aos nossos critérios - verificar se não há produtos sugeridos que atendam mais aos nossos critérios do que os atualmente listados -ethereum.org é mantida pela comunidade de código aberto; nós confiamos na comunidade para ajudar a mantê-la atualizada. Se você notar que alguma informação sobre as carteiras listadas precisa ser atualizada, [abra um tíquete](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=wallet+%3Apurse%3A&template=suggest_wallet.yaml) ou uma [solicitação de pull](https://github.com/ethereum/ethereum-org-website/pulls)! - +O ethereum.org é mantido pela comunidade de código aberto e contamos com a comunidade para ajudar a mantê-lo atualizado. Se você notar qualquer informação sobre as carteiras listadas que precise ser atualizada, por favor, [abra um problema](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=wallet+%3Apurse%3A&template=suggest_wallet.yaml) ou uma [requisição de envio](https://github.com/ethereum/ethereum-org-website/pulls)! ## Termos de uso {#terms-of-use} -Consulte também nossos [termos de uso](/terms-of-use/). Informações sobre o ethereum.org são fornecidas exclusivamente para fins de informação geral. +Consulte também nossos [termos de uso](/terms-of-use/). Informações sobre o ethereum.org são fornecidas exclusivamente para fins de informação geral. diff --git a/public/content/translations/pt-br/contributing/content-resources/index.md b/public/content/translations/pt-br/contributing/content-resources/index.md index acba18e7eb7..087e1f4b4bf 100644 --- a/public/content/translations/pt-br/contributing/content-resources/index.md +++ b/public/content/translations/pt-br/contributing/content-resources/index.md @@ -1,10 +1,10 @@ --- -title: Adicionando recursos de conteúdo +title: "Adicionando recursos de conteúdo" lang: pt-br -description: Nossos critérios para adicionar recursos de conteúdo no ethereum.org +description: "Nossos critérios para adicionar recursos de conteúdo no ethereum.org" --- -# Adicionando fontes de conteúdo {#adding-content-resources} +# Adicionando recursos de conteúdo {#adding-content-resources} Não é possível abordar tudo sobre o Ethereum, então tentamos destacar alguns artigos, tutoriais, boletins informativos, sites de empregos e vários outros recursos de conteúdo excelentes criados pela comunidade. Elas geralmente fornecem informações aprofundadas sobre tópicos de interesse dos usuários. @@ -17,9 +17,9 @@ Conteúdos de aprendizado serão avaliados pelos seguintes critérios: - O conteúdo está atualizado? - O conteúdo é pago? - A informação é de confiança? É objetiva ou subjetiva? -- O autor tem credibilidade? As fontes são referenciadas? +- O autor tem credibilidade? Ela faz referência às suas fontes? - Esse conteúdo possui novidades inexistentes nos conteúdos anteriores? -- Esse conteúdo atende a um dos nossos [tipos de usuários](https://www.notion.so/efdn/Ethereum-org-User-Persona-Memo-b44dc1e89152457a87ba872b0dfa366c)? +- Este conteúdo atende a uma das nossas [personas de usuário](https://www.notion.so/efdn/Ethereum-org-User-Persona-Memo-b44dc1e89152457a87ba872b0dfa366c)? --- @@ -28,5 +28,5 @@ Conteúdos de aprendizado serão avaliados pelos seguintes critérios: Se você deseja adicionar uma fonte de conteúdo ao ethereum.org que atende aos critérios, abra um tíquete no GitHub. - Criar um novo problema +Abrir chamado diff --git a/public/content/translations/pt-br/contributing/design-principles/index.md b/public/content/translations/pt-br/contributing/design-principles/index.md index 4a633f79d9b..ad7d065e868 100644 --- a/public/content/translations/pt-br/contributing/design-principles/index.md +++ b/public/content/translations/pt-br/contributing/design-principles/index.md @@ -1,45 +1,45 @@ --- -title: Princípios de design +title: "Princípios de design" lang: pt-br -description: Os princípios por trás das decisões de design e conteúdo do ethereum.org +description: "Os princípios por trás das decisões de design e conteúdo do ethereum.org" --- # Nossos princípios de design {#contributing-to-ethereumorg-} - Olá, bem-vindo aos princípios de design do ethereum.org. Isso faz parte de um processo em curso para desenvolver e melhorar o ethereum.org. + Olá, e bem-vindo aos princípios de design do ethereum.org. Isso faz parte de um processo em curso para desenvolver e melhorar o ethereum.org. Nossos fundamentos orientam a aparência e percepção do site e do conteúdo dele. -Leia isso antes de [contribuir para o ethereum.org](/contributing/). +Você deve lê-los antes de [contribuir para o ethereum.org](/contributing/). -## Quais são os nossos princípios de design? {#ways-to-contribute} +## Quais são os nossos princípios de design? Formas de contribuir {#ways-to-contribute} -Não se preocupe, eles são muito simples! **Os princípios de design** são um conjunto de diretrizes a que nos referimos ao projetar (isto é, criar, manter ou atualizar) algo. +Não se preocupe, eles são muito simples! **Princípios de design** são um conjunto de diretrizes às quais nos referimos ao projetar (isto é, criar, manter ou atualizar) algo. -No contexto do ethereum.org, esses princípios de “design” são a base do que queremos que o site represente e projete para o mundo. Eles são ambiciosos **e** funcionais ao mesmo tempo. Não se trata apenas da _aparência_ do site, mas também como ele _funciona_ e até mesmo como faz alguém _se sentir._ Tudo isso, desde as cores dos "layouts" de página até a forma como falamos sobre o Ethereum no site, deve ser orientado por esses princípios. +No contexto do ethereum.org, esses princípios de “design” são a base do que queremos que o site represente e projete para o mundo. Eles são tanto aspiracionais **quanto** funcionais. Não é apenas sobre a _aparência_ do site, mas também sobre como ele _funciona_ e até mesmo como faz alguém se _sentir_. Tudo, desde as cores até os layouts da página e a forma como falamos sobre o Ethereum no site, deve ser informado por esses princípios. ## Os princípios na prática {#how-decisions-about-the-site-are-made} -Vejamos um exemplo. Um dos princípios é a Credibilidade, o que significa que queremos que os visitantes do site _sintam_ e _saibam_ que o site é confiável — assim como todo o ecossistema do Ethereum. Com base nesse princípio, temos 3 "sub-princípios" funcionais que acreditamos serem medidas viáveis para tornar o site confiável: +Vejamos um exemplo. Um dos princípios é “Confiável”, o que significa que queremos que os visitantes do site _sintam_ e _saibam_ que o site é confiável, assim como o ecossistema Ethereum em geral. Com base nesse princípio, temos 3 "sub-princípios" funcionais que acreditamos serem medidas viáveis para tornar o site confiável: -- _"Atual"_, ou seja, manter o conteúdo atualizado. -- _"Apresentar uma prova social"_, ou seja, mostrar o tamanho, diversidade e atividade do ecossistema (você sabe, o progresso de atualização do Ethereum, DeFi, jogos, todos os hackathons, etc.) -- _"Consistente"_, ou seja, consistência no “design” do site, bem como o tom e precisão da escrita. +- _“Atual”_, ou seja, manter o conteúdo atualizado. +- _“Prova Social”_, ou seja, mostrar o tamanho, a diversidade e a atividade do ecossistema (sabe: o progresso da melhoria do Ethereum, DeFi, jogos, todos os hackathons, etc.) +- _“Consistente”_, ou seja, consistência no design do site e no tom e precisão da escrita. Portanto, quando estamos tomando decisões de design ou de redação, podemos recorrer ao fundamento de credibilidade e perguntar: -- _O site reflete informações atuais?_ -- _"Como e onde estamos mostrando o tamanho e a atividade do ecossistema?"_ -- _"As novas contribuições propostas por um membro da comunidade que estou revisando são consistentes com o design e o texto atuais do site?"_ +- _“O site reflete as informações atuais?”_ +- _“Como e onde estamos mostrando o tamanho e a atividade do ecossistema?”_ +- _“As novas contribuições propostas por um membro da comunidade que estou analisando são consistentes com o design e a escrita atuais no site?”_ -## Os fundamentos de design do ethereum.org {#contributors} +## Os princípios de design do ethereum.org {#contributors} ### 1. Inspirador {#1-inspirational} O site deve inspirar os usuários a sonhar com a maneira como o Ethereum pode mudar o mundo. Ele deve motivar as pessoas a explorar, brincar e mexer com as ferramentas e aplicativos do ecossistema Ethereum. -- **Radical:** o site deve comunicar os objetivos ambiciosos do Ethereum para mudar o mundo de forma significativa. É importante deixar claro que o Ethereum não é apenas uma pilha de tecnologia, mas uma tecnologia transformacional. -- **Empoderamento por meio da educação:** o site deve educar as pessoas de modo que entendam o potencial do Ethereum, encontrem o seu lugar no ecossistema e sintam-se empoderadas a participar dele. +- **Radical:** o site deve comunicar as metas ambiciosas do Ethereum de mudar o mundo de forma significativa. É importante deixar claro que o Ethereum não é apenas uma pilha de tecnologia, mas uma tecnologia transformacional. +- **Empoderamento por meio da educação:** o site deve educar as pessoas para que elas possam entender o potencial do Ethereum, encontrar seu lugar no ecossistema e se sentirem empoderadas para participar dele. Direção Visual • Conteúdo @@ -47,8 +47,8 @@ Direção Visual • Conteúdo O Ethereum é um projeto global, descentralizado, e nosso público reflete isso. O site deve aspirar ser acessível a todos e sensível às diversas culturas do mundo. -- **Acessível:** o site deve seguir diretrizes de acessibilidade, inclusive para pessoas com conexões de baixa largura de banda. -- **Avançar:** o site deve ser simples e isento de ambiguidades. A versão não deve usar linguagem que possa ser mal interpretada ou conter traduções imprecisas. +- **Acessível:** o site deve seguir as diretrizes de acessibilidade, inclusive para pessoas com conexões de baixa largura de banda. +- **Direto ao ponto:** o site deve ser simples e sem ambiguidades. A versão não deve usar linguagem que possa ser mal interpretada ou conter traduções imprecisas. - **O Ethereum é multifacetado:** o Ethereum é um projeto, uma base de código, uma comunidade e uma visão. O Ethereum é valioso para diferentes pessoas por diferentes razões, e há muitas maneiras de se envolver com ele. Sistemas de escrita • Uso de cores • Direção visual • Conteúdo @@ -57,8 +57,8 @@ Sistemas de escrita • Uso de cores • Direção visual • Conteúdo O site deve funcionar como uma boa história. Os visitantes estão em uma jornada e o conteúdo que você contribui faz parte disso. Suas contribuições devem se encaixar em uma narrativa clara: com início (introdução/ponto de partida), meio (conjunto de aprendizados e informações) e fim (links para recursos relevantes ou próximos passos). -- **Hierárquico**: uma arquitetura de informações clara e hierarquicamente estruturada ajuda os visitantes do ethereum.org a navegar no site "como uma história" à medida que buscam atingir seus objetivos. -- **Um trampolim:** somos um trampolim para quem procura respostas. Não queremos substituir ou nos tornar um substituto para os muitos recursos que já existem. Fornecemos respostas e informações confiáveis sobre próximos passos a seguir. +- **Hierárquico**: uma arquitetura de informações clara e hierarquicamente estruturada ajuda os visitantes do ethereum.org a navegar pelo site "como uma história" enquanto buscam atingir seus objetivos. +- **Um trampolim:** somos um trampolim para qualquer pessoa que esteja procurando por respostas. Não queremos substituir ou nos tornar um substituto para os muitos recursos que já existem. Damos uma resposta e fornecemos os próximos passos confiáveis. Jornadas do usuário • Conteúdo @@ -68,26 +68,26 @@ As pessoas podem estar procurando descobrir o ecossistema Ethereum ou podem ser - **Atual:** sempre atualizado. - **Prova social:** mostre o tamanho, a diversidade e a atividade do ecossistema. -- **Consistente:** consistência no design e no conteúdo transmite credibilidade. +- **Consistente:** a consistência no design e no conteúdo comunica credibilidade. Direção Visual • Conteúdo -### 5. Melhoria colaborativa {#5-collaborative-improvement} +### 5. Melhoria Colaborativa {#5-collaborative-improvement} O site é o produto de muitos colaboradores, assim como o ecossistema como um todo. -- **Aberto:** celebre a transparência do código-fonte, processos e projetos em todo o ecossistema. -- **Extensível:** a modularidade é um elemento fundamental por trás de tudo o que fazemos e, portanto, as contribuições também devem ser modulares. O projeto principal, o código do componente e a implementação do site devem permitir que ele seja facilmente ampliado no futuro. +- **Aberto:** celebre a transparência do código-fonte, dos processos e dos projetos em todo o ecossistema. +- **Extensível:** a modularidade é um foco principal por trás de tudo o que fazemos e, portanto, as contribuições também devem ser modulares. O design principal, o código do componente e a implementação do site devem permitir que ele seja facilmente estendido no futuro. - **Experimental:** estamos constantemente experimentando, testando e iterando. -- **Colaborativo:** esse projeto reúne todos nós. -- **Sustentável:** estabelecendo uma manutenção de longo prazo pela comunidade +- **Colaborativo:** este projeto reúne todos nós. +- **Sustentável:** preparando para a manutenção de longo prazo pela comunidade -Você pode ver nossos princípios de design em ação [em nosso site](/). +Você pode ver nossos princípios de design em ação [em todo o nosso site](/). -## Enviar comentários {#give-feedback} +## Forneça feedback {#give-feedback} -**Compartilhe seus comentários sobre este documento!** Um de nossos princípios propostos é a “**Melhoria Colaborativa**”, ou seja, queremos o site seja o produto de muitos colaboradores. Portanto, no espírito desse princípio, queremos compartilhar esses princípios de design com a comunidade Ethereum. +**Compartilhe seu feedback sobre este documento!** Um dos nossos princípios propostos é a “**Melhoria Colaborativa**”, o que significa que queremos que o site seja o produto de muitos contribuidores. Portanto, no espírito desse princípio, queremos compartilhar esses princípios de design com a comunidade Ethereum. -Embora esses princípios estejam focados no site ethereum.org, esperamos que muitos deles representem os valores do ecossistema Ethereum em geral. Talvez você até queira incorporar alguns deles em seu próprio projeto! +Embora estes princípios sejam focados no site ethereum.org, esperamos que muitos deles sejam representativos dos valores do ecossistema Ethereum como um todo. Talvez você até queira incorporar alguns deles em seu próprio projeto! -Dê sua opinião no [servidor Discord](https://discord.gg/ethereum-org) ou [criando um tíquete](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=Type%3A+Feature&template=feature_request.yaml&title=). +Conte-nos o que você pensa em nosso [servidor do Discord](https://discord.gg/ethereum-org) ou [criando um issue](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=Type%3A+Feature&template=feature_request.yaml&title=). diff --git a/public/content/translations/pt-br/contributing/design/adding-design-resources/index.md b/public/content/translations/pt-br/contributing/design/adding-design-resources/index.md index 95aa42d318c..7d2c66ab2f2 100644 --- a/public/content/translations/pt-br/contributing/design/adding-design-resources/index.md +++ b/public/content/translations/pt-br/contributing/design/adding-design-resources/index.md @@ -6,7 +6,7 @@ lang: pt-br # Adicionando recursos de design {#adding-design-resources} -Qualquer pessoa pode sugerir novos materiais de design para a página de [Design e UX na web3](/developers/docs/design-and-ux/). +Qualquer pessoa pode sugerir novos materiais de design para a [página de Design e UX na web3](/developers/docs/design-and-ux/). Esteja ciente de que o foco desta página é fornecer valor ao usuário para candidatos a designers web3. A seção de design não está lá para anunciar seus serviços, produtos ou plataformas. @@ -56,7 +56,7 @@ a. O objetivo principal do artigo deve ser compartilhar informações em vez de a. Os benefícios de se tornar um membro devem ser apresentados em destaque. -**Exemplos**: receber comentários sobre o trabalho, acessar oportunidades de trabalho ou recompensas, compartilhar conhecimentos de design e pesquisa. +**Exemplos**: receber feedback sobre o trabalho, acessar oportunidades de emprego ou recompensas, compartilhar insights de design e pesquisa. 3. Comunicação ativa e vibrante no Discord diff --git a/public/content/translations/pt-br/contributing/design/index.md b/public/content/translations/pt-br/contributing/design/index.md index f01744e575c..707353c99e7 100644 --- a/public/content/translations/pt-br/contributing/design/index.md +++ b/public/content/translations/pt-br/contributing/design/index.md @@ -1,26 +1,26 @@ --- -title: Contribuição no design -description: Contribuição no design do ethereum.org +title: "Contribuição no design" +description: "Contribuição no design do ethereum.org" lang: pt-br --- -# Contribuição no design do ethereum.org {#design-contributions} +# Contribuição de design para o ethereum.org {#design-contributions} -O design é um componente crítico de qualquer projeto e, dedicando seu tempo e habilidades de design ao Ethereum.org, você pode ajudar a melhorar a experiência do usuário para nossos visitantes. Contribuir para um projeto de código aberto oferece uma oportunidade de ganhar experiência relevante e desenvolver suas habilidades em um ambiente colaborativo. Você terá a chance de trabalhar com outros designers, desenvolvedores e membros da comunidade, todos com suas próprias perspectivas e visões. +O design é um componente essencial de qualquer projeto e, ao dedicar seu tempo e habilidades de design ao ethereum.org, você pode ajudar a melhorar a experiência do usuário para nossos visitantes. Contribuir para um projeto de código aberto oferece uma oportunidade de ganhar experiência relevante e desenvolver suas habilidades em um ambiente colaborativo. Você terá a chance de trabalhar com outros designers, desenvolvedores e membros da comunidade, todos com suas próprias perspectivas e visões. Por fim, essa é uma ótima maneira de construir um portfólio diversificado e impressionante que mostre suas habilidades de design. ## Como contribuir? -###  Forneça feedback sobre os primeiros protótipos de design {#design-critique} +###  Forneça feedback sobre protótipos de design iniciais {#design-critique} Às vezes, precisamos de ajuda para testar nossas ideias originais. Esta é uma ótima maneira de como contribuir sem nenhum conhecimento técnico. -1. A equipe de design compartilhará um modelo de projeto no [Discord](https://discord.com/invite/ethereum-org) e no [GitHub](https://github.com/ethereum/ethereum-org-website/labels/design%20required%20%F0%9F%8E%A8). +1. A equipe de design compartilhará um mockup de design no [Discord](https://discord.com/invite/ethereum-org) e no [GitHub](https://github.com/ethereum/ethereum-org-website/labels/design%20required%20%F0%9F%8E%A8). 2. Você será guiado pelos projetos para fornecer feedback por meio da função de comentários. 3. O resultado será compartilhado em problemas do GitHub e depois fechado pela equipe. -###  Participe da pesquisa de levantamento {#answer-surveys} +###  Participe de pesquisas {#answer-surveys} Forneça seus comentários em nosso site: @@ -28,50 +28,50 @@ Forneça seus comentários em nosso site: 2. Clicando no widget de feedback no canto inferior direito e respondendo a perguntas relacionadas ao design e conteúdo. 3. Foque nas perguntas de formato livre. -###  Encontre problemas relacionados ao design no site e reporte-os {#report-design-issues} +###  Encontre problemas relacionados a design no site e relate-os {#report-design-issues} -O Ethereum.org é um site de rápido crescimento com muitos recursos e conteúdo. Algumas das interfaces de usuário podem facilmente se tornar obsoletas ou poderiam ser aprimoradas. Se você encontrar qualquer caso parecido, por favor reporte ele para que chame a nossa atenção. +ethereum.org é um site de rápido crescimento com muitos recursos e conteúdo. Algumas das interfaces de usuário podem facilmente se tornar obsoletas ou poderiam ser aprimoradas. Se você encontrar qualquer caso parecido, por favor reporte ele para que chame a nossa atenção. 1. Acesse o site e preste atenção em seu design. 2. Faça capturas de tela e anotações se você notar algum problema visual ou de experiência do usuário. -3. Reporte os problemas encontrados usando um [formulário de bug](https://github.com/ethereum/ethereum-org-website/issues/new/choose). +3. Relate os problemas encontrados usando um [relatório de bug](https://github.com/ethereum/ethereum-org-website/issues/new/choose). -###  Proponha mudanças de design {#propose-design-changes} +###  Proponha alterações de design {#propose-design-changes} -Se você se sente à vontade para enfrentar desafios de design, visite nosso quadro de problemas do GitHub e filtre por [problemas relacionados ao design](https://github.com/ethereum/ethereum-org-website/labels/design%20required%20%F0%9F%8E%A8). +Se você se sentir à vontade para assumir desafios de design, pode visitar nosso quadro de problemas do GitHub e filtrar por [problemas relacionados a design](https://github.com/ethereum/ethereum-org-website/labels/design%20required%20%F0%9F%8E%A8). -1. Vá ao nosso site e preste atenção em seu design ou acesse nosso repositório GitHub e analise os problemas sinalizados com a [Etiqueta "Design necessário"](https://github.com/ethereum/ethereum-org-website/labels/design%20required%20%F0%9F%8E%A8). -2. Idealize a solução e desenhe-a. (idealmente usando nosso [sistema de design](https://www.figma.com/community/file/1134414495420383395)). -3. Proponha a solução no tíquete do GitHub correspondente ou [abra um novo.](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=feature+%3Asparkles%3A&template=feature_request.yaml&title=Feature+request) +1. Navegue em nosso site e preste atenção ao seu design ou acesse nosso repositório no GitHub e revise os problemas sinalizados com a [tag “Design required”](https://github.com/ethereum/ethereum-org-website/labels/design%20required%20%F0%9F%8E%A8). +2. Idealize a solução e desenhe-a. (de preferência, usando nosso [sistema de design](https://www.figma.com/community/file/1134414495420383395)). +3. Proponha a solução no problema correspondente do GitHub ou [crie um novo.](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=feature+%3Asparkles%3A&template=feature_request.yaml&title=Feature+request) 4. Aguarde a revisão do time de design. -###  Construir o Sistema de Design juntos {#Contribute-to-design-system} +###  Construa o Sistema de Design em conjunto {#Contribute-to-design-system} Nosso sistema de design torna o projeto ethereum.org divertido e fácil. Se você é um designer experiente, você pode nos ajudar a preparar muitos componentes para o site. -1. Selecione um problema para trabalhar no painel [sobre sistema de design](https://github.com/ethereum/ethereum-org-website/labels/design%20system) no GitHub ou crie um novo. +1. Selecione um problema para trabalhar no [quadro do sistema de design](https://github.com/ethereum/ethereum-org-website/labels/design%20system) no GitHub ou crie um novo. 2. Peça que o problema selecionado seja atribuído a você. -3. Comece a projetar o componente solicitado na figma. +3. Comece a projetar o componente solicitado no Figma. 4. Compartilhe-o com a equipe de design no GitHub, assim que você precisar de revisão ou orientação. 5. A equipe de design revisará. -6. A equipe de design vai incorporar as mudanças no arquivo principal e publicará o arquivo para a comunidade. +6. A equipe de design incorporará as alterações no arquivo principal e publicará o arquivo na comunidade. -###  Escreva o conteúdo relacionado ao design no site {#write-design-articles} +###  Escreva conteúdo relacionado a design no site {#write-design-articles} -A comunidade de desenvolvedores Ethereum é forte, mas a comunidade de design está ficando um pouco para trás. Se você é um designer com conhecimento em web3, por favor, considere compartilhar seus aprendizados com a comunidade maior, para que todos possamos crescer e melhorar juntos; temos [uma página sobre design para Ethereum](/developers/docs/design-and-ux/) para a qual você pode contribuir. Você também pode verificar nossas [políticas de listagem](/contributing/design/adding-design-resources). +A comunidade de desenvolvedores Ethereum é forte, mas a comunidade de design está ficando um pouco para trás. Se você é um designer com conhecimento em web3, por favor, considere compartilhar seus aprendizados com a comunidade maior para que todos possamos crescer e melhorar juntos; temos [uma página sobre design para Ethereum](/developers/docs/design-and-ux/) para a qual você pode contribuir. Você também pode conferir nossas [políticas de listagem](/contributing/design/adding-design-resources). 1. Idealize sobre tópicos de design que devem ser cobertos no ethereum.org e seriam benéficos para os designers no espaço. -2. Vá ao nosso repositório do GitHub e [levante um problema](https://github.com/ethereum/ethereum-org-website/issues/new) propondo um tópico (não escreva o conteúdo ainda). +2. Acesse nosso repositório do GitHub e [abra um problema](https://github.com/ethereum/ethereum-org-website/issues/new) propondo um tópico (ainda não escreva o conteúdo). 3. Aguarde a aprovação do time de design. 4. Uma vez aprovado, escreva o conteúdo. -5. Envie-o no problema GH correspondente. +5. Envie-o no ticket correspondente do GitHub. ###  Desenhe novas ilustrações {#prepare-illustrations} As visualizações são uma das ferramentas mais poderosas para explicar tópicos abstratos. Há um enorme potencial ao adicionar diagramas e infográficos. Afinal, uma imagem pode dizer mil palavras. 1. Vá ao nosso site e veja as páginas onde alguns novos infográficos poderiam ser adicionados. -2. Certifique-se de que o estilo da ilustração corresponda aos nossos [recursos](/assets/). -3. Vá ao nosso repositório GitHub e [levante um problema](https://github.com/ethereum/ethereum-org-website/issues/new) propondo a ilustração. +2. Certifique-se de que o estilo da ilustração corresponda aos nossos [ativos](/assets/). +3. Acesse nosso repositório do GitHub e [abra um problema](https://github.com/ethereum/ethereum-org-website/issues/new) propondo a ilustração. 4. A equipe de design irá analisá-lo. 5. Nós criamos um novo problema para pedir a um desenvolvedor que implemente a nova imagem. diff --git a/public/content/translations/pt-br/contributing/index.md b/public/content/translations/pt-br/contributing/index.md index effce42555b..3cba1975d88 100644 --- a/public/content/translations/pt-br/contributing/index.md +++ b/public/content/translations/pt-br/contributing/index.md @@ -1,46 +1,51 @@ --- -title: Contribuições +title: "Contribuições" description: Descubra as diferentes maneiras de contribuir com o ethereum.org lang: pt-br --- -# Contribua com o ethereum.org 🦄 {#contributing-to-ethereumorg} +# Contribuindo para o ethereum.org 🦄 {#contributing-to-ethereumorg} -Ethereum.org é um projeto de código aberto em execução com **mais de 12.000** contribuidores que ajudam a traduzir, escrever, estruturar e manter o site. +O Ethereum.org é um projeto de código aberto com mais de **12.000** colaboradores que ajudam a traduzir, escrever, criar o design e manter o site. Nós somos uma comunidade de braços abertos que irá ajudá-lo a crescer e se informar no ecossistema Ethereum enquanto você também contribui significativamente e obtém experiência prática relevante. ## Formas de contribuir {#ways-to-contribute} **Traduções** -- [Junte-se ao programa de tradução](/contributing/translation-program/) – Nos ajude a levar o ethereum.org para novos idiomas + +- [Participe do programa de tradução](/contributing/translation-program/) – Ajude-nos a levar o ethereum.org para novos idiomas **Desenvolvimento** -- [Trabalhe em um problema aberto](https://github.com/ethereum/ethereum-org-website/issues) – Trabalho que nós identificamos que deve ser feito -**Visual** -- [Ajude a estruturar o site](/contributing/design/) Profissionais de design de todos os níveis podem contribuir para melhorar o site +- [Trabalhe em um problema em aberto](https://github.com/ethereum/ethereum-org-website/issues) – Trabalho que identificamos que precisa ser feito + +**Design** + +- [Ajude a projetar o site](/contributing/design/) – Designers de todos os níveis podem contribuir para melhorar o site **Conteúdo** -- [Criar/editar conteúdo](/contributing/#how-to-update-content) – Sugira novas páginas ou ajustes para o que já existe aqui -- [Adicione recursos da comunidade](/contributing/content-resources/) – Adicione um artigo ou recurso útil a uma página -- [Sugira um recurso de design](/contributing/design/adding-design-resources/) – Adicione e atualize recursos de design que possam ajudar ou exclua algum deles -- [Adicione um termo de glossário](/contributing/adding-glossary-terms/) – Nos ajude a continuar a expandir o [glossário](/glossary/) do Ethereum -- [Jogos de perguntas e respostas](/contributing/quizzes/) – Adicione, atualize ou exclua bancos de jogos de perguntas e respostas de uma página + +- [Criar/editar conteúdo](/contributing/#how-to-update-content) – Sugira novas páginas ou faça ajustes no que já existe +- [Adicione recursos da comunidade](/contributing/content-resources/) – Adicione um artigo ou recurso útil a uma página relevante +- [Sugira um recurso de design](/contributing/design/adding-design-resources/) – Adicione, atualize e exclua recursos de design úteis +- [Questionários](/contributing/quizzes/) – Adicione, atualize e exclua bancos de perguntas de questionários para uma página relevante **Ideias para funcionalidades** -- [Solicite uma funcionalidade](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=Type%3A+Feature&template=feature_request.yaml&title=) – Nos avise sobre qualquer ideia que você tenha para uma nova funcionalidade ou design + +- [Solicite um recurso](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=Type%3A+Feature&template=feature_request.yaml&title=) – Conte-nos sobre qualquer ideia que você tenha para um novo recurso ou design **Listagens de produtos** -- [Adicione uma exchange](/contributing/adding-exchanges/) – Adicione uma exchange ao nosso [buscador de exchanges](/get-eth/#country-picker) -- [Adicione um produto](/contributing/adding-products/) – Adicione um dapp ou uma carteira a uma página -- [Adicione ferramentas para desenvolvimento](/contributing/adding-developer-tools/) – Adicione uma ferramenta para desenvolvimento a uma página -- [Adicione uma camada 2](/contributing/adding-layer-2s/) – Adicione a camada 2 a uma página -- [Adicione um produto ou serviço para investimentos](/contributing/adding-staking-products/) – Adicione um projeto que ajude a facilitar o staking solo, em grupo ou o staking como serviço + +- [Adicione uma corretora](/contributing/adding-exchanges/) – Adicione uma corretora ao nosso [localizador de corretoras](/get-eth/#country-picker) +- [Adicione um produto](/contributing/adding-products/) – Adicione um dapp ou uma carteira a uma página relevante +- [Adicione ferramentas de desenvolvedor](/contributing/adding-developer-tools/) – Adicione uma ferramenta de desenvolvedor a uma página relevante +- [Adicione uma layer 2](/contributing/adding-layer-2s/) – Adicione uma layer 2 a uma página relevante +- [Adicione um produto ou serviço de staking](/contributing/adding-staking-products/) – Adicione um projeto que ajude a facilitar o staking individual, staking em pool ou staking como serviço - [Adicione uma carteira](/contributing/adding-wallets/) – Adicione uma carteira para a [página de busca de carteiras](/wallets/find-wallet/) -- [Sugira um projeto para a nossa página DeSci](/contributing/adding-desci-projects/) – Adicione um projeto criado no Ethereum que contribua para descentralizar a ciência +- [Sugira um projeto para nossa página DeSci](/contributing/adding-desci-projects/) – Adicione um projeto construído no Ethereum que contribua para a ciência descentralizada -Alguma dúvida? 🤔 Junte-se ao nosso [servidor Discord](https://discord.gg/ethereum-org) +Alguma dúvida? 🤔 Junte-se ao nosso [servidor do Discord](https://discord.gg/ethereum-org) ## Tarefas adequadas para começar a contribuir @@ -52,64 +57,64 @@ Estas são algumas tarefas atuais das que você poderia se encarregar e nos ajud ## Como trabalhar no ethereum.org {#how-to-update-content} -Se você deseja contribuir com o [Programa de Tradução](/contributing/translation-program/), crie uma conta no [Crowdin](https://crowdin.com/project/ethereum-org). Para adicionar e editar conteúdo ou efeitos visuais no site, corrigir erros, trabalhar em tarefas abertas, por exemplo, você vai precisar de uma conta no [GitHub](https://github.com/). +Se você deseja contribuir no [Programa de Tradução](/contributing/translation-program/), pedimos que crie uma conta no [Crowdin](https://crowdin.com/project/ethereum-org). Para todo o resto – adicionar ou editar conteúdo ou elementos visuais do site, corrigir bugs, trabalhar em tarefas em aberto – você precisará de uma conta no [GitHub](https://github.com/). -Todas as atualizações são efetuadas por meio do processo de PR (solicitação de pull) do GitHub. Isso significa que você cria uma cópia local do site, faz as suas alterações e solicita que elas sejam implementadas. Se você nunca fez isso antes, siga as instruções na parte inferior do nosso [repositório GitHub](https://github.com/ethereum/ethereum-org-website). +Todas as atualizações são efetuadas por meio do processo de PR (solicitação de pull) do GitHub. Isso significa que você cria uma cópia local do site, faz as suas alterações e solicita que elas sejam implementadas. Se você nunca fez isso antes, siga as instruções na parte inferior do nosso [repositório do GitHub](https://github.com/ethereum/ethereum-org-website). Você não precisa de permissão para trabalhar em nada, mas é sempre melhor nos informar sobre o que está planejando fazer. Você pode fazer isso: -- Comentando sobre um problema ou uma solicitação de pull (PR) no [GitHub](https://github.com/ethereum/ethereum-org-website) -- Enviando uma mensagem via o [servidor Discord](https://discord.gg/ethereum-org) +- Comentando em um problema ou PR no [GitHub](https://github.com/ethereum/ethereum-org-website) +- Enviando mensagens em nosso [servidor do Discord](https://discord.gg/ethereum-org) Antes de contribuir, certifique-se de está familiarizado com: -- a [visão do ethereum.org](/about/) em evolução +- a [visão em evolução do ethereum.org](/about/) - nossos [princípios de design](/contributing/design-principles/) - nosso [guia de estilo](/contributing/style-guide/) - nosso [código de conduta](/community/code-of-conduct) -## Como são tomadas as decisões sobre o site {#how-decisions-about-the-site-are-made} +## How decisions about the site are made {#how-decisions-about-the-site-are-made} -As decisões sobre PRs individuais, desenvolvimento do design e melhorias importantes são feitas por uma equipe formada no ecossistema Ethereum. Esta equipe inclui gerentes de projeto, desenvolvedores, designers, gerentes de marketing e comunicação, e especialistas no assunto. Cada decisão considera as contribuições da comunidadem. Portanto, não duvide em fazer perguntas via tíquetes, enviar PRs ou entrar em contato com a equipe: +Decisions about individual PRs, design evolution and major upgrades are made by a team from across the Ethereum ecosystem. This team includes project managers, developers, designers, marketing and communications, and subject matter experts. Community input informs every decision: so please raise questions in issues, submit PRs, or contact the team: - [website@ethereum.org](mailto:website@ethereum.org) - [@ethdotorg](https://twitter.com/ethdotorg) -- [Servidor do Discord](https://discord.gg/ethereum-org) +- [Discord server](https://discord.gg/ethereum-org) -### Observação sobre plágio {#plagiarism} +### A note on plagiarism {#plagiarism} -Ao contribuir com qualquer conteúdo ou artefato no ethereum.org, use somente trabalhos ou conteúdos originais para os que você tem permissão de utilizar. Muitos projetos no ecossistema do Ethereum usam licenças de código aberto que permitem o compartilhamento livre de informações. No entanto, se você não encontrar essas informações, não tente adicioná-los ao ethereum.org. Todas as solicitações de envio (PR, pull request) consideradas como plágio serão rejeitadas. +Only use your original work or content that you have permission to use when contributing any content or artifact to ethereum.org. Many projects within the Ethereum ecosystem use open-source licensing that allows for the free sharing of information. However, if you cannot find this information, do not attempt to add it to ethereum.org. Any pull requests deemed as plagiarism will get rejected. -## Você é iniciante em código aberto? {#new-to-open-source} +## New to open-source? {#new-to-open-source} -Em nosso repositório do GitHub, temos uma categoria de envio de tíquetes especialmente criada para desenvolvedores iniciantes em código aberto. Esses tíquetes de baixa dificuldade são rotulados como [good first issue](https://github.com/ethereum/ethereum-org-website/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) (boa escolha para primeiro tíquete). +We have low barrier to entry issues on our GitHub repository specifically designed for developers who are new to open-source labelled [good first issue](https://github.com/ethereum/ethereum-org-website/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22). -## Reivindique seu token de conquista on-chain (OAT) {#oat} +## Claim your Onchain Achievement Token (OAT) {#oat} -Se sua contribuição for incluída no ethereum.org, você terá a chance de reivindicar um badge especial no [Galxe](https://app.galxe.com/quest/ethereumorg). Um token de conquista on-chain (OAT) é uma prova de que você contribuiu com o ecossistema de maneira considerável. +If your contribution gets merged into ethereum.org, you will have a chance to claim a special badge on [Galxe](https://app.galxe.com/quest/ethereumorg). An Onchain Achievement Token (OAT) is a proof that you helped make the ecosystem a little more awesome. -[Mais sobre OATs](https://help.galxe.com/en/articles/9645630-create-quest-rewards#h_1c5d63ba03) +[More on OATs](https://help.galxe.com/en/articles/9645630-create-quest-rewards#h_1c5d63ba03) -### Como solicitar seu POAP -1. Junte-se ao nosso [servidor Discord](https://discord.gg/ethereum-org). -2. Cole um link para sua contribuição no canal `#🥇 | proof-of-contribution` -3. Aguarde até que um membro da nossa equipe lhe envie um link para seu OAT. -4. Reivindique seu OAT! +### How to claim -Você só deve usar carteiras de autocustódia para reivindicar OATs. Não use contas de exchange ou outras contas cujas chaves privadas você não tenha, pois elas não permitirão que você acesse e gerencie seus OATs. +1. Join our [Discord server](https://discord.gg/ethereum-org). +2. Paste a link to your contribution in the `#🥇 | proof-of-contribution` channel. +3. Wait for a member of our team to send you a link to your OAT. +4. Claim your OAT! -## Resgate seu GitPOAP {#claim-gitpoap} +You should only use self-custody wallets to claim OATs. Do not use exchange accounts or other accounts you do not hold the private keys to, as these will not allow you to access and manage your OATs. -O GITPOAP também reconhecerá automaticamente sua contribuição fusionada e permitirá que você cunhe um POAP de colaboradores exclusivo e separado na sua própria plataforma! +## Claim your GitPOAP {#claim-gitpoap} +GitPOAP will also automatically recognize your merged contribution and let you mint a separate unique contributors POAP on their platform itself! -### Como solicitar seu POAP {#how-to-claim} +### How to claim {#how-to-claim} -1. Visite [GitPOAP](https://www.gitpoap.io). -2. Conecte-se à sua carteira ou mesmo ao seu e-mail com a opção de entrada. -3. Procure seu nome de usuário no GitHub, endereço ETH, nomes ENS ou qualquer GitPOAP para verificar se você é elegível. -4. Se sua conta no GitHub for elegível, você poderá cunhar um GitPOAP! +1. Visit [GitPOAP](https://www.gitpoap.io). +2. Connect with your wallet or even with your email through sign in option. +3. Search for your GitHub username, ETH address, ENS names or any GitPOAP to check if you're eligible. +4. If your GitHub account is eligible, then you would be able to mint a GitPOAP! -## Colaboradores {#contributors} +## Contributors {#contributors} diff --git a/public/content/translations/pt-br/contributing/quizzes/index.md b/public/content/translations/pt-br/contributing/quizzes/index.md index e972230a9b7..bb61e776c82 100644 --- a/public/content/translations/pt-br/contributing/quizzes/index.md +++ b/public/content/translations/pt-br/contributing/quizzes/index.md @@ -1,6 +1,6 @@ --- -title: Adicionando um questionário -description: A política que nós usamos quando adicionando questionários na ethereum.org +title: "Adicionando um questionário" +description: "A política que nós usamos quando adicionando questionários na ethereum.org" lang: pt-br --- @@ -14,12 +14,12 @@ Alguns exemplos de questionários atuais podem ser encontrados aqui: - [Camada 2](/layer-2) - [NFT](/nft/) -- [O que é o Ethereum?](/what-is-ethereum/) +- [O que é Ethereum?](/what-is-ethereum/) - [O que é ETH?](/what-is-ether/) ## Adicionando um questionário de aprendizado -Se há uma página que não tem um questionário de aprendizado criado para ela, por favor [abra um issue](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=&template=suggest_quiz.yaml) para ela. +Se uma página ainda não tiver um questionário de aprendizado, [abra um issue](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=&template=suggest_quiz.yaml) para criá-lo. Por favor forneça as seguintes informações: @@ -32,7 +32,7 @@ Por favor forneça as seguintes informações: ## Adicionando uma pergunta ao questionário -Se há uma questão que você quer adicionar para o banco de questões para um questionário, por favor [abra um issue](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=&template=suggest_quiz.yaml) e forneça as seguintes informações: +Se você quiser adicionar uma pergunta ao banco de perguntas de um questionário, [abra um issue](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=&template=suggest_quiz.yaml) e forneça as seguintes informações: - A página a qual você quer adicionar uma questão de questionário - Para cada questão, forneça as seguintes informações: @@ -43,7 +43,7 @@ Se há uma questão que você quer adicionar para o banco de questões para um q ## Atualizando uma questão de questionário -Se há uma questão que você quer atualizar no banco de questões para um questionário, por favor [abra um issue](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=&template=suggest_quiz.yaml) e forneça as seguintes informações: +Se você quiser atualizar uma pergunta no banco de perguntas de um questionário, [abra um issue](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=&template=suggest_quiz.yaml) e forneça as seguintes informações: - A página à qual você quer atualizar uma questão de questionário - Para cada questão sendo atualizada, forneça as seguintes informações: @@ -55,7 +55,7 @@ Se há uma questão que você quer atualizar no banco de questões para um quest ## Removendo uma questão de questionário -Se o conteúdo não existe mais na página de uma questão e ela precisa ser removida, [abra um tíquete](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=&template=suggest_quiz.yaml) para remover a questão e forneça as seguintes informações: +Para remover uma pergunta cujo conteúdo não existe mais na página, [abra um issue](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=&template=suggest_quiz.yaml) e forneça as seguintes informações: - A página à qual você quer excluir uma questão de questionário - A questão que você quer excluir diff --git a/public/content/translations/pt-br/contributing/translation-program/faq/index.md b/public/content/translations/pt-br/contributing/translation-program/faq/index.md index f1ef27d0e4c..d8ffa9a4a7f 100644 --- a/public/content/translations/pt-br/contributing/translation-program/faq/index.md +++ b/public/content/translations/pt-br/contributing/translation-program/faq/index.md @@ -1,10 +1,10 @@ --- -title: Perguntas frequentes sobre o Programa de tradução +title: "Perguntas frequentes sobre o Programa de tradução" lang: pt-br -description: Perguntas frequentes sobre o Programa de tradução da ethereum.org +description: "Perguntas frequentes sobre o Programa de tradução da ethereum.org" --- -# Traduzindo o guia ethereum.org {#translating-ethereum-guide} +# Guia de tradução do ethereum.org {#translating-ethereum-guide} Se você é novo no Programa de tradução e está hesitante em participar, aqui estão algumas perguntas frequentes que podem ajudá-lo a começar. Use este guia para encontrar respostas para as consultas mais comuns. @@ -18,31 +18,31 @@ O objetivo do Programa de Tradução é tornar o conteúdo do Ethereum acessíve Por essa razão, o Programa de Tradução é aberto e voluntário, e a participação não está sujeita a compensações. Se fôssemos compensar os tradutores pelo número de palavras traduzidas, só poderíamos convidar aqueles com experiência de tradução suficiente (tradutores profissionais) para participar do Programa de Tradução. Isso tornaria o Programa de Tradução exclusivo e nos impediria de alcançar os objetivos delineados, especificamente, permitindo que todos participem e se envolvam com o ecossistema. -Fazemos o possível para permitir que nossos colaboradores tenham sucesso no ecossistema Ethereum. Muitos incentivos não-monetários estão em vigor, como [oferecer POAPs](/contributing/translation-program/acknowledgements/#poap) e um [certificado de tradutor](/contributing/translation-program/acknowledgements/#certificate), além de organizar os [rankings de tradução](/contributing/translation-program/acknowledgements/) e [listar todos os nossos tradutores no site](/contributing/translation-program/contributors/). +Fazemos todos os esforços para permitir que nossos contribuidores tenham sucesso no ecossistema Ethereum; muitos incentivos não monetários estão em vigor, como: [oferecer POAPs](/contributing/translation-program/acknowledgements/#poap) e um [certificado de tradutor](/contributing/translation-program/acknowledgements/#certificate), bem como organizar os [Placares de Líderes de Tradução](/contributing/translation-program/acknowledgements/) e [listar todos os nossos tradutores no site](/contributing/translation-program/contributors/). -## Como traduzo cadeias de caracteres com ``? {#tags} +## Como traduzo strings com ``? {#tags} -Nem toda cadeia de caracteres é escrita na forma de texto puro. Há algumas cadeias de caracteres que consistem em cadeias de caracteres mistas como, por exemplo, as tags HTML (`<0>`, ``). Geralmente, elas são usadas para hiperlinks ou estilos alternativos no meio de uma frase. +Nem toda cadeia de caracteres é escrita na forma de texto puro. Existem algumas strings que consistem em scripts mistos, como tags HTML (`<0>`, ``). Isso geralmente é para hyperlinks ou estilo alternativo no meio de uma frase. -- Traduza o texto dentro das tags, mas não as tags em si. Nada entre `<` e `>` deve ser traduzido nem removido. +- Traduza o texto dentro das tags, mas não as tags em si. Qualquer coisa entre `<` e `>` não deve ser traduzida ou removida. - Para manter a string íntegra recomendamos que você clique no botão "Copiar origem" no canto inferior esquerdo. Isso vai copiar a string original e colá-la na caixa de texto. Isto permite que você ponha em evidência onde estão as tags e ajude a evitar erros. -![Interface Crowdin com o botão "copiar origem" destacado](./html-tag-strings.png) +![Interface do Crowdin com o botão de copiar origem destacado](./html-tag-strings.png) Você pode mover a posição das tags dentro da cadeia de caracteres para torná-la mais natural em seu idioma — apenas se certifique de mover a tag inteira. -Para mais informações aprofundadas sobre como lidar com tags e trechos de código, consulte o [Guia de estilo de tradução do ethereum.org](/contributing/translation-program/translators-guide/#dealing-with-tags). +Para obter informações mais detalhadas sobre como lidar com tags e trechos de código, consulte o [Guia de Estilo de Tradução do ethereum.org](/contributing/translation-program/translators-guide/#dealing-with-tags). ## Onde encontrar as cadeias de caracteres? {#strings} Geralmente, as cadeias de caracteres de origem podem não ser suficientes para que você forneça uma tradução exata. - Dê uma olhada em "capturas de tela" e "contexto" para obter mais informações. Na seção da string de origem, você verá a imagem de captura de tela anexada que mostrará como estamos usando a sequência de caracteres no contexto. -- Se você ainda não tiver certeza, coloque uma observação na "seção de comentários". [Em dúvida sobre como deixar um comentário?](#comment) +- Se você ainda não tiver certeza, coloque uma observação na "seção de comentários". [Não sabe como deixar um comentário?](#comment) -![Imagem mostrando como o contexto pode ser fornecido para uma cadeia de caracteres com uma captura de tela](./source-string.png) +![Mostrando como o contexto pode ser fornecido para uma string com uma captura de tela](./source-string.png) -![Exemplo de captura de tela adicionada para o contexto](./source-string-2.png) +![Um exemplo de captura de tela adicionada para contexto](./source-string-2.png) ## Como posso deixar comentários ou fazer perguntas? Gostaria de relatar um problema ou erro de digitação... {#comment} @@ -52,11 +52,11 @@ Se você quiser reportar um erro em uma determinada cadeia de caracteres que pre - Uma vez enviado, será reportado à nossa equipe. Vamos corrigir o problema e informar você respondendo ao seu comentário e encerrando a requisição. - Se você informar uma tradução incorreta, sua tradução e sugestão serão revisadas por um nativo na próxima revisão. -![Imagem mostrando como fazer comentários e relatar problemas](./comment-issue.png) +![Mostrando como fazer comentários e relatar problemas](./comment-issue.png) ## O que é Memória de Tradução (MT)? {#translation-memory} -Memória de Tradução (MT) é uma funcionalidade do Crowdin que armazena todas as frases traduzidas anteriormente no [ethereum.org](https://ethereum.org/). Quando uma cadeia de caracteres é traduzida, ela é automaticamente salva em nosso projeto de MT. Ela pode ser uma ferramenta útil para você economizar tempo! +Memória de Tradução (MT) é uma funcionalidade do Crowdin que armazena todas as frases traduzidas anteriormente no ethereum.org. Quando uma cadeia de caracteres é traduzida, ela é automaticamente salva em nosso projeto de MT. Ela pode ser uma ferramenta útil para você economizar tempo! - Veja na seção "Sugestões de MT " como outros tradutores traduziram a mesma string, ou similar. Se você encontrar uma sugestão com uma alta correspondência, sinta-se livre para se referir à tradução clicando nela. - Se não houver nada na lista, você poderá procurar na MT traduções feitas anteriormente e reutilizá-las para consistência. @@ -71,7 +71,7 @@ O glossário do Crowdin é o melhor lugar para esclarecer termos e definições. - Primeiro, quando você encontrar um termo sublinhado na string de origem, você pode passar o mouse por cima e ver uma breve definição dela. -![Um exemplo de definição do glossário](./glossary-definition.png) +![Uma definição de exemplo do glossário](./glossary-definition.png) - Segundo, se você ver um termo não familiar que não está sublinhado, você pode procurar na guia do glossário (o terceiro botão da coluna da direita). Você encontrará explicações de termos específicos e outros frequentemente utilizados no projeto. @@ -81,7 +81,7 @@ O glossário do Crowdin é o melhor lugar para esclarecer termos e definições. ![Uma captura de tela mostrando como adicionar um termo ao glossário do Crowdin](./add-glossary-term.png) -### Política de tradução de terminologias {#terminology} +### Política de tradução de terminologia {#terminology} _Para nomes (marcas, empresas, pessoas) e novos termos tecnológicos (Beacon Chain, cadeia de fragmentos, etc.)_ @@ -93,7 +93,7 @@ Após cuidadosa reflexão, tomamos a decisão de deixar para os tradutores a esc Quando você encontrar um termo que não é familiar para você, sugerimos o seguinte: -- Consulte o [Glossário de termos](#glossary), onde você pode ver como outros tradutores o traduziram anteriormente. Se você acha que o termo previamente traduzido não é apropriado, reverta a tradução adicionando um novo termo ao glossário do Crowdin. +- Consulte o [Glossário de termos](#glossary), você poderá encontrar como outros tradutores o traduziram anteriormente. Se você acha que o termo previamente traduzido não é apropriado, reverta a tradução adicionando um novo termo ao glossário do Crowdin. - Se tal tradução anterior não existir no Glossário, o encorajamos a procurá-lo em um mecanismo de busca ou artigo de mídia que mostre como o termo é realmente utilizado na sua comunidade. - Se você não encontrar nenhuma referência, sugira uma nova tradução para o seu idioma! - Se você se sentir menos confiante para fazê-lo, deixe o termo não traduzido. Às vezes, os termos em inglês são mais do que adequados para fornecer definições precisas. @@ -102,18 +102,18 @@ Recomendamos que deixe nomes de marcas, empresas e pessoas sem tradução, visto ## Como funciona o processo de revisão? {#review-process} -Para garantir um certo nível de qualidade e consistência nas nossas traduções, trabalhamos com a [Acolad](https://www.acolad.com/), uma das maiores empresas de serviços linguísticos no mundo. A Acolad conta com 20.000 linguistas profissionais, o que significa que ela pode fornecer revisores profissionais para cada idioma e tipo de conteúdo de que precisamos. +Para garantir um certo nível de qualidade e consistência em nossas traduções, trabalhamos com a [Acolad](https://www.acolad.com/), um dos maiores provedores de serviços linguísticos do mundo. A Acolad conta com 20.000 linguistas profissionais, o que significa que ela pode fornecer revisores profissionais para cada idioma e tipo de conteúdo de que precisamos. -O processo de revisão é simples: uma vez que um determinado [lote de conteúdo](/contributing/translation-program/) é 100% traduzido, pedimos uma revisão desse conteúdo. O processo de revisão ocorre diretamente no Crowdin. Uma vez que a revisão é concluída, atualizamos o site com o conteúdo traduzido. +O processo de revisão é simples; uma vez que um conjunto de conteúdo esteja 100% traduzido, solicitamos uma revisão para esse lote de conteúdo. O processo de revisão ocorre diretamente no Crowdin. Uma vez que a revisão é concluída, atualizamos o site com o conteúdo traduzido. ## Como faço para adicionar conteúdo no meu idioma? {#adding-foreign-language-content} Atualmente, todo o conteúdo que não está na língua inglesa é traduzido diretamente do conteúdo em inglês, e qualquer conteúdo que não esteja nesse idioma não pode ser adicionado a outros idiomas. -Para sugerir um novo conteúdo para o ethereum.org, é possível [criar um tíquete](https://github.com/ethereum/ethereum-org-website/issues) no GitHub. Se adicionado, o conteúdo será escrito em inglês e traduzido para outros idiomas usando o Crowdin. +Para sugerir novo conteúdo para o ethereum.org, você pode [criar um problema](https://github.com/ethereum/ethereum-org-website/issues) no GitHub. Se adicionado, o conteúdo será escrito em inglês e traduzido para outros idiomas usando o Crowdin. Planejamos adicionar suporte para adições de conteúdos que não estejam em inglês em um futuro próximo. -## Entre em contato conosco {#contact} +## Entre em contato {#contact} -Agradecemos por ter lido todas estas informações. Esperamos que elas tenham incentivado você a participar de nosso programa. Junte-se ao nosso [canal de tradução do Discord](https://discord.gg/ethereum-org) para fazer perguntas e colaborar com outros tradutores, ou envie um e-mail para translations@ethereum.org! +Agradecemos por ter lido todas estas informações. Esperamos que elas tenham incentivado você a participar de nosso programa. Sinta-se à vontade para entrar em nosso [canal de tradução do Discord](https://discord.gg/ethereum-org) para fazer perguntas e colaborar com outros tradutores, ou entre em contato conosco em translations@ethereum.org! diff --git a/public/content/translations/pt-br/contributing/translation-program/how-to-translate/index.md b/public/content/translations/pt-br/contributing/translation-program/how-to-translate/index.md index abc35e838aa..e9f9dbabfa0 100644 --- a/public/content/translations/pt-br/contributing/translation-program/how-to-translate/index.md +++ b/public/content/translations/pt-br/contributing/translation-program/how-to-translate/index.md @@ -1,7 +1,7 @@ --- title: Como traduzir lang: pt-br -description: Instruções de uso do Crowdin para traduzir o ethereum.org +description: "Instruções de uso do Crowdin para traduzir o ethereum.org" --- # Como traduzir {#how-to-translate} @@ -22,9 +22,10 @@ Você precisará fazer login na sua conta do Crowdin ou criar uma conta, caso ai Junte-se ao projeto -### Selecione seu idioma {#open-language} +### Abra seu idioma {#open-language} -Depois de fazer login no Crowdin, você verá uma descrição do projeto e uma lista de todos os idiomas disponíveis. Cada idioma também contém informações sobre a quantidade total de palavras traduzíveis e uma visão geral de quanto conteúdo foi traduzido e aprovado em um idioma específico. +Depois de fazer login no Crowdin, você verá uma descrição do projeto e uma lista de todos os idiomas disponíveis. +Cada idioma também contém informações sobre a quantidade total de palavras traduzíveis e uma visão geral de quanto conteúdo foi traduzido e aprovado em um idioma específico. Escolha o idioma para o qual deseja traduzir para ver a lista de arquivos disponíveis para tradução. @@ -34,16 +35,14 @@ Escolha o idioma para o qual deseja traduzir para ver a lista de arquivos dispon O conteúdo do site é dividido em vários documentos e grupos de conteúdo. Você pode verificar o progresso de cada documento à direita. Se o progresso da tradução estiver abaixo de 100%, contribua! -Não vê seu idioma na lista? [Abra um tíquete](https://github.com/ethereum/ethereum-org-website/issues/new/choose) ou faça uma pergunta no [Discord](https://discord.gg/ethereum-org) +Não vê seu idioma na lista? [Abra uma issue](https://github.com/ethereum/ethereum-org-website/issues/new/choose) ou pergunte em nosso [Discord](https://discord.gg/ethereum-org) ![Arquivos traduzidos e não traduzidos no Crowdin](./crowdin-files.png) -Uma nota sobre recipientes de conteúdo: utilizamos “recipientes de conteúdos” dentro do Crowdin para ter o conteúdo de prioridade mais alta lançado primeiro. Ao verificar um idioma, por exemplo, [Filipino](https://crowdin.com/project/ethereum-org/fil#) você verá pastas por categoria de conteúdo (“1. Página inicial", "2. Essenciais", "3. Explorando”, etc.). +Uma nota sobre recipientes de conteúdo: utilizamos “recipientes de conteúdos” dentro do Crowdin para ter o conteúdo de prioridade mais alta lançado primeiro. Quando você confere um idioma, por exemplo, [Filipino](https://crowdin.com/project/ethereum-org/fil#), você verá pastas para a categoria de conteúdo ("1. Página inicial", "2. Essenciais", "3. Explorando”, etc.). Recomendamos que você traduza nesta ordem numérica (1 → 2 → 3 → ⋯) para assegurar que as páginas de maior impacto sejam traduzidas primeiro. -[Saiba mais sobre os recipientes de conteúdo do ethereum.org](/contributing/translation-program/) - ### Traduzir {#translate} Após selecionar o arquivo que você deseja traduzir, ele será aberto no editor online. Se você nunca usou o Crowdin antes, você pode usar este guia rápido para conferir as noções básicas. @@ -60,7 +59,8 @@ Você também pode usar os botões no topo para pesquisar segmentos específicos **_2 – Área do editor_** -A área de tradução principal — o texto de origem é exibido no topo, com contexto adicional e capturas de tela, se disponíveis. Para sugerir uma nova tradução, insira sua sugestão no campo “Insira sua tradução aqui” e clique em Salvar. +A área de tradução principal — o texto de origem é exibido no topo, com contexto adicional e capturas de tela, se disponíveis. +Para sugerir uma nova tradução, insira sua sugestão no campo “Insira sua tradução aqui” e clique em Salvar. Você também pode encontrar traduções existentes do texto e traduções para outros idiomas nesta seção, além das correspondências de memória de tradução e sugestões de tradução automática. @@ -70,11 +70,11 @@ Aqui você pode encontrar comentários, assim como entradas da memória de tradu Usando os botões na parte superior, você também pode alternar para a memória de tradução, na qual você pode procurar traduções existentes, ou para o Glossário, que contém descrições e traduções padrão de termos-chave. -Quer saber mais? Confira a [documentação sobre como usar o editor online do Crowdin](https://support.crowdin.com/online-editor/) +Quer saber mais? Sinta-se à vontade para conferir a [documentação sobre como usar o editor online do Crowdin](https://support.crowdin.com/online-editor/) ### Processo de revisão {#review-process} -Quando tiver concluído a tradução (ou seja, todos os arquivos de um grupo de conteúdo que exibem 100%), nosso serviço de tradução profissional revisará (e possivelmente editará) o conteúdo. Assim que a revisão estiver completa (ou seja, o progresso de revisão atingir 100%), o adicionaremos ao site. +Quando tiver concluído a tradução (ou seja, todos os arquivos para uma categoria de conteúdo exibirem 100%), nosso serviço de tradução profissional revisará (e potencialmente editará) o conteúdo. Assim que a revisão estiver completa (ou seja, o progresso da revisão atingir 100%), nós o adicionaremos ao site. @@ -83,9 +83,9 @@ Quando tiver concluído a tradução (ou seja, todos os arquivos de um grupo de -### Entre em contato conosco {#get-in-touch} +### Entre em contato {#get-in-touch} -Você tem alguma dúvida? Ou quer colaborar com nossa equipe e outros tradutores? Publique no canal #translations do nosso [servidor Discord no ethereum.org](https://discord.gg/ethereum-org) +Você tem alguma dúvida? Ou quer colaborar com nossa equipe e outros tradutores? Publique no canal #translations do nosso [servidor do Discord do ethereum.org](https://discord.gg/ethereum-org) Você também pode entrar em contato conosco por meio do e-mail translations@ethereum.org diff --git a/public/content/translations/pt-br/contributing/translation-program/index.md b/public/content/translations/pt-br/contributing/translation-program/index.md index e7c10227529..fce4f682050 100644 --- a/public/content/translations/pt-br/contributing/translation-program/index.md +++ b/public/content/translations/pt-br/contributing/translation-program/index.md @@ -1,10 +1,10 @@ --- -title: Programa de tradução +title: "Programa de tradução" lang: pt-br -description: Informações sobre o Programa de Tradução do ethereum.org +description: "Informações sobre o Programa de Tradução do ethereum.org" --- -# Programa de tradução {#translation-program} +# Programa de Tradução {#translation-program} O Programa de tradução é um esforço colaborativo para traduzir ethereum.org em diferentes idiomas para tornar o site mais acessível a bilhões de falantes não ingleses em todo o mundo. @@ -16,11 +16,11 @@ O Programa de Tradução do ethereum.org está aberto e qualquer um pode contrib 1. Você precisará entrar na sua conta do Crowdin ou se inscrever. 2. Selecione o idioma para o qual você deseja contribuir. -3. Antes de começar, confira o guia [Como traduzir](/contributing/translation-program/how-to-translate/) para aprender como usar o Crowdin, e o [Guia de Estilo de Tradução](/contributing/translation-program/translators-guide/) para dicas e melhores práticas. +3. Antes de começar, consulte o guia [Como traduzir](/contributing/translation-program/how-to-translate/) para aprender a usar o Crowdin e o [Guia de Estilo de Tradução](/contributing/translation-program/translators-guide/) para dicas e melhores práticas. 4. As traduções automáticas não serão aprovadas. 5. Todas as traduções são revisadas antes de serem adicionadas ao site, por isso, haverá um pequeno atraso antes que suas traduções sejam publicadas. -_Junte-se ao [ethereum.org Discord](https://discord.gg/ethereum-org) para colaborar com traduções, fazer perguntas, compartilhar comentários e ideias ou juntar-se a um grupo de tradução._ +_Junte-se ao [Discord do ethereum.org](https://discord.gg/ethereum-org) para colaborar em traduções, fazer perguntas, compartilhar feedback e ideias ou participar de um grupo de tradução._ Comece a traduzir @@ -36,31 +36,32 @@ Leia mais sobre a [missão e visão](/contributing/translation-program/mission-a ### Nosso progresso até agora {#our-progress} -- [**Mais de 6.000**tradutores](/contributing/translation-program/contributors/) -- **62** idiomas presentes no site -- [**3 milhões** de palavras traduzidas em 2023](/contributing/translation-program/acknowledgements/) +- [**Mais de 6.900** tradutores](/contributing/translation-program/contributors/) +- **68** idiomas disponíveis no site +- [**2,89 milhões** de palavras traduzidas em 2024](/contributing/translation-program/acknowledgements/) ### Agradecimentos {#acknowledgements} -O Ethereum.org é traduzido por milhares de membros da comunidade e eles são a peça chave do Programa de Tradução. Queremos agradecer nossos tradutores e apoiá-los em seu percurso profissional. Aqui estão alguns de nossos agradecimentos aos tradutores: +O Ethereum.org é traduzido por milhares de membros da comunidade e eles são a peça chave do Programa de Tradução. +Queremos agradecer nossos tradutores e apoiá-los em seu percurso profissional. Aqui estão alguns de nossos agradecimentos aos tradutores: #### Certificado {#certificate} -Se você contribuiu para o Programa de Tradução e teve, pelo menos, 5.000 palavras traduzidas aprovadas, você pode receber um certificado de tradutor do ethereum.org. [Saiba mais sobre os certificados](/contributing/translation-program/acknowledgements/#certificate) +Se você contribuiu para o Programa de Tradução e teve, pelo menos, 5.000 palavras traduzidas aprovadas, você pode receber um certificado de tradutor do ethereum.org. [Mais sobre certificados](/contributing/translation-program/acknowledgements/#certificate) -#### OATs (tokens de conquista on-chain) {#oats} +#### OATs {#oats} Os contribuidores do Programa de Tradução são elegíveis para diferentes OATs (tokens de conquista on-chain) com base no número de palavras traduzidas em 2024. OATs são NFTs que comprovam sua contribuição ao Programa de Tradução do ethereum.org. [Mais sobre OATs](/contributing/translation-program/acknowledgements/#oats) #### Agradecimentos aos tradutores {#translator-acknowledgements} -Agradecimentos públicos aos nossos principais tradutores por meio de [tabelas de classificação](/contributing/translation-program/acknowledgements/) e uma [lista de todos os colaboradores do Programa de Tradução](/contributing/translation-program/contributors/). +Agradecimentos públicos aos nossos principais tradutores por meio de [placar de líderes](/contributing/translation-program/acknowledgements/) e uma [lista de todos os contribuidores do Programa de Tradução](/contributing/translation-program/contributors/). #### Recompensas {#rewards} -No passado, recompensamos retroativamente nossos colaboradores mais ativos com ingressos para conferências do Ethereum como a [Devcon](https://devcon.org/en/) e a [Devconnect](https://devconnect.org/), assim como com produtos exclusivos do ethereum.org. +No passado, recompensamos retroativamente nossos contribuidores mais ativos com ingressos para conferências da Ethereum, como a [Devcon](https://devcon.org/en/) e a [Devconnect](https://devconnect.org/), bem como produtos exclusivos do ethereum.org. Estamos constantemente pensando em maneiras novas e inovadoras de recompensar nossos colaboradores, então fique ligado! @@ -68,23 +69,23 @@ Estamos constantemente pensando em maneiras novas e inovadoras de recompensar no Se você está contribuindo para o Programa de Tradução ou pensando em se envolver com ele, confira os guias de tradução abaixo: -- [Guia de Estilo de Tradução](/contributing/translation-program/translators-guide/) _ — instruções e dicas para tradutores do ethereum.org_ -- [Perguntas frequentes sobre tradução](/contributing/translation-program/faq/) _ — perguntas frequentes e respostas sobre o Programa de Tradução do ethereum.org_ -- [Guia do editor online do Crowdin](https://support.crowdin.com/online-editor/) _ — um guia detalhado sobre como usar o editor online do Crowdin e algumas funcionalidades avançadas do Crowdin_ -- [Pacotes de conteúdo](/contributing/translation-program/) _ — quais páginas estão incluídas em cada pacote de conteúdo do ethereum.org_ +- [Guia de Estilo de Tradução](/contributing/translation-program/translators-guide/) _– instruções e dicas para tradutores do ethereum.org_ +- [Perguntas frequentes sobre tradução](/contributing/translation-program/faq/) _– perguntas e respostas frequentes sobre o Programa de Tradução do ethereum.org_ +- [Guia do editor on-line do Crowdin](https://support.crowdin.com/online-editor/) _– um guia detalhado sobre como usar o editor on-line do Crowdin e alguns dos recursos avançados do Crowdin_ -Para outras ferramentas úteis de tradução, comunidades de tradutores e postagens no blog do Programa de Tradução, visite a [Página de recursos](/contribuindo/tradução-programa/recursos/). +Para outras ferramentas de tradução úteis, comunidades de tradutores e posts de blog do Programa de Tradução, visite a [página de Recursos](/contributing/translation-program/resources/). -## Envolva-se {#get-in-touch} +## Entre em contato {#get-in-touch} -Você tem alguma dúvida? Ou quer colaborar com nossa equipe e outros tradutores? Publique no canal #translations do nosso [servidor Discord no ethereum.org](https://discord.gg/ethereum-org) +Você tem alguma dúvida? Ou quer colaborar com nossa equipe e outros tradutores? Publique no canal #translations do nosso [servidor do Discord do ethereum.org](https://discord.gg/ethereum-org) Você também pode entrar em contato conosco por meio do e-mail translations@ethereum.org -## Iniciando o seu próprio programa de tradução {#starting-a-translation-program} +## Iniciando seu próprio programa de tradução {#starting-a-translation-program} -Estamos empenhados em traduzir o conteúdo do Ethereum para o maior número possível de idiomas e tornar o conteúdo educacional disponível a todos. Em sintonia com a importância que damos às traduções, queremos ajudar outros projetos do Ethereum a organizar, gerenciar e melhorar suas próprias iniciativas de tradução. +Estamos empenhados em traduzir o conteúdo do Ethereum para o maior número possível de idiomas e tornar o conteúdo educacional disponível a todos. +Em sintonia com a importância que damos às traduções, queremos ajudar outros projetos do Ethereum a organizar, gerenciar e melhorar suas próprias iniciativas de tradução. -Por esta razão, criamos um [Manual do Programa de Tradução](/contributing/translation-program/playbook/), que contém algumas dicas e práticas recomendadas que coletamos no processo de tradução do ethereum.org. +Por esse motivo, criamos um [manual do Programa de Tradução](/contributing/translation-program/playbook/) que contém algumas dicas e melhores práticas que aprendemos no processo de tradução do ethereum.org. Quer colaborar mais ou usar alguns dos nossos recursos de tradução? Tem algum comentário sobre o manual? Envie-nos uma mensagem em translations@ethereum.org. diff --git a/public/content/translations/pt-br/contributing/translation-program/mission-and-vision/index.md b/public/content/translations/pt-br/contributing/translation-program/mission-and-vision/index.md index 08a5a2fb95a..3261f124019 100644 --- a/public/content/translations/pt-br/contributing/translation-program/mission-and-vision/index.md +++ b/public/content/translations/pt-br/contributing/translation-program/mission-and-vision/index.md @@ -1,7 +1,7 @@ --- -title: Missão e visão +title: "Missão e visão" lang: pt-br -description: A missão e visão do Programa de Tradução do ethereum.org +description: "A missão e visão do Programa de Tradução do ethereum.org" --- # Missão e visão {#mission-and-vision} diff --git a/public/content/translations/pt-br/contributing/translation-program/playbook/index.md b/public/content/translations/pt-br/contributing/translation-program/playbook/index.md new file mode 100644 index 00000000000..a14183c884a --- /dev/null +++ b/public/content/translations/pt-br/contributing/translation-program/playbook/index.md @@ -0,0 +1,317 @@ +--- +title: "Manual do programa de tradução" +lang: pt-br +description: "Uma coleção de dicas e considerações importantes para a criação de um programa de tradução" +--- + +# Manual do Programa de Tradução {#translation-program-playbook} + +O inglês é uma das línguas mais faladas no mundo e, de longe, a língua mais estudada do mundo. Como o inglês é o idioma mais comum usado na internet — especialmente nas mídias sociais — e as linguagens de programação multilíngues são escassas, a maior parte do conteúdo no espaço blockchain é escrito nativamente em inglês. + +No entanto, como mais de 6 bilhões de pessoas no mundo (mais de 75% da população) não falam inglês, isso representa uma barreira enorme para a entrada no Ethereum para a grande maioria da população mundial. + +Por esse motivo, um número crescente de projetos nesse setor busca traduzir seu conteúdo para diferentes idiomas e localizá-lo para comunidades globais. + +Fornecer conteúdo multilíngue é uma maneira simples e eficaz de expandir sua comunidade global, fornecer educação a pessoas que não falam inglês, garantir que seu conteúdo e comunicações alcancem um público maior e atrair mais pessoas para o espaço. + +Este guia tem como objetivo abordar os desafios e equívocos comuns sobre localização de conteúdo. Ele fornece um guia passo a passo para gerenciar conteúdo, o processo de tradução e revisão, garantia de qualidade, alcance do tradutor e outros aspectos vitais do processo de localização. + +## Gerenciamento de conteúdo {#content-management} + +O gerenciamento de conteúdo de tradução refere-se ao processo de automatização do fluxo de trabalho de tradução, o que elimina a necessidade de trabalho manual repetitivo, melhora a eficiência e a qualidade, permite melhor controle e possibilita a colaboração. + +Existem muitas abordagens diferentes para o gerenciamento de conteúdo no processo de localização, dependendo do conteúdo e das suas necessidades. + +A maneira fundamental de gerenciar conteúdo é criar arquivos bilíngues, contendo o texto de origem e de destino. Isso é raramente usado em tradução, pois não oferece vantagens significativas, além da simplicidade. + +As agências de tradução geralmente abordam o gerenciamento usando softwares de tradução ou ferramentas de localização, que fornecem recursos para os projetos e permitem um controle muito maior sobre os arquivos, o conteúdo e os linguistas. + +Saiba mais sobre gerenciamento de conteúdo: + +[Trados sobre o que é gestão de tradução](https://www.trados.com/solutions/translation-management/) + +[Frase sobre gerenciamento de conteúdo multilíngue](https://phrase.com/blog/posts/multilingual-content-management/) + +### Software de gerenciamento de tradução {#translation-management-software} + +Existem muitos sistemas de gerenciamento de tradução e ferramentas de localização, e a escolha do software depende principalmente de suas necessidades. + +Embora alguns projetos decidam não usar sistemas de gerenciamento de tradução e prefiram lidar com as traduções manualmente — seja diretamente em arquivos bilíngues ou em serviços de hospedagem, como o GitHub — isso reduz drasticamente o controle, a produtividade, a qualidade, a escalabilidade e os recursos de colaboração. Essa abordagem pode ser mais benéfica para projetos de tradução de pequena escala ou pontuais. + +Uma rápida olhada em algumas das ferramentas de gerenciamento de tradução mais poderosas e amplamente utilizadas: + +**Melhor para crowdsourcing e colaboração** + +[Crowdin](https://crowdin.com/) + +- Gratuito para projetos de código aberto (número ilimitado de strings e projetos) +- TM e glossário disponíveis com todos os planos +- Mais de 60 formatos de arquivo suportados, mais de 70 integrações de API + +[Lokalise](https://lokalise.com/) + +- Grátis para 2 membros da equipe, planos pagos para mais colaboradores (número limitado de strings para a maioria dos planos) +- TM e glossário disponíveis com alguns planos pagos +- Mais de 30 formatos de arquivo suportados, mais de 40 integrações de API + +[Transifex](https://www.transifex.com/) + +- Somente planos pagos (número limitado de sequências para a maioria dos planos) +- TM e glossário disponíveis em todos os planos pagos +- Mais de 30 formatos de arquivo suportados, mais de 20 integrações de API + +[Phrase](https://phrase.com/) + +- Somente planos pagos (número ilimitado de strings para todos os planos, número limitado de projetos e membros da equipe) +- TM e glossário disponíveis com alguns planos pagos +- Mais de 40 formatos de arquivo suportados, mais de 20 integrações de API + +[Smartcat](https://www.smartcat.com/) + +- Plano básico gratuito com recursos avançados pagos (número ilimitado de strings e projetos para todos os planos) +- TM e glossário disponíveis com todos os planos +- Mais de 60 formatos de arquivo suportados, mais de 20 integrações de API + +[POEditor](https://poeditor.com/) + +- Gratuito para projetos de código aberto (número limitado de strings para todos os projetos, ilimitado para projetos de código aberto) +- TM e glossário disponíveis para planos pagos +- Mais de 20 formatos de arquivo suportados, mais de 10 integrações de API + +e muitos outros... + +**Ferramentas de tradução profissionais** + +[SDL Trados Studio](https://www.trados.com/products/trados-studio/) + +- Planos pagos para tradutores e equipes freelancers +- Ferramenta de tradução assistida por computador (CAT) muito poderosa e software de produtividade para tradutores + +[MemoQ](https://www.memoq.com/) + +- Versão gratuita limitada disponível com vários planos pagos para recursos avançados +- Software de gestão de tradução para empresas, prestadores de serviços de idiomas e tradutores + +[Memsource](https://www.memsource.com/) + +- Gratuito para tradutores individuais com vários planos pagos para equipes +- Sistema de tradução e gestão de tradução assistido por computador baseado em nuvem + +e muitos outros... + +Saiba mais sobre software de gerenciamento de tradução: + +[Definição da Wikipédia de sistemas de gestão de tradução](https://en.wikipedia.org/wiki/Translation_management_system) + +[Frase sobre 7 coisas que todo software de gerenciamento de tradução deveria ter](https://phrase.com/blog/posts/7-things-every-translation-management-software-should-have/) + +[MemoQ sobre o que é um sistema de gerenciamento de tradução](https://www.memoq.com/tools/what-is-a-translation-management-system) + +[Lista da Gengo dos 16 melhores sistemas de gestão de tradução](https://gengo.com/translator-product-updates/16-best-translation-management-systems/) + +## Workflow {#workflow} + +No mundo da tradução, o fluxo de trabalho da tradução pode significar algumas coisas diferentes, ambas de certa forma inter-relacionadas e considerações importantes para o seu projeto. + +Exploraremos ambos abaixo. + +**Significado 1** + +Esta é provavelmente a maneira mais comum de pensar sobre fluxos de trabalho de tradução e algo que geralmente vem à mente quando ouço a palavra fluxo de trabalho. + +Em essência, é o “fluxo de trabalho” desde o início da reflexão sobre as traduções até a utilização do conteúdo traduzido no seu produto. + +Um exemplo de workflow neste caso seria: + +1. **Preparando os arquivos para tradução** – Parece simples; no entanto, você precisa considerar algumas coisas importantes. Nesta etapa, você deve ter um plano claro de como todo o processo deve funcionar. + +- Quais tipos de arquivo você usará? Em qual formato você deseja receber seus arquivos traduzidos?_ + - Se o seu conteúdo estiver disponível em formato DOCX ou MD, a abordagem será muito mais direta do que se você estivesse traduzindo uma versão em PDF do seu Whitepaper ou de outros documentos. +- _Quais ferramentas de localização suportam esse tipo de arquivo? O arquivo pode ser traduzido para manter a formatação original?_ + - Nem todos os tipos de arquivo suportam localização direta (por exemplo, arquivos PDF, arquivos de imagem), e nem todas as ferramentas de localização suportam todos os tipos de arquivo. +- _Quem traduzirá o conteúdo? Você solicitará traduções profissionais ou dependerá de voluntários?_ + - Isso afeta uma série de outras decisões que você precisa tomar. Por exemplo, tradutores profissionais se sentem mais confortáveis ​​trabalhando com ferramentas avançadas de localização do que voluntários. +- Quais são suas expectativas para os linguistas? Se você estiver usando um provedor de serviços de idiomas, o que eles esperam de você?_ + - Esta é a etapa para garantir que seus objetivos, expectativas e cronogramas estejam alinhados. +- _Todo o conteúdo para tradução é igualmente importante? Algum conteúdo deve ser traduzido primeiro?_ + - Existem algumas maneiras de priorizar determinado conteúdo, que deve ser traduzido e implementado primeiro. Por exemplo, se você tem muito conteúdo para traduzir, pode usar o controle de versão para garantir que os tradutores saibam o que devem priorizar. + +2. **Compartilhamento dos arquivos para tradução** – Esta etapa também requer algum pensamento de longo prazo e não é tão simples quanto enviar os arquivos de origem para um provedor de serviços de idiomas. + +- _Quem traduzirá o conteúdo? Quantas pessoas estarão envolvidas neste processo?_ + - Se você planeja usar uma ferramenta de localização, esta etapa é simplificada, pois você pode carregar os arquivos de origem diretamente na ferramenta. Isso também é verdade se o processo de tradução ocorrer no serviço de hospedagem, já que os arquivos de origem não precisam ser exportados para lugar nenhum. +- _Os arquivos de origem serão manipulados manualmente ou esse processo pode ser automatizado?_ + - A maioria das ferramentas de localização permite algum tipo de integração ou automação do processo de gerenciamento de arquivos. Por outro lado, se você estiver trabalhando com tradutores individuais e não estiver usando uma ferramenta de localização, enviar manualmente os arquivos de origem para centenas ou milhares de tradutores não é um processo escalável. +- _Quais ferramentas serão usadas para a localização?_ + - A resposta a essa pergunta determinará como você abordará o resto. Selecionar a ferramenta adequada pode ajudar você a automatizar o gerenciamento de conteúdo, gerenciar a Memória de Tradução e o Glossário, gerenciar tradutores, acompanhar o progresso da tradução/revisão, etc., então reserve um tempo e pesquise qual ferramenta você deseja usar. Se você não planeja usar uma ferramenta de localização, tudo isso precisará ser feito manualmente. +- _Quanto tempo levará o processo de tradução? Quanto vai custar?_ + - Neste ponto, você deve estar pronto para compartilhar os arquivos de origem com o provedor de serviços de idiomas ou com o grupo de tradutores. O provedor de serviços de idiomas pode ajudar você a analisar a contagem de palavras e fornecer um orçamento, incluindo as taxas e o cronograma do processo de tradução. +- _Você está planejando fazer alterações/atualizar o conteúdo de origem durante esse processo?_ + - Se o seu conteúdo for dinâmico e mudar com frequência, quaisquer alterações ou atualizações podem atrapalhar o andamento da tradução. Usar uma memória de tradução pode ajudar a atenuar isso significativamente, embora ainda seja importante pensar em como o processo funcionará e como você pode evitar atrasos no progresso dos tradutores. + +3. **Gerenciando o processo de tradução** – Seu trabalho não termina quando o conteúdo de origem é entregue ao provedor de serviços de idioma ou aos tradutores. Para garantir a qualidade ideal das traduções, os criadores de conteúdo devem estar o mais envolvidos possível no processo de tradução. + +- _Como você planeja se comunicar com os tradutores?_ + - Se você planeja usar uma ferramenta de localização, a comunicação pode ocorrer diretamente na ferramenta. Também é recomendável criar um canal de comunicação alternativo com os tradutores, pois eles podem ficar menos hesitantes em entrar em contato, e as ferramentas de mensagens permitem uma comunicação mais fluida. +- _Como lidar com perguntas de tradutores? Quem deve responder a essas perguntas?_ + - Tradutores (profissionais e não profissionais) frequentemente entrarão em contato com perguntas e solicitações de esclarecimentos ou contexto adicional, bem como feedback e ideias para melhorias. Responder a essas perguntas geralmente pode levar a um melhor engajamento e qualidade do conteúdo traduzido. Também é valioso fornecer a eles o máximo de recursos possível (por exemplo, guias, dicas, diretrizes de terminologia, perguntas frequentes, etc.). +- _Como lidar com o processo de revisão? Você quer terceirizar ou tem capacidade de realizar revisões internamente?_ + - Embora nem sempre sejam necessárias, as revisões são parte integrante de um processo de tradução ideal. Normalmente, é mais fácil terceirizar o processo de revisão para revisores profissionais. No entanto, se você tiver uma grande equipe internacional, as revisões ou o controle de qualidade também podem ser feitos internamente. + +4. **Implementando o conteúdo traduzido** – A última parte do fluxo de trabalho, embora ainda seja importante considerar com antecedência. + +- _Todas as traduções serão concluídas ao mesmo tempo?_ + - Caso contrário, você deve pensar em quais traduções devem ser priorizadas, como acompanhar as que estão em andamento e como a implementação é tratada enquanto elas são feitas. +- _Como o conteúdo traduzido será entregue a você? Em que formato será?_ + - Esta é uma consideração importante, independentemente da abordagem que você usar. As ferramentas de localização permitem que você mantenha o controle sobre o formato do arquivo de destino e o processo de exportação e geralmente oferecem suporte à automação, por exemplo, permitindo a integração com o serviço de hospedagem. +- _Como você implementará as traduções no seu projeto?_ + - Em alguns casos, isso pode ser tão simples quanto enviar o arquivo traduzido ou adicioná-lo aos seus documentos. No entanto, em projetos mais complexos, como traduções de sites ou aplicativos, você deve garantir que o código suporte a internacionalização e estabelecer com antecedência como o processo de implementação será conduzido. +- _O que acontece se a formatação for diferente da fonte?_ + - Semelhante ao acima, se você estiver traduzindo arquivos de texto simples, a formatação provavelmente não será tão importante. No entanto, com arquivos mais complexos, como conteúdo para um site ou aplicativo, a formatação e o código precisam ser idênticos ao código-fonte para serem implementados no seu projeto. Caso contrário, os arquivos de destino precisarão ser editados, pelos tradutores ou pelos seus desenvolvedores. + +**Significado 2** + +Um fluxo de trabalho de tradução alternativo, que não considera decisões e abordagens internas. A principal consideração aqui é o fluxo do conteúdo em si. + +Um exemplo de workflow neste caso seria: + +1. _Tradução → Implementação_ + +- O fluxo de trabalho mais simples, onde a tradução provavelmente será feita por uma tradução humana, já que não há processo de revisão ou controle de qualidade para avaliar a qualidade e editar as traduções antes da implementação. +- Com esse fluxo de trabalho, é importante que os tradutores consigam manter um certo nível de qualidade, o que exigirá recursos adequados e comunicação entre os gerentes de projeto e os tradutores. + +2. _Tradução → Revisão → Implementação_ + +- Um fluxo de trabalho mais avançado, que inclui um processo de revisão e edição, para garantir que a qualidade das traduções seja aceitável e consistente. +- Há uma série de abordagens para esse fluxo de trabalho, onde as traduções podem ser realizadas por tradutores profissionais ou voluntários, enquanto o processo de revisão provavelmente será conduzido por revisores profissionais, que estão familiarizados com todas as regras gramaticais e ortográficas que precisam ser observadas no idioma de destino. + +3. _Tradução → Revisão → QA → Implementação_ + +- O fluxo de trabalho ideal para garantir o mais alto nível de qualidade. Embora o controle de qualidade nem sempre seja necessário, ele pode ser útil para lhe dar uma noção melhor da qualidade do texto traduzido após a tradução e a revisão. +- Com esse fluxo de trabalho, as traduções poderiam ser realizadas exclusivamente por voluntários ou até mesmo por tradução automática. O processo de revisão deve ser realizado por tradutores profissionais, enquanto o controle de qualidade pode ser realizado por um provedor de serviços de idiomas ou internamente, se você tiver funcionários que sejam falantes nativos dos idiomas de destino. + +Saiba mais sobre fluxos de trabalho de tradução: + +[Regras de conteúdo sobre as cinco fases do fluxo de trabalho de tradução](https://contentrules.com/creating-translation-workflow/) + +[Smartling sobre o que é gerenciamento de fluxo de trabalho de tradução](https://www.smartling.com/resources/101/what-is-translation-workflow-management/) + +[RixTrans sobre o fluxo de trabalho de tradução](https://www.rixtrans.com/translation-workflow) + +## Gestão de Terminologia {#terminology-management} + +Estabelecer um plano claro sobre como lidar com a terminologia é um dos passos mais importantes para garantir a qualidade e a consistência das suas traduções e economizar tempo dos seus tradutores. + +No setor de tradução, isso é conhecido como gerenciamento de terminologia e é um dos principais serviços que os provedores de serviços de idiomas oferecem aos seus clientes, além do acesso ao seu conjunto de linguistas e gerenciamento de conteúdo. + +Gerenciamento de terminologia se refere ao processo de identificar, reunir e gerenciar terminologia que é importante para seu projeto e deve sempre ser traduzida de forma correta e consistente. + +Há alguns passos a seguir ao começar a pensar sobre gerenciamento de terminologia: + +- Identifique os termos-chave que devem ser incluídos na base de termos. +- Crie um glossário de termos e suas definições. +- Traduza os termos e adicione-os ao glossário. +- Verifique e aprove as traduções. +- Mantenha o glossário e atualize-o com novos termos, à medida que se tornam importantes. + +Saiba mais sobre gerenciamento de terminologia: + +[Trados sobre o que é gerenciamento de terminologia](https://www.trados.com/solutions/terminology-management/translation-101-what-is-terminology-management.html) + +[Language Scientific sobre a importância da gestão de terminologia](https://www.languagescientific.com/terminology-management-why-it-matters/#:~:text=Terminology%20management%20is%20the%20process,are%20related%20to%20each%20other.) + +[Clear Words Translation sobre o que é gerenciamento de terminologia e por que isso é importante](http://clearwordstranslations.com/language/en/what-is-terminology-management/) + +### Memória de tradução e glossário {#tm-and-glossary} + +A Memória de Tradução e o Glossário são ferramentas importantes no setor de tradução e algo em que a maioria dos provedores de serviços de idiomas confia. + +Vamos ver o que esses termos significam e como eles são diferentes entre si: + +**Memória de tradução (TM)** – Um banco de dados que armazena automaticamente segmentos ou sequências de caracteres, incluindo blocos de texto mais longos, frases completas, parágrafos e termos individuais, bem como suas traduções atuais e anteriores em todos os idiomas. + +A maioria das ferramentas de localização, sistemas de gerenciamento de tradução e ferramentas de tradução assistida por computador têm memórias de tradução integradas, que geralmente podem ser exportadas e usadas em outras ferramentas semelhantes. + +Os benefícios de usar uma memória de tradução incluem traduções mais rápidas, melhor qualidade de tradução, a capacidade de reter determinadas traduções ao atualizar ou alterar o conteúdo de origem e custos de tradução mais baixos para conteúdo repetitivo. + +As memórias de tradução funcionam com base em uma porcentagem de correspondência entre diferentes segmentos e geralmente são mais úteis quando dois segmentos contêm mais de 50% do mesmo conteúdo. Eles também são usados ​​para traduzir automaticamente segmentos repetitivos, que são 100% correspondentes, eliminando assim a necessidade de traduzir conteúdo repetitivo mais de uma vez. + +Leia mais sobre memórias de tradução: + +[Memsource sobre memórias de tradução](https://www.memsource.com/translation-memory/) + +[Smartling sobre o que é uma memória de tradução](https://www.smartling.com/resources/101/what-is-translation-memory/) + +**Glossário –** Uma lista de termos importantes ou sensíveis, suas definições, funções e traduções estabelecidas. A principal diferença entre um glossário e uma memória de tradução é que um glossário não é criado automaticamente e não contém traduções de frases completas. + +A maioria das ferramentas de localização, sistemas de gerenciamento de tradução e ferramentas de tradução assistida por computador têm glossários integrados que você pode manter para garantir que contenham terminologia importante para seu projeto. Assim como a TM, o glossário geralmente pode ser exportado e usado em outras ferramentas de localização. + +Antes de começar seu projeto de tradução, é altamente recomendável reservar um tempo para criar um glossário para seus tradutores e revisores. Usar um glossário garante que termos importantes sejam traduzidos corretamente, fornece aos tradutores o contexto necessário e garante consistência nas traduções. + +Embora os glossários geralmente contenham traduções estabelecidas nos idiomas de destino, eles também são úteis sem elas. Mesmo sem traduções estabelecidas, um glossário pode ter definições de termos técnicos, destacar termos que não devem ser traduzidos e informar aos tradutores se um termo específico é usado como substantivo, verbo, nome próprio ou qualquer outra parte do discurso. + +Saiba mais sobre glossários: + +[Lionbridge sobre o que é um glossário de tradução](http://info.lionbridge.com/rs/lionbridge/images/Lionbridge%20FAQ_Glossary_2013.pdf) + +[Transifex sobre glossários](https://docs.transifex.com/glossary/glossary) + +Se você não estiver planejando usar uma ferramenta de localização para seu projeto, provavelmente não poderá usar uma memória de tradução e um glossário (você pode criar um glossário ou base de termos em um arquivo Excel; no entanto, os glossários automatizados eliminam a necessidade de os tradutores procurarem manualmente os termos e suas definições). + +Isso significa que todo conteúdo repetitivo e semelhante teria que ser traduzido manualmente todas as vezes. Além disso, os tradutores teriam que entrar em contato com perguntas sobre se um determinado termo precisa ser traduzido ou não, como ele é usado no texto e se um termo já tem uma tradução estabelecida. + +_Você quer usar a memória de tradução e o glossário do ethereum.org no seu projeto? Entre em contato conosco pelo e-mail translations@ethereum.org._ + +## Divulgação do tradutor {#translator-outreach} + +**Trabalhando com um provedor de serviços de idiomas** + +Se você estiver trabalhando com um provedor de serviços de idiomas e seus tradutores profissionais, esta seção pode não ser muito relevante para você. + +Nesse caso, é importante selecionar um provedor de serviços de idiomas com capacidade para fornecer todos os serviços que você precisa (por exemplo, tradução, revisão, controle de qualidade) em vários idiomas. + +Embora possa ser tentador selecionar um provedor de serviços de idiomas apenas com base nas taxas oferecidas, é importante observar que os maiores provedores de serviços de idiomas têm taxas mais altas por um motivo. + +- Eles têm dezenas de milhares de linguistas em seu banco de dados, o que significa que poderão designar tradutores com experiência e conhecimento suficientes do seu setor específico para o seu projeto (por exemplo, tradutores técnicos). +- Eles têm experiência significativa trabalhando em diferentes projetos e atendendo às diversas necessidades de seus clientes. Isso significa que eles estarão mais propensos a se adaptar ao seu fluxo de trabalho específico, oferecer sugestões valiosas e possíveis melhorias para seu processo de tradução e atender às suas necessidades, requisitos e prazos. +- A maioria dos grandes provedores de serviços de idiomas também tem suas próprias ferramentas de localização, memórias de tradução e glossários que você pode usar. Caso contrário, eles pelo menos têm linguistas suficientes em seu grupo para garantir que seus tradutores estejam familiarizados e consigam trabalhar com qualquer ferramenta de localização que você queira usar. + +Você pode encontrar uma comparação detalhada dos maiores provedores de serviços de idiomas do mundo, alguns detalhes sobre cada um deles e detalhamentos pelos serviços que eles fornecem, dados geográficos, etc. no [relatório Nimdzi 100 de 2021](https://www.nimdzi.com/nimdzi-100-top-lsp/). + +**Trabalhando com tradutores não profissionais** + +Você pode estar trabalhando com tradutores não profissionais e procurando voluntários para ajudá-lo a traduzir. + +Existem várias maneiras de alcançar pessoas e convidá-las a participar do seu projeto. Isso dependerá muito do seu produto e do tamanho da comunidade que você já tem. + +Algumas maneiras de integrar voluntários são descritas abaixo: + +**Divulgação –** Embora isso seja parcialmente abordado nos pontos abaixo, entrar em contato com potenciais voluntários e garantir que eles estejam cientes da sua iniciativa de tradução pode ser eficaz por si só. + +Muitas pessoas querem se envolver e contribuir com seus projetos favoritos, mas geralmente não veem uma maneira clara de fazer isso sem ser um desenvolvedor ou ter habilidades técnicas especiais. Se você puder divulgar seu projeto, muitos bilíngues provavelmente ficarão interessados ​​em se envolver. + +**Olhando para dentro da sua comunidade –** A maioria dos projetos nesse espaço já conta com comunidades grandes e ativas. Muitos membros da sua comunidade provavelmente apreciariam a oportunidade de contribuir com o projeto de uma forma simples. + +Embora contribuir para projetos de código aberto geralmente se baseie na motivação intrínseca, também é uma experiência de aprendizado fantástica. Qualquer pessoa interessada em aprender mais sobre seu projeto provavelmente ficaria feliz em se envolver em um programa de tradução como voluntário, pois isso lhe permitiria combinar o fato de ter contribuído para algo que lhe interessa com uma experiência intensiva de aprendizado prático. + +**Mencione a iniciativa em seu produto –** Se seu produto for popular e usado por um grande número de pessoas, destacar seu programa de tradução e chamar os usuários para ação enquanto usam o produto pode ser extremamente eficaz. + +Isso pode ser tão simples quanto adicionar um banner ou pop-up com um CTA ao seu produto para aplicativos e sites. Isso é eficaz porque seu público-alvo é sua comunidade — as pessoas que têm maior probabilidade de se envolver em primeiro lugar. + +**Mídias sociais –** As mídias sociais podem ser uma forma eficaz de divulgar seu programa de tradução e alcançar os membros da sua comunidade, bem como outras pessoas que ainda não são membros da sua comunidade. + +Se você tem um servidor Discord ou um canal do Telegram, é fácil usá-lo para divulgação, comunicação com seus tradutores e reconhecimento de seus colaboradores. + +Plataformas como o X (antigo Twitter) também podem ser úteis para integrar novos membros da comunidade e reconhecer publicamente seus contribuidores. + +A Linux Foundation criou um extenso [Relatório sobre a pesquisa de contribuidores FOSS de 2020](https://www.linuxfoundation.org/wp-content/uploads/2020FOSSContributorSurveyReport_121020.pdf), analisando os contribuidores de código aberto e suas motivações. + +## Conclusão {#conclusion} + +Este documento contém algumas considerações importantes que todo programa de tradução deve saber. Não é de forma alguma um guia exaustivo, embora possa ajudar qualquer pessoa sem experiência no setor de tradução a organizar um programa de tradução para seu projeto. + +Se você estiver procurando por instruções mais detalhadas e análises de diferentes ferramentas, processos e aspectos críticos do gerenciamento de um programa de tradução, alguns dos maiores provedores de serviços de idiomas mantêm blogs e frequentemente publicam artigos sobre diferentes aspectos do processo de localização. Estes são os melhores recursos se você quiser se aprofundar em qualquer um dos tópicos acima e entender como o processo de localização funciona profissionalmente. + +Alguns links relevantes estão incluídos no final de cada seção; no entanto, você pode encontrar muitos outros recursos online. + +Para propostas de cooperação ou informações adicionais, aprendizados e melhores práticas que adquirimos ao manter o Programa de Tradução do ethereum.org, sinta-se à vontade para entrar em contato conosco pelo e-mail translations@ethereum.org. diff --git a/public/content/translations/pt-br/contributing/translation-program/resources/index.md b/public/content/translations/pt-br/contributing/translation-program/resources/index.md index d19b83b2b26..074bc7f78ec 100644 --- a/public/content/translations/pt-br/contributing/translation-program/resources/index.md +++ b/public/content/translations/pt-br/contributing/translation-program/resources/index.md @@ -1,44 +1,49 @@ --- title: Recursos para tradutores lang: pt-br -description: Recursos úteis para tradutores do ethereum.org +description: "Recursos úteis para tradutores do ethereum.org" --- -# Recursos {#resources} +# Documentos {#resources} Você pode encontrar alguns guias e ferramentas úteis para tradutores do ethereum.org, bem como comunidades de tradução e atualizações abaixo. ## Guias {#guides} -- [Guia de estilo de tradução](/contributing/translation-program/translators-guide/) _: instruções e dicas para tradutores do ethereum.org_ -- [Perguntas frequentes sobre tradução](/contributing/translation-program/faq/) _ — perguntas frequentes e respostas sobre o Programa de Tradução do ethereum.org_ -- [Guia do editor online do Crowdin](https://support.crowdin.com/online-editor/) _ — um guia detalhado sobre como usar o editor online do Crowdin e algumas funcionalidades avançadas do Crowdin_ -- [Pacotes de conteúdo](/contributing/translation-program/) _ — quais páginas estão incluídas em cada pacote de conteúdo do ethereum.org_ +- [Guia de estilo de tradução](/contributing/translation-program/translators-guide/) _– instruções e dicas para tradutores do ethereum.org_ +- [Perguntas frequentes sobre tradução](/contributing/translation-program/faq/) _– perguntas e respostas frequentes sobre o Programa de Tradução do ethereum.org_ +- [Guia do editor on-line do Crowdin](https://support.crowdin.com/online-editor/) _– um guia detalhado sobre como usar o editor on-line do Crowdin e alguns dos recursos avançados do Crowdin_ ## Ferramentas {#tools} -- [Linguee](https://www.linguee.com/) _: mecanismo de busca para traduções e dicionário que permite a pesquisa por palavra ou frase_ -- [Proz](https://www.proz.com/search/) _: banco de dados de traduções, dicionários e glossários para termos especializados_ -- [Eurotermbank](https://www.eurotermbank.com/) _: coleções de terminologia europeia em 42 idiomas_ +- [Linguee](https://www.linguee.com/) + _– mecanismo de busca para traduções e dicionário que permite a pesquisa por palavra ou frase_ +- [Proz term search](https://www.proz.com/search/) + _– banco de dados de dicionários de tradução e glossários para termos especializados_ +- [Eurotermbank](https://www.eurotermbank.com/) + _– coleções de terminologia europeia em 42 idiomas_ ## Comunidades {#communities} -- [Grupos de tradução do Discord para idiomas específicos](https://discord.gg/ethereum-org) _: iniciativa que conecta tradutores do ethereum.org a Grupos de Tradução_ -- [Grupo de tradutores de chinês](https://www.notion.so/Ethereum-org-05375fe0a94c4214acaf90f42ba40171) _: página de noções para facilitar a coordenação entre tradutores de chinês_ +- [Grupos de tradução do Discord para idiomas específicos](https://discord.gg/ethereum-org) + _– uma iniciativa para conectar os tradutores do ethereum.org aos Grupos de Tradução_ +- [Grupo de tradutores de chinês](https://www.notion.so/Ethereum-org-05375fe0a94c4214acaf90f42ba40171) + _– página do Notion para facilitar a coordenação entre os tradutores de chinês_ ## Últimas atualizações {#latest-updates} -Para se manter atualizado sobre os avanços mais recentes do Programa de Tradução, você pode seguir o [blog da Fundação Ethereum](https://blog.ethereum.org/): +Para se manter atualizado com o progresso mais recente do Programa de Tradução, você pode seguir o [blog da Ethereum Foundation](https://blog.ethereum.org/): -- [Atualização de outubro de 2021](https://blog.ethereum.org/2021/10/04/translation-program-update) -- [Atualização de dezembro de 2020](https://blog.ethereum.org/2020/12/21/translation-program-milestones-updates-20) -- [Atualização de julho de 2020](https://blog.ethereum.org/2020/07/29/ethdotorg-translation-milestone) -- [Lançamento do Programa de Tradução de agosto de 2019](https://blog.ethereum.org/2019/08/20/translating-ethereum-for-our-global-community) +- [Atualização dos marcos de outubro de 2021](https://blog.ethereum.org/2021/10/04/translation-program-update/) +- [Atualização dos marcos de dezembro de 2020](https://blog.ethereum.org/2020/12/21/translation-program-milestones-updates-20/) +- [Atualização dos marcos de julho de 2020](https://blog.ethereum.org/2020/07/29/ethdotorg-translation-milestone/) +- [Lançamento do Programa de Tradução de agosto de 2019](https://blog.ethereum.org/2019/08/20/translating-ethereum-for-our-global-community/) -## Horários de trabalho para tradutores {#office-hours} +## Horário de atendimento para tradutores {#office-hours} -Temos horários de plantão para tradutores na segunda quarta-feira de cada mês. Eles são mantidos no canal de voz #horários de plantão no [Discord do ethereum.org](https://discord.gg/ethereum-org), no qual você também pode encontrar os horários exatos e detalhes adicionais. +Temos horários de plantão para tradutores na segunda quarta-feira de cada mês. As sessões acontecem no canal de voz #office-hours no [Discord do ethereum.org](https://discord.gg/ethereum-org), onde você também pode encontrar os horários exatos e detalhes adicionais. -O horário de plantão permite que nossos tradutores façam perguntas sobre o processo de tradução, forneçam comentários sobre o programa, compartilhem suas ideias ou simplesmente conversem com a equipe principal do ethereum.org. Por último, queremos usar essas chamadas para comunicar desenvolvimentos recentes no Programa de Tradução e compartilhar dicas importantes e instruções com nossos colaboradores. +O horário de plantão permite que nossos tradutores façam perguntas sobre o processo de tradução, forneçam comentários sobre o programa, compartilhem suas ideias ou simplesmente conversem com a equipe principal do ethereum.org. +Por último, queremos usar essas chamadas para comunicar desenvolvimentos recentes no Programa de Tradução e compartilhar dicas importantes e instruções com nossos colaboradores. Se você é um tradutor do ethereum.org ou deseja ser, venha participar dessas sessões. diff --git a/public/content/translations/pt-br/contributing/translation-program/translatathon/details/index.md b/public/content/translations/pt-br/contributing/translation-program/translatathon/details/index.md new file mode 100644 index 00000000000..093cd73f0e0 --- /dev/null +++ b/public/content/translations/pt-br/contributing/translation-program/translatathon/details/index.md @@ -0,0 +1,90 @@ +--- +title: Detalhes e regras +lang: pt-br +template: translatathon +--- + +![](./participate.png) + +O Translatathon está aberto e qualquer pessoa pode participar preenchendo o formulário de inscrição e entrando no projeto no Crowdin. + +Os tradutores acumulam pontos ao sugerir traduções para textos não traduzidos em seu idioma no editor do Crowdin durante o período de tradução. + +A pontuação final de cada participante é determinada por sua posição no placar de líderes com base no número de palavras que traduziram durante o período de tradução e quaisquer pontos de bônus que tenham acumulado. + +## Primeiros passos {#getting-started} + +O processo de tradução ocorre no projeto ethereum.org no Crowdin e os tradutores sugerem suas traduções para textos não traduzidos, compostos por quase todo o conteúdo do site ethereum.org. + +As traduções são sugeridas diretamente no editor online, portanto, não há necessidade de baixar ou enviar arquivos ou entregáveis. Cada palavra traduzida é rastreada e contada. + +**1) Junte-se ao projeto** + +- Para começar a contribuir, junte-se ao [projeto ethereum.org no Crowdin](https://crowdin.com/project/ethereum-org) +- Você precisará fazer login ou criar uma conta - tudo o que é necessário é um endereço de e-mail e uma senha + +**2) Selecione seu idioma** + +- Encontre seu idioma na lista de idiomas de destino e abra-o clicando em seu nome ou bandeira +- Se você quiser traduzir para um idioma que não está disponível, entre em contato com a [Equipe do Ethereum.org](https://crowdin.com/profile/ethdotorg) no Crowdin ou envie-nos um e-mail para translations@ethereum.org e adicionaremos idiomas de destino adicionais mediante solicitação + +**3) Abra um arquivo não traduzido** + +- Encontre o primeiro arquivo não traduzido para começar a traduzir. As pastas que contêm os arquivos de origem são baseadas em prioridade, então você deve começar a traduzir a primeira pasta que contém arquivos não traduzidos +- Cada arquivo tem um indicador de progresso que mostra quanto do conteúdo traduzível no arquivo foi traduzido e aprovado... se o progresso da tradução de qualquer arquivo estiver abaixo de 100%, traduza-o + +**4) Traduza os textos não traduzidos** + +- Ao abrir um arquivo para traduzir, certifique-se de que está traduzindo apenas os textos não traduzidos! +- Cada texto tem um indicador de status que mostra se está _Traduzido_, _Não traduzido_ ou _Aprovado_. Se um texto de origem já tiver uma tradução sugerida em seu idioma, não há necessidade de traduzi-lo +- Você também pode filtrar os textos no editor para mostrar _Não traduzidos primeiro_ ou _Apenas não traduzidos_ + +Para um guia detalhado sobre como navegar e usar o editor do Crowdin, recomendamos que todos os participantes do Translatathon leiam nosso guia [Como traduzir](/contributing/translation-program/how-to-translate/). + +Você também pode encontrar algumas dicas e melhores práticas conferindo nosso [guia de estilo de tradução](/contributing/translation-program/translators-guide/). + +**Como funcionam os pontos** + +Todo participante do Translatathon ganhará pontos para sua pontuação final, traduzindo conteúdo no projeto ethereum.org do Crowdin e em outros projetos elegíveis (a lista completa de projetos elegíveis está disponível abaixo). + +A pontuação é simples: **1 palavra traduzida = 1 ponto** + +Para receber sua alocação final de pontos, suas traduções sugeridas precisarão passar pelo processo de avaliação, onde revisores profissionais verificarão as traduções de cada participante para garantir que atendam ao limite mínimo de qualidade e que não tenham sido usadas traduções automáticas ou por IA no processo. + +## Conteúdo do ecossistema {#ecosystem-content} + +Como o programa de tradução do ethereum.org está sempre ativo, o progresso da tradução em alguns idiomas de destino no site é significativamente maior do que em outros. + +Para garantir que todos os participantes do Translatathon tenham uma oportunidade igual de traduzir o máximo de conteúdo que puderem e competir pelos prêmios principais, o conteúdo de origem que faz parte do Translatathon não se limita apenas ao conteúdo do site ethereum.org. + +Os participantes que traduzirem qualquer um dos projetos elegíveis ganharão uma quantidade igual de pontos, 1 palavra traduzida em qualquer projeto = 1 ponto. + +Aqui está uma lista de todos os projetos elegíveis que fazem parte do Translatathon de 2025: + +- [Ethereum.org](https://crowdin.com/project/ethereum-org) + +- [Tutoriais para desenvolvedores do Ethereum.org](https://crowdin.com/project/33388446abbe9d7aa21e42e49bba7f97) + +- [CLI de depósito do EthStaker](https://crowdin.com/project/ethstaker-deposit-cli) + +- [Documentação do Eth Docker](https://crowdin.com/project/eth-docker-docs) + +- [Documentação do Remix IDE](https://crowdin.com/project/remix-translation) + +- [Remix LearnEth](https://crowdin.com/project/remix-learneth) + +- [web3.py](https://crowdin.com/project/web3py) + +## Processo de avaliação {#evaluation-process} + +Todas as traduções estarão sujeitas a QA e feedback, onde linguistas profissionais avaliarão os envios com base na qualidade e precisão. + +Também estaremos aplicando **medidas contra a tradução automática** usando algumas ferramentas que detectam automaticamente traduções automáticas ou de IA. + +Embora a qualidade da tradução não desempenhe um papel crítico na pontuação, quaisquer **participantes que utilizarem traduções automáticas ou de IA** ou que sugerirem traduções de baixa qualidade e imprecisas não serão elegíveis para os prêmios! + +O período de avaliação ocorrerá durante todo o mês de setembro e os resultados serão anunciados na chamada da comunidade do ethereum.org em 25 de setembro. + +Todas as traduções também serão totalmente revisadas antes de serem adicionadas ao site. + + diff --git a/public/content/translations/pt-br/contributing/translation-program/translatathon/index.md b/public/content/translations/pt-br/contributing/translation-program/translatathon/index.md new file mode 100644 index 00000000000..496d7618a69 --- /dev/null +++ b/public/content/translations/pt-br/contributing/translation-program/translatathon/index.md @@ -0,0 +1,100 @@ +--- +title: Translatathon 2025 da ethereum.org +lang: pt-br +template: translatathon +--- + + + + + + + +## Introdução {#introduction} + +Acreditamos que o conteúdo e os recursos de integração da Ethereum devem ser acessíveis a todos, independentemente do idioma que falam. +Para nos aproximarmos desse objetivo, o programa de tradução da ethereum.org é uma iniciativa para traduzir o site para o maior número possível de idiomas. + +Como parte do programa de tradução, estamos organizando a 3ª edição da Translatathon, nosso concurso de tradução que visa incentivar contribuições de tradução em idiomas menos ativos, aumentar o número de idiomas e a quantidade de conteúdo disponível no site, integrar novos contribuidores e recompensar os já existentes. + +Se você é falante nativo de um idioma que não seja o inglês e quer ajudar a tornar o conteúdo da Ethereum mais acessível enquanto compete por prêmios, continue lendo para saber mais! + +[Saiba mais sobre o programa de tradução da ethereum.org](/contributing/translation-program/) + +## Cronograma {#timeline} + +Aqui estão as datas importantes para a Translatathon de 2025: + + + + + +## Participe {#participate} + +![Imagem de comunidade e globo](./participate.png) + + + +

Quem pode participar?

+ Qualquer pessoa com mais de 18 anos, falante nativo de pelo menos um idioma que não seja o inglês e proficiente em inglês. +
+ +

Preciso ser um tradutor?

+ Não. Você só precisa ser bilíngue e sugerir traduções humanas (o uso de tradução automática é proibido!) da melhor forma possível, não é necessária experiência profissional. +
+
+ + + +

Quanto tempo preciso dedicar?

+ O quanto você quiser. O limite mínimo para ser elegível aos prêmios é de 1.000 palavras traduzidas, o que deve levar cerca de 2 horas para ser concluído, enquanto competir pelos prêmios principais exigirá um maior comprometimento de tempo. +
+ +

Preciso estar familiarizado com o Ethereum?

+ Não. Embora estar familiarizado com o Ethereum possa ajudar com sua produtividade e qualidade, a Translatathon também é uma experiência de aprendizado, e todos estão convidados a participar e aprender mais sobre o Ethereum enquanto participam. +
+
+ +Para mais detalhes, [consulte os Termos e Condições completos](/contributing/translation-program/translatathon/terms-and-conditions) + +### Instruções passo a passo {#step-by-step-instructions} + + + +## Prêmios {#prizes} + +| Classificação | Valor do prêmio | +| ----------------- | ---------------------- | +| 1º lugar | $4.000 | +| 2º lugar | $2.500 | +| 3º lugar | $1.500 | +| 4º lugar | $1.100 | +| 5º lugar | $1.000 | +| 6º lugar | $600 | +| 7º lugar | $550 | +| 8º lugar | $500 | +| 9º lugar | $450 | +| 10º lugar | $400 | +| 11º - 20º lugar | $240 | +| 21º - 50º lugar | $120 | +| 51º - 100º lugar | $60 | +| 101º - 150º lugar | $40 | +| Restante | $20 | + +Todos os prêmios serão pagos em ETH. + + + + diff --git a/public/content/translations/pt-br/contributing/translation-program/translators-guide/index.md b/public/content/translations/pt-br/contributing/translation-program/translators-guide/index.md index fea6275d313..217e271684a 100644 --- a/public/content/translations/pt-br/contributing/translation-program/translators-guide/index.md +++ b/public/content/translations/pt-br/contributing/translation-program/translators-guide/index.md @@ -1,7 +1,7 @@ --- title: Guia para tradutores lang: pt-br -description: Instruções e dicas para os tradutores do ethereum.org +description: "Instruções e dicas para os tradutores do ethereum.org" --- # Guia de Estilo de Tradução do Ethereum.org {#style-guide} @@ -10,15 +10,15 @@ O Guia de Estilo de Tradução do ethereum.org contém algumas das diretrizes, i Este documento serve como um guia geral e não é específico para nenhum idioma. -Se você tiver alguma dúvida, sugestão ou feedback, envie um e-mail para translations@ethereum.org, uma mensagem para @ethdotorg no Crowdin ou [inscreva-se no Discord](https://discord.gg/ethereum-org), para nos mandar mensagens no canal #translations ou entrar em contato com qualquer um dos membros da equipe. +Se tiver alguma dúvida, sugestão ou feedback, sinta-se à vontade para entrar em contato conosco em translations@ethereum.org, enviar uma mensagem para @ethdotorg no Crowdin, ou [entrar no nosso Discord](https://discord.gg/ethereum-org), onde você pode nos enviar uma mensagem no canal #translations ou contatar qualquer um dos membros da equipe. -## Como usar o Crowdin {#using-crowdin} +## Usando o Crowdin {#using-crowdin} Você pode encontrar instruções básicas sobre como participar do projeto no Crowdin e como usar o editor online do Crowdin na [página do Programa de Tradução](/contributing/translation-program/#how-to-translate). -Se você quiser saber mais sobre o Crowdin e usar alguns dos seus recursos avançados, a [Base de conhecimento do Crowdin](https://support.crowdin.com/online-editor/) contém vários de guias detalhados e resumos de todas as funcionalidades do Crowdin. +Se você quiser aprender mais sobre o Crowdin e usar alguns de seus recursos avançados, a [base de conhecimento do Crowdin](https://support.crowdin.com/online-editor/) contém muitos guias detalhados e visões gerais de todas as funcionalidades do Crowdin. -## Entendendo a essência da mensagem {#capturing-the-essence} +## Capturando a essência da mensagem {#capturing-the-essence} Ao traduzir o conteúdo do ethereum.org, evite traduções literais. @@ -28,7 +28,7 @@ Idiomas diferentes têm diferentes regras gramaticais, convenções e ordem de p Em vez de traduzir o texto de origem palavra por palavra, é recomendado ler toda a frase e adaptá-la para que ela se adapte às convenções do idioma de destino. -## Formal ou informal {#formal-vs-informal} +## Formal vs. informal {#formal-vs-informal} Utilizamos linguagem formal, que é sempre mais educada e apropriada a todos os visitantes. @@ -36,7 +36,7 @@ O uso do estilo formal nos permite evitar soarmos ofensivos ou inapropriados, e A maioria dos idiomas indo-europeus e afro-asiáticos utiliza pronomes pessoais em segunda pessoa específicos de gênero, que fazem a distinção entre masculino e feminino. Quando nos dirigimos ao usuário ou usamos pronomes possessivos, podemos evitar supor o sexo do visitante, uma vez que a maneira formal de tratamento é geralmente aplicável e consistente, independentemente da forma como se identificam. -## Vocabulário simples e claro {#simple-vocabulary} +## Vocabulário e significado simples e claros {#simple-vocabulary} Nosso objetivo é tornar o conteúdo do site compreensível para o maior número de pessoas possível. @@ -50,17 +50,17 @@ Todo o conteúdo deve ser traduzido usando a norma padrão de seu idioma, e não Ao traduzir o conteúdo, você deve garantir que a tradução está correta. -Um engano comum é o de que Ethereum deve ser escrito sempre em caracteres latinos. Essa é uma ideia incorreta, por isso, use a grafia do Ethereum de acordo com seu idioma nativo (por exemplo, 以太坊 em chinês, إيثيريوم em árabe, etc.). +Um engano comum é o de que Ethereum deve ser escrito sempre em caracteres latinos. Isso está, em geral, incorreto. Por favor, use a grafia de Ethereum nativa do seu idioma (p. ex., 以太坊 em chinês, إيثيريوم em árabe, etc.). **O mencionado acima não se aplica a idiomas em que nomes próprios não devem ser traduzidos como regra geral.** -## Traduzindo metadados da página {#translating-metadata} +## Tradução de metadados de página {#translating-metadata} Algumas páginas contêm metadados, como "title", "lang", "description", "sidebar", etc. Ocultamos o conteúdo que os tradutores nunca devem traduzir ao carregar novas páginas no Crowdin, ou seja, todos os metadados visíveis aos tradutores no Crowdin devem ser traduzidos. -Esteja atento ao traduzir quaisquer frases em que o texto de origem seja "en". Isso representa o idioma no qual a página está disponível e deve ser traduzida para o [código de idioma ISO para o seu idioma.](https://www.andiamo.co.uk/resources/iso-language-codes/). Essas frases devem sempre ser traduzidas usando caracteres latinos, e não o script de escrita nativo do idioma de destino. +Esteja atento ao traduzir quaisquer frases em que o texto de origem seja "en". Isso representa o idioma em que a página está disponível e deve ser traduzido para o [código de idioma ISO para o seu idioma](https://www.andiamo.co.uk/resources/iso-language-codes/). Essas frases devem sempre ser traduzidas usando caracteres latinos, e não o script de escrita nativo do idioma de destino. Se você não tem certeza de qual código de idioma usar, você pode verificar a memória de tradução no Crowdin ou encontrar o código de idioma para o seu idioma na URL da página no editor online do Crowdin. @@ -78,15 +78,18 @@ Algumas frases contêm títulos de artigos externos. A maioria das nossas págin Você pode encontrar alguns exemplos de como essas frases aparecem para os tradutores e como identificá-las abaixo (os links para artigos podem ser encontrados na parte inferior destas páginas, na seção "Leitura adicional"): -![Títulos de artigos no sidebar.png](./article-titles-in-sidebar.png) ![Títulos de artigos no editor.png](./article-titles-in-editor.png) +![Títulos do artigo na barra lateral](./article-titles-in-sidebar.png) +![Títulos do artigo no editor](./article-titles-in-editor.png) -## Alertas do Crowdin {#crowdin-warnings} +## Avisos do Crowdin {#crowdin-warnings} -O Crowdin tem um recurso integrado que alerta os tradutores quando eles estão prestes a cometer um erro. O Crowdin avisará automaticamente antes de salvar sua tradução, caso você se esqueça de incluir uma tag da fonte, traduzir elementos que não devem ser traduzidos, adicionar espaços adicionais ou se esqueça da pontuação final, etc. Se você vir um aviso como este, verifique novamente a tradução sugerida. +O Crowdin tem um recurso integrado que alerta os tradutores quando eles estão prestes a cometer um erro. O Crowdin avisará automaticamente antes de salvar sua tradução, caso você se esqueça de incluir uma tag da fonte, traduzir elementos que não devem ser traduzidos, adicionar espaços adicionais ou se esqueça da pontuação final, etc. +Se você vir um aviso como este, verifique novamente a tradução sugerida. **Nunca ignore esses avisos, pois significa que algo está errado, ou está faltando uma parte importante do texto original.** -Um exemplo de alerta do Crowdin quando você se esquece de adicionar uma tag à sua tradução: ![Exemplo de um aviso do Crowdin](./crowdin-warning-example.png) +Um exemplo de um aviso do Crowdin quando você se esquece de adicionar uma tag à sua tradução: +![Exemplo de um aviso do Crowdin](./crowdin-warning-example.png) ## Lidando com tags e trechos de código {#dealing-with-tags} @@ -96,15 +99,18 @@ Grande parte do conteúdo fonte contém tags e variáveis, que são destacadas e Para tornar mais fácil gerenciar tags e copiá-las diretamente da fonte, recomendamos alterar as suas configurações no editor do Crowdin. -1. Abra as configurações ![Como abrir as configurações no editor](./editor-settings.png) +1. Abrir configurações + ![Como abrir as configurações no editor](./editor-settings.png) 2. Role para baixo até a seção "Exibição de tags HTML" -3. Selecione "Ocultar" ![Selecione "Ocultar"](./hide-tags.png) +3. Selecione 'Ocultar' + ![Por favor, selecione 'Ocultar'](./hide-tags.png) 4. Clique em "Salvar" -Ao selecionar esta opção, o texto completo da tag não será mais exibido e será substituído por um número. Ao traduzir, clicar nesta tag copiará automaticamente a tag exata para o campo de tradução. +Ao selecionar esta opção, o texto completo da tag não será mais exibido e será substituído por um número. +Ao traduzir, clicar nesta tag copiará automaticamente a tag exata para o campo de tradução. **Links** @@ -116,7 +122,7 @@ A melhor maneira de lidar com links é copiá-los diretamente da fonte, clicando ![Exemplo de link.png](./example-of-link.png) -Links também aparecem no texto fonte na forma de tags (ou seja, \<0> \). Se você passar o mouse por cima da tag, o editor exibirá seu conteúdo completo. Às vezes, essas tags representarão links. +Os links também aparecem no texto de origem na forma de tags (ou seja, `<0>` ``). Se você passar o mouse por cima da tag, o editor exibirá seu conteúdo completo. Às vezes, essas tags representarão links. É muito importante copiar os links da origem e não mudar a sua ordem. @@ -132,33 +138,33 @@ As tags sempre contêm uma identificação de abertura e fechamento. Geralmente, Exemplo: ``Descentralizado`` -`` — _Tag de abertura que deixa o texto em negrito_ +`` - _Tag de abertura que deixa o texto em negrito_ -Descentralizado — _Texto traduzível_ +Descentralizado - _Texto traduzível_ -`` — _Tag de fechamento_ +`` - _Tag de fechamento_ -![Exemplo de tags.png ''fortes"](./example-of-strong-tags.png) +![Exemplo de tags 'strong'](./example-of-strong-tags.png) Os trechos de código (snippets) devem ser abordados de maneira ligeiramente diferente das outras tags por conterem código que não deveria ser traduzido. Exemplo: ``nonce`` -`` — _Tag de abertura, que contém um trecho de código_ +`` - _Tag de abertura, que contém um trecho de código_ -nonce — _Texto não traduzível_ +nonce - _Texto não traduzível_ -`` — _Tag de fechamento_ +`` - _Tag de fechamento_ ![Exemplo de código snippets.png](./example-of-code-snippets.png) O texto original também contém tags abreviadas, que contêm apenas números, o que significa que sua função não é imediatamente óbvia. Você pode passar o mouse sobre essas tags para ver exatamente para qual função elas servem. -No exemplo abaixo, ao passar o mouse sobre a \<0> tag mostra que ela representa `` e contém um trecho de código. Portanto, o conteúdo dentro dessas tags não deve ser traduzido. +No exemplo abaixo, você pode ver que passar o mouse sobre a tag `<0>` mostra que ela representa `` e contém um trecho de código, portanto, o conteúdo dentro dessas tags não deve ser traduzido. -![Exemplo de tags.png ambíguas](./example-of-ambiguous-tags.png) +![Exemplo de tags.png](./example-of-ambiguous-tags.png ambíguas) -## Formas/abreviaturas curtas vs. completas {#short-vs-full-forms} +## Formas curtas vs. formas completas/abreviações {#short-vs-full-forms} Existem muitas abreviações usadas no site, por exemplo, dapps, NFT, DAO, DeFi, etc. Essas abreviações são comumente usadas em inglês e a maioria dos visitantes do site estão familiarizados com elas. @@ -168,7 +174,7 @@ Não traduza essas abreviaturas, já que a maioria das pessoas não estaria fami Exemplo de como traduzir dapps: -- Aplicativos descentralizados (dapps) → _Formulário completo traduzido (abreviação em inglês entre parênteses)_ +- aplicativos descentralizados (dapps) → _Forma por extenso traduzida (abreviação em inglês entre parênteses)_ ## Termos sem traduções estabelecidas {#terms-without-established-translations} @@ -180,17 +186,17 @@ Ao traduzi-los, sinta-se livre para ser criativo, use traduções descritivas ou **A razão pela qual a maioria dos termos deveria ser traduzida, em vez ser deixada em inglês, é que essa nova terminologia se tornará mais difundida no futuro, à medida que mais pessoas começarem a usar o Ethereum e tecnologias relacionadas. Se queremos envolver mais pessoas de todo o mundo nesse espaço, precisamos fornecer uma terminologia compreensível no maior número possível de idiomas, mesmo que precisemos criá-la nós mesmos.** -## Botões e chamadas para a ação (CTAs) {#buttons-and-ctas} +## Botões e CTAs {#buttons-and-ctas} O site contém vários botões, que devem ser traduzidos de forma diferente dos outros tipos de conteúdo. O texto do botão pode ser identificado visualizando o contexto das telas capturadas, conectadas com a maioria das frases, ou verificando o contexto no editor, que inclui a frase 'botão'. -As traduções dos botões devem ser o mais curtas possível, para evitar incompatibilidade de formatação. Além disso, as traduções dos botões devem ter o verbo no imperativo, ou seja, apresentar um comando ou solicitação. +As traduções dos botões devem ser o mais curtas possível, para evitar incompatibilidade de formatação. Além disso, as traduções de botões devem estar no imperativo, ou seja, apresentar um comando ou solicitação. -![Como encontrar um botão.png](./how-to-find-a-button.png) +![Como encontrar um botão](./how-to-find-a-button.png) -## Traduzindo de forma inclusiva {#translating-for-inclusivity} +## Traduzindo para a inclusividade {#translating-for-inclusivity} Os visitantes do ethereum.org vêm de todo o mundo e de diferentes origens. Por conseguinte, a linguagem utilizada no site deve ser neutra, acolhedora para todos e inclusiva. @@ -200,7 +206,7 @@ Outra forma de inclusão é tentar traduzir para um público global, sem especif Por último, a língua deve ser adequada para todos os públicos e todas as idades. -## Traduções específicas de um idioma {#language-specific-translations} +## Traduções específicas do idioma {#language-specific-translations} Ao traduzir, é importante seguir as regras gramaticais, convenções e formatação usadas em seu idioma, em vez de copiá-las do idioma de origem. O texto de origem segue as regras e convenções gramaticais do inglês, o que não é aplicável a muitos outros idiomas. @@ -208,7 +214,7 @@ Você deve estar ciente das regras do seu idioma e traduzir de acordo com elas. Aqui estão alguns exemplos a que você deve ter atenção: -### Pontuação, formatação {#punctuation-and-formatting} +### Pontuação e formatação {#punctuation-and-formatting} **Regras de uso de maiúsculas e minúsculas** @@ -220,8 +226,8 @@ Aqui estão alguns exemplos a que você deve ter atenção: - As regras da ortografia definem o uso de espaços para cada língua. Como os espaços são usados em toda a parte, essas regras são frequentemente bem específicas e estão entre os elementos mais mal traduzidos. - Algumas diferenças comuns de espaçamento entre inglês e outras línguas: - - Espaço antes das unidades de medida e moedas (por exemplo: USD, EUR, kB, MB) - - Espaço antes dos sinais de graus (ex.: °C, °F) + - Espaço antes de unidades de medida e moedas (p. ex., USD, EUR, kB, MB) + - Espaço antes de sinais de grau (p. ex., °C, ℉) - Espaço antes de algumas marcas de pontuação, especialmente as reticências (…) - Espaço antes e após barras (/) @@ -229,7 +235,7 @@ Aqui estão alguns exemplos a que você deve ter atenção: - Toda língua tem um conjunto diversificado e complexo de regras para escrever listas. Elas podem ser significativamente diferentes do inglês. - Em algumas línguas, a primeira palavra de cada nova linha precisa ser colocada em maiúscula, enquanto em outras, novas linhas devem começar com letras minúsculas. Muitas línguas também têm regras diferentes sobre o uso de maiúsculas em listas, dependendo do tamanho de cada linha. -- O mesmo se aplica à pontuação de itens de linha. A pontuação final em listas pode ser um ponto (**.**), vírgula (**,**), ou ponto e vírgula (**;**), dependendo do idioma. +- O mesmo se aplica à pontuação de itens de linha. A pontuação final em listas pode ser um ponto (.), vírgula (,) ou ponto e vírgula (;), dependendo do idioma. **Aspas** @@ -253,10 +259,10 @@ Aqui estão alguns exemplos a que você deve ter atenção: - A principal diferença entre is idiomas em relação à escrita de números é o separador usado para números decimais e milhares. Para milhares, isso pode ser um ponto, vírgula ou espaço. Da mesma forma, alguns idiomas usam um ponto decimal, enquanto outros usam uma vírgula decimal. - Alguns exemplos de números grandes: - - Inglês — **1,000.50** - - Espanhol — **1.000,50** - - Francês — **1 000,50** -- Outra consideração importante ao traduzir números é o sinal de percentagem. Ele pode ser escrito de diferentes formas: **100%**, **100 %** ou **%100**. + - Inglês – **1,000.50** + - Espanhol – **1.000,50** + - Francês – **1 000,50** +- Outra consideração importante ao traduzir números é o sinal de percentagem. Pode ser escrito de diferentes maneiras: **100%**, **100 %** ou **%100**. - Por fim, números negativos podem ser exibidos de formas diferentes, dependendo do idioma: -100, 100-, (100) ou [100]. **Datas** diff --git a/public/content/translations/pt-br/dao/index.md b/public/content/translations/pt-br/dao/index.md index 4624fef8cba..750bf6f7040 100644 --- a/public/content/translations/pt-br/dao/index.md +++ b/public/content/translations/pt-br/dao/index.md @@ -1,15 +1,16 @@ --- -title: Organizações autônomas descentralizadas (DAOs) -description: Uma visão geral de DAOs no Ethereum +title: "O que é uma DAO?" +metaTitle: "O que é uma DAO? | Organização autônoma descentralizada" +description: "Uma visão geral de DAOs no Ethereum" lang: pt-br template: use-cases emoji: ":handshake:" sidebarDepth: 2 image: /images/use-cases/dao-2.png -alt: Uma representação de uma votação DAO em uma proposta. -summaryPoint1: Comunidades de membros sem liderança centralizada. +alt: "Uma representação de uma votação DAO em uma proposta." +summaryPoint1: "Comunidades de membros sem liderança centralizada." summaryPoint2: Uma maneira segura de colaborar com desconhecidos na Internet. -summaryPoint3: Um local seguro para destinar fundos para uma causa específica. +summaryPoint3: "Um local seguro para destinar fundos para uma causa específica." --- ## O que são DAOs? {#what-are-daos} @@ -18,7 +19,7 @@ Uma DAO é uma organização de propriedade coletiva que trabalha para uma miss As DAOs permitem-nos trabalhar com pessoas que pensam da mesma maneira em todo o mundo sem confiar em um líder benevolente para gerenciar os fundos ou as operações. Não há CEO que possa gastar fundos por impulso ou CFO que capaz de manipular as contas. Em vez disso, as regras baseadas em blockchain incorporadas ao código definem como a organização funciona e como os fundos são gastos. -Elas possuem receitas integradas que não podem ser acessadas por ninguém sem a aprovação do grupo. As decisões são regidas por propostas e votações para garantir que todos na organização tenham voz e que tudo aconteça de forma transparente [na blockchain](/glossary/#on-chain). +Elas possuem receitas integradas que não podem ser acessadas por ninguém sem a aprovação do grupo. As decisões são regidas por propostas e votações para garantir que todos na organização tenham voz, e tudo aconteça de forma transparente [onchain](/glossary/#onchain). ## Por que precisamos de DAOs? {#why-dao} @@ -28,27 +29,27 @@ Isto abre muitas novas oportunidades para a colaboração e coordenação globai ### Uma comparação {#dao-comparison} -| DAO | Uma empresa tradicional | -| --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | -| Hierarquia horizontal e totalmente democratizada. | Hierarquia vertical. | -| Votação exigida pelos membros para que quaisquer alterações sejam implementadas. | Dependendo da estrutura, as mudanças podem ser requeridas por uma única parte, ou ter opção de voto. | -| Votos conhecidos e resultados implementados automaticamente sem intermediário confiável. | Se a votação é permitida, os votos são homologados internamente e o resultado da votação tem de ser tratado manualmente. | +| DAO | Uma organização tradicional | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | +| Hierarquia horizontal e totalmente democratizada. | Hierarquia vertical. | +| Votação exigida pelos membros para que quaisquer alterações sejam implementadas. | Dependendo da estrutura, as mudanças podem ser requeridas por uma única parte, ou ter opção de voto. | +| Votos conhecidos e resultados implementados automaticamente sem intermediário confiável. | Se a votação é permitida, os votos são homologados internamente e o resultado da votação tem de ser tratado manualmente. | | Os serviços oferecidos são tratados automaticamente de forma descentralizada (por exemplo, distribuição de fundos filantrópicos). | Requer manipulação humana, ou automação controlada centralmente, propensa a manipulação. | -| Toda a atividade é transparente e totalmente pública. | A atividade é tipicamente privada e limitada ao público. | +| Toda a atividade é transparente e totalmente pública. | A atividade é tipicamente privada e limitada ao público. | -### Exemplos de DAOs {#dao-examples} +### Exemplos de DAO {#dao-examples} Para dar um pouco de contexto, veja alguns exemplos de como você poderia usar uma DAO: -- **Uma instituição de caridade** - você pode aceitar doações de qualquer pessoa no mundo e votar em quais causas financiar. -- **Propriedade coletiva** - você pode comprar ativos físicos ou digitais, e os membros podem votar sobre como utilizá-los. -- **Empreendimentos e subsídios** - você pode criar um fundo de investimentos que reúna capital e decida coletivamente quais projetos apoiar. O rendimento do dinheiro aplicado poderia mais tarde ser redistribuído entre os membros da DAO. +- **Uma instituição de caridade** – você pode aceitar doações de qualquer pessoa no mundo e votar em quais causas financiar. +- **Propriedade coletiva** – você pode comprar ativos físicos ou digitais, e os membros podem votar sobre como utilizá-los. +- **Empreendimentos e subsídios** – você pode criar um fundo de investimentos que reúna capital e decida coletivamente quais projetos apoiar. O rendimento do dinheiro aplicado poderia mais tarde ser redistribuído entre os membros da DAO. ## Como funcionam as DAOs? {#how-daos-work} -A base de uma DAO é seu [contrato inteligente](/glossary/#smart-contract), que define as regras da organização e mantém os bens do grupo. Quando o contrato for publicado no Ethereum, ninguém poderá alterar as regras, exceto por votação. Se alguém tentar fazer algo que não esteja coberto pelas regras e lógica do código, não terá sucesso. E como a tesouraria é definida pelo contrato inteligente, também significa que ninguém pode gastar o dinheiro sem a aprovação do grupo. Isso significa que as DAOs não precisam de uma autoridade central. Em vez disso, o grupo toma decisões coletivas e os pagamentos são autorizados automaticamente quando os votos são aprovados. +A espinha dorsal de uma DAO é seu [contrato inteligente](/glossary/#smart-contract), que define as regras da organização e detém a tesouraria do grupo. Quando o contrato for publicado no Ethereum, ninguém poderá alterar as regras, exceto por votação. Se alguém tentar fazer algo que não esteja coberto pelas regras e lógica do código, não terá sucesso. E como a tesouraria é definida pelo contrato inteligente, também significa que ninguém pode gastar o dinheiro sem a aprovação do grupo. Isso significa que as DAOs não precisam de uma autoridade central. Em vez disso, o grupo toma decisões coletivas e os pagamentos são autorizados automaticamente quando os votos são aprovados. Isso é possível porque os contratos inteligentes são imunes a adulterações quando são implementados no Ethereum. Você não pode simplesmente editar o código (as regras das DAOs) sem que as pessoas percebam porque tudo é público. @@ -61,7 +62,7 @@ O Ethereum é a base perfeita para DAOs por várias razões: - Os contratos inteligentes podem enviar/receber fundos. Sem isso, você precisaria de um intermediário confiável para gerenciar os fundos do grupo. - A comunidade Ethereum provou ser mais colaborativa do que competitiva, permitindo que as melhores práticas e sistemas de suporte surjam rapidamente. -## Governança DAO {#dao-governance} +## Governança de DAO {#dao-governance} Há muitas considerações ao gerenciar uma DAO, como o funcionamento da votação e das propostas. @@ -71,27 +72,25 @@ A delegação é como a versão DAO da democracia representativa. Os detentores #### Um exemplo famoso {#governance-example} -[ENS](https://claim.ens.domains/delegate-ranking) - os detentores de ENS podem delegar seus votos a membros da comunidade engajados para representá-los. - -### Governança automática de transações {#governance-example} +### Governança de transação automática {#governance-example} Em muitas DAOs, as transações serão executadas automaticamente se um quórum de membros votar a favor. #### Um exemplo famoso {#governance-example} -[Nouns](https://nouns.wtf) - no Nouns DAO, uma transação é automaticamente executada se um quórum de votos for realizado e a maioria dos votos for a favor, desde que não seja vetada pelos fundadores. +[Nouns](https://nouns.wtf) – Na Nouns DAO, uma transação é executada automaticamente se um quórum de votos for atingido e a maioria votar afirmativamente, desde que não seja vetada pelos fundadores. ### Governança Multisig {#governance-example} -Embora as DAOs possam ter milhares de membros votantes, os fundos podem ficar em uma [carteira](/glossary/#wallet) compartilhada por 5-20 membros ativos da comunidade que são confiáveis e conhecidos publicamente (identidades públicas conhecidas pela comunidade). Após uma votação, os assinantes [multisig](/glossary/#multisig) executam a vontade da comunidade. +Embora as DAOs possam ter milhares de membros votantes, os fundos podem ficar em uma [carteira](/glossary/#wallet) compartilhada por 5-20 membros ativos da comunidade que são confiáveis e geralmente têm suas identidades reveladas (identidades públicas conhecidas pela comunidade). Após uma votação, os signatários da [multisig](/glossary/#multisig) executam a vontade da comunidade. -## Leis DAO {#dao-laws} +## Leis de DAO {#dao-laws} Em 1977, Wyoming inventou a LLC, que protege os empreendedores e limita a responsabilidade deles. Mais recentemente, eles foram pioneiros na lei DAO que estabelece o status legal para DAOs. Atualmente Wyoming, Vermont e as Ilhas Virgens têm alguma legislação que regula a DAO. ### Um exemplo famoso {#law-example} -[CityDAO](https://citizen.citydao.io/) – CityDAO usou a lei DAO do Wyoming para comprar 40 acres de terra perto do Parque Nacional de Yellowstone. +[CityDAO](https://citizen.citydao.io/) – A CityDAO usou a lei de DAO do Wyoming para comprar 40 acres de terra perto do Parque Nacional de Yellowstone. ## Adesão à DAO {#dao-membership} @@ -99,15 +98,15 @@ Existem diferentes modelos para a adesão à DAO. A adesão pode determinar como ### Adesão baseada em token {#token-based-membership} -Normalmente, não precisa de [permissão](/glossary/#permissionless) para ser usada, dependendo do token usado. A maioria desses tokens de governança podem ser trocados sem permissão em uma [corretora descentralizada](/glossary/#dex). Outros devem ser obtidos através do fornecimento de liquidez ou alguma outra “prova de trabalho”. De qualquer forma, a simples detenção do token permite o acesso à votação. +Geralmente totalmente [permissionless](/glossary/#permissionless), dependendo do token utilizado. Na maioria das vezes, esses tokens de governança podem ser negociados sem permissão em uma [corretora descentralizada](/glossary/#dex). Outros devem ser obtidos através do fornecimento de liquidez ou alguma outra “prova de trabalho”. De qualquer forma, a simples detenção do token permite o acesso à votação. _Normalmente usado para governar amplos protocolos descentralizados e/ou tokens._ #### Um exemplo famoso {#token-example} -[MakerDAO](https://makerdao.com) – O token MKR do MakerDAO está amplamente disponível em corretoras descentralizadas e qualquer pessoa pode comprar o poder de voto no futuro do protocolo Maker. +[MakerDAO](https://makerdao.com) – O token MKR da MakerDAO está amplamente disponível em corretoras descentralizadas, e qualquer pessoa pode comprar poder de voto sobre o futuro do protocolo Maker. -### Adesão compartilhada {#share-based-membership} +### Adesão baseada em cotas {#share-based-membership} As DAOs compartilhadas são mais restritas, mas ainda bem abertas. Qualquer membro potencial pode apresentar uma proposta para participar da DAO, geralmente com uma contribuição sob a forma de tokens ou trabalho. Cotas representam o poder de voto e a propriedade. Os membros podem sair a qualquer momento, com a sua parte proporcional da receita. @@ -115,51 +114,53 @@ _Normalmente utilizado em organizações mais coesas e com abordagem humanitári #### Um exemplo famoso {#share-example} -[MolochDAO](http://molochdao.com/) – MolochDAO foca no financiamento dos projetos Ethereum. Exigem uma proposta de adesão para que o grupo possa avaliar se você dispõe dos conhecimentos especializados e do capital necessários para fazer considerações fundamentadas sobre potenciais donatários. Você não pode simplesmente comprar acesso à DAO no mercado aberto. +[MolochDAO](http://molochdao.com/) – A MolochDAO é focada no financiamento de projetos Ethereum. Exigem uma proposta de adesão para que o grupo possa avaliar se você dispõe dos conhecimentos especializados e do capital necessários para fazer considerações fundamentadas sobre potenciais donatários. Você não pode simplesmente comprar acesso à DAO no mercado aberto. ### Adesão baseada em reputação {#reputation-based-membership} -A reputação representa a prova de participação e concede poder de voto na DAO. Diferentemente de adesões baseadas em ações ou tokens, as DAOs baseadas em reputação não transferem a propriedade para seus colaboradores. Reputação não pode ser comprada, transferida ou delegada; os membros da DAO devem ganhar reputação por meio de participação. A votação em cadeia não requer permissão e os potenciais membros podem apresentar propostas livremente para ingressar na DAO e solicitar o recebimento de reputação e tokens como recompensa em troca de suas contribuições. +A reputação representa a prova de participação e concede poder de voto na DAO. Diferentemente de adesões baseadas em ações ou tokens, as DAOs baseadas em reputação não transferem a propriedade para seus colaboradores. Reputação não pode ser comprada, transferida ou delegada; os membros da DAO devem ganhar reputação por meio de participação. Votação em rede não requer permissão e os membros em potencial podem submeter livremente propostas para ingressar a DAO e solicitar o recebimento de reputação e tokens como recompensa por suas contribuições. -_Tipicamente usados para descentralizar desenvolvimentos e protocolos de governança e [dApps](/glossary/#dapp), mas também se adapta bem a uma grande variedade de organizações, como instituições de caridade, cooperativas, clubes de investimento, etc._ +_Normalmente usado para o desenvolvimento descentralizado e governança de protocolos e [dapps](/glossary/#dapp), mas também é adequado para um conjunto diversificado de organizações como instituições de caridade, coletivos de trabalhadores, clubes de investimento, etc._ #### Um exemplo famoso {#reputation-example} -[DXdao](https://DXdao.eth.limo) -- DXdao é uma comunidade global e soberana que cria e controla protocolos e aplicativos descentralizados desde 2019. Usa governança baseada em reputação e [consenso holográfico](/glossary/#holographic-consensus) para coordenar e gerenciar fundos, o que significa que ninguém pode de alguma maneira tentar influenciar o futuro ou a governança. +[DXdao](https://DXdao.eth.limo) – A DXdao foi um coletivo soberano global que construiu e governou protocolos e aplicativos descentralizados desde 2019. Ela utilizou governança baseada em reputação e [consenso holográfico](/glossary/#holographic-consensus) para coordenar e gerenciar fundos, o que significa que ninguém poderia comprar influência sobre seu futuro ou governança. -## Iniciar/participar de uma DAO {#join-start-a-dao} +## Participe ou inicie uma DAO {#join-start-a-dao} ### Participe de uma DAO {#join-a-dao} - [DAOs da comunidade Ethereum](/community/get-involved/#decentralized-autonomous-organizations-daos) -- [Lista DAOHaus's de DAOs](https://app.daohaus.club/explore) -- [Lista Tally.xyz de DAOs](https://www.tally.xyz) +- [Lista de DAOs da DAOHaus](https://app.daohaus.club/explore) +- [Lista de DAOs da Tally.xyz](https://www.tally.xyz/explore) +- [Lista de DAOs da DeGov.AI](https://apps.degov.ai/) ### Inicie uma DAO {#start-a-dao} -- [Comece uma DAO com DAOHaus](https://app.daohaus.club/summon) -- [Inicie uma DAO de Governança com sistema de contagem](https://www.tally.xyz/add-a-dao) -- [Criar uma DAO suportada por Aragon](https://aragon.org/product) +- [Invoque uma DAO com a DAOHaus](https://app.daohaus.club/summon) +- [Inicie uma Governor DAO com a Tally](https://www.tally.xyz/get-started) +- [Crie uma DAO com a tecnologia da Aragon](https://aragon.org/product) - [Inicie uma colônia](https://colony.io/) -- [Crie uma DAO com o consenso holográfico de DAOstack](https://alchemy.daostack.io/daos/create) +- [Crie uma DAO com o consenso holográfico da DAOstack](https://alchemy.daostack.io/daos/create) +- [Lance uma DAO com o DeGov Launcher](https://docs.degov.ai/integration/deploy) ## Leitura adicional {#further-reading} -### Artigos sobre DAOs {#dao-articles} +### Artigos sobre DAO {#dao-articles} - [O que é uma DAO?](https://aragon.org/dao) – [Aragon](https://aragon.org/) - [Casa das DAOs](https://wiki.metagame.wtf/docs/great-houses/house-of-daos) – [Metagame](https://wiki.metagame.wtf/) - [O que é uma DAO e para que serve?](https://daohaus.substack.com/p/-what-is-a-dao-and-what-is-it-for) – [DAOhaus](https://daohaus.club/) -- [Como começar uma comunidade digital alimentada por DAO](https://daohaus.substack.com/p/four-and-a-half-steps-to-start-a) – [DAOhaus](https://daohaus.club/) +- [Como iniciar uma comunidade digital com uma DAO](https://daohaus.substack.com/p/four-and-a-half-steps-to-start-a) – [DAOhaus](https://daohaus.club/) - [O que é uma DAO?](https://coinmarketcap.com/alexandria/article/what-is-a-dao) – [Coinmarketcap](https://coinmarketcap.com) -- [O que é Consenso Holográfico?](https://medium.com/daostack/holographic-consensus-part-1-116a73ba1e1c) - [DAOstack](https://daostack.io/) -- [DAOs não são corporações: onde a descentralização em organizações autônomas é importante para Vitalik](https://vitalik.eth.limo/general/2022/09/20/daos.html) -- [DAOs, DACs, DAs e mais: Um Guia Terminológico Incompleto](https://blog.ethereum.org/2014/05/06/daos-dacs-das-and-more-an-incomplete-terminology-guide) - [Blog Ethereum](https://blog.ethereum.org) +- [O que é o Consenso Holográfico?](https://medium.com/daostack/holographic-consensus-part-1-116a73ba1e1c) - [DAOstack](https://daostack.io/) +- [DAOs não são corporações: onde a descentralização em organizações autônomas é importante, por Vitalik](https://vitalik.eth.limo/general/2022/09/20/daos.html) +- [DAOs, DACs, DAs e mais: um guia de terminologia incompleto](https://blog.ethereum.org/2014/05/06/daos-dacs-das-and-more-an-incomplete-terminology-guide) - [Blog do Ethereum](https://blog.ethereum.org) ### Vídeos {#videos} - [O que é uma DAO em cripto?](https://youtu.be/KHm0uUPqmVE) -- [Uma DAO pode construir uma cidade?](https://www.ted.com/talks/scott_fitsimones_could_a_dao_build_the_next_great_city) – [TED](https://www.ted.com/) +- [Pode uma DAO construir uma cidade?](https://www.ted.com/talks/scott_fitsimones_could_a_dao_build_the_next_great_city) – [TED](https://www.ted.com/) diff --git a/public/content/translations/pt-br/decentralized-identity/index.md b/public/content/translations/pt-br/decentralized-identity/index.md index 0ac4e34597e..1bd22d8facb 100644 --- a/public/content/translations/pt-br/decentralized-identity/index.md +++ b/public/content/translations/pt-br/decentralized-identity/index.md @@ -1,19 +1,19 @@ --- title: Identidade descentralizada -description: O que é uma identidade descentralizada e por que isso importa? +description: "O que é uma identidade descentralizada e por que isso importa?" lang: pt-br template: use-cases emoji: ":id:" sidebarDepth: 2 image: /images/eth-gif-cat.png -summaryPoint1: Os sistemas de identidade tradicionais centralizaram a emissão, manutenção e controle de seus identificadores. -summaryPoint2: A identidade descentralizada elimina a dependência de terceiros centralizados. -summaryPoint3: Graças à criptografia, os usuários agora têm as ferramentas para emitir, manter e controlar seus próprios identificadores e atestações novamente. +summaryPoint1: "Os sistemas de identidade tradicionais centralizaram a emissão, manutenção e controle de seus identificadores." +summaryPoint2: "A identidade descentralizada elimina a dependência de terceiros centralizados." +summaryPoint3: "Graças à criptografia, os usuários agora têm as ferramentas para emitir, manter e controlar seus próprios identificadores e atestações novamente." --- A identidade sustenta virtualmente todos os aspectos da sua vida hoje. Usar serviços on-line, abrir uma conta bancária, votar em eleições, comprar propriedades, garantir um emprego – todas essas coisas exigem que você prove sua identidade. -Entretanto, os sistemas tradicionais de gerenciamento de identidade há muito tempo dependem de intermediários centralizados que emitem, mantêm e controlam seus identificadores e [atestados](/glossary/#attestation). Isso significa que você não pode controlar as informações relacionadas à sua identidade ou decidir quem tem acesso às informações de identificação pessoal (PII) e quanto acesso essas partes têm. +No entanto, os sistemas tradicionais de gerenciamento de identidade há muito tempo dependem de intermediários centralizados que emitem, mantêm e controlam seus identificadores e [atestados](/glossary/#attestation). Isso significa que você não pode controlar as informações relacionadas à sua identidade ou decidir quem tem acesso às informações de identificação pessoal (PII) e quanto acesso essas partes têm. Para resolver esses problemas, temos sistemas de identidade descentralizados construídos em blockchains públicos como o Ethereum. A identidade descentralizada permite que indivíduos gerenciem informações relacionadas à sua identidade. Com soluções de identidade descentralizadas, _você_ pode criar identificadores e reivindicar e manter seus atestados sem depender de autoridades centrais, como provedores de serviços ou governos. @@ -39,63 +39,89 @@ Esses exemplos tradicionais de identificadores são emitidos, mantidos e control 1. A identidade descentralizada aumenta o controle individual de identificação da informação. Identificadores e atestados descentralizados podem ser verificados sem depender de autoridades centralizadas e serviços de terceiros. -2. As soluções de identidade descentralizadas facilitam um método com necessidade mínima de confiança, sem interrupções e de proteção de privacidade para verificar e gerenciar a identidade do usuário. +2. As soluções de identidade descentralizadas facilitam um método com necessidade mínima de confiança, sem interrupções e que protege a privacidade para verificar e gerenciar a identidade do usuário. 3. A identidade descentralizada aproveita a tecnologia blockchain, que cria confiança entre diferentes partes e fornece garantias criptográficas para provar a validade dos atestados. -4. A identidade descentralizada torna os dados de identidade portáteis. Os usuários armazenam atestados e identificadores na carteira móvel e podem compartilhar com qualquer parte de sua escolha. Identificadores e atestados descentralizados não são bloqueados no banco de dados da organização emissora. +4. A identidade descentralizada torna os dados de identidade portáteis. Os usuários armazenam atestados e identificadores em uma carteira móvel e podem compartilhar com qualquer parte de sua escolha. Identificadores e atestados descentralizados não são bloqueados no banco de dados da organização emissora. -5. A identidade descentralizada deve funcionar bem com tecnologias emergentes de [conhecimento zero](/glossary/#zk-proof), que permitirão que indivíduos provem que possuem ou fizeram algo sem revelar o que é essa coisa. Isso pode se tornar uma maneira poderosa de combinar confiança e privacidade para aplicações como votação. +5. A identidade descentralizada deve funcionar bem com as tecnologias emergentes de [conhecimento zero](/glossary/#zk-proof) que permitirão que os indivíduos provem que possuem ou fizeram algo sem revelar o que é essa coisa. Isso pode se tornar uma maneira poderosa de combinar confiança e privacidade para aplicações como votação. -6. A identidade descentralizada permite que mecanismos [anti-Sybil](/glossary/#anti-sybil) identifiquem quando um humano individual está fingindo ser vários humanos para jogar ou enviar spam a algum sistema. +6. A identidade descentralizada permite que mecanismos [anti-Sybil](/glossary/#anti-sybil) identifiquem quando um indivíduo humano está fingindo ser vários humanos para explorar ou enviar spam para algum sistema. -## Casos de uso de identidade descentralizadas {#decentralized-identity-use-cases} +## Casos de uso de identidade descentralizada {#decentralized-identity-use-cases} A identidade descentralizada tem muitos casos de uso em potencial: ### 1. Logins universais {#universal-dapp-logins} -A identidade descentralizada pode ajudar a substituir os logins baseados em senha pela autenticação descentralizada. Os provedores de serviços podem emitir atestados aos usuários, aos que podem ser armazenados em uma carteira Ethereum. Um exemplo de atestado seria uma [NFT](/glossary/#nft) concedendo ao titular acesso a uma comunidade on-line. +A identidade descentralizada pode ajudar a substituir os logins baseados em senha pela autenticação descentralizada. Os provedores de serviços podem emitir atestados aos usuários, aos que podem ser armazenados em uma carteira Ethereum. Um exemplo de atestado seria um [NFT](/glossary/#nft) que concede ao titular acesso a uma comunidade online. -Uma função [Entrar com Ethereum](https://siwe.xyz/) permitiria que os servidores confirmassem a conta Ethereum do usuário e buscassem o atestado necessário de seu endereço de conta. Isso significa que os usuários podem acessar plataformas e sites sem precisar memorizar senhas longas e melhorar a experiência on-line dos usuários. +Uma função [Entrar com Ethereum](https://siwe.xyz/) permitiria que os servidores confirmassem a conta Ethereum do usuário e buscassem o atestado necessário em seu endereço de conta. Isso significa que os usuários podem acessar plataformas e sites sem precisar memorizar senhas longas e melhorar a experiência on-line dos usuários. ### 2. Autenticação KYC {#kyc-authentication} O uso de muitos serviços on-line exige que os indivíduos forneçam atestados e credenciais, como carteira de motorista ou passaporte nacional. Mas essa abordagem é problemática porque as informações privadas do usuário podem ser comprometidas e os provedores de serviços não podem verificar a autenticidade do atestado. -A identidade descentralizada permite que as empresas ignorem os processos convencionais de [Conheça seu Cliente (KYC)](https://en.wikipedia.org/wiki/Know_your_customer) e autentiquem identidades de usuários por meio de credenciais verificáveis. Isso reduz o custo de gerenciamento de identidade e previne o uso de documentação falsa. +A identidade descentralizada permite que as empresas pulem os processos convencionais de [Conheça seu Cliente (KYC)](https://en.wikipedia.org/wiki/Know_your_customer) e autentiquem as identidades dos usuários por meio de Credenciais Verificáveis. Isso reduz o custo de gerenciamento de identidade e previne o uso de documentação falsa. -### 3. Votação e comunidades on-line {#voting-and-online-communities} +### 3. Votação e comunidades online {#voting-and-online-communities} -A votação on-line e as mídias sociais são duas novas aplicações para a identidade descentralizada. Esquemas de votação on-line são suscetíveis à manipulação, especialmente se atores mal-intencionados criarem identidades falsas para votar. Pedir a indivíduos que apresentem atestados on-chain pode melhorar a integridade dos processos de votação on-line. +A votação on-line e as mídias sociais são duas novas aplicações para a identidade descentralizada. Esquemas de votação on-line são suscetíveis à manipulação, especialmente se atores mal-intencionados criarem identidades falsas para votar. Pedir que indivíduos apresentem atestados on-chain pode melhorar a integridade dos processos de votação online. -A identidade descentralizada pode ajudar a criar comunidades on-line livres de contas falsas. Por exemplo, cada usuário pode ter que autenticar sua identidade usando um sistema de identidade on-chain, como o Nomes de Serviço Ethereum, reduzindo a possibilidade de bots. +A identidade descentralizada pode ajudar a criar comunidades on-line livres de contas falsas. Por exemplo, cada usuário pode ter que autenticar sua identidade usando um sistema de identidade on-chain, como o Ethereum Name Service, reduzindo a possibilidade de bots. ### 4. Proteção Anti-Sybil {#sybil-protection} -Os aplicativos de atribuição de concessões que usam [votação quadrática](/glossary/#quadratic-voting) são vulneráveis a [ataques Sybil](/glossary/#sybil-attack) porque o valor de uma concessão aumenta quando mais indivíduos votam nela, incentivando os usuários a dividir suas contribuições entre várias identidades. As identidades descentralizadas ajudam a evitar isso, aumentando o ônus de cada participante para provar que eles são realmente humanos, embora muitas vezes sem ter que revelar informações particulares específicas. +Aplicativos de concessão de doações que usam [votação quadrática](/glossary/#quadratic-voting) são vulneráveis a [ataques Sybil](/glossary/#sybil-attack) porque o valor de uma doação aumenta quando mais indivíduos votam nela, incentivando os usuários a dividir suas contribuições em várias identidades. As identidades descentralizadas ajudam a evitar isso, aumentando o ônus de cada participante para provar que eles são realmente humanos, embora muitas vezes sem ter que revelar informações particulares específicas. + +### 5. Identidade Nacional e Governamental {#national-and-government-id} + +Governos podem usar os princípios da identidade descentralizada para emitir documentos de identidade fundamentais — como identidades nacionais, passaportes ou carteiras de motorista — como credenciais verificáveis no Ethereum, fornecendo fortes garantias criptográficas de autenticidade para reduzir fraudes e falsificações na verificação de identidade online. Os cidadãos podem armazenar esses atestados em sua [carteira](/wallets/) pessoal e usá-los para provar sua identidade, idade ou direito de voto. + +Este modelo permite a divulgação seletiva, especialmente quando combinado com a tecnologia de privacidade de [prova de conhecimento zero (ZKP)](/zero-knowledge-proofs/). Por exemplo, um cidadão poderia provar criptograficamente que tem mais de 18 anos para acessar um serviço com restrição de idade sem revelar sua data de nascimento exata, oferecendo maior privacidade do que uma identidade tradicional. + +#### 💡Estudo de caso: Identidade Digital Nacional (NDI) do Butão no Ethereum {#case-study-bhutan-ndi} + +- Fornece acesso a credenciais de identidade verificáveis para os quase 800.000 cidadãos do Butão +- Migrado da rede Polygon [para a rede principal do Ethereum](https://www.bhutanndi.com/article/bhutan-adopts-ethereum-for-national-identity-a-new-chapter-in-digital-sovereignty_2d0c7ec2-5605-4c42-b258-bd9361ae8878) em outubro de 2025 +- Mais de [234.000 identidades digitais](https://www.blockchain-council.org/blockchain/bhutan-uses-blockchain-in-digital-id-project/) emitidas até março de 2025 + +O Reino do Butão [migrou seu sistema de Identidade Digital Nacional (NDI)](https://www.bhutanndi.com/article/bhutan-adopts-ethereum-for-national-identity-a-new-chapter-in-digital-sovereignty_2d0c7ec2-5605-4c42-b258-bd9361ae8878) para o Ethereum em outubro de 2025. Construído sobre os princípios de identidade descentralizada e identidade auto-soberana, o sistema NDI do Butão usa identificadores descentralizados e credenciais verificáveis para emitir credenciais assinadas digitalmente diretamente para a carteira pessoal de um cidadão. Ao ancorar provas criptográficas dessas credenciais no Ethereum, o sistema garante que elas sejam autênticas, à prova de adulteração e possam ser verificadas por qualquer parte sem consultar uma autoridade central. + +A arquitetura do sistema enfatiza a privacidade através do uso da tecnologia de [prova de conhecimento zero (ZKP)](/zero-knowledge-proofs/). Essa implementação de "divulgação seletiva" permite que os cidadãos provem fatos específicos (por exemplo, "Tenho mais de 18 anos" ou "Sou um cidadão") para acessar serviços sem revelar os dados pessoais subjacentes, como o número completo da identidade ou a data de nascimento exata. Isso demonstra um uso poderoso e real do Ethereum para um sistema de identidade nacional seguro, centrado no usuário e que preserva a privacidade. + +#### 💡Estudo de caso: QuarkID da Cidade de Buenos Aires na [Segunda Camada](/layer-2/) do Ethereum, ZKSync Era {#case-study-buenos-aires-quarkid} + +- Emissão de credenciais de identidade descentralizadas para mais de [3,6 milhões de usuários](https://buenosaires.gob.ar/innovacionytransformaciondigital/miba-con-tecnologia-quarkid-la-ciudad-de-buenos-aires-incorporo) no lançamento +- O QuarkID é um protocolo de código aberto reconhecido como um [Bem Público Digital](https://www.digitalpublicgoods.net/r/quarkid) sob os Objetivos de Desenvolvimento Sustentável da ONU +- Enfatiza um modelo de "[governo como usuário](https://buenosaires.gob.ar/innovacionytransformaciondigital/miba-con-tecnologia-quarkid-la-ciudad-de-buenos-aires-incorporo)", no qual a cidade não é dona do protocolo, dando aos cidadãos total propriedade e privacidade dos dados + +Em 2024, o Governo da Cidade de Buenos Aires (GCBA) integrou o QuarkID, a "estrutura de confiança digital" de código aberto construída pela Secretaria de Inovação e Transformação Digital do GCBA, no miBA, o aplicativo oficial da cidade para que os residentes acessem serviços governamentais e documentos oficiais. No lançamento, todos os mais de 3,6 milhões de usuários do miBA receberam identidades digitais descentralizadas que lhes permitem gerenciar e compartilhar documentos e certificados digitais verificáveis on-chain, incluindo credenciais de cidadania, certidões de nascimento, casamento e óbito, registros fiscais, registros de vacinação e muito mais. + +Construído na rede de [Segunda Camada](/layer-2/) do Ethereum, ZKSync Era, o sistema QuarkID usa a tecnologia ZKP para permitir que os cidadãos verifiquem credenciais pessoais ponto a ponto por meio de seus dispositivos móveis — sem expor dados pessoais desnecessários. O programa destaca um modelo de "governo como usuário", no qual o GCBA atua como um usuário do protocolo QuarkID, de código aberto e interoperável, em vez de atuar como um proprietário centralizado. Essa arquitetura habilitada para ZKP fornece um recurso de privacidade chave: nenhum terceiro, nem mesmo o GCBA, pode rastrear como, quando ou por que um cidadão usa suas credenciais. Este programa bem-sucedido oferece aos cidadãos identidade auto-soberana completa e controle sobre seus dados sensíveis, tudo protegido pela rede globalmente distribuída do Ethereum. ## O que são atestados? {#what-are-attestations} Um atestado é uma reivindicação feita por uma entidade sobre outra entidade. Se você mora nos Estados Unidos, a carteira de motorista emitida a você pelo Departamento de Veículos Motorizados (uma entidade) atesta que você (outra entidade) tem permissão legal para dirigir um carro. -Atestados são diferentes de identificadores. Um atestado _contém_ identificadores para referir-se a uma identidade específica e faz uma declaração sobre um atributo relacionado a essa identidade. Portanto, sua carteira de motorista possui identificadores (nome, data de nascimento, endereço), mas também é o atestado sobre seu direito legal de dirigir. +Atestados são diferentes de identificadores. Um atestado _contém_ identificadores para fazer referência a uma identidade específica e faz uma reivindicação sobre um atributo relacionado a essa identidade. Portanto, sua carteira de motorista possui identificadores (nome, data de nascimento, endereço), mas também é o atestado sobre seu direito legal de dirigir. ### O que são identificadores descentralizados? {#what-are-decentralized-identifiers} Identificadores tradicionais como seu nome legal ou endereço de e-mail dependem de terceiros – governos e provedores de e-mail. Os identificadores descentralizados (DIDs) são diferentes — eles não são emitidos, gerenciados ou controlados por qualquer entidade central. -Os identificadores descentralizados são emitidos, mantidos e controlados por indivíduos. Uma [conta Ethereum](/glossary/#account) é um exemplo de identificador descentralizado. Você pode criar quantas contas quiser sem permissão de ninguém e sem a necessidade de armazená-las em um registro central. +Os identificadores descentralizados são emitidos, mantidos e controlados por indivíduos. Uma [conta Ethereum](/glossary/#account) é um exemplo de um identificador descentralizado. Você pode criar quantas contas quiser sem permissão de ninguém e sem a necessidade de armazená-las em um registro central. -Os identificadores descentralizados são armazenados em registros distribuídos ([blockchains](/glossary/#blockchain)) ou [redes ponto a ponto](/glossary/#peer-to-peer-network). Isso torna os DIDs [globalmente exclusivos, solucionáveis com alta disponibilidade e verificáveis criptograficamente](https://w3c-ccg.github.io/did-primer/). Um identificador descentralizado pode ser associado a diferentes entidades, incluindo pessoas, organizações ou instituições governamentais. +Identificadores descentralizados são armazenados em livros-razão distribuídos ([blockchains](/glossary/#blockchain)) ou [redes ponto a ponto](/glossary/#peer-to-peer-network). Isso torna os DIDs [globalmente únicos, solucionáveis com alta disponibilidade e criptograficamente verificáveis](https://w3c-ccg.github.io/did-primer/). Um identificador descentralizado pode ser associado a diferentes entidades, incluindo pessoas, organizações ou instituições governamentais. ## O que torna os identificadores descentralizados possíveis? {#what-makes-decentralized-identifiers-possible} -### 1. Criptografia de chave pública {#public-key-cryptography} +### 1. Criptografia de Chave Pública {#public-key-cryptography} -A criptografia de chave pública é uma medida de segurança de informações que gera uma [chave pública](/glossary/#public-key) e uma [chave privada](/glossary/#private-key) para uma entidade. A [criptografia de chave pública](/glossary/#cryptography) é usada em redes de blockchain para autenticar identidades de usuários e comprovar a propriedade de ativos digitais. +A criptografia de chave pública é uma medida de segurança da informação que gera uma [chave pública](/glossary/#public-key) e uma [chave privada](/glossary/#private-key) para uma entidade. A [criptografia](/glossary/#cryptography) de chave pública é usada em redes blockchain para autenticar identidades de usuários e provar a propriedade de ativos digitais. -Alguns identificadores descentralizados, como uma conta Ethereum, possuem chaves públicas e privadas. A chave pública identifica o controlador da conta, enquanto as chaves privadas podem assinar e descriptografar mensagens para essa conta. A criptografia de chave pública fornece as provas necessárias para autenticar entidades e evitar a falsificação de identidade e o uso de identidades falsas, usando [assinaturas criptográficas](https://andersbrownworth.com/blockchain/public-private-keys/) para verificar todas as reclamações. +Alguns identificadores descentralizados, como uma conta Ethereum, possuem chaves públicas e privadas. A chave pública identifica o controlador da conta, enquanto as chaves privadas podem assinar e descriptografar mensagens para essa conta. A criptografia de chave pública fornece as provas necessárias para autenticar entidades e evitar a falsificação e o uso de identidades falsas, usando [assinaturas criptográficas](https://andersbrownworth.com/blockchain/public-private-keys/) para verificar todas as reivindicações. ### 2. Armazenamentos de dados descentralizados {#decentralized-datastores} @@ -103,11 +129,11 @@ Um blockchain serve como um registro de dados verificável: um repositório de i Se alguém precisar confirmar a validade de um identificador descentralizado, ele poderá procurar a chave pública associada no blockchain. Isso difere dos identificadores tradicionais que exigem autenticação de terceiros. -## Como os identificadores e atestados descentralizados permitem a identidade descentralizada? {#how-decentralized-identifiers-and-attestations-enable-decentralized-identity} +## Como os identificadores e atestados descentralizados permitem a identidade descentralizada? Como os identificadores e atestados descentralizados viabilizam a identidade descentralizada? {#how-decentralized-identifiers-and-attestations-enable-decentralized-identity} A identidade descentralizada é a ideia de que as informações relacionadas à identidade devem ser autocontroladas, privadas e portáteis, com identificadores descentralizados e atestações sendo os principais blocos de construção. -No contexto da identidade descentralizada, os atestados (também conhecidos como [Credenciais verificáveis](https://www.w3.org/TR/vc-data-model/)) são declarações à prova de adulteração e criptograficamente verificáveis feitas pelo emissor. Cada atestado ou credencial verificável de uma entidade (por exemplo, uma organização) está associada ao seu DID. +No contexto da identidade descentralizada, atestados (também conhecidos como [Credenciais Verificáveis](https://www.w3.org/TR/vc-data-model/)) são reivindicações à prova de adulteração e criptograficamente verificáveis feitas pelo emissor. Cada atestado ou credencial verificável de uma entidade (por exemplo, uma organização) está associada ao seu DID. Como os DIDs são armazenados no blockchain, qualquer pessoa pode verificar a validade de um atestado verificando o DID do emissor no Ethereum. Essencialmente, o blockchain Ethereum atua como um diretório global que permite a verificação de DIDs associados a determinadas entidades. @@ -115,15 +141,15 @@ Os identificadores descentralizados são o motivo de os atestados serem autocont Os identificadores descentralizados também são cruciais para proteger a privacidade das informações pessoais por meio da identidade descentralizada. Por exemplo, se um indivíduo apresentar prova de um atestado (carteira de motorista), a parte verificadora não precisa verificar a validade das informações na prova. Em vez disso, o verificador precisa apenas de garantias criptográficas da autenticidade do atestado e da identidade da organização emissora para determinar se a prova é válida. -## Categorias de atestados na identidade descentralizada {#types-of-attestations-in-decentralized-identity} +## Tipos de atestados na identidade descentralizada {#types-of-attestations-in-decentralized-identity} Como as informações de atestado são armazenadas e recuperadas em um ecossistema de identidade baseado em Ethereum difere do gerenciamento de identidade tradicional. Aqui está uma visão geral das várias abordagens para emitir, armazenar e verificar atestados em sistemas de identidade descentralizados: -### Atestados Off-Chain {#off-chain-attestations} +### Atestados off-chain {#offchain-attestations} -Uma das preocupações com o armazenamento de certificados na cadeia é que eles podem conter informações que os usuários queiram manter privadas. A natureza pública da blockchain Ethereum a torna não atraente armazenar tais atestações. +Uma preocupação com o armazenamento de atestados on-chain é que eles podem conter informações que os indivíduos querem manter privadas. A natureza pública da blockchain Ethereum a torna não atraente armazenar tais atestações. -A solução é emitir atestados, mantidos por usuários off-chain em carteiras digitais, mas assinados com o DID do emissor armazenado on-chain. Esses atestados são codificados como [JSON Web Tokens](https://en.wikipedia.org/wiki/JSON_Web_Token) e contêm a assinatura digital do emissor, que permite a verificação fácil de reivindicações off-chain. +A solução é emitir atestados, mantidos por usuários off-chain em carteiras digitais, mas assinados com o DID do emissor armazenado on-chain. Esses atestados são codificados como [JSON Web Tokens](https://en.wikipedia.org/wiki/JSON_Web_Token) e contêm a assinatura digital do emissor, o que permite a verificação fácil de reivindicações off-chain. Aqui está um cenário hipotético para explicar os atestados off-chain: @@ -133,59 +159,60 @@ Aqui está um cenário hipotético para explicar os atestados off-chain: ### Atestados off-chain com acesso persistente {#offchain-attestations-with-persistent-access} -Sob esse arranjo, os atestados são transformados em arquivos JSON e armazenados off-chain (idealmente em uma plataforma de [armazenamento em nuvem descentralizado](/developers/docs/storage/), como IPFS ou Swarm). Entretanto, um [hash](/glossary/#hash) do arquivo JSON é armazenado on-chain e vinculado a um DID por meio de um registro on-chain. O DID associado pode ser o do emissor do atestado ou o do destinatário. +Nesse arranjo, os atestados são transformados em arquivos JSON e armazenados off-chain (idealmente em uma plataforma de [armazenamento em nuvem descentralizado](/developers/docs/storage/), como IPFS ou Swarm). No entanto, um [hash](/glossary/#hash) do arquivo JSON é armazenado on-chain e vinculado a um DID por meio de um registro on-chain. O DID associado pode ser o do emissor do atestado ou o do destinatário. Essa abordagem permite que os atestados obtenham persistência baseada em blockchain, mantendo as informações de declarações criptografadas e verificáveis. Ele também permite a divulgação seletiva, visto que o titular da chave privada pode descriptografar as informações. ### Atestados on-chain {#onchain-attestations} -Os atestados on-chain são mantidos em [contratos inteligentes](/glossary/#smart-contract) na blockchain Ethereum. O contrato inteligente (agindo como um registro) mapeará um atestado para um identificador descentralizado on-chain correspondente (uma chave pública). +Atestados on-chain são mantidos em [contratos inteligentes](/glossary/#smart-contract) na blockchain Ethereum. O contrato inteligente (atuando como um registro) mapeará um atestado para o identificador descentralizado on-chain correspondente (uma chave pública). -Aqui está um exemplo para mostrar como os atestados on-chain podem funcionar na prática: +Aqui está um exemplo para mostrar como os atestados on-chain deveriam funcionar na prática: 1. Uma empresa (XYZ Corp) planeja vender ações de propriedade usando um contrato inteligente, mas quer apenas compradores que concluíram uma verificação de fundo. -2. A empresa XYZ pode fazer com que a empresa realize verificações de fundo para emitir atestados on-chain no Ethereum. Este atestado certifica que um indivíduo passou na verificação de fundo sem expor nenhuma informação pessoal. +2. A empresa XYZ pode fazer com que a empresa realize verificações de fundo para emitir atestados onchain no Ethereum. Este atestado certifica que um indivíduo passou na verificação de fundo sem expor nenhuma informação pessoal. 3. O contrato inteligente de venda de ações pode verificar no contrato de registro as identidades dos compradores selecionados, possibilitando que o contrato inteligente determine quem tem permissão para comprar ações ou não. ### Tokens Soulbound e identidade {#soulbound} -[Tokens Soulbound](https://vitalik.eth.limo/general/2022/01/26/soulbound.html) ([NFTs intransferíveis](/glossary/#nft)) podem ser usados para coletar informações exclusivas de uma carteira específica. Isso cria efetivamente uma identidade única on-chain vinculada a um endereço Ethereum específico que pode incluir tokens que representam conquistas (por exemplo, terminar algum curso on-line específico ou passar uma pontuação mínima em um jogo) ou participação da comunidade. +[Tokens Soulbound](https://vitalik.eth.limo/general/2022/01/26/soulbound.html) ([NFTs não transferíveis](/glossary/#nft)) podem ser usados para coletar informações exclusivas de uma carteira específica. Isso cria efetivamente uma identidade única on-chain vinculada a um endereço Ethereum específico, que pode incluir tokens que representam conquistas (por exemplo, concluir um curso online específico ou atingir uma pontuação limite em um jogo) ou participação na comunidade. -## Use identidade descentralizada {#use-decentralized-identity} +## Use a identidade descentralizada {#use-decentralized-identity} Existem muitos projetos ambiciosos usando Ethereum como base para soluções de identidade descentralizadas: -- **[Nomes de Serviço Ethereum (ENS)](https://ens.domains/)** - _ Um sistema de nomes descentralizado para identificadores legíveis por máquina on-chain, como endereços de carteira Ethereum, hashes de conteúdo e metadados._ -- **[SpruceID](https://www.spruceid.com/)** - _Um projeto de identidade descentralizada que permite aos usuários controlar a identidade digital com contas Ethereum e perfis ENS em vez de depender de serviços de terceiros._ -- **[Serviço de Atestação do Ethereum (EAS)](https://attest.sh/)** - _ Um ledger/protocolo descentralizado para fazer atestações on-chain ou off-chain sobre qualquer coisa._ -- **[Prova de Humanidade](https://www.proofofhumanity.id)** - _Prova de Humanidade (ou PoH) é um sistema de verificação de identidade social construído no Ethereum._ -- **[BrightID](https://www.brightid.org/)** - _Uma descentralizada, rede de identidade social de código aberto que busca reformar a verificação de identidade por meio da criação e análise de um grafo social._ -- **[walt.id](https://walt.id)** — _Identidade descentralizada de código aberto e infraestrutura de carteira que permite que desenvolvedores e organizações usem identidade autosoberana e NFTs/SBTs._ -- **[Veramo](https://veramo.io/)** - _Uma estrutura JavaScript que facilita o uso de dados criptograficamente verificáveis nos próprios aplicativos por qualquer pessoa._ +- **[Ethereum Name Service (ENS)](https://ens.domains/)** - _Um sistema de nomes descentralizado para identificadores on-chain legíveis por máquina, como endereços de carteira Ethereum, hashes de conteúdo e metadados._ +- **[Entrar com Ethereum (SIWE)](https://siwe.xyz/)** - _Padrão aberto para autenticação com contas Ethereum._ +- **[SpruceID](https://www.spruceid.com/)** - _Um projeto de identidade descentralizada que permite aos usuários controlar a identidade digital com contas Ethereum e perfis ENS, em vez de depender de serviços de terceiros._ +- **[Serviço de Atestado Ethereum (EAS)](https://attest.org/)** - _Um livro-razão/protocolo descentralizado para fazer atestados on-chain ou off-chain sobre qualquer coisa._ +- **[Prova de Humanidade](https://www.proofofhumanity.id)** - _A Prova de Humanidade (ou PoH) é um sistema de verificação de identidade social construído em Ethereum._ +- **[BrightID](https://www.brightid.org/)** - _Uma rede de identidade social descentralizada e de código aberto que busca reformar a verificação de identidade por meio da criação e análise de um grafo social._ +- **[walt.id](https://walt.id)** — _Infraestrutura de identidade descentralizada e de carteira de código aberto que permite que desenvolvedores e organizações aproveitem a identidade auto-soberana e NFTs/SBTs._ +- **[Veramo](https://veramo.io/)** - _Uma estrutura JavaScript que facilita para qualquer pessoa o uso de dados criptograficamente verificáveis em seus aplicativos._ ## Leitura adicional {#further-reading} ### Artigos {#articles} -- [Casos de uso de blockchain: Blockchain em identidade digital](https://consensys.net/blockchain-use-cases/digital-identity/) — _ConsenSys_ -- [O que é Ethereum ERC725? Gerenciamento de identidade autossoberana no Blockchain](https://cryptoslate.com/what-is-erc725-self-sovereign-identity-management-on-the-blockchain/) — _Sam Town_ -- [Como o Blockchain pode resolver o problema da identidade digital](https://time.com/6142810/proof-of-humanity/) — _Andrew R. Comida_ -- [O que é identidade descentralizada e por que você deve se importar?](https://web3.hashnode.com/what-is-decentralized-identity) — _Emmanuel Awosika_ -- [Introdução à identidade descentralizada](https://walt.id/white-paper/digital-identity) — _Dominik Beron_ +- [Casos de Uso de Blockchain: Blockchain na Identidade Digital](https://consensys.net/blockchain-use-cases/digital-identity/) — _ConsenSys_ +- [O que é Ethereum ERC725? [Gerenciamento de Identidade Auto-Soberana na Blockchain](https://cryptoslate.com/what-is-erc725-self-sovereign-identity-management-on-the-blockchain/) — _Sam Town_ +- [Como a Blockchain Poderia Resolver o Problema da Identidade Digital](https://time.com/6142810/proof-of-humanity/) — _Andrew R. Chow_ +- [O Que É Identidade Descentralizada e Por Que Você Deveria se Importar?](https://web3.hashnode.com/what-is-decentralized-identity) — _Emmanuel Awosika_ +- [Introdução à Identidade Descentralizada](https://walt.id/white-paper/digital-identity) — _Dominik Beron_ ### Vídeos {#videos} -- [Identidade descentralizada (bônus sessão de transmissão ao vivo)](https://www.youtube.com/watch?v=ySHNB1za_SE&t=539s) — _Um ótimo vídeo explicativo sobre identidade descentralizada por Andreas Antoniopolitas_ -- [Faça login com o Ethereum e identidade descentralizada com Ceramic, IDX, React e 3ID Connect](https://www.youtube.com/watch?v=t9gWZYJxk7c) — _Tutorial do YouTube sobre como criar um sistema de gerenciamento de identidade para criar, ler e atualizar o perfil de um usuário usando sua carteira Ethereum por Nader Dabit_ -- [BrightID - Identidade descentralizada no Ethereum](https://www.youtube.com/watch?v=D3DbMFYGRoM) — _Episódio de podcast sem banco discutindo o BrightID, uma solução de identidade descentralizada para Ethereum_ -- [A Internet off-chain: identidade descentralizada & Credenciais verificáveis](https://www.youtube.com/watch?v=EZ_Bb6j87mg) — apresentação EthDenver 2022 por Evin McMullen -- [Credenciais verificáveis explicadas](https://www.youtube.com/watch?v=ce1IdSr-Kig) - vídeo explicativo do YouTube com demonstração de Tamino Baumann +- [Identidade Descentralizada (Sessão Bônus de Transmissão ao Vivo)](https://www.youtube.com/watch?v=ySHNB1za_SE&t=539s) — _Um ótimo vídeo explicativo sobre identidade descentralizada por Andreas Antonopoulos_ +- [Entrar com Ethereum e Identidade Descentralizada com Ceramic, IDX, React e 3ID Connect](https://www.youtube.com/watch?v=t9gWZYJxk7c) — _Tutorial do YouTube sobre como construir um sistema de gerenciamento de identidade para criar, ler e atualizar o perfil de um usuário usando sua carteira Ethereum por Nader Dabit_ +- [BrightID - Identidade Descentralizada no Ethereum](https://www.youtube.com/watch?v=D3DbMFYGRoM) — _Episódio do podcast Bankless discutindo o BrightID, uma solução de identidade descentralizada para o Ethereum_ +- [A Internet Off-chain: Identidade Descentralizada e Credenciais Verificáveis](https://www.youtube.com/watch?v=EZ_Bb6j87mg) — Apresentação de Evin McMullen na EthDenver 2022 +- [Credenciais Verificáveis Explicadas](https://www.youtube.com/watch?v=ce1IdSr-Kig) - Vídeo explicativo do YouTube com demonstração por Tamino Baumann ### Comunidades {#communities} -- [Aliança ERC-725 no GitHub](https://github.com/erc725alliance) — _Apoiadores do padrão ERC725 para gerenciamento de identidade no blockchain Ethereum_ -- [Servidor do Discord do EthID](https://discord.com/invite/ZUyG3mSXFD) — _Comunidade para entusiastas e desenvolvedores que trabalham no Entrar com Ethereum_ -- [Veramo Labs](https://discord.gg/sYBUXpACh4) — _Uma comunidade de desenvolvedores contribuindo para criar um framework de dados verificáveis para aplicativos_ -- [walt.id](https://discord.com/invite/AW8AgqJthZ) — _ Uma comunidade de desenvolvedores e construtores trabalhando em casos de uso de identidade descentralizada em vários setores_ +- [Aliança ERC-725 no GitHub](https://github.com/erc725alliance) — _Apoiadores do padrão ERC725 para gerenciamento de identidade na blockchain Ethereum_ +- [Servidor do Discord EthID](https://discord.com/invite/ZUyG3mSXFD) — _Comunidade para entusiastas e desenvolvedores que trabalham com o Entrar com Ethereum e o Ethereum Follow Protocol_ +- [Veramo Labs](https://discord.gg/sYBUXpACh4) — _Uma comunidade de desenvolvedores contribuindo para a construção de uma estrutura para dados verificáveis para aplicativos_ +- [walt.id](https://discord.com/invite/AW8AgqJthZ) — _Uma comunidade de desenvolvedores e construtores que trabalham em casos de uso de identidade descentralizada em vários setores_ diff --git a/public/content/translations/pt-br/defi/index.md b/public/content/translations/pt-br/defi/index.md index 78293634eff..1899e1f6d4e 100644 --- a/public/content/translations/pt-br/defi/index.md +++ b/public/content/translations/pt-br/defi/index.md @@ -1,6 +1,7 @@ --- -title: Finanças descentralizadas (DeFi) -description: Uma visão geral do DeFi na Ethereum +title: "Finanças descentralizadas (DeFi)" +metaTitle: "O que é DeFi? | O benefício das Finanças descentralizadas" +description: "Uma visão geral do DeFi na Ethereum" lang: pt-br template: use-cases emoji: ":money_with_wings:" @@ -8,8 +9,8 @@ image: /images/use-cases/defi.png alt: Um logotipo Eth feito de blocos de lego. sidebarDepth: 2 summaryPoint1: Uma alternativa global e aberta ao sistema financeiro atual. -summaryPoint2: Produtos que deixam você pedir emprestado, economizar, investir, comercializar e muito mais. -summaryPoint3: Com base na tecnologia de código aberto com a qual qualquer pessoa pode programar. +summaryPoint2: "Produtos que deixam você pedir emprestado, economizar, investir, comercializar e muito mais." +summaryPoint3: "Com base na tecnologia de código aberto com a qual qualquer pessoa pode programar." --- A DeFi é um sistema financeiro aberto e global criado para a era da Internet – uma alternativa a um sistema que não é transparente, controlado rigorosamente e mantido por infraestruturas e processos com décadas de existência. Oferece controle e visibilidade sobre o seu dinheiro. Ela fornece exposição aos mercados globais e alternativas a sua moeda local ou opções bancárias. Os produtos DeFi oferecem serviços financeiros a qualquer pessoa com uma conexão com a Internet e são em grande parte de propriedade e mantidos por seus usuários. Até agora, dezenas de bilhões de dólares de criptos foram transacionados através de aplicativos DeFi e seguem crescendo todos os dias. @@ -31,44 +32,44 @@ Uma das melhores maneiras de avaliar o potencial das DeFi é compreender os prob - A falta de acesso a serviços financeiros pode impedir que você seja pago. - Uma cobrança oculta dos serviços financeiros são os seus dados pessoais. - Os governos e as instituições centralizadas podem fechar os mercados de forma arbitrária. -- Os horários de negociação geralmente são limitados ao horário comercial de um fuso horário específico. +- O horário de negociação geralmente é limitado ao horário comercial de um fuso horário específico. - Transferências de dinheiro podem levar dias devido a processos humanos internos. - Há um prêmio para operar os serviços financeiros porque as instituições intermediárias cobram a parte delas. ### Uma comparação {#defi-comparison} -| DeFi | Finanças tradicionais | -| ----------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Você detém seu dinheiro. | Seu dinheiro é controlado por empresas. | -| Você controla a destinação de seu dinheiro e como será gasto. | Você precisa confiar que as empresas não administrarão os seus fundos indevidamente, como, por exemplo, fazer empréstimos a tomadores de risco. | -| Transferências de dinheiro acontecem em minutos. | Os pagamentos podem levar dias devido a processos manuais. | -| A transação é anônima. | A operação financeira é fortemente ligada à sua identidade. | -| A DeFi é aberta a qualquer pessoa. | Você deve se cadastrar para usar os serviços financeiros. | -| Os mercados estão sempre abertos. | Mercados fecham porque os empregados cumprem horários. | +| DeFi | Finanças tradicionais | +| --------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Você detém seu dinheiro. | Seu dinheiro é controlado por empresas. | +| Você controla a destinação de seu dinheiro e como será gasto. | Você precisa confiar que as empresas não administrarão os seus fundos indevidamente, como, por exemplo, fazer empréstimos a tomadores de risco. | +| Transferências de dinheiro acontecem em minutos. | Os pagamentos podem levar dias devido a processos manuais. | +| A transação é anônima. | A operação financeira é fortemente ligada à sua identidade. | +| A DeFi é aberta a qualquer pessoa. | Você deve se cadastrar para usar os serviços financeiros. | +| Os mercados estão sempre abertos. | Mercados fecham porque os empregados cumprem horários. | | Construído com base na transparência – qualquer pessoa pode ver os dados de um produto e inspecionar como o sistema funciona. | As instituições financeiras são livros fechados: não se pode pedir para ver o histórico de empréstimos, um registro dos seus ativos gerenciados, e assim por diante. | - Ver aplicativos DeFi + Explorar aplicativos DeFi ## Tudo começou com o Bitcoin... {#bitcoin} O Bitcoin, de muitas maneiras, foi a primeira aplicação DeFi. O Bitcoin permite que você realmente tenha e controle valores e os envie para qualquer lugar ao redor do mundo. Isso é feito oferecendo uma maneira para que um grande número de pessoas, que não confiam umas nas outras, concordem com um livro de contas sem a necessidade de um intermediário confiável. O Bitcoin é aberto a qualquer um e ninguém tem autoridade para alterar suas regras. As regras do Bitcoin, como sua escassez e acessibilidade, estão incorporadas na tecnologia. Não funciona como nas finanças tradicionais, em que os governos podem imprimir moeda que desvaloriza as suas economias e as empresas podem fechar os mercados. -Ethereum baseia-se nisso. Como o Bitcoin, as regras não mudam por você, e todos têm acesso. Mas ele também torna esse dinheiro digital programável, usando [contratos inteligentes](/glossary/#smart-contract), para que você possa fazer mais do que guardar e enviar valores. +Ethereum baseia-se nisso. Como o Bitcoin, as regras não mudam por você, e todos têm acesso. Mas também torna esse dinheiro digital programável, usando [contratos inteligentes](/glossary/#smart-contract), para que você possa ir além de armazenar e enviar valores. ## Dinheiro programável {#programmable-money} -Isso soa estranho... "Por que eu gostaria de programar meu dinheiro"? No entanto, esta é mais uma característica padrão dos tokens no Ethereum. Qualquer um pode programar a lógica em pagamentos. Assim, você pode ter o controle e a segurança do Bitcoin somados aos serviços fornecidos por instituições financeiras. Isso permite fazer coisas com criptomoedas que você não poderia fazer com o Bitcoin, tais como emprestar e tomar empréstimos, agendar pagamentos, investir em fundos de índices e mais. +Isso soa estranho... "por que eu iria querer programar meu dinheiro"? No entanto, esta é mais uma característica padrão dos tokens no Ethereum. Qualquer um pode programar a lógica em pagamentos. Assim, você pode ter o controle e a segurança do Bitcoin somados aos serviços fornecidos por instituições financeiras. Isso permite fazer coisas com criptomoedas que você não poderia fazer com o Bitcoin, tais como emprestar e tomar empréstimos, agendar pagamentos, investir em fundos de índices e mais. - +
Explore nossas sugestões de aplicativos DeFi para iniciar se você é novo no Ethereum.
- Ver aplicativos DeFi + Explorar aplicativos DeFi
@@ -77,23 +78,23 @@ Isso soa estranho... "Por que eu gostaria de programar meu dinheiro"? No entanto Há uma alternativa descentralizada para a maioria dos serviços financeiros. Mas o Ethereum também cria oportunidades para a criação de produtos financeiros completamente novos. Esta lista está em constante crescimento. -- [Envie dinheiro para qualquer lugar do mundo](#send-money) -- [Pagamentos em tempo real ao redor do mundo](#stream-money) -- [Acesso a moedas estáveis](#stablecoins) -- [Empréstimos com garantia](#lending) -- [Empréstimos sem garantias](#flash-loans) -- [Poupança com criptomoedas](#saving) +- [Enviar dinheiro para o mundo todo](#send-money) +- [Fazer streaming de dinheiro pelo mundo](#stream-money) +- [Acessar moedas estáveis](#stablecoins) +- [Pegar fundos emprestados com garantia](#lending) +- [Pegar fundos emprestados sem garantia](#flash-loans) +- [Começar uma poupança em cripto](#saving) - [Negociar tokens](#swaps) -- [Aumente seu portfólio](#investing) -- [Financie seus projetos](#crowdfunding) -- [Compra de seguros](#insurance) -- [Gerenciamento de portfolio](#aggregators) +- [Aumentar seu portfólio](#investing) +- [Financiar suas ideias](#crowdfunding) +- [Contratar seguro](#insurance) +- [Gerenciar seu portfólio](#aggregators) -### Envie dinheiro ao redor do mundo rapidamente {#send-money} +### Envie dinheiro para o mundo todo rapidamente {#send-money} -Como um blockchain, o Ethereum foi concebido para o envio de transações de forma segura e de modo global. Assim como o Bitcoin, o Ethereum torna o envio de dinheiro ao redor do mundo tão fácil quanto enviar um e-mail. Basta digitar o [nome ENS](/glossary/#ens) do seu beneficiário, por exemplo, bob.eth, ou o endereço de conta da respectiva carteira e seu pagamento será enviado em minutos, normalmente. Para enviar ou receber pagamentos, você precisará de uma [carteira](/wallets/). +Como um blockchain, o Ethereum foi concebido para o envio de transações de forma segura e de modo global. Assim como o Bitcoin, o Ethereum torna o envio de dinheiro ao redor do mundo tão fácil quanto enviar um e-mail. Basta inserir o [nome ENS](/glossary/#ens) do destinatário (como bob.eth) ou o endereço da conta dele na sua carteira e seu pagamento irá diretamente para ele em minutos (geralmente). Para enviar ou receber pagamentos, você precisará de uma [carteira](/wallets/). Ver dapps de pagamento @@ -103,7 +104,7 @@ Como um blockchain, o Ethereum foi concebido para o envio de transações de for Você também pode transferir dinheiro através da Ethereum. Isso permite que você pague imediatamente o salário de alguém, dando a essa pessoa acesso ao valor devido sempre que preciso. Ou alugue algo de forma imediata, como um guarda-volume ou uma moto elétrica. -E se você não quiser enviar ou transferir [ETH](/glossary/#ether) devido à flutuação de valor que pode sofrer, existem outras moedas alternativas no Ethereum: as [stablecoins](/glossary/#stablecoin). +E se você não quiser enviar ou fazer streaming de [ETH](/glossary/#ether) por causa do quanto seu valor pode mudar, existem moedas alternativas no Ethereum: [stablecoins](/glossary/#stablecoin). @@ -114,12 +115,12 @@ A volatilidade das criptomoedas é um problema para muitos produtos financeiros Moedas como Dai ou USDC têm um valor que não superam alguns centavos de dólar. Isso as torna perfeitas para rendimentos ou varejo. Muitas pessoas na América Latina utilizaram as stablecoins como forma de proteger suas poupanças, em tempos de grande incerteza com as moedas emitidas pelos governos. - Mais sobre moedas estáveis + Mais em moedas estáveis -### Empréstimos {#lending} +### Tomar empréstimos {#lending} Empréstimos de recursos de fornecedores descentralizados se dão de duas formas principais. @@ -132,7 +133,7 @@ Empréstimos de recursos de fornecedores descentralizados se dão de duas formas Há diversas vantagens em usar um financiador descentralizado... -#### Empréstimos com privacidade {#borrowing-privacy} +#### Tomar empréstimos com privacidade {#borrowing-privacy} Hoje, pegar dinheiro emprestado ou emprestar gira em torno dos indivíduos envolvidos. Os bancos precisam saber se você terá condições de pagar um empréstimo antes de concedê-lo. @@ -142,13 +143,13 @@ Isso permite que você tome empréstimo de dinheiro sem checagem de crédito ou #### Acesso a fundos globais {#access-global-funds} -Quando você usa um mutuante descentralizado, você tem acesso a fundos depositados de todo o mundo, não apenas os fundos em custódia de seu banco ou instituição escolhida. Isto torna os empréstimos mais acessíveis e melhora as taxas de juro. +Quando você usa um mutuante descentralizado, você tem acesso a fundos depositados de todo o mundo, não apenas os fundos em custódia de seu banco ou instituição escolhida. Isso torna os empréstimos mais acessíveis e melhora as taxas de juros. -#### Eficiência tributária {#tax-efficiencies} +#### Eficiência fiscal {#tax-efficiencies} Pedir empréstimo pode dar a você acesso aos fundos de que você precisa sem precisar vender seus ETHs (um evento tributável). Em vez disso, você pode usar ETH como garantia colateral de um empréstimo em stablecoin. Isso dá a você acesso ao fluxo de caixa de que você precisa sem abrir mão de seus ETHs. Stablecoins são tokens muito melhores quando você precisa de dinheiro, já que elas não oscilam tanto quanto o ETH. [Mais sobre stablecoins](#stablecoins) -#### Empréstimos rápidos {#flash-loans} +#### Empréstimos-relâmpago {#flash-loans} Empréstimos rápidos são uma forma mais experimental de empréstimos descentralizados que permite que você peça empréstimo sem garantia ou sem fornecer qualquer informação pessoal. @@ -172,27 +173,27 @@ Se o estoque da exchange B cair de repente e o usuário não conseguir comprar o Para ser capaz de fazer o exemplo acima no mundo financeiro tradicional, você precisaria de uma quantidade enorme de dinheiro. Estas estratégias de fazer dinheiro só são acessíveis aos que já possuem economias. Os empréstimos rápidos são um exemplo do futuro em que possuir dinheiro não é necessariamente uma condição prévia para se fazer dinheiro. - Mais sobre empréstimos rápidos + Mais sobre empréstimos-relâmpago -### Comece a poupar com criptomoedas {#saving} +### Comece a poupar com cripto {#saving} #### Empréstimos {#lending} Você pode ganhar juros sobre suas criptomoedas emprestando-as e vendo seus fundos crescerem em tempo real. No momento, as taxas de juros são muito mais altas do que as que você pode obter no seu banco local (se você tiver sorte o suficiente para ter acesso a um). Aqui está um exemplo: -- Você empresta 100 Dai, uma [stablecoin](/stablecoins/), a um produto como Aave. +- Você empresta seus 100 Dai, uma [stablecoin](/stablecoins/), para um produto como o Aave. - Você recebe 100 Aave Dai (aDai) que é um token que representa seus Dai emprestados. -- Seu aDai aumentará com base nas taxas de juros e você poderá ver o saldo crescendo na sua carteira. Dependendo da [APR](/glossary/#apr), o saldo da sua carteira será algo como 100.1234 depois de alguns dias ou até horas! +- Seu aDai aumentará com base nas taxas de juros e você poderá ver o saldo crescendo na sua carteira. Dependendo da [APR](/glossary/#apr), o saldo da sua carteira mostrará algo como 100.1234 após alguns dias ou mesmo horas! - Você pode retirar uma quantidade de Dai regular, igual ao seu saldo em aDai, a qualquer momento. Ver dapps de empréstimos -#### Loterias sem perda {#no-loss-lotteries} +#### Loterias sem perdas {#no-loss-lotteries} Loterias sem perda como a PoolTogether são uma divertida e inovadora maneira de economizar dinheiro. @@ -210,19 +211,19 @@ O dinheiro acumulado para premiação é gerado por todos os juros gerados pelo -### Negociar tokens {#swaps} +### Trocar tokens {#swaps} Existem milhares de tokens no Ethereum. Exchanges descentralizadas (DEXs) permitem que você opere diferentes tokens sempre que quiser. Você nunca entrega o controle de seus ativos. Isso é como usar uma exchange quando você visita um país diferente. Mas a versão de DeFi nunca fecha. Os mercados funcionam de maneira ininterrupta e a tecnologia garante que sempre haverá alguém disposto a fazer negociações. Por exemplo, se você quiser usar a loteria sem perda PoolTogether (descrita acima), você precisará de um token como Dai ou USDC. Estas DEXs permitem que você troque seus ETH por esses tokens e reverta novamente quando terminar. - Exibir exchanges de token + Ver corretoras de tokens -### Negociações avançadas {#trading} +### Trading avançado {#trading} Existem opções mais avançadas para traders que gostam de um pouco mais de controle. Limitar ordens, contratos futuros sem vencimento, trading alavancado e muito mais é possível. Com negociações descentralizadas você obtém acesso à liquidez global, o mercado nunca fecha e você está sempre no controle de seus ativos. @@ -234,7 +235,7 @@ Quando você usa uma exchange centralizada, tem que depositar seus ativos antes -### Aumente seu portfolio {#investing} +### Aumente seu portfólio {#investing} Existem produtos de gestão de fundos na Ethereum que tentarão aumentar a sua carteira com base em uma estratégia à sua escolha. Isto é automático, aberto a todos, e não precisa de um gerente humano pegando uma fatia de seus lucros. @@ -255,7 +256,7 @@ Ethereum é uma plataforma ideal para financiamento colaborativo: - Os captadores de recursos podem criar reembolsos automáticos se, por exemplo, houver um prazo específico e um montante mínimo que não seja cumprido. - Ver dapps de captação de recursos + Ver dapps de financiamento coletivo #### Financiamento quadrático {#quadratic-funding} @@ -277,11 +278,11 @@ Isso significa que o Projeto A com suas 100 doações de 1 dólar poderia acabar -### Seguros {#insurance} +### Seguro {#insurance} Seguros descentralizados visam tornar o seguro mais barato, mais rápido para pagar e mais transparente. Com mais automação, a cobertura é mais acessível e os pagamentos são muito mais rápidos. Os dados utilizados para decidir sobre a sua reivindicação são completamente transparentes. -Os produtos Ethereum, como qualquer software, estão propensos a bugs e exploits. Então, atualmente, muitos produtos na área de seguros visam proteger seus usuários contra a perda de fundos. Entretanto, há projetos que estão começando a criar cobertura para tudo o que a vida pode nos oferecer. Um bom exemplo disto é a cobertura para o cultivo do Etherisc, que visa [proteger os pequenos agricultores do Quênia contra secas e inundações](https://blog.etherisc.com/etherisc-teams-up-with-chainlink-to-deliver-crop-insurance-in-kenya-137e433c29dc). Um seguro descentralizado pode proporcionar cobertura mais barata aos agricultores que são frequentemente deixados de fora do seguro tradicional. +Os produtos Ethereum, como qualquer software, estão propensos a bugs e exploits. Então, atualmente, muitos produtos na área de seguros visam proteger seus usuários contra a perda de fundos. Entretanto, há projetos que estão começando a criar cobertura para tudo o que a vida pode nos oferecer. Um bom exemplo disso é a cobertura de safra da Etherisc, que visa [proteger pequenos agricultores no Quênia contra secas e inundações](https://blog.etherisc.com/etherisc-teams-up-with-chainlink-to-deliver-crop-insurance-in-kenya-137e433c29dc). Um seguro descentralizado pode proporcionar cobertura mais barata aos agricultores que são frequentemente deixados de fora do seguro tradicional. Ver dapps de seguros @@ -289,12 +290,12 @@ Os produtos Ethereum, como qualquer software, estão propensos a bugs e exploits -### Agregadores e gerenciadores de portfolio {#aggregators} +### Agregadores e gerenciadores de portfólio {#aggregators} Com tanta coisa acontecendo, você precisará de uma maneira de acompanhar todos os seus investimentos, empréstimos e operações. Há uma série de produtos que permitem coordenar todas as atividades DeFi de um só lugar. Esta é a beleza da arquitetura aberta do DeFi. Equipes podem construir interfaces onde você não somente vê os saldos entre produtos, mas também pode usar os recursos correspondentes. Você vai achar isso útil enquanto aprende mais sobre DeFi. - Ver dapps de portfolio + Ver dapps de portfólio @@ -323,41 +324,42 @@ O Ethereum é a base perfeita para DeFi por várias razões: Pense no DeFi como camadas: 1. O blockchain: Ethereum contém o histórico das transações e o estado das contas. -2. Os ativos: [ETH](/what-is-ether/) e outros tokens (moedas). -3. Os protocolos, [contratos inteligentes](/glossary/#smart-contract) que oferecem a funcionalidade, por exemplo, um serviço que permite o empréstimo descentralizado de ativos. -4. [As aplicações](/apps/): os produtos que usamos para gerenciar e acessar os protocolos. +2. Os ativos – [ETH](/what-is-ether/) e os outros tokens (moedas). +3. Os protocolos – [contratos inteligentes](/glossary/#smart-contract) que fornecem a funcionalidade, por exemplo, um serviço que permite o empréstimo descentralizado de ativos. +4. [Os aplicativos](/apps/) – os produtos que usamos para gerenciar e acessar os protocolos. -Nota: grande parte do DeFi usa o [padrão ERC-20](/glossary/#erc-20). Aplicações em DeFi usam um encapsulamento para ETH chamado Wrapped Ether (WETH). [Saiba mais sobre o Wrapped Ether](/wrapped-eth). +Observação: grande parte do DeFi usa o [padrão ERC-20](/glossary/#erc-20). Aplicações em DeFi utilizam um wrapper para ETH chamado Wrapped Ether (WETH). [Saiba mais sobre ether encapsulado](/wrapped-eth). -## Criar Defi {#build-defi} +## Desenvolva com DeFi {#build-defi} DeFi é um movimento de código aberto. Os protocolos e aplicações DeFi são todos abertos, para você inspecionar, fazer updates e inovar. Por causa dessa pilha em camadas (todos compartilham o mesmo blockchain e ativos base), os protocolos podem ser combinados para proporcionar oportunidades únicas. - Mais sobre como criar Dapps + Mais sobre a criação de dapps ## Leitura adicional {#further-reading} -### Dados DeFi {#defi-data} +### Dados de DeFi {#defi-data} - [DeFi Prime](https://defiprime.com/) - [DeFi Llama](https://defillama.com/) ### Artigos sobre DeFi {#defi-articles} -- [Um guia de DeFi para iniciantes](https://blog.coinbase.com/a-beginners-guide-to-decentralized-finance-defi-574c68ff43c4) – _Sid Coelho-Prabhu, 6 de janeiro de 2020_ +- [Um guia para iniciantes sobre DeFi](https://blog.coinbase.com/a-beginners-guide-to-decentralized-finance-defi-574c68ff43c4) – _Sid Coelho-Prabhu, 6 de janeiro de 2020_ +- [Diretrizes de Avaliação de Risco DeFi da EEA](https://entethalliance.org/specs/defi-risks/) – Uma visão geral apoiada pela indústria sobre como identificar e avaliar os principais riscos em protocolos DeFi. ### Vídeos {#videos} -- [Finematics - Informações sobre finanças descentralizadas](https://finematics.com/) – _Vídeos sobre DeFi_ -- [The Defiant](https://www.youtube.com/playlist?list=PLaDcID4s1KronHMKojfjwiHL0DdQEPDcq) - _Fundamentos DeFi: Tudo o que você precisa saber para começar neste espaço às vezes desconcertante._ +- [Finematics - educação sobre finanças descentralizadas](https://finematics.com/) – _Vídeos sobre DeFi_ +- [The Defiant](https://www.youtube.com/playlist?list=PLaDcID4s1KronHMKojfjwiHL0DdQEPDcq) - _Noções básicas de DeFi: tudo o que você precisa saber para começar neste espaço ocasionalmente desconcertante._ - [Whiteboard Crypto](https://youtu.be/17QRFlml4pA) _O que é DeFi?_ ### Comunidades {#communities} -- [Servidor DeFi Llama no Discord](https://discord.defillama.com/) -- [Servidor DeFi Pulse no Discord](https://discord.gg/Gx4TCTk) +- [Servidor do Discord do DeFi Llama](https://discord.defillama.com/) +- [Servidor do Discord do DeFi Pulse](https://discord.gg/Gx4TCTk) diff --git a/public/content/translations/pt-br/desci/index.md b/public/content/translations/pt-br/desci/index.md index 9285d777bf7..6278591ca68 100644 --- a/public/content/translations/pt-br/desci/index.md +++ b/public/content/translations/pt-br/desci/index.md @@ -1,24 +1,24 @@ --- -title: Ciência descentralizada (DeSci) -description: Uma visão geral da ciência descentralizada no Ethereum +title: "Ciência descentralizada (DeSci)" +description: "Uma visão geral da ciência descentralizada no Ethereum" lang: pt-br template: use-cases emoji: ":microscope:" sidebarDepth: 2 image: /images/future_transparent.png alt: "" -summaryPoint1: Uma alternativa global e aberta ao sistema científico atual. -summaryPoint2: Tecnologia que permite aos cientistas levantar fundos, realizar experimentos, compartilhar dados, distribuir informações e muito mais. -summaryPoint3: Constrói o movimento de ciência aberta. +summaryPoint1: "Uma alternativa global e aberta ao sistema científico atual." +summaryPoint2: "Tecnologia que permite aos cientistas levantar fundos, realizar experimentos, compartilhar dados, distribuir informações e muito mais." +summaryPoint3: "Constrói o movimento de ciência aberta." --- ## O que é ciência descentralizada (DeSci)? {#what-is-desci} -Ciência descentralizada (DeSci) é um movimento cujo objetivo é construir infraestrutura pública para financiar, criar, revisar, atribuir autoria, armazenar e disseminar conhecimento científico de forma justa e equitária usando a pilha [Web3](/glossary/#web3). +A ciência descentralizada (DeSci) é um movimento que visa construir uma infraestrutura pública para financiar, criar, revisar, creditar, armazenar e disseminar o conhecimento científico de forma justa e equitativa usando a pilha da [Web3](/glossary/#web3). A DeSci visa criar um ecossistema em que os cientistas sejam incentivados a partilhar abertamente a sua pesquisa e a receber crédito pelo seu trabalho, enquanto permite a qualquer pessoa acessar e contribuir para a pesquisa com facilidade. A DeSci parte da ideia de que o conhecimento científico deve ser acessível a todos e de que o processo de pesquisa científica deve ser transparente. A DeSci está criando um modelo de pesquisa científica mais descentralizado e distribuído, tornando-o mais resistente à censura e ao controle das autoridades centrais. A DeSci espera criar um ambiente no qual possam florescer novas ideias não convencionais por meio da descentralização do acesso ao financiamento, ferramentas científicas e canais de comunicação. -A ciência descentralizada possibilita mais diversas fontes de financiamento (de [DAOs](/glossary/#dao), [doações quadráticas](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=2003531) a financiamento colaborativo, entre outros), mais acessibilidade de dados e métodos, além de fornecer incentivos para reprodutibilidade. +A ciência descentralizada permite fontes de financiamento mais diversas (de [DAOs](/glossary/#dao), [doações quadráticas](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=2003531) a crowdfunding e muito mais), dados e métodos mais acessíveis e, ao mesmo tempo, fornece incentivos para a reprodutibilidade. ### Juan Benet — O Movimento DeSci @@ -28,16 +28,16 @@ A ciência descentralizada possibilita mais diversas fontes de financiamento (de Uma lista incompleta dos principais problemas encontrados pela ciência e como a ciência descentralizada pode ajudar a resolver esses problemas -| **Ciência descentralizada** | **Ciência tradicional** | -| ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | -| A distribuição de fundos é **determinada pelo público** usando mecanismos como as doações quadráticas ou DAOs. | **Grupos centralizados** pequenos e fechados controlam a distribuição de fundos. | -| Você colabora com pares ao **redor do mundo** em equipes dinâmicas. | Organizações de financiamento e instituições domésticas **limitam** suas colaborações. | -| Decisões de financiamento são feitos online e **de maneira transparente**. São explorados novos mecanismos de financiamento. | As decisões de financiamento levam muito tempo e são**pouco transparentes**. Existem poucos mecanismos de financiamento. | -| Compartilhar os serviços laboratoriais ficou mais fácil e mais transparente usando tecnologia [Web3](/glossary/#web3). | O compartilhamento de recursos laboratoriais é frequentemente **lento e difuso**. | -| **Novos modelos para publicação** podem ser desenvolvidos por Web3 primitivos para certificar confiança, transparência e acesso universal. | A publicação é feita de formas frequentemente consideradas **ineficientes, tendenciosas e abusivas**. | -| Você pode **ganhar tokens e consolidar sua reputação ao avaliar o trabalho de outros**. | O**trabalho de avaliação por pares não é remunerado**, o que beneficia os editores com fins lucrativos. | -| **Você é dono da propriedade intelectual (PI)** que gera e a distribui conforme termos transparentes. | **Sua instituição doméstica é dona da propriedade intelectual (IP)** que você gera. O acesso ao IP não é transparente. | -| **Compartilhar toda a pesquisa**, incluindo os dados de pesquisas que não deram certo, ao ter todas as etapas em cadeia. | **Bias de publicação** significa que pesquisadores são mais propensos a compartilhar experimentos que tiveram bons resultados. | +| **Ciência descentralizada** | **Ciência tradicional** | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| A distribuição dos fundos é **determinada pelo público** usando mecanismos como doações quadráticas ou DAOs. | Grupos pequenos, fechados e **centralizados** controlam a distribuição dos fundos. | +| Você colabora com colegas de **todo o mundo** em equipes dinâmicas. | Organizações de financiamento e instituições de origem **limitam** suas colaborações. | +| As decisões de financiamento são tomadas online e de forma **transparente**. São explorados novos mecanismos de financiamento. | As decisões de financiamento são tomadas com um longo tempo de resposta e **transparência limitada**. Existem poucos mecanismos de financiamento. | +| O compartilhamento de serviços de laboratório é facilitado e mais transparente com o uso da tecnologia [Web3](/glossary/#web3). | O compartilhamento de recursos de laboratório é muitas vezes **lento e opaco**. | +| **Novos modelos de publicação** podem ser desenvolvidos que usam primitivos da Web3 para confiança, transparência e acesso universal. | Você publica por meio de caminhos estabelecidos, frequentemente reconhecidos como **ineficientes, tendenciosos e exploratórios**. | +| Você pode **ganhar tokens e reputação pela revisão por pares** do trabalho. | Seu trabalho de **revisão por pares não é remunerado**, beneficiando editoras com fins lucrativos. | +| **Você é dono da propriedade intelectual (PI)** que gera e a distribui conforme termos transparentes. | **Sua instituição de origem detém a PI** que você gera. O acesso ao IP não é transparente. | +| **Compartilhamento de toda a pesquisa**, incluindo os dados de esforços malsucedidos, por ter todas as etapas onchain. | **Viés de publicação** significa que os pesquisadores são mais propensos a compartilhar experimentos que tiveram resultados bem-sucedidos. | ## Ethereum e DeSci {#ethereum-and-desci} @@ -49,9 +49,9 @@ A DeSci está criando um conjunto de ferramentas científicas para levar o meio ### Publicação {#publishing} -A publicação científica é notoriamente problemática por ser gerida por editoras que dependem do trabalho gratuito de cientistas, revisores e editores para produzir os artigos, mas, em seguida, cobram taxas de publicação exorbitantes. O público, que geralmente pagou indiretamente pelo trabalho e os custos de publicação por meio de impostos, muitas vezes, não conseguem acessar esse mesmo trabalho sem pagar novamente ao editor. As taxas totais para a publicação de artigos científicos individuais frequentemente somam dezenas de milhares de dólares, minando todo o conceito de conhecimento científico como um [bem público](/glossary/#public-goods), enquanto gera enormes lucros para um pequeno grupo de editoras. +A publicação científica é notoriamente problemática por ser gerida por editoras que dependem do trabalho gratuito de cientistas, revisores e editores para produzir os artigos, mas, em seguida, cobram taxas de publicação exorbitantes. O público, que geralmente pagou indiretamente pelo trabalho e os custos de publicação por meio de impostos, muitas vezes, não conseguem acessar esse mesmo trabalho sem pagar novamente ao editor. As taxas totais para a publicação de artigos científicos individuais geralmente chegam a cinco dígitos (em USD), minando todo o conceito de conhecimento científico como um [bem público](/glossary/#public-goods), ao mesmo tempo que geram lucros enormes para um pequeno grupo de editoras. -Plataformas de acesso aberto e gratuito existem na forma de servidores de pré-impressão, [como o ArXiv](https://arxiv.org/). No entanto, essas plataformas carecem de controle de qualidade, [mecanismos anti-sybil](/glossary/#anti-sybil) e geralmente não rastreiam métricas de nível de artigo, ou seja, são geralmente usadas apenas para divulgar o trabalho antes do envio a uma editora tradicional. O SciHub também disponibiliza os artigos publicados gratuitamente, mas não de forma legal, e apenas após os editores já terem pago e protegido o trabalho a uma rigorosa legislação de direitos autorais. Isso deixa uma lacuna grave nos artigos científicos e dados acessíveis com um mecanismo de legitimidade e um modelo de incentivos. As ferramentas para a construção desse sistema existem na Web3. +Existem plataformas gratuitas e de acesso aberto na forma de servidores de pré-publicação, [como o ArXiv](https://arxiv.org/). No entanto, essas plataformas carecem de controle de qualidade, [mecanismos anti-Sybil](/glossary/#anti-sybil), e geralmente não rastreiam métricas em nível de artigo, o que significa que geralmente são usadas apenas para divulgar o trabalho antes do envio a uma editora tradicional. O SciHub também disponibiliza os artigos publicados gratuitamente, mas não de forma legal, e apenas após os editores já terem pago e protegido o trabalho a uma rigorosa legislação de direitos autorais. Isso deixa uma lacuna grave nos artigos científicos e dados acessíveis com um mecanismo de legitimidade e um modelo de incentivos. As ferramentas para a construção desse sistema existem na Web3. ### Reprodutibilidade e replicabilidade {#reproducibility-and-replicability} @@ -60,29 +60,30 @@ Reprodutibilidade e replicabilidade são os fundamentos da descoberta científic - Resultados reprodutíveis podem ser alcançados várias vezes seguidas pela mesma equipe usando a mesma metodologia. - Resultados replicáveis podem ser alcançados por um grupo diferente usando a mesma configuração experimental. -As novas ferramentas nativas da Web3 podem garantir que a reprodutibilidade e a replicabilidade sejam a base da descoberta. Dessa forma, é possível tecer ciência de qualidade no tecido tecnológico do mundo acadêmico. Web3 oferece a capacidade de criar [atestações](/glossary/#attestation) para cada componente de análise: os dados brutos, o mecanismo computacional e o resultado do aplicativo. A beleza dos sistemas de consenso é que quando uma rede confiável é criada para manter esses componentes, cada participante da rede pode ser responsável por reproduzir o cálculo e validar cada resultado. +As novas ferramentas nativas da Web3 podem garantir que a reprodutibilidade e a replicabilidade sejam a base da descoberta. Dessa forma, é possível tecer ciência de qualidade no tecido tecnológico do mundo acadêmico. A Web3 oferece a capacidade de criar [atestados](/glossary/#attestation) para cada componente de análise: os dados brutos, o mecanismo computacional e o resultado da aplicação. A beleza dos sistemas de consenso é que quando uma rede confiável é criada para manter esses componentes, cada participante da rede pode ser responsável por reproduzir o cálculo e validar cada resultado. ### Financiamento {#funding} -O modelo padrão atual para o financiamento da ciência é que indivíduos ou grupos de cientistas façam solicitações por escrito a uma agência de financiamento. Um pequeno painel de indivíduos de confiança avaliam as inscrições e, em seguida, entrevistam os candidatos antes de conceder fundos a uma pequena porção de candidatos. Além de criar gargalos que levam, às vezes, a **anos de espera** entre a solicitação e o recebimento de um subsídio, acredita-se que esse modelo seja altamente **vulnerável aos biases, aos interesses próprios e às políticas** do painel de avaliação. +O modelo padrão atual para o financiamento da ciência é que indivíduos ou grupos de cientistas façam solicitações por escrito a uma agência de financiamento. Um pequeno painel de indivíduos de confiança avaliam as inscrições e, em seguida, entrevistam os candidatos antes de conceder fundos a uma pequena porção de candidatos. Além de criar gargalos que levam a, por vezes, **anos de espera** entre a candidatura e o recebimento de uma bolsa, este modelo é conhecido por ser altamente **vulnerável aos vieses, interesses próprios e políticas** do painel de revisão. Estudos mostraram que os painéis de revisão de bolsas fazem um trabalho ruim na seleção de propostas de alta qualidade, pois as mesmas propostas apresentadas a diferentes painéis têm resultados totalmente diferentes. Como o financiamento se tornou mais escasso, ele se concentrou em um grupo menor de pesquisadores mais experientes com projetos mais intelectualmente conservadores. O efeito criou um cenário de financiamento hipercompetitivo, entrincheirando incentivos perversos e asfixiando a inovação. -A Web3 tem o potencial de interromper este modelo de financiamento quebrado, experimentando diferentes modelos de incentivo desenvolvidos pelos DAOs e Web3 mais amplos. [Financiamento retroativo de bens públicos](https://medium.com/ethereum-optimism/retroactive-public-goods-funding-33c9b7d00f0c), [financiamento quadrático](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=2003531), [governança DAO](https://www.antler.co/blog/daos-and-web3-governance-the-promise-implications-and-challenges-ahead) e [estruturas de incentivo tokenizadas](https://cdixon.org/2017/05/27/crypto-tokens-a-breakthrough-in-open-network-design) são algumas das ferramentas Web3 que podem revolucionar o financiamento da ciência. +A Web3 tem o potencial de interromper este modelo de financiamento quebrado, experimentando diferentes modelos de incentivo desenvolvidos pelos DAOs e Web3 mais amplos. [Financiamento retroativo de bens públicos](https://medium.com/ethereum-optimism/retroactive-public-goods-funding-33c9b7d00f0c), [financiamento quadrático](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=2003531), [governança de DAO](https://www.antler.co/blog/daos-and-web3-governance-the-promise-implications-and-challenges-ahead) e [estruturas de incentivo tokenizadas](https://cdixon.org/2017/05/27/crypto-tokens-a-breakthrough-in-open-network-design) são algumas das ferramentas da Web3 que podem revolucionar o financiamento da ciência. -### Propriedade e desenvolvimento de IP {#ip-ownership} +### Propriedade e desenvolvimento de PI {#ip-ownership} -A propriedade intelectual (IP) é um grande problema na ciência tradicional: de ficar presa em universidades ou não utilizada em biotecnologia, a ser notoriamente difícil de avaliar. No entanto, a propriedade de ativos digitais (como dados ou artigos científicos) é algo que a Web3 faz excepcionalmente bem usando [tokens não fungíveis (NFTs)](/glossary/#nft). +A propriedade intelectual (IP) é um grande problema na ciência tradicional: de ficar presa em universidades ou não utilizada em biotecnologia, a ser notoriamente difícil de avaliar. No entanto, a propriedade de ativos digitais (como dados científicos ou artigos) é algo que a Web3 faz excepcionalmente bem usando [tokens não fungíveis (NFTs)](/glossary/#nft). Da mesma forma que os NFTs podem repassar receitas para transações futuras de volta ao criador original, você pode estabelecer cadeias de atribuição de valor transparentes para recompensar pesquisadores, órgãos governamentais (como DAOs) ou até mesmo as pessoas de cujos dados são coletados. -[IP-NFTs](https://medium.com/molecule-blog/ip-nfts-for-researchers-a-new-biomedical-funding-paradigm-91312d8d92e6) também podem funcionar como elemento de acesso a um repositório descentralizado de dados referentes a experimentos de pesquisa sendo realizados e se integrar ao NFT e ao financiamento de [DeFi](/glossary/#defi) (de fracionamento aos pools de empréstimo e avaliação de valor). Ele também permite que entidades nativamente em cadeia, como DAOs do tipo [VitaDAO](https://www.vitadao.com/), conduzam pesquisas diretamente em cadeia. Os [tokens "soulbound" intransferíveis](https://vitalik.eth.limo/general/2022/01/26/soulbound.html) também podem desempenhar um papel importante na DeSci, permitindo que indivíduos provem sua experiência e credenciais vinculadas ao seu endereço Ethereum. +[IP-NFTs](https://medium.com/molecule-blog/ip-nfts-for-researchers-a-new-biomedical-funding-paradigm-91312d8d92e6) também podem funcionar como uma chave para um repositório de dados descentralizado dos experimentos de pesquisa que estão sendo realizados e se conectar à financeirização de NFTs e [DeFi](/glossary/#defi) (desde o fracionamento até pools de empréstimo e avaliação de valor). Isso também permite que entidades nativamente onchain, como as DAOs, tal como a [VitaDAO](https://www.vitadao.com/), conduzam pesquisas diretamente onchain. +O advento dos [tokens "soulbound"](https://vitalik.eth.limo/general/2022/01/26/soulbound.html) não transferíveis também pode desempenhar um papel importante na DeSci, permitindo que indivíduos comprovem sua experiência e credenciais vinculadas ao seu endereço Ethereum. -### Armazenamento de dados, acesso e arquitetura {#data-storage} +### Armazenamento, acesso e arquitetura de dados {#data-storage} Os dados científicos podem se tornar muito mais acessíveis usando padrões Web3, e o armazenamento distribuído permite que a pesquisa sobreviva a eventos cataclísmicos. -O ponto de partida deve ser um sistema acessível por qualquer identidade descentralizada que possua as credenciais verificáveis adequadas. Isso permite que dados confidenciais sejam replicados com segurança por partes confiáveis, permitindo redundância e resistência à censura, reprodução de resultados e até mesmo a capacidade de várias partes colaborarem e adicionarem novos dados ao conjunto de dados. Métodos de computação confidenciais como [compute-to-data](https://7wdata.be/predictive-analytics/compute-to-data-using-blockchain-to-decentralize-data-science-and-ai-with-the-ocean-protocol) fornecem mecanismos alternativos de acesso à replicação de dados brutos, criando ambientes de pesquisa confiáveis para os dados mais confidenciais. Ambientes de pesquisa confiáveis foram [citados pelo NHS](https://medium.com/weavechain/whats-in-store-for-the-future-of-healthcare-data-b6398745fbbb) como uma solução voltada para o futuro para privacidade e colaboração de dados, criando um ecossistema no qual os pesquisadores podem trabalhar em segurança com dados no local usando ambientes padronizados para compartilhamento de código e práticas. +O ponto de partida deve ser um sistema acessível por qualquer identidade descentralizada que possua as credenciais verificáveis adequadas. Isso permite que dados confidenciais sejam replicados com segurança por partes confiáveis, permitindo redundância e resistência à censura, reprodução de resultados e até mesmo a capacidade de várias partes colaborarem e adicionarem novos dados ao conjunto de dados. Métodos de computação confidencial como o [compute-to-data](https://7wdata.be/predictive-analytics/compute-to-data-using-blockchain-to-decentralize-data-science-and-ai-with-the-ocean-protocol) fornecem mecanismos de acesso alternativos à replicação de dados brutos, criando Ambientes de Pesquisa Confiáveis para os dados mais sensíveis. Os Ambientes de Pesquisa Confiáveis foram [citados pelo NHS](https://medium.com/weavechain/whats-in-store-for-the-future-of-healthcare-data-b6398745fbbb) como uma solução voltada para o futuro para a privacidade e colaboração de dados, criando um ecossistema onde os pesquisadores podem trabalhar com segurança com dados no local usando ambientes padronizados para o compartilhamento de código e práticas. As soluções flexíveis de dados Web3 suportam os cenários acima e fornecem a base para a verdadeira Ciência Aberta, na qual os pesquisadores podem criar bens públicos sem permissões ou taxas. Soluções de dados públicos da Web3 como IPFS, Arweave e Filecoin são otimizadas para descentralização. O dClimate, por exemplo, fornece acesso universal a dados climáticos e meteorológicos, inclusive de estações meteorológicas e modelos climáticos preditivos. @@ -90,47 +91,49 @@ As soluções flexíveis de dados Web3 suportam os cenários acima e fornecem a Explore projetos e junte-se à comunidade DeSci. -- [DeSci.Global: eventos globais e calendário de encontros](https://desci.global) -- [Cadeia de blocos para o Science Telegram](https://t.me/BlockchainForScience) -- [Molecule: financie e obtenha financiamento para seus projetos de pesquisa](https://www.molecule.xyz/) -- [Virotada: receba financiamento por meio de acordos de pesquisa patrocinados para pesquisas sobre longevidade](https://www.vitadao.com/) +- [DeSci.Global: calendário global de eventos e encontros](https://desci.global) +- [Blockchain for Science Telegram](https://t.me/BlockchainForScience) +- [Molecule: Financie e obtenha financiamento para seus projetos de pesquisa](https://www.molecule.xyz/) +- [VitaDAO: receba financiamento por meio de acordos de pesquisa patrocinados para pesquisas sobre longevidade](https://www.vitadao.com/) - [ResearchHub: publique um resultado científico e converse com colegas](https://www.researchhub.com/) -- [dClimate API: consulte dados climáticos coletados por uma comunidade descentralizada](https://www.dclimate.net/) -- [DeSci Foundation: construtor de ferramentas de publicação DeSci](https://descifoundation.org/) -- [DeSci.World: balcão único para os usuários visualizarem e interagirem com a ciência descentralizada](https://desci.world) -- [OceanDAO: financiamento governado pela DAO para ciência relacionada a dados](https://oceanprotocol.com/) -- [Opscientia: fluxos de trabalho de ciência descentralizados abertos](https://opsci.io/research/) -- [Bio.xyz: obtenha financiamento para sua DAO de biotecnologia ou projeto desci](https://www.bio.xyz/) +- [API dClimate: consulte dados climáticos coletados por uma comunidade descentralizada](https://www.dclimate.net/) +- [DeSci Foundation: construtor de ferramentas de publicação da DeSci](https://descifoundation.org/) +- [DeSci.World: um balcão único para os usuários visualizarem e se engajarem com a ciência descentralizada](https://desci.world) +- [OceanDAO: financiamento governado por DAO para ciência relacionada a dados](https://oceanprotocol.com/) +- [Opscientia: fluxos de trabalho de ciência descentralizada abertos](https://opsci.io/research/) +- [Bio.xyz: obtenha financiamento para sua DAO de biotecnologia ou projeto DeSci](https://www.bio.xyz/) +- [Fleming Protocol: economia de dados de código aberto que impulsiona a descoberta biomédica colaborativa](http://flemingprotocol.io/) - [Active Inference Institute](https://www.activeinference.org/) -- [IdeaMarkets: para uma credibilidade científica descentralizada](https://ideamarket.io/) +- [IdeaMarkets: viabilizando a credibilidade científica descentralizada](https://ideamarket.io/) - [DeSci Labs](https://www.desci.com/) - [ValleyDAO: uma comunidade aberta e global que oferece financiamento e suporte translacional para pesquisas em biologia sintética](https://www.valleydao.bio) -- [Cerebrum DAO: buscando e promovendo soluções para melhorar a saúde cerebral e prevenir a neurodegeneração](https://www.cerebrumdao.com/) -- [CryoDAO: financiando pesquisas inovadoras na área de criopreservação](https://www.cryodao.org) +- [Cerebrum DAO: buscando e nutrindo soluções para avançar a saúde do cérebro e prevenir a neurodegeneração](https://www.cerebrumdao.com/) +- [CryoDAO: financiando pesquisas arrojadas na área de criopreservação](https://www.cryodao.org) +- [Elata: opine sobre o futuro da medicina psiquiátrica](https://www.elata.bio/) -Agradecemos o envio de sugestões para novos projetos a serem listados — veja nossa [política de listagem](/contributing/adding-desci-projects/) para começar! +Agradecemos sugestões de novos projetos para listar — consulte nossa [política de listagem](/contributing/adding-desci-projects/) para começar! ## Leitura adicional {#further-reading} -- [DeSci Wiki por Jocelynn Pearl e Ultrarare](https://docs.google.com/document/d/1aQC6zn-eXflSmpts0XGE7CawbUEHwnL6o-OFXO52PTc/edit#) -- [Um guia sobre biotecnologia descentralizada por Jocelynn Pearl para o futuro a16z](https://future.a16z.com/a-guide-to-decentralized-biotech/) -- [O caso da DeSci](https://gitcoin.co/blog/desci-the-case-for-decentralised-science/) -- [Guia para a DeSci](https://future.com/what-is-decentralized-science-aka-desci/) -- [Recursos científicos descentralizados](https://www.vincentweisser.com/desci) -- [IP-NFTs Bio-Farmacêuticas da Molecule — Uma descrição técnica](https://www.molecule.xyz/blog/molecules-biopharma-ip-nfts-a-technical-description) -- [Construindo sistemas de ciência sem confiança, de Jon Arrastar](https://medium.com/@jringo/building-systems-of-trustless-science-1cd2d072f673) -- [Paul Kohlhaas — DeSci: O Futuro da ciência descentralizada (podcast)](https://anchor.fm/andrew-steinwold/episodes/Paul-Kohlhaas---DeSci-The-Future-of-Decentralized-Science---Zima-Red-ep-117-e1h683a) -- [Uma ontologia de inferência ativa para a ciência descentralizada: da criação de sentido situada aos comuns epistêmicos](https://zenodo.org/record/6320575) -- [DeSci: O futuro da pesquisa por Samuel Azinhoso](https://lucidsamuel.medium.com/desci-the-future-of-research-b76cfc88c8ec) -- [Financiamento de ciência (Epílogo: DeSci e novas criptoprimitivas) por Nadia](https://nadia.xyz/science-funding) -- [A descentralização está perturbando o desenvolvimento de medicamentos](https://medium.com/id-theory/decentralisation-is-disrupting-drug-development-28b5ba5d447f) +- [Wiki da DeSci por Jocelynn Pearl e Ultrarare](https://docs.google.com/document/d/1aQC6zn-eXflSmpts0XGE7CawbUEHwnL6o-OFXO52PTc/edit#) +- [Um guia para a biotecnologia descentralizada por Jocelynn Pearl para a a16z future](https://future.a16z.com/a-guide-to-decentralized-biotech/) +- [A defesa da DeSci](https://gitcoin.co/blog/desci-the-case-for-decentralised-science/) +- [Guia da DeSci](https://future.com/what-is-decentralized-science-aka-desci/) +- [Recursos sobre ciência descentralizada](https://www.vincentweisser.com/desci) +- [IP-NFTs de biofarma da Molecule – uma descrição técnica](https://www.molecule.xyz/blog/molecules-biopharma-ip-nfts-a-technical-description) +- [Construindo sistemas de ciência sem necessidade de confiança por Jon Starr](https://medium.com/@jringo/building-systems-of-trustless-science-1cd2d072f673) +- [Paul Kohlhaas – DeSci: o futuro da ciência descentralizada (podcast)](https://anchor.fm/andrew-steinwold/episodes/Paul-Kohlhaas---DeSci-The-Future-of-Decentralized-Science---Zima-Red-ep-117-e1h683a) +- [Uma ontologia de inferência ativa para a ciência descentralizada: da criação de sentido situada aos bens comuns epistêmicos](https://zenodo.org/record/6320575) +- [DeSci: O Futuro da Pesquisa por Samuel Akinosho](https://lucidsamuel.medium.com/desci-the-future-of-research-b76cfc88c8ec) +- [Financiamento da ciência (Epílogo: DeSci e novas primitivas cripto) por Nadia](https://nadia.xyz/science-funding) +- [A descentralização está revolucionando o desenvolvimento de medicamentos](https://medium.com/id-theory/decentralisation-is-disrupting-drug-development-28b5ba5d447f) - [O que é DeSci – Ciência Descentralizada?](https://usadailytimes.com/2022/09/12/what-is-desci-decentralized-science/) ### Vídeos {#videos} -- [O que é ciência descentralizada?](https://www.youtube.com/watch?v=-DeMklVWNdA) -- [Conversa entre Vitalik Buterin e o cientista Aubrey de Gray sobre a interseção de pesquisas de longevidade e criptomoedas](https://www.youtube.com/watch?v=x9TSJK1widA) -- [A publicação científica está em pane. A Web3 pode resolver isso?](https://www.youtube.com/watch?v=WkvzYgCvWj8) -- [Juan Benet - DeSci, Laboratórios Independentes, & Ciência de Dados em Grande Escala](https://www.youtube.com/watch?v=zkXM9H90g_E) -- [Sebastian Brunemeier — Como a DeSci pode transformar a Pesquisa Biomédica e o Capital de Risco](https://www.youtube.com/watch?v=qB4Tc3FcVbM) -- [Paige Donner – Ferramentas para Ciência Aberta com Web3 & Blockchain](https://www.youtube.com/watch?v=nC-2QWQ-lgw&t=17s) +- [O que é Ciência Descentralizada?](https://www.youtube.com/watch?v=-DeMklVWNdA) +- [Conversa entre Vitalik Buterin e o cientista Aubrey de Grey sobre a interseção entre pesquisa de longevidade e cripto](https://www.youtube.com/watch?v=x9TSJK1widA) +- [A publicação científica está em pane. A Web3 pode consertar isso?](https://www.youtube.com/watch?v=WkvzYgCvWj8) +- [Juan Benet – DeSci, laboratórios independentes e ciência de dados em larga escala](https://www.youtube.com/watch?v=zkXM9H90g_E) +- [Sebastian Brunemeier – Como a DeSci pode transformar a pesquisa biomédica e o capital de risco](https://www.youtube.com/watch?v=qB4Tc3FcVbM) +- [Paige Donner – Ferramentas para a ciência aberta com a Web3 e a Blockchain](https://www.youtube.com/watch?v=nC-2QWQ-lgw&t=17s) diff --git a/public/content/translations/pt-br/developers/docs/accounts/index.md b/public/content/translations/pt-br/developers/docs/accounts/index.md index 1456285c484..40061fac959 100644 --- a/public/content/translations/pt-br/developers/docs/accounts/index.md +++ b/public/content/translations/pt-br/developers/docs/accounts/index.md @@ -1,10 +1,10 @@ --- title: Contas Ethereum -description: Uma explicação das contas Ethereum – suas estruturas de dados e sua relação com a criptografia de pares de chaves. +description: "Uma explicação das contas Ethereum – suas estruturas de dados e sua relação com a criptografia de pares de chaves." lang: pt-br --- -Uma conta Ethereum é uma entidade com um saldo de ether (ETH) que pode enviar transações no Ethereum. As contas podem ser controladas pelo usuário ou implementadas como contratos inteligentes. +Uma conta Ethereum é uma entidade com um saldo de ether (ETH) que pode enviar mensagens na Ethereum. As contas podem ser controladas pelo usuário ou implementadas como contratos inteligentes. ## Pré-requisitos {#prerequisites} @@ -34,20 +34,21 @@ Ambos os tipos de conta têm capacidade para: **Contrato** - Criar um contrato tem um custo porque você está usando o armazenamento de rede -- Só pode enviar transações em resposta ao recebimento de transação +- Pode enviar mensagens apenas em resposta ao recebimento de uma transação - Transações de uma conta externa para uma conta contrato podem acionar um código que pode executar muitas ações diferentes, como transferir tokens ou até mesmo criar um contrato - As contas de contrato não têm chaves privadas. Em vez disso, eles são controlados pela lógica do código do contrato inteligente -## Uma conta analisada {#an-account-examined} +## Análise de uma conta {#an-account-examined} As contas Ethereum têm quatro campos: - `nonce` – Um contador que indica o número de transações enviadas de uma conta de propriedade externa ou o número de contratos criados por uma conta de contrato. Apenas uma transação com um dado nonce pode ser executada para cada conta, protegendo contra ataques de repetição em que as transações assinadas são repetidamente transmitidas e reexecutadas. -- `balance` – o número de Wei pertencentes a este endereço. Wei é uma denominação de ETH e existem 1e + 18 Wei por ETH. -- `codeHash` - este hash se refere ao _código_ de uma conta na máquina virtual Ethereum (EVM). Contas contratuais têm fragmentos de código programados que podem executar diferentes operações. Este código EVM é executado se a conta receber uma chamada de mensagem. Diferentemente dos outros campos da conta, ele não pode ser alterado. Todos esses fragmentos de código estão contidos na base de dados de estados sob suas hashes correspondentes para recuperação posterior. Este valor de hash é conhecido como codeHash. Para contas de propriedade externa, o campo codeHash é o hash de uma “string” vazia. -- `storageRoot` – Às vezes conhecido como um hash de armazenamento. Um hash de 256 bits do nó raiz de uma árvore de Merkle que codifica o conteúdo de armazenamento da conta (um mapeamento entre valores inteiros de 256 bits), codificado para o mapeamento a partir do hash Keccak de 256 bits das chaves inteiras de 256 bits para os valores inteiros codificados no RLP-256 bits. Esta árvore codifica o hash do conteúdo de armazenamento desta conta e está vazia por padrão. +- `balance` – O número de wei detido por este endereço. Wei é uma denominação de ETH e existem 1e + 18 Wei por ETH. +- `codeHash` – Este hash refere-se ao _código_ de uma conta na máquina virtual Ethereum (EVM). Contas contratuais têm fragmentos de código programados que podem executar diferentes operações. Este código EVM é executado se a conta receber uma chamada de mensagem. Diferentemente dos outros campos da conta, ele não pode ser alterado. Todos esses fragmentos de código estão contidos na base de dados de estados sob suas hashes correspondentes para recuperação posterior. Este valor de hash é conhecido como codeHash. Para contas de propriedade externa, o campo codeHash é o hash de uma “string” vazia. +- `storageRoot` – Às vezes conhecido como um hash de armazenamento. Um hash de 256 bits do nó raiz de uma [Trie Merkle Patricia](/developers/docs/data-structures-and-encoding/patricia-merkle-trie/) que codifica o conteúdo de armazenamento da conta (um mapeamento entre valores inteiros de 256 bits), codificado na trie como um mapeamento do hash Keccak de 256 bits das chaves de inteiros de 256 bits para os valores inteiros de 256 bits codificados em RLP. Esta árvore codifica o hash do conteúdo de armazenamento desta conta e está vazia por padrão. -![Um diagrama mostrando a criação de uma conta](./accounts.png) _Diagrama adaptado do [Ethereum EVM ilustrado](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ +![Um diagrama mostrando a composição de uma conta](./accounts.png) +_Diagrama adaptado de [Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ ## Contas de propriedade externa e pares de chaves {#externally-owned-accounts-and-key-pairs} @@ -67,32 +68,32 @@ Exemplo: `fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036415f` -A chave pública é gerada a partir da chave privada usando o [Algoritmo de assinatura digital da curva elíptica](https://wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm). Você recebe um endereço público para sua conta a partir dos últimos 20 “bytes” do hash Keccak-256 da chave pública e adiciona `0x` no início. +A chave pública é gerada a partir da chave privada usando o [Algoritmo de Assinatura Digital de Curva Elíptica](https://wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm). Você obtém um endereço público para sua conta pegando os últimos 20 bytes do hash Keccak-256 da chave pública e adicionando `0x` no início. -Isso significa que uma Conta de Propriedade Externa (EOA) possui um endereço de 42 caracteres (um segmento de 20 bytes, que corresponde a 40 caracteres hexadecimais mais o prefixo `0x`). +Isso significa que uma conta de propriedade externa (EOA) possui um endereço de 42 caracteres (um segmento de 20 bytes que corresponde a 40 caracteres hexadecimais mais o prefixo `0x`). Exemplo: `0x5e97870f263700f46aa00d967821199b9bc5a120` -O exemplo a seguir mostra como usar uma ferramenta de assinatura chamada [Clef](https://geth.ethereum.org/docs/tools/clef/introduction) para gerar uma nova conta. Clef é uma ferramenta de assinatura e gerenciamento de contas que vem com o cliente Ethereum, [Geth](https://geth.ethereum.org). O comando `clef newaccount` cria um novo par de chaves e os salva em um repositório de chaves criptografado. +O exemplo a seguir mostra como usar uma ferramenta de assinatura chamada [Clef](https://geth.ethereum.org/docs/tools/clef/introduction) para gerar uma nova conta. Clef é uma ferramenta de gerenciamento de contas e assinatura que vem junto com o cliente Ethereum, [Geth](https://geth.ethereum.org). O comando `clef newaccount` cria um novo par de chaves e o salva em um repositório de chaves criptografado. ``` > clef newaccount --keystore -Please enter a password for the new account to be created: +Insira uma senha para a nova conta a ser criada: > ------------ -INFO [10-28|16:19:09.156] Your new key was generated address=0x5e97870f263700f46aa00d967821199b9bc5a120 -WARN [10-28|16:19:09.306] Please backup your key file path=/home/user/go-ethereum/data/keystore/UTC--2022-10-28T15-19-08.000825927Z--5e97870f263700f46aa00d967821199b9bc5a120 -WARN [10-28|16:19:09.306] Please remember your password! -Generated account 0x5e97870f263700f46aa00d967821199b9bc5a120 +INFO [10-28|16:19:09.156] Sua nova chave foi gerada address=0x5e97870f263700f46aa00d967821199b9bc5a120 +WARN [10-28|16:19:09.306] Faça o backup do seu arquivo de chave path=/home/user/go-ethereum/data/keystore/UTC--2022-10-28T15-19-08.000825927Z--5e97870f263700f46aa00d967821199b9bc5a120 +WARN [10-28|16:19:09.306] Lembre-se da sua senha! +Conta gerada 0x5e97870f263700f46aa00d967821199b9bc5a120 ``` [Documentação do Geth](https://geth.ethereum.org/docs) -É possível obter novas chaves públicas de sua chave privada, mas você não pode obter uma chave privada de chaves públicas. É fundamental manter suas chaves privadas seguras e, como o nome sugere, **PRIVADAS**. +É possível derivar novas chaves públicas da sua chave privada, mas não é possível derivar uma chave privada de chaves públicas. É vital manter suas chaves privadas seguras e, como o nome sugere, **PRIVADAS**. Você precisa de uma chave privada para assinar mensagens e transações que resultam em uma assinatura. Outros podem então pegar a assinatura derivada da sua chave pública, provando a autoria da mensagem. Em seu aplicativo, é possível usar uma biblioteca JavaScript para enviar transações para a rede. @@ -106,13 +107,13 @@ Exemplo: O endereço do contrato é geralmente dado quando um contrato é implantado na Blockchain do Ethereum. O endereço vem do endereço do criador e do número de transações enviadas desse endereço (o “nonce”). -## Chaves de validação {#validators-keys} +## Chaves do validador {#validators-keys} Há também outro tipo de chave no Ethereum, introduzida quando o Ethereum mudou de prova de trabalho para prova de participação baseado no consenso. Essas chaves são "BLS" e são usadas para identificar validadores. Essas chaves podem ser agregadas de forma eficiente para reduzir a largura de banda necessária para que a rede chegue a um consenso. Sem essa agregação de chaves, a participação mínima para um validador seria muito maior. -[Mais sobre chaves de validação](/developers/docs/consensus-mechanisms/pos/keys/). +[Mais sobre as chaves do validador](/developers/docs/consensus-mechanisms/pos/keys/). -## Observação sobre carteiras {#a-note-on-wallets} +## Uma observação sobre carteiras {#a-note-on-wallets} Uma conta não é uma carteira. Uma carteira é uma interface ou aplicativo que permite interagir com sua conta Ethereum, seja uma conta de propriedade externa ou uma conta de contrato. @@ -126,9 +127,9 @@ Assista a Austin mostrando passo a passo as funções de hash e os pares de chav ## Leitura adicional {#further-reading} -- [Entendendo Contas Ethereum](https://info.etherscan.com/understanding-ethereum-accounts/) - etherscan +- [Entendendo as Contas Ethereum](https://info.etherscan.com/understanding-ethereum-accounts/) - etherscan -_Conhece algum recurso da comunidade que o ajudou? Edite essa página e adicione-a!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ ## Tópicos relacionados {#related-topics} diff --git a/public/content/translations/pt-br/developers/docs/apis/backend/index.md b/public/content/translations/pt-br/developers/docs/apis/backend/index.md index b5459e72699..b75a9832bc0 100644 --- a/public/content/translations/pt-br/developers/docs/apis/backend/index.md +++ b/public/content/translations/pt-br/developers/docs/apis/backend/index.md @@ -1,64 +1,69 @@ --- title: Bibliotecas de API no Backend -description: Uma introdução as API's do Ethereum que permitem interações de seu App com a Blockchain. +description: "Uma introdução as API's do Ethereum que permitem interações de seu App com a Blockchain." lang: pt-br --- -Para um aplicativo de software interagir com a blockchain Ethereum (ou seja, leia os dados da blockchain e/ou envie transações para a rede), ele deve se conectar a um nó do Ethereum. +Para que um aplicativo de software interaja com a blockchain Ethereum (ou seja, para ler dados da blockchain e/ou enviar transações para a rede), ele deve se conectar a um nó Ethereum. -Para este propósito, todos os clientes do Ethereum implementam a especificação [JSON-RPC](/developers/docs/apis/json-rpc/), para que haja um conjunto uniforme de [métodos](/developers/docs/apis/json-rpc/#json-rpc-methods) nos quais os aplicativos podem confiar. +Para este propósito, cada cliente Ethereum implementa a especificação [JSON-RPC](/developers/docs/apis/json-rpc/), então há um conjunto uniforme de [métodos](/developers/docs/apis/json-rpc/#json-rpc-methods) nos quais os aplicativos podem confiar. Se você quiser usar uma linguagem de programação específica para se conectar com um nó Ethereum, existem várias bibliotecas de conveniência dentro do ecossistema que tornam isso muito mais fácil. Com essas bibliotecas, os desenvolvedores podem escrever intuitivamente métodos on-line para iniciar requisições JSON RPC (por debaixo dos panos) que interajam com a Ethereum. ## Pré-requisitos {#prerequisites} -Pode ser útil para entender a [stack da Ethereum](/developers/docs/ethereum-stack/) e [clientes Ethereum](/developers/docs/nodes-and-clients/). +Pode ser útil entender a [pilha Ethereum](/developers/docs/ethereum-stack/) e os [clientes Ethereum](/developers/docs/nodes-and-clients/). ## Por que usar uma biblioteca? {#why-use-a-library} -Essas bibliotecas abstraem muito da complexidade de interagir diretamente com um nó Ethereum. Eles também fornecem funções de utilidade (por exemplo, Convertendo ETH para Gwei) para que como desenvolvedor você possa passar menos tempo lidando com as complexidades de clientes da Ethereum e mais tempo focado na funcionalidade única do seu aplicativo. +Essas bibliotecas abstraem muito da complexidade de interagir diretamente com um nó Ethereum. Elas também fornecem funções utilitárias (p. ex., converter ETH para Gwei), de modo que, como desenvolvedor, você pode gastar menos tempo lidando com as complexidades dos clientes Ethereum e mais tempo focado na funcionalidade exclusiva do seu aplicativo. ## Bibliotecas disponíveis {#available-libraries} -### Serviços de nós e infraestrutura {#infrastructure-and-node-services} +### Infraestrutura e serviços de nó {#infrastructure-and-node-services} **Alchemy -** **_Plataforma de Desenvolvimento Ethereum._** - [alchemy.com](https://www.alchemy.com/) -- [Documentação](https://docs.alchemy.com/) +- [Documentação](https://www.alchemy.com/docs/) - [GitHub](https://github.com/alchemyplatform) - [Discord](https://discord.com/invite/alchemyplatform) -**All That Node - ** **_Nós-como-um-serviço._** +**All That Node -** **_Nó como serviço._** - [All That Node.com](https://www.allthatnode.com/) - [Documentação](https://docs.allthatnode.com) - [Discord](https://discord.gg/GmcdVEUbJM) -**Blast, da Bware Labs -****_ APIs descentralizadas para a Ethereum Mainnet ant Testnets._** +**Blast da Bware Labs -** **_APIs descentralizadas para a Mainnet e Testnets da Ethereum._** - [blastapi.io](https://blastapi.io/) - [Documentação](https://docs.blastapi.io) -- [Discord](https://discord.gg/bwarelabs) +- [Discord](https://discord.gg/SaRqmRUjjQ) -**BlockPi -** **_Fornece serviços RPC mais eficientes e mais rápidos_** +**BlockPi -** **_Fornece serviços RPC mais eficientes e rápidos._** - [blockpi.io](https://blockpi.io/) - [Documentação](https://docs.blockpi.io/) - [GitHub](https://github.com/BlockPILabs) - [Discord](https://discord.com/invite/xTvGVrGVZv) -**Gateway Cloudflare de Ethereum.** +**Cloudflare Ethereum Gateway.** - [cloudflare-eth.com](https://www.cloudflare.com/application-services/products/web3/) **Etherscan - Explorador de blocos e APIs de transações** + - [Documentação](https://docs.etherscan.io/) -**GetBlock-** **_Blockchain-as-a-service para desenvolvimento Web3_** +**Blockscout - Explorador de Blocos de Código Aberto** + +- [Documentação](https://docs.blockscout.com/) + +**GetBlock-** **_Blockchain como serviço para desenvolvimento Web3_** - [GetBlock.io](https://getblock.io/) -- [Documentação](https://getblock.io/docs/) +- [Documentação](https://docs.getblock.io/) **Infura -** **_A API da Ethereum como serviço._** @@ -74,20 +79,21 @@ Essas bibliotecas abstraem muito da complexidade de interagir diretamente com um **NOWNodes - _Nós Completos e Exploradores de Blocos._** - [NOWNodes.io](https://nownodes.io/) +- [Documentação](https://nownodes.gitbook.io/documentation) -**QuickNode -** **_Infraestrutura Blockchain como Serviço._** +**QuickNode -** **_Infraestrutura de blockchain como serviço._** - [quicknode.com](https://quicknode.com) - [Documentação](https://www.quicknode.com/docs/welcome) - [Discord](https://discord.gg/quicknode) -**Rivet -** **_Ethereum e Ethereum Classic APIs como serviço, desenvolvido por software de código aberto._** +**Rivet -** **_APIs do Ethereum e Ethereum Classic como serviço, desenvolvidas com software de código aberto._** - [rivet.cloud](https://rivet.cloud) - [Documentação](https://rivet.cloud/docs/) - [GitHub](https://github.com/openrelayxyz/ethercattle-deployment) -**Zmok -** **_Nós Ethereum orientados a velocidade como JSON-RPC/WebSockets API._** +**Zmok -** **_Nós Ethereum orientados à velocidade como API JSON-RPC/WebSockets._** - [zmok.io](https://zmok.io/) - [GitHub](https://github.com/zmok-io) @@ -108,13 +114,13 @@ Essas bibliotecas abstraem muito da complexidade de interagir diretamente com um - [Documentação](http://docs.nethereum.com/en/latest/) - [Discord](https://discord.com/invite/jQPrR58FxX) -**Python Tooling -** **_Variedade de bibliotecas para interação com a Ethereum via Python._** +**Ferramentas Python -** **_Variedade de bibliotecas para interação com o Ethereum via Python._** -- [py.ethereum.org](https://snakecharmers.ethereum.org) -- [web3.py GitHub](https://github.com/ethereum/web3.py) -- [web3.py Chat](https://gitter.im/ethereum/web3.py) +- [py.ethereum.org](https://snakecharmers.ethereum.org/) +- [GitHub do web3.py](https://github.com/ethereum/web3.py) +- [Bate-papo do web3.py](https://gitter.im/ethereum/web3.py) -**QuikNode -** **_A plataforma definitiva de desenvolvimento de blockchains_** +**Tatum -** **_A plataforma definitiva de desenvolvimento de blockchain._** - [Tatum](https://tatum.io/) - [GitHub](https://github.com/tatumio/) @@ -127,36 +133,36 @@ Essas bibliotecas abstraem muito da complexidade de interagir diretamente com um - [Documentação](https://docs.web3j.io/) - [Gitter](https://gitter.im/web3j/web3j) -### Serviços blockchain {#blockchain-services} +### Serviços de blockchain {#blockchain-services} -**BlockCypher -** **_APIs Web Ethereum._** +**BlockCypher -** **_APIs web do Ethereum._** - [blockcypher.com](https://www.blockcypher.com/) - [Documentação](https://www.blockcypher.com/dev/ethereum/) -**Chainbase -** **_Infraestrutura de dados web3 tudo-em-um para Ethereum._** +**Chainbase -** **_Infraestrutura de dados Web3 tudo-em-um para o Ethereum._** - [chainbase.com](https://chainbase.com/) - [Documentação](https://docs.chainbase.com/) - [Discord](https://discord.gg/Wx6qpqz4AF) -**Chainstack -** **_Nós Ethereum compartilhados e dedicados como serviço._** +**Chainstack -** **_Nós Ethereum elásticos e dedicados como serviço._** - [chainstack.com](https://chainstack.com) -- [Documentação](https://docs.chainbase.com/docs) -- [Referência da API Ethereum](https://docs.chainstack.com/reference/ethereum-getting-started) +- [Documentação](https://docs.chainstack.com/) +- [Referência da API do Ethereum](https://docs.chainstack.com/reference/ethereum-getting-started) -**Nó da Nuvem da Coinbase -** **_API de infraestrutura Blockchain._** +**Coinbase Cloud Node -** **_API de infraestrutura de blockchain._** -- [Nó da Nuvem da Coinbase](https://www.coinbase.com/cloud) -- [Documentação](https://docs.cloud.coinbase.com/) +- [Coinbase Cloud Node](https://www.coinbase.com/developer-platform) +- [Documentação](https://docs.cdp.coinbase.com/) -**DataHub por Figment -** **_Serviços de API Web3 API com rede principal Ethereum e rede de testes._** +**DataHub da Figment -** **_Serviços de API Web3 com a Mainnet e as testnets do Ethereum._** - [DataHub](https://www.figment.io/) - [Documentação](https://docs.figment.io/) -**Moralis -** **_Provedor de API para EVM para uso corporativo._** +**Moralis -** **_Provedor de API EVM de nível empresarial._** - [moralis.io](https://moralis.io) - [Documentação](https://docs.moralis.io/) @@ -164,20 +170,20 @@ Essas bibliotecas abstraem muito da complexidade de interagir diretamente com um - [Discord](https://moralis.io/joindiscord/) - [Fórum](https://forum.moralis.io/) -**NFTPort -** **_Dados Ethereum e APIs Mint._** +**NFTPort -** **_Dados do Ethereum e APIs de cunhagem._** - [nftport.xyz](https://www.nftport.xyz/) - [Documentação](https://docs.nftport.xyz/) - [GitHub](https://github.com/nftport/) - [Discord](https://discord.com/invite/K8nNrEgqhE) -**Tokenview -** **_A plataforma geral de APIs blockchain multi-cripto._** +**Tokenview -** **_A plataforma geral de APIs de blockchain para múltiplas criptos._** - [services.tokenview.io](https://services.tokenview.io/) - [Documentação](https://services.tokenview.io/docs?type=api) - [GitHub](https://github.com/Tokenview) -**Watchdata -** **_Fornecer acesso API simples e confiável à blockchain Ethereum._** +**Watchdata -** **_Fornece acesso simples e confiável via API à blockchain do Ethereum._** - [Watchdata](https://watchdata.io/) - [Documentação](https://docs.watchdata.io/) @@ -190,17 +196,16 @@ Essas bibliotecas abstraem muito da complexidade de interagir diretamente com um - [GitHub](https://github.com/covalenthq) - [Discord](https://www.covalenthq.com/discord/) - ## Leitura adicional {#further-reading} -_Conhece um recurso da comunidade que te ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite essa página e adicione-o!_ ## Tópicos relacionados {#related-topics} - [Nós e clientes](/developers/docs/nodes-and-clients/) -- [Estruturas de desenvolvimento](/developers/docs/frameworks/) +- [Frameworks de desenvolvimento](/developers/docs/frameworks/) ## Tutoriais relacionados {#related-tutorials} -- [Configure Web3js para usar a blockchain Ethereum em Javascript](/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/) _ – Instruções para configurar web3.js no seu projeto._ -- [Chamando um contrato inteligente do JavaScript](/developers/tutorials/calling-a-smart-contract-from-javascript/) _ – Usando o token do DAI, veja como os contratos de chamadas funcionam usando JavaScript._ +- [Configurar o Web3js para usar a blockchain Ethereum em JavaScript](/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/) _– Instruções para configurar o web3.js em seu projeto._ +- [Chamando um contrato inteligente a partir do JavaScript](/developers/tutorials/calling-a-smart-contract-from-javascript/) _– Usando o token DAI, veja como chamar funções de contratos usando JavaScript._ diff --git a/public/content/translations/pt-br/developers/docs/apis/javascript/index.md b/public/content/translations/pt-br/developers/docs/apis/javascript/index.md index fa1dba1ced9..1ec1696ddac 100644 --- a/public/content/translations/pt-br/developers/docs/apis/javascript/index.md +++ b/public/content/translations/pt-br/developers/docs/apis/javascript/index.md @@ -1,31 +1,33 @@ --- title: Bibliotecas de API JavaScript -description: Uma introdução às bibliotecas de cliente JavaScript que permitem que você interaja com a cadeia de blocos de seu aplicativo. +description: "Uma introdução às bibliotecas de cliente JavaScript que permitem que você interaja com a cadeia de blocos de seu aplicativo." lang: pt-br --- -Para que um aplicativo web interaja com a cadeia de blocos Ethereum (ou seja, leia os dados da blockchain e/ou envie transações para a rede), ele deve se conectar a um nó Ethereum. +Para que um aplicativo da web interaja com a blockchain Ethereum (ou seja, leia os dados da blockchain e/ou envie transações para a rede), ele deve se conectar a um nó Ethereum. -Para esse propósito, cada cliente Ethereum implementa a especificação [JSON-RPC](/developers/docs/apis/json-rpc/), para que haja um conjunto uniforme de [métodos](/developers/docs/apis/json-rpc/#json-rpc-methods) com os quais os aplicativos podem conta. +Para este propósito, cada cliente Ethereum implementa a especificação [JSON-RPC](/developers/docs/apis/json-rpc/), portanto, há um conjunto uniforme de [métodos](/developers/docs/apis/json-rpc/#json-rpc-methods) nos quais os aplicativos podem confiar. Se você quiser usar JavaScript para se conectar a um nó Ethereum, é possível usar o JavaScript vanilla, mas existem várias bibliotecas convenientes dentro do ecossistema que tornam isso muito mais fácil. Com essas bibliotecas, os desenvolvedores podem escrever intuitivamente métodos on-line para iniciar requisições JSON RPC (por debaixo dos panos) que interajam com a Ethereum. -Observe que, desde [A Fusão](/roadmap/merge/) (The Merge), duas partes conectadas do software Ethereum — um cliente de execução e um cliente de consenso — são necessárias para executar um nó. Certifique-se de que seu nó inclui tanto o cliente de execução quanto o consensual. Se o seu nó não estiver na sua máquina local (por exemplo, seu nó está sendo executado em uma instância da AWS) atualize os endereços IP no tutorial adequadamente. Para obter mais informações, veja nossa página no [executando um nó](/developers/docs/nodes-and-clients/run-a-node/). +Observe que, desde [A Fusão](/roadmap/merge/), duas partes conectadas do software Ethereum - um cliente de execução e um cliente de consenso - são necessárias para executar um nó. Certifique-se de que seu nó inclui tanto o cliente de execução quanto o consensual. Se o seu nó não estiver na sua máquina local (p. ex., seu nó está sendo executado em uma instância da AWS), atualize os endereços IP no tutorial. Para mais informações, consulte nossa página sobre [como executar um nó](/developers/docs/nodes-and-clients/run-a-node/). ## Pré-requisitos {#prerequisites} -Além de entender o JavaScript, pode ser útil entender a [pilha de Ethereum](/developers/docs/ethereum-stack/) e[ clientes Ethereum](/developers/docs/nodes-and-clients/). +Além de entender JavaScript, pode ser útil entender a [pilha Ethereum](/developers/docs/ethereum-stack/) e os [clientes Ethereum](/developers/docs/nodes-and-clients/). ## Por que usar uma biblioteca? {#why-use-a-library} -Essas bibliotecas abstraem muito da complexidade de interagir diretamente com um nó Ethereum. Eles também fornecem funções de utilidade (por exemplo, Convertendo ETH para Gwei) para que como desenvolvedor, você possa passar menos tempo lidando com as complexidades de clientes da Ethereum e mais tempo focado na funcionalidade única do seu aplicativo. +Essas bibliotecas abstraem muito da complexidade de interagir diretamente com um nó Ethereum. Elas também fornecem funções utilitárias (p. ex., converter ETH para Gwei), de modo que, como desenvolvedor, você pode gastar menos tempo lidando com as complexidades dos clientes Ethereum e mais tempo focado na funcionalidade exclusiva do seu aplicativo. ## Recursos da biblioteca {#library-features} -### Conectar aos nós da Ethereum {#connect-to-ethereum-nodes} +### Conectar-se aos nós do Ethereum {#connect-to-ethereum-nodes} Usando provedores, essas bibliotecas permitem que você se conecte à Ethereum e leia os seus dados, seja por JSON-RPC, INFURA, Etherscan, Alquimia ou MetaMask. +> **Aviso:** O Web3.js foi arquivado em 4 de março de 2025. [Leia o anúncio](https://blog.chainsafe.io/web3-js-sunset/). Considere o uso de bibliotecas alternativas como [ethers.js](https://ethers.org) ou [viem](https://viem.sh) para novos projetos. + **Exemplo de Ethers** ```js @@ -33,7 +35,7 @@ Usando provedores, essas bibliotecas permitem que você se conecte à Ethereum e // o que o MetaMask injeta como window.ethereum em cada página const provider = new ethers.BrowserProvider(window.ethereum) -// O plugin MetaMask também permite assinar transações para +// O plug-in MetaMask também permite assinar transações para // enviar ether e pagar para alterar o estado dentro da blockchain. // Para isso, precisamos do signatário da conta... const signer = provider.getSigner() @@ -70,29 +72,29 @@ Uma vez configurado, você poderá consultar a blockchain para: - id da rede - e mais... -### Funcionalidade de carteira {#wallet-functionality} +### Funcionalidade da carteira {#wallet-functionality} Essas bibliotecas oferecem a funcionalidade de criar carteiras, gerenciar chaves e assinar transações. Veja alguns exemplos de Ethers ```js -// Cria uma instância de carteira de um mnemonic... +// Crie uma instância de carteira a partir de uma mnemônica... mnemonic = "announce room limb pattern dry unit scale effort smooth jazz weasel alcohol" walletMnemonic = Wallet.fromPhrase(mnemonic) -// ...ou a partir de uma chave privada +// ...ou de uma chave privada walletPrivateKey = new Wallet(walletMnemonic.privateKey) walletMnemonic.address === walletPrivateKey.address // true -// O endereço como uma Promise conforme a API Signer +// O endereço como uma Promise pela API do Signer walletMnemonic.getAddress() // { Promise: '0x71CB05EE1b1F506fF321Da3dac38f25c0c9ce6E1' } -// O endereço de uma Wallet também está disponível de forma síncrona +// Um endereço de Carteira também está disponível de forma síncrona walletMnemonic.address // '0x71CB05EE1b1F506fF321Da3dac38f25c0c9ce6E1' @@ -102,7 +104,7 @@ walletMnemonic.privateKey walletMnemonic.publicKey // '0x04b9e72dfd423bcf95b3801ac93f4392be5ff22143f9980eb78b3a860c4843bfd04829ae61cdba4b3b1978ac5fc64f5cc2f4350e35a108a9c9a92a81200a60cd64' -// A frase mnemônica da wallet +// A mnemônica da carteira walletMnemonic.mnemonic // { // locale: 'en', @@ -110,8 +112,8 @@ walletMnemonic.mnemonic // phrase: 'announce room limb pattern dry unit scale effort smooth jazz weasel alcohol' // } -// Nota: Uma wallet criada com uma chave privada não -// possui uma frase mnemônica (a derivação a impede) +// Observação: uma carteira criada com uma chave privada não +// tem uma mnemônica (a derivação o impede) walletPrivateKey.mnemonic // null @@ -128,8 +130,8 @@ tx = { walletMnemonic.signTransaction(tx) // { Promise: '0xf865808080948ba1f109551bd432803012645ac136ddd64dba72880de0b6b3a7640000801ca0918e294306d177ab7bd664f5e141436563854ebe0a3e523b9690b4922bbb52b8a01181612cec9c431c4257a79b8c9f0c980a2c49bb5a0e6ac52949163eeb565dfc' } -// O método connect retorna uma nova instância da -// Wallet conectada a um provedor +// O método de conexão retorna uma nova instância da +// Carteira conectada a um provedor wallet = walletMnemonic.connect(provider) // Consultando a rede @@ -151,7 +153,7 @@ Uma vez configurado você será capaz de: - assinar transações - e mais... -### Interaja com funções de contrato inteligentes {#interact-with-smart-contract-functions} +### Interagir com funções de contrato inteligente {#interact-with-smart-contract-functions} As bibliotecas de clientes Javascript permitem que sua aplicação chame funções de contratos inteligentes lendo a Interface Binária da Aplicação (en: ABI, pt: IBA) de um contrato compilado. @@ -164,7 +166,7 @@ contract Test { uint a; address d = 0x12345678901234567890123456789012; - function Test(uint testInt) { a = testInt;} + constructor(uint testInt) { a = testInt;} event Event(uint indexed b, bytes32 c); @@ -217,7 +219,7 @@ Isso significa que você pode: Funções utilitárias lhe dão atalhos úteis que facilitam um pouco a construção com a Ethereum. -Os valores ETH estão em Wei por padrão. 1 ETH = 1.000.000.000.000.000.000 WEI – isso significa que você está lidando com muitos números! `web3.utils.toWei` converte ether para Wei pra você. +Os valores ETH estão em Wei por padrão. 1 ETH = 1.000.000.000.000.000.000 WEI – isso significa que você está lidando com muitos números! `web3.utils.toWei` converte ether para Wei para você. E em ethers fica assim: @@ -232,59 +234,56 @@ ethers.utils.formatEther(balance) // '2.337132817842795605' ``` -- [Funções utilitárias da Web3js](https://docs.web3js.org/api/web3-utils) -- [Funções utilitárias da EthersJs](https://docs.ethers.io/v5/api/utils/) +- [Funções utilitárias do Web3js](https://docs.web3js.org/api/web3-utils) +- [Funções utilitárias do Ethers](https://docs.ethers.org/v6/api/utils/) ## Bibliotecas disponíveis {#available-libraries} -**Web3.js -** **_API para Ethereum em JavaScript._** +**Web3.js -** **_API JavaScript do Ethereum._** -- [Documentação](https://docs.web3js.org/) -- [GitHub](https://github.com/ethereum/web3.js/) +- [Documentação](https://docs.web3js.org) +- [GitHub](https://github.com/ethereum/web3.js) -**Ethers.js -** **_Implementação completa de uma carteira Ethereum e utilidades em JavaScript e TypeScript._** +**Ethers.js -** **_Implementação completa da carteira Ethereum e utilitários em JavaScript e TypeScript._** -- [Documentação](https://docs.ethers.io/) -- [GitHub](https://github.com/ethers-io/ethers.js/) +- [Página inicial do Ethers.js](https://ethers.org/) +- [Documentação](https://docs.ethers.io) +- [GitHub](https://github.com/ethers-io/ethers.js) -**The Graph -** **_Um protocolo para indexação de dados de Ethereum e IPFS e sua consulta usando GraphQL._** +**The Graph -** **_Um protocolo para indexar dados do Ethereum e IPFS e consultá-los usando GraphQL._** -- [The Graph](https://thegraph.com/) -- [Graph Explorer](https://thegraph.com/explorer/) -- [Documentação](https://thegraph.com/docs/) -- [GitHub](https://github.com/graphprotocol/) +- [The Graph](https://thegraph.com) +- [Graph Explorer](https://thegraph.com/explorer) +- [Documentação](https://thegraph.com/docs) +- [GitHub](https://github.com/graphprotocol) - [Discord](https://thegraph.com/discord) -**light.js -** **_Uma biblioteca em alto nível reativa em JS otimizada para clientes leves._** - -- [GitHub](https://github.com/openethereum/js-libs/tree/master/packages/light.js) - -**Alchemyweb3 -** **_Wrapper em torno de Web3.js com tentativas automáticas e apis aprimoradas._** - -- [Documentação](https://docs.alchemy.com/reference/api-overview) -- [GitHub](https://github.com/alchemyplatform/alchemy-web3) +**Alchemy SDK -** **_Wrapper em torno do Ethers.js com APIs aprimoradas._** -**Alchemy NFT API -** **_API para buscar dados NFT, incluindo propriedade, atributos de metadados e muito mais._** - -- [Documentação](https://docs.alchemy.com/alchemy/enhanced-apis/nft-api) -- [GitHub](https://github.com/alchemyplatform/alchemy-web3) +- [Documentação](https://www.alchemy.com/docs) +- [GitHub](https://github.com/alchemyplatform/alchemy-sdk-js) **viem -** **_Interface TypeScript para Ethereum._** - [Documentação](https://viem.sh) - [GitHub](https://github.com/wagmi-dev/viem) +**Drift -** **_Metabiblioteca TypeScript com cache, ganchos e simulações de teste integrados._** + +- [Documentação](https://ryangoree.github.io/drift/) +- [GitHub](https://github.com/ryangoree/drift/) + ## Leitura adicional {#further-reading} -_Conhece um recurso da comunidade que te ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ ## Tópicos relacionados {#related-topics} -- [ Nós e clientes](/developers/docs/nodes-and-clients/) -- [Estruturas de desenvolvimento](/developers/docs/frameworks/) +- [Nós e clientes](/developers/docs/nodes-and-clients/) +- [Frameworks de desenvolvimento](/developers/docs/frameworks/) ## Tutoriais relacionados {#related-tutorials} -- [Configure Web3js para usar a blockchain Ethereum em Javascript](/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/) _ – Instruções para configurar web3.js no seu projeto._ -- [Chamando um contrato inteligente do JavaScript](/developers/tutorials/calling-a-smart-contract-from-javascript/) _ – Usando o token do DAI, veja como os contratos de chamadas funcionam usando JavaScript._ -- [Enviando transações usando web3 e Alchemy](/developers/tutorials/sending-transactions-using-web3-and-alchemy/) _ – Passo a passo para enviar transações pelo back-end._ +- [Configurar o Web3js para usar a blockchain Ethereum em JavaScript](/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/) _– Instruções para configurar o web3.js em seu projeto._ +- [Chamando um contrato inteligente a partir do JavaScript](/developers/tutorials/calling-a-smart-contract-from-javascript/) _– Usando o token DAI, veja como chamar funções de contratos usando JavaScript._ +- [Enviando transações usando web3 e Alchemy](/developers/tutorials/sending-transactions-using-web3-and-alchemy/) _– Passo a passo para enviar transações pelo back-end._ diff --git a/public/content/translations/pt-br/developers/docs/apis/json-rpc/index.md b/public/content/translations/pt-br/developers/docs/apis/json-rpc/index.md index 8c29fca6938..2660ec71713 100644 --- a/public/content/translations/pt-br/developers/docs/apis/json-rpc/index.md +++ b/public/content/translations/pt-br/developers/docs/apis/json-rpc/index.md @@ -6,27 +6,27 @@ lang: pt-br Para que um aplicativo de software interaja com a blockchain Ethereum - lendo os dados da blockchain ou enviando transações para a rede - ele deve se conectar na Ethereum. -Para esse fim, todos os [clientes Ethereum](/developers/docs/nodes-and-clients/#execution-clients) implementam uma [especificação JSON-RPC](https://github.com/ethereum/execution-apis) para que exista um conjunto uniforme de métodos nos quais os aplicativos podem confiar, independentemente do nó específico ou da implementação do cliente. +Para essa finalidade, todo [cliente Ethereum](/developers/docs/nodes-and-clients/#execution-clients) implementa uma [especificação JSON-RPC](https://github.com/ethereum/execution-apis), de modo que haja um conjunto uniforme de métodos nos quais os aplicativos podem confiar, independentemente da implementação específica do nó ou do cliente. [JSON-RPC](https://www.jsonrpc.org/specification) é um protocolo de chamada de procedimento remoto (RPC) leve e sem estado. Ele define várias estruturas de dados e as regras em torno de seu processamento. É agnóstico de transporte no sentido de que os conceitos podem ser usados dentro do mesmo processo, sobre sockets, HTTP ou em vários ambientes de passagem de mensagens. Usa o formato de dados JSON (RFC 4627). -## Implementações do cliente {#client-implementations} +## Implementações de cliente {#client-implementations} -Cada cliente Ethereum pode utilizar linguagens de programação diferentes ao implementar a especificação JSON-RPC. Consulte a [documentação individual do cliente](/developers/docs/nodes-and-clients/#execution-clients) para mais detalhes relacionados a linguagens de programação específicas. Recomendamos verificar a documentação de cada cliente para as informações mais recentes de suporte à API. +Cada cliente Ethereum pode utilizar linguagens de programação diferentes ao implementar a especificação JSON-RPC. Consulte a [documentação do cliente](/developers/docs/nodes-and-clients/#execution-clients) individual para mais detalhes relacionados a linguagens de programação específicas. Recomendamos verificar a documentação de cada cliente para as informações mais recentes de suporte à API. -## Bibliotecas de Conveniência {#convenience-libraries} +## Bibliotecas de conveniência {#convenience-libraries} -Embora você possa optar por interagir diretamente com clientes da Ethereum usando a API JSON-RPC, muitas vezes existem opções mais fáceis para desenvolvedores de dapps. Muitas [bibliotecas de](/developers/docs/apis/javascript/#available-libraries) e [de backend API](/developers/docs/apis/backend/#available-libraries) existem para fornecer wrappers além de API JSON-RPC. Com essas bibliotecas, os desenvolvedores podem escrever intuitivamente métodos de uma linha para inicializar requisições JSON RPC (sob os capôs) que interagem com a Ethereum. +Embora você possa optar por interagir diretamente com clientes da Ethereum usando a API JSON-RPC, muitas vezes existem opções mais fáceis para desenvolvedores de dapps. Existem muitas bibliotecas de [JavaScript](/developers/docs/apis/javascript/#available-libraries) e [API de backend](/developers/docs/apis/backend/#available-libraries) que fornecem wrappers sobre a API JSON-RPC. Com essas bibliotecas, os desenvolvedores podem escrever intuitivamente métodos de uma linha para inicializar requisições JSON RPC (sob os capôs) que interagem com a Ethereum. ## APIs de cliente de consenso {#consensus-clients} -Esta página trata principalmente da API JSON-RPC usada pelos clientes de execução Ethereum. No entanto, os clientes de consenso também têm uma API RPC que permite aos usuários consultar informações sobre o nó, solicitar blocos Beacon, estado do Beacon, e outras informações relacionadas ao consenso diretamente de um nó. Essa API está documentada na [página da Web da API Beacon](https://ethereum.github.io/beacon-APIs/#/). +Esta página trata principalmente da API JSON-RPC usada pelos clientes de execução Ethereum. No entanto, os clientes de consenso também têm uma API RPC que permite aos usuários consultar informações sobre o nó, solicitar blocos Beacon, estado do Beacon, e outras informações relacionadas ao consenso diretamente de um nó. Esta API está documentada na [página da Beacon API](https://ethereum.github.io/beacon-APIs/#/). -Uma API interna também é usada para comunicação entre clientes dentro de um nó - ou seja, permite que o cliente de consenso e o cliente de execução troquem dados. Ela é chamada de “API Engine” e suas especificações estão disponíveis no [Github](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md). +Uma API interna também é usada para comunicação entre clientes dentro de um nó - ou seja, permite que o cliente de consenso e o cliente de execução troquem dados. Isso é chamado de 'Engine API' e as especificações estão disponíveis no [GitHub](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md). ## Especificação do cliente de execução {#spec} -[Leia a especificação completa da API JSON-RPC no GitHub](https://github.com/ethereum/execution-apis). Esta API está documentada na [página da Web da API de execução](https://ethereum.github.io/execution-apis/api-documentation/) e inclui um Inspetor para testar todos os métodos disponíveis. +[Leia a especificação completa da API JSON-RPC no GitHub](https://github.com/ethereum/execution-apis). Esta API está documentada na [página da web da API de Execução](https://ethereum.github.io/execution-apis/) e inclui um Inspetor para experimentar todos os métodos disponíveis. ## Convenções {#conventions} @@ -50,7 +50,7 @@ Veja aqui alguns exemplos: Ao codificar dados não formatados (arrays de bytes, endereços de contas, hashes, matrizes de bytecodes): codifique como hexadecimal, prefixe com "0x", dois dígitos hexadecimais por byte. -Aqui estão alguns exemplos: +Veja aqui alguns exemplos: - 0x41 (tamanho 1, "A") - 0x004200 (tamanho 3, "0B0") @@ -58,9 +58,9 @@ Aqui estão alguns exemplos: - ERRADO: 0xf0f0f (deve ser um número par de dígitos) - ERRADO: 004200 (deve ser prefixado 0x) -### O parâmetro de bloco padrão {#default-block} +### O parâmetro de bloco {#block-parameter} -Os métodos a seguir têm um parâmetro de bloco padrão extra: +Os seguintes métodos têm um parâmetro de bloco: - [eth_getBalance](#eth_getbalance) - [eth_getCode](#eth_getcode) @@ -68,26 +68,27 @@ Os métodos a seguir têm um parâmetro de bloco padrão extra: - [eth_getStorageAt](#eth_getstorageat) - [eth_call](#eth_call) -Quando são feitas requisições que atuam no estado da Ethereum, o último parâmetro de bloco padrão determina a altura do bloco. +Quando são feitas solicitações que consultam o estado do Ethereum, o parâmetro de bloco fornecido determina a altura do bloco. -As seguintes opções são possíveis para o parâmetro defaultBlock: +As seguintes opções são possíveis para o parâmetro de bloco: - `String HEX` - um número de bloco inteiro -- `String "earliest"` para o bloco mais antigo/de início +- `String "earliest"` para o bloco mais antigo/gênese - `String "latest"` - para o último bloco proposto -- `String "safe"` – para o último bloco de cabeçalho seguro -- `String "finalized"` – para o último bloco finalizado -- `String "pendente"` – para o estado/transações pendentes +- `String "safe"` - para o último bloco principal seguro +- `String "finalized"` - para o último bloco finalizado +- `String "pending"` - para o estado/transações pendentes ## Exemplos -Nesta página, fornecemos exemplos de como usar endpoints de API JSON_RPC individuais usando a ferramenta de linha de comando [curl](https://curl.se). Esses exemplos de endpoints individuais são encontrados abaixo na seção [Exemplos Curl](#curl-examples). Mais abaixo na página, também fornecemos um [exemplo de ponta a ponta](#usage-example) para compilar e implantar um contrato inteligente usando um nó Geth, a API JSON_RPC e curl. +Nesta página, fornecemos exemplos de como usar endpoints individuais da API JSON_RPC usando a ferramenta de linha de comando [curl](https://curl.se). Esses exemplos de endpoint individuais são encontrados abaixo na seção [Exemplos de Curl](#curl-examples). Mais adiante na página, também fornecemos um [exemplo de ponta a ponta](#usage-example) para compilar e implantar um contrato inteligente usando um nó Geth, a API JSON_RPC e o curl. -## Exemplos Curl {#curl-examples} +## Exemplos de Curl {#curl-examples} -Exemplos de uso da API JSON_RPC fazendo pedidos [curl](https://curl.se) para um nó Ethereum são fornecidos abaixo. Cada exemplo inclui uma descrição do endpoint específico, seus parâmetros, tipo de retorno e um exemplo funcional de como ele deve ser usado. +Abaixo, são fornecidos exemplos de uso da API JSON_RPC, fazendo solicitações com o [curl](https://curl.se) para um nó do Ethereum. Cada exemplo +inclui uma descrição do endpoint específico, seus parâmetros, tipo de retorno e um exemplo funcional de como ele deve ser usado. -Os pedidos curl podem retornar uma mensagem de erro relacionada ao tipo de conteúdo. Isso ocorre porque a opção `--data` define o tipo de conteúdo como `application/x-www-form-urlencoded`. Se o seu nó reclamar sobre isso, defina manualmente o cabeçalho colocando `-H "Content-Type: application/json"` no início da chamada. Os exemplos também não incluem a URL/IP & combinação de porta que deve ser o último argumento dado para curl (por exemplo, `127.0.0.1:8545`). Uma solicitação de curl completa, incluindo esses dados adicionais, tem o seguinte formato: +Os pedidos curl podem retornar uma mensagem de erro relacionada ao tipo de conteúdo. Isso ocorre porque a opção `--data` define o tipo de conteúdo para `application/x-www-form-urlencoded`. Se o seu nó reclamar sobre isso, defina manualmente o cabeçalho, inserindo `-H "Content-Type: application/json"` no início da chamada. Os exemplos também não incluem a combinação de URL/IP e porta que deve ser o último argumento dado ao curl (por exemplo, `127.0.0.1:8545`). Uma solicitação de curl completa, incluindo esses dados adicionais, tem o seguinte formato: ```shell curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}' 127.0.0.1:8545 @@ -95,7 +96,7 @@ curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","metho ## Gossip, Estado, Histórico {#gossip-state-history} -Alguns dos métodos JSON-RPC principais exigem dados da rede Ethereum, se enquadram perfeitamente em três categorias principais: _Gossip, Estado e Histórico_. Use os links nestas seções para pular para cada método ou use a tabela de conteúdos para explorar toda a lista de métodos. +Alguns métodos JSON-RPC principais exigem dados da rede Ethereum e se enquadram em três categorias principais: _Gossip, Estado e Histórico_. Use os links nestas seções para pular para cada método ou use a tabela de conteúdos para explorar toda a lista de métodos. ### Métodos Gossip {#gossip-methods} @@ -136,7 +137,7 @@ Alguns dos métodos JSON-RPC principais exigem dados da rede Ethereum, se enquad Você pode usar a [ferramenta de playground](https://ethereum-json-rpc.com) para descobrir e testar os métodos da API. Ele também mostra quais métodos e redes são suportados por vários provedores de nós. -## Métodos de API JSON-RPC {#json-rpc-methods} +## Métodos da API JSON-RPC {#json-rpc-methods} ### web3_clientVersion {#web3_clientversion} @@ -146,7 +147,7 @@ Retorna a versão atual do cliente. Nenhum -**Returnos** +**Retornos** `String` - A versão atual do cliente @@ -165,7 +166,7 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[], ### web3_sha3 {#web3_sha3} -Retorna Keccak-256 (_não_ o SHA3-256 padronizado) dos dados fornecidos. +Retorna o Keccak-256 (_não_ o SHA3-256 padronizado) dos dados fornecidos. **Parâmetros** @@ -175,16 +176,16 @@ Retorna Keccak-256 (_não_ o SHA3-256 padronizado) dos dados fornecidos. params: ["0x68656c6c6f20776f726c64"] ``` -**Retorna** +**Retornos** `DATA` - O resultado SHA3 da string fornecida. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"web3_sha3","params":["0x68656c6c6f20776f726c64"],"id":64}' -// Result +// Resultado { "id":64, "jsonrpc": "2.0", @@ -200,22 +201,22 @@ Retorna a id da rede atual. Nenhum -**Retorna** +**Retornos** -`String` - A id da rede atual. +`String` - O id da rede atual. -A lista completa das IDs da rede atual está disponível em [chainlist.org](https://chainlist.org). Alguns exemplos comuns são: +A lista completa dos IDs de rede atuais está disponível em [chainlist.org](https://chainlist.org). Alguns exemplos comuns são: -- `1`: Ethereum Mainnet -- `11155111`: Sepolia testnet -- `560048` : Hoodi testnet +- `1`: Rede Principal do Ethereum +- `11155111`: Rede de teste Sepolia +- `560048` : Rede de teste Hoodi **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"net_version","params":[],"id":67}' -// Result +// Resultado { "id":67, "jsonrpc": "2.0", @@ -225,22 +226,22 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"net_version","params":[],"id":67 ### net_listening {#net_listening} -Retorna `true` se o cliente estiver escutando ativamente as conexões de rede. +Retorna `true` se o cliente está ativamente escutando por conexões de rede. **Parâmetros** Nenhum -**Retorna** +**Retornos** -`Boolean` - `true` quando escuta, do contrário `false`. +`Booleano` - `true` quando escutando, caso contrário, `false`. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"net_listening","params":[],"id":67}' -// Result +// Resultado { "id":67, "jsonrpc":"2.0", @@ -256,16 +257,16 @@ Retorna o número de pares atualmente conectados ao cliente. Nenhum -**Retorna** +**Retornos** -`QUANTITY` - número inteiro do número de pares conectados. +`QUANTITY` - número inteiro de pares conectados. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":74}' -// Result +// Resultado { "id":74, "jsonrpc": "2.0", @@ -275,22 +276,22 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id": ### eth_protocolVersion {#eth_protocolversion} -Retorna a versão atual do protocolo Ethereum. Note que este método [não está disponível no Geth](https://github.com/ethereum/go-ethereum/pull/22064#issuecomment-788682924). +Retorna a versão atual do protocolo Ethereum. Observe que este método [não está disponível no Geth](https://github.com/ethereum/go-ethereum/pull/22064#issuecomment-788682924). **Parâmetros** Nenhum -**Retorna** +**Retornos** `String` - A versão atual do protocolo Ethereum **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_protocolVersion","params":[],"id":67}' -// Result +// Resultado { "id":67, "jsonrpc": "2.0", @@ -302,19 +303,23 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_protocolVersion","params":[] Retorna um objeto com dados sobre o status da sincronização ou `false`. + + Experimente o endpoint no playground + + **Parâmetros** Nenhum -**Retorna** +**Retornos** Os dados de retorno precisos variam entre as implementações do cliente. Todos os clientes retornam `False` quando o nó não está sincronizando, e todos os clientes retornam os seguintes campos. -`Object|Boolean`, um objeto com dados de status da sincronização ou `FALSE`, quando não está sincronizando: +`Objeto|Booleano`, um objeto com dados de status de sincronização ou `FALSE`, quando não está sincronizando: -- `startingBlock`: `QUANTITY` — O bloco no qual a importação começou (só será reiniciado após a sincronização atingir seu cabeçalho) -- `currentBlock`: `QUANTITY` — O bloco atual, o mesmo que eth_blockNumber -- `highestBlock`: `QUANTITY` — O bloco mais alto estimado +- `startingBlock`: `QUANTITY` - O bloco no qual a importação foi iniciada (só será reiniciado depois que a sincronização atingir o bloco principal) +- `currentBlock`: `QUANTITY` - O bloco atual, o mesmo que eth_blockNumber +- `highestBlock`: `QUANTITY` - O bloco mais alto estimado No entanto, os clientes individuais também podem fornecer dados adicionais. Por exemplo, Geth retorna o seguinte: @@ -362,9 +367,9 @@ Consulte a documentação do seu cliente específico para obter mais detalhes. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' -// Result +// Resultado { "id":1, "jsonrpc": "2.0", @@ -374,7 +379,7 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1} highestBlock: '0x454' } } -// Or when not syncing +// Ou quando não estiver sincronizando { "id":1, "jsonrpc": "2.0", @@ -386,22 +391,26 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1} Retorna o endereço de coinbase do cliente. -> **Nota:** Este método foi descontinuado a partir da versão **v1.14.0** e não é mais suportado. Tentar usar este método resultará em um erro de "Método não suportado". + + Experimente o endpoint no playground + + +> **Observação:** Este método foi preterido a partir da **v1.14.0** e não tem mais suporte. Tentar usar este método resultará em um erro de "Método não suportado". **Parâmetros** Nenhum -**Returnos** +**Retornos** -`DATA`, 20 bytes - O endereço atual da coinbase. +`DATA`, 20 bytes - o endereço coinbase atual. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_coinbase","params":[],"id":64}' -// Result +// Resultado { "id":64, "jsonrpc": "2.0", @@ -413,20 +422,24 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_coinbase","params":[],"id":6 Retorna a ID da cadeia usada para assinar transações protegidas contra reprodução. + + Experimente o endpoint no playground + + **Parâmetros** Nenhum -**Returnos** +**Retornos** -`chainId`, valor hexadecimal como uma cadeia de caracteres representando o inteiro da ID da cadeia atual. +`chainId`, valor hexadecimal como uma string representando o número inteiro do ID da cadeia atual. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":67}' -// Result +// Resultado { "id":67, "jsonrpc": "2.0", @@ -436,20 +449,24 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":67 ### eth_mining {#eth_mining} -Retorna `true` se o cliente estiver minerando novos blocos de maneira ativa. Isso só pode retornar `true` para redes de prova de trabalho e pode não estar disponível em alguns clientes desde a [Fusão](/roadmap/merge/). +Retorna `true` se o cliente estiver minerando ativamente novos blocos. Isso só pode retornar `true` para redes de prova de trabalho e pode não estar disponível em alguns clientes desde [A Fusão](/roadmap/merge/). + + + Experimente o endpoint no playground + **Parâmetros** Nenhum -**Returnos** +**Retornos** -`Boolean` — retorna `true` do cliente que está minerando, caso contrário, `false`. +`Booleano` - retorna `true` se o cliente estiver minerando, caso contrário, `false`. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_mining","params":[],"id":71}' // { @@ -461,22 +478,26 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_mining","params":[],"id":71} ### eth_hashrate {#eth_hashrate} -Retorna o número de hashes por segundo do nó que está minerando. Isso só pode retornar `true` para redes de prova de trabalho e pode não estar disponível em alguns clientes desde a [Fusão](/roadmap/merge/). +Retorna o número de hashes por segundo do nó que está minerando. Isso só pode retornar `true` para redes de prova de trabalho e pode não estar disponível em alguns clientes desde [A Fusão](/roadmap/merge/). + + + Experimente o endpoint no playground + **Parâmetros** Nenhum -**Returnos** +**Retornos** -`QUANTITY` — número de hashes por segundo. +`QUANTITY` - número de hashes por segundo. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_hashrate","params":[],"id":71}' -// Result +// Resultado { "id":71, "jsonrpc": "2.0", @@ -488,20 +509,24 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_hashrate","params":[],"id":7 Retorna uma estimativa do preço atual por unidade de gás em wei. Por exemplo, o cliente Besu examina os últimos 100 blocos e retorna o preço unitário médio do gás por padrão. + + Experimente o endpoint no playground + + **Parâmetros** Nenhum -**Returnos** +**Retornos** -`QUANTITY` — Número inteiro do preço atual do gás em Wei. +`QUANTITY` - número inteiro do preço do gás atual em wei. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":73}' -// Result +// Resultado { "id":73, "jsonrpc": "2.0", @@ -513,20 +538,24 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":7 Retorna uma lista de endereços de propriedade do cliente. + + Experimente o endpoint no playground + + **Parâmetros** Nenhum -**Returnos** +**Retornos** -`Array of DATA`, 20 Bytes — endereços de propriedade do cliente. +`Array de DATA`, 20 Bytes - endereços pertencentes ao cliente. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_accounts","params":[],"id":1}' -// Result +// Resultado { "id":1, "jsonrpc": "2.0", @@ -538,20 +567,24 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_accounts","params":[],"id":1 Retorna o número do bloco mais recente. + + Experimente o endpoint no playground + + **Parâmetros** Nenhum -**Returnos** +**Retornos** -`QUANTITY` — Inteiro do número do bloco atual no qual o cliente está. +`QUANTITY` - número inteiro do bloco atual em que o cliente está. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":83}' -// Result +// Resultado { "id":83, "jsonrpc": "2.0", @@ -561,27 +594,31 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id ### eth_getBalance {#eth_getbalance} -Retorna o saldo da conta do endereço fornecido. +Retorna o saldo da conta de um determinado endereço. + + + Experimente o endpoint no playground + **Parâmetros** -1. `DATA`, 20 Bytes - Endereço para verificar o saldo. -2. `QUANTITY|TAG` - número de bloco inteiro ou a string `"latest"`, `"earliest"`, `"pending"`, `"safe"` ou `"finalized"`. Consulte o [parâmetro de bloco padrão](/developers/docs/apis/json-rpc/#default-block) +1. `DATA`, 20 Bytes - endereço para verificar o saldo. +2. `QUANTITY|TAG` - número de bloco inteiro, ou a string `"latest"`, `"earliest"`, `"pending"`, `"safe"` ou `"finalized"`, veja o [parâmetro de bloco](/developers/docs/apis/json-rpc/#block-parameter) ```js params: ["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest"] ``` -**Returnos** +**Retornos** -`QUANTITY` — Inteiro do saldo atual em Wei. +`QUANTITY` - número inteiro do saldo atual em wei. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest"],"id":1}' -// Result +// Resultado { "id":1, "jsonrpc": "2.0", @@ -593,30 +630,35 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x407 Retorna o valor de uma posição de armazenamento em um determinado endereço. + + Experimente o endpoint no playground + + **Parâmetros** -1. `DATA`, 20 Bytes - Endereço do armazenamento. -2. `QUANTITY` - Número inteiro da posição no armazenamento. -3. `QUANTITY|TAG` - número de bloco inteiro ou a string `"latest"`, `"earliest"`, `"pending"`, `"safe"`, `"finalized"`. Veja o [parâmetro de bloco padrão](/developers/docs/apis/json-rpc/#default-block) +1. `DATA`, 20 Bytes - endereço do armazenamento. +2. `QUANTITY` - inteiro da posição no armazenamento. +3. `QUANTITY|TAG` - número de bloco inteiro, ou a string `"latest"`, `"earliest"`, `"pending"`, `"safe"` ou `"finalized"`, veja o [parâmetro de bloco](/developers/docs/apis/json-rpc/#block-parameter) -**Returnos** +**Retornos** -`DATA` — O valor nessa posição de armazenamento. +`DATA` - o valor nesta posição de armazenamento. -**Exemplo** O cálculo da posição correta depende do armazenamento a ser recuperado. Considere o seguinte contrato implementado em `0x295a70b2de5e3953354a6a8344e616ed314d7251` pelo endereço `0x391694e7e0b0cce554cb130d723a9d27458f9298`. +**Exemplo** +Calcular a posição correta depende do armazenamento a ser recuperado. Considere o seguinte contrato implantado em `0x295a70b2de5e3953354a6a8344e616ed314d7251` pelo endereço `0x391694e7e0b0cce554cb130d723a9d27458f9298`. ``` contract Storage { uint pos0; mapping(address => uint) pos1; - function Storage() { + constructor() { pos0 = 1234; pos1[msg.sender] = 5678; } } ``` -Recuperar o valor da pos0 é simples: +Recuperar o valor de pos0 é simples: ```js curl -X POST --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x0", "latest"], "id": 1}' localhost:8545 @@ -658,30 +700,34 @@ curl -X POST --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": [ ### eth_getTransactionCount {#eth_gettransactioncount} -Retorna o número de transações _enviadas_ a partir de um endereço. +Retorna o número de transações _enviadas_ de um endereço. + + + Experimente o endpoint no playground + **Parâmetros** -1. `DATA`, 20 Bytes - Endereço. -2. `QUANTITY|TAG` - número de bloco inteiro ou a string `"latest"`, `"earliest"`, `"pending"`, `"safe"` ou `"finalized"`. Consulte o [parâmetro de bloco padrão](/developers/docs/apis/json-rpc/#default-block) +1. `DATA`, 20 Bytes - endereço. +2. `QUANTITY|TAG` - número de bloco inteiro, ou a string `"latest"`, `"earliest"`, `"pending"`, `"safe"` ou `"finalized"`, veja o [parâmetro de bloco](/developers/docs/apis/json-rpc/#block-parameter) ```js params: [ "0x407d73d8a49eeb85d32cf465507dd71d507100c1", - "latest", // state at the latest block + "latest", // estado no bloco mais recente ] ``` -**Returnos** +**Retornos** -`QUANTITY` — Inteiro do número de transações enviadas a partir desse endereço. +`QUANTITY` - inteiro do número de transações enviadas a partir deste endereço. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["0x407d73d8a49eeb85d32cf465507dd71d507100c1","latest"],"id":1}' -// Result +// Resultado { "id":1, "jsonrpc": "2.0", @@ -693,17 +739,21 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionCount","params Retorna o número de transações em um bloco a partir de um bloco que corresponde ao hash de bloco fornecido. + + Experimente o endpoint no playground + + **Parâmetros** -1. `DATA`, 32 bytes - Hash de um bloco +1. `DATA`, 32 Bytes - hash de um bloco ```js params: ["0xd03ededb7415d22ae8bac30f96b2d1de83119632693b963642318d87d1bece5b"] ``` -**Returnos** +**Retornos** -`QUANTITY` — Inteiro do número de transações nesse bloco. +`QUANTITY` - inteiro do número de transações neste bloco. **Exemplo** @@ -722,9 +772,13 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockTransactionCountByHa Retorna o número de transações em um bloco a partir de um bloco que corresponde ao hash de bloco fornecido. + + Experimente o endpoint no playground + + **Parâmetros** -1. `QUANTITY|TAG` - inteiro de um número de bloco, ou a string `"earliest"`, `"latest"`, `"pending"`, `"safe"` ou `"finalized"`, como no [parâmetro de bloco padrão](/developers/docs/apis/json-rpc/#default-block). +1. `QUANTITY|TAG` - inteiro de um número de bloco ou a string `"earliest"`, `"latest"`, `"pending"`, `"safe"` ou `"finalized"`, como no [parâmetro de bloco](/developers/docs/apis/json-rpc/#block-parameter). ```js params: [ @@ -732,9 +786,9 @@ params: [ ] ``` -**Returnos** +**Retornos** -`QUANTITY` — Inteiro do número de transações nesse bloco. +`QUANTITY` - inteiro do número de transações neste bloco. **Exemplo** @@ -753,17 +807,21 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockTransactionCountByNu Retorna o número de transações em um bloco a partir de um bloco que corresponde ao hash de bloco fornecido. + + Experimente o endpoint no playground + + **Parâmetros** -1. `DADOS`, 32 bytes - hash de um bloco +1. `DATA`, 32 Bytes - hash de um bloco ```js params: ["0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2"] ``` -**Returnos** +**Retornos** -`QUANTITY` — Inteiro do número de transações nesse bloco. +`QUANTITY` - inteiro do número de tios neste bloco. **Exemplo** @@ -782,9 +840,13 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getUncleCountByBlockHash","p Retorna o número de transações em um bloco a partir de um bloco que corresponde ao hash de bloco fornecido. + + Experimente o endpoint no playground + + **Parâmetros** -1. `QUANTITY|TAG` - inteiro de um número de bloco, ou a string `"latest"`, `"earliest"`, `"pending"`, `"safe"` ou `"finalized"`. Veja o [parâmetro de bloco padrão](/developers/docs/apis/json-rpc/#default-block) +1. `QUANTITY|TAG` - inteiro de um número de bloco, ou a string `"latest"`, `"earliest"`, `"pending"`, `"safe"` ou `"finalized"`, veja o [parâmetro de bloco](/developers/docs/apis/json-rpc/#block-parameter) ```js params: [ @@ -792,9 +854,9 @@ params: [ ] ``` -**Returnos** +**Retornos** -`QUANTITY` — Inteiro do número de transações nesse bloco. +`QUANTITY` - inteiro do número de tios neste bloco. **Exemplo** @@ -813,10 +875,14 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getUncleCountByBlockNumber", Retorna o código em um endereço fornecido. + + Experimente o endpoint no playground + + **Parâmetros** -1. `DATA`, 20 Bytes - Endereço -2. `QUANTITY|TAG` - número de bloco inteiro ou a string `"latest"`, `"earliest"`, `"pending"`, `"safe"` ou `"finalized"`. Consulte o [parâmetro de bloco padrão](/developers/docs/apis/json-rpc/#default-block) +1. `DATA`, 20 Bytes - endereço +2. `QUANTITY|TAG` - número de bloco inteiro, ou a string `"latest"`, `"earliest"`, `"pending"`, `"safe"` ou `"finalized"`, veja o [parâmetro de bloco](/developers/docs/apis/json-rpc/#block-parameter) ```js params: [ @@ -825,9 +891,9 @@ params: [ ] ``` -**Returnos** +**Retornos** -`DATA` — O código do endereço fornecido. +`DATA` - o código do endereço fornecido. **Exemplo** @@ -846,25 +912,25 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getCode","params":["0xC02aaA O método de assinatura calcula uma assinatura específica do Ethereum com: `sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)))`. -Ao adicionar um prefixo à mensagem, a assinatura calculada é reconhecível como uma assinatura específica do Ethereum. Isso evita o uso indevido por parte de um dapp malicioso, que pode assinar dados arbitrários (por exemplo, de transação) e usar a assinatura para usar a identidade da vítima. +Ao adicionar um prefixo à mensagem, a assinatura calculada é reconhecível como uma assinatura específica do Ethereum. Isso evita o uso indevido, no qual um dapp mal-intencionado pode assinar dados arbitrários (por exemplo, uma transação) e usar a assinatura para se passar pela vítima. Observação: o endereço de assinatura deve estar desbloqueado. **Parâmetros** -1. `DADOS`, 20 Bytes - endereço -2. `DATA`, N Bytes - Mensagem para assinar +1. `DATA`, 20 Bytes - endereço +2. `DATA`, N Bytes - mensagem a ser assinada -**Returnos** +**Retornos** -`DATA`: assinatura +`DATA`: Assinatura **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sign","params":["0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", "0xdeadbeaf"],"id":1}' -// Result +// Resultado { "id":1, "jsonrpc": "2.0", @@ -880,25 +946,25 @@ Assina uma transação que pode ser enviada à rede posteriormente usando [eth_s 1. `Objeto` - O objeto da transação -- `type`: -- `from`: `DATA`, 20 Bytes — Endereço de onde a transação é enviada. -- `to`: `DATA`, 20 Bytes — (opcional ao criar um novo contrato) O endereço para o qual a transação é direcionada. -- `gas`: `QUANTITY` — (opcional, padrão: 90000) Inteiro do gás fornecido para a execução da transação. Retornará o gás não utilizado. -- `gasPrice`: `QUANTITY` — (opcional, padrão: a ser determinado) Inteiro do gasPrice usado para cada gás pago, em Wei. -- `valor`: `QUANTITY` — (opcional) Inteiro do valor enviado com esta transação, em Wei. -- `data`: `DATA` — Código compilado de um contrato OU do hash da assinatura do método invocado e parâmetros codificados. -- `nonce`: `QUANTITY` — (opcional) Inteiro de um nonce. Isso permite substituir suas próprias transações pendentes que usam o mesmo nonce. +- `tipo`: +- `from`: `DATA`, 20 Bytes - O endereço de onde a transação é enviada. +- `to`: `DATA`, 20 Bytes - (opcional ao criar um novo contrato) O endereço para o qual a transação é direcionada. +- `gas`: `QUANTITY` - (opcional, padrão: 90000) Inteiro do gás fornecido para a execução da transação. Retornará o gás não utilizado. +- `gasPrice`: `QUANTITY` - (opcional, padrão: a ser determinado) Inteiro do gasPrice usado para cada gás pago, em Wei. +- `value`: `QUANTITY` - (opcional) Inteiro do valor enviado com esta transação, em Wei. +- `data`: `DATA` - O código compilado de um contrato OU o hash da assinatura do método invocado e parâmetros codificados. +- `nonce`: `QUANTITY` - (opcional) Inteiro de um nonce. Isso permite substituir suas próprias transações pendentes que usam o mesmo nonce. -**Returnos** +**Retornos** -`DATA`: o objeto de transação codificado em RLP assinado pela conta especificada. +`DATA`, o objeto da transação codificado por RLP e assinado pela conta especificada. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"id": 1,"jsonrpc": "2.0","method": "eth_signTransaction","params": [{"data":"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675","from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155","gas": "0x76c0","gasPrice": "0x9184e72a000","to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567","value": "0x9184e72a"}]}' -// Result +// Resultado { "id": 1, "jsonrpc": "2.0", @@ -908,19 +974,19 @@ curl -X POST --data '{"id": 1,"jsonrpc": "2.0","method": "eth_signTransaction"," ### eth_sendTransaction {#eth_sendtransaction} -Cria uma nova transação de chamada de mensagem ou uma criação de contrato, se o campo de dados contiver código, e o assina usando a conta especificada `em`. +Cria uma nova transação de chamada de mensagem ou uma criação de contrato, se o campo de dados contiver código, e o assina usando a conta especificada em `from`. **Parâmetros** -1. `Object` - O objeto da transação +1. `Objeto` - O objeto da transação -- `from`: `DATA`, 20 Bytes — Endereço de onde a transação é enviada. -- `to`: `DATA`, 20 Bytes — (opcional ao criar um novo contrato) O endereço para o qual a transação é direcionada. -- `gas`: `QUANTITY` — (opcional, padrão: 90000) Inteiro do gás fornecido para a execução da transação. Retornará o gás não utilizado. -- `gasPrice`: `QUANTITY` — (opcional, padrão: a ser determinado) Inteiro do gasPrice usado para cada gás pago. -- `valor`: `QUANTITY` — (opcional) Inteiro do valor enviado com esta transação. +- `from`: `DATA`, 20 Bytes - O endereço de onde a transação é enviada. +- `to`: `DATA`, 20 Bytes - (opcional ao criar um novo contrato) O endereço para o qual a transação é direcionada. +- `gas`: `QUANTITY` - (opcional, padrão: 90000) Inteiro do gás fornecido para a execução da transação. Retornará o gás não utilizado. +- `gasPrice`: `QUANTITY` - (opcional, padrão: a ser determinado) Inteiro do gasPrice usado para cada gás pago. +- `value`: `QUANTITY` - (opcional) Inteiro do valor enviado com esta transação. - `input`: `DATA` - O código compilado de um contrato OU o hash da assinatura do método invocado e dos parâmetros codificados. -- `nonce`: `QUANTITY` — (opcional) Inteiro de um nonce. Isso permite substituir suas próprias transações pendentes que usam o mesmo nonce. +- `nonce`: `QUANTITY` - (opcional) Inteiro de um nonce. Isso permite substituir suas próprias transações pendentes que usam o mesmo nonce. ```js params: [ @@ -936,18 +1002,18 @@ params: [ ] ``` -**Returnos** +**Retornos** -`DATA`, 32 Bytes — O hash da transação ou o hash zero se a transação ainda não estiver disponível. +`DATA`, 32 Bytes - o hash da transação, ou o hash zero se a transação ainda não estiver disponível. Use [eth_getTransactionReceipt](#eth_gettransactionreceipt) para obter o endereço do contrato, depois de a transação ter sido proposta em um bloco, quando você criou um contrato. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{see above}],"id":1}' -// Result +// Resultado { "id":1, "jsonrpc": "2.0", @@ -961,7 +1027,7 @@ Cria uma nova transação de chamada de mensagem ou um contrato para transaçõe **Parâmetros** -1. `DATA`, O objeto de transação assinada. +1. `DATA`, Os dados da transação assinada. ```js params: [ @@ -969,18 +1035,18 @@ params: [ ] ``` -**Returnos** +**Retornos** -`DATA`, 32 Bytes — O hash da transação ou o hash zero se a transação ainda não estiver disponível. +`DATA`, 32 Bytes - o hash da transação, ou o hash zero se a transação ainda não estiver disponível. Use [eth_getTransactionReceipt](#eth_gettransactionreceipt) para obter o endereço do contrato, depois de a transação ter sido proposta em um bloco, quando você criou um contrato. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":[{see above}],"id":1}' -// Result +// Resultado { "id":1, "jsonrpc": "2.0", @@ -990,31 +1056,35 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params" ### eth_call {#eth_call} -Executa uma nova chamada de mensagem imediatamente sem criar uma transação na blockchain. Frequentemente usado para executar funções de contrato inteligente somente leitura, por exemplo, o `balanceOf` para um contrato ERC-20. +Executa uma nova chamada de mensagem imediatamente sem criar uma transação no blockchain. Frequentemente usado para executar funções de contrato inteligente somente leitura, por exemplo, o `balanceOf` para um contrato ERC-20. + + + Experimente o endpoint no playground + **Parâmetros** -1. `Object` - O objeto de chamada de transação +1. `Objeto` - O objeto de chamada de transação -- `from`: `DATA`, 20 Bytes — (opcional) O endereço a partir do qual a transação é enviada. -- `to`: `DATA`, 20 Bytes — O endereço para o qual a transação é direcionada. -- `gas`: `QUANTITY` — (opcional) Inteiro do gás fornecido para a execução da transação. eth_call consome zero gás, mas este parâmetro pode ser necessário para algumas execuções. -- `gasPrice`: `QUANTITY` — (opcional) Inteiro do gasPrice usado para cada gás pago -- `valor`: `QUANTITY` — (opcional) Inteiro do valor enviado com esta transação -- `input`: `DATA` - (opcional) Hash da assinatura do método e parâmetros codificados. Para obter mais detalhes, consulte o [Contrato Ethereum ABI na documentação do Solidity](https://docs.soliditylang.org/en/latest/abi-spec.html). +- `from`: `DATA`, 20 Bytes - (opcional) O endereço de onde a transação é enviada. +- `to`: `DATA`, 20 Bytes - O endereço para o qual a transação é direcionada. +- `gas`: `QUANTITY` - (opcional) Inteiro do gás fornecido para a execução da transação. eth_call consome zero gás, mas este parâmetro pode ser necessário para algumas execuções. +- `gasPrice`: `QUANTITY` - (opcional) Inteiro do gasPrice usado para cada gás pago +- `value`: `QUANTITY` - (opcional) Inteiro do valor enviado com esta transação +- `input`: `DATA` - (opcional) Hash da assinatura do método e parâmetros codificados. Para obter detalhes, consulte [IAB do Contrato Ethereum na documentação do Solidity](https://docs.soliditylang.org/en/latest/abi-spec.html). -2. `QUANTITY|TAG` - número de bloco inteiro ou a string `"latest"`, `"earliest"`, `"pending"`, `"safe"` ou `"finalized"`. Consulte o [parâmetro de bloco padrão](/developers/docs/apis/json-rpc/#default-block) +2. `QUANTITY|TAG` - número de bloco inteiro, ou a string `"latest"`, `"earliest"`, `"pending"`, `"safe"` ou `"finalized"`, veja o [parâmetro de bloco](/developers/docs/apis/json-rpc/#block-parameter) -**Returnos** +**Retornos** -`DATA` — O valor de retorno do contrato executado. +`DATA` - o valor de retorno do contrato executado. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{see above}],"id":1}' -// Result +// Resultado { "id":1, "jsonrpc": "2.0", @@ -1026,20 +1096,24 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{see above}] Gera e retorna uma estimativa de quantas unidades de gás são necessárias para permitir que a transação seja concluída. A transação não será adicionada à blockchain. Observe que a estimativa pode ser significativamente maior do que a quantidade de gás realmente usada pela transação, por vários motivos, incluindo a mecânica do EVM e o desempenho do nó. + + Experimente o endpoint no playground + + **Parâmetros** -Veja os parâmetros do [eth_call](#eth_call), a menos que todas as propriedades sejam opcionais. Se nenhum limite de gás é especificado, o geth usa o limite de gás do bloco pendente como um limite superior. Consequentemente, a estimativa retornada poderá não ser suficiente para executar a chamada/transação quando a quantidade de gás for maior que o limite de gás do bloco pendente. +Consulte os parâmetros de [eth_call](#eth_call), exceto que todas as propriedades são opcionais. Se nenhum limite de gás é especificado, o geth usa o limite de gás do bloco pendente como um limite superior. Como resultado, a estimativa retornada pode não ser suficiente para executar a chamada/transação quando a quantidade de gás for maior que o limite de gás do bloco pendente. -**Returnos** +**Retornos** -`QUANTITY` — A quantidade de gás usada. +`QUANTITY` - a quantidade de gás usada. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_estimateGas","params":[{see above}],"id":1}' -// Result +// Resultado { "id":1, "jsonrpc": "2.0", @@ -1051,10 +1125,14 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_estimateGas","params":[{see Retorna informações sobre um bloco por hash. + + Experimente o endpoint no playground + + **Parâmetros** 1. `DATA`, 32 Bytes - Hash de um bloco. -2. `Boolean` - Se `true` retorna os objetos de transação completos, se `false` apenas os hashes das transações. +2. `Booleano` - Se `true`, retorna os objetos de transação completos; se `false`, apenas os hashes das transações. ```js params: [ @@ -1063,41 +1141,40 @@ params: [ ] ``` -**Returnos** - -`Object` — Um objeto de bloco, ou `null` quando nenhum bloco foi encontrado: - -- `number`: `QUANTITY` — O número do bloco. `null` quando o bloco está pendente. -- `hash`: `DATA`, 32 Bytes — Hash do bloco. `null` quando o bloco está pendente. -- `parentHash`: `DATA`, 32 Bytes — Hash do bloco pai. -- `nonce`: `DATA`, 8 Bytes — Hash da prova de trabalho gerada. `null` quando o bloco está pendente. -- `sha3Uncles`: `DATA`, 32 Bytes — SHA3 dos dados tios no bloco. -- `logsBloom`: `DATA`, 256 Bytes — O filtro bloom para os logs do bloco. `null` quando o bloco está pendente. -- `transactionsRoot`: `DATA`, 32 Bytes — A raiz da árvore de transação do bloco. -- `stateRoot`: `DATA`, 32 Bytes — A raiz da árvore do estado final do bloco. -- `receiptsRoot`: `DATA`, 32 Bytes — A raiz da árvore de itens recebidos do bloco. -- `miner`: `DATA`, 20 Bytes — O endereço do beneficiário a quem as recompensas de mineração foram dadas. -- `dificuldade`: `QUANTITY` — Inteiro da dificuldade para este bloco. -- `totalDifficulty`: `QUANTITY` — Inteiro da dificuldade total da cadeia até este bloco. -- `extraData`: `DATA` — O campo “dados extras” deste bloco. -- `size`: `QUANTITY` — Inteiro do tamanho deste bloco em bytes. -- `gasLimit`: `QUANTITY` — O gás máximo permitido neste bloco. -- `gasUsed`: `QUANTITY` — O total de gás usado por todas as transações neste bloco. -- `timestamp`: `QUANTITY` — O carimbo de data/hora unix no momento em que o bloco foi agrupado. -- `transactions`: `Array` — Matriz de objetos de transação ou hashes de transação de 32 bytes, dependendo do último parâmetro fornecido. -- `uncles`: `Array` — Matriz de hashes tio. +**Retornos** + +`Objeto` - Um objeto de bloco, ou `nulo` quando nenhum bloco foi encontrado: + +- `number`: `QUANTITY` - o número do bloco. `null` quando o bloco está pendente. +- `hash`: `DATA`, 32 Bytes - hash do bloco. `null` quando o bloco está pendente. +- `parentHash`: `DATA`, 32 Bytes - hash do bloco pai. +- `nonce`: `DATA`, 8 Bytes - hash da prova de trabalho gerada. `null` quando seu bloco estiver pendente, `0x0` para blocos de prova de participação (desde A Fusão) +- `sha3Uncles`: `DATA`, 32 Bytes - SHA3 dos dados dos tios no bloco. +- `logsBloom`: `DATA`, 256 Bytes - o filtro bloom para os logs do bloco. `null` quando o bloco está pendente. +- `transactionsRoot`: `DATA`, 32 Bytes - a raiz da árvore de transação do bloco. +- `stateRoot`: `DATA`, 32 Bytes - a raiz da árvore do estado final do bloco. +- `receiptsRoot`: `DATA`, 32 Bytes - a raiz da árvore de recibos do bloco. +- `miner`: `DATA`, 20 Bytes - o endereço do beneficiário a quem as recompensas do bloco foram dadas. +- `difficulty`: `QUANTITY` - inteiro da dificuldade para este bloco. +- `totalDifficulty`: `QUANTITY` - inteiro da dificuldade total da cadeia até este bloco. +- `extraData`: `DATA` - o campo "dados extras" deste bloco. +- `size`: `QUANTITY` - inteiro do tamanho deste bloco em bytes. +- `gasLimit`: `QUANTITY` - o gás máximo permitido neste bloco. +- `gasUsed`: `QUANTITY` - o total de gás usado por todas as transações neste bloco. +- `timestamp`: `QUANTITY` - o carimbo de data/hora unix no momento em que o bloco foi agrupado. +- `transactions`: `Array` - Matriz de objetos de transação, ou hashes de transação de 32 Bytes, dependendo do último parâmetro fornecido. +- `uncles`: `Array` - Matriz de hashes tio. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockByHash","params":["0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae", false],"id":1}' -// Result -{ +// Resultado { -"jsonrpc": "2.0", -"id": 1, -"result": { + "jsonrpc": "2.0", + "id": 1, + "result": { "difficulty": "0x4ea3f27bc", "extraData": "0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32", "gasLimit": "0x1388", @@ -1120,7 +1197,7 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockByHash","params":["0 "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncles": [ ] -} + } } ``` @@ -1128,10 +1205,14 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockByHash","params":["0 Retorna informações sobre um bloco por número de bloco. + + Experimente o endpoint no playground + + **Parâmetros** -1. `QUANTITY|TAG` - inteiro de um número de bloco, ou a string `"earliest"`, `"latest"`, `"pending"`, `"safe"` ou `"finalized"`, como no [parâmetro de bloco padrão](/developers/docs/apis/json-rpc/#default-block). -2. `Boolean` - Se `true` retorna os objetos de transação completos, se `false` apenas os hashes das transações. +1. `QUANTITY|TAG` - inteiro de um número de bloco ou a string `"earliest"`, `"latest"`, `"pending"`, `"safe"` ou `"finalized"`, como no [parâmetro de bloco](/developers/docs/apis/json-rpc/#block-parameter). +2. `Booleano` - Se `true`, retorna os objetos de transação completos; se `false`, apenas os hashes das transações. ```js params: [ @@ -1140,21 +1221,26 @@ params: [ ] ``` -**Retorna** Consulte [eth_getBlockByHash](#eth_getblockbyhash) +**Retornos** +Consulte [eth_getBlockByHash](#eth_getblockbyhash) **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x1b4", true],"id":1}' ``` -Veja o resultado [eth_getBlockByHash](#eth_getblockbyhash) +Resultado: consulte [eth_getBlockByHash](#eth_getblockbyhash) ### eth_getTransactionByHash {#eth_gettransactionbyhash} Retorna as informações sobre uma transação solicitada pelo hash de transação. + + Experimente o endpoint no playground + + **Parâmetros** 1. `DATA`, 32 Bytes - hash de uma transação @@ -1163,31 +1249,31 @@ Retorna as informações sobre uma transação solicitada pelo hash de transaç params: ["0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b"] ``` -**Returnos** +**Retornos** -`Object` — Um objeto de transação ou `null` quando nenhuma transação foi encontrada: +`Objeto` - Um objeto de transação ou `null` quando nenhuma transação foi encontrada: -- `blockHash`: `DATA`, 32 Bytes — Hash do bloco onde esta transação estava localizada. `null` quando está pendente. -- `blockNumber`: `QUANTITY` — Número do bloco onde esta transação estava localizada. `null` quando está pendente. -- `from`: `DATA`, 20 Bytes — Endereço do remetente. -- `gás`: `QUANTITY` — Gás fornecido pelo remetente. -- `gasPrice`: `QUANTITY` — Preço do gás fornecido pelo remetente em Wei. -- `hash`: `DATA`, 32 Bytes — Hash da transação. -- `input`: `DATA` — Os dados enviados com a transação. -- `nonce`: `QUANTITY` — O número de transações feitas pelo remetente antes desta. -- `to`: `DATA`, 20 Bytes — Endereço do destinatário. `null` quando for uma transação de criação de contrato. -- `transactionIndex`: `QUANTITY` — Inteiro da posição do índice de transações no bloco. `null` quando está pendente. -- `valor`: `QUANTITY` — Valor transferido em Wei. -- `v`: `QUANTITY` — ID de recuperação ECDSA -- `r`: `QUANTITY` — Assinatura ECDSA r -- `s`: `QUANTITY` — Assinatura ECDSA s +- `blockHash`: `DATA`, 32 Bytes - hash do bloco onde esta transação estava localizada. `null` quando está pendente. +- `blockNumber`: `QUANTITY` - número do bloco onde esta transação estava localizada. `null` quando está pendente. +- `from`: `DATA`, 20 Bytes - endereço do remetente. +- `gas`: `QUANTITY` - gás fornecido pelo remetente. +- `gasPrice`: `QUANTITY` - preço do gás fornecido pelo remetente em Wei. +- `hash`: `DATA`, 32 Bytes - hash da transação. +- `input`: `DATA` - os dados enviados com a transação. +- `nonce`: `QUANTITY` - o número de transações feitas pelo remetente antes desta. +- `to`: `DATA`, 20 Bytes - endereço do destinatário. `null` quando for uma transação de criação de contrato. +- `transactionIndex`: `QUANTITY` - inteiro da posição do índice de transações no bloco. `null` quando está pendente. +- `value`: `QUANTITY` - valor transferido em Wei. +- `v`: `QUANTITY` - ID de recuperação ECDSA +- `r`: `QUANTITY` - Assinatura ECDSA r +- `s`: `QUANTITY` - Assinatura ECDSA s **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b"],"id":1}' -// Result +// Resultado { "jsonrpc":"2.0", "id":1, @@ -1214,10 +1300,14 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","param Retorna informações sobre uma transação por hash de bloco e a posição do índice de transação. + + Experimente o endpoint no playground + + **Parâmetros** -1. `DATA`, 32 Bytes - Hash de um bloco. -2. `QUANTITY` - Inteiro da posição do índice da transação. +1. `DATA`, 32 Bytes - hash de um bloco. +2. `QUANTITY` - inteiro da posição do índice da transação. ```js params: [ @@ -1226,7 +1316,8 @@ params: [ ] ``` -**Retorna** Consulte [eth_getTransactionByHash](#eth_gettransactionbyhash) +**Retornos** +Consulte [eth_getTransactionByHash](#eth_gettransactionbyhash) **Exemplo** @@ -1235,16 +1326,20 @@ params: [ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionByBlockHashAndIndex","params":["0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2", "0x0"],"id":1}' ``` -Resultado. Veja [eth_getTransactionByHash](#eth_gettransactionbyhash) +Resultado: consulte [eth_getTransactionByHash](#eth_gettransactionbyhash) ### eth_getTransactionByBlockNumberAndIndex {#eth_gettransactionbyblocknumberandindex} Retorna informações sobre uma transação pelo número do bloco e posição do índice da transação. + + Experimente o endpoint no playground + + **Parâmetros** -1. `QUANTITY|TAG` - um número de bloco ou a string `"earliest"`, `"latest"`, `"pending"`, `"safe"` ou `"finalized"`, como no [parâmetro de bloco padrão](/developers/docs/apis/json-rpc/#default-block). -2. `QUANTITY` - A posição do índice da transação. +1. `QUANTITY|TAG` - um número de bloco, ou a string `"earliest"`, `"latest"`, `"pending"`, `"safe"` ou `"finalized"`, como no [parâmetro de bloco](/developers/docs/apis/json-rpc/#block-parameter). +2. `QUANTITY` - a posição do índice da transação. ```js params: [ @@ -1253,58 +1348,60 @@ params: [ ] ``` -**Retorna** Consulte [eth_getTransactionByHash](#eth_gettransactionbyhash) +**Retornos** +Consulte [eth_getTransactionByHash](#eth_gettransactionbyhash) **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionByBlockNumberAndIndex","params":["0x9c47cf", "0x24"],"id":1}' ``` -Resultado. Veja [eth_getTransactionByHash](#eth_gettransactionbyhash) +Resultado: consulte [eth_getTransactionByHash](#eth_gettransactionbyhash) ### eth_getTransactionReceipt {#eth_gettransactionreceipt} Retorna o recebimento de uma transação pelo hash de transação. -**Observe** que o recibo não está disponível para transações pendentes. +**Observação** Que o recibo não está disponível para transações pendentes. **Parâmetros** -1. `DADOS`, 32 bytes - hash de um bloco +1. `DATA`, 32 Bytes - hash de uma transação ```js params: ["0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c5"] ``` -**Retorna** `Object` — Um objeto de recebimento de transação, ou `null` quando nenhum recebimento foi encontrado: +**Retornos** +`Objeto` - Um objeto de recibo de transação, ou `null` quando nenhum recibo foi encontrado: -- `transactionHash`: `DATA`, 32 Bytes — Hash da transação. -- `transactionIndex`: `QUANTITY` — Inteiro da posição do índice de transações no bloco. -- `blockHash`: `DATA`, 32 Bytes — Hash do bloco onde esta transação estava localizada. -- `blockNumber`: `QUANTITY` — Número do bloco onde esta transação estava localizada. -- `from`: `DATA`, 20 Bytes — Endereço do remetente. -- `to`: `DATA`, 20 Bytes — Endereço do destinatário. null quando for uma transação de criação de contrato. -- `cumulativeGasUsed` : `QUANTITY` — A quantidade total de gás utilizada quando esta transação foi executada no bloco. -- `effectiveGasPrice` : `QUANTITY` — A soma da taxa base e gorjeta pagas por unidade de gás. -- `gasUsed`: `QUANTITY` — A quantidade de gás usada apenas por esta transação específica. -- `contractAddress`: `DATA`, 20 Bytes — O endereço do contrato criado, se a transação era uma criação do contrato, caso contrário `null`. -- `logs`: `Array` — Matriz de objetos de log gerados por esta transação. -- `logsBloom`: `DATA`, 256 Bytes — Filtro Bloom para clientes leves para recuperar rapidamente os logs relacionados. -- `type`: `QUANTITY` — Inteiro do tipo de transação, `0x0` para transações herdadas, `0x1` para tipos de lista de acesso, `0x2` para taxas dinâmicas. +- `transactionHash `: `DATA`, 32 Bytes - hash da transação. +- `transactionIndex`: `QUANTITY` - inteiro da posição do índice de transações no bloco. +- `blockHash`: `DATA`, 32 Bytes - hash do bloco onde esta transação estava localizada. +- `blockNumber`: `QUANTITY` - número do bloco onde esta transação estava localizada. +- `from`: `DATA`, 20 Bytes - endereço do remetente. +- `to`: `DATA`, 20 Bytes - endereço do destinatário. null quando for uma transação de criação de contrato. +- `cumulativeGasUsed` : `QUANTITY ` - A quantidade total de gás utilizada quando esta transação foi executada no bloco. +- `effectiveGasPrice` : `QUANTITY` - A soma da taxa base e gorjeta pagas por unidade de gás. +- `gasUsed `: `QUANTITY ` - A quantidade de gás usada apenas por esta transação específica. +- `contractAddress `: `DATA`, 20 Bytes - O endereço do contrato criado, se a transação foi uma criação de contrato, caso contrário, `null`. +- `logs`: `Array` - Matriz de objetos de log gerados por esta transação. +- `logsBloom`: `DATA`, 256 Bytes - Filtro Bloom para clientes leves para recuperar rapidamente os logs relacionados. +- `type`: `QUANTITY` - inteiro do tipo de transação, `0x0` para transações legadas, `0x1` para tipos de lista de acesso, `0x2` para taxas dinâmicas. -Ele também retorna _seja_ : +Também retorna _seja_: -- `root` : `DATA` 32 bytes de stateRoot pós-transação (anterior à atualização Byzantium) -- `status`: `QUANTITY` seja `1` (êxito) ou `0` (falha) +- `root`: `DATA` 32 bytes da raiz do estado pós-transação (pré-Byzantium) +- `status`: `QUANTITY` seja `1` (sucesso) ou `0` (falha) **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c5"],"id":1}' -// Result +// Resultado { "jsonrpc": "2.0", "id": 1, @@ -1312,15 +1409,15 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","para "blockHash": "0xa957d47df264a31badc3ae823e10ac1d444b098d9b73d204c40426e57f47e8c3", "blockNumber": "0xeff35f", - "contractAddress": null, // string of the address if it was created + "contractAddress": null, // string do endereço se ele foi criado "cumulativeGasUsed": "0xa12515", "effectiveGasPrice": "0x5a9c688d4", "from": "0x6221a9c005f6e47eb398fd867784cacfdcfff4e7", "gasUsed": "0xb4c8", "logs": [{ - // logs as returned by getFilterLogs, etc. + // logs como retornado por getFilterLogs, etc. }], - "logsBloom": "0x00...0", // 256 byte bloom filter + "logsBloom": "0x00...0", // filtro bloom de 256 bytes "status": "0x1", "to": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "transactionHash": @@ -1333,7 +1430,11 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","para ### eth_getUncleByBlockHashAndIndex {#eth_getunclebyblockhashandindex} -Retorna informações sobre o tio de um bloco por hash e a posição do índice de um tio. +Retorna informações sobre um tio de um bloco por hash e posição de índice do tio. + + + Experimente o endpoint no playground + **Parâmetros** @@ -1347,7 +1448,8 @@ params: [ ] ``` -**Retorna** Consulte [eth_getBlockByHash](#eth_getblockbyhash) +**Retornos** +Consulte [eth_getBlockByHash](#eth_getblockbyhash) **Exemplo** @@ -1356,18 +1458,22 @@ params: [ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getUncleByBlockHashAndIndex","params":["0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2", "0x0"],"id":1}' ``` -Veja o resultado [eth_getBlockByHash](#eth_getblockbyhash) +Resultado: consulte [eth_getBlockByHash](#eth_getblockbyhash) -**Observação**: um tio (bloco) não contém transações individuais. +**Observação**: um tio não contém transações individuais. ### eth_getUncleByBlockNumberAndIndex {#eth_getunclebyblocknumberandindex} -Retorna informações sobre um tio de um bloco por número e posição do índice tio. +Retorna informações sobre um tio de um bloco por número e posição do índice do tio. + + + Experimente o endpoint no playground + **Parâmetros** -1. `QUANTITY|TAG` - um número de bloco ou a string `"earliest"`, `"latest"`, `"pending"`, `"safe"`, `"finalized"`, como no [parâmetro de bloco padrão](/developers/docs/apis/json-rpc/#default-block). -2. `QUANTITY` - A posição do índice tio. +1. `QUANTITY|TAG` - um número de bloco, ou a string `"earliest"`, `"latest"`, `"pending"`, `"safe"`, `"finalized"`, como no [parâmetro de bloco](/developers/docs/apis/json-rpc/#block-parameter). +2. `QUANTITY` - a posição do índice tio. ```js params: [ @@ -1376,38 +1482,41 @@ params: [ ] ``` -**Retorna** Consulte [eth_getBlockByHash](#eth_getblockbyhash) +**Retornos** +Consulte [eth_getBlockByHash](#eth_getblockbyhash) -**Observação**: um tio (bloco) não contém transações individuais. +**Observação**: um tio não contém transações individuais. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getUncleByBlockNumberAndIndex","params":["0x29c", "0x0"],"id":1}' ``` -Veja o resultado [eth_getBlockByHash](#eth_getblockbyhash) +Resultado: consulte [eth_getBlockByHash](#eth_getblockbyhash) ### eth_newFilter {#eth_newfilter} -Cria um objeto de filtro, com base nas opções de filtro, para notificar quando o estado é alterado (logs). Para verificar se o estado mudou, chame [eth_getFilterChanges](#eth_getfilterchanges). +Cria um objeto de filtro, com base nas opções de filtro, para notificar quando o estado é alterado (logs). +Para verificar se o estado mudou, chame [eth_getFilterChanges](#eth_getfilterchanges). -**Observação sobre a especificação de filtros de tópicos:** Os tópicos são dependentes da ordem. Uma transação com um log com tópicos [A, B] será combinada pelos seguintes filtros de tópicos: +**Uma observação sobre a especificação de filtros de tópicos:** +Os tópicos dependem da ordem. Uma transação com um log com tópicos [A, B] será combinada pelos seguintes filtros de tópicos: -- `[]` “qualquer coisa” -- `[A]` “A na primeira posição (e qualquer coisa depois)” -- `[null, B]` “qualquer coisa na primeira posição E B na segunda posição (e qualquer coisa depois)” -- `[A, B]` “A na primeira posição E B na segunda posição (e qualquer coisa depois)” -- `[[A, B], [A, B]]` “(A OU B) na primeira posição E (A OU B) na segunda posição (e qualquer coisa depois)” +- `[]` "qualquer coisa" +- `[A]` "A na primeira posição (e qualquer coisa depois)" +- `[null, B]` "qualquer coisa na primeira posição E B na segunda posição (e qualquer coisa depois)" +- `[A, B]` "A na primeira posição E B na segunda posição (e qualquer coisa depois)" +- `[[A, B], [A, B]]` "(A OU B) na primeira posição E (A OU B) na segunda posição (e qualquer coisa depois)" - **Parâmetros** -1. `Object` - As opções de filtro: +1. `Objeto` - As opções de filtro: -- `fromBlock`: `QUANTITY|TAG` - (opcional, padrão: `"latest"`) Número de bloco inteiro ou `"latest"` para o último bloco proposto, `"safe"` para o último bloco seguro, `"finalized"` para o último bloco finalizado ou `"pending"`, `"earliest"` para transações que ainda não estão em um bloco. +- `fromBlock`: `QUANTITY|TAG` - (opcional, padrão: `"latest"`) Número de bloco inteiro, ou `"latest"` para o último bloco proposto, `"safe"` para o último bloco seguro, `"finalized"` para o último bloco finalizado, ou `"pending"`, `"earliest"` para transações que ainda não estão em um bloco. - `toBlock`: `QUANTITY|TAG` - (opcional, padrão: `"latest"`) Número de bloco inteiro, ou `"latest"` para o último bloco proposto, `"safe"` para o último bloco seguro, `"finalized"` para o último bloco finalizado, ou `"pending"`, `"earliest"` para transações que ainda não estão em um bloco. -- `endereço`: `DATA|Array`, 20 Bytes - (opcional) Endereço do contrato ou uma lista de endereços dos quais os logs devem se originar. -- `topics`: `Array of DATA`, - (opcional) Array de tópicos de `DATA` de 32 Bytes. Os tópicos são dependentes da ordem. Cada tópico também pode ser uma matriz de DADOS com opções "ou". +- `address`: `DATA|Array`, 20 Bytes - (opcional) Endereço do contrato ou uma lista de endereços dos quais os logs devem ser originados. +- `topics`: `Array de DATA`, - (opcional) Array de 32 Bytes de tópicos de `DATA`. Os tópicos são dependentes da ordem. Cada tópico também pode ser uma matriz de DADOS (array of DATA) com opções “ou”. ```js params: [ @@ -1427,14 +1536,15 @@ params: [ ] ``` -**Retorna** `QUANTITY` — Uma ID de filtro. +**Retornos** +`QUANTITY` - Uma ID de filtro. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newFilter","params":[{"topics":["0x12341234"]}],"id":73}' -// Result +// Resultado { "id":1, "jsonrpc": "2.0", @@ -1444,18 +1554,21 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newFilter","params":[{"topic ### eth_newBlockFilter {#eth_newblockfilter} -Cria um filtro no nó para notificar quando um novo bloco chega. Para verificar se o estado mudou, chame [eth_getFilterChanges](#eth_getfilterchanges). +Cria um filtro no nó para notificar quando um novo bloco chega. +Para verificar se o estado mudou, chame [eth_getFilterChanges](#eth_getfilterchanges). -**Parâmetros** Nenhum +**Parâmetros** +Nenhum -**Retorna** `QUANTITY` — Uma ID de filtro. +**Retornos** +`QUANTITY` - Uma ID de filtro. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newBlockFilter","params":[],"id":73}' -// Result +// Resultado { "id":1, "jsonrpc": "2.0", @@ -1465,18 +1578,21 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newBlockFilter","params":[], ### eth_newPendingTransactionFilter {#eth_newpendingtransactionfilter} -Cria um filtro no nó para notificar quando chegam novas transações pendentes. Para verificar se o estado mudou, chame [eth_getFilterChanges](#eth_getfilterchanges). +Cria um filtro no nó para notificar quando chegam novas transações pendentes. +Para verificar se o estado mudou, chame [eth_getFilterChanges](#eth_getfilterchanges). -**Parâmetros** Nenhum +**Parâmetros** +Nenhum -**Retorna** `QUANTITY` — Uma ID de filtro. +**Retornos** +`QUANTITY` - Uma ID de filtro. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newPendingTransactionFilter","params":[],"id":73}' -// Result +// Resultado { "id":1, "jsonrpc": "2.0", @@ -1486,7 +1602,8 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newPendingTransactionFilter" ### eth_uninstallFilter {#eth_uninstallfilter} -Desinstala um filtro com a ID fornecida. Deve ser sempre chamado quando nenhum tipo de observação é necessária. Além disso, os filtros expiram quando não são solicitados com [eth_getFilterChanges](#eth_getfilterchanges) por um período de tempo. +Desinstala um filtro com a ID fornecida. Deve ser sempre chamado quando nenhum tipo de observação é necessária. +Além disso, os filtros expiram quando não são solicitados com [eth_getFilterChanges](#eth_getfilterchanges) por um período de tempo. **Parâmetros** @@ -1498,14 +1615,15 @@ params: [ ] ``` -**Retorna** `Boolean` — `true` se o filtro foi desinstalado com sucesso, caso contrário `false`. +**Retornos** +`Booleano` - `true` se o filtro foi desinstalado com sucesso, caso contrário, `false`. **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_uninstallFilter","params":["0xb"],"id":73}' -// Result +// Resultado { "id":1, "jsonrpc": "2.0", @@ -1519,7 +1637,7 @@ Método de sondagem para um filtro, que retorna uma matriz de logs produzidos de **Parâmetros** -1. `QUANTITY` - A ID do filtro. +1. `QUANTITY` - a ID do filtro. ```js params: [ @@ -1527,26 +1645,30 @@ params: [ ] ``` -**Retorna** `Array` — Matriz de objetos de log ou uma matriz vazia se nada mudou desde a última sondagem. +**Retornos** +`Array` - Matriz de objetos de log, ou uma matriz vazia se nada mudou desde a última sondagem. - Para filtros criados com `eth_newBlockFilter`, o retorno são hashes de bloco (`DATA`, 32 Bytes), por exemplo, `["0x3454645634534..."]`. -- Para filtros criados com `eth_newPendingTransactionFilter`, o retorno são hashes de transação (`DATA`, 32 Bytes), por exemplo, `["0x6345343454645..."]`. + +- Para filtros criados com `eth_newPendingTransactionFilter `, o retorno são hashes de transação (`DATA`, 32 Bytes), por exemplo, `["0x6345343454645..."]`. + - Para filtros criados com `eth_newFilter`, os logs são objetos com os seguintes parâmetros: - - `removed`: `TAG` — `true` quando o log foi removido devido a uma reorganização da cadeia. `false` se for um log válido. - - `logIndex`: `QUANTITY` — Inteiro da posição do índice de log no bloco. `null` quando o log estiver pendente. - - `transactionIndex`: `QUANTITY` — Inteiro a partir do qual o log de posição do índice foi criado. `null` quando o log estiver pendente. - - `transactionHash`: `DATA`, 32 Bytes — Hash das transações a partir das quais este log foi criado. `null` quando o log estiver pendente. - - `blockHash`: `DATA`, 32 Bytes — Hash do bloco onde este log estava localizado. `null` quando está pendente. `null` quando o log estiver pendente. - - `blockNumber`: `QUANTITY` — O número do bloco onde este log estava localizado. `null` quando está pendente. `null` quando o log estiver pendente. - - `endereço`: `DADOS`, 20 Bytes — Endereço de origem deste log. - - `data`: `DATA` - contém zero ou mais argumentos não indexados de 32 bytes do log. - - `topics`: `Array of DATA` — Matriz de 0 a 4 32 Bytes `DATA` de argumentos de log indexados. (No _Solidity_: O primeiro tópico é o _hash_ da assinatura do evento (por exemplo, ` Deposit(address,bytes32,uint256)`), exceto se você declarou o evento com o especificador `anonymous`.) + - `removed`: `TAG` - `true` quando o log foi removido, devido a uma reorganização da cadeia. `false` se for um log válido. + - `logIndex`: `QUANTITY` - inteiro da posição do índice de log no bloco. `null` quando o log estiver pendente. + - `transactionIndex`: `QUANTITY` - inteiro da posição do índice de transações a partir do qual o log foi criado. `null` quando o log estiver pendente. + - `transactionHash`: `DATA`, 32 Bytes - hash das transações a partir das quais este log foi criado. `null` quando o log estiver pendente. + - `blockHash`: `DATA`, 32 Bytes - hash do bloco onde este log estava localizado. `null` quando está pendente. `null` quando o log estiver pendente. + - `blockNumber`: `QUANTITY` - o número do bloco onde este log estava localizado. `null` quando está pendente. `null` quando o log estiver pendente. + - `address`: `DATA`, 20 Bytes - endereço de origem deste log. + - `data`: `DATA` - dados de log de comprimento variável e não indexados. (Em _solidity_: zero ou mais argumentos de log de 32 Bytes não indexados.) + - `topics`: `Array de DATA` - Matriz de 0 a 4 `DATA` de 32 Bytes de argumentos de log indexados. (Em _solidity_: O primeiro tópico é o _hash_ da assinatura do evento (ex., `Deposit(address,bytes32,uint256)`), exceto se você declarou o evento com o especificador `anonymous`.) + - **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0x16"],"id":73}' -// Result +// Resultado { "id":1, "jsonrpc":"2.0", @@ -1579,16 +1701,17 @@ params: [ ] ``` -**Retorna** Consulte [eth_getFilterChanges](#eth_getfilterchanges) +**Retornos** +Consulte [eth_getFilterChanges](#eth_getfilterchanges) **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterLogs","params":["0x16"],"id":74}' ``` -Resultado. Veja [eth_getFilterChanges](#eth_getfilterchanges) +Resultado: consulte [eth_getFilterChanges](#eth_getfilterchanges) ### eth_getLogs {#eth_getlogs} @@ -1596,13 +1719,13 @@ Retorna uma matriz de todos os logs que correspondem a um determinado objeto de **Parâmetros** -1. `Object` - As opções de filtro: +1. `Objeto` - As opções de filtro: -- `fromBlock`: `QUANTITY|TAG` - (opcional, padrão: `"latest"`) Número de bloco inteiro ou `"latest"` para o último bloco proposto, `"safe"` para o último bloco seguro, `"finalized"` para o último bloco finalizado ou `"pending"`, `"earliest"` para transações que ainda não estão em um bloco. +- `fromBlock`: `QUANTITY|TAG` - (opcional, padrão: `"latest"`) Número de bloco inteiro, ou `"latest"` para o último bloco proposto, `"safe"` para o último bloco seguro, `"finalized"` para o último bloco finalizado, ou `"pending"`, `"earliest"` para transações que ainda não estão em um bloco. - `toBlock`: `QUANTITY|TAG` - (opcional, padrão: `"latest"`) Número de bloco inteiro, ou `"latest"` para o último bloco proposto, `"safe"` para o último bloco seguro, `"finalized"` para o último bloco finalizado, ou `"pending"`, `"earliest"` para transações que ainda não estão em um bloco. -- `endereço`: `DATA|Array`, 20 Bytes - (opcional) Endereço do contrato ou uma lista de endereços dos quais os logs devem se originar. -- `topics`: `Array of DATA`, - (opcional) Array de tópicos de `DATA` de 32 Bytes. Os tópicos são dependentes da ordem. Cada tópico também pode ser uma matriz de DADOS com opções "ou". -- `blockhash`: `DATA`, 32 Bytes — (opcional, **futuro**) Com a adição do EIP-234, `blockHash` será uma nova opção de filtro, que restringe os logs retornados ao bloco único com o hash de 32 bytes `blockHash`. Usar `blockHash` é equivalente a `fromBlock` = `toBlock` = o número do bloco com hash `blockHash`. Se `blockHash` estiver presente nos critérios de filtro, nem `fromBlock`, nem `toBlock` serão permitidos. +- `address`: `DATA|Array`, 20 Bytes - (opcional) Endereço do contrato ou uma lista de endereços dos quais os logs devem ser originados. +- `topics`: `Array de DATA`, - (opcional) Array de 32 Bytes de tópicos de `DATA`. Os tópicos são dependentes da ordem. Cada tópico também pode ser uma matriz de DADOS (array of DATA) com opções “ou”. +- `blockHash`: `DATA`, 32 Bytes - (opcional, **futuro**) Com a adição do EIP-234, `blockHash` será uma nova opção de filtro que restringe os logs retornados ao bloco único com o hash de 32-byte `blockHash`. Usar `blockHash` é equivalente a `fromBlock` = `toBlock` = o número do bloco com hash `blockHash`. Se `blockHash` estiver presente nos critérios de filtro, `fromBlock` e `toBlock` não serão permitidos. ```js params: [ @@ -1614,24 +1737,25 @@ params: [ ] ``` -**Retorna** Consulte [eth_getFilterChanges](#eth_getfilterchanges) +**Retornos** +Consulte [eth_getFilterChanges](#eth_getfilterchanges) **Exemplo** ```js -// Request +// Requisição curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"topics":["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"]}],"id":74}' ``` -Resultado. Veja [eth_getFilterChanges](#eth_getfilterchanges) +Resultado: consulte [eth_getFilterChanges](#eth_getfilterchanges) -## Exemplos de uso {#usage-example} +## Exemplo de uso {#usage-example} -### Implementando um contrato usando JSON_RPC {#deploying-contract} +### Implantando um contrato usando JSON_RPC {#deploying-contract} Esta seção inclui uma demonstração de como implantar um contrato usando apenas a interface RPC. Existem rotas alternativas para a implantação de contratos nos quais essa complexidade é abstraída, por exemplo, usando bibliotecas criadas sobre a interface RPC, como [web3.js](https://web3js.readthedocs.io/) e [web3.py](https://github.com/ethereum/web3.py). Essas abstrações são geralmente mais fáceis de entender e menos propensas a erros, mas ainda é útil entender o que está acontecendo internamente, ou seja, sem que o usuário perceba. -Veja a seguir um contrato inteligente simples chamado `Multiply7` que será implantado usando a interface JSON-RPC em um nó Ethereum. Este tutorial pressupõe que o leitor já esteja executando um nó Geth. Mais informações sobre nós e clientes estão disponíveis [aqui](/developers/docs/nodes-and-clients/run-a-node). Consulte a documentação específica de cada [cliente](/developers/docs/nodes-and-clients/) para ver como iniciar o JSON-RPC HTTP para clientes não Geth. A maioria dos clientes atende por padrão no `localhost:8545`. +Veja a seguir um contrato inteligente simples chamado `Multiply7` que será implantado usando a interface JSON-RPC em um nó Ethereum. Este tutorial pressupõe que o leitor já esteja executando um nó Geth. Mais informações sobre nós e clientes estão disponíveis [aqui](/developers/docs/nodes-and-clients/run-a-node). Consulte a documentação específica de cada [cliente](/developers/docs/nodes-and-clients/) para ver como iniciar o JSON-RPC HTTP para clientes não Geth. A maioria dos clientes atende por padrão em `localhost:8545`. ```javascript contract Multiply7 { @@ -1651,10 +1775,10 @@ geth --http --dev console 2>>geth.log Isso iniciará a interface HTTP RPC em `http://localhost:8545`. -Podemos verificar se a interface está em execução recuperando o endereço da coinbase (obtendo o primeiro endereço da matriz de contas) e o saldo usando [curl](https://curl.se). Observe que os dados nesses exemplos serão diferentes no seu nó local. Se você quiser tentar esses comandos, substitua os parâmetros de solicitação na segunda solicitação curl pelo resultado retornado da primeira. +Podemos verificar se a interface está em execução recuperando o endereço coinbase (obtendo o primeiro endereço da matriz de contas) e o saldo usando o [curl](https://curl.se). Observe que os dados nesses exemplos serão diferentes no seu nó local. Se você quiser tentar esses comandos, substitua os parâmetros de solicitação na segunda solicitação curl pelo resultado retornado da primeira. ```bash -curl --data '{"jsonrpc":"2.0","method":"eth_accounts","params":[]", "id":1}' -H "Content-Type: application/json" localhost:8545 +curl --data '{"jsonrpc":"2.0","method":"eth_accounts","params":[], "id":1}' -H "Content-Type: application/json" localhost:8545 {"id":1,"jsonrpc":"2.0","result":["0x9b1d35635cc34752ca54713bb99d38614f63c955"]} curl --data '{"jsonrpc":"2.0","method":"eth_getBalance", "params": ["0x9b1d35635cc34752ca54713bb99d38614f63c955", "latest"], "id":2}' -H "Content-Type: application/json" localhost:8545 @@ -1668,9 +1792,9 @@ web3.fromWei("0x1639e49bba16280000", "ether") // "410" ``` -Agora que já temos alguns Ether em nossa cadeia de desenvolvimento privada, podemos implantar o contrato. O primeiro passo é compilar o contrato Multiply7 em byte code, que pode ser enviado para a EVM. Para instalar o solc, o compilador do Solidity, confira a [documentação do Solidity](https://docs.soliditylang.org/en/latest/installing-solidity.html). (Você pode usar uma versão do `solc` mais antiga que corresponda [à versão do compilador usada em nosso exemplo](https://github.com/ethereum/solidity/releases/tag/v0.4.20).) +Agora que já temos alguns Ether em nossa cadeia de desenvolvimento privada, podemos implantar o contrato. O primeiro passo é compilar o contrato Multiply7 em byte code, que pode ser enviado para a EVM. Para instalar o solc, o compilador do Solidity, siga a [documentação do Solidity](https://docs.soliditylang.org/en/latest/installing-solidity.html). (Você pode usar uma versão mais antiga do `solc` para corresponder à [versão do compilador usada em nosso exemplo](https://github.com/ethereum/solidity/releases/tag/v0.4.20).) -O próximo passo é compilar o contrato Multiply7 em byte code, que pode ser enviado para a EVM. +O próximo passo é compilar o contrato Multiply7 para bytecode que pode ser enviado para a EVM. ```bash echo 'pragma solidity ^0.4.16; contract Multiply7 { event Print(uint); function multiply(uint input) public returns (uint) { Print(input * 7); return input * 7; } }' | solc --bin @@ -1680,7 +1804,7 @@ Binary: 6060604052341561000f57600080fd5b60eb8061001d6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa1146044575b600080fd5b3415604e57600080fd5b606260048080359060200190919050506078565b6040518082815260200191505060405180910390f35b60007f24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da600783026040518082815260200191505060405180910390a16007820290509190505600a165627a7a7230582040383f19d9f65246752244189b02f56e8d0980ed44e7a56c0b200458caad20bb0029 ``` -Agora que temos o código compilado, precisamos determinar o quanto a sua implantação custará em gás. A interface RPC tem um método `eth_estimateGas`, que nos dará uma estimativa. +Agora que temos o código compilado, precisamos determinar o quanto a sua implantação custará em gás. A interface RPC tem um método `eth_estimateGas` que nos dará uma estimativa. ```bash curl --data '{"jsonrpc":"2.0","method": "eth_estimateGas", "params": [{"from": "0x9b1d35635cc34752ca54713bb99d38614f63c955", "data": "0x6060604052341561000f57600080fd5b60eb8061001d6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa1146044575b600080fd5b3415604e57600080fd5b606260048080359060200190919050506078565b6040518082815260200191505060405180910390f35b60007f24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da600783026040518082815260200191505060405180910390a16007820290509190505600a165627a7a7230582040383f19d9f65246752244189b02f56e8d0980ed44e7a56c0b200458caad20bb0029"}], "id": 5}' -H "Content-Type: application/json" localhost:8545 @@ -1694,7 +1818,7 @@ curl --data '{"jsonrpc":"2.0","method": "eth_sendTransaction", "params": [{"from {"id":6,"jsonrpc":"2.0","result":"0xe1f3095770633ab2b18081658bad475439f6a08c902d0915903bafff06e6febf"} ``` -A transação é aceita pelo nó e um hash de transação é retornado. Esse hash pode ser usado para rastrear a transação. O próximo passo é determinar o endereço onde nosso contrato está implantado. Cada transação executada criará uma confirmação de recebimento. Essa confirmação de recebimento contém várias informações sobre a transação, como em qual bloco a transação foi incluída e quanto gás foi usado pela EVM. Se uma transação criar um contrato, ela também conterá o endereço do contrato. Podemos recuperar a confirmação de recebimento com o método RPC `eth_getTransactionReceipt`. +A transação é aceita pelo nó e um hash de transação é retornado. Esse hash pode ser usado para rastrear a transação. O próximo passo é determinar o endereço onde nosso contrato está implantado. Cada transação executada criará uma confirmação de recebimento. Essa confirmação de recebimento contém várias informações sobre a transação, como em qual bloco a transação foi incluída e quanto gás foi usado pela EVM. Se uma transação criar um contrato, ela também conterá o endereço do contrato. Podemos recuperar o recibo com o método `eth_getTransactionReceipt` da RPC. ```bash curl --data '{"jsonrpc":"2.0","method": "eth_getTransactionReceipt", "params": ["0xe1f3095770633ab2b18081658bad475439f6a08c902d0915903bafff06e6febf"], "id": 7}' -H "Content-Type: application/json" localhost:8545 @@ -1707,7 +1831,7 @@ Nosso contrato foi criado em `0x4d03d617d700cf81935d7f797f4e2ae719648262`. Um re Neste exemplo, enviaremos uma transação usando `eth_sendTransaction` para o método `multiply` do contrato. -`eth_sendTransaction` requer vários argumentos, especificamente `from`, `to` e `data`. `From` é o endereço público de nossa conta, e `to` é o endereço do contrato. O argumento `data` contém uma carga que define qual método deve ser chamado e com quais argumentos. É aqui que a [interface binária do aplicativo (ABI, na sigla em inglês)](https://docs.soliditylang.org/en/latest/abi-spec.html) entra em ação. A ABI é um arquivo JSON que estabelece como definir e codificar dados para a EVM. +`eth_sendTransaction` requer vários argumentos, especificamente `from`, `to` e `data`. `From` é o endereço público de nossa conta, e `to` é o endereço do contrato. O argumento `data` contém um payload que define qual método deve ser chamado e com quais argumentos. É aqui que a [IAB (interface binária de aplicativo)](https://docs.soliditylang.org/en/latest/abi-spec.html) entra em jogo. A ABI é um arquivo JSON que estabelece como definir e codificar dados para a EVM. Os bytes da carga definem qual método no contrato é chamado. Esses são os primeiros 4 bytes do hash Keccak sobre o nome da função e seus tipos de argumento, com codificação hexadecimal. A função multiplicar aceita um uint, que é um alias de uint256. Isso nos deixa com: @@ -1718,9 +1842,9 @@ web3.sha3("multiply(uint256)").substring(0, 10) O próximo passo é codificar os argumentos. Existe apenas um uint256, por exemplo, o valor 6. A ABI tem uma seção que especifica como codificar os tipos uint256. -`int: enc(X)` é a codificação Big Endian do complemento de dois de X, preenchida no lado superior (esquerdo) com 0xff para X negativo e com zero > bytes para X positivo, de modo que o tamanho seja um múltiplo de 32 bytes. +`int: enc(X)` é a codificação de complemento de dois big-endian de X, preenchida no lado de ordem superior (esquerdo) com 0xff para X negativo e com bytes zero para X positivo, de modo que o comprimento seja um múltiplo de 32 bytes. -Isso codifica em `0000000000000000000000000000000000000000000000000000000000000006`. +Isso codifica para `0000000000000000000000000000000000000000000000000000000000000006`. Combinando o seletor de função e o argumento codificado, nossos dados serão `0xc6888fa10000000000000000000000000000000000000000000000000000000000000006`. @@ -1755,7 +1879,7 @@ Como uma transação foi enviada, um hash de transação foi retornado. A recupe } ``` -O recibo contém um log. Esse log foi gerado pela EVM na execução da transação e incluído no recibo. A função `multiply` mostra que o evento `Print` foi gerado com a entrada 7 vezes. Como o argumento do evento `Print` era um uint256, podemos decodificá-lo conforme as regras da ABI, o que nos deixará com a decimal 42 esperada. Além dos dados, vale ressaltar que os tópicos podem ser usados para determinar qual evento criou o log: +O recibo contém um log. Esse log foi gerado pela EVM na execução da transação e incluído no recibo. A função `multiply` mostra que o evento `Print` foi acionado com a entrada multiplicada por 7. Como o argumento para o evento `Print` era um uint256, podemos decodificá-lo de acordo com as regras da IAB, o que nos deixará com o decimal esperado 42. Além dos dados, vale ressaltar que os tópicos podem ser usados para determinar qual evento criou o log: ```javascript web3.sha3("Print(uint256)") @@ -1766,8 +1890,8 @@ Esta foi apenas uma breve introdução a algumas das tarefas mais comuns, demons ## Tópicos relacionados {#related-topics} -- [Especificações do JSON-RPC](http://www.jsonrpc.org/specification) -- [ Nós e clientes](/developers/docs/nodes-and-clients/) -- [APIs JavaScript](/developers/docs/apis/javascript/) -- [APIs de back-end](/developers/docs/apis/backend/) +- [Especificação JSON-RPC](http://www.jsonrpc.org/specification) +- [Nós e clientes](/developers/docs/nodes-and-clients/) +- [APIs de JavaScript](/developers/docs/apis/javascript/) +- [APIs de backend](/developers/docs/apis/backend/) - [Clientes de execução](/developers/docs/nodes-and-clients/#execution-clients) diff --git a/public/content/translations/pt-br/developers/docs/blocks/index.md b/public/content/translations/pt-br/developers/docs/blocks/index.md index c94e1e77c54..1455b7552fc 100644 --- a/public/content/translations/pt-br/developers/docs/blocks/index.md +++ b/public/content/translations/pt-br/developers/docs/blocks/index.md @@ -1,6 +1,6 @@ --- title: Blocos -description: Uma visão geral dos blocos na blockchain do Ethereum — sua estrutura de dados, por que são necessários e como são feitos. +description: "Uma visão geral dos blocos na blockchain do Ethereum — sua estrutura de dados, por que são necessários e como são feitos." lang: pt-br --- @@ -8,13 +8,14 @@ Blocos são lotes de transações com um hash do bloco anterior na cadeia. Isso ## Pré-requisitos {#prerequisites} -Os blocos são um tópico muito amigável para iniciantes. Mas para ajudá-lo a entender melhor esta página, recomendamos que você primeiro leia [Contas](/developers/docs/accounts/), [Transações](/developers/docs/transactions/)e nossa [introdução ao Ethereum](/developers/docs/intro-to-ethereum/). +Os blocos são um tópico muito amigável para iniciantes. Mas, para ajudar você a entender melhor esta página, recomendamos que primeiro leia [Contas](/developers/docs/accounts/), [Transações](/developers/docs/transactions/) e nossa [introdução ao Ethereum](/developers/docs/intro-to-ethereum/). ## Por que blocos? {#why-blocks} Para garantir que todos os participantes da rede Ethereum mantenham um estado sincronizado e concordem com o histórico preciso de transações, nós processamos lotes de transações em blocos. Isso significa que dezenas (ou centenas) de transações são confirmadas, acordadas e sincronizadas de uma só vez. -![Um diagrama mostrando transações em um bloco causando mudanças de estado](./tx-block.png) _Diagrama adaptado de [Ethereum EVM ilustrado](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ +![Um diagrama mostrando transações em um bloco causando mudanças de estado](./tx-block.png) +_Diagrama adaptado de [Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ Ao espaçar as confirmações, damos a todos os participantes da rede tempo suficiente para chegar a um consenso: mesmo que as solicitações de transação ocorram dezenas de vezes por segundo, os blocos só são criados e confirmados na Ethereum uma vez a cada doze segundos. @@ -24,13 +25,13 @@ Para preservar o histórico de transação, os blocos são estritamente ordenado Uma vez que um bloco é agregado por um validador selecionado aleatoriamente na rede, ele é propagado pelo resto da rede. Em seguida, todos os nós adicionam esse bloco ao final de sua blockchain e um novo validador é selecionado para criar o próximo bloco. O processo exato de montagem de blocos e o processo de compromisso/consenso são atualmente especificados pelo protocolo de “prova de participação” da Ethereum. -## Protocolo de prova de participação {#proof-of-work-protocol} +## Protocolo de prova de participação {#proof-of-stake-protocol} Prova de participação significa o seguinte: - Os nós de validação precisam colocar 32 ETH em um contrato de depósito como garantia contra mau comportamento. Isso ajuda a proteger a rede porque atividades comprovadamente desonestas fazem com que parte de ou toda essa participação seja destruída. - Em cada espaço (espaçados de doze segundos), um validador é selecionado aleatoriamente para ser o proponente do bloco. Eles agrupam transações, as executam e determinam um novo "estado". Eles agrupam essas informações em um bloco e as passam para outros validadores. -- Outros validadores que ouvem sobre um novo bloco reexecutam as transações para garantir que concordam com a mudança proposta para o estado global. Assumindo que o bloco é válido, eles o adicionam ao seu próprio banco de dados. +- Outros validadores que ficam sabendo do novo bloco reexecutam as transações para garantir que concordam com a mudança proposta no estado global. Supondo que o bloco seja válido, eles o adicionam ao seu próprio banco de dados. - Se um validador ouvir sobre dois blocos conflitantes para o mesmo espaço, eles usam seu algoritmo de escolha de fork para escolher aquele suportado pelo ETH que teve mais participação. [Mais sobre prova de participação](/developers/docs/consensus-mechanisms/pos) @@ -40,52 +41,52 @@ Prova de participação significa o seguinte: Há muitas informações contidas em um bloco. No nível mais alto, um bloco contém os seguintes campos: | Campo | Descrição | -|:---------------- |:---------------------------------------------------------- | -| `slot` | o slot ao qual o bloco pertence | +| :--------------- | :--------------------------------------------------------- | +| `espaço` | o slot ao qual o bloco pertence | | `proposer_index` | a ID do validador que propõe o bloco | | `parent_root` | o hash do bloco anterior | | `state_root` | o hash raiz do estado do objeto | -| `body` | um objeto contendo vários campos, conforme definido abaixo | +| `apresentação` | um objeto contendo vários campos, conforme definido abaixo | -O bloco `body` contém vários campos próprios: +O `body` do bloco contém vários campos próprios: | Campo | Descrição | -|:-------------------- |:------------------------------------------------------------- | +| :------------------- | :------------------------------------------------------------ | | `randao_reveal` | um valor usado para selecionar o proponente do próximo bloco | | `eth1_data` | informações sobre o contrato de depósito | | `graffiti` | dados arbitrários usados para marcar blocos | | `proposer_slashings` | lista de validadores a serem removidos | | `attester_slashings` | lista de validadores a serem removidos | -| `attestations` | lista de validadores a serem removidos | -| `deposits` | lista de novos depósitos para o contrato de depósito | +| `atestações` | lista de atestações feitas em relação aos espaços anteriores | +| `depósitos` | lista de novos depósitos para o contrato de depósito | | `voluntary_exits` | lista de validadores saindo da rede | | `sync_aggregate` | subconjunto de validadores usados para atender clientes leves | | `execution_payload` | transações transmitidas do cliente de execução | O campo `attestations` contém uma lista de todas as atestações no bloco. As atestações têm seu próprio tipo de dados que contém vários dados. Cada atestação contém: -| Campo | Descrição | -|:------------------ |:----------------------------------------------------------- | -| `aggregation_bits` | uma lista de quais validadores participaram desta atestação | -| `data` | um contêiner com vários subcampos | -| `signature` | assinatura agregada com todos os validadores de atestação | +| Campo | Descrição | +| :----------------- | :-------------------------------------------------------------------------- | +| `aggregation_bits` | uma lista de quais validadores participaram desta atestação | +| `dados` | um contêiner com vários subcampos | +| `assinatura` | assinatura agregada de um conjunto de validadores em relação à parte `data` | -O campo `data` no `attestation` contém o seguinte: +O campo `data` na `attestation` contém o seguinte: -| Campo | Descrição | -|:------------------- |:------------------------------------------------ | -| `slot` | o local ao qual a atestação se refere | -| `index` | índices para as atestações dos validadores | -| `beacon_block_root` | o hash raiz do bloco Beacon contendo este objeto | -| `source` | o último ponto de verificação justificado | -| `target` | o último bloco de limite de época | +| Campo | Descrição | +| :------------------ | :----------------------------------------------------------- | +| `espaço` | o local ao qual a atestação se refere | +| `índice` | índices para as atestações dos validadores | +| `beacon_block_root` | o hash raiz do bloco Beacon visto como o cabeçalho da cadeia | +| `fonte` | o último ponto de verificação justificado | +| `target` | o último bloco de limite de época | -A execução das transações no `execution_payload` atualiza o estado global. Todos os clientes reexecutam as transações no `execution_payload` para garantir que o novo estado corresponda ao novo bloco do campo `state_root`. É assim que os clientes podem dizer que um novo bloco é válido e seguro para adicionar à cadeia de blocos deles. O próprio `execution payload` é um objeto com vários campos. Há também um `execution_payload_header` que contém informações importantes de resumo sobre os dados de execução. Essas estruturas de dados são organizadas da seguinte forma: +A execução das transações no `execution_payload` atualiza o estado global. Todos os clientes reexecutam as transações no `execution_payload` para garantir que o novo estado corresponda àquele no campo `state_root` do novo bloco. É assim que os clientes podem dizer que um novo bloco é válido e seguro para adicionar à cadeia de blocos deles. O próprio `execution payload` é um objeto com vários campos. Há também um `execution_payload_header` que contém informações de resumo importantes sobre os dados de execução. Essas estruturas de dados são organizadas da seguinte forma: O `execution_payload_header` contém os seguintes campos: | Campo | Descrição | -|:------------------- |:------------------------------------------------------------------ | +| :------------------ | :----------------------------------------------------------------- | | `parent_hash` | hash do bloco pai | | `fee_recipient` | endereço da conta para pagar taxas de transação para | | `state_root` | hash raiz para o estado global após aplicar alterações neste bloco | @@ -102,48 +103,48 @@ O `execution_payload_header` contém os seguintes campos: | `transactions_root` | hash raiz das transações na carga | | `withdrawal_root` | hash raiz das retiradas no payload | -O próprio `execution_payload` contém o seguinte (note que é idêntico ao cabeçalho, exceto que, em vez do hash raiz das transações, ele inclui a lista real de transações e informações de retirada): - -| Campo | Descrição | -|:------------------ |:------------------------------------------------------------------ | -| `parent_hash` | hash do bloco pai | -| `fee_recipient` | endereço da conta para pagar taxas de transação para | -| `state_root` | hash raiz para o estado global após aplicar alterações neste bloco | -| `receipts_root` | hash dos recibos da transação trie | -| `logs_bloom` | estrutura de dados contendo logs de eventos | -| `prev_randao` | valor usado na seleção do validador aleatório | -| `block_number` | o número do bloco atual | -| `gas_limit` | gás máximo permitido neste bloco | -| `gas_used` | a quantidade real de gás usado neste bloco | -| `timestamp` | o tempo do bloco | -| `extra_data` | dados adicionais arbitrários como bytes brutos | -| `base_fee_per_gas` | o valor da taxa base | -| `block_hash` | hash do bloco de execução | -| `transações` | lista de transações a serem executadas | -| `saques` | lista de objetos de retirada | +O próprio `execution_payload` contém o seguinte (observe que isso é idêntico ao cabeçalho, exceto que, em vez do hash raiz das transações, ele inclui a lista real de transações e informações de retirada): + +| Campo | Descrição | +| :------------------- | :----------------------------------------------------------------- | +| `parent_hash` | hash do bloco pai | +| `fee_recipient` | endereço da conta para pagar taxas de transação para | +| `state_root` | hash raiz para o estado global após aplicar alterações neste bloco | +| `receipts_root` | hash dos recibos da transação trie | +| `logs_bloom` | estrutura de dados contendo logs de eventos | +| `prev_randao` | valor usado na seleção do validador aleatório | +| `block_number` | o número do bloco atual | +| `gas_limit` | gás máximo permitido neste bloco | +| `gas_used` | a quantidade real de gás usado neste bloco | +| `timestamp` | o tempo do bloco | +| `extra_data` | dados adicionais arbitrários como bytes brutos | +| `base_fee_per_gas` | o valor da taxa base | +| `block_hash` | hash do bloco de execução | +| `transações` | lista de transações a serem executadas | +| `retirada de fundos` | lista de objetos de retirada | A lista `withdrawals` contém objetos `withdrawal` estruturados da seguinte forma: | Campo | Descrição | -|:---------------- |:----------------------------- | +| :--------------- | :---------------------------- | | `endereço` | endereço da conta que retirou | | `quantidade` | quantidade retirada | -| `index` | valor do índice da retirada | +| `índice` | valor do índice da retirada | | `validatorIndex` | valor do índice do validador | ## Tempo de bloco {#block-time} O tempo do bloco refere-se ao tempo de separação dos blocos. No Ethereum, o tempo é dividido em doze unidades de segundos chamadas de "espaços". Em cada espaço, um único validador é selecionado para propor um bloco. Supondo que todos os validadores estejam online e totalmente funcionais, haverá um bloco em cada espaço, o que significa que o tempo de um bloco é de 12s. No entanto, ocasionalmente, os validadores podem estar offline quando chamados para propor um bloco, o que significa que os espaços podem às vezes ficar vazios. -Essa implementação difere dos sistemas baseados em prova de trabalho, na qual os tempos de bloco são probabilísticos e ajustados de acordo com a dificuldade da meta de mineração do protocolo. O [tempo médio do bloco](https://etherscan.io/chart/blocktime) do Ethereum é um exemplo perfeito disso, no qual a transição de prova de trabalho para prova de participação pode ser claramente inferida com base na consistência do novo tempo do bloco de 12s. +Essa implementação difere dos sistemas baseados em prova de trabalho, na qual os tempos de bloco são probabilísticos e ajustados de acordo com a dificuldade da meta de mineração do protocolo. O [tempo médio de bloco](https://etherscan.io/chart/blocktime) do Ethereum é um exemplo perfeito disso, no qual a transição de prova de trabalho para prova de participação pode ser claramente inferida com base na consistência do novo tempo de bloco de 12s. ## Tamanho do bloco {#block-size} -Uma observação final importante é que os blocos em si são delimitados por tamanho. Cada bloco tem um tamanho alvo de 30 milhões de gás, mas o tamanho dos blocos aumentar ou diminui de acordo com as demandas da rede, até o limite do bloco de 60 milhões de gás (2 vezes o tamanho do bloco de destino). O limite de gás do bloco pode ser ajustado para mais ou para menos em um fator de 1/1.024 em relação ao limite de gás do bloco anterior. Como resultado, os validadores podem alterar o limite de gás do bloco por meio de um consenso. A quantidade total de gás gasto por todas as transações no bloco deve ser inferior ao limite de gás do bloco. Isso é importante porque garante que os blocos não possam ser arbitrariamente grandes. Se os blocos pudessem ser arbitrariamente grandes, os nós completos com menos desempenho iriam gradualmente deixar de conseguir acompanhar a rede devido aos requisitos de espaço e velocidade. Quanto maior o bloco, maior o poder de computação necessário para processá-los a tempo para o próximo espaço. Essa força centralizadora é impedida com a limitação do tamanho dos blocos. +Uma observação final importante é que os blocos em si são delimitados por tamanho. Cada bloco tem um tamanho alvo de 30 milhões de gás, mas o tamanho dos blocos aumentará ou diminuirá de acordo com as demandas da rede, até o limite de bloco de 60 milhões de gás (2x o tamanho alvo do bloco). O limite de gás do bloco pode ser ajustado para mais ou para menos em um fator de 1/1.024 em relação ao limite de gás do bloco anterior. Como resultado, os validadores podem alterar o limite de gás do bloco por meio de um consenso. A quantidade total de gás gasto por todas as transações no bloco deve ser inferior ao limite de gás do bloco. Isso é importante porque garante que os blocos não possam ser arbitrariamente grandes. Se os blocos pudessem ser arbitrariamente grandes, os nós completos com menos desempenho iriam gradualmente deixar de conseguir acompanhar a rede devido aos requisitos de espaço e velocidade. Quanto maior o bloco, maior o poder de computação necessário para processá-los a tempo para o próximo espaço. Essa força centralizadora é impedida com a limitação do tamanho dos blocos. ## Leitura adicional {#further-reading} -_Conhece um recurso da comunidade que te ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ ## Tópicos relacionados {#related-topics} diff --git a/public/content/translations/pt-br/developers/docs/bridges/index.md b/public/content/translations/pt-br/developers/docs/bridges/index.md index 22a4c4c95ea..5e6429e1f07 100644 --- a/public/content/translations/pt-br/developers/docs/bridges/index.md +++ b/public/content/translations/pt-br/developers/docs/bridges/index.md @@ -1,20 +1,20 @@ --- title: Pontes -description: Uma visão geral da ponte para desenvolvedores +description: "Uma visão geral da ponte para desenvolvedores" lang: pt-br --- -Com a proliferação de soluções de blockchains L1 e de [dimensionamento](/developers/docs/scaling/) L2, junto com um número cada vez maior de aplicativos descentralizados cross-chain, a necessidade de comunicação e de movimentação de ativos entre as chains tornou-se uma parte essencial da infraestrutura das redes. Há diferentes tipos de bridges para ajudar a tornar isso possível. +Com a proliferação de blockchains L1 e soluções de [escalabilidade](/developers/docs/scaling/) L2, juntamente com um número cada vez maior de aplicativos descentralizados se tornando cross-chain, a necessidade de comunicação e movimentação de ativos entre redes tornou-se uma parte essencial da infraestrutura de rede. Há diferentes tipos de bridges para ajudar a tornar isso possível. -## Necessidade de bridges {#need-for-bridges} +## Necessidade de pontes {#need-for-bridges} Bridges existem para conectar redes blockchain. Elas permitem conectividade e interoperabilidade entre blockchains. Blockchains existem em ambientes isolados, o que significa que não há maneira de blockchains negociarem e se comunicarem com outros blockchains naturalmente. Como resultado, embora possa haver atividade e inovação significantes dentro de um ecossistema, elas estão limitadas pela falta de conexão e interoperabilidade com outros ecossistemas. -Bridges oferecem uma maneira de os ambientes isolados de blockchain se conectarem entre si. Eles estabelecem uma rota de transporte entre blockchains na qual tokens, mensagens, dados arbitrários, e até mesmo chamadas de [contratos inteligentes](/developers/docs/smart-contracts/) podem ser transferidos de uma cadeia para outra. +Bridges oferecem uma maneira de os ambientes isolados de blockchain se conectarem entre si. Elas estabelecem uma rota de transporte entre blockchains onde tokens, mensagens, dados arbitrários e até mesmo chamadas de [contrato inteligente](/developers/docs/smart-contracts/) podem ser transferidos de uma rede para outra. -## Benefícios das bridges {#benefits-of-bridges} +## Benefícios das pontes {#benefits-of-bridges} De maneira simples, as bridges desbloqueiam numerosos casos de uso, já que possibilitam que as redes blockchain troquem dados e movam ativos entre si. @@ -23,97 +23,98 @@ Blockchains têm pontos fortes, pontos fracos e abordagens exclusivos para a cri Para os desenvolvedores, as bridges habilitam o seguinte: - a transferência de qualquer dado, informações e ativos entre as chains. -- desbloquear novos recursos e casos de uso para protocolos, já que as bridges expandem o espaço de desenho do que os protocolos podem oferecer. Por exemplo, um protocolo de yield farming originalmente implantado na rede principal do Ethereum pode oferecer pools de liquidez em todas as chains compatíveis com EVM. +- desbloquear novos recursos e casos de uso para protocolos, já que as bridges + expandem o espaço de desenho do que os protocolos podem oferecer. Por exemplo, um protocolo de yield farming originalmente implantado na rede principal do Ethereum pode oferecer pools de liquidez em todas as chains compatíveis com EVM. - a oportunidade de alavancar os pontos fortes das diferentes blockchains. Por exemplo, os desenvolvedores podem se beneficiar das taxas mais baixas oferecidas pelas diferentes soluções de L2, implantando seus dapps em roolups e sidechains, e os usuários podem conectá-los por meio da bridge. - colaboração entre desenvolvedores de vários ecossistemas blockchain para desenvolver novos produtos. - atrair usuários e comunidades de vários ecossistemas para seus dapps. ## Como as bridges funcionam? {#how-do-bridges-work} -Embora haja muitos [tipos de desenhos de bridge](https://blog.li.fi/what-are-blockchain-bridges-and-how-can-we-classify-them-560dc6ec05fa), há três maneiras principais de facilitar a transferência de ativos entre as cadeias: +Embora existam muitos [tipos de designs de pontes](https://li.fi/knowledge-hub/blockchain-bridges-and-classification/), três maneiras de facilitar a transferência de ativos entre redes se destacam: -- **Lock and ming**: bloqueia os ativos na cadeia de origem e faz a "mintagem" na cadeia de destino. -- **Burn and mint**: faz o burn dos ativos na cadeia de origem e faz a mintagem de ativos na cadeia de destino. -- **Atomic swaps**: troca ativos na cadeia de origem por ativos na cadeia de destino com terceiros. +- **Bloquear e cunhar –** Bloqueia ativos na rede de origem e cunha ativos na rede de destino. +- **Queimar e cunhar –** Queima ativos na rede de origem e cunha ativos na rede de destino. +- **Swaps atômicos –** Troca de ativos na rede de origem por ativos na rede de destino com outra parte. -## Tipos de bridge {#bridge-types} +## Tipos de pontes {#bridge-types} Geralmente, as bridges podem ser classificadas como um dos seguintes tipos: -- **Bridges nativas**: estas bridges são tipicamente criadas para criar liquidez em uma determinada blockchain, o que simplifica para os usuários mover fundos para o ecossistema. Por exemplo, a [Arbitrum Bridge](https://bridge.arbitrum.io/) foi criada para que os usuários pudessem fazer uma "ponte" entre a rede principal do Ethereum e a Arbitrum. Outras bridges incluem a Polygon PoS Bridge, a [Optimism Gateway](https://app.optimism.io/bridge) etc. -- **Bridges baseadas em validador ou oráculos**: estas bridges dependem de um conjunto de validadores externos ou oráculos para validar as transferências entre cadeias. Exemplos: Multichain e Across. -- **Bridges para o envio de mensagens generalizadas**: estas bridges podem transferir ativos, juntamente com mensagens e dados arbitrários entre cadeias. Exemplos: Nomad e LayerZero. -- **Redes de liquidez**: o objetivo principal destas bridges é a transferência de ativos de uma cadeia para outra através de atomic swaps. Geralmente, elas não suportam o envio de mensagens entre cadeias. Exemplos: Connext e Hop. +- **Pontes nativas –** Essas pontes são normalmente construídas para impulsionar a liquidez em um blockchain específico, facilitando para os usuários moverem fundos para o ecossistema. Por exemplo, a [Arbitrum Bridge](https://bridge.arbitrum.io/) foi construída para facilitar que os usuários façam a ponte da Rede Principal do Ethereum para a Arbitrum. Outras pontes semelhantes incluem a Polygon PoS Bridge, a [Optimism Gateway](https://app.optimism.io/bridge), etc. +- **Pontes baseadas em validador ou oráculo –** Essas pontes dependem de um conjunto de validadores externos ou oráculos para validar as transferências entre redes. Exemplos: Multichain e Across. +- **Pontes de passagem de mensagens generalizadas –** Essas pontes podem transferir ativos, juntamente com mensagens e dados arbitrários entre redes. Exemplos: Axelar, LayerZero e Nomad. +- **Redes de liquidez –** Essas pontes focam principalmente na transferência de ativos de uma rede para outra por meio de atomic swaps. Geralmente, elas não suportam o envio de mensagens entre cadeias. Exemplos: Connext e Hop. ## Vantagens e desvantagens a considerar {#trade-offs} Com bridges, não há soluções perfeitas. Em vez disso, existem apenas compromissos feitos para cumprir uma finalidade. Desenvolvedores e usuários podem avaliar bridges com base nos seguintes fatores: - **Segurança –** Quem verifica o sistema? Bridges protegidas por validadores externos são tipicamente menos seguras do que as bridges que são locais ou nativamente protegidas pelos validadores do blockchain. -- **Conveniência –** Quanto tempo leva para completar uma transação e quantas transações um usuário precisa assinar? Para um desenvolvedor, quanto tempo leva para integrar uma bridge e qual é a complexidade do processo? -- **Connectivity –** Quais são as diferentes cadeias de destino que uma bridge pode conecta, por exemplo, rollups, sidechains, outras blockchains de camada etc, e quão difícil é integrar uma nova blockchain? -- **Capacidade de enviar dados mais complexos —** Uma bridge pode permitir a transferência de mensagens e dados arbitrários mais complexos entre cadeias ou só suporta transferências de ativos cross-chain? -- **Relação custo-benefício –** Quanto custa transferir ativos entre chains através de uma bridge? Normalmente, as bridges cobram uma taxa fixa ou variável, dependendo dos custos de gás e da liquidez de rotas específicas. É igualmente fundamental avaliar a relação custo-benefício de uma ponte baseada no capital necessário para garantir a sua segurança. +- **Conveniência –** Quanto tempo leva para concluir uma transação e quantas transações um usuário precisa assinar? Para um desenvolvedor, quanto tempo leva para integrar uma bridge e qual é a complexidade do processo? +- **Conectividade –** Quais são as diferentes redes de destino que uma ponte pode conectar (isto é, rollups, sidechains, outras blockchains de camada 1, etc.), e qual a dificuldade para integrar um novo blockchain? +- **Capacidade de passar dados mais complexos –** Uma ponte pode permitir a transferência de mensagens e dados arbitrários mais complexos entre redes, ou ela suporta apenas transferências de ativos entre redes? +- **Custo-benefício –** Quanto custa transferir ativos entre redes por meio de uma ponte? Normalmente, as bridges cobram uma taxa fixa ou variável, dependendo dos custos de gás e da liquidez de rotas específicas. É igualmente fundamental avaliar a relação custo-benefício de uma ponte baseada no capital necessário para garantir a sua segurança. Em termos gerais, as bridges podem ser categorizadas como confiáveis e não confiáveis. -- **Confiável –** Bridges confiáveis são verificadas externamente. Elas usam um conjunto externo de verificadores (federações com sistemas de computação multi-sig e multi-partes, rede de oráculos) para enviar dados através das cadeias. Como resultado, elas podem oferecer grande conectividade e permitir a transmissão de mensagens totalmente generalizadas através das cadeias. Elas também tendem a funcionar bem com velocidade e custo-eficácia. Isto vem à custa da segurança, uma vez que os usuários têm de confiar na segurança da bridge. -- **Não confiáveis –** Estas bridges dependem das blockchains que estão conectando e seus validadores para transferir mensagens e tokens. Elas são "não confiáveis" porque não agregam novas suposições de confiança (em adição aos blockchains). Como resultado, bridges não confiáveis são consideradas mais seguras do que as bridges confiáveis. +- **Confiáveis –** Pontes confiáveis são verificadas externamente. Elas usam um conjunto externo de verificadores (federações com sistemas de computação multi-sig e multi-partes, rede de oráculos) para enviar dados através das cadeias. Como resultado, elas podem oferecer grande conectividade e permitir a transmissão de mensagens totalmente generalizadas através das cadeias. Elas também tendem a funcionar bem com velocidade e custo-eficácia. Isto vem à custa da segurança, uma vez que os usuários têm de confiar na segurança da bridge. +- **Sem necessidade de confiança –** Essas pontes dependem dos blockchains que estão conectando e de seus validadores para transferir mensagens e tokens. Elas são "não confiáveis" porque não agregam novas suposições de confiança (em adição aos blockchains). Como resultado, bridges não confiáveis são consideradas mais seguras do que as bridges confiáveis. Para avaliar bridges não confiáveis baseadas em outros fatores, temos de dividi-las em mensagens generalizadas que são enviadas a bridges e redes de liquidez. -- **Bridges para o envio de mensagens generalizadas –** Estas bridges apresentam excelente segurança e a capacidade de transferir dados mais complexos entre cadeias. Normalmente, também apresentam uma boa relação custo-benefício. No entanto, estes pontos fortes geralmente afetam a conectividade para clientes leves de bridge (ex: IBC) e apresentam desvantagens em termos de velocidade para bridges otimistas (ex: Nomad) que usam provas de fraude. -- **Redes de liquidez –** Estas bridges usam atomic swaps para a transferência de ativos e são sistemas verificados localmente (ou seja, elas usam os validadores dos blockchains subjacentes para verificar transações). Como resultado, apresentam grande segurança e velocidade. Além disso, elas são consideradas relativamente eficazes em termos de custos e oferecem uma boa conectividade. No entanto, a maior desvantagem é sua incapacidade de enviar dados mais complexos, já que elas não suportam o envio de mensagens cross-chain. +- **Pontes de passagem de mensagens generalizadas –** Essas pontes se destacam pela segurança e pela capacidade de transferir dados mais complexos entre redes. Normalmente, também apresentam uma boa relação custo-benefício. No entanto, estes pontos fortes geralmente afetam a conectividade para clientes leves de bridge (ex: IBC) e apresentam desvantagens em termos de velocidade para bridges otimistas (ex: Nomad) que usam provas de fraude. +- **Redes de liquidez –** Essas pontes usam atomic swaps para transferir ativos e são sistemas verificados localmente (ou seja, usam os validadores dos blockchains subjacentes para verificar as transações). Como resultado, apresentam grande segurança e velocidade. Além disso, elas são consideradas relativamente eficazes em termos de custos e oferecem uma boa conectividade. No entanto, a maior desvantagem é sua incapacidade de enviar dados mais complexos, já que elas não suportam o envio de mensagens cross-chain. -## Riscos com bridges {#risk-with-bridges} +## Riscos das pontes {#risk-with-bridges} -As bridges são responsáveis pelos três principais [maiores hacks em DeFi](https://rekt.news/leaderboard/) e ainda estão nos estágios iniciais de desenvolvimento. Usar qualquer bridge traz os seguintes riscos: +As pontes são responsáveis pelos três [maiores hacks em DeFi](https://rekt.news/leaderboard/) e ainda estão nos estágios iniciais de desenvolvimento. Usar qualquer bridge traz os seguintes riscos: -- **Risco de contrato inteligente**: embora muitas bridges passaram com sucesso em auditorias, basta uma falha de contrato inteligente para que os ativos sejam expostos a hacks (ex: [Wormhole da bridge Solana](https://rekt.news/wormhole-rekt/)). -- **Riscos financeiros sistêmicos**: muitas bridges usam ativos encapsulados para mintar versões canônicas do ativo original em uma nova cadeia. Isso expõe o ecossistema a riscos sistêmicos. Um exemplo foi o que aconteceu com versões encapsuladas de tokens. -- **Risco de contraparte**: algumas bridges utilizam um design confiável que requer que os usuários confiem em que os validadores não roubarão fundos dos usuários. A necessidade de os usuários confiarem nesses atores externos os expõe a riscos como rug pull, censura e outras atividades maliciosas. -- **Problemas existentes**: dado que as bridges estão em fase inicial de desenvolvimento, existem muitas perguntas não respondidas relacionadas a como as bridges irão funcionar em diferentes condições de mercado, como tempos de congestionamento de rede e durante eventos imprevistos, como ataques a nível de rede ou estados de rollback. Esta incerteza comporta certos riscos, cujo grau ainda é desconhecido. +- **Risco de contrato inteligente –** Embora muitas pontes tenham sido aprovadas em auditorias, basta uma falha em um contrato inteligente para que os ativos fiquem expostos a hacks (ex.: a [Wormhole Bridge da Solana](https://rekt.news/wormhole-rekt/)). +- **Riscos financeiros sistêmicos –** Muitas pontes usam ativos encapsulados (wrapped assets) para cunhar versões canônicas do ativo original em uma nova rede. Isso expõe o ecossistema a riscos sistêmicos. Um exemplo foi o que aconteceu com versões encapsuladas de tokens. +- **Risco de contraparte –** Algumas pontes utilizam um design confiável que exige que os usuários confiem na premissa de que os validadores não entrarão em conluio para roubar os fundos dos usuários. A necessidade de os usuários confiarem nesses atores externos os expõe a riscos como rug pull, censura e outras atividades maliciosas. +- **Questões em aberto –** Como as pontes estão nos estágios iniciais de desenvolvimento, há muitas perguntas sem resposta relacionadas a como as pontes se comportarão em diferentes condições de mercado, como em momentos de congestionamento da rede e durante eventos imprevistos, como ataques no nível da rede ou reversões de estado. Esta incerteza comporta certos riscos, cujo grau ainda é desconhecido. ## Como os dApps podem usar bridges? {#how-can-dapps-use-bridges} Aqui estão algumas aplicações práticas que os desenvolvedores podem considerar sobre as bridges e levar seus dApps cross-chain: -### Como integrar bridges {#integrating-bridges} +### Integrando pontes {#integrating-bridges} Para desenvolvedores, há muitas maneiras adicionar suporte a bridges: -1. **Criar sua própria bridge**: criar uma bridge segura e confiável não é fácil, especialmente se sua abordagem considerar uma rota de confiança minimizada. Além disso, requer anos de experiência e conhecimento técnico em termos de dimensionamento e interoperabilidade. Adicionalmente, exigiria uma equipe ativa para manter uma bridge e atrair liquidez suficiente para torná-la viável. +1. **Construindo sua própria ponte –** Construir uma ponte segura e confiável não é fácil, especialmente se você seguir uma rota com confiança minimizada. Além disso, requer anos de experiência e conhecimento técnico em termos de dimensionamento e interoperabilidade. Adicionalmente, exigiria uma equipe ativa para manter uma bridge e atrair liquidez suficiente para torná-la viável. -2. **Oferecer aos usuários várias opções de bridge**: muitos [dapps](/developers/docs/dapps/) exigem que os usuários tenham o próprio token nativo para interagir com eles. Para permitir que os usuários acessem seus tokens, eles oferecem diferentes opções de bridge em seu site. No entanto, esse método é uma correção rápida para o problema, uma vez que leva o usuário para fora da interface do dapp e ainda requer que ele interaja com outros dapps e bridges. Trata-se de uma experiência pouco atraente e com maior probabilidade de erros. +2. **Mostrando aos usuários múltiplas opções de ponte –** Muitos [dapps](/developers/docs/dapps/) exigem que os usuários tenham seu token nativo para interagir com eles. Para permitir que os usuários acessem seus tokens, eles oferecem diferentes opções de bridge em seu site. No entanto, esse método é uma correção rápida para o problema, uma vez que leva o usuário para fora da interface do dapp e ainda requer que ele interaja com outros dapps e bridges. Trata-se de uma experiência pouco atraente e com maior probabilidade de erros. -3. **Integrar uma bridge**: esta solução não requer que o dapp envie usuários para a bridge externa e interfaces DEX. Ela permite que dapps melhorem a experiência de integração do usuário. No entanto, esta abordagem tem suas limitações: +3. **Integrando uma ponte –** Essa solução não exige que o dapp envie os usuários para a ponte externa e para as interfaces de DEX. Ela permite que dapps melhorem a experiência de integração do usuário. No entanto, esta abordagem tem suas limitações: - A avaliação e a manutenção das bridges são difíceis e demoradas. - Selecionar uma única bridge cria um ponto único de falha e dependência. - O dapp é limitado pelas capacidades da bridge. - Bridges por si só podem não ser suficientes. Os Dapps podem precisar de DEXs para oferecer mais funcionalidades, como swaps cross-chain. -4. **Integrar várias bridges**: esta solução resolve muitos problemas associados à integração de uma única bridge. No entanto, ela também tem limitações, já que integrar várias bridges consome recursos e cria sobrecargas técnicas e de comunicação para desenvolvedores, o recurso mais escasso em cripto. +4. **Integrando múltiplas pontes –** Essa solução resolve muitos problemas associados à integração de uma única ponte. No entanto, ela também tem limitações, já que integrar várias bridges consome recursos e cria sobrecargas técnicas e de comunicação para desenvolvedores, o recurso mais escasso em cripto. -5. **Integrar um agregador de bridge**: outra opção para dapps é integrar uma solução de agregação de bridges que permita a eles ter acesso a várias bridges. Agregadores de bridge herdam as forças de todas as bridges, e portanto, não são limitados pelas capacidades de uma única bridge. É importante observar que os agregadores de bridge normalmente mantêm as integrações da bridge, o que permite que o dapp não tenha que monitorar os aspectos técnicos e operacionais de uma integração de bridge. +5. **Integrando um agregador de pontes –** Outra opção para dapps é integrar uma solução de agregação de pontes que lhes dê acesso a múltiplas pontes. Agregadores de bridge herdam as forças de todas as bridges, e portanto, não são limitados pelas capacidades de uma única bridge. É importante observar que os agregadores de bridge normalmente mantêm as integrações da bridge, o que permite que o dapp não tenha que monitorar os aspectos técnicos e operacionais de uma integração de bridge. Dito isto, os agregadores de bridge também têm as suas limitações. Por exemplo, enquanto eles podem oferecer mais opções de bridge, há muitas outras bridges disponíveis no mercado, além das oferecidas na plataforma do agregador. Além disso, tal como as bridges, os agregadores de bridge também estão expostos a riscos de contratos inteligentes e tecnológicos, ou seja, uma maior quantidade de contratos inteligentes implica em mais riscos. Se um dapp for integrar uma bridge ou um agregador, existem diferentes opções com base no do grau de integração pretendido. Por exemplo, se for apenas uma integração front-end para melhorar a experiência de integração do usuário, um dapp integraria o widget. No entanto, se a integração é para conhecer mais em detalhes estratégias cross-chain, como staking, yield farming etc, o dapp integra o SDK ou API. -### Como implantar um dapp em múltiplas cadeias {#deploying-a-dapp-on-multiple-chains} +### Fazendo deploy de um dapp em múltiplas redes {#deploying-a-dapp-on-multiple-chains} -Para implantar um dapp em várias cadeias, os desenvolvedores podem usar plataformas de desenvolvimento como [Alchemy](https://www.alchemy.com/), [Hardhat](https://hardhat.org/), [Moralis](https://moralis.io/) etc. Normalmente, essas plataformas vêm com plugins compostos que podem habilitar dapps para cross-chain. Por exemplo, os desenvolvedores podem usar um proxy de implantação determinístico oferecido pelo [plugin hardhat-deploy](https://github.com/wighawag/hardhat-deploy). +Para fazer deploy de um dapp em múltiplas redes, os desenvolvedores podem usar plataformas de desenvolvimento como [Alchemy](https://www.alchemy.com/), [Hardhat](https://hardhat.org/), [Moralis](https://moralis.io/), etc. Normalmente, essas plataformas vêm com plugins compostos que podem habilitar dapps para cross-chain. Por exemplo, os desenvolvedores podem usar um proxy de implantação determinístico oferecido pelo [plugin hardhat-deploy](https://github.com/wighawag/hardhat-deploy). #### Exemplos: -- [Como criar dapps cross-chain](https://moralis.io/how-to-build-cross-chain-dapps/) -- [Como criar um marketplace de NFT cross-chain](https://youtu.be/WZWCzsB1xUE) -- [Moralis: Como criar dapps NFT cross-chain](https://www.youtube.com/watch?v=ehv70kE1QYo) +- [Como construir dapps de cross-chain](https://moralis.io/how-to-build-cross-chain-dapps/) +- [Construindo um Marketplace de NFT de Múltiplas Redes](https://youtu.be/WZWCzsB1xUE) +- [Moralis: Construindo dapps de NFT de múltiplas redes](https://www.youtube.com/watch?v=ehv70kE1QYo) -### Como monitorar atividades de contrato entre cadeias {#monitoring-contract-activity-across-chains} +### Monitorando a atividade de contratos entre redes {#monitoring-contract-activity-across-chains} -Para monitorar atividades de contrato entre cadeias, os desenvolvedores podem usar subgraphs e plataformas de desenvolvedores, como Tenderly, para acompanhar os contratos inteligentes em tempo real. Tais plataformas também têm ferramentas que oferecem melhor funcionalidade de monitoramento de dados para atividades cross-chain, tais como a busca por [eventos emitidos por contratos](https://docs.soliditylang.org/en/v0.8.14/contracts.html?highlight=events#events) etc. +Para monitorar atividades de contrato entre cadeias, os desenvolvedores podem usar subgraphs e plataformas de desenvolvedores, como Tenderly, para acompanhar os contratos inteligentes em tempo real. Essas plataformas também têm ferramentas que oferecem maior funcionalidade de monitoramento de dados para atividades entre redes, como a verificação de [eventos emitidos por contratos](https://docs.soliditylang.org/en/v0.8.14/contracts.html?highlight=events#events), etc. #### Ferramentas @@ -122,14 +123,17 @@ Para monitorar atividades de contrato entre cadeias, os desenvolvedores podem us ## Leitura adicional {#further-reading} -- [Blockchain Bridges](/bridges/) – ethereum.org -- [Blockchain Bridges: Building Networks of Cryptonetworks](https://medium.com/1kxnetwork/blockchain-bridges-5db6afac44f8) 8 set., 2021 – Dmitriy Berenzon -- [The Interoperability Trilemma](https://blog.connext.network/the-interoperability-trilemma-657c2cf69f17) 1 out., 2021 – Arjun Bhuptani -- [Clusters: How Trusted & Trust-Minimized Bridges Shape the Multi-Chain Landscape](https://blog.celestia.org/clusters/) 4 out, 2021 – Mustafa Al-assam -- [LI.FI: With Bridges, Trust is a Spectrum](https://blog.li.fi/li-fi-with-bridges-trust-is-a-spectrum-354cd5a1a6d8) 28 abril, 2022 – Arjun Chand +- [Pontes de Blockchain](/bridges/) – ethereum.org +- [Estrutura de Risco de Pontes do L2Beat](https://l2beat.com/bridges/summary) +- [Pontes de Blockchain: Construindo Redes de Cripto-redes](https://medium.com/1kxnetwork/blockchain-bridges-5db6afac44f8) - 8 de setembro de 2021 – Dmitriy Berenzon +- [O Trilema da Interoperabilidade](https://blog.connext.network/the-interoperability-trilemma-657c2cf69f17) - 1 de outubro de 2021 – Arjun Bhuptani +- [Clusters: Como as pontes confiáveis e com confiança minimizada moldam o cenário de múltiplas redes](https://blog.celestia.org/clusters/) - 4 de outubro de 2021 – Mustafa Al-Bassam +- [LI.FI: Com as pontes, a confiança é um espectro](https://blog.li.fi/li-fi-with-bridges-trust-is-a-spectrum-354cd5a1a6d8) - 28 de abril de 2022 – Arjun Chand +- [O estado das soluções de interoperabilidade de rollup](https://web.archive.org/web/20250428015516/https://research.2077.xyz/the-state-of-rollup-interoperability) - 20 de junho de 2024 – Alex Hook +- [Aproveitando a segurança compartilhada para interoperabilidade segura entre redes: Comitês de Estado de Lagrange e além](https://web.archive.org/web/20250125035123/https://research.2077.xyz/harnessing-shared-security-for-secure-blockchain-interoperability) - 12 de junho de 2024 – Emmanuel Awosika -Além disso, aqui estão algumas grandes apresentações úteis por[James Prestwich](https://twitter.com/_prestwich) que podem ajudar a desenvolver uma compreensão mais profunda das bridges: +Além disso, aqui estão algumas apresentações perspicazes de [James Prestwich](https://twitter.com/_prestwich) que podem ajudar a desenvolver uma compreensão mais profunda sobre pontes: -- [Building Bridges, Not Walled Gardens](https://youtu.be/ZQJWMiX4hT0) -- [Breaking Down Bridges](https://youtu.be/b0mC-ZqN8Oo) -- [Why are the Bridges Burning](https://youtu.be/c7cm2kd20j8) +- [Construindo Pontes, Não Jardins Murados](https://youtu.be/ZQJWMiX4hT0) +- [Analisando as Pontes](https://youtu.be/b0mC-ZqN8Oo) +- [Por que as Pontes Estão Queimando?](https://youtu.be/c7cm2kd20j8) diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/index.md index 58765e328f7..538a7948dc8 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/index.md @@ -1,20 +1,20 @@ --- title: Mecanismos de consenso -description: Uma explicação dos protocolos de consenso em sistemas distribuídos e o papel que desempenham no Ethereum. +description: "Uma explicação dos protocolos de consenso em sistemas distribuídos e o papel que desempenham no Ethereum." lang: pt-br --- -O termo "mecanismo de consenso" é frequentemente usado de forma coloquial para se referir a protocolos de "prova de participação", "prova de trabalho" ou "prova de autoridade". No entanto, esses são apenas componentes nos mecanismos de consenso que protegem contra [ataques Sybil](/glossary/#sybil-attack). Mecanismos de consenso são a pilha completa de ideias, protocolos e incentivos que permitem que um conjunto distribuído de nós concorde com o estado da cadeia de blocos. +O termo "mecanismo de consenso" é frequentemente usado de forma coloquial para se referir a protocolos de "prova de participação", "prova de trabalho" ou "prova de autoridade". No entanto, esses são apenas componentes em mecanismos de consenso que protegem contra [ataques Sybil](/glossary/#sybil-attack). Mecanismos de consenso são a pilha completa de ideias, protocolos e incentivos que permitem que um conjunto distribuído de nós concorde com o estado da cadeia de blocos. ## Pré-requisitos {#prerequisites} -Para melhor entender esta página, recomendamos que você leia primeiro a nossa [Introdução ao Ethereum](/developers/docs/intro-to-ethereum/). +Para entender melhor esta página, recomendamos que você leia primeiro nossa [introdução ao Ethereum](/developers/docs/intro-to-ethereum/). ## O que é consenso? {#what-is-consensus} Por consenso, queremos dizer que se chegou a um acordo geral. Considere um grupo de pessoas indo ao cinema. Se não houver desacordo sobre uma proposta de escolha de filme, então um consenso é alcançado. Se houver desacordo, o grupo deve ter meios para decidir qual filme assistir. Em casos extremos, o grupo eventualmente se separará. -Em relação à cadeia de blocos Ethereum, o processo é formalizado e chegar a um consenso significa que pelo menos 66% dos nós da rede concordam com o estado global da rede. +No que diz respeito à blockchain da Ethereum, o processo é formalizado, e alcançar o consenso significa que pelo menos 66% dos nós na rede concordam com o estado global da rede. ## O que é um mecanismo de consenso? {#what-is-a-consensus-mechanism} @@ -32,9 +32,9 @@ Esses componentes juntos formam o mecanismo de consenso. ### Baseado em prova de trabalho {#proof-of-work} -Como o Bitcoin, o Ethereum já usou um protocolo de consenso baseado em **prova de trabalho (PoW)**. +Assim como o Bitcoin, a Ethereum já usou um protocolo de consenso baseado em **prova de trabalho (PoW)**. -#### Criação de blocos {#pow-block-creation} +#### Criação de bloco {#pow-block-creation} Os mineradores competem para criar novos blocos preenchidos com transações processadas. O ganhador compartilha o novo bloco com o restante da rede e ganha alguns ETH recentemente cunhados. A corrida é vencida pelo computador que é capaz de resolver um quebra-cabeça matemático mais rápido. Isso produz o link criptográfico entre o bloco atual e o bloco anterior. Resolver o quebra-cabeça é o trabalho na “prova de trabalho”. A cadeia padrão é então determinada por uma regra de escolha de bifurcação que seleciona o conjunto de blocos que tiveram mais trabalho para minerá-los. @@ -46,9 +46,9 @@ Mais sobre [prova de trabalho](/developers/docs/consensus-mechanisms/pow/) ### Baseado em prova de participação {#proof-of-stake} -O Ethereum agora usa um protocolo de consenso baseado em **prova de participação (PoS)**. +A Ethereum agora usa um protocolo de consenso baseado em **prova de participação (PoS)**. -#### Criação de blocos {#pos-block-creation} +#### Criação de bloco {#pos-block-creation} Validadores criam blocos. Um validador é selecionado aleatoriamente em cada espaço para ser o proponente do bloco. Seu cliente de consenso solicita um pacote de transações como uma “carga de execução” de seu cliente de execução emparelhado. Eles envolvem isso em dados de consenso para formar um bloco, o qual eles enviam para outros nós na rede Ethereum. Essa produção de blocos é recompensada em ETH. Em casos raros, quando existem múltiplos blocos possíveis para um único espaço, ou os nós ouvem sobre blocos em tempos diferentes, o algoritmo da bifurcação escolhido seleciona o bloco que forma a cadeia com o maior peso de atestações (em que o peso é o número de validadores que atestam a escala pelo seu saldo ETH). @@ -68,21 +68,21 @@ Saiba mais sobre os diferentes tipos de mecanismos de consenso utilizados no Eth Prova de trabalho e prova de participação por si só não são protocolos de consenso, mas são frequentemente referidos como tal por simplicidade. Na verdade, são mecanismos de resistência a ataques Sybil e bloqueiam os seletores de autores; eles são uma maneira de decidir quem é o autor do bloco mais recente. Outro componente importante é o algoritmo de seleção de cadeia (também conhecido como escolha da bifurcação), o qual permite que os nós escolham um único bloco correto no início da cadeia em cenários em que existem vários blocos na mesma posição. -**A resistência a ataques Sybil** mede como um protocolo se comporta frente um ataque Sybil. A resistência a esse tipo de ataque é essencial para uma cadeia de blocos descentralizada e permite que os mineradores e validadores sejam recompensados igualmente com base nos recursos colocados. A prova de trabalho e a prova de participação protegem contra isso fazendo os usuários gastarem muita energia ou colocarem muitas garantias. Essas proteções são um elemento econômico de dissuasão dos ataques Sybil. +**A resistência a ataques Sybil** mede como um protocolo se comporta contra um ataque Sybil. A resistência a esse tipo de ataque é essencial para uma cadeia de blocos descentralizada e permite que os mineradores e validadores sejam recompensados igualmente com base nos recursos colocados. A prova de trabalho e a prova de participação protegem contra isso fazendo os usuários gastarem muita energia ou colocarem muitas garantias. Essas proteções são um elemento econômico de dissuasão dos ataques Sybil. -Uma **regra de seleção de cadeia** é usada para decidir qual é a cadeia "correta". O Bitcoin usa a regra da "cadeia mais longa", o que significa que qualquer cadeia de blocos mais longa será aquela que o resto dos nós aceitam como válida e com a qual trabalha. Para as cadeias de prova de trabalho, a cadeia mais longa é determinada pela dificuldade cumulativa total da prova de trabalho. O Ethereum costumava usar a regra da cadeia mais longa também; no entanto, agora que o Ethereum é executado em prova de participação, ele adotou um algoritmo atualizado de escolha da bifurcação que mede o "peso" da cadeia. O peso é a soma acumulada dos votos do validador, ponderada pelos saldos de ether envolvidos do validador. +Uma **regra de seleção de cadeia** é usada para decidir qual cadeia é a "correta". O Bitcoin usa a regra da "cadeia mais longa", o que significa que qualquer cadeia de blocos mais longa será aquela que o resto dos nós aceitam como válida e com a qual trabalha. Para as cadeias de prova de trabalho, a cadeia mais longa é determinada pela dificuldade cumulativa total da prova de trabalho. Ethereum costumava usar a regra da cadeia mais longa também; no entanto, agora que o Ethereum é executado em prova de participação, ele adotou um algoritmo atualizado de escolha de fork que mede o 'peso' da cadeia. O peso é a soma acumulada dos votos do validador, ponderada pelos saldos de ether envolvidos do validador. -O Ethereum usa um mecanismo de consenso conhecido como [Gasper](/developers/docs/consensus-mechanisms/pos/gasper/) que combina a [prova de participação do Casper FFG](https://arxiv.org/abs/1710.09437) com a [regra de escolha de bifurcação GHOST](https://arxiv.org/abs/2003.03052). +A Ethereum usa um mecanismo de consenso conhecido como [Gasper](/developers/docs/consensus-mechanisms/pos/gasper/) que combina a [prova de participação Casper FFG](https://arxiv.org/abs/1710.09437) com a [regra GHOST de escolha de bifurcação](https://arxiv.org/abs/2003.03052). ## Leitura adicional {#further-reading} - [O que é um algoritmo de consenso de blockchain?](https://academy.binance.com/en/articles/what-is-a-blockchain-consensus-algorithm) -- [O que é Consenso de Nakamoto? Guia completo do principiante](https://blockonomi.com/nakamoto-consensus/) +- [O que é Consenso de Nakamoto? Guia completo para iniciantes](https://blockonomi.com/nakamoto-consensus/) - [Como o Casper funciona?](https://medium.com/unitychain/intro-to-casper-ffg-9ed944d98b2d) - [Sobre a segurança e o desempenho das blockchains de prova de trabalho](https://eprint.iacr.org/2016/555.pdf) - [Falha bizantina](https://en.wikipedia.org/wiki/Byzantine_fault) -_Conhece algum recurso da comunidade que o ajudou? Edite essa página e adicione-o!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ ## Tópicos relacionados {#related-topics} diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/poa/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/poa/index.md index 8b22af17858..c5518051edd 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/poa/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/poa/index.md @@ -1,6 +1,6 @@ --- title: Prova de autoridade (PoA) -description: Uma explicação do protocolo de consenso de prova de autoridade e seu papel no ecossistema. +description: "Uma explicação do protocolo de consenso de prova de autoridade e seu papel no ecossistema." lang: pt-br --- @@ -77,3 +77,4 @@ Assista a uma explicação visual da prova de autoridade: - [Prova de trabalho](/developers/docs/consensus-mechanisms/pow/) - [Prova de participação](/developers/docs/consensus-mechanisms/pos/) + diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/attack-and-defense/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/attack-and-defense/index.md index 68395a28f94..f37960c6baf 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/attack-and-defense/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/attack-and-defense/index.md @@ -1,6 +1,6 @@ --- -title: Ataque e defesa da prova de participação do Ethereum -description: Aprenda sobre os vetores de ataque conhecidos na prova de participação do Ethereum e como eles são defendidos. +title: "Ataque e defesa da prova de participação do Ethereum" +description: "Aprenda sobre os vetores de ataque conhecidos na prova de participação do Ethereum e como eles são defendidos." lang: pt-br --- @@ -12,7 +12,7 @@ Ladrões e sabotadores estão constantemente buscando oportunidades para atacar ## O que os atacantes querem? {#what-do-attackers-want} -Um equívoco comum é achar que um atacante bem-sucedido pode gerar um novo ether ou drenar ethers de contas arbitrárias. Nenhuma dessas duas situações é possível, pois todas as transações são executadas por todos os clientes de execução na rede. Elas devem satisfazer condições básicas de validade (por exemplo, transações são assinadas pela chave privada do remetente, o remetente tem saldo suficiente, etc.) ou então elas simplesmente são anuladas. Há três classes de resultado que um atacante pode visar realisticamente: reorgs, dupla finalidade ou atraso de finalidade. +Um equívoco comum é achar que um atacante bem-sucedido pode gerar um novo ether ou drenar ethers de contas arbitrárias. Nenhuma dessas duas situações é possível, pois todas as transações são executadas por todos os clientes de execução na rede. Elas devem satisfazer as condições básicas de validade (por exemplo, as transações são assinadas pela chave privada do remetente, o remetente tem saldo suficiente, etc.), caso contrário, elas simplesmente revertem. Há três classes de resultado que um atacante pode visar realisticamente: reorgs, dupla finalidade ou atraso de finalidade. Uma **“reorg”** é uma reorganização de blocos em uma nova ordem, possivelmente com a adição ou subtração de alguns blocos na cadeia padrão. Uma reorg maliciosa pode garantir que blocos específicos sejam incluídos ou excluídos, permitindo gastos duplos ou extração de valores ao executar transações front-running e back-running (MEV). As reorgs também podem ser usadas para evitar que certas transações sejam incluídas na cadeia padrão, o que é uma espécie de censura. A forma mais extrema de reorg é a “reversão de finalidade”, que remove ou substitui blocos que foram previamente finalizados. Isso só é possível se mais de ⅓ do ether total em stake for destruído pelo atacante — esta garantia é conhecida como “finalidade econômica” — falaremos sobre isso mais tarde. @@ -58,11 +58,11 @@ Essencialmente, todos os ataques com pouco stake são variações sutis de dois #### reorgs {#reorgs} -Vários artigos descreveram ataques ao Ethereum que realizam reorgs ou atraso de finalidade com apenas uma pequena proporção do total de ethers em stake. Geralmente, esses ataques dependem de o atacante reter algumas informações de outros validadores e, em seguida, divulgá-las de maneira sutil e/ou em algum momento oportuno. Eles geralmente visam deslocar algum(ns) bloco(s) honesto(s) da cadeia padrão. [Neuder et al. 2020](https://arxiv.org/pdf/2102.02247.pdf) mostrou como um validador atacante pode criar e atestar um bloco ("B") para um determinado slot "n+1", mas evita propagá-lo para outros nós na rede. Em vez disso, eles mantêm o bloco atestado até o próximo slot "n+2". Um validador honesto propõe um bloco ("C") para o slot "n+2". Quase simultaneamente, o atacante pode liberar seu bloco retido ("B") e suas atestações retidas para ele, além de atestar que "B" é a cabeça da cadeia com seus votos para o slot "n+2", efetivamente negando a existência do bloco honesto "C". Quando o bloco honesto "D" é liberado, o algoritmo de escolha de fork vê "D" construindo sobre "B" como sendo mais pesado do que "D" construindo sobre "C". O atacante conseguiu, portanto, remover o bloco honesto "C" no slot "n+2" da cadeia padrão usando uma reorganização ex ante de 1 bloco. [Um atacante com 34%](https://www.youtube.com/watch?v=6vzXwwk12ZE) do stake tem uma chance muito alta de sucesso nesse ataque, como explicado [nesta nota](https://notes.ethereum.org/plgVdz-ORe-fGjK06BZ_3A#Fork-choice-by-block-slot-pair). Em teoria, porém, esse ataque poderia ser tentado com stakes menores. [Neuder et al 2020](https://arxiv.org/pdf/2102.02247.pdf) descreveu esse ataque funcionando com 30% do stake, mas posteriormente foi demonstrado que ele é viável com [2% do stake total](https://arxiv.org/pdf/2009.04987.pdf) e, depois, até mesmo para um [único validador](https://arxiv.org/abs/2110.10086#) usando técnicas de balanceamento que examinaremos na próxima seção. +Vários artigos descreveram ataques ao Ethereum que realizam reorgs ou atraso de finalidade com apenas uma pequena proporção do total de ethers em stake. Geralmente, esses ataques dependem de o atacante reter algumas informações de outros validadores e, em seguida, divulgá-las de maneira sutil e/ou em algum momento oportuno. Eles geralmente visam deslocar algum(ns) bloco(s) honesto(s) da cadeia padrão. [Neuder et al. 2020 (https://arxiv.org/pdf/2102.02247.pdf) mostrou como um validador atacante pode criar e atestar um bloco (`B`) para um determinado slot `n+1`, mas evita propagá-lo para outros nós na rede. Em vez disso, eles mantêm o bloco atestado até o próximo slot `n+2`. Um validador honesto propõe um bloco (`C`) para o slot `n+2`. Quase simultaneamente, o atacante pode liberar seu bloco retido (`B`) e suas atestações retidas para ele, além de atestar que `B` é a cabeça da cadeia com seus votos para o slot `n+2`, efetivamente negando a existência do bloco honesto `C`. Quando o bloco honesto `D` é liberado, o algoritmo de escolha de fork vê `D` construindo sobre `B` como sendo mais pesado do que `D` construindo sobre `C`. O atacante conseguiu, portanto, remover o bloco honesto `C` no slot `n+2` da cadeia padrão usando uma reorganização ex ante de 1 bloco. [Um atacante com 34%](https://www.youtube.com/watch?v=6vzXwwk12ZE) do stake tem uma chance muito alta de sucesso nesse ataque, como explicado [nesta nota](https://notes.ethereum.org/plgVdz-ORe-fGjK06BZ_3A#Fork-choice-by-block-slot-pair). Em teoria, porém, esse ataque poderia ser tentado com stakes menores. [Neuder et al 2020](https://arxiv.org/pdf/2102.02247.pdf) descreveu esse ataque funcionando com 30% do stake, mas posteriormente foi demonstrado que ele é viável com [2% do stake total](https://arxiv.org/pdf/2009.04987.pdf) e, depois, até mesmo para um [único validador](https://arxiv.org/abs/2110.10086#) usando técnicas de balanceamento que examinaremos na próxima seção. ![ex-ante re-org](reorg-schematic.png) -Um diagrama conceitual do ataque de reorg de um bloco descrito acima [adaptado de](https://notes.ethereum.org/plgVdz-ORe-fGjK06BZ_3A#Fork-choice-by-block-slot-pair) +Um diagrama conceitual do ataque de reorg de um bloco descrito acima (adaptado de https://notes.ethereum.org/plgVdz-ORe-fGjK06BZ_3A#Fork-choice-by-block-slot-pair) Um ataque mais sofisticado pode dividir o conjunto do validador honesto em grupos discretos contendo visões diferentes da cabeça da cadeia. Isso é conhecido como um **ataque de balanceamento**. O atacante espera pela sua oportunidade de propor um bloco e, quando ela chega, engana e propõe dois. Ele envia um bloco para metade do conjunto do validador honesto e o outro bloco para a outra metade. O erro seria detectado pelo algoritmo de escolha de fork e o proponente de blocos seria reduzido e removido pela rede, mas os dois blocos ainda existiriam e teriam cerca de metade do conjunto validador atestando cada fork. Enquanto isso, os demais validadores maliciosos retêm suas atestações. Então, ao liberar seletivamente as atestações favorecendo um ou outro fork para apenas validadores suficientes no momento em que o algoritmo de escolha de fork é executado, eles inclinam o peso acumulado das atestações a favor de um ou outro fork. Isso pode continuar indefinidamente, com os validadores atacantes mantendo uma divisão igual de validadores entre os dois forks. Como nenhum fork pode atrair uma supermaioria de 2/3, a rede não seria finalizada. @@ -74,9 +74,9 @@ Tanto os ataques de salto, quanto os ataques de balanceamento, dependem de o ata Combinadas, essas medidas criam um cenário em que um proponente de blocos honesto emite seu bloco muito rapidamente após o início do slot, então há um período de ~1/3 de um slot (4 segundos), no qual esse novo bloco pode fazer com que o algoritmo de escolha de fork alterne para outra cadeia. Depois desse mesmo prazo, as atestações que chegam de validadores lentos têm peso reduzido em comparação com os que chegaram mais cedo. Isso favorece fortemente os proponentes e validadores rápidos na determinação da cabeça da cadeia e reduz substancialmente a probabilidade de um ataque de salto ou balanceamento bem-sucedido. -É importante observar que o proponente apenas defende contra “reorgs baratas”, ou seja, tentativas feitas por um atacante com um stake pequeno. Na verdade, o próprio impulsionador do proponente pode ser induzido por partes interessadas maiores. Os autores [desta postagem](https://ethresear.ch/t/change-fork-choice-rule-to-mitigate-balancing-and-reorging-attacks/11127) descrevem como um atacante com 7% de stake pode implantar seus votos estrategicamente para enganar validadores honestos para construir sobre o seu fork, reorganizando um bloco honesto. Esse ataque foi concebido assumindo condições de latência ideais muito improváveis. As probabilidades são ainda muito grandes para o atacante, e o stake maior também significa mais capital em risco e um desincentivo econômico maior. +Vale notar que o proposer boosting, por si só, apenas defende contra “reorgs baratas”, ou seja, aquelas tentadas por um atacante com um stake pequeno. Na verdade, o próprio impulsionador do proponente pode ser induzido por partes interessadas maiores. Os autores [desta postagem](https://ethresear.ch/t/change-fork-choice-rule-to-mitigate-balancing-and-reorging-attacks/11127) descrevem como um atacante com 7% de stake pode implantar seus votos estrategicamente para enganar validadores honestos para construir sobre o seu fork, reorganizando um bloco honesto. Esse ataque foi concebido assumindo condições de latência ideais muito improváveis. As probabilidades são ainda muito grandes para o atacante, e o stake maior também significa mais capital em risco e um desincentivo econômico maior. -Um [ataque de balanceamento visando especificamente a regra LMD](https://ethresear.ch/t/balancing-attack-lmd-edition/11853) também foi proposto, e foi sugerido que ele é viável apesar do impulsionamento do proponente. Um atacante cria duas cadeias concorrentes equivocando sua proposta de bloco e propagando cada bloco para cerca de metade da rede cada, estabelecendo um equilíbrio aproximado entre os forks. Em seguida, os validadores em conluio confundem seus votos, calculando o tempo para que metade da rede receba seus votos no fork "A" primeiro, e a outra metade receba seus votos no fork "B" primeiro. Já que a regra de LMD descarta o segundo certificado e mantém apenas o primeiro para cada validador, metade da rede vê os votos para "A" e nenhum para "B", sendo que a outra metade vê votos para "B" e nenhum para "A". Os autores descrevem a regra de LMD como dando ao adversário “poder notável” para montar um ataque de balanceamento. +Um [ataque de balanceamento visando especificamente a regra LMD](https://ethresear.ch/t/balancing-attack-lmd-edition/11853) também foi proposto, e foi sugerido que ele é viável apesar do impulsionamento do proponente. Um atacante cria duas cadeias concorrentes equivocando sua proposta de bloco e propagando cada bloco para cerca de metade da rede cada, estabelecendo um equilíbrio aproximado entre os forks. Em seguida, os validadores em conluio confundem seus votos, calculando o tempo para que metade da rede receba seus votos no fork `A` primeiro, e a outra metade receba seus votos no fork `B` primeiro. Já que a regra de LMD descarta o segundo certificado e mantém apenas o primeiro para cada validador, metade da rede vê os votos para `A` e nenhum para `B`, sendo que a outra metade vê votos para `B` e nenhum para `A`. Os autores descrevem a regra de LMD como dando ao adversário “poder notável” para montar um ataque de balanceamento. Esse vetor de ataque LMD foi fechado ao [atualizar o algoritmo de escolha de fork](https://github.com/ethereum/consensus-specs/pull/2845) para descartar completamente os validadores que cometerem equívocos de consideração na escolha do fork. Os validadores equivocados também têm sua futura influência descontada pelo algoritmo de escolha do fork. Isso evita o ataque de balanceamento descrito acima e mantém também resiliência contra ataques em avalanche. @@ -84,7 +84,7 @@ Outra classe de ataque, chamada de [**ataques de avalanche**](https://ethresear. O ataque em avalanche é mitigado pela porção de LMD do algoritmo de escolha do fork LMD-GHOST. LMD significa “latest-message-driven” (dirigido à última mensagem) e se refere a uma tabela mantida por cada validador contendo a última mensagem recebida de outros validadores. Esse campo só é atualizado se a nova mensagem for de um slot posterior ao que já está na tabela para um validador em particular. Na prática, isso significa que em cada slot, a primeira mensagem recebida é aquela que aceitou e todas as mensagens adicionais são equívocos a serem ignorados. Por outras palavras, os clientes de consenso não contam equívocos — eles usam a primeira mensagem de cada validador e os equívocos são simplesmente descartados, evitando ataques em avalanche. -Há várias outras atualizações futuras possíveis para a regra de escolha do fork que podem aumentar a segurança fornecida pelo impulsionador do proponente. Uma delas é a [view-merge](https://ethresear.ch/t/view-merge-as-a-replacement-for-proposer-boost/13739), na qual os atestadores congelam sua visão da escolha de fork "n" segundos antes do início de um slot e, em seguida, o proponente ajuda a sincronizar a visão da cadeia em toda a rede. Outra possível melhoria é a [finalidade em slot único](https://notes.ethereum.org/@vbuterin/single_slot_finality), que protege contra ataques baseados no tempo das mensagens ao finalizar a cadeia após apenas um slot. +Há várias outras atualizações futuras possíveis para a regra de escolha do fork que podem aumentar a segurança fornecida pelo impulsionador do proponente. Uma delas é a [view-merge](https://ethresear.ch/t/view-merge-as-a-replacement-for-proposer-boost/13739), na qual os atestadores congelam sua visão da escolha de fork `n` segundos antes do início de um slot e, em seguida, o proponente ajuda a sincronizar a visão da cadeia em toda a rede. Outra possível melhoria é a [finalidade em slot único](https://notes.ethereum.org/@vbuterin/single_slot_finality), que protege contra ataques baseados no tempo das mensagens ao finalizar a cadeia após apenas um slot. #### Atraso de finalidade {#finality-delay} @@ -120,7 +120,7 @@ Com >50% do stake total, o atacante poderia dominar o algoritmo de escolha do fo ### Atacantes usando >=66% do stake total {#attackers-with-66-stake} -Um atacante com 66% ou mais do ether total em stake pode finalizar sua cadeia preferida sem ter que coagir nenhum validador honesto. O atacante pode simplesmente votar no seu fork preferido e depois finalizá-lo, simplesmente porque ele pode votar com uma supermaioria desonesta. Como detentor da supermaioria, o atacante sempre controlaria o conteúdo dos blocos finalizados, com o poder de gastar, retroceder e gastar novamente, censurar determinadas transações e reorganizar a cadeia como quisesse. Comprando mais ethers para controlar 66% em vez de 51%, o atacante está efetivamente comprando a capacidade de fazer reorganizações ex post e anulações de finalidade (ou seja, alterar o passado e controlar o futuro). As únicas defesas reais aqui são o enorme custo de 66% do total de ethers em stake e a opção de voltar à camada social para coordenar a adoção de um fork alternativo. Podemos explorar isso com mais detalhes na próxima seção. +Um atacante com 66% ou mais do ether total em stake pode finalizar sua cadeia preferida sem ter que coagir nenhum validador honesto. O atacante pode simplesmente votar no seu fork preferido e depois finalizá-lo, simplesmente porque ele pode votar com uma supermaioria desonesta. Como detentor da supermaioria, o atacante sempre controlaria o conteúdo dos blocos finalizados, com o poder de gastar, retroceder e gastar novamente, censurar determinadas transações e reorganizar a cadeia como quisesse. Ao comprar ether adicional para controlar 66% em vez de 51%, o atacante está efetivamente comprando a capacidade de fazer reorganizações ex post e reversões de finalidade (ou seja, mudar o passado, bem como controlar o futuro). As únicas defesas reais aqui são o enorme custo de 66% do total de ethers em stake e a opção de voltar à camada social para coordenar a adoção de um fork alternativo. Podemos explorar isso com mais detalhes na próxima seção. ## Pessoas: a última linha de defesa {#people-the-last-line-of-defense} @@ -130,9 +130,9 @@ Um dos pontos fortes do consenso de prova de participação do Ethereum é que e Seja qual for a penalidade imposta ao atacante, a comunidade também tem de decidir em conjunto se a cadeia desonesta, apesar de ser a favorita pelo algoritmo de escolha do fork codificado nos clientes Ethereum, é de fato inválida e se a comunidade deve construir por cima da cadeia honesta. Os validadores honestos poderiam concordar coletivamente em construir sobre um fork aceito pela comunidade da blockchain Ethereum que poderia, por exemplo, ter feito o fork da cadeia padrão antes de o ataque começar ou ter os validadores dos atacantes removidos forçadamente. Os validadores honestos seriam incentivados a construir nessa cadeia, pois eles evitariam as penalidades aplicadas a eles por falhar (devidamente) em atestar a cadeia do invasor. Agências de câmbio, rampas de acesso e aplicativos construídos no Ethereum provavelmente prefeririam estar na cadeia honesta e seguir os validadores honestos na blockchain honesta. -No entanto, isso constituiria um desafio substancial em termos de governança. Alguns usuários e validadores certamente se perderiam ao retornar à cadeia honesta. As transações em blocos validados após o ataque poderiam ser anuladas, perturbando a camada de aplicação, o que simplesmente compromete a ética de alguns usuários que tendem a acreditar que “código é lei”. Agências de câmbio e aplicações teriam provavelmente vinculado ações fora da cadeia a transações na cadeia, que agora podem ser anuladas, começando uma cascata de retratações e revisões que seria difícil de desfazer de forma justa, especialmente se os ganhos obtidos ilicitamente tiverem sido misturados, depositados em DeFi ou em outros derivados com efeitos secundários para usuários honestos. Sem dúvida que alguns usuários, talvez mesmo institucionais, já teriam se beneficiado da cadeia desonesta, seja por esperteza ou por acaso, e poderiam se opor a um fork para proteger seus ganhos. Houve pedidos para ensaiar a resposta da comunidade a ataques de >51% para que uma mitigação coordenada e sensata possa ser executada rapidamente. Há uma discussão útil de Vitalik no ethresear.ch [aqui](https://ethresear.ch/t/timeliness-detectors-and-51-attack-recovery-in-blockchains/6925) e [aqui](https://ethresear.ch/t/responding-to-51-attacks-in-casper-ffg/6363) e no Twitter aqui. O objetivo de uma resposta social coordenada é o de ser muito direcionada e específica para punir o atacante e minimizar os efeitos para outros usuários. +No entanto, isso constituiria um desafio substancial em termos de governança. Alguns usuários e validadores certamente se perderiam ao retornar à cadeia honesta. As transações em blocos validados após o ataque poderiam ser anuladas, perturbando a camada de aplicação, o que simplesmente compromete a ética de alguns usuários que tendem a acreditar que “código é lei”. Agências de câmbio e aplicações teriam provavelmente vinculado ações fora da cadeia a transações na cadeia, que agora podem ser anuladas, começando uma cascata de retratações e revisões que seria difícil de desfazer de forma justa, especialmente se os ganhos obtidos ilicitamente tiverem sido misturados, depositados em DeFi ou em outros derivados com efeitos secundários para usuários honestos. Sem dúvida que alguns usuários, talvez mesmo institucionais, já teriam se beneficiado da cadeia desonesta, seja por esperteza ou por acaso, e poderiam se opor a um fork para proteger seus ganhos. Houve pedidos para ensaiar a resposta da comunidade a ataques de >51% para que uma mitigação coordenada e sensata possa ser executada rapidamente. Há uma discussão útil de Vitalik no ethresear.ch [aqui](https://ethresear.ch/t/timeliness-detectors-and-51-attack-recovery-in-blockchains/6925) e [aqui](https://ethresear.ch/t/responding-to-51-attacks-in-casper-ffg/6363) e no Twitter [aqui](https://twitter.com/skylar_eth/status/1551798684727508992?s=20&t=oHZ1xv8QZdOgAXhxZKtHEw). O objetivo de uma resposta social coordenada é o de ser muito direcionada e específica para punir o atacante e minimizar os efeitos para outros usuários. -Governança já é um tema complicado. Gerenciar uma resposta de emergência na Camada 0 para uma cadeia de finalização desonesta seria, sem dúvida, um desafio para a comunidade Ethereum, mas isso [já aconteceu](/ethereum-forks/#dao-fork-summary) — [duas vezes](/ethereum-forks/#tangerine-whistle) — na história da Ethereum. +Governança já é um tema complicado. Gerenciar uma resposta de emergência na Camada 0 para uma cadeia de finalização desonesta seria, sem dúvida, um desafio para a comunidade Ethereum, mas isso [já aconteceu](/ethereum-forks/#dao-fork-summary) — [duas vezes](/ethereum-forks/#tangerine-whistle) — na história da Ethereum). No entanto, há algo que é bastante satisfatório na última tentativa no mundo real. Por fim, mesmo com essa pilha fenomenal de tecnologia acima de nós, se o pior alguma vez acontecer, pessoas reais terão de coordenar a solução. diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/attestations/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/attestations/index.md index d37ffa9b2c4..35ba9012abe 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/attestations/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/attestations/index.md @@ -1,6 +1,6 @@ --- -title: Atestações -description: Uma descrição de atestações em prova de participação Ethereum. +title: "Atestações" +description: "Uma descrição de atestações em prova de participação Ethereum." lang: pt-br --- @@ -8,31 +8,31 @@ Espera-se que um validador crie, assine e transmita uma atestação durante cada ## O que é uma atestação? {#what-is-an-attestation} -A cada [época](/glossary/#epoch) (6,4 minutos) um validador propõe uma atestação para a rede. A atestação é para um espaço específico na época. O objetivo da atestação é votar a favor da visão do validador da cadeia, em particular, o bloco justificado mais recente e o primeiro bloco na época atual (conhecidos como pontos de verificação `source` e `target`). Essas informações são combinadas por todos os validadores participantes, permitindo que a rede chegue a consenso sobre o estado da blockchain. +A cada [época](/glossary/#epoch) (6,4 minutos), um validador propõe uma atestação para a rede. A atestação é para um espaço específico na época. O objetivo da atestação é votar a favor da visão do validador da cadeia, em particular, o bloco justificado mais recente e o primeiro bloco na época atual (conhecidos como pontos de verificação `source` e `target`). Essas informações são combinadas por todos os validadores participantes, permitindo que a rede chegue a consenso sobre o estado da blockchain. A atestação contém os seguintes componentes: -- `aggregation_bits`: uma lista de bits de validadores onde a posição mapeia para o índice do validador em seu comitê; o valor (0/1) indica se o validador assinou os `data` (ou seja, se eles estão ativos e concordam com o proponente de blocos) +- `aggregation_bits`: uma bitlist de validadores onde a posição mapeia para o índice do validador em seu comitê; o valor (0/1) indica se o validador assinou o `data` (ou seja, se ele está ativo e concorda com o proponente de bloco) - `data`: detalhes relacionados à atestação, conforme definido abaixo - `signature`: uma assinatura BLS que agrega as assinaturas de validadores individuais -A primeira tarefa para um validador de atestação é construir os `data`. Os `data` contém as seguintes informações: +A primeira tarefa de um validador de atestação é construir o `data`. O `data` contém as seguintes informações: -- `slot`: O número do slot ao qual a atestação se refere -- `index`: Um número que identifica a qual comitê o validador pertence em um determinado slot -- `beacon_block_root`: Hash raiz do bloco que o validador vê à cabeça da cadeia (o resultado da aplicação do algoritmo de escolha de fork) -- `source`: Parte do voto de finalidade indicando o que os validadores veem como o bloco justificado mais recente -- `source`: Parte do voto de finalidade indicando o que os validadores veem como o primeiro bloco na época atual +- `slot`: o número do slot ao qual a atestação se refere +- `index`: um número que identifica a qual comitê o validador pertence em um determinado slot +- `beacon_block_root`: hash raiz do bloco que o validador vê no cabeçalho da cadeia (o resultado da aplicação do algoritmo de escolha de bifurcação) +- `source`: parte do voto de finalidade que indica o que os validadores veem como o bloco justificado mais recente +- `target`: parte do voto de finalidade que indica o que os validadores veem como o primeiro bloco na época atual -Quando o `data` for construído, o validador pode virar o bit em `agregation_bits` correspondente a seu próprio índice validador de 0 a 1 para mostrar que eles participaram. +Depois que o `data` for construído, o validador pode inverter o bit no `aggregation_bits` correspondente ao seu próprio índice de validador de 0 para 1 para mostrar que participou. Finalmente, o validador assina a atestação e o transmite para a rede. ### Atestação agregada {#aggregated-attestation} -Há uma sobrecarga substancial associada ao envio desses dados em torno da rede para cada validador. Portanto, as atestações de validadores individuais são agregados dentro das sub-redes antes de serem transmitidas de forma mais ampla. Isso inclui agregar assinaturas juntas para que uma atestação que é transmitida inclua `data` de consenso e uma única assinatura formada por combinar as assinaturas de todos os validadores que concordam com `data`. Isso pode ser verificado usando `aggregation_bits` porque fornece o índice de cada validador em seu comitê (cuja ID é fornecida em `data`) que podem ser usados para consultar assinaturas individuais. +Há uma sobrecarga substancial associada ao envio desses dados em torno da rede para cada validador. Portanto, as atestações de validadores individuais são agregados dentro das sub-redes antes de serem transmitidas de forma mais ampla. Isso inclui agregar assinaturas para que uma atestação transmitida inclua o `data` de consenso e uma única assinatura formada pela combinação das assinaturas de todos os validadores que concordam com esse `data`. Isso pode ser verificado usando `aggregation_bits`, pois isso fornece o índice de cada validador em seu comitê (cujo ID é fornecido em `data`), que pode ser usado para consultar assinaturas individuais. -Em cada período, 16 validadores em cada sub-rede são selecionados para serem os `agregadores`. Os agregadores coletam todas as atestações que ouvem na rede gossip que têm `dados` equivalentes aos deles. O remetente de cada atestação correspondente é registrado nos `agregation_bits`. Os agregadores então transmitem a agregação de atestação para a rede mais ampla. +Em cada época, 16 validadores em cada sub-rede são selecionados para serem os `agregadores`. Os agregadores coletam todas as atestações que recebem pela rede gossip que têm `data` equivalente aos seus. O remetente de cada atestação correspondente é registrado no `aggregation_bits`. Os agregadores então transmitem a agregação de atestação para a rede mais ampla. Quando um validador é selecionado para ser um proponente de blocos, eles empacotam as atestações das sub-redes até o último slot do novo bloco. @@ -64,29 +64,29 @@ A taxa de atestação do sinalizador é medida usando a soma dos saldos efetivos A recompensa base é calculada de acordo com o número de validadores atestadores e seus saldos efetivos de ether em stake: -`base reward = validator effective balance x 2^6 / SQRT(Effective balance of all active validators)` +`recompensa base = saldo efetivo do validador x 2^6 / SQRT(saldo efetivo de todos os validadores ativos)` -#### Atraso de inclusão {#inclusion-delay} +#### Atraso na inclusão {#inclusion-delay} -No momento em que os validadores votaram no topo da cadeia (`bloco n`), `bloco n+1` ainda não foi proposto. Portanto, as atestações naturalmente são incluídas **um bloco mais tarde** de modo que todas as atestações que votaram no `block n` sendo a cabeça da cadeia foram incluídos no `block n+1` e o **atraso de inclusão** é 1. Se o atraso de inclusão dobrar para dois slots, a recompensa da atestação cai pela metade, porque para calcular a recompensa da atestação, a recompensa base é multiplicada pelo recíproco do atraso de inclusão. +No momento em que os validadores votaram no cabeçalho da cadeia (`bloco n`), o `bloco n+1` ainda não havia sido proposto. Portanto, as atestações são naturalmente incluídas **um bloco depois**, de modo que todas as atestações que votaram no `bloco n` como cabeçalho da cadeia foram incluídas no `bloco n+1`, e o **atraso na inclusão** é de 1. Se o atraso de inclusão dobrar para dois slots, a recompensa da atestação cai pela metade, porque para calcular a recompensa da atestação, a recompensa base é multiplicada pelo recíproco do atraso de inclusão. ### Cenários de atestação {#attestation-scenarios} -#### Validador votante faltante {#missing-voting-validator} +#### Validador de votação ausente {#missing-voting-validator} Validadores têm um máximo de 1 época para enviar sua atestação. Se a atestação foi perdido na época 0, eles podem enviá-lo com um atraso na inclusão na época 1. -#### Agregador faltante {#missing-aggregator} +#### Agregador ausente {#missing-aggregator} -Existem 16 Agregadores por época no total. Além disso, os validadores aleatórios inscrevem-se para **duas sub-redes por 256 épocas** e servem como um backup caso agregadores estejam faltando. +Existem 16 Agregadores por época no total. Além disso, validadores aleatórios se inscrevem em **duas sub-redes por 256 épocas** e servem como backup caso os agregadores estejam ausentes. -#### Proponente de bloco faltante {#missing-block-proposer} +#### Proponente de bloco ausente {#missing-block-proposer} -Observe que, em alguns casos, um agregador de sorte também pode se tornar o proponente de blocos. Se a atestação não foi incluída porque o proponente de bloco foi perdido, o proponente do próximo bloco pega a atestação agregada e a inclui no próximo bloco. No entanto, o **atraso de inclusão** aumentará em um. +Observe que, em alguns casos, um agregador de sorte também pode se tornar o proponente de blocos. Se a atestação não foi incluída porque o proponente de bloco foi perdido, o proponente do próximo bloco pega a atestação agregada e a inclui no próximo bloco. No entanto, o **atraso na inclusão** aumentará em um. ## Leitura adicional {#further-reading} -- [Atestações na especificação anotada de consenso de Vitalik](https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md#attestationdata) +- [Atestações na especificação de consenso anotada do Vitalik](https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md#attestationdata) - [Atestações em eth2book.info](https://eth2book.info/capella/part3/containers/dependencies/#attestationdata) -_Conhece um recurso da comunidade que ajudou você? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/block-proposal/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/block-proposal/index.md index 52527a8e786..2668b7b87ca 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/block-proposal/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/block-proposal/index.md @@ -1,6 +1,6 @@ --- title: Proposta de bloqueio -description: Explicação de como os blocos são propostos na prova de participação do Ethereum. +description: "Explicação de como os blocos são propostos na prova de participação do Ethereum." lang: pt-br --- @@ -8,7 +8,7 @@ Os blocos são as unidades fundamentais da blockchain. Blocos são unidades disc ## Pré-requisitos {#prerequisites} -A proposta de bloco faz parte do protocolo de prova de participação. Para ajudar a entender esta página, recomendamos que você leia sobre a [prova de participação](/developers/docs/consensus-mechanisms/pos/) e a [arquitetura de bloco](/developers/docs/blocks/). +A proposta de bloco faz parte do protocolo de prova de participação. Para ajudar a entender esta página, recomendamos que você leia sobre [prova de participação](/developers/docs/consensus-mechanisms/pos/) e [arquitetura de blocos](/developers/docs/blocks/). ## Quem produz os blocos? {#who-produces-blocks} @@ -18,7 +18,7 @@ Contas validadoras propõem blocos. Contas validadoras são gerenciadas por oper Um único validador é pseudo-aleatoriamente escolhido para propor um bloco em cada slot. Não existe algo realmente aleatório em uma blockchain, porque se cada nó gerou números genuinamente aleatórios, não há como chegar a um consenso. Em vez disso, o objetivo é tornar o processo de seleção do validador imprevisível. A aleatoriedade é alcançada no Ethereum usando um algoritmo chamado RANDAO, que mistura um hash do proponente do bloco com uma semente que é atualizada em todos os blocos. Esse valor é usado para selecionar um validador específico do validador total definido. A seleção do validador é fixa em duas épocas de antecedência como uma forma de proteção contra certos tipos de manipulação de sementes. -Embora os validadores se adicionem ao RANDAO em cada slot, o valor global do RANDAO só é atualizado uma vez por época. Para calcular o índice do próximo proponente de bloco, o valor de RANDAO é misturado com o número do slot para dar um valor único a cada slot. A probabilidade de um validador individual ser selecionado não é simplesmente `1/N` (em que `N` = total de validadores ativos). Em vez disso, ele é ponderado pelo saldo de ETH efetivo de cada validador. O saldo máximo efetivo é de 32 ETH (isso significa que o `saldo < 32 ETH` leva a um peso menor do que o `saldo == 32 ETH`, mas `saldo > 32 ETH` não leva a uma ponderação maior que o saldo de `== 32 ETH`). +Embora os validadores se adicionem ao RANDAO em cada slot, o valor global do RANDAO só é atualizado uma vez por época. Para calcular o índice do próximo proponente de bloco, o valor de RANDAO é misturado com o número do slot para dar um valor único a cada slot. A probabilidade de um validador individual ser selecionado não é simplesmente `1/N` (onde `N` = total de validadores ativos). Em vez disso, ele é ponderado pelo saldo de ETH efetivo de cada validador. O saldo efetivo máximo é de 32 ETH (isso significa que `balance < 32 ETH` leva a um peso menor do que `balance == 32 ETH`, mas `balance > 32 ETH` não leva a um peso maior do que `balance == 32 ETH`). Somente um proponente de blocos é selecionado em cada slot. Em condições normais, um único produtor de blocos cria e libera um único bloco no seu slot dedicado. A criação de dois blocos para o mesmo slot é uma ofensiva removível, geralmente conhecida como “ambiguidade”. @@ -42,9 +42,9 @@ class BeaconBlockBody(Container): execution_payload: ExecutionPayload ``` -O campo `randao_reveal` leva um valor aleatório verificável que o proponente do bloco cria assinando o número da época atual. `eth1_data` é uma votação para a visualização do proponente do bloco no contrato de depósito, incluindo a raiz do depósito da árvore Merkle de depósito e o número total de depósitos que permitem a verificação de novos depósitos. `graffiti` é um campo opcional que pode ser usado para adicionar uma mensagem ao bloco. `proposer_slashings` e `attester_slashings` são campos que contêm provas de que alguns validadores cometeram ofensivas sujeitas a remoção segundo a visualização do proponente da cadeia. `depósitos` é uma lista de novos depósitos do validador dos quais o proponente de bloco está ciente, e `voluntary_exits` é uma lista de validadores que desejam sair, segundo o que o proponente de blocos ouviu falar na rede de fofocas da camada de consenso. O `sync_aggregate` é um vetor que mostra quais validadores foram previamente atribuídos a um comitê de sincronização (um subconjunto de validadores que atendem dados de cliente leve) e participaram da assinatura de dados. +O campo `randao_reveal` recebe um valor aleatório verificável que o propositor do bloco cria ao assinar o número da época atual. `eth1_data` é um voto para a visão do propositor do bloco sobre o contrato de depósito, incluindo a raiz da árvore de Merkle de depósito e o número total de depósitos que permitem que novos depósitos sejam verificados. `graffiti` é um campo opcional que pode ser usado para adicionar uma mensagem ao bloco. `proposer_slashings` e `attester_slashings` são campos que contêm provas de que certos validadores cometeram ofensas passíveis de slashing de acordo com a visão da cadeia do propositor. `deposits` é uma lista de novos depósitos de validadores dos quais o propositor do bloco está ciente, e `voluntary_exits` é uma lista de validadores que desejam sair e dos quais o propositor do bloco ouviu falar na rede gossip da camada de consenso. O `sync_aggregate` é um vetor que mostra quais validadores foram previamente atribuídos a um comitê de sincronização (um subconjunto de validadores que servem dados de cliente leve) e participaram da assinatura de dados. -O `execution_payload` permite que informações sobre transações sejam passadas entre clientes de execução e clientes de consenso. O `execution_payload` é um bloco de dados de execução que fica aninhado em um bloco de sinal (beacon). Os campos dentro de `execution_payload` refletem a estrutura do bloco delineada nas especificações formais (Yellow Paper) do Ethereum, exceto pelo fato de não haver ommers e `prev_randao` existe no lugar de `difficulty`. O cliente de execução tem acesso a um conjunto de operações locais de que ouviu falar na sua própria rede de fofocas. Essas transações são executadas localmente para gerar uma árvore de estado atualizada, conhecida como pós-estado. As transações são incluídas no `execution_payload` como uma lista chamada `transactions` e o pós-estado é fornecido no campo `state-root`. +O `execution_payload` permite que informações sobre transações sejam passadas entre os clientes de execução e de consenso. O `execution_payload` é um bloco de dados de execução que fica aninhado dentro de um bloco de beacon. Os campos dentro do `execution_payload` refletem a estrutura de blocos descrita no yellow paper do Ethereum, exceto que não há ommers e o `prev_randao` existe no lugar de `difficulty`. O cliente de execução tem acesso a um conjunto de operações locais de que ouviu falar na sua própria rede de fofocas. Essas transações são executadas localmente para gerar uma árvore de estado atualizada, conhecida como pós-estado. As transações são incluídas no `execution_payload` como uma lista chamada `transactions` e o pós-estado é fornecido no campo `state-root`. Todos esses dados são coletados em um bloco de sinal, assinado e transmitido para os pares do proponente de blocos, que o propagam para seus pares, etc. @@ -52,18 +52,18 @@ Leia mais sobre a [anatomia dos blocos](/developers/docs/blocks). ## O que acontece com os blocos? {#what-happens-to-blocks} -O bloco é adicionado ao banco de dados local do proponente do bloco e transmitido aos pares pela rede de fofocas da camada de consenso. Quando um validador recebe o bloco, ele verifica os dados dentro dele, inclusive se o bloco tem o pai correto, corresponde ao pacote correto, se o índice do proponente é o esperado, se a revelação RANDAO é válida e se o proponente não foi removido. O `execution_payload` é descompactado e o cliente de execução do validador reexecuta as transações na lista para verificar a proposta de mudança de estado. Supondo que o bloco passe em todas essas verificações, cada validador adiciona o bloco à sua própria cadeia padronizada. O processo recomeça no próximo slot. +O bloco é adicionado ao banco de dados local do proponente do bloco e transmitido aos pares pela rede de fofocas da camada de consenso. Quando um validador recebe o bloco, ele verifica os dados dentro dele, inclusive se o bloco tem o pai correto, corresponde ao pacote correto, se o índice do proponente é o esperado, se a revelação RANDAO é válida e se o proponente não foi removido. O `execution_payload` é desempacotado, e o cliente de execução do validador reexecuta as transações na lista para verificar a mudança de estado proposta. Supondo que o bloco passe em todas essas verificações, cada validador adiciona o bloco à sua própria cadeia padronizada. O processo recomeça no próximo slot. -## Recompensas do bloco {#block-rewards} +## Recompensas de bloco {#block-rewards} -O proponente de blocos recebe pagamento pelo seu trabalho. Há uma `base_reward` calculada como uma função do número de validadores ativos e seus saldos efetivos. O proponente de blocos recebe uma fração de `base_reward` por cada certificado válido incluído no bloco; quanto mais validadores atestarem o bloco, maior será a recompensa do seu proponente. Há também uma recompensa por reportar validadores que devem ser removidos, igual a `1/512 * saldo efetivo` para cada validador removido. +O proponente de blocos recebe pagamento pelo seu trabalho. Há uma `base_reward` calculada como uma função do número de validadores ativos e seus saldos efetivos. O propositor do bloco então recebe uma fração da `base_reward` para cada atestação válida incluída no bloco; quanto mais validadores atestarem o bloco, maior será a recompensa do propositor do bloco. Há também uma recompensa por denunciar validadores que deveriam sofrer slashing, igual a 1/512 \* saldo efetivo para cada validador que sofreu slashing. -[Recompensas e penalidades da PoS](/developers/docs/consensus-mechanisms/pos/rewards-and-penalties) +[Mais sobre recompensas e penalidades](/developers/docs/consensus-mechanisms/pos/rewards-and-penalties) ## Leitura adicional {#further-reading} - [Introdução aos blocos](/developers/docs/blocks/) - [Introdução à prova de participação](/developers/docs/consensus-mechanisms/pos/) -- [Especificações do consenso do Ethereum](https://github.com/ethereum/consensus-specs) -- [Introdução ao Gasper](/developers/docs/consensus-mechanisms/pos/) +- [Especificações de consenso do Ethereum](https://github.com/ethereum/consensus-specs) +- [Introdução ao Gasper](/developers/docs/consensus-mechanisms/pos/gasper/) - [Atualizando o Ethereum](https://eth2book.info/) diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/faqs/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/faqs/index.md index c66156b53a3..0db8a00edc6 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/faqs/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/faqs/index.md @@ -1,6 +1,6 @@ --- title: Perguntas Frequentes -description: Perguntas frequentes sobre a prova de participação do Ethereum. +description: "Perguntas frequentes sobre a prova de participação do Ethereum." lang: pt-br --- @@ -18,7 +18,7 @@ A prova de participação requer nós, conhecidos como validadores, para enviar A prova de trabalho consome muito mais energia porque a eletricidade é consumida no processo de mineração. Por outro lado, a prova de participação requer apenas uma quantidade muito pequena de energia: os validadores do Ethereum podem até ser executados em um dispositivo de baixa potência, como o Raspberry Pi. O mecanismo de prova de participação do Ethereum é considerado mais seguro do que a prova de trabalho, porque o custo do ataque é maior e as consequências para um invasor são mais severas. -A comparação entre prova de trabalho e prova de participação é um tópico controverso. [O blog do Vitalik Buterin](https://vitalik.eth.limo/general/2017/12/31/pos_faq.html#what-are-the-benefits-of-proof-of-stake-as-opposed-to-proof-of-work) e o debate entre Justin Drake e Lyn Alden fornecem um bom resumo dos argumentos. +A comparação entre prova de trabalho e prova de participação é um tópico controverso. O [blog de Vitalik Buterin](https://vitalik.eth.limo/general/2017/12/31/pos_faq.html#what-are-the-benefits-of-proof-of-stake-as-opposed-to-proof-of-work) e o debate entre Justin Drake e Lyn Alden fornecem um bom resumo dos argumentos. @@ -32,8 +32,8 @@ Sim. Os nós em uma rede com prova de participação usam uma pequena quantidade A prova de participação do Ethereum é muito segura. O mecanismo foi pesquisado, desenvolvido e testado rigorosamente ao longo de oito anos de atividade antes de entrar em produção. As garantias de segurança são diferentes de blockchains com prova de trabalho. Na prova de participação, os validadores maliciosos podem ser punidos ativamente (“removidos”) e expulsos do conjunto de validadores, custando uma quantia substancial de ETH. Na prova de trabalho, um invasor pode continuar repetindo seu ataque enquanto ele tem poder de hash suficiente. Também é mais caro organizar ataques equivalentes na prova de participação do Ethereum do que na prova de trabalho. Para afetar a vitalidade da cadeia, é necessário pelo menos 33% do total de ether em participação (stake) na rede (exceto nos casos de ataques muito sofisticados com uma probabilidade de sucesso extremamente baixa). Para controlar o conteúdo de futuros blocos, é necessário pelo menos 51% do total de ETH em participação (stake) e, para reescrever o histórico, é necessário mais de 66% do total em participação (stake). O protocolo Ethereum destruiria esses ativos nos cenários de ataque de 33% ou 51% e por consenso social no cenário de ataque de 66%. -- [Saiba mais sobre como defender a prova de participação do Ethereum contra invasores](/developers/docs/consensus-mechanisms/pos/attack-and-defense) -- [Mais sobre o design da prova de participação](https://medium.com/@VitalikButerin/a-proof-of-stake-design-philosophy-506585978d51) +- [Mais sobre como defender a prova de participação do Ethereum contra invasores](/developers/docs/consensus-mechanisms/pos/attack-and-defense) +- [Mais sobre o projeto da prova de participação](https://medium.com/@VitalikButerin/a-proof-of-stake-design-philosophy-506585978d51) ## A prova de participação torna o Ethereum mais barato? {#does-pos-make-ethereum-cheaper} @@ -50,7 +50,7 @@ Nós são computadores conectados à rede Ethereum. Clientes são o software que ## A prova de participação é uma nova ideia? {#is-pos-new} -Não. Um usuário do BitcoinTalk [propôs a ideia básica de prova de participação](https://bitcointalk.org/index.php?topic=27787.0) como uma atualização para o Bitcoin em 2011. Passaram-se onze anos antes de estar pronto para ser implementado na Rede principal (Mainnet) do Ethereum. Algumas outras cadeias implementaram a prova de participação antes do Ethereum, mas não o mecanismo específico do Ethereum (conhecido como Gasper). +Não. Um usuário no BitcoinTalk [propôs a ideia básica de prova de participação](https://bitcointalk.org/index.php?topic=27787.0) como uma atualização para o Bitcoin em 2011. Passaram-se onze anos antes de estar pronto para ser implementado na Rede principal (Mainnet) do Ethereum. Algumas outras cadeias implementaram a prova de participação antes do Ethereum, mas não o mecanismo específico do Ethereum (conhecido como Gasper). ## O que tem de especial na prova de participação do Ethereum? {#why-is-ethereum-pos-special} @@ -66,7 +66,7 @@ A combinação do Casper com o LMD_GHOST é conhecida como Gasper. Remoção (slashing) é o termo dado à destruição de parte da participação do validador e à expulsão do validador da rede. A quantidade de ETH perdida em escalas de remoção com o número de validadores sendo reduzidos — isso significa que os validadores cúmplices são punidos com mais severidade do que indivíduos. -[Mais sobre remoção (slashing)](/developers/docs/consensus-mechanisms/pos/rewards-and-penalties#slashing) +[Mais sobre remoção](/developers/docs/consensus-mechanisms/pos/rewards-and-penalties#slashing) ## Por que os validadores precisam de 32 ETH? {#why-32-eth} @@ -74,34 +74,34 @@ Os validadores têm que colocar ETH em participação (stake) para que tenham al ## Como os validadores são selecionados? {#how-are-validators-selected} -Um único validador é pseudo-aleatoriamente escolhido para propor um bloco em cada slot usando um algoritmo chamado RANDAO, que mistura um hash do proponente do bloco com uma semente que é atualizada em cada bloco. Esse valor é usado para selecionar um validador específico do conjunto total de validadores. A seleção do validador é fixada com duas épocas de antecedência. +Um único validador é pseudo-aleatoriamente escolhido para propor um bloco em cada slot usando um algoritmo chamado RANDAO, que mistura um hash do proponente do bloco com uma semente que é atualizada em cada bloco. Esse valor é usado para selecionar um validador específico do validador total definido. A seleção do validador é fixada com duas épocas de antecedência. -[Mais sobre a seleção do validador](/developers/docs/consensus-mechanisms/pos/block-proposal) +[Mais sobre a seleção de validadores](/developers/docs/consensus-mechanisms/pos/block-proposal) ## O que significa ataque forçado de participação (stake grinding)? {#what-is-stake-grinding} O ataque forçado de participação é uma categoria de ataque em redes de prova de participação na qual o invasor tenta influenciar o algoritmo de seleção do validador para beneficiar seus próprios validadores. Os ataques forçados de participação (grinding attacks) em RANDAO exigem cerca de metade do total de ETH em participação (stake). -[Mais sobre forçar participação (stake grinding)](https://eth2book.info/altair/part2/building_blocks/randomness/#randao-biasability) +[Mais sobre stake grinding](https://eth2book.info/altair/part2/building_blocks/randomness/#randao-biasability) ## O que é a remoção social? {#what-is-social-slashing} A remoção social consiste na capacidade de uma comunidade em coordenar uma bifurcação (fork) da blockchain em resposta a um ataque. Ela permite à comunidade se recuperar do ataque de um invasor, finalizando uma cadeia desonesta. O corte social também pode ser utilizado contra ataques de censura. -- [Mais a respeito de remoção social](https://ercwl.medium.com/the-case-for-social-slashing-59277ff4d9c7) +- [Mais sobre remoção social](https://ercwl.medium.com/the-case-for-social-slashing-59277ff4d9c7) - [Vitalik Buterin sobre remoção social](https://vitalik.eth.limo/general/2017/12/31/pos_faq.html#what-is-proof-of-stake) ## Eu serei removido? {#will-i-get-slashed} Como validador, é muito difícil ser removido, a menos que você se envolva deliberadamente em um comportamento malicioso. A remoção só é implementada em cenários muito específicos, nos quais os validadores propõem vários blocos para o mesmo slot ou se contradizem com suas atestações, o que é muito improvável acontecer acidentalmente. -[Mais sobre condições de remoção](https://eth2book.info/altair/part2/incentives/slashing) +[Mais sobre as condições de remoção](https://eth2book.info/altair/part2/incentives/slashing) ## Qual é o problema do “nada em participação” (nothing-at-stake)? {#what-is-nothing-at-stake-problem} O problema do nada em participação (stake) é uma questão conceitual com alguns mecanismos de prova de participação, nos quais há apenas recompensas e nenhuma penalidade. Se não há nada em participação (stake), um validador pragmático poderá sem problemas atestar qualquer uma, ou mesmo várias, bifurcações (forks) da blockchain, pois isso aumenta suas recompensas. O Ethereum contorna isso usando condições de finalidade e remoções para garantir uma cadeia padronizada. -[Mais sobre o problema do “nada em participação”](https://vitalik.eth.limo/general/2017/12/31/pos_faq.html#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed) +[Mais sobre o problema do 'nada em jogo'](https://vitalik.eth.limo/general/2017/12/31/pos_faq.html#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed) ## O que é um algoritmo de escolha de bifurcação (fork)? {#what-is-a-fork-choice-algorithm} @@ -109,7 +109,7 @@ Um algoritmo de escolha de bifurcação (fork) implementa regras que determinam O algoritmo de escolha da bifurcação (fork) do Ethereum é chamado LMD-GHOST. Ele escolhe a bifurcação (fork) com o maior peso de atestações, ou seja, aquele que tem votado mais ETH em participação (stake). -[Mais sobre LMD-GHOST](/developers/docs/consensus-mechanisms/pos/gasper/#fork-choice) +[Mais sobre o LMD-GHOST](/developers/docs/consensus-mechanisms/pos/gasper/#fork-choice) ## Qual a finalidade da prova de participação? {#what-is-finality} @@ -127,19 +127,19 @@ A subjetividade fraca é um recurso de redes de prova de participação, em que No momento, é difícil provar resistência à censura. No entanto, ao contrário da prova de trabalho, a prova de participação oferece a opção de coordenar remoções para punir os validadores que censuram. Há mudanças futuras no protocolo que separam os construtores de blocos dos proponentes de blocos e implementam listas de transações que os construtores devem incluir em cada bloco. Essa proposta é conhecida como separação apropriada do construtor e ajuda a evitar que os validadores censurem as transações. -[Mais sobre separação apropriada do construtor](https://notes.ethereum.org/@fradamt/H1TsYRfJc#Original-basic-scheme) +[Mais sobre a separação proponente-construtor](https://notes.ethereum.org/@fradamt/H1TsYRfJc#Original-basic-scheme) ## O sistema de prova de participação do Ethereum pode ser atacado em 51%? {#pos-51-attack} Sim. A prova de participação é vulnerável a 51% dos ataques, bem como a prova de trabalho. Ao invés do atacante precisar de 51% do poder de hash da rede, o atacante requer 51% do total de ETH em stake. Um invasor que acumula 51% do total em participação (stake) consegue controlar o algoritmo de escolha da bifurcação (fork). Isso permite que o invasor censure certas transações, faça reorganizações de curto alcance e extraia MEV reordenando blocos a seu favor. -[Leia mais sobre ataques na prova de participação](/developers/docs/consensus-mechanisms/pos/attack-and-defense) +[Mais sobre ataques à prova de participação](/developers/docs/consensus-mechanisms/pos/attack-and-defense) ## O que é coordenação social e por que ela é necessária? {#what-is-social-coordination} A coordenação social é a última linha de defesa do Ethereum que permitiria uma cadeia honesta ser recuperada de um ataque que finalizou blocos desonestos. Nesse caso, a comunidade do Ethereum teria que se coordenar “fora de banda” e concordar em usar uma bifurcação (fork) minoritária honesta, removendo os validadores mal-intencionados no processo. Isso exigiria aplicativos e corretoras para reconhecer também a bifurcação (fork) honesta. -[Leia mais a respeito da coordenação social](/developers/docs/consensus-mechanisms/pos/attack-and-defense#people-the-last-line-of-defense) +[Leia mais sobre coordenação social](/developers/docs/consensus-mechanisms/pos/attack-and-defense#people-the-last-line-of-defense) ## O rico fica mais rico na prova de participação? {#do-rich-get-richer} @@ -147,9 +147,9 @@ Quanto mais ETH alguém tiver para colocar em participação (stake), mais os va ## A prova de participação é mais centralizada do que a prova de trabalho? {#is-pos-decentralized} -Não, a prova de trabalho tende à centralização, porque os custos de mineração aumentam e tiram indivíduos do mercado, depois tiram pequenas empresas do mercado, e assim por diante. O problema atual com prova de participação é a influência dos derivados líquidos de participação (LSDs). Eles são tokens que representam o ETH em participação (stake) por algum provedor, com o qual qualquer pessoa pode fazer swap cambial em mercados secundários sem que o ETH real seja retirado da participação (stake). Os LSDs permitem que usuários coloquem em participação (stake) menos de 32 ETH, mas também criam um risco de centralização, permitindo que algumas organizações importantes acabem controlando grande parte da participação (stake). É por isso que a [participação individual](/staking/solo) (solo staking) é a melhor opção para o Ethereum. +Não, a prova de trabalho tende à centralização, porque os custos de mineração aumentam e tiram indivíduos do mercado, depois tiram pequenas empresas do mercado, e assim por diante. O problema atual com prova de participação é a influência dos derivados líquidos de participação (LSDs). Eles são tokens que representam o ETH em participação (stake) por algum provedor, com o qual qualquer pessoa pode fazer swap cambial em mercados secundários sem que o ETH real seja retirado da participação (stake). Os LSDs permitem que usuários coloquem em participação (stake) menos de 32 ETH, mas também criam um risco de centralização, permitindo que algumas organizações importantes acabem controlando grande parte da participação (stake). É por isso que a [participação individual (solo staking)](/staking/solo) é a melhor opção para o Ethereum. -[Mais sobre a centralização de participação (stake) em LSDs](https://notes.ethereum.org/@djrtwo/risks-of-lsd) +[Mais sobre a centralização de stake em LSDs](https://notes.ethereum.org/@djrtwo/risks-of-lsd) ## Por que eu só posso colocar ETH em participação (stake)? {#why-can-i-only-stake-eth} @@ -163,10 +163,10 @@ Não, há várias blockchains que possuem prova de participação. No entanto, n A Fusão (The Merge) foi o momento em que o Ethereum desligou o seu mecanismo de consenso baseado em prova de trabalho e ativou o seu mecanismo de consenso baseado em prova de participação. A Fusão (The Merge) ocorreu em 15 de setembro de 2022. -[Mais sobre a integração](/roadmap/merge) +[Mais sobre A Fusão](/roadmap/merge) ## O que é atividade e segurança? {#what-are-liveness-and-safety} -Atividade e segurança são as duas preocupações fundamentais relativas à segurança de uma blockchain. Atividade é a disponibilidade de uma cadeia de finalização. São consideradas falhas de atividade se a cadeia parar de finalizar ou se os usuários não conseguirem acessá-la facilmente. Custos de acesso extremamente elevados também poderiam ser considerados como falha de atividade. Já a segurança se refere ao quão difícil é atacar a cadeia, ou seja, finalizar os pontos de verificação conflitantes. +Atividade e segurança são as duas preocupações fundamentais relativas à segurança de uma blockchain. Atividade é a disponibilidade de uma cadeia de finalização. São consideradas falhas de atividade se a cadeia parar de finalizar ou se os usuários não conseguirem acessá-la facilmente. Custos de acesso extremamente elevados também poderiam ser considerados como falha de atividade. A segurança se refere a quão difícil é atacar a cadeia, ou seja, finalizar pontos de verificação conflitantes. [Leia mais no artigo do Casper](https://arxiv.org/pdf/1710.09437.pdf) diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/gasper/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/gasper/index.md index 4a633193622..e93496bd22d 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/gasper/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/gasper/index.md @@ -1,16 +1,16 @@ --- title: Gasper -description: Uma explicação do mecanismo de prova de participação do Gasper. +description: "Uma explicação do mecanismo de prova de participação do Gasper." lang: pt-br --- Gasper é uma combinação de Casper, o Gadget de Finalidade Amigável (Casper-FFG) e o algoritmo de escolha do fork de LMD-GHOST. Juntos, esses componentes formam o mecanismo de consenso que garante a prova de participação do Ethereum. Casper é o mecanismo que atualiza certos blocos para "finalizados" para que os novos participantes da rede possam ter certeza de que estão sincronizando a cadeia canônica. O algoritmo de escolha de fork usa votos acumulados para garantir que os nós possam selecionar facilmente o correto quando surgirem forks na blockchain. -**Observe** que a definição original de Casper-FFG foi levemente atualizada para inclusão no Gasper. Nesta página consideramos a versão atualizada. +**Nota**: a definição original do Casper-FFG foi ligeiramente atualizada para inclusão no Gasper. Nesta página consideramos a versão atualizada. -## Pré-requisitos +## Pré-Requisitos -Para entender este material, é necessário ler a página introdutória em [prova de participação](/developers/docs/consensus-mechanisms/pos/). +Para entender este material, é necessário ler a página introdutória sobre [prova de participação](/developers/docs/consensus-mechanisms/pos/). ## O papel do Gasper {#role-of-gasper} @@ -23,30 +23,30 @@ Finalidade é uma propriedade de certos blocos que significa que eles não podem 1. Dois terços do total do ether em stake devem ter votado a favor da inclusão desse bloco na cadeia canônica. Essa condição atualiza o bloco para "justificado". Blocos justificados dificilmente serão revertidos, mas podem ser em determinadas condições. 2. Quando outro bloco é justificado em cima de um bloco justificado, ele é atualizado para "finalizado". Finalizar um bloco é um compromisso de incluí-lo na cadeia canônica. Não pode ser revertido, a menos que um atacante destrua milhões de ether (bilhões de $USD). -Estas atualizações de blocos não acontecem em todos os slots. Em vez disso, apenas blocos adjacentes ao epoch podem ser justificados e finalizados. Estes blocos são conhecidos como "checkpoints". A atualização considera pares de checkpoints. Um "link da grande maioria" deve existir entre dois checkpoints sucessivos (ou seja, dois terços do total em stake de ether votam que o checkpoint B é o descendente correto do checkpoint A) para atualizar o checkpoint menos recente para finalizado e o bloco mais recente para justificado. +Estas atualizações de blocos não acontecem em todos os slots. Em vez disso, apenas blocos adjacentes ao epoch podem ser justificados e finalizados. Estes blocos são conhecidos como "checkpoints". A atualização considera pares de checkpoints. Um "link de supermaioria" deve existir entre dois checkpoints sucessivos (ou seja, dois terços do total de ether em stake votando que o checkpoint B é o descendente correto do checkpoint A) para atualizar o checkpoint menos recente para finalizado e o bloco mais recente para justificado. Dado que a finalidade requer um acordo de dois terços de que um bloco é canônico, um atacante não pode possivelmente criar uma cadeia finalizada alternativa sem: 1. Possuir ou manipular dois terços do ether em stake. 2. Destruir pelo menos um terço do ether em stake. -A primeira condição surge porque dois terços do ether em stake são necessários para finalizar uma cadeia. A segunda condição surge porque se dois terços do stake total votaram a favor de ambos forks, então um terço deve ter votado em ambos. O voto duplicado é uma condição de corte, que seria punida ao máximo, e um terço do stake total seria destruído. Desde maio de 2022, isto requer que um atacante queime cerca de US$ 10 bilhões de ether. O algoritmo que justifica e finaliza os blocos no Gasper é uma forma ligeiramente modificada de [Casper o Gadget de Finalidade Amigável (Casper-FFG)](https://arxiv.org/pdf/1710.09437.pdf). +A primeira condição surge porque dois terços do ether em stake são necessários para finalizar uma cadeia. A segunda condição surge porque se dois terços do stake total votaram a favor de ambos forks, então um terço deve ter votado em ambos. O voto duplicado é uma condição de corte, que seria punida ao máximo, e um terço do stake total seria destruído. Desde maio de 2022, isto requer que um atacante queime cerca de US$ 10 bilhões de ether. O algoritmo que justifica e finaliza os blocos no Gasper é uma forma ligeiramente modificada do [Casper, o Gadget de Finalidade Amigável (Casper-FFG)](https://arxiv.org/pdf/1710.09437.pdf). -### Incentivos e cortes {#incentives-and-slashing} +### Incentivos e Remoção {#incentives-and-slashing} Os validadores são recompensados por propor e validar blocos honestamente. Ether é dado como recompensa e adicionado ao stake deles. Por outro lado, validadores que estão ausentes e não conseguem agir quando chamados perdem essas recompensas e, às vezes, perdem uma pequena parte de seu stake existente. No entanto, as penalizações por estar off-line são pequenas e, na maioria dos casos, equivalem ao custo das recompensas perdidas. No entanto, algumas ações do validador são muito difíceis de fazer acidentalmente e significam alguma intenção maliciosa, tais como propor vários blocos para o mesmo slot, atestar em vários blocos para o mesmo slot, ou contradizer votos anteriores de checkpoint. Estes são comportamentos "de remoção" que são penalizados mais duramente: destruição de parte da participação do validador e o validador sendo removido da rede de validadores. Este processo dura 36 dias. No dia 1, há uma penalidade inicial de até 1 ETH. O ether do validador removido drena lentamente ao longo do período de saída, mas no dia 18 eles recebem uma “penalidade de correlação”, que é maior quando mais validadores são removidos ao mesmo tempo. A pena máxima é todo o stake. Essas recompensas e penalidades são concebidas para incentivar validadores honestos e desincentivar ataques na rede. -### Perda por inatividade {#inactivity-leak} +### Vazamento por Inatividade {#inactivity-leak} Além da segurança, o Gasper também fornece "uma vivacidade plausível". Esta condição prevê que enquanto dois terços do ether total em stake votarem honestamente e seguirem o protocolo, a cadeia poderá finalizar independentemente de qualquer outra atividade (como ataques, problemas de latência ou cortes). Em outras palavras, um terço do ether total em stake deve estar comprometido de alguma forma para evitar que a cadeia finalize. No Gasper, existe uma linha de defesa adicional contra uma falha de vivacidade, conhecida como o "perda por inatividade". Este mecanismo é ativado quando a cadeia falhou em finalizar por mais de quatro epochs. Os validadores que não estão atestando ativamente a cadeia da maioria, têm seu stake gradualmente drenado até que a maioria recupere dois terços do stake total, assegurando que as falhas de vivacidade sejam apenas temporárias. -### Escolha do fork {#fork-choice} +### Escolha de bifurcação {#fork-choice} -A definição original do Casper-FFG incluía um algoritmo de escolha de fork que determinava a regra: `follow the chain containing the justified checkpoint that has the greatest height` em que a altura é definida como a maior distância do bloco de início. No Gasper, a regra de escolha do fork original está descontinuada em favor de um algoritmo mais sofisticado chamado LMD-GHOST. É importante compreender que, em condições normais, uma regra de escolha de fork é desnecessária – há um único proponente de bloco para cada slot, e validadores honestos atestam isso. Um algoritmo de escolha de fork é necessário somente quando há uma grande assincronicidade de rede ou quando um proponente de blocos desonesto se equivoca. Quando esses casos surgem, o algoritmo de escolha do fork é uma defesa fundamental que protege a cadeia correta. +A definição original do Casper-FFG incluía um algoritmo de escolha de bifurcação que impunha a regra: `siga a cadeia que contém o checkpoint justificado que tem a maior altura`, onde a altura é definida como a maior distância do bloco de início. No Gasper, a regra de escolha do fork original está descontinuada em favor de um algoritmo mais sofisticado chamado LMD-GHOST. É importante compreender que, em condições normais, uma regra de escolha de fork é desnecessária – há um único proponente de bloco para cada slot, e validadores honestos atestam isso. Um algoritmo de escolha de fork é necessário somente quando há uma grande assincronicidade de rede ou quando um proponente de blocos desonesto se equivoca. Quando esses casos surgem, o algoritmo de escolha do fork é uma defesa fundamental que protege a cadeia correta. LMD-GHOST são as siglas de "latest message-driven greedy heaviest observed sub-tree". Esta é uma definição em jargão de um algoritmo que seleciona o fork com o maior peso acumulado de confimações como a canônica (subárvore mais pesada) e que se várias mensagens forem recebidas de um validador, apenas a última será considerada (orientada pela última mensagem). Antes de adicionar o bloco mais pesado à sua cadeia canônica, todo validador avalia cada bloco usando esta regra. -## Leitura Adicional {#further-reading} +## Leitura adicional {#further-reading} -- [Gasper: Combinando GHOST e Casper](https://arxiv.org/pdf/2003.03052.pdf) -- [Casper, o Mecanismo de Finalidade Amigável](https://arxiv.org/pdf/1710.09437.pdf) +- [Gasper: Combining GHOST and Casper](https://arxiv.org/pdf/2003.03052.pdf) +- [Casper, o Gadget de Finalidade Amigável](https://arxiv.org/pdf/1710.09437.pdf) diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/index.md index 9ee5d73316d..437868396ce 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/index.md @@ -1,14 +1,14 @@ --- -title: Prova de participação (PoS) -description: Explicação do protocolo de consenso "Prova de participação" e seu papel no Ethereum. +title: "Prova de participação (PoS)" +description: "Explicação do protocolo de consenso \"Prova de participação\" e seu papel no Ethereum." lang: pt-br --- -A prova de participação (PoS) é a base do [mecanismo de consenso](/developers/docs/consensus-mechanisms/) do Ethereum. O Ethereum ativou seu mecanismo de prova de participação em 2022 porque é mais seguro, consome menos energia e é melhor para implementar novas soluções de escalabilidade em comparação com a arquitetura de [prova de trabalho](/developers/docs/consensus-mechanisms/pow) anterior. +A Prova de participação (PoS) fundamenta o [mecanismo de consenso](/developers/docs/consensus-mechanisms/) do Ethereum. O Ethereum ativou seu mecanismo de prova de participação em 2022 porque é mais seguro, consome menos energia e é melhor para implementar novas soluções de escalabilidade em comparação com a arquitetura de [prova de trabalho](/developers/docs/consensus-mechanisms/pow) anterior. ## Pré-requisitos {#prerequisites} -Para entender melhor esta página, recomendamos que você primeiro leia [mecanismos de consenso](/developers/docs/consensus-mechanisms/). +Para entender melhor esta página, recomendamos que você leia primeiro sobre os [mecanismos de consenso](/developers/docs/consensus-mechanisms/). ## O que é prova de participação (PoS)? {#what-is-pos} @@ -20,38 +20,38 @@ Para participar como validador, um usuário deve depositar 32 ETH no contrato de Enquanto na prova de trabalho, o tempo dos blocos é determinado pela dificuldade de mineração, na prova de participação o tempo é fixo. O tempo na prova de participação do Ethereum é dividido em slots (12 segundos) e épocas (32 slots). Um validador é selecionado aleatoriamente para ser um proponente de bloco em cada espaço. Esse validador é responsável por criar um novo bloco e enviá-lo para outros nós da rede. Também em cada slot, um comitê de validadores é escolhido aleatoriamente, cujos votos são utilizados para determinar a validade do bloco proposto. Dividir o validador configurado em comitês é importante para manter a carga de rede gerenciável. Os comitês dividem o conjunto de validadores, de modo que cada validador ativo ateste em cada época, mas não em cada espaço (slot). -## Como uma transação é executada na Ethereum PoS {#transaction-execution-ethereum-pos} +## Como uma transação é executada no Ethereum PoS {#transaction-execution-ethereum-pos} -O seguinte fornece uma explicação de ponta a ponta de como uma transação é executada na proof-of-stake da Ethereum. +Abaixo está uma explicação completa de como uma transação é executada no proof-of-stake do Ethereum. -1. Um usuário cria e assina uma href="/developers/docs/transactions/">transação/a> com sua chave privada. Isso geralmente é feito por uma carteira ou uma biblioteca como a [ethers.js](https://docs.ethers.org/v6/), [web3js](https://docs.web3js.org/), [web3py](https://web3py.readthedocs.io/en/v5/) etc., mas, no fundo, o usuário está fazendo uma solicitação para um nó usando o Ethereum [JSON-RPC API](/developers/docs/apis/json-rpc/). O usuário define a quantidade de gás que está disposto a pagar como gorjeta a um validador para incentivá-lo a incluir a transação em um bloco. As [dicas](/developers/docs/gas/#priority-fee) são pagas ao validador enquanto a [taxa básica](/developers/docs/gas/#base-fee) é paga queimado. -2. A transação é enviada para um [cliente de execução](/developers/docs/nodes-and-clients/#execution-client) Ethereum que verifica a sua validade. Isto significa garantir que o remetente tem ETH suficiente para realizar a transação e eles o assinaram com a chave correta. -3. Se a transação for válida, o cliente de execução adiciona-o à sua mempool local (lista de transações pendentes) e também a transmite para outros nós por meio da rede gossip da camada de execução. Quando outros nós ouvem sobre a transação, eles a adicionam à sua mempool local também. Os usuários avançados podem abster-se de transmitir sua transações e, em vez disso, encaminhá-la a criadores de blocos especializados, como [Flashbots Auction](https://docs.flashbots.net/flashbots-auction/overview). Isso permite que eles organizem as transações nos próximos blocos para obter o máximo lucro ([MEV](/developers/docs/mev/#mev-extraction)). -4. Um dos nós validadores na rede é o proponente de bloco para o slot atual, tendo sido selecionado pseudo-aleatoriamente usando RANDAO. Este nó é responsável pela construção e transmissão do próximo bloco a ser adicionado à blockchain Ethereum e pela atualização do estado global. O nó é composto por três partes: um cliente de execução, um cliente de consenso e um cliente validador. O cliente de execução empacota transações da mempool local em um "payload de execução" e executa-os localmente para gerar uma mudança de estado. Essas informações são passadas para o cliente de consenso em que a carga da execução é agrupada como parte de um "bloco de sinalização" que também contém informações sobre as recopensas, penalidades, cortes, atestações etc. que permitem que a rede entre em acordo sobre a sequência de blocks no topo da cadeia. A comunicação entre os clientes de execução e consenso é descrita em mais detalhes em [Conectando os clientes de consenso e de execução](/developers/docs/networking-layer/#connecting-clients). -5. Outros nós recebem o novo bloco beacon na rede gossip na camada de consenso. Eles o passam para seu cliente de execução onde as transações são novamente executadas localmente para garantir que a proposta alteração de estado é válida. O cliente validador então atesta que o bloco é válido e é o bloco seguinte lógico em sua visão da cadeia (ou seja, ele constrói na cadeia com o maior peso de atestações, conforme definido nas [regras de escolha de fork (bifurcação)](/developers/docs/consensus-mechanisms/pos/#fork-choice)). O bloco é adicionado ao banco de dados local em cada nó que o atestar. +1. Um usuário cria e assina uma [transação](/developers/docs/transactions/) com sua chave privada. Isso geralmente é tratado por uma carteira ou uma biblioteca como [ethers.js](https://docs.ethers.org/v6/), [web3js](https://docs.web3js.org/), [web3py](https://web3py.readthedocs.io/en/v5/), etc., mas, por baixo dos panos, o usuário está fazendo uma solicitação a um nó usando a [API JSON-RPC](/developers/docs/apis/json-rpc/) do Ethereum. O usuário define a quantidade de gás que está disposto a pagar como gorjeta a um validador para incentivá-lo a incluir a transação em um bloco.As [gorjetas](/developers/docs/gas/#priority-fee) são pagas ao validador, enquanto a [taxa base](/developers/docs/gas/#base-fee) é queimada. +2. A transação é enviada para um [cliente de execução](/developers/docs/nodes-and-clients/#execution-client) do Ethereum, que verifica sua validade. Isto significa garantir que o remetente tem ETH suficiente para realizar a transação e eles o assinaram com a chave correta. +3. Se a transação for válida, o cliente de execução adiciona-o à sua mempool local (lista de transações pendentes) e também a transmite para outros nós por meio da rede gossip da camada de execução. Quando outros nós ouvem sobre a transação, eles a adicionam à sua mempool local também. Usuários avançados podem abster-se de transmitir sua transação e, em vez disso, encaminhá-la a construtores de blocos especializados, como o [Flashbots Auction](https://docs.flashbots.net/flashbots-auction/overview). Isso permite que eles organizem as transações nos próximos blocos para obter o máximo lucro ([MEV](/developers/docs/mev/#mev-extraction)). +4. Um dos nós validadores na rede é o proponente de bloco para o slot atual, tendo sido selecionado pseudo-aleatoriamente usando RANDAO. Este nó é responsável pela construção e transmissão do próximo bloco a ser adicionado à blockchain Ethereum e pela atualização do estado global. O nó é composto por três partes: um cliente de execução, um cliente de consenso e um cliente validador. O cliente de execução empacota transações da mempool local em um "payload de execução" e executa-os localmente para gerar uma mudança de estado. Essas informações são passadas para o cliente de consenso em que a carga da execução é agrupada como parte de um "bloco de sinalização" que também contém informações sobre as recopensas, penalidades, cortes, atestações etc. que permitem que a rede entre em acordo sobre a sequência de blocks no topo da cadeia. A comunicação entre os clientes de execução e de consenso é descrita com mais detalhes em [Conectando os clientes de consenso e de execução](/developers/docs/networking-layer/#connecting-clients). +5. Outros nós recebem o novo bloco beacon na rede gossip na camada de consenso. Eles o passam para seu cliente de execução onde as transações são novamente executadas localmente para garantir que a proposta alteração de estado é válida. O cliente validador então atesta que o bloco é válido e é o próximo bloco lógico em sua visão da cadeia (o que significa que ele se baseia na cadeia com o maior peso de atestações, conforme definido nas [regras de escolha de bifurcação](/developers/docs/consensus-mechanisms/pos/#fork-choice)). O bloco é adicionado ao banco de dados local em cada nó que o atestar. 6. A transação pode ser considerada "finalizada", se fizer parte de uma cadeia com um "vínculo majoritário" entre dois pontos de verificação. Os pontos de verificação ocorrem no início de cada época e existem para explicar o fato de que apenas um subconjunto de validadores ativos atestam em cada espaço, mas todos os validadores ativos atestam em cada época. Portanto, é apenas entre as épocas que um 'vínculo de supermaioria' pode ser demonstrado (isto é onde 66% do total de ETH envolvido na rede concorda em dois pontos de verificação). Mais detalhes sobre finalidade podem ser encontrados abaixo. -## Finalidade {#finality} +## Finality {#finality} -Uma transação tem "finalidade" em redes distribuídas quando faz parte de um bloco que não pode mudar, sem que uma grande quantidade de ETH seja queimada. Na prova de participação da Ethereum, isto é gerenciado usando blocos de pontos de verificação. O primeiro bloco em cada época é um ponto de verificação. Os validadores votam nos pares de pontos de verificação que eles consideram válidos. Se um par de pontos de verificação atrair votos que representem pelo menos dois terços do total de ETH envolvido, os checkpoints serão atualizados. O mais recente dos dois (alvo) torna-se "justificado". O primeiro dos dois já é justificado porque era o "alvo" na época anterior. Agora ele é atualizado para "finalizado". +Uma transação tem "finalidade" em redes distribuídas quando faz parte de um bloco que não pode mudar, sem que uma grande quantidade de ETH seja queimada. Na prova de participação da Ethereum, isto é gerenciado usando blocos de pontos de verificação. O primeiro bloco em cada época é um ponto de verificação. Os validadores votam nos pares de pontos de verificação que eles consideram válidos. Se um par de pontos de verificação atrair votos que representem pelo menos dois terços do total de ETH envolvido, os checkpoints serão atualizados. O mais recente dos dois (alvo) torna-se "justificado". O primeiro dos dois já é justificado porque era o "alvo" na época anterior. Agora ele é atualizado para "finalizado". Este processo de atualização dos pontos de verificação é tratado pelo **[Casper the Friendly Finality Gadget (Casper-FFG)](https://arxiv.org/pdf/1710.09437)**. O Casper-FFG é uma ferramenta de finalidade de bloco para consenso. Uma vez que um bloco é finalizado, ele não pode ser revertido ou alterado sem uma remoção da maioria dos stakers, tornando-o economicamente inviável. -Para reverter um bloco finalizado, um invasor se comprometeria a perder pelo menos um terço do fornecimento total de ETH envolvido. A razão exata para isso é explicada nesta [postagem do blog da Ethereum Foundation](https://blog.ethereum.org/2016/05/09/on-settlement-finality). Uma vez que a finalidade exige a maioria de dois terços, um invasor poderia impedir que a rede chegue à finalidade votando com um terço da participação total. Existe um mecanismo de defesa contra isso: o [vazamento de inatividade](https://eth2book.info/bellatrix/part2/incentives/inactivity). Isso é ativado sempre que a cadeia falha em finalizar por mais de quatro épocas. O vazamento de inatividade afasta o ETH envolvido dos validadores que votam contra a maioria, permitindo que a maioria recupere uma maioria de dois terços e finalize a cadeia. +Para reverter um bloco finalizado, um invasor se comprometeria a perder pelo menos um terço do fornecimento total de ETH envolvido. A razão exata para isso é explicada nesta [postagem do blog da Ethereum Foundation](https://blog.ethereum.org/2016/05/09/on-settlement-finality/). Uma vez que a finalidade exige a maioria de dois terços, um invasor poderia impedir que a rede chegue à finalidade votando com um terço da participação total. Há um mecanismo para se defender contra isso: o [vazamento por inatividade](https://eth2book.info/bellatrix/part2/incentives/inactivity). Isso é ativado sempre que a cadeia falha em finalizar por mais de quatro épocas. O vazamento de inatividade afasta o ETH envolvido dos validadores que votam contra a maioria, permitindo que a maioria recupere uma maioria de dois terços e finalize a cadeia. ## Segurança criptoeconômica {#crypto-economic-security} A execução de um validador é um compromisso. Espera-se que o validador mantenha hardware e conectividade suficientes para participar da validação e proposta de bloco. Em troca, o validador é pago em ETH (seu saldo colocado aumenta). Por outro lado, participar como validador também abre novos caminhos para os usuários atacarem a rede para ganho pessoal ou sabotagem. Para evitar isso, os validadores perdem as recompensas de ETH se não participarem quando chamados, e sua participação existente pode ser destruída ao se comportarem de forma desonesta. Dois comportamentos principais podem ser considerados desonestos: propor múltiplos blocos em um único espaço (equívoco) e apresentar atestações contraditórias. -A quantidade de ETH reduzida depende de quantos validadores também estão sendo removidos ao mesmo tempo. Isso é conhecido como ["penalidade de correlação"](https://eth2book.info/bellatrix/part2/incentives/slashing#the-correlation-penalty) e pode ser menor (em torno de ~1% de participação para um único validador reduzido por si só) ou pode resultar na destruição de 100% da participação do validador (evento de remoção em massa). É imposto no meio de um período de saída forçada que começa com uma penalidade imediata (até 1 ETH) no dia 1, a penalidade de correlação no dia 18 e, finalmente, a ejeção da rede no dia 36. Os validadores recebem todos os dias pequenas penalidades de atestações porque estão presentes na rede, mas não enviam votos. Tudo isso significa que um ataque coordenado seria muito caro para o invasor. +A quantidade de ETH reduzida depende de quantos validadores também estão sendo removidos ao mesmo tempo. Isso é conhecido como a ["penalidade de correlação"](https://eth2book.info/bellatrix/part2/incentives/slashing#the-correlation-penalty), e pode ser pequena (\~1% de participação para um único validador removido por conta própria) ou pode resultar na destruição de 100% da participação do validador (evento de remoção em massa). É imposto no meio de um período de saída forçada que começa com uma penalidade imediata (até 1 ETH) no dia 1, a penalidade de correlação no dia 18 e, finalmente, a ejeção da rede no dia 36. Os validadores recebem todos os dias pequenas penalidades de atestações porque estão presentes na rede, mas não enviam votos. Tudo isso significa que um ataque coordenado seria muito caro para o invasor. -## Escolha da bifurcação {#fork-choice} +## Escolha de bifurcação {#fork-choice} -Quando a rede funciona de maneira otimizada e honesta, há apenas um novo bloco no início da cadeia, e todos os validadores o atestam. No entanto, é possível que os validadores tenham visões diferentes do cabeçalho da cadeia devido à latência de rede ou porque um proponente de bloco se equivocou. Portanto, os clientes de consenso exigem um algoritmo para decidir qual deles favorecer. O algoritmo usado na prova de participação do Ethereum se chama [LMD-GHOST](https://arxiv.org/pdf/2003.03052.pdf) e funciona identificando a bifurcação que tem o maior peso de atestações em seu histórico. +Quando a rede funciona de maneira otimizada e honesta, há apenas um novo bloco no início da cadeia, e todos os validadores o atestam. No entanto, é possível que os validadores tenham visões diferentes do cabeçalho da cadeia devido à latência de rede ou porque um proponente de bloco se equivocou. Portanto, os clientes de consenso exigem um algoritmo para decidir qual deles favorecer. O algoritmo usado na prova de participação do Ethereum é chamado [LMD-GHOST](https://arxiv.org/pdf/2003.03052.pdf), e funciona identificando a bifurcação que tem o maior peso de atestações em sua história. ## Prova de participação e segurança {#pos-and-security} -A ameaça de um [ataque de 51%](https://www.investopedia.com/terms/1/51-attack.asp) ainda existe na prova de participação, como na prova de trabalho, mas ainda é mais arriscada para os invasores. Um invasor precisaria de 51% do ETH colocado em participação. Eles poderiam então usar suas próprias atestações para garantir que sua bifurcação preferida fosse aquela com o maior número de atestações acumuladas. O “peso” das atestações acumuladas é o que os clientes de consenso usam para determinar a cadeia correta, de modo que esse invasor conseguiria tornar sua bifurcação a opção padrão. No entanto, um ponto forte da prova de participação sobre a prova de trabalho é que a comunidade tem flexibilidade para montar um contra-ataque. Por exemplo, os validadores honestos podem decidir continuar construindo a cadeia minoritária e ignorar a bifurcação do invasor enquanto encorajam aplicativos, agências de câmbio e pools a fazerem o mesmo. Eles também podem decidir remover forçadamente o invasor da rede e destruir o ETH colocado em participação. Estas são defesas econômicas fortes contra um ataque de 51%. +A ameaça de um [ataque de 51%](https://www.investopedia.com/terms/1/51-attack.asp) ainda existe na prova de participação, assim como na prova de trabalho, mas é ainda mais arriscado para os atacantes. Um invasor precisaria de 51% do ETH colocado em participação. Eles poderiam então usar suas próprias atestações para garantir que sua bifurcação preferida fosse aquela com o maior número de atestações acumuladas. O “peso” das atestações acumuladas é o que os clientes de consenso usam para determinar a cadeia correta, de modo que esse invasor conseguiria tornar sua bifurcação a opção padrão. No entanto, um ponto forte da prova de participação sobre a prova de trabalho é que a comunidade tem flexibilidade para montar um contra-ataque. Por exemplo, os validadores honestos podem decidir continuar construindo a cadeia minoritária e ignorar a bifurcação do invasor enquanto encorajam aplicativos, agências de câmbio e pools a fazerem o mesmo. Eles também podem decidir remover forçadamente o invasor da rede e destruir o ETH colocado em participação. Estas são defesas econômicas fortes contra um ataque de 51%. Além dos ataques de 51%, agentes maliciosos também podem tentar outros tipos de atividades prejudiciais, como: @@ -64,12 +64,12 @@ No geral, a prova de participação, conforme implementada no Ethereum, demonstr ## Prós e contras {#pros-and-cons} -| Prós | Contras | -| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -| O staking facilita a participação dos indivíduos na segurança da rede, promovendo a descentralização. o nó validador pode ser executado em um laptop normal. Os pools de participação permitem que os usuários participem sem ter 32 ETH. | A prova de participação é mais recente e menos testada na prática em comparação com a prova de trabalho | -| A participação é mais descentralizada, As economias de escala não se aplicam da mesma forma que para a mineração de PoW. | A prova de participação é mais complexa de implementar do que a prova de trabalho | -| A prova de participação oferece maior segurança criptoeconômica do que a prova de trabalho | Os usuários precisam executar três softwares para participar da prova de participação do Ethereum. | -| É necessário emitir uma quantidade menor de novos ETH para incentivar os participantes da rede | | +| Prós | Contras | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | +| O staking facilita a participação dos indivíduos na segurança da rede, promovendo a descentralização. o nó validador pode ser executado em um laptop normal. Os pools de participação permitem que os usuários participem sem ter 32 ETH. | A prova de participação é mais recente e menos testada na prática em comparação com a prova de trabalho | +| A participação é mais descentralizada, As economias de escala não se aplicam da mesma forma que para a mineração de PoW. | A prova de participação é mais complexa de implementar do que a prova de trabalho | +| A prova de participação oferece maior segurança criptoeconômica do que a prova de trabalho | Os usuários precisam executar três softwares para participar da prova de participação do Ethereum. | +| É necessário emitir uma quantidade menor de novos ETH para incentivar os participantes da rede | | ### Comparação com a prova de trabalho {#comparison-to-proof-of-work} @@ -84,14 +84,14 @@ O Ethereum originalmente usava prova de trabalho, mas mudou para prova de partic ## Leitura adicional {#further-reading} -- [Perguntas frequentes sobre prova de participação](https://vitalik.eth.limo/general/2017/12/31/pos_faq.html) _Vitalik Buterin_ -- [O que é prova de participação](https://consensys.net/blog/blockchain-explained/what-is-proof-of-stake/) _ConsenSys_ -- [O que prova de participação é por que é importante](https://bitcoinmagazine.com/culture/what-proof-of-stake-is-and-why-it-matters-1377531463) _Vitalik Buterin_ -- [Por que a prova de participação (nov. de 2020)](https://vitalik.eth.limo/general/2020/11/06/pos2020.html) _Vitalik Buterin_ -- [Prova da participação: como aprendi a amar a pouca subjetividade](https://blog.ethereum.org/2014/11/25/proof-stake-learned-love-weak-subjectivity) _Vitalik Buterin_ -- [Ataque e defesa da prova de participação do Ethereum](https://mirror.xyz/jmcook.eth/YqHargbVWVNRQqQpVpzrqEQ8IqwNUJDIpwRP7SS5FXs) -- [A filosofia por trás do design da prova de participação](https://medium.com/@VitalikButerin/a-proof-of-stake-design-philosophy-506585978d51) _Vitalik Buterin_ -- [Vídeo: Vitalik buterin explica a prova de participação para Lex Fridman](https://www.youtube.com/watch?v=3yrqBG-7EVE) +- [FAQ sobre Prova de Participação](https://vitalik.eth.limo/general/2017/12/31/pos_faq.html) _Vitalik Buterin_ +- [O que é Prova de Participação](https://consensys.net/blog/blockchain-explained/what-is-proof-of-stake/) _ConsenSys_ +- [O que é a Prova de Participação e por que ela é importante](https://bitcoinmagazine.com/culture/what-proof-of-stake-is-and-why-it-matters-1377531463) _Vitalik Buterin_ +- [Por que Prova de Participação (Nov 2020)](https://vitalik.eth.limo/general/2020/11/06/pos2020.html) _Vitalik Buterin_ +- [Prova de Participação: Como Aprendi a Amar a Subjetividade Fraca](https://blog.ethereum.org/2014/11/25/proof-stake-learned-love-weak-subjectivity/) _Vitalik Buterin_ +- [Ataque e defesa na prova de participação do Ethereum](https://mirror.xyz/jmcook.eth/YqHargbVWVNRQqQpVpzrqEQ8IqwNUJDIpwRP7SS5FXs) +- [Uma Filosofia de Design da Prova de Participação](https://medium.com/@VitalikButerin/a-proof-of-stake-design-philosophy-506585978d51) _Vitalik Buterin_ +- [Vídeo: Vitalik Buterin explica a prova de participação para Lex Fridman](https://www.youtube.com/watch?v=3yrqBG-7EVE) ## Tópicos relacionados {#related-topics} diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/keys/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/keys/index.md index 273fde5b8b7..24b780bf934 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/keys/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/keys/index.md @@ -1,31 +1,31 @@ --- -title: Chaves na prova de participação do Ethereum -description: Uma explicação das chaves usadas no mecanismo de consenso da prova de participação do Ethereum +title: "Chaves na prova de participação do Ethereum" +description: "Uma explicação das chaves usadas no mecanismo de consenso da prova de participação do Ethereum" lang: pt-br --- O Ethereum protege os ativos do usuário usando a criptografia de chave pública-privada. A chave pública é usada como base para um endereço Ethereum — ou seja, é visível para o público em geral e utilizada como um identificador único. A chave privada (ou “secret”) deve sempre ser acessível apenas ao proprietário da conta. A chave privada é usada para “assinar” as transações e os dados para que a criptografia possa provar que o proprietário aprova alguma ação de uma chave privada específica. -As chaves do Ethereum são geradas usando a [criptografia de curva elíptica](https://en.wikipedia.org/wiki/Elliptic-curve_cryptography). +As chaves do Ethereum são geradas usando [criptografia de curva elíptica](https://en.wikipedia.org/wiki/Elliptic-curve_cryptography). No entanto, quando o Ethereum mudou de [prova de trabalho](/developers/docs/consensus-mechanisms/pow) para [prova de participação](/developers/docs/consensus-mechanisms/pos), um novo tipo de chave foi adicionado ao Ethereum. As chaves originais ainda funcionam exatamente como antes — não houve alterações nas chaves baseadas em curva elíptica que protegem as contas. No entanto, os usuários precisavam de um novo tipo de chave para participar da prova de participação colocando ETH em stake e executando validadores. Essa necessidade surgiu dos desafios de escalabilidade associados a muitas mensagens trocadas entre inúmeros validadores que exigiam um método criptográfico que pudesse ser agregado facilmente para reduzir a quantidade de comunicação necessária para a rede chegar a consenso. Este novo tipo de chave usa o esquema de assinatura [**Boneh-Lynn-Shacham (BLS)**](https://wikipedia.org/wiki/BLS_digital_signature). O BLS permite uma agregação de assinaturas muito eficiente, mas também permite a engenharia reversa de chaves agregadas de validadores individuais e é ideal para gerenciar ações entre validadores. -## Os dois tipos de chaves de validação {#two-types-of-keys} +## Os dois tipos de chaves de validador {#two-types-of-keys} -Antes da mudança para prova de participação, os usuários do Ethereum tinham uma única chave privada baseada em curva elíptica para acessar seus fundos. Com a introdução da prova de participação, os usuários que quisessem ser participantes individuais também precisavam de uma **chave de validação** e uma **chave de saque**. +Antes da mudança para prova de participação, os usuários do Ethereum tinham uma única chave privada baseada em curva elíptica para acessar seus fundos. Com a introdução da prova de participação, os usuários que desejavam ser stakers solo também precisavam de uma **chave de validador** e uma **chave de saque**. -### A chave de validação {#validator-key} +### A chave do validador {#validator-key} A chave de assinatura de validação consiste em dois elementos: -- Chave de validação **privada** -- Chave de validação **pública** +- Chave **privada** do validador +- Chave **pública** do validador O objetivo da chave de validação privada é assinar operações em cadeia, como propostas de bloco e atestações. Por causa disso, essas chaves devem estar guardadas numa carteira quente. -Essa flexibilidade tem a vantagem de mover rapidamente as chaves de assinatura do validador de um dispositivo para outro, no entanto, se elas se perderem ou forem roubadas, um ladrão poderá **agir maliciosamente** de algumas maneiras: +Essa flexibilidade tem a vantagem de mover as chaves de assinatura do validador muito rapidamente de um dispositivo para outro, no entanto, se elas forem perdidas ou roubadas, um ladrão pode **agir maliciosamente** de algumas maneiras: - Remover o validador por: - Ser um proponente e assinar dois blocos diferentes da beacon para o mesmo slot @@ -33,36 +33,36 @@ Essa flexibilidade tem a vantagem de mover rapidamente as chaves de assinatura d - Ser um atestador e assinar duas atestações diferentes com o mesmo destino - Forçar uma saída voluntária, que interrompe o validador de fazer stake, e conceder acesso ao seu saldo de ETH para o proprietário da chave de saque -A **chave pública do validador** é incluída nos dados de transação quando um usuário deposita ETH no contrato de depósito de stake. Isso é conhecido como _dados de depósito_ e permite que o Ethereum identifique o validador. +A **chave pública do validador** é incluída nos dados da transação quando um usuário deposita ETH no contrato de depósito de staking. Isso é conhecido como _dados de depósito_ e permite que o Ethereum identifique o validador. ### Credenciais de saque {#withdrawal-credentials} -Todo validador tem uma propriedade conhecida como _credenciais de saque_. Esse campo de 32 bytes começa com um `0x00`, representando credenciais de saque do BLS, ou um `0x01`, representando credenciais que apontam para um endereço de execução. +Todo validador tem uma propriedade conhecida como _credenciais de saque_. Este campo de 32 bytes começa com `0x00`, representando as credenciais de saque BLS, ou `0x01`, representando as credenciais que apontam para um endereço de execução. -Os validadores com chaves BLS `0x00` devem atualizar estas credenciais para apontar para um endereço de execução e ativar pagamentos de saldo em excesso ou saque total de participação (stake). Isso pode ser feito fornecendo um endereço de execução nos dados de depósito durante a geração inicial da chave, _OU_ usando a chave de saque posteriormente para assinar e transmitir uma mensagem `BLSToExecutionChange`. +Os validadores com chaves `0x00` BLS devem atualizar essas credenciais para apontar para um endereço de execução, a fim de ativar pagamentos de saldo excedente ou saque total do staking. Isso pode ser feito fornecendo um endereço de execução nos dados de depósito durante a geração inicial da chave, _OU_ usando a chave de saque posteriormente para assinar e transmitir uma mensagem `BLSToExecutionChange`. -### Chave de saque {#withdrawal-key} +### A chave de saque {#withdrawal-key} A chave de saque será necessária para atualizar as credenciais de saque para apontar para um endereço de execução, se não for definido durante o depósito inicial. Isso permitirá que os pagamentos do saldo em excesso comecem a ser processados e também permitirá que os usuários saquem totalmente seus ETH em participação (stake). Assim como as chaves de validador, as chaves de saque também consistem em dois componentes: -- Chave de saque **privada** -- Chave de saque **pública** +- Chave **privada** de saque +- Chave **pública** de saque -Perder esta chave antes de atualizar as credenciais de saque para o tipo `0x01` significa perder o acesso ao saldo do validador. O validador pode ainda assinar atestações e bloqueios, pois essas ações exigem a chave privada do validador, no entanto, há pouco ou nenhum incentivo se as chaves de saque forem perdidas. +Perder essa chave antes de atualizar as credenciais de saque para o tipo `0x01` significa perder o acesso ao saldo do validador. O validador pode ainda assinar atestações e bloqueios, pois essas ações exigem a chave privada do validador, no entanto, há pouco ou nenhum incentivo se as chaves de saque forem perdidas. Separar as chaves de validação das chaves da conta Ethereum permite que vários validadores sejam executados por um único usuário. -![esquema da chave de validação](validator-key-schematic.png) +![esquema de chave de validador](validator-key-schematic.png) -**Nota**: Sair das funções de staking e sacar o saldo de um validador atualmente requer a assinatura de uma [mensagem de saída voluntária (VEM)](https://mirror.xyz/ladislaus.eth/wmoBbUBes2Wp1_6DvP6slPabkyujSU7MZOFOC3QpErs&1) com a chave do validador. No entanto, o [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002) é uma proposta que permitirá que um usuário acione a saída de um validador e saque seu saldo assinando mensagens de saída com a chave de saque no futuro. Isso reduzirá as suposições de confiança ao permitir que os participantes que delegam ETH a [provedores de staking como serviço](/staking/saas/#what-is-staking-as-a-service) mantenham o controle de seus fundos. +**Observação**: Sair das tarefas de staking e sacar o saldo de um validador atualmente exige a assinatura de uma [mensagem de saída voluntária (VEM)](https://mirror.xyz/ladislaus.eth/wmoBbUBes2Wp1_6DvP6slPabkyujSU7MZOFOC3QpErs&1) com a chave do validador. No entanto, o [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002) é uma proposta que permitirá a um usuário acionar a saída de um validador e sacar seu saldo, assinando mensagens de saída com a chave de saque no futuro. Isso reduzirá as premissas de confiança, permitindo que stakers que delegam ETH a [provedores de staking como serviço](/staking/saas/#what-is-staking-as-a-service) permaneçam no controle de seus fundos. -## Obtendo chaves de uma frase semente {#deriving-keys-from-seed} +## Derivando chaves de uma frase semente {#deriving-keys-from-seed} Se cada 32 ETH em stake precisavam de um novo conjunto de 2 chaves completamente independentes, o gerenciamento de chaves se tornaria rapidamente complicado, especialmente para usuários que executam vários validadores. Em vez disso, várias chaves de validação podem ser obtidas de um único segredo comum e armazenar esse segredo único permite acesso a várias chaves de validação. -[Mnemônicos](https://en.bitcoinwiki.org/wiki/Mnemonic_phrase) e caminhos são recursos importantes que os usuários geralmente encontram ao [acessar](https://ethereum.stackexchange.com/questions/19055/what-is-the-difference-between-m-44-60-0-0-and-m-44-60-0) suas carteiras. Mnemônico é uma sequência de palavras que atuam como uma semente inicial para uma chave privada. Quando combinado com dados adicionais, o mnemônico gera um hash conhecido como “chave mestra”. Isso pode ser considerado como a raiz de uma árvore. Os galhos dessa raiz podem ser obtidos usando um caminho hierárquico de forma que os nós filhos possam existir como combinações de hash do nó pai e de seus índices na árvore. Leia sobre as normas [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) e [ BIP-19](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) para geração de chaves baseadas em mnemônicos. +[Mnemônicos](https://en.bitcoinwiki.org/wiki/Mnemonic_phrase) e caminhos são recursos proeminentes que os usuários costumam encontrar quando [acessam](https://ethereum.stackexchange.com/questions/19055/what-is-the-difference-between-m-44-60-0-0-and-m-44-60-0) suas carteiras. Mnemônico é uma sequência de palavras que atuam como uma semente inicial para uma chave privada. Quando combinado com dados adicionais, o mnemônico gera um hash conhecido como “chave mestra”. Isso pode ser considerado como a raiz de uma árvore. Os galhos dessa raiz podem ser obtidos usando um caminho hierárquico de forma que os nós filhos possam existir como combinações de hash do nó pai e de seus índices na árvore. Leia sobre os padrões [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) e [BIP-19](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) para geração de chaves baseada em mnemônicos. Esses caminhos possuem a seguinte estrutura, que será familiar para usuários que já interagiram com carteiras de hardware: @@ -76,7 +76,7 @@ As barras nesse caminho separam os componentes da chave privada da seguinte form master_key / purpose / coin_type / account / change / address_index ``` -Essa lógica permite aos usuários anexar o maior número possível de validadores a uma única **frase mnemônica**, pois a raiz da árvore pode ser comum e a diferenciação pode ocorrer nas ramificações. O usuário pode **obter qualquer número de chaves** da frase mnemônica. +Essa lógica permite que os usuários anexem o maior número possível de validadores a uma única **frase mnemônica**, pois a raiz da árvore pode ser comum e a diferenciação pode ocorrer nos ramos. O usuário pode **derivar qualquer número de chaves** da frase mnemônica. ``` [m / 0] @@ -88,13 +88,13 @@ Essa lógica permite aos usuários anexar o maior número possível de validador [m / 2] ``` -Cada galho é separado por uma `/`, então `m/2` significa iniciar com a chave mestra e seguir a ramificação 2. No esquema abaixo, uma única frase mnemônica é usada para armazenar três chaves de saque, cada uma com dois validadores associados. +Cada ramo é separado por `/`, então `m/2` significa começar com a chave mestra e seguir o ramo 2. No esquema abaixo, uma única frase mnemônica é usada para armazenar três chaves de saque, cada uma com dois validadores associados. -![lógica da chave de validação](multiple-keys.png) +![lógica da chave do validador](multiple-keys.png) ## Leitura adicional {#further-reading} -- [Postagem no blog da Ethereum Foundation por Carl Beekhuizen](https://blog.ethereum.org/2020/05/21/keys) -- [Geração de chave EIP-2333 BLS12-381](https://eips.ethereum.org/EIPS/eip-2333) -- [EIP-7002: Saídas acionadas pela camada de execução](https://web.archive.org/web/20250125035123/https://research.2077.xyz/eip-7002-unpacking-improvements-to-staking-ux-post-merge) +- [Postagem no blog da Ethereum Foundation por Carl Beekhuizen](https://blog.ethereum.org/2020/05/21/keys/) +- [EIP-2333 Geração de chave BLS12-381](https://eips.ethereum.org/EIPS/eip-2333) +- [EIP-7002: Saídas acionadas pela Camada de Execução](https://web.archive.org/web/20250125035123/https://research.2077.xyz/eip-7002-unpacking-improvements-to-staking-ux-post-merge) - [Gerenciamento de chaves em escala](https://docs.ethstaker.cc/ethstaker-knowledge-base/scaled-node-operators/key-management-at-scale) diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/pos-vs-pow/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/pos-vs-pow/index.md index 5f774fa10ab..1f6edbf34e2 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/pos-vs-pow/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/pos-vs-pow/index.md @@ -1,6 +1,6 @@ --- -title: Prova de participação versus Prova de trabalho -description: Uma comparação entre o mecanismo de consenso baseado em prova de participação e prova de trabalho do Ethereum +title: "Prova de participação versus Prova de trabalho" +description: "Uma comparação entre o mecanismo de consenso baseado em prova de participação e prova de trabalho do Ethereum" lang: pt-br --- @@ -12,7 +12,7 @@ Esta página explica a lógica por trás da mudança do Ethereum para prova de p Os pesquisadores da Ethereum consideram a prova de participação mais segura do que a prova de trabalho. No entanto, ele só foi implementado recentemente para a rede principal real do Ethereum e é menos comprovado pelo tempo do que a prova de trabalho. As seções a seguir discutem os prós e os contras do modelo de segurança da prova de participação, em comparação com a prova de trabalho. -### Custo de ataque {#cost-to-attack} +### Custo para atacar {#cost-to-attack} Na prova de participação, os validadores são obrigados a depositar ("participação") pelo menos 32 ETH em um contrato inteligente. O Ethereum pode destruir o ether em participação para punir os validadores que se comportam mal. Para chegar a um consenso, pelo menos 66% do total de ether em participação deve votar a favor de um determinado conjunto de blocos. Os blocos votados por >=66% da participação tornam-se "finalizados", o que significa que não podem ser removidos ou reorganizados. @@ -20,11 +20,11 @@ Atacar a rede pode significar impedir a cadeia de finalizar ou garantir uma cert O menor custo de ataque é >33% da participação total. Um atacante com >33% da participação total pode causar um atraso de finalização simplesmente ficando offline. Este é um problema relativamente menor para a rede, pois existe um mecanismo conhecido como "vazamento de inatividade" que vaza a participação dos validadores offline até que a maioria online represente 66% de participação e possa finalizar a cadeia novamente. Também é teoricamente possível para um atacante causar dupla finalidade com um pouco mais de 33% da participação total, criando dois blocos em vez de um quando ele for solicitado para ser um produtor de bloco e, em seguida, votar duas vezes com todos os seus validadores. Cada fork (bifurcação) requer apenas 50% dos validadores honestos restantes para ver cada bloco primeiro, portanto, se eles conseguirem gerenciar o tempo de suas mensagens da maneira certa, eles poderão finalizar ambos os forks. Isso tem uma baixa probabilidade de sucesso, mas se um atacante for capaz de causar dupla finalidade, a comunidade Ethereum teria que decidir seguir um fork, nesse caso, os validadores do atacante seriam necessariamente cortados no outro fork. -Com >33% da participação total, um atacante tem a chance de ter um efeito menor (atraso de finalização) ou mais grave (finalidade dupla) na rede Ethereum. Com mais de 14.000.000 ETH em participação na rede e um preço representativo de US$ 1.000/ETH, o custo mínimo para montar esses ataques é `1.000 x 14.000.000 x 0,33 = US$ 4.620.000.000`. O atacante perderia esse dinheiro cortando e seria expulso da rede. Para atacar novamente, eles teriam que acumular >33% da participação (novamente) e queimá-la (novamente). Cada tentativa de ataque à rede custaria >$ 4,6 bilhões (US$ 1.000/ETH e 14 milhões de ETH em participação). O atacante também é ejetado da rede quando ele é cortado, e precisa entrar em uma fila de ativação para entrar novamente. Isso significa que a taxa de um ataque repetido é limitado não apenas à taxa que o atacante pode acumular >33% da participação total, mas também ao tempo que leva para incluir todos os seus validadores à rede. Cada vez que o atacante ataca, eles ficam muito mais pobres e o resto da comunidade fica mais rico, graças ao choque da oferta resultante. +Com >33% da participação total, um atacante tem a chance de ter um efeito menor (atraso de finalização) ou mais grave (finalização dupla) na rede Ethereum. Com mais de 14.000.000 de ETH em participação na rede e um preço representativo de $1000/ETH, o custo mínimo para montar esses ataques é de `1000 x 14,000,000 x 0.33 = $4,620,000,000`. O atacante perderia esse dinheiro cortando e seria expulso da rede. Para atacar novamente, eles teriam que acumular >33% da participação (novamente) e queimá-la (novamente). Cada tentativa de ataque à rede custaria >$4,6 bilhões (a $1000/ETH e 14 milhões de ETH em participação). O atacante também é ejetado da rede quando ele é cortado, e precisa entrar em uma fila de ativação para entrar novamente. Isso significa que a taxa de um ataque repetido é limitada não apenas pela taxa com que o atacante pode acumular >33% da participação total, mas também pelo tempo que leva para integrar todos os seus validadores na rede. Cada vez que o atacante ataca, eles ficam muito mais pobres e o resto da comunidade fica mais rico, graças ao choque da oferta resultante. Outros ataques, como ataques de 51% ou reversão de finalidade com 66% da participação total, exigem substancialmente mais ETH e são muito mais caros para o atacante. -Compare isso com a prova de trabalho. O custo de lançar um ataque à prova de trabalho Ethereum era o custo de possuir consistentemente >50% da taxa total de hash da rede. Isso somado aos custos de hardware e funcionamento do poder de computação suficiente, para superar outros mineradores a computar soluções de prova de trabalho de forma consistente. O Ethereum foi minerado principalmente usando GPUs em vez de ASICs, o que manteve o custo baixo (embora o Ethereum tivesse continuado na prova de trabalho, a mineração ASIC poderia ter se tornado mais popular). Um adversário teria que adquirir muito hardware e pagar pela eletricidade para executá-lo para atacar uma rede Ethereum de prova de trabalho, mas o custo total seria menor que o custo necessário para acumular ETH suficiente para lançar um ataque. Um ataque de 51% é ~[20 vezes mais barato](https://youtu.be/1m12zgJ42dI?t=1562) na prova de trabalho do que na prova de participação. Se o ataque for detectado e a cadeia realizasse o fork para remover suas alterações, o atacante poderia usar repetidamente o mesmo hardware para atacar o novo fork. +Compare isso com a prova de trabalho. O custo de lançar um ataque no Ethereum com prova de trabalho era o custo de possuir consistentemente >50% da taxa de hash total da rede. Isso somado aos custos de hardware e funcionamento do poder de computação suficiente, para superar outros mineradores a computar soluções de prova de trabalho de forma consistente. O Ethereum foi minerado principalmente usando GPUs em vez de ASICs, o que manteve o custo baixo (embora o Ethereum tivesse continuado na prova de trabalho, a mineração ASIC poderia ter se tornado mais popular). Um adversário teria que adquirir muito hardware e pagar pela eletricidade para executá-lo para atacar uma rede Ethereum de prova de trabalho, mas o custo total seria menor que o custo necessário para acumular ETH suficiente para lançar um ataque. Um ataque de 51% é ~[20x mais barato](https://youtu.be/1m12zgJ42dI?t=1562) na prova de trabalho do que na prova de participação. Se o ataque for detectado e a cadeia realizasse o fork para remover suas alterações, o atacante poderia usar repetidamente o mesmo hardware para atacar o novo fork. ### Complexidade {#complexity} @@ -32,7 +32,7 @@ A prova de participação é muito mais complexa do que a prova de trabalho. Iss Para desenvolver e testar com segurança a lógica de consenso da prova de participação, a Beacon Chain foi lançada dois anos antes da prova de participação ser implementada na rede principal do Ethereum. A Beacon Chain atuou como um ambiente para testes da prova de participação, já que era uma blockchain ativa implementando a lógica de consenso da prova de participação, mas sem tocar em transações reais do Ethereum - apenas efetivamente chegando a um consenso sobre si mesmo. Uma vez que isso tem sido estável e livre de bugs por tempo suficiente, a Beacon Chain foi "fundida" com a rede principal do Ethereum. Tudo isso contribuiu para domar a complexidade da prova de participação a ponto que o risco de consequências não intencionais ou bugs de cliente serem muito baixos. -### Superfície de Ataque {#attack-surface} +### Superfície de ataque {#attack-surface} A prova de participação é mais complexa do que a prova de trabalho, o que significa que há mais vetores de ataque em potencial a tratar. Em vez de uma rede ponto-a-ponto conectando clientes, há duas, cada uma implementando um protocolo separado. Ter um validador específico pré-selecionado para propor um bloco em cada slot, cria o potencial de negação de serviço quando grandes quantidades de tráfego de rede colocam esse validador específico off-line. @@ -50,7 +50,7 @@ A melhor opção para o Ethereum é que os validadores sejam executados localmen A prova de participação é uma forma barata de proteger a blockchain. Na prova de trabalho, os mineradores competem pelo direito de minerar um bloco. Os mineradores são mais bem-sucedidos quando podem realizar cálculos mais rápidos, incentivando o investimento em hardware e o consumo de energia. Isso foi observado no Ethereum antes de mudar para a prova de participação. Pouco antes da transição para prova de participação, o Ethereum consumia aproximadamente 78 TWh/ano - tanto quanto um pequeno país. No entanto, a mudança para a prova de participação reduziu esse gasto de energia em ~99,98%. A prova de participação tornou o Ethereum uma plataforma de baixo carbono e eficiência energética. -[Saiba mais sobre o consumo energético do Ethereum](/energy-consumption) +[Mais sobre o consumo de energia da Ethereum](/energy-consumption) ## Emissão {#issuance} @@ -64,6 +64,6 @@ Assista Justin Drake explicando os benefícios da prova de participação em rel ## Leitura adicional {#further-reading} -- [Filosofia de design da prova de participação de Vitalik](https://medium.com/@VitalikButerin/a-proof-of-stake-design-philosophy-506585978d51) -- [Perguntas frequentes sobre a prova de participação de Vitalik](https://vitalik.eth.limo/general/2017/12/31/pos_faq.html#what-is-proof-of-stake) -- [Vídeo "Simplesmente Explicado" sobre pos vs pow](https://www.youtube.com/watch?v=M3EFi_POhps) +- [Filosofia de design de prova de participação de Vitalik](https://medium.com/@VitalikButerin/a-proof-of-stake-design-philosophy-506585978d51) +- [Perguntas frequentes sobre prova de participação de Vitalik](https://vitalik.eth.limo/general/2017/12/31/pos_faq.html#what-is-proof-of-stake) +- [Vídeo "Simply Explained" sobre pos vs pow](https://www.youtube.com/watch?v=M3EFi_POhps) diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/rewards-and-penalties/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/rewards-and-penalties/index.md index d0f64d36a63..a9200bb2c23 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/rewards-and-penalties/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/rewards-and-penalties/index.md @@ -1,10 +1,10 @@ --- -title: Recompensas e penalidades na prova de participação -description: Saiba mais sobre os incentivos no protocolo da prova de participação Ethereum. +title: "Recompensas e penalidades na prova de participação" +description: "Saiba mais sobre os incentivos no protocolo da prova de participação Ethereum." lang: pt-br --- -Ethereum é protegido usando sua criptomoeda nativa, ether (ETH). Os operadores de nós que desejam participar da validação de blocos e da identificação do cabeçalho da cadeia depositam ether no [contrato de depósito](/staking/deposit-contract/) do Ethereum. Eles são então pagos em ether para executar um software validador que verifica a validade de novos blocos recebidos pela rede ponto a ponto e aplicam o algoritmo de escolha de bifurcação para identificar o cabeçalho da cadeia. +Ethereum é protegido usando sua criptomoeda nativa, ether (ETH). Operadores de nós que desejam participar da validação de blocos e da identificação do cabeçalho da cadeia, depositam ether no [contrato de depósito](/staking/deposit-contract/) no Ethereum. Eles são então pagos em ether para executar um software validador que verifica a validade de novos blocos recebidos pela rede ponto a ponto e aplicam o algoritmo de escolha de bifurcação para identificar o cabeçalho da cadeia. Existem duas funções principais para um validador: 1) verificar novos blocos e “atestar” se eles são válidos para eles, 2) propor novos blocos quando selecionados aleatoriamente a partir do pool total de validadores. Se o validador falhar em realizar qualquer uma dessas tarefas quando solicitado, eles perdem um pagamento em ether. Às vezes, os validadores também são encarregados de agregar assinaturas e participar dos comitês de sincronização. @@ -18,51 +18,51 @@ Leia para obter mais detalhes... ### Recompensas {#rewards} -Os validadores recebem recompensas quando votam de modo consistente com a maioria dos outros validadores, quando propõem blocos e quando participam de comitês de sincronização. O valor das recompensas em cada época são calculadas a partir de um `base_reward`. Essa é a unidade base a partir da qual outras recompensas são calculadas. O `base_reward` representa a recompensa média recebida por um validador em condições ideais por época. Isso é calculado a partir do saldo efetivo do validador e do número total de validadores ativos da seguinte forma: +Os validadores recebem recompensas quando votam de modo consistente com a maioria dos outros validadores, quando propõem blocos e quando participam de comitês de sincronização. O valor das recompensas em cada época é calculado a partir de uma `base_reward`. Essa é a unidade base a partir da qual outras recompensas são calculadas. A `base_reward` representa a recompensa média recebida por um validador em condições ideais por época. Isso é calculado a partir do saldo efetivo do validador e do número total de validadores ativos da seguinte forma: ``` base_reward = effective_balance * (base_reward_factor / (base_rewards_per_epoch * sqrt(sum(active_balance)))) ``` -quando `base_reward_factor` é 64, `base_rewards_per_epoch` é 4 e `sum(active balance)` é o total de ether colocado por todos os validadores ativos. +onde `base_reward_factor` é 64, `base_rewards_per_epoch` é 4 e `sum(active balance)` é o total de ether em stake de todos os validadores ativos. -Isso significa que a recompensa base é proporcional ao saldo efetivo do validador e inversamente proporcional ao número de validadores na rede. Quanto mais validadores, maior a emissão geral (como `sqrt(N)`, mas menor a `base_reward` por validador (como `1/sqrt(N)`). Esses fatores influenciam o APR para um nó de staking. Leia a justificativa para isso nas [notas de Vitalik](https://notes.ethereum.org/@vbuterin/rkhCgQteN?type=view#Base-rewards). +Isso significa que a recompensa base é proporcional ao saldo efetivo do validador e inversamente proporcional ao número de validadores na rede. Quanto mais validadores, maior a emissão geral (como `sqrt(N)`), mas menor a `base_reward` por validador (como `1/sqrt(N)`). Esses fatores influenciam o APR para um nó de staking. Leia a justificativa para isso nas [anotações de Vitalik](https://notes.ethereum.org/@vbuterin/rkhCgQteN?type=view#Base-rewards). A recompensa total é então calculada como a soma de cinco componentes, sendo que cada um tem uma ponderação que determina quanto cada componente adiciona à recompensa total. Os componentes são: ``` -1. voto de origem: o validador fez um voto oportuno para o ponto de verificação de origem correta -2. voto de destino: o validador fez um voto oportuno para o ponto de verificação de destino correto -3. voto de cabeçalho: o validador fez um voto oportuno para o bloco de cabeçalho correto +1. voto de origem: o validador votou oportunamente no checkpoint de origem correto +2. voto de destino: o validador votou oportunamente no checkpoint de destino correto +3. voto de cabeçalho: o validador votou oportunamente no bloco de cabeçalho correto 4. recompensa do comitê de sincronização: o validador participou de um comitê de sincronização -5. recompensa do proponente: o validador propôs um bloco no slot correto +5. recompensa do propositor: o validador propôs um bloco no slot correto ``` As ponderações para cada componente são as seguintes: ``` -TIMELY_SOURCE_WEIGHT uint64(14) -TIMELY_TARGET_WEIGHT uint64(26) -TIMELY_HEAD_WEIGHT uint64(14) -SYNC_REWARD_WEIGHT uint64(2) -PROPOSER_WEIGHT uint64(8) +TIMELY_SOURCE_WEIGHT uint64(14) +TIMELY_TARGET_WEIGHT uint64(26) +TIMELY_HEAD_WEIGHT uint64(14) +SYNC_REWARD_WEIGHT uint64(2) +PROPOSER_WEIGHT uint64(8) ``` -Esses pesos somam 64. A recompensa é calculada como a soma dos pesos aplicáveis dividido por 64. Um validador que tenha feito votos oportunos de origem, destino e cabeçalho propôs um bloco e participou de um comitê de sincronização poderá receber `64/64 * base_reward == base_reward`. No entanto, um validador geralmente não é um proponente de bloco, então sua recompensa máxima é `64-8 /64 * base_reward == 7/8 * base_reward`. Os validadores que não são proponentes de bloco nem estão em um comitê de sincronização podem receber `64-8-2 / 64 * base_reward == 6,75/8 * base_reward`. +Esses pesos somam 64. A recompensa é calculada como a soma dos pesos aplicáveis dividido por 64. Um validador que tenha feito votos de origem, destino e cabeçalho oportunos, proposto um bloco e participado de um comitê de sincronização pode receber `64/64 * base_reward == base_reward`. No entanto, um validador geralmente não é um propositor de bloco, portanto, sua recompensa máxima é `64-8 /64 * base_reward == 7/8 * base_reward`. Validadores que não são propositores de bloco nem estão em um comitê de sincronização podem receber `64-8-2 / 64 * base_reward == 6.75/8 * base_reward`. -Uma recompensa adicional é incluída para incentivar atestações rápidas. Esse é o `inclusion_delay_reward`. Isso tem um valor igual a `base_reward` multiplicado por `1/delay`, no qual o `delay` é o número de slots que separam a proposta do bloco e o atestado. Por exemplo, se o atestado for enviado dentro de um slot da proposta do bloco, o atestante receberá `base_reward * 1/1 == base_reward`. Se o atestado chegar no próximo slot, o atestador receberá `base_reward * 1/2` e assim por diante. +Uma recompensa adicional é incluída para incentivar atestações rápidas. Esta é a `inclusion_delay_reward`. Isso tem um valor igual à `base_reward` multiplicada por `1/delay`, em que `delay` é o número de slots que separam a proposta de bloco e a atestação. Por exemplo, se a atestação for enviada dentro de um slot da proposta de bloco, o atestador recebe `base_reward * 1/1 == base_reward`. Se a atestação chegar no próximo slot, o atestador recebe `base_reward * 1/2` e assim por diante. -Os proponentes de bloco recebem `8 / 64 * base_reward` para **cada atestado válido** incluída no bloco, logo, o valor real da recompensa varia com o número de validadores atestantes. Os proponentes de bloco também podem aumentar sua recompensa incluindo evidências de mau comportamento de outros validadores em seu bloco proposto. Essas recompensas são as “cenouras” que encorajam a honestidade do validador. Um proponente de bloco que inclui uma punição será recompensado com o `slashed_validators_effective_balance / 512`. +Os propositores de bloco recebem `8 / 64 * base_reward` para **cada atestação válida** incluída no bloco, de modo que o valor real da recompensa escala com o número de validadores atestantes. Os proponentes de bloco também podem aumentar sua recompensa incluindo evidências de mau comportamento de outros validadores em seu bloco proposto. Essas recompensas são as “cenouras” que encorajam a honestidade do validador. Um propositor de bloco que inclui slashing será recompensado com `slashed_validators_effective_balance / 512`. ### Penalidades {#penalties} Até agora, temos considerado validadores perfeitamente bem comportados, mas o que acontece quando os validadores não fazem votos de cabeçalho, origem e destino em tempo hábil ou o fazem lentamente? -As penalidades por perda de votos de destino e de origem são iguais às recompensas que o atestador teria recebido se as tivesse enviado. Isso significa que, em vez de ter a recompensa adicionada ao seu saldo, eles têm um valor igual retirado do seu saldo. Não há penalidade por perder o voto de cabeçalho (ou seja, os votos de cabeçalhos são apenas recompensados, nunca penalizados). Não há penalidade associada ao `inclusion_delay` – a recompensa simplesmente não será adicionada ao saldo do validador. Também não existe nenhuma penalidade por falhar em propor um bloco. +As penalidades por perda de votos de destino e de origem são iguais às recompensas que o atestador teria recebido se as tivesse enviado. Isso significa que, em vez de ter a recompensa adicionada ao seu saldo, eles têm um valor igual retirado do seu saldo. Não há penalidade por perder o voto de cabeçalho (ou seja, os votos de cabeçalho são apenas recompensados, nunca penalizados). Não há penalidade associada ao `inclusion_delay` - a recompensa simplesmente não será adicionada ao saldo do validador. Também não existe nenhuma penalidade por falhar em propor um bloco. -Leia mais sobre recompensas e penalidades nas [especificações de consenso](https://github.com/ethereum/consensus-specs/blob/master/specs/altair/beacon-chain.md). Recompensas e penalidades foram ajustadas na atualização Bellatrix – assista a Danny Ryan e Vitalik falando sobre isso neste vídeo: [Peep an EIP](https://www.youtube.com/watch?v=iaAEGs1DMgQ). +Leia mais sobre recompensas e penalidades nas [especificações de consenso](https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md). As recompensas e penalidades foram ajustadas na atualização Bellatrix. Assista a Danny Ryan e Vitalik discutirem sobre isso neste [vídeo Peep an EIP](https://www.youtube.com/watch?v=iaAEGs1DMgQ). -## Remoção {#slashing} +## Slashing {#slashing} Remoção é uma ação mais severa que resulta na remoção forçada de um validador da rede e na perda associada de seu ether em participação. Há três maneiras que um validador pode ser removido: pela proposta ou atestação desonestas de blocos: @@ -70,9 +70,9 @@ Remoção é uma ação mais severa que resulta na remoção forçada de um vali - Ao confirmar um bloco “em volta” de outro (mudando efetivamente o histórico) - Por “votação dupla”, atestando dois candidatos para o mesmo bloco -Se essas ações forem detectadas, o validador é removido. Isso significa que 1/32 do seu ether em risco (até um máximo de 1 ether) é imediatamente queimado, então um período de remoção de 36 dias é iniciado. Durante esse período de remoção, a participação dos validadores vai diminuir gradualmente. No meio do período (dia 18) é aplicada uma penalidade adicional cuja magnitude é escalada com o total de ether em stake de todos os validadores cortados nos 36 dias anteriores ao evento de corte. Isso significa que quanto mais validadores são removidos, a magnitude da remoção aumenta. A remoção máxima é o saldo total efetivo de todos os validadores removidos (ou seja, se houver muitos validadores sendo removidos, eles poderiam perder toda a sua participação). Por outro lado, um evento único e isolado de remoção apenas queima uma pequena parte da participação do validador. Esta penalidade de ponto médio que escala com o número de validadores removidos é chamada de “penalidade de correlação”. +Se essas ações forem detectadas, o validador é removido. Isso significa que 0,0078125 é imediatamente queimado para um validador de 32 ETH (escalado linearmente com saldo ativo), então um período de remoção de 36 dias começa. Durante esse período de remoção, a participação dos validadores vai diminuir gradualmente. No meio do período (dia 18) é aplicada uma penalidade adicional cuja magnitude é escalada com o total de ether em stake de todos os validadores cortados nos 36 dias anteriores ao evento de corte. Isso significa que quanto mais validadores são removidos, a magnitude da remoção aumenta. O slashing máximo é o saldo efetivo total de todos os validadores que sofreram slashing (ou seja, se muitos validadores sofrerem slashing, eles podem perder todo o seu stake). Por outro lado, um evento único e isolado de remoção apenas queima uma pequena parte da participação do validador. Esta penalidade de ponto médio que escala com o número de validadores removidos é chamada de “penalidade de correlação”. -## Vazamento de inatividade {#inactivity-leak} +## Vazamento por inatividade {#inactivity-leak} Se a camada de consenso tiver passado mais de quatro épocas sem finalizar, um protocolo de emergência chamado "vazamento de inatividade" é ativado. O objetivo final do vazamento de inatividade é criar as condições necessárias para a cadeia recuperar a finalidade. Como explicado acima, a finalidade requer uma maioria 2/3 do ether total em participação para concordar sobre os pontos de verificação de origem e destino. Se os validadores representando mais de 1/3 do total dos validadores ficarem offline ou falharem em enviar os atestados corretos, então não é possível que uma supermaioria de 2/3 finalize os pontos de verificação. O vazamento de inatividade deixa o stake pertencente aos validadores inativos esvaziar gradualmente até que eles controlem menos de 1/3 do stake total, permitindo que os validadores ativos restantes finalizem a cadeia. Por maior que seja o pool de validadores inativos, os validadores ativos restantes acabarão controlando >2/3 do stake. A perda de stake é um forte incentivo para os validadores inativos reativarem o mais rápido possível! Um cenário de vazamento de inatividade foi encontrado na rede de testes Medalla quando < 66% dos validadores ativos conseguiram chegar a um consenso sobre a cabeça atual da blockchain. O vazamento de inatividade foi ativado e a finalidade acabou sendo recuperada! @@ -82,9 +82,9 @@ O design de recompensa, penalidade e corte do mecanismo de consenso incentiva os - [Atualizando o Ethereum: a camada de incentivo](https://eth2book.info/altair/part2/incentives) - [Incentivos no protocolo Casper híbrido do Ethereum](https://arxiv.org/pdf/1903.04205.pdf) -- [Especificação anotada de Vitalik](https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md#rewards-and-penalties-1) -- [Dicas para evitar remoções no Eth2](https://medium.com/prysmatic-labs/eth2-slashing-prevention-tips-f6faa5025f50) -- [Análise das penalidades de remoção sob o EIP-7251](https://ethresear.ch/t/slashing-penalty-analysis-eip-7251/16509) +- [Especificação comentada de Vitalik](https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md#rewards-and-penalties-1) +- [Dicas de prevenção de slashing do Eth2](https://medium.com/prysmatic-labs/eth2-slashing-prevention-tips-f6faa5025f50) +- [Análise das penalidades de slashing sob o EIP-7251](https://ethresear.ch/t/slashing-penalty-analysis-eip-7251/16509) _Fontes_ diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/weak-subjectivity/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/weak-subjectivity/index.md index a001e71118c..19da9a79bfe 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/weak-subjectivity/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pos/weak-subjectivity/index.md @@ -1,14 +1,14 @@ --- title: Subjetividade fraca -description: Uma explicação de subjetividade fraca e o seu papel na prova de participação do Ethereum. +description: "Uma explicação de subjetividade fraca e o seu papel na prova de participação do Ethereum." lang: pt-br --- Subjetividade em blockchains refere-se à dependência de informações sociais para concordar com o estado atual. Pode haver vários forks válidos que são escolhidos de acordo com as informações coletadas de outros pares na rede. A questão é a objetividade a que se refere às cadeias onde existe apenas uma cadeia válida possível e que todos os nós necessariamente concordarão aplicando as suas regras codificadas. Há também um terceiro estado, conhecido como subjetivo fraco. Isso se refere a uma cadeia que pode progredir objetivamente após alguma semente inicial de informação ser recuperada socialmente. -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -Para entender esta página é necessário primeiro entender os fundamentos de [prova de participação](/developers/docs/consensus-mechanisms/pos/). +Para entender esta página, é necessário primeiro entender os fundamentos da [prova de participação](/developers/docs/consensus-mechanisms/pos/). ## Quais são os problemas que a subjetividade fraca resolve? {#problems-ws-solves} @@ -16,7 +16,7 @@ A subjetividade é inerente às blockchains de prova de participação porque a ## Pontos de verificação de subjetividade fraca {#ws-checkpoints} -A subjetividade fraca é implementada na prova de participação do Ethereum usando "pontos de verificação de subjetividade fraca". Estes são raízes de estado que todos os nós da rede concordam em integrar à cadeia canônica. Eles servem o mesmo propósito de "verdade universal" para blocos de início, exceto que eles não se colocam na posição de início na blockchain. O algoritmo de escolha de fork confia em que o estado definido naquele ponto de verificação é correto e que ele verifica a cadeia de forma independente e objetiva a partir desse ponto. Os pontos de verificação atuam como "limites de reversão" porque os blocos localizados antes dos pontos de verificação de subjetividade fraca não podem ser alterados. Isto mina os ataques de longo alcance simplesmente definindo forks de longo alcance como inválidos como parte do modelo do mecanismo. Garantir que os pontos de verificação de subjetividade fraca sejam separados por uma distância menor que o período de retirada do validador garante que um validador que faz o fork da cadeia tenha removido pelo menos algum valor limite antes que eles possam retirar seu stake e que novos participantes não possam ser enganados em forks incorretos por validadores cuja participação foi retirada. +A subjetividade fraca é implementada na prova de participação do Ethereum usando "pontos de verificação de subjetividade fraca". Estes são raízes de estado que todos os nós da rede concordam em integrar à cadeia canônica. Eles servem ao mesmo propósito de "verdade universal" dos blocos iniciais, exceto que não ficam na posição de início na blockchain. O algoritmo de escolha de fork confia em que o estado definido naquele ponto de verificação é correto e que ele verifica a cadeia de forma independente e objetiva a partir desse ponto. Os pontos de verificação atuam como "limites de reversão" porque os blocos localizados antes dos pontos de verificação de subjetividade fraca não podem ser alterados. Isto mina os ataques de longo alcance simplesmente definindo forks de longo alcance como inválidos como parte do modelo do mecanismo. Garantir que os pontos de verificação de subjetividade fraca sejam separados por uma distância menor que o período de retirada do validador garante que um validador que faz o fork da cadeia tenha removido pelo menos algum valor limite antes que eles possam retirar seu stake e que novos participantes não possam ser enganados em forks incorretos por validadores cuja participação foi retirada. ## Diferença entre pontos de verificação de subjetividade fraca e blocos finalizados {#difference-between-ws-and-finalized-blocks} @@ -32,8 +32,8 @@ Finalmente, os pontos de verificação podem ser solicitados a partir de outros ## Leitura adicional {#further-reading} -- [Subjetividade fraca em Eth2](https://notes.ethereum.org/@adiasg/weak-subjectvity-eth2) -- [Vitalik: Como eu aprendi a amar a subjetividade fraca](https://blog.ethereum.org/2014/11/25/proof-stake-learned-love-weak-subjectivity) -- [Subjetividade fraca (documentos Teku)](https://docs.teku.consensys.net/en/latest/Concepts/Weak-Subjectivity/) -- [Guia de subjetividade fraca: fase-0](https://github.com/ethereum/consensus-specs/blob/master/specs/phase0/weak-subjectivity.md) -- [Análise de subjetividade fraca no Ethereum 2.0](https://github.com/runtimeverification/beacon-chain-verification/blob/master/weak-subjectivity/weak-subjectivity-analysis.pdf) +- [Subjetividade fraca no Eth2](https://notes.ethereum.org/@adiasg/weak-subjectvity-eth2) +- [Vitalik: Como aprendi a amar a subjetividade fraca](https://blog.ethereum.org/2014/11/25/proof-stake-learned-love-weak-subjectivity/) +- [Subjetividade fraca (docs do Teku)](https://docs.teku.consensys.io/concepts/weak-subjectivity) +- [Guia de subjetividade fraca da Fase 0](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/weak-subjectivity.md) +- [Análise da subjetividade fraca no Ethereum 2.0](https://github.com/runtimeverification/beacon-chain-verification/blob/master/weak-subjectivity/weak-subjectivity-analysis.pdf) diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/index.md index 83ce699a367..5417e9297a2 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/index.md @@ -1,27 +1,27 @@ --- title: Prova de trabalho (PoW) -description: Uma explicação do protocolo de consenso de prova de trabalho e seu papel no Ethereum. +description: "Uma explicação do protocolo de consenso de prova de trabalho e seu papel no Ethereum." lang: pt-br --- -A rede Ethereum começou usando um mecanismo de consenso que envolvia **[Prova de trabalho (PoW)](/developers/docs/consensus-mechanisms/pow)**. Isso permitiu que os nós da rede Ethereum concordassem com o estado de todas as informações registradas na cadeia de blocos Ethereum e impediu certos tipos de ataques econômicos. No entanto, o Ethereum desativou a prova de trabalho em 2022 e começou a usar a [prova de participação](/developers/docs/consensus-mechanisms/pos). +A rede Ethereum começou usando um mecanismo de consenso que envolvia a **[prova de trabalho (PoW)](/developers/docs/consensus-mechanisms/pow)**. Isso permitiu que os nós da rede Ethereum concordassem com o estado de todas as informações registradas na cadeia de blocos Ethereum e impediu certos tipos de ataques econômicos. No entanto, o Ethereum desativou a prova de trabalho em 2022 e passou a usar a [prova de participação](/developers/docs/consensus-mechanisms/pos). - A prova de trabalho agora está obsoleta. O Ethereum não usa mais a prova de trabalho como parte de seu mecanismo de consenso. Em vez disso, ele usa a prova de participação. Leia mais sobre [prova de participação](/developers/docs/consensus-mechanisms/pos/) e [participação](/staking/). + A prova de trabalho agora está obsoleta. O Ethereum não usa mais a prova de trabalho como parte de seu mecanismo de consenso. Em vez disso, ele usa a prova de participação. Leia mais em [proof-of-stake](/developers/docs/consensus-mechanisms/pos/) e [staking](/staking/). ## Pré-requisitos {#prerequisites} -Para entender melhor esta página, recomendamos ler primeiro sobre [ transações ](/developers/docs/transactions/), [blocos](/developers/docs/blocks/) e [mecanismos de consenso](/developers/docs/consensus-mechanisms/). +Para entender melhor esta página, recomendamos que você leia primeiro sobre [transações](/developers/docs/transactions/), [blocos](/developers/docs/blocks/) e [mecanismo de consenso](/developers/docs/consensus-mechanisms/). ## O que é prova de trabalho (PoW)? {#what-is-pow} -O consenso de Nakamoto, que utiliza prova de trabalho, é o mecanismo que uma vez permitiu que a rede descentralizada Ethereum chegasse a um consenso (ou seja, todos os nós concordam) em coisas como saldos de contas e a ordem das transações. Isso impediu os usuários de "gastar duas vezes" suas moedas e garantiu que a cadeia Ethereum se tornasse tremendamente difícil de atacar ou manipular. Essas propriedades de segurança agora vêm da prova de participação usando o mecanismo de consenso conhecido como [Gasper](/developers/docs/consensus-mechanisms/pos/gasper/). +O consenso de Nakamoto, que utiliza a prova de trabalho, é o mecanismo que permitiu que a rede descentralizada do Ethereum chegasse a um consenso (isto é, que todos os nós concordassem) sobre questões como saldos de contas e a ordem das transações. Isso impediu os usuários de "gastar duas vezes" suas moedas e garantiu que a cadeia Ethereum se tornasse tremendamente difícil de atacar ou manipular. Essas propriedades de segurança agora vêm da prova de participação, usando o mecanismo de consenso conhecido como [Gasper](/developers/docs/consensus-mechanisms/pos/gasper/). ## Prova de trabalho e mineração {#pow-and-mining} @@ -39,7 +39,7 @@ As transações Ethereum são processadas em blocos. Na agora obsoleta prova de Esses dados de bloco estavam diretamente relacionados à prova de trabalho. -### O trabalho em prova-de-trabalho {#the-work} +### O trabalho na prova de trabalho {#the-work} O protocolo de prova de trabalho, Ethash, exigia que os mineradores passassem por uma intensa corrida de tentativa e erro para encontrar o nonce para um bloco. Apenas blocos com um nonce válido podem ser adicionados à cadeia. @@ -57,31 +57,31 @@ O objetivo da prova de trabalho era estender a cadeia. A cadeia mais longa era m Para criar consistentemente blocos maliciosos, ainda que válidos, um minerador mal-intencionado precisaria de mais de 51% do poder de mineração da rede para superar todos os demais. Essa quantidade de "trabalho" requer muito poder de computação caro e a energia gasta pode até ter superado os ganhos obtidos em um ataque. -### Aspectos econômicos da prova de trabalho {#economics} +### Economia da prova de trabalho {#economics} A prova de trabalho também foi responsável por emitir novas moedas no sistema e incentivar os mineradores a fazer o trabalho. -Desde a [atualização de Constantinopla](/ethereum-forks/#constantinople), os mineradores que criaram com sucesso um bloco foram recompensados com dois ETH recém-cunhados e parte das taxas de transação. Os blocos Omner também compensaram 1,75 ETH. Os blocos Ommer eram blocos válidos criados por um minerador praticamente ao mesmo tempo que outro minerador criava o bloco canônico, o que foi determinado em última instância por qual cadeia foi construída em cima da primeira. Os blocos Ommer geralmente aconteciam devido à latência da rede. +Desde a [atualização Constantinople](/ethereum-forks/#constantinople), os mineradores que criaram blocos com sucesso foram recompensados com dois ETH recém-cunhados e parte das taxas de transação. Os blocos Omner também compensaram 1,75 ETH. Os blocos Ommer eram blocos válidos criados por um minerador praticamente ao mesmo tempo que outro minerador criava o bloco canônico, o que foi determinado em última instância por qual cadeia foi construída em cima da primeira. Os blocos Ommer geralmente aconteciam devido à latência da rede. -## Finalidade {#finality} +## Finality {#finality} Uma transação tem "finalidade" no Ethereum quando ela faz parte de um bloco que não pode mudar. Como os mineradores trabalhavam de maneira descentralizada, dois blocos válidos poderiam ser minerados ao mesmo tempo. Isso cria uma bifurcação temporária. Por fim, uma dessas cadeias se tornou a cadeia aceita depois que os blocos subsequentes foram minerados e adicionados a ela, tornando-a mais longa. -Para complicar ainda mais, as transações rejeitadas na bifurcação temporária podem não ter sido incluídas na cadeia aceita. Ou seja, isso poderia ser revertido. Portanto, a finalização se refere ao tempo que você deve esperar antes de considerar uma transação irreversível. Na prova de trabalho Ethereum anterior, quanto mais blocos foram extraídos em cima de um bloco `N` específico, maior a confiança de que as transações em `N` foram bem-sucedidas e não seriam revertidas. Agora, com a prova de participação, a finalização é uma propriedade explícita, e não probabilística, de um bloco. +Para complicar ainda mais, as transações rejeitadas na bifurcação temporária podem não ter sido incluídas na cadeia aceita. Ou seja, isso poderia ser revertido. Portanto, "finalidade" se refere ao tempo que você deve esperar antes de considerar uma transação irreversível. No Ethereum com prova de trabalho anterior, quanto mais blocos fossem minerados sobre um bloco `N` específico, maior a confiança de que as transações em `N` foram bem-sucedidas e não seriam revertidas. Agora, com a prova de participação, a finalização é uma propriedade explícita, e não probabilística, de um bloco. -## Uso de energia na prova de trabalho {#energy} +## Uso de energia da prova de trabalho {#energy} -Uma importante crítica à prova de trabalho é a quantidade de energia necessária para manter a rede segura. Para manter a segurança e a descentralização, o Ethereum na prova de trabalho consumia grandes quantidades de energia. Pouco antes de mudar para a prova de participação, os mineradores do Ethereum consumiam coletivamente cerca de 70 TWh/ano (aproximadamente o mesmo que a República Tcheca, de acordo com [digiconomist](https://digiconomist.net/) em 18 de julho de 2022). +Uma importante crítica à prova de trabalho é a quantidade de energia necessária para manter a rede segura. Para manter a segurança e a descentralização, o Ethereum na prova de trabalho consumia grandes quantidades de energia. Pouco antes da mudança para a prova de participação, os mineradores do Ethereum consumiam coletivamente cerca de 70 TWh/ano (aproximadamente o mesmo que a República Tcheca - de acordo com o [digiconomist](https://digiconomist.net/) em 18 de julho de 2022). ## Prós e contras {#pros-and-cons} -| Prós | Contras | -| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| A prova de trabalho é neutra. Você não precisa de ETH para começar, e as recompensas por bloco permitem que você vá de 0 ETH a um saldo positivo. Na [prova de participação](/developers/docs/consensus-mechanisms/pos/), você precisa de ETH para começar. | A prova de trabalho consome tanta energia que é prejudicial ao meio ambiente. | -| A prova de trabalho é um mecanismo de consenso testado que manteve o Bitcoin e o Ethereum seguros e descentralizados por muitos anos. | Se você quer minerar, você precisa de equipamento especializado, e isso é um grande investimento para começar. | -| Comparada com a prova de participação, é relativamente fácil de implementar. | Devido ao aumento necessário do cálculo de mineração, as pools de mineração poderiam potencialmente dominar o mercado de mineração, levando à centralização e a riscos de segurança. | +| Prós | Contras | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| A prova de trabalho é neutra. Você não precisa de ETH para começar, e as recompensas por bloco permitem que você vá de 0 ETH a um saldo positivo. Com a [prova de participação](/developers/docs/consensus-mechanisms/pos/), você precisa de ETH para começar. | A prova de trabalho consome tanta energia que é prejudicial ao meio ambiente. | +| A prova de trabalho é um mecanismo de consenso testado que manteve o Bitcoin e o Ethereum seguros e descentralizados por muitos anos. | Se você quer minerar, você precisa de equipamento especializado, e isso é um grande investimento para começar. | +| Comparada com a prova de participação, é relativamente fácil de implementar. | Devido ao aumento necessário do cálculo de mineração, as pools de mineração poderiam potencialmente dominar o mercado de mineração, levando à centralização e a riscos de segurança. | ## Comparação com a prova de participação {#compared-to-pos} @@ -92,7 +92,7 @@ Em termos gerais, a prova de participação tem o mesmo objetivo final que a pro - Os validadores não competem para criar blocos, em vez disso, eles são escolhidos aleatoriamente por um algoritmo. - A finalidade é clara: em certos pontos de controle, se 2/3 dos validadores concordam com o estado do bloco então ele é considerado finalizado. Os validadores devem apostar todas as suas fichas nisso, assim, caso tentem conspirar, irão perder toda a aposta. -[Mais sobre prova de participação](/developers/docs/consensus-mechanisms/pos/) +[Mais sobre a prova de participação](/developers/docs/consensus-mechanisms/pos/) ## Você é o tipo de pessoa que aprende mais com recursos visuais? {#visual-learner} @@ -100,8 +100,8 @@ Em termos gerais, a prova de participação tem o mesmo objetivo final que a pro ## Leitura adicional {#further-reading} -- [Ataque majoritário](https://en.bitcoin.it/wiki/Majority_attack) -- [Finalidade do acordo](https://blog.ethereum.org/2016/05/09/on-settlement-finality) +- [Ataque de maioria](https://en.bitcoin.it/wiki/Majority_attack) +- [Sobre a finalidade da liquidação](https://blog.ethereum.org/2016/05/09/on-settlement-finality/) ### Vídeos {#videos} diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/index.md index e4d080759df..0aac89c90de 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/index.md @@ -1,6 +1,6 @@ --- -title: Mineração -description: Uma explicação de como a mineração funcionava no Ethereum. +title: "Mineração" +description: "Uma explicação de como a mineração funcionava no Ethereum." lang: pt-br --- @@ -8,14 +8,14 @@ lang: pt-br -A prova de trabalho não está mais subjacente ao mecanismo de consenso do Ethereum, o que significa que a mineração foi desativada. Em vez disso, o Ethereum é garantido por validadores que apostam em ETH. Você pode começar a participar com o seu ETH hoje. Leia mais sobre
A Fusão (The MErge), prova de participação e participação (stake). Esta página é apenas para interesse histórico. +A prova de trabalho não está mais subjacente ao mecanismo de consenso do Ethereum, o que significa que a mineração foi desativada. Em vez disso, o Ethereum é garantido por validadores que apostam em ETH. Você pode começar a participar com o seu ETH hoje. Leia mais sobre A Fusão (The Merge), prova de participação e participação (stake). Esta página é apenas de interesse histórico. ## Pré-requisitos {#prerequisites} -Para melhor entender esta página, recomendamos que você leia primeiro [transações](/developers/docs/transactions/), [blocos](/developers/docs/blocks/) e [prova de trabalho ](/developers/docs/consensus-mechanisms/pow/). +Para entender melhor esta página, recomendamos que você leia primeiro sobre [transações](/developers/docs/transactions/), [blocos](/developers/docs/blocks/) e [prova de trabalho](/developers/docs/consensus-mechanisms/pow/). ## O que é mineração de Ethereum? {#what-is-ethereum-mining} @@ -42,30 +42,30 @@ Anteriormente, qualquer era capaz de minerar na rede Ethereum usando seu computa - Se você estivesse minerando em um pool, esses pools normalmente cobravam uma taxa percentual fixa de cada bloco gerado pelo pool - Custo potencial do equipamento para apoiar a plataforma de mineração (ventilação, monitoramento de energia, fiação elétrica, etc.) -Para conhecer ainda mais a rentabilidade da mineração, use uma calculadora de mineração, como a fornecida pela [Etherscan](https://etherscan.io/ether-mining-calculator). +Para explorar ainda mais a rentabilidade da mineração, use uma calculadora de mineração, como a que o [Etherscan](https://etherscan.io/ether-mining-calculator) oferece. ## Como as transações do Ethereum eram mineradas {#how-ethereum-transactions-were-mined} -O seguinte fornece uma visão geral de como as transações foram mineradas na prova de trabalho Ethereum. Uma descrição análoga deste processo para a prova de participação Ethereum pode ser encontrada [aqui](/developers/docs/consensus-mechanisms/pos/#transaction-execution-ethereum-pos). +O seguinte fornece uma visão geral de como as transações foram mineradas na prova de trabalho Ethereum. Uma descrição análoga deste processo para a prova de participação do Ethereum pode ser encontrada [aqui](/developers/docs/consensus-mechanisms/pos/#transaction-execution-ethereum-pos). 1. Um usuário escreve e assina uma solicitação de [transação](/developers/docs/transactions/) com a chave privada de alguma [conta](/developers/docs/accounts/). -2. O usuário transmite a solicitação de transação para toda a rede Ethereum de algum [nó](/developers/docs/nodes-and-clients/). +2. O usuário transmite a solicitação de transação para toda a rede Ethereum a partir de algum [nó](/developers/docs/nodes-and-clients/). 3. Ao ouvir tomar conhecimento da nova solicitação de transação, cada nó na rede Ethereum adiciona a solicitação ao seu mempool local, uma lista de todas as solicitações de transação sobre as quais eles têm conhecimento que ainda não foram confirmadas na blockchain em um bloco. -4. Em algum ponto, um nó de mineração agrega várias dezenas ou centenas de solicitações de transação a um [bloco](/developers/docs/blocks/) potencial, de uma forma que maximiza as [taxas de transação](/developers/docs/gas/) que eles ganham enquanto ainda estão abaixo do limite de gás de bloco. Então, o nó de mineração: - 1. Verifica a validade de cada pedido de transação (por exemplo, ninguém está tentando transferir o ether de uma conta para a qual não produziu uma assinatura, a solicitação não está malformada, etc.), e em seguida executa o código da solicitação, alterando o estado de sua cópia local do EVM. O minerador atribui a taxa de transação para cada um desses pedidos de transação à sua própria conta. +4. Em algum momento, um nó de mineração agrega várias dezenas ou centenas de solicitações de transação em um [bloco](/developers/docs/blocks/) potencial, de uma forma que maximize as [taxas de transação](/developers/docs/gas/) que ele ganha, enquanto ainda permanece abaixo do limite de gás do bloco. Então, o nó de mineração: + 1. Verifica a validade de cada solicitação de transação (ou seja, ninguém está tentando transferir ether de uma conta para a qual não produziu uma assinatura, a solicitação não está malformada, etc.), e, em seguida, executa o código da solicitação, alterando o estado de sua cópia local da EVM. O minerador atribui a taxa de transação para cada um desses pedidos de transação à sua própria conta. 2. Começa o processo de produção do "certificado de legitimidade" da Prova de participação para o bloco em potencial, uma vez que todas as solicitações de transação no bloco tenham sido verificadas e executadas na cópia local do EVM. 5. Eventualmente, um minerador terminará de produzir um certificado para um bloco que inclui nossa solicitação específica de transação. O minerador, em seguida, transmite o bloco completo, que inclui o certificado e uma soma de verificação do novo estado EVM requerido. 6. Outros nós obtêm informação sobre o novo bloco. Eles verificam o certificado, executam todas as transações no próprio bloco (incluindo a transação originalmente transmitida pelo nosso usuário) e verifique se a soma de verificação de seu novo estado EVM após a execução de todas as transações corresponde à soma de verificação do estado reivindicada pelo bloco do minerador. Só então esses nós adicionam este bloco à cauda do blockchain e aceitam o novo estado EVM como o estado canônico. 7. Cada nó remove todas as transações do novo bloco de suas memórias locais de pedidos de transações não atendidos. 8. Novos nós que se juntam à rede baixam todos os blocos em sequência, incluindo o bloco que contém nossa transação de interesse. Eles inicializam uma cópia local de EVM (que começa como uma EVM em branco) e, em seguida, passa pelo processo de execução de cada transação em cada bloco em cima de sua cópia de EVM local, verificando as somas de verificação de estado em cada bloco ao longo do caminho. -Cada transação é extraída (incluída em um novo bloco e propagada pela primeira vez) uma vez, mas executada e verificada por cada participante no processo de avanço do estado EVM padrão. Isso destaca um dos mantras centrais da cadeia de blocos: ** Não confie, verifique **. +Cada transação é extraída (incluída em um novo bloco e propagada pela primeira vez) uma vez, mas executada e verificada por cada participante no processo de avanço do estado EVM padrão. Isso destaca um dos mantras centrais da cadeia de blocos: **Não confie, verifique**. ## Blocos Ommer (tio) {#ommer-blocks} -Mineração de blocos na prova de trabalho era probabilística, o que significa que às vezes dois blocos válidos eram publicados simultaneamente devido à latência da rede. Nesse caso, o protocolo tinha que determinar a cadeia mais longa (e, portanto, mais “válida”), enquanto garante justiça para os mineradores, recompensando parcialmente o bloco válido proposto não incluído. Isso encorajou uma maior descentralização da rede, pois mineradores menores, que podem enfrentar maior latência, ainda poderiam gerar retornos por meio de recompensas de bloco [ommer](/glossary/#ommer). +Mineração de blocos na prova de trabalho era probabilística, o que significa que às vezes dois blocos válidos eram publicados simultaneamente devido à latência da rede. Nesse caso, o protocolo tinha que determinar a cadeia mais longa (e, portanto, mais “válida”), enquanto garante justiça para os mineradores, recompensando parcialmente o bloco válido proposto não incluído. Isso incentivou uma maior descentralização da rede, pois mineradores menores, que podem enfrentar maior latência, ainda poderiam gerar retornos por meio de recompensas de bloco [ommer](/glossary/#ommer). -O termo "ommer" é o termo neutro de gênero preferido para o irmão de um bloco pai, mas às vezes também é chamado de "tio". **Desde a mudança do Ethereum para prova de participação, os blocos ommer não são mais minerados**, pois apenas um proponente é eleito em cada espaço. Você pode ver essa mudança visualizando o [gráfico histórico](https://ycharts.com/indicators/ethereum_uncle_rate) dos blocos ommer minerados. +O termo "ommer" é o termo neutro de gênero preferido para o irmão de um bloco pai, mas às vezes também é chamado de "tio". **Desde a mudança do Ethereum para a prova de participação, os blocos ommer não são mais minerados**, pois apenas um proponente é eleito em cada espaço. Você pode ver essa mudança visualizando o [gráfico histórico](https://ycharts.com/indicators/ethereum_uncle_rate) dos blocos ommer minerados. ## Uma demonstração visual {#a-visual-demo} @@ -75,7 +75,7 @@ Acompanhe o Austin enquanto ele explica como funciona o processo de mineração ## O algoritmo de mineração {#mining-algorithm} -A Rede principal do Ethereum usou apenas um algoritmo de mineração, o ["Ethash"](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/ethash/). Ethash foi o sucessor de um algoritmo original de pesquisa e desenvolvimento conhecido como ['Dagger-Hashimoto'](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto/). +A rede principal do Ethereum sempre usou apenas um algoritmo de mineração - ['Ethash'](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/ethash/). O Ethash foi o sucessor de um algoritmo de P&D original conhecido como ['Dagger-Hashimoto'](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto/). [Mais sobre algoritmos de mineração](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/). diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto/index.md index 84ae914d111..37899ccb0e8 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto/index.md @@ -4,32 +4,32 @@ description: O algoritmo Dagger-Hashimoto em detalhes lang: pt-br --- -Dagger-Hashimoto foi a implementação original de pesquisa e especificação para o algoritmo de mineração do Ethereum. Dagger-Hashimoto foi substituído por [Ethash](#ethash). A mineração foi completamente interrompida na [Fusão](/roadmap/merge/) no dia 15 de setembro de 2022. Desde então, o Ethereum foi protegido usando um mecanismo [prova de participação](/developers/docs/consensus-mechanisms/pos). Esta página é para fins históricos. As informações aqui não são mais relevantes para o Ethereum posterior à Fusão. +Dagger-Hashimoto foi a implementação original de pesquisa e especificação para o algoritmo de mineração do Ethereum. O Dagger-Hashimoto foi substituído pelo [Ethash](#ethash). A mineração foi completamente desligada em [A Fusão](/roadmap/merge/) em 15 de setembro de 2022. Desde então, o Ethereum tem sido protegido usando um mecanismo de [prova de participação](/developers/docs/consensus-mechanisms/pos). Esta página é para fins históricos. As informações aqui não são mais relevantes para o Ethereum posterior à Fusão. -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -Para melhor entender esta página, recomendamos que você leia primeiro o [consenso de prova de trabalho](/developers/docs/consensus-mechanisms/pow), [mineração](/developers/docs/consensus-mechanisms/pow/mining) e [algoritmos de mineração](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms). +Para entender melhor esta página, recomendamos que você leia primeiro sobre [consenso de prova de trabalho](/developers/docs/consensus-mechanisms/pow), [mineração](/developers/docs/consensus-mechanisms/pow/mining) e [algoritmos de mineração](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms). ## Dagger-Hashimoto {#dagger-hashimoto} Dagger-Hashimoto pretende satisfazer dois objetivos: -1. **Resistência a ASIC**: o benefício de criar hardware especializado para o algoritmo deve ser o menor possível. -2. **Cliente leve verificável**: um bloco deve ser verificável eficientemente por um cliente leve. +1. **Resistência a ASIC**: o benefício de criar hardware especializado para o algoritmo deve ser o menor possível +2. **Verificabilidade de cliente leve**: um bloco deve ser eficientemente verificável por um cliente leve. Com uma modificação adicional, também especificamos como atingir um terceiro objetivo se desejado, mas à custa de uma complexidade adicional: -**Armazenamento completo da cadeia**: a mineração deveria exigir o armazenamento do estado completo da blockchain (devido à estrutura irregular da árvore de estado Ethereum, esperamos que haja um pouco de perda, especialmente de alguns contratos muitas vezes usados, mas queremos minimizar isso). +**Armazenamento completo da cadeia**: a mineração deve exigir o armazenamento do estado completo da blockchain (devido à estrutura irregular da trie de estado do Ethereum, prevemos que alguma poda será possível, particularmente de alguns contratos usados com frequência, mas queremos minimizar isso). -## Geração do DAG {#dag-generation} +## Geração de DAG {#dag-generation} -O código do algoritmo será definido em Python abaixo. Primeiro, damos `encode_int` para combinar inteiros sem sinal de precisão especificada em strings. Sua inversa também é dada: +O código do algoritmo será definido em Python abaixo. Primeiro, apresentamos o `encode_int` para o empacotamento (marshaling) de inteiros sem sinal de precisão especificada em strings. Sua inversa também é dada: ```python NUM_BITS = 512 def encode_int(x): - "Encode an integer x as a string of 64 characters using a big-endian scheme" + "Codifica um inteiro x como uma string de 64 caracteres usando um esquema big-endian" o = '' for _ in range(NUM_BITS / 8): o = chr(x % 256) + o @@ -37,7 +37,7 @@ def encode_int(x): return o def decode_int(s): - "Unencode an integer x from a string using a big-endian scheme" + "Decodifica um inteiro x de uma string usando um esquema big-endian" x = 0 for c in s: x *= 256 @@ -45,7 +45,7 @@ def decode_int(s): return x ``` -Em seguida assumimos que `sha3` é uma função que recebe um inteiro e retorna um inteiro, e `dbl_sha3` é uma função double-sha3, se converter este código de referência em uma implementação de uso: +Em seguida, assumimos que `sha3` é uma função que recebe um inteiro e retorna um inteiro, e `dbl_sha3` é uma função double-sha3; se estiver convertendo este código de referência em uma implementação, use: ```python from pyethereum import utils @@ -65,26 +65,26 @@ def dbl_sha3(x): Os parâmetros usados para o algoritmo são: ```python -SAFE_PRIME_512 = 2**512 - 38117 # Largest Safe Prime less than 2**512 +SAFE_PRIME_512 = 2**512 - 38117 # O maior primo seguro menor que 2**512 params = { - "n": 4000055296 * 8 // NUM_BITS, # Size of the dataset (4 Gigabytes); MUST BE MULTIPLE OF 65536 - "n_inc": 65536, # Increment in value of n per period; MUST BE MULTIPLE OF 65536 - # with epochtime=20000 gives 882 MB growth per year - "cache_size": 2500, # Size of the light client's cache (can be chosen by light - # client; not part of the algo spec) - "diff": 2**14, # Difficulty (adjusted during block evaluation) - "epochtime": 100000, # Length of an epoch in blocks (how often the dataset is updated) - "k": 1, # Number of parents of a node - "w": w, # Used for modular exponentiation hashing - "accesses": 200, # Number of dataset accesses during hashimoto - "P": SAFE_PRIME_512 # Safe Prime for hashing and random number generation + "n": 4000055296 * 8 // NUM_BITS, # Tamanho do conjunto de dados (4 Gigabytes); DEVE SER MÚLTIPLO DE 65536 + "n_inc": 65536, # Incremento no valor de n por período; DEVE SER MÚLTIPLO DE 65536 + # com epochtime=20000 resulta em um crescimento de 882 MB por ano + "cache_size": 2500, # Tamanho do cache do cliente leve (pode ser escolhido pelo cliente + # leve; não faz parte da especificação do algoritmo) + "diff": 2**14, # Dificuldade (ajustada durante a avaliação do bloco) + "epochtime": 100000, # Duração de uma época em blocos (com que frequência o conjunto de dados é atualizado) + "k": 1, # Número de pais de um nó + "w": w, # Usado para hashing de exponenciação modular + "accesses": 200, # Número de acessos ao conjunto de dados durante o hashimoto + "P": SAFE_PRIME_512 # Primo Seguro para hashing e geração de números aleatórios } ``` -`P` neste caso é uma primeira escolha tal que `log(P)` é apenas ligeiramente menor que 512, que corresponde aos 512 bits que temos usado para representar nossos números. Observe que apenas a última metade do DAG precisa realmente ser armazenado, assim o requisito de RAM de-facto começa em 1 GB e cresce 441 MB por ano. +`P` neste caso é um primo escolhido tal que `log₂(P)` é apenas um pouco menor que 512, o que corresponde aos 512 bits que temos usado para representar nossos números. Observe que apenas a última metade do DAG precisa realmente ser armazenado, assim o requisito de RAM de-facto começa em 1 GB e cresce 441 MB por ano. -### Construção de gráfico Dagger {#dagger-graph-building} +### Construção do grafo Dagger {#dagger-graph-building} A construção primitiva de gráfico dagger é definida da seguinte forma: @@ -101,11 +101,11 @@ def produce_dag(params, seed, length): return o ``` -Essencialmente, ele começa um gráfico como um único nó, `sha3(seed)`, e de lá começa a adicionar sequencialmente outros nós com base em nós aleatórios anteriores. Quando um novo nó é criado, uma potência modular da semente é computada para aleatoriamente selecionar alguns índices menores que `i` (usando `x % i` acima), e os valores dos nós desses índices são usados em um cálculo para gerar um novo valor para `x`, que é então alimentada em uma pequena função de prova de trabalho (baseada em XOR) para finalmente gerar o valor do gráfico no índice `i`. A lógica por trás deste design específico é forçar o acesso sequencial do DAG; o próximo valor do DAG que será acessado não pode ser determinado até que o valor atual seja conhecido. Finalmente, a exponenciação modular faz o hash do resultado ainda mais. +Essencialmente, ele inicia um grafo como um único nó, `sha3(seed)`, e a partir daí começa a adicionar sequencialmente outros nós com base em nós anteriores aleatórios. Quando um novo nó é criado, uma potência modular da semente é computada para selecionar aleatoriamente alguns índices menores que `i` (usando `x % i` acima), e os valores dos nós nesses índices são usados em um cálculo para gerar um novo valor para `x`, que é então alimentado em uma pequena função de prova de trabalho (baseada em XOR) para finalmente gerar o valor do grafo no índice `i`. A lógica por trás deste design específico é forçar o acesso sequencial do DAG; o próximo valor do DAG que será acessado não pode ser determinado até que o valor atual seja conhecido. Finalmente, a exponenciação modular faz o hash do resultado ainda mais. Este algoritmo depende de vários resultados da teoria numérica. Veja o apêndice abaixo para uma discussão. -## Avaliação de cliente leve {#light-client-evaluation} +## Avaliação do cliente leve {#light-client-evaluation} A construção do gráfico acima pretende permitir que cada nó no gráfico seja reconstruído computando uma subárvore com apenas um pequeno número de nós e exigindo uma pequena quantidade de memória auxiliar. Note que com k=1, a subárvore é apenas uma cadeia de valores que vai subindo até o primeiro elemento do DAG. @@ -131,11 +131,11 @@ def quick_calc(params, seed, p): return quick_calc_cached(p) ``` -Essencialmente, é simplesmente uma reescrita do algoritmo acima que remove o loop de computação dos valores de todo o DAG e substitui a pesquisa anterior de nó por uma chamada recursiva ou uma pesquisa de cache. Observe que para `k=1` o cache é desnecessário, embora uma otimização maior na verdade pré-calcula os primeiros poucos milhares de valores do DAG e o mantém como um cache estático para computações; ver o apêndice para uma implementação de código disso. +Essencialmente, é simplesmente uma reescrita do algoritmo acima que remove o loop de computação dos valores de todo o DAG e substitui a pesquisa anterior de nó por uma chamada recursiva ou uma pesquisa de cache. Observe que para `k=1` o cache é desnecessário, embora uma otimização adicional na verdade pré-compute os primeiros milhares de valores do DAG e mantenha isso como um cache estático para computações; veja o apêndice para uma implementação de código disso. ## Buffer duplo de DAGs {#double-buffer} -Em um cliente completo, é usado um [_buffer duplo_](https://wikipedia.org/wiki/Multiple_buffering) de 2 DAGs produzidos pela fórmula acima. A ideia é que DAGs são produzidos a cada `epochtime` número de blocos de acordo com os parâmetros acima. Em vez do cliente usar o último DAG produzido, ele usa o anterior. A vantagem disto é permitir que os DAG sejam substituídos com o passar do tempo, sem necessidade de incorporar um passo em que os mineradores devem, de repente, recriar todos os dados. Caso contrário, existe o potencial para um abrandamento abrupto temporário do processamento da cadeia a intervalos regulares e um aumento dramático da centralização. Assim, existe o risco de ataques de 51% dentro desses poucos minutos antes de todos os dados serem recomputados. +Em um cliente completo, é usado um [_buffer duplo_](https://wikipedia.org/wiki/Multiple_buffering) de 2 DAGs produzidos pela fórmula acima. A ideia é que os DAGs sejam produzidos a cada `epochtime` número de blocos, de acordo com os parâmetros acima. Em vez do cliente usar o último DAG produzido, ele usa o anterior. A vantagem disto é permitir que os DAG sejam substituídos com o passar do tempo, sem necessidade de incorporar um passo em que os mineradores devem, de repente, recriar todos os dados. Caso contrário, existe o potencial para um abrandamento abrupto temporário do processamento da cadeia a intervalos regulares e um aumento dramático da centralização. Assim, existe o risco de ataques de 51% dentro desses poucos minutos antes de todos os dados serem recomputados. O algoritmo usado para gerar o conjunto de DAGs usados para computar o trabalho de um bloco é o seguinte: @@ -164,7 +164,7 @@ def get_daggerset(params, block): dagsz = get_dagsize(params, block) seedset = get_seedset(params, block) if seedset["front_hash"] <= 0: - # No back buffer is possible, just make front buffer + # Nenhum buffer traseiro é possível, apenas crie o buffer frontal return {"front": {"dag": produce_dag(params, seedset["front_hash"], dagsz), "block_number": 0}} else: @@ -256,54 +256,50 @@ Além disso, note que Dagger-Hashimoto impõe requisitos adicionais no cabeçalh ## Leitura adicional {#further-reading} -_Conhece algum recurso da comunidade que o ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ ## Apêndice {#appendix} -Como mencionado acima, o RNG usado para geração de DAGs depende de alguns resultados da teoria de números. Primeiro, nós fornecemos garantias de que o Lehmer RNG, que é a base para a variável `picker`, tenha um longo período. Segundo, mostramos que `pow(x,3,P)` não vai correlacionar `x` para `1` ou `P-1` fornecer `x ∈ [2,P-2]` para começar. Finalmente, mostramos que `pow(x,3,P)` tem uma baixa taxa de colisão quando tratado como uma função de hashing. +Como mencionado acima, o RNG usado para geração de DAGs depende de alguns resultados da teoria de números. Primeiro, fornecemos a garantia de que o Lehmer RNG, que é a base para a variável `picker`, tem um período amplo. Segundo, mostramos que `pow(x,3,P)` não mapeará `x` para `1` ou `P-1`, desde que `x ∈ [2,P-2]` para começar. Finalmente, mostramos que `pow(x,3,P)` tem uma baixa taxa de colisão quando tratado como uma função de hashing. -### Gerador de números aleatórios Lehmer {#lehmer-random-number} +### Gerador de números aleatórios de Lehmer {#lehmer-random-number} -Enquanto a função `produce_dag` não precisa produzir números aleatórios sem viés, uma ameaça potencial é que `seed**i % P` só absorve um punhado de valores. Isto poderia proporcionar uma vantagem aos mineradores reconhecendo o padrão em relação aos que não o fazem. +Embora a função `produce_dag` não precise produzir números aleatórios imparciais, uma ameaça em potencial é que `seed**i % P` assuma apenas um punhado de valores. Isto poderia proporcionar uma vantagem aos mineradores reconhecendo o padrão em relação aos que não o fazem. -Para evitar isso, apela-se a um resultado da teoria dos números. Um [_número primo seguro_](https://en.wikipedia.org/wiki/Safe_prime) é definido como sendo um `P` primo tal que `(P-1)/2` também é primo. A _ordem_ de um membro `x` do [grupo multiplicativo](https://en.wikipedia.org/wiki/Multiplicative_group_of_integers_modulo_n) `Z/nZ` é definido como o mínimo de `m` tal que
xᵐ mod P ≡ 1
+Para evitar isso, apela-se a um resultado da teoria dos números. Um [_Primo Seguro_](https://en.wikipedia.org/wiki/Safe_prime) é definido como um primo `P` tal que `(P-1)/2` também é primo. A _ordem_ de um membro `x` do [grupo multiplicativo](https://en.wikipedia.org/wiki/Multiplicative_group_of_integers_modulo_n) `ℤ/nℤ` é definida como o `m` mínimo tal que
xᵐ mod P ≡ 1
Dadas essas definições, temos: -> Observação 1. Deixe `x` ser um membro do grupo multiplicador `Z/PZ` para um `P` primo seguro. Se `x mod P ≠ 1 mod P` e `x mod P ≠ P-1 mod P`, então a ordem de `x` é `P-1` ou `(P-1)/2`. +> Observação 1. Seja `x` um membro do grupo multiplicativo `ℤ/Pℤ` para um primo seguro `P`. Se `x mod P ≠ 1 mod P` e `x mod P ≠ P-1 mod P`, então a ordem de `x` é `P-1` ou `(P-1)/2`. -_Prova_. Já que `P` é um primo seguro, então pelo \[Teorema de Lagrange\]\[lagrange\] temos que a ordem de `x` é `1`, `2`, `(P-1)/2` ou `P-1`. +_Prova_. Como `P` é um primo seguro, então, pelo [Teorema de Lagrange][lagrange], temos que a ordem de `x` é `1`, `2`, `(P-1)/2` ou `P-1`. -A ordem de `x` não pode ser `1`, já que pelo Pequeno Teorema de Fermat, nós temos: +A ordem de `x` não pode ser `1`, uma vez que, pelo Pequeno Teorema de Fermat, temos:
xP-1 mod P ≡ 1
-Daí `x` deve ser uma identidade multiplicadora de `Z/nZ`, que é única. Como partimos do princípio de que `x ≠ 1` por suposição, isso não é possível. +Portanto, `x` deve ser uma identidade multiplicativa de `ℤ/nℤ`, que é única. Como assumimos que `x ≠ 1` por suposição, isso não é possível. -A ordem de `x` não pode ser `2` a menos que `x = P-1`, já que isso violaria o princípio de que `P` é primo. +A ordem de `x` não pode ser `2` a menos que `x = P-1`, pois isso violaria o fato de `P` ser primo. -A partir da proposta acima, podemos reconhecer que a iteração `(picker * init) % P` terá um ciclo de comprimento de pelo menos `(P-1)/2`. Isso acontece porque selecionamos `P` para ser um primo seguro aproximadamente igual a uma potência de dois mais alta, e `init` está no intervalo `[2,2**256+1]`. Dada a magnitude de `P`, nunca deveríamos esperar um ciclo da exponenciação modular. +A partir da proposição acima, podemos reconhecer que a iteração de `(picker * init) % P` terá um comprimento de ciclo de pelo menos `(P-1)/2`. Isso ocorre porque selecionamos `P` para ser um primo seguro aproximadamente igual a uma potência de dois mais alta, e `init` está no intervalo `[2,2**256+1]`. Dada a magnitude de `P`, nunca devemos esperar um ciclo da exponenciação modular. -Quando estamos atribuindo a primeira célula no DAG (a variável rotulada como `init`), nós computamos `pow (sha3(seed) + 2, 3, P)`. À primeira vista, isso não garante que o resultado não é `1` nem `P-1`. No entanto, como `P-1` é um primo seguro, temos a seguinte garantia adicional, que é uma afirmação deduzida da Observação 1: +Quando estamos atribuindo a primeira célula no DAG (a variável rotulada `init`), nós computamos `pow(sha3(seed) + 2, 3, P)`. À primeira vista, isso não garante que o resultado não seja nem `1` nem `P-1`. No entanto, como `P-1` é um primo seguro, temos a seguinte garantia adicional, que é um corolário da Observação 1: -> Observação 2. Deixe `x` ser um membro do grupo multiplicador `Z/PZ` para um `P` primo seguro, e deixe `w` ser um número natural. Se `x mod P ≠ 1 mod P` e `x mod P ≠ P-1 mod P`, assim como `w mod P ≠ P-1 mod P` e `w mod P ≠ 0 mod P`, então `xʷ mod P ≠ 1 mod P` e `xʷ mod P ≠ P-1 mod P` +> Observação 2. Seja `x` um membro do grupo multiplicativo `ℤ/Pℤ` para um primo seguro `P`, e seja `w` um número natural. Se `x mod P ≠ 1 mod P` e `x mod P ≠ P-1 mod P`, bem como `w mod P ≠ P-1 mod P` e `w mod P ≠ 0 mod P`, então `xʷ mod P ≠ 1 mod P` e `xʷ mod P ≠ P-1 mod P` -### Exponenciação modular como uma função hash {#modular-exponentiation} +### Exponenciação modular como uma função de hash {#modular-exponentiation} -Para certos valores de `P` e `w`, a função `pow(x, w, P)` pode ter muitas colisões. Por exemplo, `pow(x,9,19)` recebe apenas valores `{1,18}`. +Para certos valores de `P` e `w`, a função `pow(x, w, P)` pode ter muitas colisões. Por exemplo, `pow(x,9,19)` só assume os valores `{1,18}`. -Dado que `P` é primo, então um `w` apropriado para uma função hash de exponenciação modular pode ser escolhida usando o seguinte resultado: +Dado que `P` é primo, um `w` apropriado para uma função de hashing de exponenciação modular pode ser escolhido usando o seguinte resultado: -> Observação 3. Considere `P` um primo; `w` e `P-1` são relativamente primos, se e somente se para todos `a` e `b` em `Z/PZ`: -> ->
-> `aʷ mod P ≡ bʷ mod P` se e somente se `a mod P ≡ b mod P` ->
+> Observação 3. Seja `P` um primo; `w` e `P-1` são primos entre si se, e somente se, para todo `a` e `b` em `ℤ/Pℤ`:
`aʷ mod P ≡ bʷ mod P` se e somente se `a mod P ≡ b mod P`
-Assim, dado que `P` é primo e `w` é relativamente primo de `P-1`, temos que `|{pow(x, w, P) : x ∈ ℤ}| = P`, implicando que a função tem a taxa mínima de colisão possível. +Assim, dado que `P` é primo e `w` é primo em relação a `P-1`, temos que `|{pow(x, w, P) : x ∈ ℤ}| = P`, o que implica que a função de hashing tem a taxa de colisão mínima possível. -No caso especial que `P` é um primo seguro como selecionamos, então `P-1` só tem fatores 1, 2, `(P-1)/2` e `P-1`. Como `P` > 7, sabemos que 3 é relativamente primo de `P-1`, daí `w=3` satisfaz a proposta acima. +No caso especial em que `P` é um primo seguro, como o que selecionamos, `P-1` tem apenas os fatores 1, 2, `(P-1)/2` e `P-1`. Como `P` > 7, sabemos que 3 é primo em relação a `P-1`, portanto `w=3` satisfaz a proposição acima. -## Algoritmo de avaliação baseado em cache mais eficiente {#cache-based-evaluation} +## Algoritmo de avaliação mais eficiente baseado em cache {#cache-based-evaluation} ```python def quick_calc(params, seed, p): diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/ethash/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/ethash/index.md index 80acd9a4c94..55bd00f8917 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/ethash/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/ethash/index.md @@ -1,6 +1,6 @@ --- title: Ethash -description: O algoritmo de mineração Ethash em detalhes +description: "O algoritmo de mineração Ethash em detalhes" lang: pt-br --- @@ -8,12 +8,12 @@ lang: pt-br - Ethash foi o algoritmo de mineração da prova de trabalho do Ethereum. A prova de trabalho foi agora **totalmente desativada** e o Ethereum agora está protegido usando a [prova de participação](/developers/docs/consensus-mechanisms/pos/). Leia mais sobre [A Fusão](/roadmap/merge/) (The Merge), [prova de participação](/developers/docs/consensus-mechanisms/pos/) e [participação (stake)](/staking/). Esta página é de interesse histórico! + Ethash foi o algoritmo de mineração da prova de trabalho do Ethereum. A prova de trabalho foi **totalmente desativada** e o Ethereum agora é protegido usando a [prova de participação](/developers/docs/consensus-mechanisms/pos/) em vez disso. Leia mais sobre [The Merge](/roadmap/merge/), [proof-of-stake](/developers/docs/consensus-mechanisms/pos/) e [staking](/staking/). Esta página é de interesse histórico! -Ethash é uma versão modificada do algoritmo [Dagger-Hashimoto](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto). A prova de trabalho Ethash faz uso de [muita memória](https://wikipedia.org/wiki/Memory-hard_function), o que foi pensado para tornar o algoritmo ASIC resistente. Os ASICs Ethash foram eventualmente desenvolvidos, mas a mineração de GPU ainda era uma opção viável até que a prova de trabalho fosse desativada. Ethash ainda é usado para minerar outras moedas em outras redes de prova de trabalho não Ethereum. +Ethash é uma versão modificada do algoritmo [Dagger-Hashimoto](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto). A prova de trabalho do Ethash tem [uso intensivo de memória](https://wikipedia.org/wiki/Memory-hard_function), o que se pensava que tornaria o algoritmo resistente a ASICs. Os ASICs Ethash foram eventualmente desenvolvidos, mas a mineração de GPU ainda era uma opção viável até que a prova de trabalho fosse desativada. Ethash ainda é usado para minerar outras moedas em outras redes de prova de trabalho não Ethereum. ## Como o Ethash funciona? {#how-does-ethash-work} @@ -21,9 +21,9 @@ Dificuldade de memória é alcançada com um algoritmo de prova de trabalho que A rota geral que o algoritmo faz é a seguinte: -1. Existe uma **seed** que pode ser calculada para cada bloco escaneando os cabeçalhos dos blocos até esse ponto. -2. Da seed, pode-se calcular um **cache pseudo-randômico de 16 MB**. Clientes leves armazenam o cache. -3. A partir do cache, podemos gerar um **conjunto de dados de 1 GB**, com a propriedade que cada item no conjunto de dados depende de apenas um pequeno número de itens do cache. Clientes e mineradores completos armazenam o conjunto de dados. O conjunto de dados cresce linearmente com o tempo. +1. Existe uma **seed** que pode ser calculada para cada bloco, escaneando os cabeçalhos do bloco até esse ponto. +2. A partir da seed, pode-se calcular um **cache pseudoaleatório de 16 MB**. Clientes leves armazenam o cache. +3. A partir do cache, podemos gerar um **conjunto de dados de 1 GB**, com a propriedade de que cada item no conjunto de dados depende de apenas um pequeno número de itens do cache. Clientes e mineradores completos armazenam o conjunto de dados. O conjunto de dados cresce linearmente com o tempo. 4. Mineração envolve pegar fatias aleatórias do conjunto de dados e fazer hashing deles juntos. A verificação pode ser feita com pouca memória usando o cache para regenerar os pedaços específicos do conjunto de dados que você precisa, então você só precisa armazenar o cache. O grande conjunto de dados é atualizado uma vez a cada 30.000 blocos, então o maior esforço de um minerador é ler o conjunto de dados, e não fazer alterações nele. @@ -33,23 +33,26 @@ O grande conjunto de dados é atualizado uma vez a cada 30.000 blocos, então o Nós empregamos as seguintes definições: ``` -WORD_BYTES = 4 # bytes in word -DATASET_BYTES_INIT = 2**30 # bytes in dataset at genesis -DATASET_BYTES_GROWTH = 2**23 # dataset growth per epoch -CACHE_BYTES_INIT = 2**24 # bytes in cache at genesis -CACHE_BYTES_GROWTH = 2**17 # cache growth per epoch -CACHE_MULTIPLIER=1024 # Size of the DAG relative to the cache -EPOCH_LENGTH = 30000 # blocks per epoch -MIX_BYTES = 128 # width of mix -HASH_BYTES = 64 # hash length in bytes -DATASET_PARENTS = 256 # number of parents of each dataset element -CACHE_ROUNDS = 3 # number of rounds in cache production -ACCESSES = 64 # number of accesses in hashimoto loop +WORD_BYTES = 4 # bytes em palavra +DATASET_BYTES_INIT = 2**30 # bytes no conjunto de dados na gênese +DATASET_BYTES_GROWTH = 2**23 # crescimento do conjunto de dados por época +CACHE_BYTES_INIT = 2**24 # bytes em cache na gênese +CACHE_BYTES_GROWTH = 2**17 # crescimento do cache por época +CACHE_MULTIPLIER=1024 # Tamanho do DAG em relação ao cache +EPOCH_LENGTH = 30000 # blocos por época +MIX_BYTES = 128 # largura da mistura +HASH_BYTES = 64 # comprimento do hash em bytes +DATASET_PARENTS = 256 # número de pais de cada elemento do conjunto de dados +CACHE_ROUNDS = 3 # número de rodadas na produção de cache +ACCESSES = 64 # número de acessos no loop hashimoto ``` ### O uso de 'SHA3' {#sha3} -O desenvolvimento do Ethereum coincidiu com o desenvolvimento do padrão SHA3, e o processo de padrões fez uma alteração tardia no preenchimento do algoritmo de hash finalizado, para que os hashes "sha3_256" e "sha3_512" do Ethereum não sejam hashes sha3 padrão, mas uma variante muitas vezes referida como "Keccak-256" e "Keccak-512" em outros contextos. Veja a discussão, por exemplo, [aqui](https://eips.ethereum.org/EIPS/eip-1803), [aqui](http://ethereum.stackexchange.com/questions/550/which-cryptographic-hash-function-does-ethereum-use) ou [aqui](http://bitcoin.stackexchange.com/questions/42055/what-is-the-approach-to-calculate-an-ethereum-address-from-a-256-bit-private-key/42057#42057). +O desenvolvimento do Ethereum coincidiu com o desenvolvimento do padrão SHA3, e o processo de padrões +fez uma alteração tardia no preenchimento do algoritmo de hash finalizado, para que os hashes +"sha3_256" e "sha3_512" do Ethereum não sejam hashes sha3 padrão, mas uma variante muitas vezes referida +como "Keccak-256" e "Keccak-512" em outros contextos. Veja a discussão, p. ex., [aqui](https://eips.ethereum.org/EIPS/eip-1803), [aqui](http://ethereum.stackexchange.com/questions/550/which-cryptographic-hash-function-does-ethereum-use), ou [aqui](http://bitcoin.stackexchange.com/questions/42055/what-is-the-approach-to-calculate-an-ethereum-address-from-a-256-bit-private-key/42057#42057). Tenha isso em mente, já que hashes "sha3" são referidos na descrição do algoritmo abaixo. @@ -83,12 +86,12 @@ Agora, especificamos a função para produzir um cache: def mkcache(cache_size, seed): n = cache_size // HASH_BYTES - # Sequentially produce the initial dataset + # Produzir sequencialmente o conjunto de dados inicial o = [sha3_512(seed)] for i in range(1, n): o.append(sha3_512(o[-1])) - # Use a low-round version of randmemohash + # Usar uma versão de poucas rodadas do randmemohash for _ in range(CACHE_ROUNDS): for i in range(n): v = o[i][0] % n @@ -97,11 +100,11 @@ def mkcache(cache_size, seed): return o ``` -O processo de produção de cache envolve primeiro preenchimento sequencial de 32 MB de memória e depois executar duas passagens do algoritmo _RandMemoHash_ de Sergio Demian Lerner de [_Strict Memory Hard Hashing Functions_ (2014)](http://www.hashcash.org/papers/memohash.pdf). A saída é um conjunto de 524288 valores de 64-bytes. +O processo de produção de cache envolve primeiro preencher sequencialmente 32 MB de memória e, em seguida, realizar duas passagens do algoritmo _RandMemoHash_ de Sergio Demian Lerner de [_Strict Memory Hard Hashing Functions_ (2014)](http://www.hashcash.org/papers/memohash.pdf). A saída é um conjunto de 524288 valores de 64-bytes. ## Função de agregação de dados {#date-aggregation-function} -Usamos um algoritmo inspirado no [FNV hash](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function) em alguns casos como um substituto não associativo para o XOR. Observe que multiplicamos o primo com a entrada completa de 32 bits, em contraste com a especificação FNV-1 que multiplica o primo por um byte (octeto) por sua vez. +Usamos um algoritmo inspirado no [hash FNV](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function) em alguns casos como um substituto não associativo para XOR. Observe que multiplicamos o primo com a entrada completa de 32 bits, em contraste com a especificação FNV-1 que multiplica o primo por um byte (octeto) por sua vez. ```python FNV_PRIME = 0x01000193 @@ -120,11 +123,11 @@ Cada item de 64 bytes no conjunto de dados completo de 1 GB é calculado da segu def calc_dataset_item(cache, i): n = len(cache) r = HASH_BYTES // WORD_BYTES - # initialize the mix + # inicializar a mistura mix = copy.copy(cache[i % n]) mix[0] ^= i mix = sha3_512(mix) - # fnv it with a lot of random cache nodes based on i + # aplicar fnv com muitos nós de cache aleatórios com base em i for j in range(DATASET_PARENTS): cache_index = fnv(i ^ j, mix[j % r]) mix = map(fnv, mix, cache[cache_index % n]) @@ -140,27 +143,27 @@ def calc_dataset(full_size, cache): ## Loop principal {#main-loop} -Agora, especificamos o loop padrão "hashimoto" principal, onde agregamos dados do conjunto de dados completo para produzir nosso valor final para um cabeçalho em particular ou nonce. No código abaixo, `header` representa o _hash _SHA3-256 da representação RLP de um cabeçalho de bloco _truncado_, ou seja, de um cabeçalho excluindo os campos **mixHash** e **nonce**. `nonce` é os oito bytes de um inteiro sem sinal de 64 bits na ordem big-endian. Então `nonce[::-1]` é a representação little-endian de oito bytes desse valor: +Agora, especificamos o loop padrão "hashimoto" principal, onde agregamos dados do conjunto de dados completo para produzir nosso valor final para um cabeçalho em particular ou nonce. No código abaixo, `header` representa o _hash_ SHA3-256 da representação RLP de um cabeçalho de bloco _truncado_, ou seja, de um cabeçalho que exclui os campos **mixHash** e **nonce**. `nonce` são os oito bytes de um inteiro sem sinal de 64 bits em ordem big-endian. Então, `nonce[::-1]` é a representação little-endian de oito bytes desse valor: ```python def hashimoto(header, nonce, full_size, dataset_lookup): n = full_size / HASH_BYTES w = MIX_BYTES // WORD_BYTES mixhashes = MIX_BYTES / HASH_BYTES - # combine header+nonce into a 64 byte seed + # combinar header+nonce em uma seed de 64 bytes s = sha3_512(header + nonce[::-1]) - # start the mix with replicated s + # iniciar a mistura com s replicado mix = [] for _ in range(MIX_BYTES / HASH_BYTES): mix.extend(s) - # mix in random dataset nodes + # misturar em nós de conjunto de dados aleatórios for i in range(ACCESSES): p = fnv(i ^ s[0], mix[i % w]) % (n // mixhashes) * mixhashes newdata = [] for j in range(MIX_BYTES / HASH_BYTES): newdata.extend(dataset_lookup(p + j)) mix = map(fnv, mix, newdata) - # compress mix + # comprimir mistura cmix = [] for i in range(0, len(mix), 4): cmix.append(fnv(fnv(fnv(mix[i], mix[i+1]), mix[i+2]), mix[i+3])) @@ -176,9 +179,9 @@ def hashimoto_full(full_size, dataset, header, nonce): return hashimoto(header, nonce, full_size, lambda x: dataset[x]) ``` -Essencialmente, mantemos um "mix" de 128 bytes de largura, e de maneira sequencial e repetida buscamos 128 bytes do conjunto de dados completo e usamos a função `fnv` para combiná-lo com o mix. 128 bytes de acesso sequencial são usados para que cada rodada do algoritmo sempre busque uma página inteira de RAM, minimizando a possibilidade de que o buffer de pesquisa de tradução perca o que os ASICs teoricamente seriam capazes de evitar. +Essencialmente, mantemos um "mix" de 128 bytes de largura e, de maneira sequencial e repetida, buscamos 128 bytes do conjunto de dados completo e usamos a função `fnv` para combiná-lo com o mix. 128 bytes de acesso sequencial são usados para que cada rodada do algoritmo sempre busque uma página inteira de RAM, minimizando a possibilidade de que o buffer de pesquisa de tradução perca o que os ASICs teoricamente seriam capazes de evitar. -Se a saída deste algoritmo está abaixo do alvo desejado, então o nonce é válido. Observe que a aplicação extra de `sha3_256` no final garante que existe um nonce intermediário que pode ser fornecido para provar que pelo menos uma pequena quantidade de trabalho foi feita; esta rápida verificação de prova de trabalho pode ser usada para fins anti-DDoS. Serve também para dar garantias estatísticas de que o resultado é um número imparcial de 256 bits. +Se a saída deste algoritmo está abaixo do alvo desejado, então o nonce é válido. Observe que a aplicação extra de `sha3_256` no final garante que existe um nonce intermediário que pode ser fornecido para provar que pelo menos uma pequena quantidade de trabalho foi feita; esta verificação rápida de PoW externa pode ser usada para fins anti-DDoS. Serve também para dar garantias estatísticas de que o resultado é um número imparcial de 256 bits. ## Mineração {#mining} @@ -186,7 +189,7 @@ O algoritmo de mineração é definido da seguinte forma: ```python def mine(full_size, dataset, header, difficulty): - # zero-pad target to compare with hash on the same digit + # preencher com zeros o alvo para comparar com o hash no mesmo dígito target = zpad(encode_int(2**256 // difficulty), 64)[::-1] from random import randint nonce = randint(0, 2**64) @@ -195,7 +198,7 @@ def mine(full_size, dataset, header, difficulty): return nonce ``` -## Definição do hash seed {#seed-hash} +## Definindo o hash da seed {#seed-hash} Para calcular o hash seed que seria usado para minerar no topo de um determinado bloco, usamos o seguinte algoritmo: @@ -211,7 +214,7 @@ Observe que, para que a mineração e a verificação aconteçam sem contratempo ## Leitura adicional {#further-reading} -_Conhece algum recurso da comunidade que o ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ ## Apêndice {#appendix} @@ -220,7 +223,7 @@ O código a seguir deve ser precedido se você estiver interessado em executar a ```python import sha3, copy -# Assumes little endian bit ordering (same as Intel architectures) +# Assume a ordem de bits little endian (a mesma das arquiteturas Intel) def decode_int(s): return int(s[::-1].encode('hex'), 16) if s else 0 @@ -248,7 +251,7 @@ def serialize_cache(ds): serialize_dataset = serialize_cache -# sha3 hash function, outputs 64 bytes +# função de hash sha3, produz 64 bytes def sha3_512(x): return hash_words(lambda v: sha3.sha3_512(v).digest(), 64, x) @@ -265,7 +268,7 @@ def isprime(x): return True ``` -### Tamanho dos dados {#data-sizes} +### Tamanhos dos Dados {#data-sizes} As tabelas de pesquisa a seguir fornecem aproximadamente 2.048 períodos eletrônicos (epoch) tabulados de tamanhos de dados e tamanhos de cache. @@ -993,7 +996,7 @@ cache_sizes = [ 265287488, 265418432, 265550528, 265681216, 265813312, 265943488, 266075968, 266206144, 266337728, 266468032, 266600384, 266731072, 266862272, 266993344, 267124288, 267255616, 267386432, 267516992, -267648704, 267777728, 267910592, 268040512, 268172096, 268302784, +267648704, 26777728, 267910592, 268040512, 268172096, 268302784, 268435264, 268566208, 268696256, 268828096, 268959296, 269090368, 269221312, 269352256, 269482688, 269614784, 269745856, 269876416, 270007616, 270139328, 270270272, 270401216, 270531904, 270663616, diff --git a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/index.md b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/index.md index 1ef0b1ea911..9fddd7cb895 100644 --- a/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/index.md +++ b/public/content/translations/pt-br/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/index.md @@ -1,6 +1,6 @@ --- -title: Algoritmos de mineração -description: Os algoritmos usados para mineração Ethereum +title: "Algoritmos de mineração" +description: "Os algoritmos usados para mineração Ethereum" lang: pt-br --- @@ -8,24 +8,24 @@ lang: pt-br -A prova de trabalho não está mais subjacente ao mecanismo de consenso do Ethereum, o que significa que a mineração foi desativada. Em vez disso, o Ethereum é garantido por validadores que apostam em ETH. Você pode começar a fazer o staking do seu ETH hoje. Leia mais sobre A Fusão (The MErge), prova de participação e participação (stake). Esta página é apenas de interesse histórico. +A prova de trabalho não está mais subjacente ao mecanismo de consenso do Ethereum, o que significa que a mineração foi desativada. Em vez disso, o Ethereum é garantido por validadores que apostam em ETH. Você pode começar a participar com o seu ETH hoje. Leia mais sobre A Fusão (The Merge), prova de participação e participação (stake). Esta página é apenas de interesse histórico. A mineração Ethereum usou um algoritmo conhecido como Ethash. A ideia fundamental do algoritmo é que um minerador tente encontrar uma entrada de nonce usando a computação de força bruta, para que o hash resultante seja menor que um limite determinado pela dificuldade calculada. Esse nível de dificuldade pode ser ajustado dinamicamente, permitindo que a produção de blocos ocorra em intervalos regulares. -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -Para entender melhor esta página, recomendamos que você leia primeiro sobre o [consenso da prova de trabalho](/developers/docs/consensus-mechanisms/pow) e a [mineração](/developers/docs/consensus-mechanisms/pow/mining). +Para entender melhor esta página, recomendamos que você leia primeiro sobre o [consenso de prova de trabalho](/developers/docs/consensus-mechanisms/pow) e a [mineração](/developers/docs/consensus-mechanisms/pow/mining). ## Dagger Hashimoto {#dagger-hashimoto} Dagger Hashimoto foi um algoritmo de pesquisa precursor para mineração Ethereum que Ethash substituiu. Era uma fusão de dois algoritmos diferentes: Dagger e Hashimoto. Foi apenas uma implementação de pesquisa e foi substituída pelo Ethash no momento em que a rede principal do Ethereum foi lançada. -[Dagger](http://www.hashcash.org/papers/dagger.html) envolve a geração de um [Grafo Acíclico Direcionado](https://en.wikipedia.org/wiki/Directed_acyclic_graph), cujas fatias aleatórias do hash são feitas juntas. O princípio central é que cada nonce requer apenas uma pequena porção de uma grande árvore de dados total. Recomputar a subárvore para cada nonce é proibitivo para a mineração – daí a necessidade de armazenar a árvore – mas tudo bem para uma única verificação de valor do nonce. O Dagger foi projetado para ser uma alternativa aos algoritmos existentes como o Scrypt, que fazem uso intenso de memória, mas que são difíceis de verificar conforme a utilização de memória aumenta para níveis genuinamente seguros. No entanto, Dagger era vulnerável à aceleração de hardware de memória compartilhada e caiu em favor de outras vias de pesquisa. +[Dagger](http://www.hashcash.org/papers/dagger.html) envolve a geração de um [Grafo Acíclico Dirigido](https://en.wikipedia.org/wiki/Directed_acyclic_graph), cujas fatias aleatórias são combinadas por hash. O princípio central é que cada nonce requer apenas uma pequena porção de uma grande árvore de dados total. Recomputar a subárvore para cada nonce é proibitivo para a mineração – daí a necessidade de armazenar a árvore – mas tudo bem para uma única verificação de valor do nonce. O Dagger foi projetado para ser uma alternativa aos algoritmos existentes como o Scrypt, que fazem uso intenso de memória, mas que são difíceis de verificar conforme a utilização de memória aumenta para níveis genuinamente seguros. No entanto, Dagger era vulnerável à aceleração de hardware de memória compartilhada e caiu em favor de outras vias de pesquisa. -[Hashimoto](http://diyhpl.us/%7Ebryan/papers2/bitcoin/meh/hashimoto.pdf) é um algoritmo que adiciona resistência ASIC ao ser vinculado à E/S (ou seja, leituras de memória são o fator limitante no processo de mineração). A teoria é que a RAM está mais disponível do que a computação; bilhões de dólares em pesquisas já investigaram a otimização de RAM para diferentes casos de uso, o que geralmente envolvem padrões de acesso quase aleatórios (daí “memória de acesso aleatório”). Como resultado, é provável que a memória RAM existente esteja moderadamente próxima do ideal para avaliar o algoritmo. Hashimoto usa a blockchain como fonte de dados, satisfazendo simultaneamente (1) e (3) acima. +[Hashimoto](http://diyhpl.us/%7Ebryan/papers2/bitcoin/meh/hashimoto.pdf) é um algoritmo que adiciona resistência a ASICs por ser vinculado a E/S (isto é, as leituras de memória são o fator limitante no processo de mineração). A teoria é que a RAM está mais disponível do que a computação; bilhões de dólares em pesquisas já investigaram a otimização de RAM para diferentes casos de uso, o que geralmente envolvem padrões de acesso quase aleatórios (daí “memória de acesso aleatório”). Como resultado, é provável que a memória RAM existente esteja moderadamente próxima do ideal para avaliar o algoritmo. Hashimoto usa a blockchain como fonte de dados, satisfazendo simultaneamente (1) e (3) acima. Dagger-Hashimoto usou versões modificadas dos algoritmos Dagger e Hashimoto. A diferença entre Dagger Hashimoto e Hashimoto é que, ao invés de usar a blockchain como fonte de dados, o Dagger Hashimoto usa um conjunto de dados gerados de forma personalizada, que atualiza com base nos dados do bloco a cada N blocos. O conjunto de dados é gerado usando o algoritmo Dagger, permitindo calcular com eficiência um subconjunto específico para cada nonce para o algoritmo de verificação de cliente leve. A diferença entre Dagger Hashimoto e Dagger é que, ao contrário do Dagger original, o conjunto de dados usado para consultar o bloco é semipermanente, sendo atualizado apenas em intervalos ocasionais (por exemplo, uma vez por semana). Isso significa que a porção do esforço de geração do conjunto de dados é próxima de zero, de modo que os argumentos de Sergio Lerner a respeito das acelerações de memória compartilhada tornam-se insignificantes. @@ -33,9 +33,9 @@ Mais sobre [Dagger-Hashimoto](/developers/docs/consensus-mechanisms/pow/mining/m ## Ethash {#ethash} -Ethash foi o algoritmo de mineração, que na verdade foi usado na rede principal Ethereum real, sob a agora obsoleta arquitetura de prova de trabalho. Ethash foi efetivamente um novo nome dado a uma versão específica do Dagger-Hashimoto depois que o algoritmo foi significativamente atualizado, enquanto ainda herdava os princípios fundamentais de seu antecessor. A Rede principal do Ethereum só utilizou o Ethash. Dagger Hashimoto era uma versão de pesquisa e desenvolvimento do algoritmo de mineração que foi substituído antes do início da mineração na Rede principal do Ethereum. +Ethash foi o algoritmo de mineração, que na verdade foi usado na rede principal Ethereum real, sob a agora obsoleta arquitetura de prova de trabalho. Ethash foi efetivamente um novo nome dado a uma versão específica do Dagger-Hashimoto depois que o algoritmo foi significativamente atualizado, enquanto ainda herdava os princípios fundamentais de seu antecessor. A Rede Principal do Ethereum só utilizou o Ethash. O Dagger Hashimoto era uma versão de pesquisa e desenvolvimento do algoritmo de mineração que foi substituído antes do início da mineração na Rede Principal do Ethereum. -[Mais sobre Ethash](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/ethash). +[Mais sobre o Ethash](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/ethash). ## Leitura adicional {#further-reading} diff --git a/public/content/translations/pt-br/developers/docs/dapps/index.md b/public/content/translations/pt-br/developers/docs/dapps/index.md index 0e3bcc4e169..f48548f24cb 100644 --- a/public/content/translations/pt-br/developers/docs/dapps/index.md +++ b/public/content/translations/pt-br/developers/docs/dapps/index.md @@ -1,47 +1,47 @@ --- -title: Introdução à aplicativos descentralizados (dapps) +title: "Introdução Técnica aos dapps" description: lang: pt-br --- -Um aplicativo descentralizado (dapp) é um aplicativo construído em uma rede descentralizada que combina um [contrato inteligente](/developers/docs/smart-contracts/) e uma interface de usuário de front-end. Observe que no Ethereum os contratos inteligentes são acessíveis e transparentes – como APIs abertas — então, seu dapp pode até incluir um contrato inteligente que outra pessoa escreveu. +Um aplicativo descentralizado (dapp) é um aplicativo criado em uma rede descentralizada que combina um [contrato inteligente](/developers/docs/smart-contracts/) e uma interface de usuário de front-end. Observe que no Ethereum os contratos inteligentes são acessíveis e transparentes – como APIs abertas — então, seu dapp pode até incluir um contrato inteligente que outra pessoa escreveu. ## Pré-requisitos {#prerequisites} -Antes de aprender sobre dapps, você deve entender sobre os [fundamentos da blockchain](/developers/docs/intro-to-ethereum/), ler sobre a rede Ethereum e como ela é descentralizada. +Antes de aprender sobre dapps, você deve entender sobre os fundamentos da blockchain, ler sobre a [rede Ethereum](/developers/docs/intro-to-ethereum/) e como ela é descentralizada. -## Definição de dapp {#definition-of-a-dapp} +## Definição de um dapp {#definition-of-a-dapp} Um dapp tem seu código de back-end em execução em uma rede peer-to-peer descentralizada. Contraste isso com um aplicativo no qual o código de back-end está sendo executado em servidores centralizados. -Um dapp pode ter código front-end e interfaces de usuário escritas em qualquer linguagem (como um aplicativo) que podem fazer chamadas para seu back-end. Além disso, o front-end dele pode ser hospedado em um sistema de armazenamento descentralizado, como [IPFS](https://ipfs.io/). +Um dapp pode ter código front-end e interfaces de usuário escritas em qualquer linguagem (como um aplicativo) que podem fazer chamadas para seu back-end. Além disso, seu front-end pode ser hospedado em armazenamento descentralizado, como o [IPFS](https://ipfs.io/). -- **Descentralizado**: os dapps operam no Ethereum, uma plataforma descentralizada pública aberta onde ninguém ou grupo tem controle -- **Determinista** ou seja, eles desempenham a mesma função independentemente do ambiente em que são executados. -- **Turing completo**: os dapps podem executar qualquer ação, dados os recursos necessários -- **Isolado**: significa que eles são executados em um ambiente virtual conhecido como Ethereum Virtual Machine para que, se o contrato inteligente tiver um bug, não dificultará o funcionamento normal da rede blockchain +- **Descentralizado** – os dapps operam no Ethereum, uma plataforma pública descentralizada e aberta, onde nenhuma pessoa ou grupo tem controle +- **Determinístico** – os dapps executam a mesma função, independentemente do ambiente em que são executados +- **Turing completo** – os dapps podem executar qualquer ação, considerando os recursos necessários +- **Isolado** – os dapps são executados em um ambiente virtual conhecido como Máquina Virtual Ethereum para que, se o contrato inteligente tiver um bug, ele não prejudique o funcionamento normal da rede blockchain ### Sobre contratos inteligentes {#on-smart-contracts} -Para introduzir dapps, precisamos introduzir contratos inteligentes (que são dapps de back-end, para assim dizer). Para obter uma visão geral detalhada, vá para a nossa seção sobre [ contratos inteligentes](/developers/docs/smart-contracts/). +Para introduzir dapps, precisamos introduzir contratos inteligentes (que são dapps de back-end, para assim dizer). Para uma visão geral detalhada, acesse nossa seção sobre [contratos inteligentes](/developers/docs/smart-contracts/). Um contrato inteligente é um código presente na blockchain Ethereum e funciona exatamente como programado. Uma vez que eles são implantados na rede, você não pode alterá-los. Os dapps podem ser descentralizados porque são controlados pela lógica escrita no contrato, não por um indivíduo ou empresa. Isso também significa que você precisa projetar seus contratos com muito cuidado e testá-los cuidadosamente. ## Benefícios do desenvolvimento de dapps {#benefits-of-dapp-development} -- **Zero tempo de inatividade**: uma vez que o contrato inteligente é implementado na base de um aplicativo e na blockchain, a rede como um todo sempre será capaz de atender clientes que procuram interagir com o contrato. Os atores mal-intencionados, portanto, não podem lançar ataques de negação de serviço direcionados a dapps individuais. -- **Privacidade**: você não precisa fornecer identidade real para implantar ou interagir com um dapp. -- **Resistância à censura**: nenhuma entidade na rede pode impedir que os usuários enviem transações, implantem dapps ou leiam dados da blockchain. -- **Completar a integridade dos dados**: os dados armazenados na blockchain são imutáveis e indiscutíveis, graças aos primitivos criptográficos. Atores mal-intencionados não podem forjar transações ou outros dados que já foram tornados públicos. -- **Computação sem confiança/comportamento verificável** – Contratos inteligentes podem ser analisados e têm garantia de execução de maneiras previsíveis, sem a necessidade de confiar em uma autoridade central. Isso não é verdade nos modelos tradicionais; por exemplo, quando usamos sistemas bancários on-line, temos que confiar que as instituições financeiras não usarão indevidamente nossos dados financeiros, adulterarão registros ou serão hackeadas. +- **Tempo de inatividade zero** – uma vez que o contrato inteligente é implantado na blockchain, a rede como um todo sempre será capaz de atender aos clientes que procuram interagir com o contrato. Os atores mal-intencionados, portanto, não podem lançar ataques de negação de serviço direcionados a dapps individuais. +- **Privacidade** – Você não precisa fornecer uma identidade do mundo real para implantar ou interagir com um dapp. +- **Resistência à censura** – Nenhuma entidade única na rede pode impedir que os usuários enviem transações, implantem dapps ou leiam dados da blockchain. +- **Integridade total dos dados** – Os dados armazenados na blockchain são imutáveis e indisputáveis, graças às primitivas criptográficas. Atores mal-intencionados não podem forjar transações ou outros dados que já foram tornados públicos. +- **Computação sem confiança/comportamento verificável** – Contratos inteligentes podem ser analisados e têm a garantia de serem executados de maneiras previsíveis, sem a necessidade de confiar em uma autoridade central. Isso não é verdade nos modelos tradicionais; por exemplo, quando usamos sistemas bancários on-line, temos que confiar que as instituições financeiras não usarão indevidamente nossos dados financeiros, adulterarão registros ou serão hackeadas. ## Desvantagens do desenvolvimento de dapps {#drawbacks-of-dapp-development} -- **Manutenção**: os dapps podem ser mais difíceis de manter, porque o código e os dados publicados na blockchain são mais difíceis de modificar. É difícil para os desenvolvedores fazerem atualizações em seus dapps (ou nos dados armazenados sob um dapp) uma vez que eles foram implantados, mesmo se bugs ou riscos de segurança forem identificados em uma versão antiga. -- **Impactos no desempenho**: há um grande impacto no desempenho, e o dimensionamento é realmente difícil. Para alcançar o nível de segurança, integridade, transparência e confiabilidade que o Ethereum aspira, cada nó executa e armazena cada transação. Além disso, o consenso de prova de participação também leva tempo. -- **Congestionamento da rede **: pelo menos no modelo atual, se um dapp estiver usando muitos recursos computacionais, toda a rede é apoiada. Atualmente, a rede só é capaz de processar cerca de 10 transações por segundo; se as transações estiverem sendo enviadas mais rápido do que isso, o pool de transações não confirmadas poderá aumentar rapidamente. -- **Experiência do usuário**: pode ser mais difícil projetar experiências amigáveis ao usuário porque o usuário final pode achar muito difícil configurar uma pilha de ferramentas necessária para interagir com a blockchain de uma forma verdadeiramente segura. -- **Centralização**: soluções amigáveis para o usuário e amigáveis ao desenvolvedor construídas sobre a camada base do Ethereum podem acabar parecendo serviços centralizados. Por exemplo, tais serviços podem armazenar chaves ou outros pontos sensíveis do servidor de informações, servir um front-end usando um servidor centralizado ou executar uma lógica de negócios importante em um servidor centralizado antes de escrever na blockchain. A centralização elimina muitas (se não todas) das vantagens da blockchain sobre o modelo tradicional. +- **Manutenção** – Pode ser mais difícil manter os Dapps porque o código e os dados publicados na blockchain são mais difíceis de modificar. É difícil para os desenvolvedores fazerem atualizações em seus dapps (ou nos dados armazenados sob um dapp) uma vez que eles foram implantados, mesmo se bugs ou riscos de segurança forem identificados em uma versão antiga. +- **Sobrecarga de desempenho** – Há uma enorme sobrecarga de desempenho, e o dimensionamento é realmente difícil. Para alcançar o nível de segurança, integridade, transparência e confiabilidade que o Ethereum aspira, cada nó executa e armazena cada transação. Além disso, o consenso de prova de participação também leva tempo. +- **Congestionamento da rede** – Quando um dapp usa muitos recursos computacionais, toda a rede fica sobrecarregada. Atualmente, a rede só é capaz de processar cerca de 10 transações por segundo; se as transações estiverem sendo enviadas mais rápido do que isso, o pool de transações não confirmadas poderá aumentar rapidamente. +- **Experiência do usuário** – Pode ser mais difícil projetar experiências fáceis de usar, pois o usuário final médio pode achar muito difícil configurar a pilha de ferramentas necessária para interagir com a blockchain de uma forma verdadeiramente segura. +- **Centralização** – Soluções amigáveis ao usuário e ao desenvolvedor, construídas sobre a camada de base da Ethereum, podem acabar parecendo serviços centralizados de qualquer maneira. Por exemplo, tais serviços podem armazenar chaves ou outros pontos sensíveis do servidor de informações, servir um front-end usando um servidor centralizado ou executar uma lógica de negócios importante em um servidor centralizado antes de escrever na blockchain. A centralização elimina muitas (se não todas) das vantagens da blockchain sobre o modelo tradicional. ## Você é o tipo de pessoa que aprende mais com recursos visuais? {#visual-learner} @@ -49,32 +49,32 @@ Um contrato inteligente é um código presente na blockchain Ethereum e funciona ## Ferramentas para criar dapps {#dapp-tools} -**Scaffold-ETH _: experimente rapidamente com Solidity usando um front-end que se adapta ao seu contrato inteligente._** +**Scaffold-ETH** _– Experimente rapidamente com Solidity usando um front-end que se adapta ao seu contrato inteligente._ - [GitHub](https://github.com/scaffold-eth/scaffold-eth-2) - [Exemplo de dapp](https://punkwallet.io/) -**Crie um aplicativo Eth_: crie aplicativos com a tecnologia Ethereum apenas com um comando._** +**Create Eth App** _– Crie aplicativos baseados em Ethereum com um único comando._ - [GitHub](https://github.com/paulrberg/create-eth-app) -**One Click Dapp _: ferramenta FOSS para gerar front-end de dapp de um [ABI](/glossary/#abi)._** +**One Click Dapp** _– Ferramenta FOSS para gerar front-ends de dapps a partir de uma [ABI](/glossary/#abi)._ - [oneclickdapp.com](https://oneclickdapp.com) - [GitHub](https://github.com/oneclickdapp/oneclickdapp-v1) -**Etherflow _: ferramenta FOSS para desenvolvedores de Ethereum testar seus nós e compor e depurar chamadas RPC do navegador._** +**Etherflow** _– Ferramenta FOSS para desenvolvedores Ethereum testarem seu nó, compor e depurar chamadas RPC a partir do navegador._ - [etherflow.quiknode.io](https://etherflow.quiknode.io/) - [GitHub](https://github.com/abunsen/etherflow) -**thirdweb _- SDKs em todos os idiomas, contratos inteligentes, ferramentas e infraestrutura para o desenvolvimento da web3._** +**thirdweb** _– SDKs em todos os idiomas, contratos inteligentes, ferramentas e infraestrutura para o desenvolvimento da web3._ - [Página inicial](https://thirdweb.com/) - [Documentação](https://portal.thirdweb.com/) - [GitHub](https://github.com/thirdweb-dev/) -**Crossmint - _Plataforma de desenvolvimento web3 de nível empresarial para implantar contratos inteligentes, habilitar pagamentos com cartão de crédito e entre cadeias, e usar APIs para criar, distribuir, vender, armazenar e editar NFTs._** +**Crossmint** _– Plataforma de desenvolvimento web3 de nível empresarial para implantar contratos inteligentes, habilitar pagamentos com cartão de crédito e entre cadeias, e usar APIs para criar, distribuir, vender, armazenar e editar NFTs._ - [crossmint.com](https://www.crossmint.com) - [Documentação](https://docs.crossmint.com) @@ -82,15 +82,15 @@ Um contrato inteligente é um código presente na blockchain Ethereum e funciona ## Leitura adicional {#further-reading} -- [Ver dapps](/apps) -- [A arquitetura de um aplicativo Web 3.0](https://www.preethikasireddy.com/post/the-architecture-of-a-web-3-0-application) - _Preethi Kasireddy_ +- [Explore os dapps](/apps) +- [A Arquitetura de um aplicativo Web 3.0](https://www.preethikasireddy.com/post/the-architecture-of-a-web-3-0-application) - _Preethi Kasireddy_ - [Um guia de 2021 para aplicativos descentralizados](https://limechain.tech/blog/what-are-dapps-the-2021-guide/) - _LimeChain_ - [O que são aplicativos descentralizados?](https://www.gemini.com/cryptopedia/decentralized-applications-defi-dapps) - _Gemini_ - [Dapps populares](https://www.alchemy.com/dapps) - _Alchemy_ -_Conhece um recurso da comunidade que te ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ ## Tópicos relacionados {#related-topics} -- [Introdução à pilha de Ethereum](/developers/docs/ethereum-stack/) -- [Estruturas de desenvolvimento](/developers/docs/frameworks/) +- [Introdução à Pilha de Ethereum](/developers/docs/ethereum-stack/) +- [Frameworks de desenvolvimento](/developers/docs/frameworks/) diff --git a/public/content/translations/pt-br/developers/docs/data-and-analytics/block-explorers/index.md b/public/content/translations/pt-br/developers/docs/data-and-analytics/block-explorers/index.md index 985faa7eeb3..74bf5341e47 100644 --- a/public/content/translations/pt-br/developers/docs/data-and-analytics/block-explorers/index.md +++ b/public/content/translations/pt-br/developers/docs/data-and-analytics/block-explorers/index.md @@ -1,11 +1,11 @@ --- title: Exploradores de bloco -description: Uma introdução aos exploradores de bloco, seu portal no mundo dos dados da blockchain, onde você pode consultar informações sobre transações, contas, contratos e mais. +description: "Uma introdução aos exploradores de bloco, seu portal no mundo dos dados da blockchain, onde você pode consultar informações sobre transações, contas, contratos e mais." lang: pt-br sidebarDepth: 3 --- -Exploradores de blocos são o seu portal para os dados do Ethereum. Você pode usá-los para ver dados em tempo real sobre blocos, transações, validadores, contas e outras atividades on-chain. +Exploradores de blocos são o seu portal para os dados do Ethereum. Você pode usá-los pelos dados atuais dos blocos, transações, validadores, contas e outras atividades on-chain. ## Pré-requisitos {#prerequisites} @@ -13,19 +13,17 @@ Você deve entender os conceitos básicos do Ethereum; para que você possa ente ## Serviços {#services} -- [Etherscan](https://etherscan.io/) -_Também disponível em chinês, coreano, russo e japonês_ +- [Etherscan](https://etherscan.io/) - _Também disponível em chinês, coreano, russo e japonês_ - [3xpl](https://3xpl.com/ethereum) - [Beaconcha.in](https://beaconcha.in/) -- [Blockchair](https://blockchair.com/ethereum) -_ Também disponível em espanhol, francês, italiano, holandês, português, russo, chinês e persa_ +- [Blockchair](https://blockchair.com/ethereum) - _Também disponível em espanhol, francês, italiano, holandês, português, russo, chinês e farsi_ - [Blockscout](https://eth.blockscout.com/) - [Chainlens](https://www.chainlens.com/) - [Explorador de Blocos DexGuru](https://ethereum.dex.guru/) - [Etherchain](https://www.etherchain.org/) -- [Ethernow](https://www.ethernow.xyz/) -- [Ethplorer](https://ethplorer.io/) -_ Também disponível em chinês, espanhol, francês, turco, russo, coreano e vietnamita_ +- [Ethplorer](https://ethplorer.io/) - _Também disponível em chinês, espanhol, francês, turco, russo, coreano e vietnamita_ - [EthVM](https://www.ethvm.com/) - [OKLink](https://www.oklink.com/eth) -- [Rantom](https://rantom.app/) - [Ethseer](https://ethseer.io) ## Ferramentas de código aberto {#open-source-tools} @@ -43,7 +41,7 @@ Aqui está um resumo dos tipos de dados que você pode obter de um explorador de Novos blocos são adicionados à Ethereum a cada 12 segundos (a menos que um proponente de bloco perca a sua vez), então um fluxo quase constante de dados é adicionado aos exploradores de blocos. Os blocos contêm muitos dados importantes que você pode achar úteis: -**Dados padrões** +**Dados padrão** - Altura do bloco - O número do bloco e o comprimento da blockchain (em blocos) na criação do bloco atual - Timestamp - A hora em que um bloco foi proposto @@ -95,7 +93,7 @@ Os exploradores de blocos se tornaram um lugar comum para as pessoas acompanhare - Limite de gás - O número máximo de unidades de gás que esta transação pode consumir - Gás usado - A quantidade real de unidades de gás que a transação consumiu - Preço do gás - O preço estabelecido por unidade de gás -- Nonce - O número da transação para o endereço `de` (tenha em mente que isso começa em 0, então um nonce de `100` seria na verdade a 101 transação enviada por esta conta +- Nonce - O número da transação para o endereço `from` (tenha em mente que isso começa em 0, então um nonce de `100` seria, na verdade, a 101ª transação enviada por esta conta) - Dados de entrada - Quaisquer informações extras necessárias pela transação ### Contas {#accounts} @@ -141,11 +139,11 @@ Alguns dados do bloco estão preocupados com a funcionalidade da Ethereum de for - Total de transações - O número de transações desde a criação da Ethereum - Transações por segundo - O número de transações processáveis em um segundo -- Preço ETH - As avaliações atuais de 1 ETTH +- Preço ETH - As avaliações atuais de 1 ETH - Fornecimento total de ETH – Número de ETH em circulação – lembre-se de que o novo ETH é criado com a criação de cada bloco sob a forma de recompensas por bloco -- Capitalização de mercado - Cálculo do preço \ * oferta +- Capitalização de mercado - Cálculo do preço \ \* oferta -## Dados de camada de consenso {#consensus-layer-data} +## Dados da camada de consenso {#consensus-layer-data} ### Época {#epoch} @@ -184,7 +182,7 @@ Espaços são oportunidades para criação de blocos, os dados disponíveis para - Atestações - Número de atestações para o bloco neste espaço - Depósitos - O número de depósitos durante este espaço - Saídas voluntárias - O número de validadores que saiu durante o espaço -- Remoções - Número de penalidades dadas aos proponentes de blocos ou atestores +- Remoções - Número de penalidades dadas aos proponentes de blocos ou atestadores - Votos - Os validadores que votaram no bloco neste espaço ### Blocos {#blocks-1} @@ -236,20 +234,18 @@ Os dados de nível superior da camada consensual incluem os seguintes: - Participação de ETH - Valor da participação de ETH na rede - Saldo médio - Saldo médio de ETH de validadores -## Exploradores de bloco {#block-explorers} +## Exploradores de Bloco {#block-explorers} -- [Etherscan](https://etherscan.io/) - um explorador de bloco que você pode usar para buscar dados da rede principal Ethereum e rede de testes Goerli +- [Etherscan](https://etherscan.io/) - um explorador de blocos que você pode usar para buscar dados da rede principal e da rede de teste da Ethereum - [3xpl](https://3xpl.com/ethereum) - um explorador Ethereum de código aberto e sem anúncios que permite o download de seus conjuntos de dados -- [Beaconcha.in](https://beaconcha.in/) - um explorador de bloco de código aberto para Ethereum Mainnet e Goerli Testnet +- [Beaconcha.in](https://beaconcha.in/) - um explorador de blocos de código aberto para a rede principal e a rede de teste da Ethereum - [Blockchair](https://blockchair.com/ethereum) - o explorador Ethereum mais privado. Também para classificação e filtragem de dados (mempool) -- [Etherchain](https://www.etherchain.org/) - um explorador de blocos para a rede principal Ethereum -- [Ethplorer](https://ethplorer.io/) - um explorador de blocos com foco nos tokens da rede principal Ethereum e rede de testes Kovan -- [Rantom](https://rantom.app/) - Um DeFi amigável de código aberto & Visualizador de transação NFT para visões detalhadas -- [Ethernow](https://www.ethernow.xyz/) - um explorador de transações em tempo real que permite que você veja a camada pré-cadeia da rede principal de Ethereum +- [Etherchain](https://www.etherchain.org/) - um explorador de blocos para a rede principal da Ethereum. +- [Ethplorer](https://ethplorer.io/) - um explorador de blocos com foco em tokens para a rede principal da Ethereum e a rede de teste Kovan. ## Leitura adicional {#further-reading} -_Conhece um recurso da comunidade que ajudou você? Edite esta página e adicione-o!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ ## Tópicos relacionados {#related-topics} diff --git a/public/content/translations/pt-br/developers/docs/data-and-analytics/index.md b/public/content/translations/pt-br/developers/docs/data-and-analytics/index.md index af6527def2a..16d7eb95a7d 100644 --- a/public/content/translations/pt-br/developers/docs/data-and-analytics/index.md +++ b/public/content/translations/pt-br/developers/docs/data-and-analytics/index.md @@ -1,55 +1,72 @@ --- -title: Dados e Estatísticas -description: Como obter dados e análises on-chain para uso em dapps +title: "Dados e Estatísticas" +description: "Como obter dados e análises on-chain usados em dapps" lang: pt-br --- ## Introdução {#Introduction} -À medida que a utilização da rede continua a aumentar, irá existir uma quantidade crescente de informações valiosas nos dados on-chain. À medida que o volume de dados aumenta rapidamente, calcular e agregar essas informações para relatar ou dirigir um dapp pode se tornar uma dura empreitada de tempo e processo. +À medida que a utilização da rede continua a aumentar, crescerá dados valiosos on-chain. À medida que o volume de dados aumenta rapidamente, calcular e agregar essas informações para relatar ou dirigir um dapp pode se tornar uma dura empreitada de tempo e processo. A alavancagem dos prestadores de dados existentes pode acelerar o desenvolvimento, produzir resultados mais precisos e reduzir os esforços contínuos de manutenção. Isso permitirá que uma equipe se concentre na funcionalidade central que seu projeto está tentando fornecer. ## Pré-requisitos {#prerequisites} -Você deve entender o conceito básico de [Exploradores de Bloco](/developers/docs/data-and-analytics/block-explorers/) para entender melhor usá-los no contexto da análise de dados. Além disso, familiarize-se com o conceito de um [índice](/glossary/#index) para entender os benefícios que eles adicionam a uma concepção do sistema. +Você deve entender o conceito básico de [Exploradores de Bloco](/developers/docs/data-and-analytics/block-explorers/) para entender melhor seu uso no contexto de análise de dados. Além disso, familiarize-se com o conceito de um [índice](/glossary/#index) para entender os benefícios que eles adicionam a um projeto de sistema. -Em termos de fundamentos arquitetônicos, entendendo o que uma [API](https://www.wikipedia.org/wiki/API) e [REST](https://www.wikipedia.org/wiki/Representational_state_transfer) são, mesmo em teoria. +Em termos de fundamentos de arquitetura, entender o que são [API](https://www.wikipedia.org/wiki/API) e [REST](https://www.wikipedia.org/wiki/Representational_state_transfer), mesmo que em teoria. -## Exploradores de bloco {#block-explorers} +## Exploradores de Bloco {#block-explorers} -Muitos [exploradores de bloco](/developers/docs/data-and-analytics/block-explorers/) oferecem gateways [RESTful](https://www.wikipedia.org/wiki/Representational_state_transfer) [API](https://www.wikipedia.org/wiki/API) que fornecerão aos desenvolvedores visibilidade de dados em tempo real sobre blocos, transações, validadores, contas e outras atividades on-chain. +Muitos [Exploradores de Bloco](/developers/docs/data-and-analytics/block-explorers/) oferecem gateways de [API](https://www.wikipedia.org/wiki/API) [RESTful](https://www.wikipedia.org/wiki/Representational_state_transfer) que fornecem aos desenvolvedores visibilidade de dados em tempo real sobre blocos, transações, validadores, contas e outras atividades em cadeia. -Desenvolvedores podem então processar e transformar esses dados para dar aos seus usuários percepções e interações exclusivas com a [blockchain](/glossary/#blockchain). Por exemplo, [Etherscan](https://etherscan.io) fornece dados de execução e consenso para cada slot de 12s. +Os desenvolvedores podem então processar e transformar esses dados para dar aos seus usuários insights e interações únicas com a [blockchain](/glossary/#blockchain). Por exemplo, [Etherscan](https://etherscan.io) e [Blockscout](https://eth.blockscout.com) fornecem dados de execução e consenso para cada slot de 12s. ## The Graph {#the-graph} -A [rede Graph Network](https://thegraph.com/) é um protocolo descentralizado de indexação para a organização de dados blockchain. Em vez de construir e gerenciar lojas de dados off-chain e centralizadas para agregação de dados on-chain com The Graph, os desenvolvedores podem construir aplicativos sem servidor que são executados inteiramente na infraestrutura pública. +[The Graph](https://thegraph.com/) é um protocolo de indexação que oferece uma maneira fácil de consultar dados de blockchain por meio de APIs abertas conhecidas como subgráficos. -Usando o [GraphQL](https://graphql.org/), os desenvolvedores podem consultar qualquer uma das APIs abertas selecionadas, conhecidas como subgráficos, para adquirir as informações necessárias para impulsionar seu dapp. Ao consultar esses subgráficos indexados, relatórios e dapps, não apenas obtêm benefícios de desempenho e escalabilidade, como também a precisão incorporada fornecida pelo consenso da rede. Como novas melhorias e/ou subgráficos são adicionados à rede, seus projetos podem iterar rapidamente para tirar proveito dessas melhorias. +Com o The Graph, os desenvolvedores podem se beneficiar de: -## Diversidade dos clientes +- Indexação descentralizada: permite a indexação de dados de blockchain por meio de vários indexadores, eliminando assim qualquer ponto único de falha +- Consultas GraphQL: fornece uma interface GraphQL poderosa para consultar dados indexados, tornando a recuperação de dados super simples +- Personalização: Defina sua própria lógica para transformar e armazenar dados de blockchain, e reutilize subgráficos publicados por outros desenvolvedores na The Graph Network -A [diversidade do cliente](/developers/docs/nodes-and-clients/client-diversity/) é importante para a saúde geral da rede Ethereum porque fornece resiliência a bugs e explorações. Agora existem vários painéis de diversidade do cliente, incluindo [clientdiversity.org](https://clientdiversity.org/), [rated.network](https://www.rated.network), [supermajority.info](https://supermajority.info//) e [Ethernodes](https://ethernodes.org/). +Siga este guia de [início rápido](https://thegraph.com/docs/en/quick-start/) para criar, implantar e consultar um subgráfico em 5 minutos. + +## Diversidade de clientes {#client-diversity} + +A [diversidade de clientes](/developers/docs/nodes-and-clients/client-diversity/) é importante para a saúde geral da rede Ethereum, pois fornece resiliência a bugs e exploits. Existem agora vários painéis de diversidade de clientes, incluindo [clientdiversity.org](https://clientdiversity.org/), [rated.network](https://www.rated.network), [supermajority.info](https://supermajority.info//) e [Ethernodes](https://ethernodes.org/). ## Dune Analytics {#dune-analytics} -[Dune Analytics](https://dune.com/) pré-processa os dados de blockchain em tabelas de banco de dados relacional (DuneSQL), permitindo que os usuários consultem dados de blockchain usando SQL e criem dashboards com base nos resultados das consultas. Os dados on-chain são organizados em 4 tabelas brutas: `blocos`, `transações`, (evento) `registros` e (chamada) `traços`. Contratos e protocolos populares foram decodificados e cada um tem seu próprio conjunto de tabelas de eventos e chamadas. Essas tabelas de eventos e chamadas são processadas e organizadas em abstração de tabelas por tipo de protocolo, por exemplo, dex, lending, stablecoins etc. +[Dune Analytics](https://dune.com/) pré-processa dados de blockchain em tabelas de banco de dados relacional (DuneSQL), permitindo que os usuários consultem dados de blockchain usando SQL e criem dashboards com base nos resultados das consultas. Os dados em cadeia são organizados em 4 tabelas brutas: `blocks`, `transactions`, `logs` (de evento) e `traces` (de chamada). Contratos e protocolos populares foram decodificados e cada um tem seu próprio conjunto de tabelas de eventos e chamadas. Essas tabelas de eventos e chamadas são processadas e organizadas em abstração de tabelas por tipo de protocolo, por exemplo, dex, lending, stablecoins etc. + +## SQD {#sqd} + +[SQD](https://sqd.dev/) é uma plataforma de dados descentralizada e hiperescalável, otimizada para fornecer acesso eficiente e sem permissão a grandes volumes de dados. Atualmente, ele fornece dados históricos on-chain, incluindo registros de eventos, recibos de transações, rastreamentos e diferenças de estado por transação. O SQD oferece um poderoso kit de ferramentas para criar pipelines personalizados de extração e processamento de dados, alcançando uma velocidade de indexação de até 150mil blocos por segundo. + +Para começar, visite a [documentação](https://docs.sqd.dev/) ou veja [exemplos de EVM](https://github.com/subsquid-labs/squid-evm-examples) do que você pode construir com o SQD. ## SubQuery Network {#subquery-network} -[SubQuery](https://subquery.network/) é um indexador de dados líder que fornece aos desenvolvedores APIs rápidas, confiáveis, descentralizadas e personalizadas para projetos web3. A SubQuery capacita desenvolvedores de mais de 165 ecossistemas (incluindo Ethereum) com dados indexados avançados para criar experiências intuitivas e imersivas para seus usuários. A SubQuery Network impulsiona seus aplicativos com uma infraestrutura resiliente e descentralizada. Utilize o kit de ferramentas para desenvolvedores de blockchain da SubQuery para construir os aplicativos web3 do futuro, sem precisar gastar tempo criando um back-end personalizado para atividades de processamento de dados. +[SubQuery](https://subquery.network/) é um indexador de dados líder que fornece aos desenvolvedores APIs rápidas, confiáveis, descentralizadas e personalizadas para seus projetos web3. A SubQuery capacita desenvolvedores de mais de 165 ecossistemas (incluindo Ethereum) com dados indexados avançados para criar experiências intuitivas e imersivas para seus usuários. A SubQuery Network impulsiona seus aplicativos com uma infraestrutura resiliente e descentralizada. Utilize o kit de ferramentas para desenvolvedores de blockchain da SubQuery para construir os aplicativos web3 do futuro, sem precisar gastar tempo criando um back-end personalizado para atividades de processamento de dados. + +Para começar, visite o [guia de início rápido do Ethereum](https://academy.subquery.network/quickstart/quickstart_chains/ethereum-gravatar.html) para começar a indexar os dados da blockchain do Ethereum em minutos em um ambiente Docker local para testes antes de ir para produção em um [serviço gerenciado do SubQuery](https://managedservice.subquery.network/) ou na [rede descentralizada do SubQuery](https://app.subquery.network/dashboard). -Para começar, acesse o [guia rápido de Ethereum](https://academy.subquery.network/quickstart/quickstart_chains/ethereum-gravatar.html) para começar a indexar dados da blockchain Ethereum em minutos em um ambiente local Docker para testes antes do lançamento em um [serviço gerenciado da SubQuery](https://managedservice.subquery.network/) ou na [rede descentralizada da SubQuery](https://app.subquery.network/dashboard). +## Linguagem de Consulta EVM {#evm-query-language} -## Ethernow - Programa de dados Mempool {#ethernow} -[Blocknative](https://www.blocknative.com/) fornece acesso aberto ao seu [arquivo de dados de mempool](https://www.ethernow.xyz/mempool-data-archive) histórico do Ethereum. Isso permite que pesquisadores e bons projetos comunitários explorem a camada pré-chain da rede principal de Ethereum. O conjunto de dados é ativamente mantido e representa o registro histórico mais abrangente dos eventos de transações de mempool dentro do ecossistema Ethereum. Saiba mais em [Ethernow](https://www.ethernow.xyz/). +O EQL é uma linguagem semelhante ao SQL por consultar EVM chains. O objetivo do EQL é dar suporte a consultar relações entre os EVM chain first-class citizens (blocos, contas e transações) e fornece aos desenvolvedores e pesquisadores uma sintaxe ergonômica por uso. Com o EQL, os desenvolvedores podem buscar dados de Cadeia de blocos usando uma sintaxe semelhante ao SQL sem códigos complexos. O EQL suporta solicitações aos dados de Cadeia de blocos e está continuamente suportando solicitações e featuresets mais complexos. -## Leitura Adicional {#further-reading} +## Leitura adicional {#further-reading} -- [Visão geral da rede de gráficos](https://thegraph.com/docs/en/about/) -- [Área de consulta de gráficos](https://thegraph.com/explorer/subgraph/graphprotocol/graph-network-mainnet?version=current) -- [Exemplos de código de API em EtherScan](https://etherscan.io/apis#contracts) -- [Explorador de Beacon Chain Beaconcha.in](https://beaconcha.in) +- [Explorando Dados de Cripto I: Arquiteturas de Fluxo de Dados](https://web.archive.org/web/20250125012042/https://research.2077.xyz/exploring-crypto-data-1-data-flow-architectures) +- [Visão Geral da Graph Network](https://thegraph.com/docs/en/about/) +- [Playground de Consultas do Graph](https://thegraph.com/explorer/subgraph/graphprotocol/graph-network-mainnet?version=current) +- [Exemplos de código da API no EtherScan](https://etherscan.io/apis#contracts) +- [Documentação da API no Blockscout](https://docs.blockscout.com/devs/apis) +- [Beaconcha.in, explorador da Beacon Chain](https://beaconcha.in) - [Fundamentos do Dune](https://docs.dune.com/#dune-basics) -- [Guia rápido de início da SubQuery para Ethereum](https://academy.subquery.network/indexer/quickstart/quickstart_chains/ethereum-gravatar.html) +- [Guia de Início Rápido do Ethereum da SubQuery](https://academy.subquery.network/indexer/quickstart/quickstart_chains/ethereum-gravatar.html) +- [Visão Geral da SQD Network](https://docs.sqd.dev/) +- [Linguagem de Consulta EVM](https://eql.sh/blog/alpha-release-notes) diff --git a/public/content/translations/pt-br/developers/docs/data-availability/blockchain-data-storage-strategies/index.md b/public/content/translations/pt-br/developers/docs/data-availability/blockchain-data-storage-strategies/index.md new file mode 100644 index 00000000000..f8d6c3a1b23 --- /dev/null +++ b/public/content/translations/pt-br/developers/docs/data-availability/blockchain-data-storage-strategies/index.md @@ -0,0 +1,118 @@ +--- +title: "Estratégias de armazenamento de dados em blockchain" +description: "Existem várias maneiras de armazenar dados usando a blockchain. Este artigo comparará as diferentes estratégias, seus custos e compensações, bem como os requisitos para usá-las com segurança." +lang: pt-br +--- + +Existem várias maneiras de armazenar informações diretamente na blockchain ou de uma maneira protegida pela blockchain: + +- Blobs EIP-4844 +- Calldata +- Offchain com mecanismos L1 +- Contrato "code" +- Eventos +- Armazenamento EVM + +A escolha do método a ser utilizado é baseada em vários critérios: + +- A fonte da informação. As informações nos calldatas não podem vir diretamente da própria blockchain. +- O destino da informação. Calldata está disponível apenas na transação que o inclui. Os eventos não são acessíveis na cadeia. +- Qual é o nível de complexidade aceitável? Computadores que executam um nó em grande escala podem executar mais processamento do que um cliente leve em um aplicativo executado em um navegador. +- É necessário facilitar o acesso às informações de cada nó? +- Os requisitos de segurança. + +## Os requisitos de segurança {#security-requirements} + +Em geral, a segurança da informação consiste em três atributos: + +- _Confidentiality_: entidades não autorizadas não estão autorizadas a ler as informações. Isso é importante em muitos casos, mas não aqui. _Não há segredos na blockchain_. As blockchains funcionam porque qualquer pessoa pode verificar as transições de estado, então é impossível usá-las para armazenar segredos diretamente. Existem maneiras de armazenar informações confidenciais na blockchain, mas todas elas dependem de algum componente offchain para armazenar pelo menos uma chave. + +- _Integrity_: as informações estão corretas, não podem ser alteradas por entidades não autorizadas ou de maneiras não autorizadas (por exemplo, transferindo [tokens ERC-20](https://eips.ethereum.org/EIPS/eip-20#events) sem um evento `Transfer`). Na blockchain, cada nó verifica cada mudança de estado, o que garante integridade. + +- _Availability_: a informação está disponível para qualquer entidade autorizada. Na blockchain, isso é geralmente obtido ao ter as informações disponíveis em cada [nó completo](https://ethereum.org/developers/docs/nodes-and-clients#full-node). + +Todas as diferentes soluções aqui têm excelente integridade, porque os hashes são postados no L1. No entanto, elas têm diferentes garantias de disponibilidade. + +## Pré-requisitos {#prerequisites} + +Você deve ter um bom entendimento dos [fundamentos da blockchain](/developers/docs/intro-to-ethereum/). Esta página também pressupõe que o leitor esteja familiarizado com [blocos](/developers/docs/blocks/), [transações](/developers/docs/transactions/) e outros tópicos relevantes. + +## Blobs EIP-4844 {#eip-4844-blobs} + +Começando com [o hardfork Dencun](https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/beacon-chain.md), a blockchain Ethereum inclui [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844), que adiciona blobs de dados Ethereum com uma vida útil limitada (inicialmente cerca de [18 dias](https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/p2p-interface.md#configuration)). Esses blobs têm preços separados do [gás de execução](/developers/docs/gas), embora usem um mecanismo semelhante. Eles são uma maneira barata de postar dados temporários. + +O principal caso de uso dos blobs EIP-4844 é a publicação das transações pelos rollups. [Optimistic rollups](/developers/docs/scaling/optimistic-rollups) precisam publicar as transações em suas blockchains. Essas transações precisam estar disponíveis para qualquer pessoa durante o [período do desafio](https://docs.optimism.io/connect/resources/glossary#challenge-period) para permitir que os [validadores](https://docs.optimism.io/connect/resources/glossary#validator) corrijam o erro se o [sequenciador](https://docs.optimism.io/connect/resources/glossary#sequencer) do rollup publicar uma raiz de estado incorreta. + +Entretanto, uma vez que o período de desafio tenha passado e a raiz do estado tenha sido finalizada, o propósito restante para conhecer essas transações é replicar o estado atual da cadeia. Esse estado também está disponível nos nós da cadeia, exigindo muito menos processamento. Portanto, as informações de transações ainda devem ser preservadas em alguns lugares, como [exploradores de bloco](/developers/docs/data-and-analytics/block-explorers), mas não há necessidade de pagar pelo nível de resistência à censura que o Ethereum oferece. + +[Rollups de conhecimento zero](/developers/docs/scaling/zk-rollups/#data-availability) também publicam seus dados de transações para permitir que outros nós repliquem o estado existente e verifiquem provas de validade, mas, novamente, esse é um requisito de curto prazo. + +No momento em que escrevo, postar no EIP-4844 custa um wei (10-18 ETH) por byte, o que é insignificante comparado aos [21.000 gases de execução que qualquer transação, incluindo uma que publica blobs, custa](https://eth.blockscout.com/tx/0xf6cfaf0431c73dd1d96369a5e6707d64f463ccf477a4131265397f1d81466929?tab=index). Você pode ver o preço atual do EIP-4844 em [blobscan.com](https://blobscan.com/blocks). + +Aqui estão os endereços para ver os blobs postados por alguns rollups famosos. + +| Rollup | Endereço | +| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- | +| [Optimism](https://www.optimism.io/) | [`0xFF00000000000000000000000000000000000010`](https://blobscan.com/address/0xFF00000000000000000000000000000000000010) | +| [Arbitrum](https://arbitrum.io/) | [`0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6`](https://blobscan.com/address/0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6) | +| [Base](https://base.org/) | [`0xFF00000000000000000000000000000000008453`](https://blobscan.com/address/0xFF00000000000000000000000000000000008453) | + +## Calldata {#calldata} + +Calldata refere-se aos bytes enviados como parte da transação. Ele é armazenado como parte do registro permanente da blockchain no bloco que inclui essa transação. + +Este é o método mais barato para colocar dados permanentemente na blockchain. O custo por byte é de 4 unidades de gás de execução (se o byte for zero) ou 16 gás (qualquer outro valor). Se os dados forem compactados, o que é uma prática padrão, cada valor de byte será igualmente provável, então o custo médio será de aproximadamente 15,95 unidades de gás por byte. + +No momento em que este artigo foi escrito, os preços eram 12 gwei/gás e 2300 $/ETH, o que significa que o custo é de aproximadamente 45 centavos por quilobyte. Como esse era o método mais barato antes do EIP-4844, esse é o método usado pelos rollups para armazenar informações de transações, que precisam estar disponíveis para [desafios de falhas](https://docs.optimism.io/stack/protocol/overview#fault-proofs), mas não precisam estar acessíveis diretamente na cadeia. + +Aqui estão os endereços para ver as transações publicadas por alguns rollups famosos. + +| Rollup | Endereço | +| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | +| [Optimism](https://www.optimism.io/) | [`0xFF00000000000000000000000000000000000010`](https://eth.blockscout.com/address/0xFF00000000000000000000000000000000000010) | +| [Arbitrum](https://arbitrum.io/) | [`0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6`](https://eth.blockscout.com/address/0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6) | +| [Base](https://base.org/) | [`0xFF00000000000000000000000000000000008453`](https://eth.blockscout.com/address/0xFF00000000000000000000000000000000008453) | + +## Offchain com mecanismos L1 {#offchain-with-l1-mechs} + +Dependendo das suas compensações de segurança, pode ser aceitável colocar as informações em outro lugar e usar um mecanismo que garanta que os dados estejam disponíveis quando necessário. Há dois requisitos para que isso funcione: + +1. Publique um [hash](https://en.wikipedia.org/wiki/Cryptographic_hash_function) dos dados na blockchain, chamado de _input commitment_. Pode ser uma única palavra de 32 bytes, portanto não é caro. Enquanto o comprometimento de entrada estiver disponível, a integridade estará garantida porque não é possível encontrar outros dados que tenham o mesmo valor. Portanto, se dados incorretos forem fornecidos, eles poderão ser detectados. + +2. Tenha um mecanismo que garanta a disponibilidade. Por exemplo, em [Redstone](https://redstone.xyz/docs/what-is-redstone) qualquer nó pode enviar um desafio de disponibilidade. Se o sequenciador não responder onchain dentro do prazo, o comprometimento de entrada será descartado, então a informação será considerada como nunca tendo sido publicada. + +Isso é aceitável para um pptimistic rollup porque já estamos contando com pelo menos um verificador honesto para a raiz do estado. Um verificador honesto também garantirá que possui os dados para processar blocos e emitirá um desafio de disponibilidade se as informações não estiverem disponíveis off-chain. Esse tipo de optimistic rollup é chamado de [plasma](/developers/docs/scaling/plasma/). + +## Código do contrato {#contract-code} + +Informações que só precisam ser escritas uma vez, nunca são substituídas e precisam estar disponíveis na cadeia podem ser armazenadas como código de contrato. Isso significa que criamos um "contrato inteligente" com os dados e então usamos [`EXTCODECOPY`](https://www.evm.codes/#3c?fork=shanghai) para ler as informações. A vantagem é que copiar código é relativamente barato. + +Além do custo de expansão de memória, `EXTCODECOPY` custa 2.600 unidades de gás para o primeiro acesso a um contrato (quando ele está "frio") e 100 unidades de gás para cópias subsequentes do mesmo contrato, mais 3 unidades de gás por palavra de 32 bytes. Comparado com o calldata, que custa 15,95 por byte, este é mais barato a partir de cerca de 200 bytes. Com base na [fórmula para custos de expansão de memória](https://www.evm.codes/about#memoryexpansion), desde que você não precise de mais de 4 Mb de memória, o custo de expansão de memória é menor que o custo de adicionar dados de chamada. + +Claro, esse é apenas o custo para ler os dados. A criação do contrato custa aproximadamente 32.000 unidades de gás + 200 unidades de gás/byte. Este método só é econômico quando a mesma informação precisa ser lida muitas vezes em transações diferentes. + +O código do contrato pode ser absurdo, desde que não comece com `0xEF`. Contratos que começam com `0xEF` são interpretados como [formato de objeto ethereum](https://notes.ethereum.org/@ipsilon/evm-object-format-overview), que tem requisitos muito mais rigorosos. + +## Eventos {#events} + +[Eventos](https://docs.alchemy.com/docs/solidity-events) são emitidos por contratos inteligentes e lidos por software offchain. +A vantagem é que o código offchain pode escutar eventos. O custo é [gás](https://www.evm.codes/#a0?fork=cancun), 375 mais 8 unidades de gás por byte de dados. A 12 gwei/gás e 2.300 $/ETH, isso se traduz em um centavo mais 22 centavos por kilobyte. + +## Armazenamento {#storage} + +Contratos inteligentes têm acesso a [armazenamento persistente](https://docs.alchemy.com/docs/smart-contract-storage-layout#what-is-storage-memory). Porém, é muito caro. Escrever uma palavra de 32 bytes em um slot de armazenamento previamente vazio pode [custar 22.100unidades de gás](https://www.evm.codes/#55?fork=cancun). A 12 gwei/gás e 2.300 $/ETH, isso é cerca de 61 centavos por operação de gravação, ou US$ 19,5 por kilobyte. + +Esta é a forma mais cara de armazenamento no Ethereum. + +## Resumo {#summary} + +Esta tabela resume as diferentes opções, suas vantagens e desvantagens. + +| Tipo de armazenamento | Fonte de dados | Garantia de disponibilidade | Disponibilidade onchain | Limitações adicionais | +| -------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | +| Blobs EIP-4844 | Offchain | Garantia Ethereum por [cerca de 18 dias](https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/p2p-interface.md#configuration) | Apenas hash está disponível | | +| Calldata | Offchain | Garantia perpétua Ethereum (parte da blockchain) | Disponível somente se escrito em um contrato e nessa transação específica | | +| Offchain com mecanismos L1 | Offchain | Garantia de "Um verificador honesto" durante o período de desafio | Somente hash | Garantido pelo mecanismo de desafio, apenas durante o período de desafio | +| Código do contrato | Onchain ou offchain | Garantia perpétua Ethereum (parte da blockchain) | Sim | Escrito em um endereço "aleatório". Não pode começar com `0xEF` | +| Eventos | Onchain | Garantia perpétua Ethereum (parte da blockchain) | Não | | +| Armazenamento | Onchain | Garantia perpétua Ethereum (parte da blockchain e o estado atual até ser substituído) | Sim | | diff --git a/public/content/translations/pt-br/developers/docs/data-availability/index.md b/public/content/translations/pt-br/developers/docs/data-availability/index.md index 316e918b191..38be0705b70 100644 --- a/public/content/translations/pt-br/developers/docs/data-availability/index.md +++ b/public/content/translations/pt-br/developers/docs/data-availability/index.md @@ -1,83 +1,84 @@ --- title: Disponibilidade de dados -description: Uma visão geral dos problemas e soluções relacionados à disponibilidade de dados no Ethereum +description: "Uma visão geral dos problemas e soluções relacionados à disponibilidade de dados no Ethereum" lang: pt-br --- “Não confie, verifique” é uma máxima comum no Ethereum. A ideia é que seu nó possa verificar de modo independente se a informação que recebe está correta, executando todas as transações nos blocos que recebem dos pares, a fim de garantir que as mudanças propostas correspondam precisamente àquelas calculadas de forma independente pelo nó. Isso significa que os nós não precisam confiar na honestidade dos remetentes do bloco. Isso não é possível se estiverem faltando dados. -**Disponibilidade de dados** se refere à confiança que um usuário pode ter de que os dados necessários para verificar um bloco estão realmente disponíveis para todos os participantes da rede. Para nós completos na camada 1 do Ethereum, isso é relativamente simples; o nó completo baixa uma cópia de todos os dados em cada bloco — os dados _devem_ estar disponíveis para que o download seja possível. Um bloco com dados faltando seria descartado em vez de ser adicionado à blockchain. Isso é “disponibilidade de dados on-chain” e é um recurso de blockchains monolíticas. Os nós completos não podem ser enganados em aceitar transações inválidas porque eles baixam e executam todas as transações para si mesmos. No entanto, para blockchains modulares, rollups de camada 2 e clientes leves, o cenário de disponibilidade de dados é mais complexo, exigindo alguns procedimentos de verificação mais sofisticados. +**Disponibilidade de dados** se refere à confiança que um usuário pode ter de que os dados necessários para verificar um bloco estão realmente disponíveis para todos os participantes da rede. Para nós completos na camada 1 do Ethereum, isso é relativamente simples; o nó completo baixa uma cópia de todos os dados em cada bloco — os dados _têm_ que estar disponíveis para que o download seja possível. Um bloco com dados faltando seria descartado em vez de ser adicionado à blockchain. Está é a "disponibilidade de dados on-chain" e é uma característica das blockchains monolíticas. Os nós completos não podem ser enganados em aceitar transações inválidas porque eles baixam e executam todas as transações para si mesmos. No entanto, para blockchains modulares, rollups de camada 2 e clientes leves, o cenário de disponibilidade de dados é mais complexo, exigindo alguns procedimentos de verificação mais sofisticados. ## Pré-requisitos {#prerequisites} -Você deve ter uma boa compreensão dos [fundamentos da blockchain](/developers/docs/intro-to-ethereum/), especialmente sobre [mecanismos de consenso](/developers/docs/consensus-mechanisms/). Esta página também pressupõe que o leitor esteja familiarizado com [blocos](/developers/docs/blocks/), [transações](/developers/docs/transactions/), [nós](/developers/docs/nodes-and-clients/), [soluções de dimensionamento](/developers/docs/scaling/) e outros tópicos relevantes. +Você deve ter um bom entendimento dos [fundamentos da blockchain](/developers/docs/intro-to-ethereum/), especialmente dos [mecanismos de consenso](/developers/docs/consensus-mechanisms/). Esta página também pressupõe que o leitor esteja familiarizado com [blocos](/developers/docs/blocks/), [transações](/developers/docs/transactions/), [nós](/developers/docs/nodes-and-clients/), [soluções de escalabilidade](/developers/docs/scaling/) e outros tópicos relevantes. ## O problema da disponibilidade de dados {#the-data-availability-problem} O problema da disponibilidade de dados é a necessidade de provar para toda a rede que a forma resumida de alguns dados de transação que estão sendo adicionados à blockchain realmente representa um conjunto de transações válidas, mas fazendo isso sem exigir que todos os nós baixem todos os dados. Os dados completos da transação são necessários para verificar os blocos de forma independente, mas exigir que todos os nós baixem todos os dados da transação é uma barreira para a escalabilidade. As soluções para o problema da disponibilidade de dados visam fornecer garantias suficientes de que os dados completos da transação foram disponibilizados para verificação aos participantes da rede que não baixam e armazenam os dados por conta própria. -[Nós leves](/developers/docs/nodes-and-clients/light-clients) e [rollups da camada 2](/developers/docs/scaling) são importantes exemplos de participantes da rede que exigem fortes garantias de disponibilidade de dados, mas não podem baixar e processar dados de transações por conta própria. Evitar baixar dados de transações é o que torna os nós leves e permite que os rollups sejam soluções de escalabilidade eficazes. +[Nós leves](/developers/docs/nodes-and-clients/light-clients) e [rollups de Camada 2](/developers/docs/scaling) são exemplos importantes de participantes da rede que exigem fortes garantias de disponibilidade de dados, mas não podem baixar e processar os dados de transações por conta própria. Evitar baixar dados de transações é o que torna os nós leves e permite que os rollups sejam soluções de escalabilidade eficazes. -A disponibilidade de dados é também uma preocupação crítica para futuros clientes do Ethereum [“sem estado”](/roadmap/statelessness) que não precisam baixar e armazenar dados de estado para verificar os blocos. Os clientes sem estado ainda precisam ter certeza de que os dados estão disponíveis _em algum lugar_ e que foram processados corretamente. +A disponibilidade de dados também é uma preocupação crítica para futuros clientes Ethereum ["sem estado"](/roadmap/statelessness) que não precisam baixar e armazenar dados de estado para verificar os blocos. Os clientes sem estado ainda precisam ter certeza de que os dados estão disponíveis _em algum lugar_ e que foram processados corretamente. ## Soluções de disponibilidade de dados {#data-availability-solutions} ### Amostragem de disponibilidade de dados (DAS) {#data-availability-sampling} -Amostragem de Disponibilidade de Dados (DAS, do inglês Data Availability Sampling) é uma forma de a rede verificar se os dados estão disponíveis sem sobrecarregar um nó excessivamente. Cada nó (incluindo os nós que não foram nomeados para o staking) baixa um subconjunto pequeno e selecionado aleatoriamente do total de dados. Baixar com sucesso as amostras confirma com alta confiança que todos os dados estão disponíveis. Isso se baseia na codificação de eliminação de dados, que expande um determinado conjunto de dados com informações redundantes (a maneira como isso é feito é encaixando uma função conhecida como _polinomial_ sobre os dados e avaliando esse polinômio em pontos adicionais). Isso permite que os dados originais sejam recuperados a partir dos dados redundantes quando necessário. Consequentemente, se _qualquer_ dado original estiver indisponível, a criação dos dados causaria a perda de _metade_ dos dados expandidos! A quantidade de amostras de dados baixadas por cada nó pode ser ajustada de modo que seja _extremamente_ provável que pelo menos um dos fragmentos de dados amostrados por cada cliente esteja faltando _se_ menos da metade dos dados estiver realmente disponível. +Amostragem de Disponibilidade de Dados (DAS, do inglês Data Availability Sampling) é uma forma de a rede verificar se os dados estão disponíveis sem sobrecarregar um nó excessivamente. Cada nó (incluindo os nós que não foram nomeados para o staking) baixa um subconjunto pequeno e selecionado aleatoriamente do total de dados. Baixar com sucesso as amostras confirma com alta confiança que todos os dados estão disponíveis. Isso se baseia na codificação de eliminação de dados, que expande um determinado conjunto de dados com informações redundantes (a maneira como isso é feito é ajustar uma função conhecida como um _polinômio_ sobre os dados e avaliar esse polinômio em pontos adicionais). Isso permite que os dados originais sejam recuperados a partir dos dados redundantes quando necessário. Uma consequência dessa criação de dados é que, se _qualquer_ parte dos dados originais não estiver disponível, _metade_ dos dados expandidos estará faltando! A quantidade de amostras de dados baixadas por cada nó pode ser ajustada para que seja _extremamente_ provável que pelo menos um dos fragmentos de dados amostrados por cada cliente esteja faltando _se_ menos da metade dos dados estiver realmente disponível. -O DAS será usado para garantir que os operadores de rollup tornem seus dados de transação disponíveis após o [EIP-4844](/roadmap/danksharding) ser implementado. Os nós do Ethereum usarão como amostras os dados da transação fornecidos nos blobs aleatoriamente usando o esquema de redundância explicado acima para garantir que todos os dados existam. A mesma técnica também poderá ser utilizada para garantir que os produtores de blocos estejam disponibilizando todos os seus dados para proteger clientes leves. Da mesma forma, na [separação entre proponentes e construtores](/roadmap/pbs), apenas o construtor do bloco seria necessário para processar um bloco inteiro, enquanto outros validadores verificariam usando uma amostragem da disponibilidade de dados. +O DAS será usado para garantir que os operadores de rollup disponibilizem seus dados de transação após a implementação do [Full Danksharding](/roadmap/danksharding/#what-is-danksharding). Os nós do Ethereum usarão como amostras os dados da transação fornecidos nos blobs aleatoriamente usando o esquema de redundância explicado acima para garantir que todos os dados existam. A mesma técnica também poderá ser utilizada para garantir que os produtores de blocos estejam disponibilizando todos os seus dados para proteger clientes leves. Da mesma forma, na [separação entre proponentes e construtores](/roadmap/pbs), apenas o construtor do bloco seria necessário para processar um bloco inteiro, enquanto outros validadores verificariam usando uma amostragem da disponibilidade de dados. ### Comitês de disponibilidade de dados {#data-availability-committees} -Os Comitês de Disponibilidade de Dados (DACs, do inglês Data Availability Committees) são partes confiáveis que fornecem ou atestam a disponibilidade de dados. DACs podem ser usados em vez de, [ou em combinação com](https://hackmd.io/@vbuterin/sharding_proposal#Why-not-use-just-committees-and-not-DAS) DAS. As garantias de segurança que chegam aos comitês dependem de configuração específica. O Ethereum usa amostras de subconjuntos de validadores escolhidos aleatoriamente para atestar a disponibilidade de dados para nós leves, por exemplo. +Os Comitês de Disponibilidade de Dados (DACs, do inglês Data Availability Committees) são partes confiáveis que fornecem ou atestam a disponibilidade de dados. Os DACs podem ser usados em vez de, [ou em combinação com](https://hackmd.io/@vbuterin/sharding_proposal#Why-not-use-just-committees-and-not-DAS), o DAS. As garantias de segurança que chegam aos comitês dependem de configuração específica. O Ethereum usa amostras de subconjuntos de validadores escolhidos aleatoriamente para atestar a disponibilidade de dados para nós leves, por exemplo. -DACs também são usados por alguns validiums. O DAC é um conjunto confiável de nós que armazena cópias de dados offline. O DAC é necessário para disponibilizar os dados em caso de litígio. Os membros do DAC também publicam certificados na cadeia para provar que os referidos dados estão efetivamente disponíveis. Alguns validiums substituem os DACs por um sistema validador de prova de participação (proof-of-stake ou PoS). Aqui, qualquer pessoa pode se tornar um validador e armazenar dados off-chain. No entanto, eles devem fornecer uma “caução”, que é depositada em um contrato inteligente. No caso de comportamento malicioso, por exemplo, o validador retendo dados, a caução pode ser interrompida. Os comitês de disponibilidade de dados da prova de participação são consideravelmente mais seguros do que os DACs regulares, porque incentivam diretamente um comportamento honesto. +DACs também são usados por alguns validiums. O DAC é um conjunto confiável de nós que armazena cópias de dados offline. O DAC é necessário para disponibilizar os dados em caso de litígio. Os membros da DAC também publicam atestados em cadeia para provar que esses dados estão realmente disponíveis. Alguns validiums substituem os DACs por um sistema validador de prova de participação (proof-of-stake ou PoS). Aqui, todo mundo pode se tornar um validador e armazenador de dados off-chain. No entanto, eles devem fornecer uma “caução”, que é depositada em um contrato inteligente. No caso de comportamento malicioso, por exemplo, o validador retendo dados, a caução pode ser interrompida. Os comitês de disponibilidade de dados da prova de participação são consideravelmente mais seguros do que os DACs regulares, porque incentivam diretamente um comportamento honesto. ## Disponibilidade de dados e nós leves {#data-availability-and-light-nodes} -Os [Nós leves](/developers/docs/nodes-and-clients/light-clients) precisam validar a exatidão dos cabeçalhos do bloco que recebem sem baixar os dados do bloco. O custo dessa leveza é a incapacidade de verificar de forma independente os cabeçalhos do bloco reexecutando as transações localmente da maneira que os nós completos fazem. +[Nós leves](/developers/docs/nodes-and-clients/light-clients) precisam validar a exatidão dos cabeçalhos do bloco que recebem sem baixar os dados do bloco. O custo dessa leveza é a incapacidade de verificar de forma independente os cabeçalhos do bloco reexecutando as transações localmente da maneira que os nós completos fazem. -Os nós leves do Ethereum confiam em conjuntos aleatórios de 512 validadores que foram atribuídos a um _comitê de sincronização_. O comitê de sincronização atua como um DAC que sinaliza aos clientes leves que os dados no cabeçalho estão corretos usando uma assinatura criptográfica. O comitê de sincronização é atualizado diariamente. Cada cabeçalho do bloco alerta os nós leves, indicando quais validadores serão destinados a assinar o _próximo_ bloco, para não serem enganados confiando em um grupo malicioso fingindo ser o verdadeiro comitê de sincronização. +Os nós leves do Ethereum confiam em conjuntos aleatórios de 512 validadores que foram atribuídos a um _comitê de sincronização_. O comitê de sincronização atua como um DAC que sinaliza aos clientes leves que os dados no cabeçalho estão corretos usando uma assinatura criptográfica. O comitê de sincronização é atualizado diariamente. Cada cabeçalho de bloco alerta os nós leves sobre quais validadores devem assinar o _próximo_ bloco, para que não possam ser enganados a confiar em um grupo mal-intencionado que finja ser o verdadeiro comitê de sincronização. -No entanto, o que acontece se um invasor _conseguir_ de alguma forma passar um cabeçalho de bloco malicioso para clientes leves e convencê-los de que foi assinado por um comitê de sincronização honesto? Nesse caso, o invasor poderia incluir transações inválidas e o cliente leve as aceitaria cegamente, pois não verifica de forma independente todas as alterações de estado resumidas no cabeçalho do bloco. Para se proteger contra isso, o cliente leve pode usar provas de fraude. +No entanto, o que acontece se um invasor de alguma forma _conseguir_ passar um cabeçalho de bloco malicioso para clientes leves e convencê-los de que foi assinado por um comitê de sincronização honesto? Nesse caso, o invasor poderia incluir transações inválidas e o cliente leve as aceitaria cegamente, pois não verifica de forma independente todas as alterações de estado resumidas no cabeçalho do bloco. Para se proteger contra isso, o cliente leve pode usar provas de fraude. Essas provas de fraude funcionam da seguinte maneira: um nó completo observa uma transição de estado inválido sendo espalhada pela rede, que poderia rapidamente gerar uma pequena parte de dados demonstrando que uma transição de estado proposta não poderia surgir de um determinado conjunto de transações e transmitir esses dados aos seus pares. Os nós leves poderiam pegar essas provas de fraude e usá-las para descartar cabeçalhos de bloco ruins, garantindo que permaneçam na mesma cadeia honesta que os nós completos. Isso depende de nós completos com acesso a dados completos da transação. Um invasor que transmite um cabeçalho de bloco inválido e também falha em disponibilizar os dados da transação seria capaz de impedir que os nós completos gerassem provas de fraude. Os nós completos poderiam conseguir sinalizar um aviso sobre um bloco ruim, mas não poderiam fazer validar seu aviso com uma prova, pois os dados não foram disponibilizados para gerar a prova! -A solução para esse problema de disponibilidade de dados é o DAS. Nós leves baixam partes aleatórias muito pequenas dos dados de estado completos e usam as amostras para verificar se o conjunto completo de dados está disponível. A probabilidade real de assumir incorretamente a disponibilidade total dos dados após baixar N blocos aleatórios pode ser calculada ([para 100 partes, a chance é de 10^-30](https://dankradfeist.de/ethereum/2019/12/20/data-availability-checks.html), ou seja, incrivelmente improvável). +A solução para esse problema de disponibilidade de dados é o DAS. Nós leves baixam partes aleatórias muito pequenas dos dados de estado completos e usam as amostras para verificar se o conjunto completo de dados está disponível. A probabilidade real de assumir incorretamente a disponibilidade total de dados após baixar N partes aleatórias pode ser calculada ([para 100 partes, a chance é de 10^-30](https://dankradfeist.de/ethereum/2019/12/20/data-availability-checks.html), ou seja, incrivelmente improvável). Mesmo nesse cenário, os ataques que retêm apenas alguns bytes poderiam passar despercebidos pelos clientes que fazem solicitações de dados aleatórios. A codificação de eliminação (remoção segura e permanente de dados de contratos) corrige isso reconstruindo pequenas partes de dados ausentes que podem ser usadas para verificar as alterações de estado propostas. Uma prova de fraude poderia então ser construída usando os dados reconstruídos, evitando que clientes leves aceitem cabeçalhos ruins. -**Nota:** DAS e provas de fraude ainda não foram implementados para clientes leves da prova de participação do Ethereum, mas estão no roteiro, muito provavelmente assumindo a forma de provas baseadas em ZK-SNARK. Os clientes leves de hoje dependem de uma forma de DAC: eles verificam as identidades do comitê de sincronização e, em seguida, confiam nos cabeçalhos de bloco assinados que recebem. +**Nota:** DAS e provas de fraude ainda não foram implementados para clientes leves de prova de participação do Ethereum, mas estão no roteiro, muito provavelmente assumindo a forma de provas baseadas em ZK-SNARK. Os clientes leves de hoje dependem de uma forma de DAC: eles verificam as identidades do comitê de sincronização e, em seguida, confiam nos cabeçalhos de bloco assinados que recebem. -## Disponibilidade de dados e rollups de camada 2 {#data-availability-and-layer-2-rollups} +## Disponibilidade de dados e rollups de Camada 2 {#data-availability-and-layer-2-rollups} -[As soluções de escalabilidade de Camada 2](/layer-2/), como [rollups](/glossary/#rollups), reduzem os custos de transação e aumentam o rendimento do Ethereum processando transações off-chain. As transações de rollup são compactadas e postadas no Ethereum em lotes. Os lotes representam milhares de transações individuais off-chain em uma única transação no Ethereum. Isso reduz o congestionamento na camada base e reduz as taxas para os usuários. +[Soluções de escalabilidade de Camada 2](/layer-2/), como [rollups](/glossary/#rollups), reduzem os custos de transação e aumentam o throughput do Ethereum ao processar transações off-chain. As transações de rollup são compactadas e postadas no Ethereum em lotes. Lotes representam milhares de transações individuais off-chain em uma única transação no Ethereum. Isso reduz o congestionamento na camada base e reduz as taxas para os usuários. -No entanto, só é possível confiar nas transações “resumidas” publicadas no Ethereum se a mudança de estado proposta puder ser verificada de forma independente e confirmada como resultado da aplicação de todas as transações individuais off-chain. Se os operadores de rollup não disponibilizarem os dados da transação para essa verificação, eles poderão enviar dados incorretos para o Ethereum. +No entanto, só é possível confiar nas transações 'resumidas' postadas na Ethereum se a mudança de estado proposta puder ser verificada e confirmada de forma independente como resultado da aplicação de todas as transações individuais fora da cadeia. Se os operadores de rollup não disponibilizarem os dados da transação para essa verificação, eles poderão enviar dados incorretos para o Ethereum. -[Rollups otimistas](/developers/docs/scaling/optimistic-rollups/) publicam dados de transação compactados no Ethereum e esperam algum tempo (normalmente 7 dias) para permitir que verificadores independentes confiram os dados. Se alguém identificar um problema, poderá gerar uma prova de fraude e usá-la para contestar o rollup. Isso faria com que a cadeia fosse revertida e omitisse o bloco inválido. Isso só é possível se houver dados disponíveis. Atualmente, os dados são disponibilizados de forma permanente como `CALLDATA`, que reside permanentemente on-chain. No entanto, o EIP-4844 em breve permitirá que os rollups publiquem seus dados de transação em um armazenamento de blob mais barato. Esse armazenamento não é permanente. Os verificadores independentes terão que consultar os blobs e reportar seus desafios entre 1 e 3 meses antes de os dados serem excluídos da camada 1 do Ethereum. A disponibilidade dos dados só é garantida pelo protocolo Ethereum para esse curto espaço de tempo fixo. Depois disso, ela é de responsabilidade de outras entidades do ecossistema Ethereum. Qualquer nó pode verificar a disponibilidade de dados usando DAS, ou seja, baixando pequenas amostras aleatórias dos dados do blob. +[Optimistic rollups](/developers/docs/scaling/optimistic-rollups/) publicam dados de transação compactados no Ethereum e esperam por um certo tempo (geralmente 7 dias) para permitir que verificadores independentes verifiquem os dados. Se alguém identificar um problema, poderá gerar uma prova de fraude e usá-la para contestar o rollup. Isso faria com que a cadeia fosse revertida e omitisse o bloco inválido. Isso só é possível se houver dados disponíveis. Atualmente, há duas maneiras pelas quais os optimistic rollups publicam dados de transações no L1. Alguns rollups tornam os dados permanentemente disponíveis como `CALLDATA`, que reside permanentemente on-chain. Com a implementação do EIP-4844, alguns rollups publicam seus dados de transações em um armazenamento de blobs mais barato. Esse armazenamento não é permanente. Verificadores independentes precisam consultar os blobs e apresentar seus desafios dentro de 18 dias (aproximadamente) antes que os dados sejam excluídos da camada 1 do Ethereum. A disponibilidade dos dados só é garantida pelo protocolo Ethereum para esse curto espaço de tempo fixo. Depois disso, ela é de responsabilidade de outras entidades do ecossistema Ethereum. Qualquer nó pode verificar a disponibilidade de dados usando DAS, ou seja, baixando pequenas amostras aleatórias dos dados do blob. -[ZK-rollups (rollups de conhecimento zero)](/developers/docs/scaling/zk-rollups) não precisam publicar dados de transação, já que as [provas de validação de conhecimento zero](/glossary/#zk-proof) garantem a exatidão das transições de estado. No entanto, a disponibilidade dos dados ainda é um problema, pois não podemos garantir a funcionalidade do ZK-rollup (ou interagir com ele) sem acesso aos seus dados de estado. Por exemplo, os usuários não podem saber os saldos deles se um operador retiver detalhes sobre o estado do rollup. Eles tampouco podem realizar atualizações de estado utilizando informações contidas em um bloco recém-adicionado. +[Rollups de conhecimento zero (ZK)](/developers/docs/scaling/zk-rollups) não precisam publicar dados de transação, pois as [provas de validade de conhecimento zero](/glossary/#zk-proof) garantem a exatidão das transições de estado. No entanto, a disponibilidade dos dados ainda é um problema, pois não podemos garantir a funcionalidade do ZK-rollup (ou interagir com ele) sem acesso aos seus dados de estado. Por exemplo, os usuários não podem saber os saldos deles se um operador retiver detalhes sobre o estado do rollup. Eles tampouco podem realizar atualizações de estado utilizando informações contidas em um bloco recém-adicionado. ## Disponibilidade de dados vs. recuperabilidade de dados {#data-availability-vs-data-retrievability} Disponibilidade de dados é diferente de recuperabilidade de dados. A disponibilidade de dados é a garantia de que nós completos conseguiram acessar e verificar o conjunto completo de transações associadas a um bloco específico. Isso não significa necessariamente que os dados ficarão acessíveis para sempre. -Recuperabilidade de dados é a capacidade de os nós recuperarem _informações históricas_ da blockchain. Esses dados históricos não são necessários para verificar novos blocos, apenas para sincronizar nós completos do bloco de origem ou servir solicitações históricas específicas. +A recuperabilidade de dados é a capacidade dos nós de recuperar _informações históricas_ da blockchain. Esses dados históricos não são necessários para verificar novos blocos, apenas para sincronizar nós completos do bloco de origem ou servir solicitações históricas específicas. -A preocupação do protocolo principal Ethereum é a disponibilidade de dados, e não a recuperação de dados. A capacidade de recuperar dados pode ser fornecida por uma pequena população de nós de arquivos executados por terceiros ou pode ser distribuída pela rede usando um armazenamento de arquivos descentralizado, como o [Portal Network](https://www.ethportal.net/). +A preocupação do protocolo principal Ethereum é a disponibilidade de dados, e não a recuperação de dados. A recuperabilidade de dados pode ser fornecida por uma pequena população de nós de arquivamento executados por terceiros, ou pode ser distribuída pela rede usando armazenamento de arquivos descentralizado, como a [Portal Network](https://www.ethportal.net/). ## Leitura adicional {#further-reading} -- [O que é disponibilidade de dados?](https://medium.com/blockchain-capital-blog/wtf-is-data-availability-80c2c95ded0f) -- [O que é a disponibilidade de dados?](https://coinmarketcap.com/alexandria/article/what-is-data-availability) -- [O cenário da disponibilidade de dados off-chain do Ethereum](https://blog.celestia.org/ethereum-off-chain-data-availability-landscape/) -- [Uma cartilha sobre verificações de disponibilidade de dados](https://dankradfeist.de/ethereum/2019/12/20/data-availability-checks.html) -- [Uma explicação da proposta de particionamento + DAS](https://hackmd.io/@vbuterin/sharding_proposal#ELI5-data-availability-sampling) -- [Uma nota sobre disponibilidade de dados e codificação de exclusão](https://github.com/ethereum/research/wiki/A-note-on-data-availability-and-erasure-coding#can-an-attacker-not-circumvent-this-scheme-by-releasing-a-full-unavailable-block-but-then-only-releasing-individual-bits-of-data-as-clients-query-for-them) +- [WTF is Data Availability?](https://medium.com/blockchain-capital-blog/wtf-is-data-availability-80c2c95ded0f) +- [O que é Disponibilidade de Dados?](https://coinmarketcap.com/academy/article/what-is-data-availability) +- [Uma introdução às verificações de disponibilidade de dados](https://dankradfeist.de/ethereum/2019/12/20/data-availability-checks.html) +- [Uma explicação da proposta de fragmentação + DAS](https://hackmd.io/@vbuterin/sharding_proposal#ELI5-data-availability-sampling) +- [Uma nota sobre disponibilidade de dados e codificação por apagamento](https://github.com/ethereum/research/wiki/A-note-on-data-availability-and-erasure-coding#can-an-attacker-not-circumvent-this-scheme-by-releasing-a-full-unavailable-block-but-then-only-releasing-individual-bits-of-data-as-clients-query-for-them) - [Comitês de disponibilidade de dados.](https://medium.com/starkware/data-availability-e5564c416424) -- [Comitês de disponibilidade de dados da prova de participação.](https://blog.matter-labs.io/zkporter-a-breakthrough-in-l2-scaling-ed5e48842fbf) -- [Soluções para o problema de recuperação de dados](https://notes.ethereum.org/@vbuterin/data_sharding_roadmap#Who-would-store-historical-data-under-sharding) +- [Comitês de disponibilidade de dados de prova de participação.](https://blog.matter-labs.io/zkporter-a-breakthrough-in-l2-scaling-ed5e48842fbf) +- [Soluções para o problema da recuperabilidade de dados](https://notes.ethereum.org/@vbuterin/data_sharding_roadmap#Who-would-store-historical-data-under-sharding) +- [Disponibilidade de Dados ou: Como os Rollups Aprenderam a Parar de Se Preocupar e Amar o Ethereum](https://web.archive.org/web/20250515194659/https://web.archive.org/web/20241108192208/https://research.2077.xyz/data-availability-or-how-rollups-learned-to-stop-worrying-and-love-ethereum) +- [EIP-7623: Aumentando o Custo do Calldata](https://web.archive.org/web/20250515194659/https://research.2077.xyz/eip-7623-increase-calldata-cost) diff --git a/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/index.md b/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/index.md index 21302a4f94a..67f557fdc6b 100644 --- a/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/index.md +++ b/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/index.md @@ -1,31 +1,31 @@ --- -title: Codificação e estruturas de dados -description: Visão geral das estruturas de dados fundamentais do Ethereum +title: "Codificação e estruturas de dados" +description: "Visão geral das estruturas de dados fundamentais do Ethereum" lang: pt-br sidebarDepth: 2 --- -O Ethereum cria, armazena e transfere grandes volumes de dados. Esses dados precisam ser formatados de maneiras padronizadas e eficientes em memória para permitir que qualquer pessoa [execute um nó](/run-a-node/) em um hardware de nível de consumo relativamente modesto. Para isso, várias estruturas de dados específicas são usadas na pilha do Ethereum. +O Ethereum cria, armazena e transfere grandes volumes de dados. Esses dados devem ser formatados de maneiras padronizadas e com uso eficiente de memória para permitir que qualquer pessoa [execute um nó](/run-a-node/) em um hardware de consumo relativamente modesto. Para isso, várias estruturas de dados específicas são usadas na pilha do Ethereum. -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -Você deve entender os fundamentos sobre o Ethereum e o [software cliente](/developers/docs/nodes-and-clients/). Recomenda-se familiaridade com a camada de rede e [o whitepaper sobre o Ethereum](/whitepaper/). +Você deve entender os fundamentos do Ethereum e do [software cliente](/developers/docs/nodes-and-clients/). Recomenda-se familiaridade com a camada de rede e com [o whitepaper do Ethereum](/whitepaper/). ## Estruturas de dados {#data-structures} -### Árvores Merkle Patricia {#patricia-merkle-tries} +### Tries Patricia Merkle {#patricia-merkle-tries} Árvores Merkle Patricia são estruturas que codificam pares de valor-chave em uma árvore determinística e criptograficamente autenticada. Estas são amplamente usadas em toda a camada de execução do Ethereum. -[Mais sobre Árvores Merkle Patricia](/developers/docs/data-structures-and-encoding/patricia-merkle-trie) +[Mais sobre Tries Patricia Merkle](/developers/docs/data-structures-and-encoding/patricia-merkle-trie) -### Prefixo de comprimento recursivo (RLP) {#recursive-length-prefix} +### Prefixo de Comprimento Recursivo {#recursive-length-prefix} Prefixo de comprimento recursivo (RLP) é um método de serialização usado extensivamente em toda a camada de execução do Ethereum. [Mais sobre RLP](/developers/docs/data-structures-and-encoding/rlp) -### Serialização simples {#simple-serialize} +### Serialização Simples {#simple-serialize} Serialização simples (SSZ) é o formato de serialização dominante na camada de consenso do Ethereum devido à sua compatibilidade com a "merklelização". diff --git a/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/patricia-merkle-trie/index.md b/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/patricia-merkle-trie/index.md index 8867c855bf6..8ff1c6e6bac 100644 --- a/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/patricia-merkle-trie/index.md +++ b/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/patricia-merkle-trie/index.md @@ -1,23 +1,23 @@ --- -title: Árvore Merkle Patricia -description: Introdução à àrvore Merkle Patricia +title: "Árvore Merkle Patricia" +description: "Introdução à àrvore Merkle Patricia" lang: pt-br sidebarDepth: 2 --- O estado do Ethereum (a totalidade de todas as contas, saldos e contratos inteligentes) é codificado em uma versão especial da estrutura de dados conhecida geralmente na ciência da computação como Árvore Merkle. Essa estrutura é útil para muitas aplicações em criptografia porque cria um relacionamento verificável entre todos os dados individuais emaranhados na árvore, resultando em um único valor **raiz** que pode ser usado para provar coisas sobre os dados. -A estrutura de dados do Ethereum é uma 'Merkle-Patricia Trie modificada', assim chamada porque toma emprestados alguns recursos do PATRICIA (o Algoritmo Prático para Recuperar Informações Codificadas em Alfanumérico) e porque foi projetada para ser eficiente na **recuperação de dados** de itens que compõem o estado do Ethereum. +A estrutura de dados do Ethereum é uma 'Merkle-Patricia Trie modificada', assim chamada porque toma emprestados alguns recursos do PATRICIA (o Algoritmo Prático para Recuperar Informações Codificadas em Alfanumérico) e porque foi projetada para ser eficiente na recuperação de dados de itens que compõem o estado do Ethereum. -Uma Merkle-Patricia é determinística e criptograficamente verificável: a única maneira de gerar uma raiz de estado é computando-a a partir de cada parte individual do estado, e dois estados que são idênticos podem ser facilmente provados comparando o hash raiz e os hashes que levaram a ele (_uma prova de Merkle_). Por outro lado, não há como criar dois estados diferentes com o mesmo hash raiz, e qualquer tentativa de modificar o estado com valores diferentes resultará em um hash raiz de estado diferente. Teoricamente, essa estrutura fornece o "Santo Graal" da eficiência `O(log(n))` para inserções, pesquisas e exclusões. +Uma Merkle-Patricia trie é determinística e criptograficamente verificável: a única maneira de gerar uma raiz de estado é computando-a a partir de cada parte individual do estado, e dois estados idênticos podem ser facilmente comprovados comparando o hash raiz e os hashes que levaram a ele (_uma prova de Merkle_). Por outro lado, não há como criar dois estados diferentes com o mesmo hash raiz, e qualquer tentativa de modificar o estado com valores diferentes resultará em um hash raiz de estado diferente. Teoricamente, essa estrutura fornece o 'Santo Graal' da eficiência de `O(log(n))` para inserções, buscas e exclusões. Em um futuro próximo, o Ethereum planeja migrar para uma estrutura de [Verkle Tree](/roadmap/verkle-trees), o que abrirá muitas novas possibilidades para futuras melhorias de protocolo. ## Pré-requisitos {#prerequisites} -Para entender melhor esta página, seria útil ter conhecimento básico sobre [hashes](https://en.wikipedia.org/wiki/Hash_function), [Árvores Merkle](https://en.wikipedia.org/wiki/Merkle_tree), [árvores](https://en.wikipedia.org/wiki/Trie) e [serialização](https://en.wikipedia.org/wiki/Serialization). Este artigo começa com uma descrição de uma [árvore radix](https://en.wikipedia.org/wiki/Radix_tree) básica e, em seguida, introduz gradualmente as modificações necessárias para a estrutura de dados mais otimizada do Ethereum. +Para entender melhor esta página, seria útil ter conhecimento básico de [hashes](https://en.wikipedia.org/wiki/Hash_function), [árvores de Merkle](https://en.wikipedia.org/wiki/Merkle_tree), [tries](https://en.wikipedia.org/wiki/Trie) e [serialização](https://en.wikipedia.org/wiki/Serialization). Este artigo começa com uma descrição de uma [árvore radix](https://en.wikipedia.org/wiki/Radix_tree) básica e, em seguida, introduz gradualmente as modificações necessárias para a estrutura de dados mais otimizada do Ethereum. -## Árvores radix básicas {#basic-radix-tries} +## Tries radix básicas {#basic-radix-tries} Em uma árvore radix básica, cada nó se parece com o seguinte: @@ -25,146 +25,149 @@ Em uma árvore radix básica, cada nó se parece com o seguinte: [i_0, i_1 ... i_n, value] ``` -Onde `i0 ... in` representa o símbolo do alfabeto (muitas vezes binário ou hex), `value` é o valor terminal no nó, e os valores nos slots `i0 . . in` são ou `NULL` ou ponteiros para (em nosso caso, hashes de) outros nós. Isto forma um armazenamento básico `(key, value)`. +Onde `i_0 ...` `i_n` representam os símbolos do alfabeto (geralmente binário ou hexadecimal), `value` é o valor terminal no nó, e os valores nos `i_0, i_1 ...` slots `i_n` são `NULL` ou ponteiros para (no nosso caso, hashes de) outros nós. Isso forma um armazenamento básico de `(key, value)`. -Digamos que você queria usar uma estrutura de dados da árvore radix para persistir em uma ordem em um conjunto de pares de valor-chave. Para encontrar o valor atualmente relacionado com a chave `dog` na árvore, primeiro você converteria `dog` em letras do alfabeto (dando `64 6f 67`), e então desceria pela árvore seguindo o caminho até encontrar o valor. Ou seja, você começa por procurar o hash raiz em uma base de dados texto chave/valor para encontrar o nó raiz da árvore. Ele é representado como uma matriz de chaves apontando para outros nós. Use o valor no índice `6` como uma chave e procure na base chave/valor para obter o nó um nível abaixo. Em seguida, escolha o índice `4` para procurar o próximo valor, depois escolha o índice `6` e assim por diante. Uma vez tendo seguido o caminho: `root-> 6 -> 4 -> 6 -> 15 -> 6 -> 7`, procure o valor do nó e retorne o resultado. +Digamos que você queria usar uma estrutura de dados da árvore radix para persistir em uma ordem em um conjunto de pares de valor-chave. Para encontrar o valor atualmente mapeado para a chave `dog` na trie, primeiro você converteria `dog` em letras do alfabeto (resultando em `64 6f 67`), e então desceria pela trie seguindo esse caminho até encontrar o valor. Ou seja, você começa por procurar o hash raiz em uma base de dados texto chave/valor para encontrar o nó raiz da árvore. Ele é representado como uma matriz de chaves apontando para outros nós. Você usaria o valor no índice `6` como uma chave e o procuraria no banco de dados simples de chave/valor para obter o nó um nível abaixo. Então, pegue o índice `4` para procurar o próximo valor, depois o índice `6`, e assim por diante, até que, depois de seguir o caminho: `root -> 6 -> 4 -> 6 -> 15 -> 6 -> 7`, você procuraria o valor do nó e retornaria o resultado. -Há uma diferença entre buscar algo na árvore e no banco de dados base subjacente (chave/valor). Ambos definem arranjos chave/valor, mas o DB subjacente pode fazer uma tradicional busca de 1 passo pela chave. Procurar uma chave na árvore requer várias buscas no banco de dados subjacente para obter o valor final descrito acima. Vamos nos referir a este último como um `path` para eliminar ambiguidade. +Há uma diferença entre buscar algo na árvore e no banco de dados base subjacente (chave/valor). Ambos definem arranjos chave/valor, mas o DB subjacente pode fazer uma tradicional busca de 1 passo pela chave. Procurar uma chave na árvore requer várias buscas no banco de dados subjacente para obter o valor final descrito acima. Vamos nos referir a este último como um `path` para eliminar a ambiguidade. As operações de atualização e exclusão em árvores radix são simples, e podem ser definidas da seguinte forma: -``` - def update(node,path,value): - curnode = db.get(node) if node else [ NULL ] * 17 +```python + def update(node_hash, path, value): + curnode = db.get(node_hash) if node_hash else [NULL] * 17 newnode = curnode.copy() - if path == '': + if path == "": newnode[-1] = value else: - newindex = update(curnode[path[0]],path[1:],value) + newindex = update(curnode[path[0]], path[1:], value) newnode[path[0]] = newindex - db.put(hash(newnode),newnode) + db.put(hash(newnode), newnode) return hash(newnode) - def delete(node,path): - if node is NULL: + def delete(node_hash, path): + if node_hash is NULL: return NULL else: - curnode = db.get(node) + curnode = db.get(node_hash) newnode = curnode.copy() - if path == '': + if path == "": newnode[-1] = NULL else: - newindex = delete(curnode[path[0]],path[1:]) + newindex = delete(curnode[path[0]], path[1:]) newnode[path[0]] = newindex if all(x is NULL for x in newnode): return NULL else: - db.put(hash(newnode),newnode) + db.put(hash(newnode), newnode) return hash(newnode) ``` -Uma árvore Radix "Merkle" é construída ligando os nós usando digests de hash criptográficos gerados deterministicamente. Este endereçamento de conteúdo (no BD chave/valor `key == keccak256(rlp(value))`) fornece uma integridade criptográfica garantida do dado armazenado. Se o hash raiz de um Trie - teste - determinado for conhecido publicamente, então, qualquer um com acesso aos dados da folha subjacente poderá fornecer uma prova de que o Trie - teste - inclui um determinado valor em um caminho específico, fornecendo os hashes de cada nódulo que se junta a um valor específico para a raiz da árvore. +Uma árvore Radix "Merkle" é construída ligando os nós usando digests de hash criptográficos gerados deterministicamente. Este endereçamento de conteúdo (no banco de dados de chave/valor `key == keccak256(rlp(value))`) fornece uma garantia de integridade criptográfica dos dados armazenados. Se o hash raiz de um Trie - teste - determinado for conhecido publicamente, então, qualquer um com acesso aos dados da folha subjacente poderá fornecer uma prova de que o Trie - teste - inclui um determinado valor em um caminho específico, fornecendo os hashes de cada nódulo que se junta a um valor específico para a raiz da árvore. -É impossível para um atacante fornecer uma prova de um par `(path, value)` que não exista, já que o hash raiz é, em última análise, baseado em todos os hashes abaixo dele. Qualquer modificação subjacente alteraria o hash raiz. Você pode pensar no hash como uma representação comprimida de informações estruturais sobre os dados, seguros pela proteção pré-imagem da função de hash. +É impossível para um invasor fornecer uma prova de um par `(path, value)` que não existe, pois o hash raiz é, em última instância, baseado em todos os hashes abaixo dele. Qualquer modificação subjacente alteraria o hash raiz. Você pode pensar no hash como uma representação comprimida de informações estruturais sobre os dados, seguros pela proteção pré-imagem da função de hash. -Vamos nos referir a uma unidade atômica de uma árvore de radix (por exemplo, um único caractere hexadecimal, ou número binário de 4 bits) como um "nibble". Ao percorrerem um caminho um nibble de cada vez, conforme descrito acima, os nós podem fazer referência a 16 filhos, no máximo, mas incluir um elemento `value`. Portanto, nós os representamos como uma faixa de comprimento 17. Chamamos esses arrays de 17 elementos de "branch nodes". +Nós nos referiremos a uma unidade atômica de uma árvore radix (por exemplo, um único caractere hexadecimal, ou um número binário de 4 bits) como um \"nibble\". Ao percorrer um caminho um nibble de cada vez, como descrito acima, os nós podem se referir a no máximo 16 filhos, mas incluem um elemento de `value`. Portanto, nós os representamos como uma faixa de comprimento 17. Chamamos esses arrays de 17 elementos de "branch nodes". -## Árvore Merkle Patricia {#merkle-patricia-trees} +## Trie Merkle Patricia {#merkle-patricia-trees} -As árvores radix têm uma grande limitação: são ineficientes. Se você quiser armazenar uma vinculação `(path, value)` em que o caminho tem, como no Ethereum, 64 caracteres de comprimento (o número de nibbles em `bytes32`), você vai precisar de mais de um kilobyte de espaço extra para armazenar um nível por caractere, e cada busca ou exclusão precisará das 64 etapas completas. A árvore Patricia apresentada aqui resolve esta questão. +As árvores radix têm uma grande limitação: são ineficientes. Se você quiser armazenar uma vinculação `(path, value)` onde o caminho, como no Ethereum, tem 64 caracteres (o número de nibbles em `bytes32`), precisaremos de mais de um kilobyte de espaço extra para armazenar um nível por caractere, e cada busca ou exclusão levará 64 passos completos. A árvore Patricia apresentada aqui resolve esta questão. ### Otimização {#optimization} Um nó em uma árvore Merkle Patricia é um dos seguintes: -1. `NULL` (representado como a string vazia) -2. `branch` Um nó de 17 itens `[ v0 ... v15, vt ]` -3. `leaf` Um nó de 2 itens `[ encodedPath, value ]` -4. `extension` Um nó de 2 itens `[ encodedPath, key ]` +1. `NULL` (representado como a string vazia) +2. `branch` Um nó de 17 itens `[ v0 ...` `v15, vt ]` +3. `leaf` Um nó de 2 itens `[ encodedPath, value ]` +4. `extension` Um nó de 2 itens `[ encodedPath, key ]` -Com caminhos de 64 caracteres, é inevitável que depois de atravessar as primeiras poucas camadas da árvore, você alcançe um nó em que não existe caminho divergente para pelo menos parte do caminho para baixo. Para evitar ter que criar até 15 nós esparsos `NULL` ao longo do caminho, encurtamos a descida configurando um nó de ` extension` do formulário `[ encodedPath, key ]`, em que `encodedPath` contém o "caminho parcial" a ignorar (usando uma codificação compacta descrita abaixo), e a `key` é para a próxima pesquisa no banco de dados. +Com caminhos de 64 caracteres, é inevitável que depois de atravessar as primeiras poucas camadas da árvore, você alcançe um nó em que não existe caminho divergente para pelo menos parte do caminho para baixo. Para evitar ter que criar até 15 nós `NULL` esparsos ao longo do caminho, encurtamos a descida configurando um nó de `extension` da forma `[ encodedPath, key ]`, onde `encodedPath` contém o \"caminho parcial\" para avançar (usando uma codificação compacta descrita abaixo), e a `key` é para a próxima consulta ao banco de dados. -Para um nó de `leaf`, que pode ser marcado por um flag na primeira nibble do `encodedPath`, o caminho codifica todos os fragmentos de caminho do nó anterior e podemos procurar o `value` diretamente. +Para um nó `leaf`, que pode ser marcado por uma flag no primeiro nibble do `encodedPath`, o caminho codifica todos os fragmentos de caminho do nó anterior e podemos consultar o `value` diretamente. Esta otimização acima, porém, introduz ambiguidade. -Quando atravessamos caminhos em nibbles, podemos acabar com um número ímpar de nibbles para percorrer, mas porque todos os dados são armazenados no formato `bytes`. Não é possível diferenciar entre, por exemplo, o nibble `1` e os nibbles`01` (ambos devem ser armazenados como `<01>`). Para especificar comprimento ímpar, o caminho parcial é precedido com um flag. +Ao percorrer caminhos em nibbles, podemos acabar com um número ímpar de nibbles para atravessar, mas como todos os dados são armazenados em formato de `bytes`. Não é possível diferenciar, por exemplo, o nibble `1` dos nibbles `01` (ambos devem ser armazenados como `<01>`). Para especificar comprimento ímpar, o caminho parcial é precedido com um flag. ### Especificação: Codificação compacta de sequência hexadecimal com terminador opcional {#specification} -A sinalização de _largura restante do caminho parcial, par ou ímpar,_ e de _nó leaf vs nó de extensão_ conforme descrito acima reside no primeiro nibble do caminho parcial de qualquer nó de 2 elementos. Eles resultam no seguinte: +A sinalização de _comprimento do caminho parcial restante par ou ímpar_ e de _nó folha versus nó de extensão_, como descrito acima, reside no primeiro nibble do caminho parcial de qualquer nó de 2 itens. Eles resultam no seguinte: - hex char bits | node type partial path length - ---------------------------------------------------------- - 0 0000 | extension even - 1 0001 | extension odd - 2 0010 | terminating (leaf) even - 3 0011 | terminating (leaf) odd +| caractere hexadecimal | bits | node tipo parcial | comprimento do caminho | +| --------------------- | ---- | ------------------------------------- | ---------------------- | +| 0 | 0000 | extensão | par | +| 1 | 0001 | extensão | mínima vantagem | +| 2 | 0010 | terminação (folha) | par | +| 3 | 0011 | terminação (folha) | mínima vantagem | -Para um comprimento restante de caminho par (`0` ou `2`), sempre seguirá um outro nibble "padding" `0`. +Para um comprimento de caminho restante par (`0` ou `2`), outro nibble `0` de \"preenchimento\" sempre se seguirá. -``` +```python def compact_encode(hexarray): term = 1 if hexarray[-1] == 16 else 0 - if term: hexarray = hexarray[:-1] + if term: + hexarray = hexarray[:-1] oddlen = len(hexarray) % 2 flags = 2 * term + oddlen if oddlen: hexarray = [flags] + hexarray else: hexarray = [flags] + [0] + hexarray - // hexarray now has an even length whose first nibble is the flags. - o = '' - for i in range(0,len(hexarray),2): - o += chr(16 * hexarray[i] + hexarray[i+1]) + # hexarray agora tem um comprimento par cujo primeiro nibble são as flags. + o = "" + for i in range(0, len(hexarray), 2): + o += chr(16 * hexarray[i] + hexarray[i + 1]) return o ``` Exemplos: -``` - > [ 1, 2, 3, 4, 5, ...] +```python + > [1, 2, 3, 4, 5, ...] '11 23 45' - > [ 0, 1, 2, 3, 4, 5, ...] + > [0, 1, 2, 3, 4, 5, ...] '00 01 23 45' - > [ 0, f, 1, c, b, 8, 10] + > [0, f, 1, c, b, 8, 10] '20 0f 1c b8' - > [ f, 1, c, b, 8, 10] + > [f, 1, c, b, 8, 10] '3f 1c b8' ``` Aqui está o código estendido para obter um nó na árvore Merkle Patricia: -``` - def get_helper(node,path): - if path == []: return node - if node = '': return '' - curnode = rlp.decode(node if len(node) < 32 else db.get(node)) +```python + def get_helper(node_hash, path): + if path == []: + return node_hash + if node_hash == "": + return "" + curnode = rlp.decode(node_hash if len(node_hash) < 32 else db.get(node_hash)) if len(curnode) == 2: (k2, v2) = curnode k2 = compact_decode(k2) - if k2 == path[:len(k2)]: - return get(v2, path[len(k2):]) + if k2 == path[: len(k2)]: + return get(v2, path[len(k2) :]) else: - return '' + return "" elif len(curnode) == 17: - return get_helper(curnode[path[0]],path[1:]) + return get_helper(curnode[path[0]], path[1:]) - def get(node,path): + def get(node_hash, path): path2 = [] for i in range(len(path)): path2.push(int(ord(path[i]) / 16)) path2.push(ord(path[i]) % 16) path2.push(16) - return get_helper(node,path2) + return get_helper(node_hash, path2) ``` -### Árvore de exemplo {#example-trie} +### Exemplo de Trie {#example-trie} -Suponha que queremos um trie contendo quatro pares de caminho/valor `('do', 'verb')`, `('dog', 'puppy')`, `('doge', 'coins')`, `('horse', 'stallion')`. +Suponha que queiramos uma trie contendo quatro pares de caminho/valor: `('do', 'verb')`, `('dog', 'puppy')`, `('doge', 'coins')`, `('horse', 'stallion')`. -Primeiro, convertemos ambos caminhos e valores para `bytes`. Abaixo, representações reais em bytes para _caminhos_ são indicadas por `<>`, embora _valores_ ainda sejam mostrados como strings, denotado por `''`, para melhor compreensão (eles, também, seriam `bytes`): +Primeiro, convertemos os caminhos e valores para `bytes`. Abaixo, as representações de bytes reais para _paths_ são denotadas por `<>`, embora os _values_ ainda sejam mostrados como strings, denotados por `''`, para facilitar a compreensão (eles também seriam `bytes`): ``` <64 6f> : 'verb' @@ -183,38 +186,38 @@ Agora, construímos uma árvore com os seguintes pares chave/valor no banco de d hashD: [ <17>, [ <>, <>, <>, <>, <>, <>, [ <35>, 'coins' ], <>, <>, <>, <>, <>, <>, <>, <>, <>, 'puppy' ] ] ``` -Quando um nó é referenciado dentro de outro nó, o que é incluído é `H(rlp.encode(node))`, onde `H(x) = keccak256(x) if len(x) >= 32 else x` e `rlp.encode` é a função de codificação [RLP](/developers/docs/data-structures-and-encoding/rlp). +Quando um nó é referenciado dentro de outro nó, o que é incluído é `keccak256(rlp.encode(node))`, se `len(rlp.encode(node)) >= 32` senão `node`, onde `rlp.encode` é a função de codificação [RLP](/developers/docs/data-structures-and-encoding/rlp). -Observe que, ao atualizar uma árvore, é necessário armazenar o par chave/valor `(keccak256(x), x)` em uma tabela de pesquisa persistente _se_ o nó recém-criado tem comprimento >= 32. Entretanto, se o nó é menor do que isso, não é preciso armazenar nada, já que a função f(x) = x é reversível. +Observe que, ao atualizar uma trie, é necessário armazenar o par de chave/valor `(keccak256(x), x)` em uma tabela de consulta persistente _se_ o nó recém-criado tiver um comprimento >= 32. Entretanto, se o nó é menor do que isso, não é preciso armazenar nada, já que a função f(x) = x é reversível. -## Árvores no Ethereum {#tries-in-ethereum} +## Tries no Ethereum {#tries-in-ethereum} Todas as árvores Merkle na camada de execução do Ethereum usam uma árvore Merkle Patricia. Do cabeçalho do bloco há 3 raízes dessas 3 árvores. -1. stateRoot -2. transactionsRoot -3. receiptsRoot +1. stateRoot +2. transactionsRoot +3. receiptsRoot -### Árvore de estado {#state-trie} +### Trie de Estado {#state-trie} -Existe um estado global da árvore que é atualizado toda vez que um cliente processa um bloco. Nela, um `path` é sempre: `keccak256(ethereumAddress)` e um `value` é sempre: `rlp(ethereumAccount)`. Mais especificamente uma `conta` Ethereum é uma array de 4 itens `[nonce,balance,storageRoot,codeHash]`. Neste ponto, vale a pena notar que este `storageRoot` é a raiz de outra árvore Patricia: +Existe um estado global da árvore que é atualizado toda vez que um cliente processa um bloco. Nela, um `path` é sempre: `keccak256(ethereumAddress)` e um `value` é sempre: `rlp(ethereumAccount)`. Mais especificamente, uma `conta` Ethereum é um array de 4 itens: `[nonce,balance,storageRoot,codeHash]`. Neste ponto, vale a pena notar que esta `storageRoot` é a raiz de outra trie Patricia: -### Árvore de armazenamento {#storage-trie} +### Trie de armazenamento {#storage-trie} -Árvore de armazenamento é onde _todos_ os dados de contrato se encontram. Há uma árvore de armazenamento separada para cada conta. Para recuperar valores em posições específicas de armazenamento em um determinado endereço, o endereço de armazenamento, posição inteira dos dados armazenados no armazenamento, e a ID do bloco, são necessárias. Eles podem então ser passados como argumentos para `eth_getStorageAt` definido na API JSON-RPC, por exemplo, para recuperar os dados no slot de armazenamento 0 para o endereço `0x295a70b2de5e3953354a6a8344e616ed314d7251`: +A trie de armazenamento é onde _todos_ os dados de contrato residem. Há uma árvore de armazenamento separada para cada conta. Para recuperar valores em posições específicas de armazenamento em um determinado endereço, o endereço de armazenamento, posição inteira dos dados armazenados no armazenamento, e a ID do bloco, são necessárias. Estes podem então ser passados como argumentos para o `eth_getStorageAt` definido na API JSON-RPC, por exemplo, para recuperar os dados no slot de armazenamento 0 para o endereço `0x295a70b2de5e3953354a6a8344e616ed314d7251`: -``` +```bash curl -X POST --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x0", "latest"], "id": 1}' localhost:8545 {"jsonrpc":"2.0","id":1,"result":"0x00000000000000000000000000000000000000000000000000000000000004d2"} ``` -Recuperar outros elementos no armazenamento é um pouco mais complicado, porque a posição na árvore de armazenamento deve ser calculada primeiro. A posição é calculada como o hash `keccak256` do endereço e da posição de armazenamento, ambos alinhados à esquerda com zeros para um comprimento de 32 bytes. Por exemplo, a posição para os dados no slot 1 de armazenamento para o endereço `0x391694e7e0b0cce554cb130d723a9d27458f9298` é: +Recuperar outros elementos no armazenamento é um pouco mais complicado, porque a posição na árvore de armazenamento deve ser calculada primeiro. A posição é calculada como o hash `keccak256` do endereço e da posição de armazenamento, ambos preenchidos à esquerda com zeros para um comprimento de 32 bytes. Por exemplo, a posição dos dados no slot de armazenamento 1 para o endereço `0x391694e7e0b0cce554cb130d723a9d27458f9298` é: -``` +```python keccak256(decodeHex("000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + "0000000000000000000000000000000000000000000000000000000000000001")) ``` @@ -229,19 +232,19 @@ undefined O `path` é, portanto, `keccak256(<6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9>)`. Isso agora pode ser usado para recuperar os dados da árvore de armazenamento como antes: -``` +```bash curl -X POST --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9", "latest"], "id": 1}' localhost:8545 {"jsonrpc":"2.0","id":1,"result":"0x000000000000000000000000000000000000000000000000000000000000162e"} ``` -Nota: O `storageRoot` para uma conta Ethereum está vazio pelo padrão se ele não for uma conta de contrato. +Observação: O `storageRoot` de uma conta Ethereum está vazio por padrão se não for uma conta de contrato. -### Árvore de transações {#transaction-trie} +### Trie de Transações {#transaction-trie} -Há uma árvore de transações separada para cada bloco, armazenando novamente pares `(key, value)`. Um caminho aqui é: `rlp(transactionIndex)` que representa a chave que corresponde a um valor determinado por: +Existe uma trie de transações separada para cada bloco, armazenando novamente pares `(chave, valor)`. Um caminho aqui é: `rlp(transactionIndex)`, que representa a chave que corresponde a um valor determinado por: -``` +```python if legacyTx: value = rlp(tx) else: @@ -250,14 +253,14 @@ else: Mais informações sobre isso podem ser encontradas na documentação do [EIP 2718](https://eips.ethereum.org/EIPS/eip-2718). -### Árvore de recibos {#receipts-trie} +### Trie de Recibos {#receipts-trie} -Cada bloco tem sua própria árvore de recibos. Um `path` aqui é: `rlp(transactionIndex)`. `transactionIndex` é seu índice dentro do bloco em que foi incluído. A árvore de recibos nunca é atualizada. De maneira similar à árvore de Transações, existem recibos atuais e legados. Para consultar um recibo específico na árvore de Recibos, o índice da transação em seu bloco, o payload do recibo e o tipo de transação são necessários. O recibo retornado pode ser do tipo `Receipt`, que é definido como a concentração de `TransactionType` e `ReceiptPayload`, ou pode ser do tipo `LegacyReceipt`, que é definido como `rlp([status, acumulativoGasUsed, logsBloom, logs])`. +Cada bloco tem sua própria árvore de recibos. Um `path` aqui é: `rlp(transactionIndex)`. `transactionIndex` é seu índice dentro do bloco em que foi incluído. A árvore de recibos nunca é atualizada. De maneira similar à árvore de Transações, existem recibos atuais e legados. Para consultar um recibo específico na árvore de Recibos, o índice da transação em seu bloco, o payload do recibo e o tipo de transação são necessários. O recibo retornado pode ser do tipo `Receipt`, que é definido como a concatenação de `TransactionType` e `ReceiptPayload` ou pode ser do tipo `LegacyReceipt`, que é definido como `rlp([status, cumulativeGasUsed, logsBloom, logs])`. Mais informações sobre isso podem ser encontradas na documentação do [EIP 2718](https://eips.ethereum.org/EIPS/eip-2718). -## Leitura Adicional {#further-reading} +## Leitura adicional {#further-reading} -- [Árvore Merkle Patricia modificada: como o Ethereum salva um estado](https://medium.com/codechain/modified-merkle-patricia-trie-how-ethereum-saves-a-state-e6d7555078dd) -- [Fazendo Merkle no Ethereum](https://blog.ethereum.org/2015/11/15/merkling-in-ethereum) -- [Entendendo a árvore Ethereum](https://easythereentropy.wordpress.com/2014/06/04/understanding-the-ethereum-trie/) +- [Trie Merkle Patricia Modificada — Como o Ethereum salva um estado](https://medium.com/codechain/modified-merkle-patricia-trie-how-ethereum-saves-a-state-e6d7555078dd) +- [Merkling no Ethereum](https://blog.ethereum.org/2015/11/15/merkling-in-ethereum/) +- [Entendendo a trie do Ethereum](https://easythereentropy.wordpress.com/2014/06/04/understanding-the-ethereum-trie/) diff --git a/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/rlp/index.md b/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/rlp/index.md index f30c5045b80..cc40d982410 100644 --- a/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/rlp/index.md +++ b/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/rlp/index.md @@ -1,24 +1,24 @@ --- -title: Serialização do prefixo de comprimento recursivo (RLP) -description: Uma definição da codificação RLP na camada de execução do Ethereum +title: "Serialização do prefixo de comprimento recursivo (RLP)" +description: "Uma definição da codificação RLP na camada de execução do Ethereum" lang: pt-br sidebarDepth: 2 --- -A Serialização do prefixo de comprimento recursivo (RLP) é usado extensivamente nos clientes de execução Ethereum. RLP padroniza a transferência de dados entre nós em um formato eficiente em espaço. O objetivo do RLP é codificar arbitrariamente arrays de dados binários aninhados, e o RLP é o principal método de codificação usado para serializar objetos na camada de execução do Ethereum. O principal objetivo do RLP é codificar a estrutura; com exceção de números inteiros positivos, o RLP delega a codificação de tipos de dados específicos (por exemplo, strings, floats) para protocolos de ordem superior. Os inteiros positivos devem ser representados no formato binário big-endian, sem zeros à esquerda (tornando assim o valor inteiro zero equivalente ao array de bytes vazio). Inteiros positivos desserializados com zeros à esquerda devem ser tratados como inválidos por qualquer protocolo de ordem superior que use RLP. +A Serialização do prefixo de comprimento recursivo (RLP) é usado extensivamente nos clientes de execução Ethereum. RLP padroniza a transferência de dados entre nós em um formato eficiente em espaço. O objetivo do RLP é codificar arbitrariamente arrays de dados binários aninhados, e o RLP é o principal método de codificação usado para serializar objetos na camada de execução do Ethereum. O objetivo principal do RLP é codificar a estrutura; com exceção de números inteiros positivos, o RLP delega a codificação de tipos de dados específicos (por exemplo, strings, floats) para protocolos de ordem superior. Os inteiros positivos devem ser representados no formato binário big-endian, sem zeros à esquerda (tornando assim o valor inteiro zero equivalente ao array de bytes vazio). Inteiros positivos desserializados com zeros à esquerda devem ser tratados como inválidos por qualquer protocolo de ordem superior que use RLP. -Mais informações nas [ páginas amarelas Ethereum (Apêndice B)](https://ethereum.github.io/yellowpaper/paper.pdf#page=19). +Mais informações em [o yellow paper do Ethereum (Apêndice B)](https://ethereum.github.io/yellowpaper/paper.pdf#page=19). Para usar o RLP para codificar um dicionário, as duas formas canônicas são: -- usar `[[k1,v1],[k2,v2]...]` com chaves em ordem lexicográfica +- use `[[k1,v1],[k2,v2]...]` com chaves em ordem lexicográfica - usar a codificação da Árvore Patricia de nível superior como Ethereum faz ## Definição {#definition} A função de codificação RLP recebe um item. Um item é definido como abaixo: -- uma string (ou seja, um byte array) é um item +- uma string (ou seja, matriz de bytes) é um item - uma lista de itens é um item - um inteiro positivo é um item @@ -27,7 +27,7 @@ Por exemplo, todos os seguintes são itens: - uma string vazia; - a string que contém a palavra "cat"; - uma lista contendo qualquer número de strings; -- e uma estrutura de dados mais complexa, como `["cat", ["puppy", "cow"], "horse", [[]], "pig", [""], "sheep"]`. +- e estruturas de dados mais complexas como `["cat", ["puppy", "cow"], "horse", [[]], "pig", [""], "sheep"]`. - o número `100` Observe que, no contexto do restante desta página, 'string' significa "um certo número de bytes de dados binários"; nenhuma codificação especial é usada, e nenhum conhecimento sobre o conteúdo das strings é implícito (exceto conforme exigido pela regra contra inteiros positivos não mínimos). @@ -35,12 +35,12 @@ Observe que, no contexto do restante desta página, 'string' significa "um certo A codificação RLP é definida da seguinte forma: - Para um número inteiro positivo, ele é convertido para o menor array de bytes cuja interpretação big-endian é o número inteiro e, então, codificado como uma string de acordo com as regras abaixo. -- Para um único byte cujo valor está na faixa `[0x00, 0x7f]` (decimal `[0, 127]`), este byte é a sua própria codificação RLP. -- Caso contrário, se uma string tem de 0 a 55 bytes de comprimento, a codificação RLP consiste em um único byte com valor **0x80** (dec. 128) mais o comprimento da string seguida pela string. O intervalo do primeiro byte é, portanto, `[0x80, 0xb7]` (dec. `[128, 183]`). -- Se uma string tem mais de 55 bytes de comprimento, a codificação RLP consiste em um único byte com valor **0xb7** (dec. 183) mais o comprimento em bytes do comprimento da sequência de caracteres na forma binária, seguido pelo comprimento da string, seguido pela string. Por exemplo, uma string de 1024 bytes de comprimento seria codificada como `\xb9\x04\x00` (dec. `185, 4, 0`) seguida pela string. Aqui, `0xb9` (183 + 2 = 185) como o primeiro byte, seguido pelos 2 bytes `0x0400` (dec. 1024) que denotam o comprimento da string real. O intervalo do primeiro byte é, portanto, `[0x80, 0xb7]` (dec. `[184, 191]`). +- Para um único byte cujo valor está no intervalo `[0x00, 0x7f]` (decimal `[0, 127]`), esse byte é sua própria codificação RLP. +- Caso contrário, se uma string tiver de 0 a 55 bytes de comprimento, a codificação RLP consiste em um único byte com valor **0x80** (dec. 128) mais o comprimento da string, seguido pela string. O intervalo do primeiro byte é, portanto, `[0x80, 0xb7]` (dec. `[128, 183]`). +- Se uma string tiver mais de 55 bytes de comprimento, a codificação RLP consiste em um único byte com valor **0xb7** (dec. 183) mais o comprimento em bytes do comprimento da string em forma binária, seguido pelo comprimento da string, seguido pela string. Por exemplo, uma string de 1024 bytes de comprimento seria codificada como `\xb9\x04\x00` (dec. `185, 4, 0`) seguida pela string. Aqui, `0xb9` (183 + 2 = 185) como o primeiro byte, seguido pelos 2 bytes `0x0400` (dec. 1024) que indicam o comprimento da string real. O intervalo do primeiro byte é, portanto, `[0xb8, 0xbf]` (dec. `[184, 191]`). - Se uma string tiver 2^64 bytes de comprimento ou mais, ela poderá não ser codificada. -- Se o total de carga de uma lista (ou seja, o comprimento combinado de totos os seus itens com codificação RLP) tiver 0 a 55 bytes de comprimento, a codificação RLP consiste em um único byte com valor **0xc0** mais o comprimento da carga seguido da concatenação das codificações dos itens. O intervalo do primeiro byte é, portanto, `[0x80, 0xb7]` (dec. `[192, 247]`). -- Se o payload total de uma lista tem mais de 55 bytes de comprimento, a codificação RLP consiste em um único byte com valor **0xf7** mais o comprimento em bytes do payload na forma binária, seguida pelo comprimento do payload, seguido pela concatenação das codificações RLP dos itens. O intervalo do primeiro byte é, portanto, `[0x80, 0xb7]` (dec. `[248, 255]`). +- Se o payload total de uma lista (ou seja, o comprimento combinado de todos os seus itens codificados em RLP) tiver de 0 a 55 bytes de comprimento, a codificação RLP consiste em um único byte com valor **0xc0** mais o comprimento do payload, seguido pela concatenação das codificações RLP dos itens. O intervalo do primeiro byte é, portanto, `[0xc0, 0xf7]` (dec. `[192, 247]`). +- Se o payload total de uma lista tiver mais de 55 bytes de comprimento, a codificação RLP consiste em um único byte com valor **0xf7** mais o comprimento em bytes do comprimento do payload em forma binária, seguido pelo comprimento do payload, seguido pela concatenação das codificações RLP dos itens. O intervalo do primeiro byte é, portanto, `[0xf8, 0xff]` (dec. `[248, 255]`). Em código, isto é: @@ -62,7 +62,7 @@ def encode_length(L, offset): elif L < 256**8: BL = to_binary(L) return chr(len(BL) + offset + 55) + BL - raise Exception("input too long") + raise Exception("input too long") def to_binary(x): if x == 0: @@ -80,30 +80,30 @@ def to_binary(x): - o byte '\\x00' = `[ 0x00 ]` - o byte '\\x0f' = `[ 0x0f ]` - os bytes '\\x04\\x00' = `[ 0x82, 0x04, 0x00 ]` -- [define a representação teórica](http://en.wikipedia.org/wiki/Set-theoretic_definition_of_natural_numbers) para três, `[ [], [[]], [ [], [[]] ] ] = [ 0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0 ]` +- a [representação teórica de conjuntos](http://en.wikipedia.org/wiki/Set-theoretic_definition_of_natural_numbers) de três, `[ [], [[]], [ [], [[]] ] ] = [ 0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0 ]` - a string "Lorem ipsum dolor sit amet, consectetur adipisicing elit" = `[ 0xb8, 0x38, 'L', 'o', 'r', 'e', 'm', ' ', ... , 'e', 'l', 'i', 't' ]` ## Decodificação RLP {#rlp-decoding} De acordo com as regras e o processo de codificação RLP, a entrada da decodificação RLP é considerada uma matriz de dados binários. O processo de decodificação do RLP é o seguinte: -1. de acordo com o primeiro byte (ou seja, o prefixo) dos dados de entrada e a decodificação do tipo de dados, o comprimento do dado em si e deslocamento; +1. de acordo com o primeiro byte (ou seja, prefixo) dos dados de entrada e decodificando o tipo de dados, o comprimento dos dados reais e o deslocamento; -2. de acordo com o tipo e deslocamento dos dados, decodificar os dados de maneira correspondente, respeitando a regra de codificação mínima para inteiros positivos; +2. de acordo com o tipo e deslocamento dos dados, decodificar os dados de maneira correspondente, respeitando a regra de codificação mínima para inteiros positivos; -3. continue a decodificar o resto da entrada; +3. continue a decodificar o resto da entrada; Entre elas, as regras de decodificação de tipos de dados e deslocamento são as seguintes: -1. os dados são uma string se a faixa do primeiro byte (por exemplo, prefixo) é [0x00, 0x7f], e a string é exatamente o primeiro byte; +1. os dados são uma string se o intervalo do primeiro byte (ou seja, prefixo) for [0x00, 0x7f], e a string for exatamente o primeiro byte; -2. o dado é uma string se o intervalo do primeiro byte é [0x80, 0xb7], e a string cujo comprimento é igual ao primeiro byte menos 0x80 segue o primeiro byte; +2. o dado é uma string se o intervalo do primeiro byte é [0x80, 0xb7], e a string cujo comprimento é igual ao primeiro byte menos 0x80 segue o primeiro byte; -3. os dados são uma string se o intervalo do primeiro byte é [0xb8, 0xbf] e o comprimento da string cujo comprimento em bytes é igual ao primeiro byte menos 0xb7 segue primeiro byte, e a cadeia de caracteres segue o comprimento da string; +3. os dados são uma string se o intervalo do primeiro byte é [0xb8, 0xbf] e o comprimento da string cujo comprimento em bytes é igual ao primeiro byte menos 0xb7 segue primeiro byte, e a cadeia de caracteres segue o comprimento da string; -4. os dados são uma lista se o intervalo do primeiro byte é [0xc0, 0xf7], e a concatenação das codificações RLP de todos os itens da lista que a carga total é igual ao primeiro byte menos 0xc0 e segue o primeiro byte; +4. os dados são uma lista se o intervalo do primeiro byte é [0xc0, 0xf7], e a concatenação das codificações RLP de todos os itens da lista que a carga total é igual ao primeiro byte menos 0xc0 e segue o primeiro byte; -5. os dados são uma string se o intervalo do primeiro byte é [0xb8, 0xbf], e o payload total da lista cujo comprimento é igual ao primeiro byte menos 0xf7 segue o primeiro byte, e a concatenação das codificações RLP de todos os itens da lista segue o payload total da lista; +5. os dados são uma string se o intervalo do primeiro byte é [0xb8, 0xbf], e o payload total da lista cujo comprimento é igual ao primeiro byte menos 0xf7 segue o primeiro byte, e a concatenação das codificações RLP de todos os itens da lista segue o payload total da lista; Em código, isto é: @@ -154,10 +154,10 @@ def to_integer(b): ## Leitura adicional {#further-reading} -- [RLP em Ethereum](https://medium.com/coinmonks/data-structure-in-ethereum-episode-1-recursive-length-prefix-rlp-encoding-decoding-d1016832f919) -- [Ethereum nos bastidores: RLP](https://medium.com/coinmonks/ethereum-under-the-hood-part-3-rlp-decoding-df236dc13e58) +- [RLP no Ethereum](https://medium.com/coinmonks/data-structure-in-ethereum-episode-1-recursive-length-prefix-rlp-encoding-decoding-d1016832f919) +- [Ethereum por baixo dos panos: RLP](https://medium.com/coinmonks/ethereum-under-the-hood-part-3-rlp-decoding-df236dc13e58) - [Coglio, A. (2020). Prefixo de comprimento recursivo do Ethereum em ACL2. arXiv preprint arXiv:2009.13769.](https://arxiv.org/abs/2009.13769) ## Tópicos relacionados {#related-topics} -- [Árvore Patricia Merkle](/developers/docs/data-structures-and-encoding/patricia-merkle-trie) +- [Patricia Merkle trie](/developers/docs/data-structures-and-encoding/patricia-merkle-trie) diff --git a/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/ssz/index.md b/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/ssz/index.md index 0193151103a..1f2bf0a91cf 100644 --- a/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/ssz/index.md +++ b/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/ssz/index.md @@ -1,11 +1,11 @@ --- -title: Serialização simples -description: Explicação do formato SSZ do Ethereum +title: "Serialização simples" +description: "Explicação do formato SSZ do Ethereum" lang: pt-br sidebarDepth: 2 --- -A **serialização simples (SSZ ou simple serialize)** é o método de serialização usado na Beacon Chain. Ela substitui a serialização RLP usada na camada de execução em toda a camada de consenso, exceto no protocolo de descoberta de pares. SSZ foi projetado para ser determinístico e também para Merkleize (transformações em árvores de Merkle) de forma eficiente. SSZ pode ser pensado como tendo dois componentes: um esquema de serialização e um esquema de Merkleization que é projetado para trabalhar eficientemente com a estrutura de dados serializada. +**A serialização simples (SSZ)** é o método de serialização usado na Beacon Chain. Ela substitui a serialização RLP usada na camada de execução em toda a camada de consenso, exceto no protocolo de descoberta de pares. Para saber mais sobre a serialização RLP, consulte [Prefixo de comprimento recursivo (RLP)](/developers/docs/data-structures-and-encoding/rlp/). SSZ foi projetado para ser determinístico e também para Merkleize (transformações em árvores de Merkle) de forma eficiente. SSZ pode ser pensado como tendo dois componentes: um esquema de serialização e um esquema de Merkleization que é projetado para trabalhar eficientemente com a estrutura de dados serializada. ## Como funciona o SSZ? {#how-does-ssz-work} @@ -16,7 +16,7 @@ SSZ é um esquema de serialização que não é autodescritivo. Em vez disso, el - inteiros sem sinal - booleanos -Para tipos complexos de "composição", a serialização é mais complicada porque o tipo composto contém múltiplos elementos que podem ter diferentes tipos ou tamanhos diferentes, ou ambos. Onde todos esses objetos têm comprimentos fixos (ou seja, o tamanho dos elementos sempre será constante, independentemente de seus valores reais), a serialização é simplesmente uma conversão de cada elemento no tipo composto ordenado em strings de bytes little-endian. Estas strings de bytes estão unidas. O objeto serializado tem a representação de bytelist (array de bytes) dos elementos de comprimento fixo na mesma ordem em que aparecem no objeto desserializado. +Para tipos complexos de "composição", a serialização é mais complicada porque o tipo composto contém múltiplos elementos que podem ter diferentes tipos ou tamanhos diferentes, ou ambos. Quando estes objetos têm todos comprimentos fixos (isto é, o tamanho dos elementos é sempre constante, independentemente dos seus valores reais), a serialização é simplesmente a conversão de cada elemento no tipo composto, ordenado em strings de bytes little-endian. Estas strings de bytes estão unidas. O objeto serializado tem a representação de bytelist (array de bytes) dos elementos de comprimento fixo na mesma ordem em que aparecem no objeto desserializado. Para tipos com comprimentos variáveis, os dados reais são substituídos por um valor de "deslocamento" na posição desse elemento no objeto serializado. Os dados reais são adicionados a uma pilha (área de memória dinâmica) no final do objeto serializado. O valor de deslocamento é o índice para o início dos dados reais na pilha, atuando como um ponteiro para os bytes relevantes. @@ -44,14 +44,14 @@ O exemplo abaixo ilustra como o deslocamento funciona para um contêiner com ele ``` -`serialized` teria a seguinte estrutura (apenas preenchido com 4 bits aqui, mas preenchido com 32 bits na realidade e mantendo a representação `int` para clareza): +`serialized` teria a seguinte estrutura (apenas preenchido para 4 bits aqui, preenchido para 32 bits na realidade e mantendo a representação `int` para maior clareza): ``` [37, 0, 0, 0, 55, 0, 0, 0, 16, 0, 0, 0, 22, 0, 0, 0, 1, 2, 3, 4] ------------ ----------- ----------- ----------- ---------- | | | | | - number1 number2 offset for number 3 value for - vector vector + number1 number2 deslocamento number3 valor + do vector do vector ``` @@ -59,11 +59,11 @@ dividido em linhas para clareza: ``` [ - 37, 0, 0, 0, # little-endian encoding of `number1`. - 55, 0, 0, 0, # little-endian encoding of `number2`. - 16, 0, 0, 0, # The "offset" that indicates where the value of `vector` starts (little-endian 16). - 22, 0, 0, 0, # little-endian encoding of `number3`. - 1, 2, 3, 4, # The actual values in `vector`. + 37, 0, 0, 0, # codificação little-endian de `number1`. + 55, 0, 0, 0, # codificação little-endian de `number2`. + 16, 0, 0, 0, # O "deslocamento" que indica onde o valor de `vector` começa (little-endian 16). + 22, 0, 0, 0, # codificação little-endian de `number3`. + 1, 2, 3, 4, # Os valores reais em `vector`. ] ``` @@ -71,54 +71,54 @@ Isso ainda é uma simplificação. Os inteiros e zeros nos esquemas acima, na ve ``` [ - 10100101000000000000000000000000 # little-endian encoding of `number1` - 10110111000000000000000000000000 # little-endian encoding of `number2`. - 10010000000000000000000000000000 # The "offset" that indicates where the value of `vector` starts (little-endian 16). - 10010110000000000000000000000000 # little-endian encoding of `number3`. - 10000001100000101000001110000100 # The actual value of the `bytes` field. + 10100101000000000000000000000000 # codificação little-endian de `number1` + 10110111000000000000000000000000 # codificação little-endian de `number2`. + 10010000000000000000000000000000 # O "deslocamento" que indica onde o valor de `vector` começa (little-endian 16). + 10010110000000000000000000000000 # codificação little-endian de `number3`. + 10000001100000101000001110000100 # O valor real do campo `bytes`. ] ``` Assim, os valores reais para tipos de comprimento variável são armazenados em uma pilha no final do objeto serializado com seus deslocamentos armazenados em suas posições corretas na lista ordenada de campos. -Existem também alguns casos especiais que requerem tratamento específico, como o tipo `BitList` que requer que seja adicionado um limite de comprimento durante a serialização e removido durante a desserialização. Os detalhes completos estão disponíveis na [especificação SSZ](https://github.com/ethereum/consensus-specs/blob/master/ssz/simple-serialize.md). +Há também alguns casos especiais que exigem tratamento específico, como o tipo `BitList`, que requer que um limite de comprimento seja adicionado durante a serialização e removido durante a desserialização. Detalhes completos estão disponíveis na [especificação SSZ](https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md). ### Desserialização {#deserialization} Para desserializar este objeto é necessário o esquema (diagrama, desenho). O esquema define o layout preciso dos dados serializados, para que cada elemento específico possa ser desserializado, de um blob de bytes em algum objeto significativo, com os elementos tendo o tipo, valor, tamanho e posição corretos. É o esquema que diz ao desserializador quais valores são valores reais e quais são deslocamentos. Todos os nomes de campo desaparecem quando um objeto é serializado, mas reinstanciados na desserialização de acordo com o esquema. -Veja [ssz.dev](https://www.ssz.dev/overview) para uma explicação interativa sobre isso. +Consulte [ssz.dev](https://www.ssz.dev/overview) para obter uma explicação interativa sobre isso. -## "Merkleização" {#merkleization} +## Merkleização {#merkleization} Esse objeto serializado SSZ pode então ser merkleizado, o seja, transformado em uma representação de árvore Merkle dos mesmos dados. Primeiro, o número de partes de 32 bytes no objeto serializado é determinado. Estas são as "folhas" da árvore. O número total de folhas deve ser uma potência de 2 para que a combinação das folhas eventualmente produza uma única raiz de árvore hash. Se este não for o caso natural, são adicionadas folhas extras que contêm 32 bytes de zeros. Diagramaticamente: ``` - hash tree root + raiz da árvore de hash / \ / \ / \ / \ - hash of leaves hash of leaves - 1 and 2 3 and 4 + hash das folhas hash das folhas + 1 e 2 3 e 4 / \ / \ / \ / \ / \ / \ - leaf1 leaf2 leaf3 leaf4 + folha1 folha2 folha3 folha4 ``` Há também casos em que as folhas da árvore não se distribuem naturalmente, de maneira uniforme, como o fazem no exemplo acima. Por exemplo, a folha 4 pode ser um contêiner com vários elementos que exige "profundidade" adicional para serem adicionados à árvore Merkle, criando uma árvore desnivelada. -Em vez de nos referirmos a esses elementos da árvore como folha X, nó X etc., podemos dar a eles índices generalizados, começando com raiz = 1 e contando da esquerda para a direita ao longo de cada nível. Este é o índice generalizado explicado acima. Cada elemento na lista serializada tem um índice genérico igual a `2**profundidade + idx`, onde o idx é a sua posição indexada por zero no objeto serializado e a profundidade é o número de níveis na árvore Merkle, que pode ser determinado como o logaritmo de base dois do número de elementos (folhas). +Em vez de nos referirmos a esses elementos da árvore como folha X, nó X etc., podemos dar a eles índices generalizados, começando com raiz = 1 e contando da esquerda para a direita ao longo de cada nível. Este é o índice generalizado explicado acima. Cada elemento na lista serializada tem um índice generalizado igual a `2**depth + idx`, onde `idx` é sua posição indexada a zero no objeto serializado e a profundidade (`depth`) é o número de níveis na árvore Merkle, que pode ser determinada como o logaritmo de base dois do número de elementos (folhas). ## Índices generalizados {#generalized-indices} -Um índice generalizado é um número inteiro que representa um nó em uma árvore Merkle binária em que cada nó tem um índice generalizado `2 ** profundidade + índice da linha`. +Um índice generalizado é um número inteiro que representa um nó em uma árvore Merkle binária, onde cada nó tem um índice generalizado de `2 ** depth + index in row`. ``` - 1 --depth = 0 2**0 + 0 = 1 - 2 3 --depth = 1 2**1 + 0 = 2, 2**1+1 = 3 - 4 5 6 7 --depth = 2 2**2 + 0 = 4, 2**2 + 1 = 5... + 1 --profundidade = 0 2**0 + 0 = 1 + 2 3 --profundidade = 1 2**1 + 0 = 2, 2**1+1 = 3 + 4 5 6 7 --profundidade = 2 2**2 + 0 = 4, 2**2 + 1 = 5... ``` @@ -126,12 +126,13 @@ Essa representação produz um índice de nó para cada parte dos dados na árvo ## Multiprovas {#multiproofs} -Fornecer a lista de índices generalizados, que representam um elemento específico, nos permite verificá-lo em relação à raiz da árvore hash. Esta raiz é nossa versão aceita da realidade. Qualquer dado que nos for fornecido pode ser verificado em relação a essa realidade, inserindo-o no lugar certo na árvore Merkle (determinado pelo seu índice generalizado) e observando que a raiz permanece constante. Há funções na especificação [aqui](https://github.com/ethereum/consensus-specs/blob/master/ssz/merkle-proofs.md#merkle-multiproofs) que mostram como calcular o conjunto mínimo de nós necessários, para verificar o conteúdo de um conjunto particular de índices generalizados. +Fornecer a lista de índices generalizados, que representam um elemento específico, nos permite verificá-lo em relação à raiz da árvore hash. Esta raiz é nossa versão aceita da realidade. Qualquer dado que nos for fornecido pode ser verificado em relação a essa realidade, inserindo-o no lugar certo na árvore Merkle (determinado pelo seu índice generalizado) e observando que a raiz permanece constante. Há funções na especificação [aqui](https://github.com/ethereum/consensus-specs/blob/dev/ssz/merkle-proofs.md#merkle-multiproofs) que mostram como calcular o conjunto mínimo de nós necessários para verificar o conteúdo de um determinado conjunto de índices generalizados. -Por exemplo, para verificar o dado no índice 9 na árvore abaixo, precisamos do hash dos dados nos índices 8, 9, 5, 3, 1. O hash de (8,9) deve ser igual ao hash (4), que faz hash com 5 para produzir 2, que faz hash com 3 para produzir a raiz da árvore 1. Se dados incorretos fossem fornecidos para 9, a raiz mudaria; detectaríamos isso e falharíamos ao verificar a branch. +Por exemplo, para verificar o dado no índice 9 na árvore abaixo, precisamos do hash dos dados nos índices 8, 9, 5, 3, 1. +O hash de (8,9) deve ser igual ao hash (4), que faz hash com 5 para produzir 2, que faz hash com 3 para produzir a raiz da árvore 1. Se dados incorretos fossem fornecidos para 9, a raiz mudaria; detectaríamos isso e falharíamos ao verificar a branch. ``` -* = data required to generate proof +* = dados necessários para gerar a prova 1* 2 3* @@ -140,10 +141,10 @@ Por exemplo, para verificar o dado no índice 9 na árvore abaixo, precisamos do ``` -## Leia mais {#further-reading} +## Leitura adicional {#further-reading} -- [Atualização do Ethereum: SSZ](https://eth2book.info/altair/part2/building_blocks/ssz) -- [Atualização do Ethereum: "Merkleização"](https://eth2book.info/altair/part2/building_blocks/merkleization) -- [Implementações SSZ](https://github.com/ethereum/consensus-specs/issues/2138) +- [Atualizando o Ethereum: SSZ](https://eth2book.info/altair/part2/building_blocks/ssz) +- [Atualizando o Ethereum: Merkleização](https://eth2book.info/altair/part2/building_blocks/merkleization) +- [Implementações do SSZ](https://github.com/ethereum/consensus-specs/issues/2138) - [Calculadora SSZ](https://simpleserialize.com/) - [SSZ.dev](https://www.ssz.dev/) diff --git a/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/web3-secret-storage-definition/index.md b/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/web3-secret-storage-definition/index.md index 70b036fdda7..b36611d4f51 100644 --- a/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/web3-secret-storage-definition/index.md +++ b/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/web3-secret-storage-definition/index.md @@ -1,6 +1,6 @@ --- -title: Definição de armazenamento secreto Web3 -description: Definição formal para armazenamento secreto web3 +title: "Definição de armazenamento secreto Web3" +description: "Definição formal para armazenamento secreto web3" lang: pt-br sidebarDepth: 2 --- diff --git a/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/web3-secret-storage/index.md b/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/web3-secret-storage/index.md new file mode 100644 index 00000000000..3e6b4607f34 --- /dev/null +++ b/public/content/translations/pt-br/developers/docs/data-structures-and-encoding/web3-secret-storage/index.md @@ -0,0 +1,195 @@ +--- +title: "Definição de armazenamento secreto Web3" +description: "Definição formal para armazenamento secreto web3" +lang: pt-br +sidebarDepth: 2 +--- + +Para fazer seu aplicativo funcionar no Ethereum, você pode usar o objeto web3 fornecido pela biblioteca web3.js. Internamente, ele se comunica com um nó local por meio de chamadas RPC. [web3](https://github.com/ethereum/web3.js/) funciona com qualquer nó Ethereum que expõe uma camada RPC. + +`web3` contém o objeto eth - web3.eth. + +```js +var fs = require("fs") +var recognizer = require("ethereum-keyfile-recognizer") + +fs.readFile("keyfile.json", (err, data) => { + var json = JSON.parse(data) + var result = recognizer(json) +}) + +/** resultado + * [ 'web3', 3 ] arquivo de chave web3 (v3) + * [ 'ethersale', undefined ] arquivo de chave Ethersale + * null arquivo de chave inválido + */ +``` + +Este documento descreve a **versão 3** da Definição de Armazenamento Secreto da Web3. + +## Definição {#definition} + +A codificação e decodificação atuais do arquivo permanece em grande medida inalteradas da versão 1, exceto que o algoritmo cripto já não é fixo no AES-128-CBC (AES-128-CTR agora é o requisito mínimo). A maioria dos significados/algoritmos são semelhantes à versão 1, exceto o `mac`, que é dado como o SHA3 (keccak-256) das concatenações dos segundos 16 bytes mais à esquerda da chave derivada, juntamente com o `ciphertext` completo. + +Arquivos de chave secreta são armazenados diretamente em `~/.web3/keystore` (para sistemas do tipo Unix) e `~/AppData/Web3/keystore` (para Windows). Eles podem receber qualquer nome, mas uma boa convenção é `.json`, onde `` é o UUID de 128 bits atribuído à chave secreta (um proxy de preservação de privacidade para o endereço da chave secreta). + +Todos esses arquivos possuem uma senha associada. Para derivar a chave secreta de um determinado arquivo `.json`, primeiro derive a chave de criptografia do arquivo; isso é feito pegando a senha do arquivo e passando-a por uma função de derivação de chave, conforme descrito pela chave `kdf`. Os parâmetros estáticos e dinâmicos dependentes do KDF para a função KDF são descritos na chave `kdfparams`. + +PBKDF2 deve ser apoiado por todas as implementações minimamente compatíveis, denotadas assim: + +- `kdf`: `pbkdf2` + +Para PBKDF2, os kdfparams incluem: + +- `prf`: Deve ser `hmac-sha256` (pode ser estendido no futuro); +- `c`: número de iterações; +- `salt`: salt (sequência de bits aleatórios) passado para o PBKDF; +- `dklen`: comprimento da chave derivada. Deve ser >= 32. + +Uma vez que a chave do arquivo tenha sido derivada, ela deveria ser verificada através da derivação do MAC. O MAC deve ser calculado como o hash SHA3 (keccak-256) do array de bytes formado pelas concatenações dos segundos 16 bytes mais à esquerda da chave derivada com o conteúdo da chave `ciphertext`, ou seja: + +```js +KECCAK(DK[16..31] ++ ) +``` + +(onde `++` é o operador de concatenação) + +Este valor deve ser comparado com o conteúdo da chave `mac`; se forem diferentes, uma senha alternativa deve ser solicitada (ou a operação cancelada). + +Após a verificação da chave do arquivo, o texto cifrado (a chave `ciphertext` no arquivo) pode ser descriptografado usando o algoritmo de criptografia simétrica, especificado pela chave `cipher` e parametrizado através da chave `cipherparams`. Se o tamanho da chave derivada e o tamanho da chave do algoritmo forem incompatíveis, os zeros à esquerda, os bytes à direita da chave derivada deverão ser usados como a chave para o algoritmo. + +Todas as implementações minimamente compatíveis devem suportar o algoritmo AES-128-CTR, indicado através de: + +- `cipher: aes-128-ctr` + +Esta cifra toma os seguintes parâmetros, dados como chaves para a chave dos parâmetros de decifração: + +- `iv`: vetor de inicialização de 128 bits para a cifra. + +A chave para a cifra são os 16 bytes mais à esquerda da chave derivada, ou seja, `DK[0..15]` + +A criação/criptografia de uma chave secreta deve ser essencialmente o inverso dessas instruções. Certifique-se de que o `uuid`, o `salt` e o `iv` sejam realmente aleatórios. + +Além do campo `version`, que deve atuar como um identificador "rígido" da versão, as implementações também podem usar o `minorversion` para rastrear alterações menores, que não quebram o formato. + +## Vetores de Teste {#test-vectors} + +Detalhes: + +- `Address`: `008aeeda4d805471df9b2a5b0f38a0c3bcba786b` +- `ICAP`: `XE542A5PZHH8PYIZUBEJEO0MFWRAPPIL67` +- `UUID`: `3198bc9c-6672-5ab3-d9954942343ae5b6` +- `Password`: `testpassword` +- `Secret`: `7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d` + +### PBKDF2-SHA-256 {#PBKDF2-SHA-256} + +Vetor de teste usando `AES-128-CTR` e `PBKDF2-SHA-256`: + +Conteúdo do arquivo `~/.web3/keystore/3198bc9c-6672-5ab3-d9954942343ae5b6.json`: + +```json +{ + "crypto": { + "cipher": "aes-128-ctr", + "cipherparams": { + "iv": "6087dab2f9fdbbfaddc31a909735c1e6" + }, + "ciphertext": "5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46", + "kdf": "pbkdf2", + "kdfparams": { + "c": 262144, + "dklen": 32, + "prf": "hmac-sha256", + "salt": "ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd" + }, + "mac": "517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2" + }, + "id": "3198bc9c-6672-5ab3-d995-4942343ae5b6", + "version": 3 +} +``` + +**Intermediários**: + +`Chave derivada`: `f06d69cdc7da0faffb1008270bca38f5e31891a3a773950e6d0fea48a7188551` +`Corpo do MAC`: `e31891a3a773950e6d0fea48a71885515318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46` +`MAC`: `517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2` +`Chave de cifra`: `f06d69cdc7da0faffb1008270bca38f5` + +### Scrypt {#scrypt} + +Vetor de teste usando AES-128-CTR e Scrypt: + +```json +{ + "crypto": { + "cipher": "aes-128-ctr", + "cipherparams": { + "iv": "740770fce12ce862af21264dab25f1da" + }, + "ciphertext": "dd8a1132cf57db67c038c6763afe2cbe6ea1949a86abc5843f8ca656ebbb1ea2", + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "n": 262144, + "p": 1, + "r": 8, + "salt": "25710c2ccd7c610b24d068af83b959b7a0e5f40641f0c82daeb1345766191034" + }, + "mac": "337aeb86505d2d0bb620effe57f18381377d67d76dac1090626aa5cd20886a7c" + }, + "id": "3198bc9c-6672-5ab3-d995-4942343ae5b6", + "version": 3 +} +``` + +**Intermediários**: + +`Chave derivada`: `7446f59ecc301d2d79bc3302650d8a5cedc185ccbb4bf3ca1ebd2c163eaa6c2d` +`Corpo do MAC`: `edc185ccbb4bf3ca1ebd2c163eaa6c2ddd8a1132cf57db67c038c6763afe2cbe6ea1949a86abc5843f8ca656ebbb1ea2` +`MAC`: `337aeb86505d2d0bb620effe57f18381377d67d76dac1090626aa5cd20886a7c` +`Chave de cifra`: `7446f59ecc301d2d79bc3302650d8a5c` + +## Alterações da Versão 1 {#alterations-from-v2} + +Esta versão corrige várias inconsistências com a versão 1 publicada [aqui](https://github.com/ethereum/homestead-guide/blob/master/old-docs-for-reference/go-ethereum-wiki.rst/Passphrase-protected-key-store-spec.rst). Em resumo, estas são: + +- A capitalização é injustificada e inconsistente (scrypt minúsculas, Kdf caso misto, MAC maiúsculas). +- Endereço desnecessário e compromete a privacidade. +- `Salt` é intrinsecamente um parâmetro da função de derivação de chave e merece ser associado a ela, não à criptografia em geral. +- _SaltLen_ desnecessário (basta derivá-lo do Salt). +- A função chave de derivação é dada, no entanto, o algoritmo de criptografia é difícil de especificar. +- `Version` é intrinsecamente numérico, mas é uma string (o versionamento estruturado seria possível com uma string, mas pode ser considerado fora do escopo para um formato de arquivo de configuração que muda raramente). +- `KDF` e `cipher` são conceitos conceitualmente semelhantes, mas organizados de forma diferente. +- `MAC` é calculado através de um trecho de dados agnóstico a espaços em branco(!) + +Foram feitas alterações no formato para dar o seguinte arquivo, funcionalmente equivalente ao exemplo dado na página anteriormente vinculada: + +```json +{ + "crypto": { + "cipher": "aes-128-cbc", + "ciphertext": "07533e172414bfa50e99dba4a0ce603f654ebfa1ff46277c3e0c577fdc87f6bb4e4fe16c5a94ce6ce14cfa069821ef9b", + "cipherparams": { + "iv": "16d67ba0ce5a339ff2f07951253e6ba8" + }, + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "n": 262144, + "p": 1, + "r": 8, + "salt": "06870e5e6a24e183a5c807bd1c43afd86d573f7db303ff4853d135cd0fd3fe91" + }, + "mac": "8ccded24da2e99a11d48cda146f9cc8213eb423e2ea0d8427f41c3be414424dd", + "version": 1 + }, + "id": "0498f19a-59db-4d54-ac95-33901b4f1870", + "version": 2 +} +``` + +## Alterações da Versão 2 {#alterations-from-v2} + +A versão 2 foi uma implementação inicial de C++ com um número de bugs. Todos os elementos essenciais permanecem inalterados. diff --git a/public/content/translations/pt-br/developers/docs/design-and-ux/dex-design-best-practice/index.md b/public/content/translations/pt-br/developers/docs/design-and-ux/dex-design-best-practice/index.md new file mode 100644 index 00000000000..65afa5021df --- /dev/null +++ b/public/content/translations/pt-br/developers/docs/design-and-ux/dex-design-best-practice/index.md @@ -0,0 +1,220 @@ +--- +title: "Melhores práticas de design para exchanges descentralizadas (DEX)" +description: "Um guia que explica decisões de UX/UI para troca de tokens." +lang: pt-br +--- + +Desde o lançamento do Uniswap em 2018, centenas de exchanges descentralizadas foram lançadas em dezenas de cadeias diferentes. +Muitos deles introduziram novos elementos ou adicionaram seu próprio toque, mas a interface permaneceu, em geral, a mesma. + +Um dos motivos para isso é a [Lei de Jakob](https://lawsofux.com/jakobs-law/): + +> Os usuários passam a maior parte do tempo em outros sites. Isso significa que os usuários preferem que o seu site funcione da mesma maneira que os outros sites com os quais já estão familiarizados. + +Graças a inovadores pioneiros como Uniswap, Pancakeswap e Sushiswap, os usuários de DeFi têm uma ideia coletiva de como uma DEX deve ser. +Por essa razão, está surgindo o conceito de "práticas recomendadas". Vemos cada vez mais decisões de design sendo padronizadas entre os sites. A evolução das exchanges descentralizadas pode ser vista como um grande exemplo de teste em tempo real. O que funcionou permaneceu, o que não funcionou foi descartado. Ainda há espaço para personalização, mas existem certos padrões que uma DEX deve seguir. + +Este artigo é um resumo de: + +- o que deve ser incluído +- como torná-lo o mais utilizável possível +- as principais formas de personalizar o design + +Todos os wireframes de exemplo foram desenvolvidos especialmente para este artigo, embora se baseiem em projetos reais. + +O kit do Figma também está incluído ao final. Sinta-se à vontade para usá-lo e acelerar a criação dos seus próprios wireframes! + +## Anatomia básica de um DEX {#basic-anatomy-of-a-dex} + +A interface do usuário geralmente contém três elementos: + +1. Formulário principal +2. Botão +3. Painel de detalhes + +![Interface de usuário genérica da DEX, mostrando os três elementos principais](./1.png) + +## Variações {#variations} + +Esse será um tema comum neste artigo, mas existem várias maneiras diferentes de organizar esses elementos. O “painel de detalhes” pode ser: + +- Acima do botão +- Abaixo do botão +- Escondido em um painel sanfonado +- E/ou em um modal de “pré-visualização” + +Nota: Um modal de “pré-visualização” é opcional, mas se você está mostrando poucos detalhes na interface de usuário principal, ele se torna essencial. + +## Estrutura do formulário principal {#structure-of-the-main-form} + +É nesta caixa em que você escolhe o token que deseja trocar. O componente é composto de um campo de entrada e um botão pequeno dispostos em linha. + +Normalmente, as exchanges descentralizadas exibem detalhes adicionais em uma linha acima e outra abaixo, embora isso possa ser configurado de forma diferente. + +![Linha de entrada, com uma linha de detalhes acima e abaixo](./2.png) + +## Variações {#variations2} + +Duas variações de interface do usuário são mostradas aqui: uma sem bordas, criando um design muito aberto, e outra em que a linha de entrada tem uma borda, criando um foco nesse elemento. + +![Duas variações de UI do formulário principal](./3.png) + +Essa estrutura básica permite que **quatro informações importantes** sejam exibidas no design: uma em cada canto. Se houver apenas uma linha superior/inferior, haverá apenas dois pontos. + +Durante a evolução do DeFi, muitas coisas diferentes foram incluídas aqui. + +## Informações importantes a serem incluídas {#key-info-to-include} + +- Saldo na carteira +- Botão máximo +- Equivalente em moeda fiduciária +- Impacto do preço no valor “recebido” + +No início do DeFi, o equivalente em moeda fiduciária muitas vezes não era exibido. Se você está desenvolvendo qualquer tipo de projeto Web3, é essencial que o equivalente em moeda fiduciária seja exibido. Os usuários ainda pensam em termos de moedas locais, então, para alinhar com os modelos mentais do mundo real, isso deve ser incluído. + +No segundo campo (aquele onde você escolhe o token para o qual está trocando), você também pode incluir o impacto no preço ao lado do valor em moeda fiduciária, calculando a diferença entre o valor de entrada e os valores estimados de saída. Esse é um detalhe bastante útil a ser incluído. + +Botões de porcentagem (p. ex., 25%, 50%, 75%) podem ser um recurso útil, mas ocupam mais espaço, adicionam mais chamadas para ação e adicionam mais carga mental. O mesmo se aplica aos controles deslizantes de porcentagem. Algumas dessas decisões de interface dependerão da sua marca e do tipo de usuário. + +Detalhes adicionais podem ser exibidos abaixo do formulário principal. Como esse tipo de informação é voltado principalmente para usuários profissionais, faz sentido optar por: + +- mantê-la o mínimo possível, ou; +- escondê-la em um painel sanfonado + +![Detalhes mostrados nos cantos do formulário principal](./4.png) + +## Informações extras a serem incluídas {#extra-info-to-include} + +- Preço do token +- Derrapagem +- Mínimo recebido +- Resultado esperado +- Impacto no preço +- Estimativa de custo de transação +- Outras taxas +- Roteamento de pedidos + +Certamente, alguns desses detalhes poderiam ser opcionais. + +O roteamento de pedidos é interessante, mas não faz muita diferença para a maioria dos usuários. + +Alguns outros detalhes estão simplesmente reafirmando a mesma coisa de maneiras diferentes. Por exemplo, "mínimo recebido" e "derrapagem" são dois lados da mesma moeda. Se você tiver uma derrapagem definida em 1%, então o mínimo que você pode esperar receber = resultado esperado-1%. Algumas interfaces de usuário mostrarão o valor esperado, o valor mínimo e a derrapagem. O que é útil, mas possivelmente excessivo. + +A maioria dos usuários deixará a derrapagem predefinida de qualquer maneira. + +O “impacto no preço” é geralmente mostrado entre parênteses ao lado do equivalente em moeda fiduciária no campo “para”. Este é um ótimo detalhe de experiência do usuário para adicionar, mas se ele é mostrado aqui, realmente precisa ser mostrado novamente abaixo? E depois novamente em uma tela de pré-visualização? + +Muitos usuários (especialmente os que trocam pequenos valores) não se preocuparão com esses detalhes; eles vão apenas inserir um valor e trocar. + +![Alguns detalhes mostram a mesma coisa](./5.png) + +Quais detalhes serão exibidos exatamente dependerá do seu público e da sensação que você deseja que o aplicativo transmita. + +Se você incluir a tolerância de derrapagem no painel de detalhes, também deverá torná-la editável diretamente daqui. Este é um bom exemplo de um “acelerador”; um truque inteligente de experiência do usuário que pode agilizar o fluxo de usuários experientes, sem comprometer a usabilidade geral do aplicativo. + +![A derrapagem pode ser controlada no painel de detalhes](./6.png) + +É uma boa ideia pensar cuidadosamente não apenas em uma informação específica em uma tela, mas em todo o fluxo, considerando: +Introduzir os números no formulário principal → Verificar os detalhes → Clicar na tela de pré-visualização (se houver uma tela de pré-visualização). +O painel de detalhes deve estar visível o tempo todo ou o usuário precisa clicar para expandi-lo? +Você deve criar atrito ao adicionar uma tela de pré-visualização? Isso força o usuário a desacelerar e considerar sua troca, o que pode ser útil. Mas eles querem ver todas as mesmas informações novamente? O que é mais útil para eles neste momento? + +## Opções de design {#design-options} + +Como mencionado, muito disso depende do seu estilo pessoal +Quem é o seu usuário? +Qual é a sua marca? +Você quer uma interface “profissional” mostrando todos os detalhes ou quer ser minimalista? +Mesmo que você esteja considerando os usuários profissionais que querem todas as informações possíveis, você ainda deve se lembrar das sábias palavras de Alan Cooper: + +> Não importa quão bonita ou legal seja sua interface, seria melhor que ela fosse mais simples. + +### Estrutura {#structure} + +- tokens à esquerda ou tokens à direita +- 2 linhas ou 3 +- detalhes acima ou abaixo do botão +- detalhes expandidos, minimizados ou não mostrados + +### Estilo do componente {#component-style} + +- vazio +- delineado +- preenchido + +De um ponto de vista puramente UX, o estilo da interface do usuário é menos importante do que você pensa. As tendências visuais vêm e vão em ciclos e muitas preferências são subjetivas. + +A maneira mais fácil de ter uma ideia disso – e pensar nas várias configurações diferentes – é dar uma olhada em alguns exemplos e depois fazer alguns experimentos você mesmo. + +O kit Figma incluído contém componentes vazios, contornados e preenchidos. + +Dê uma olhada nos exemplos abaixo para ver diferentes maneiras de juntar tudo: + +![3 linhas em estilo preenchido](./7.png) + +![3 linhas em estilo contornado](./8.png) + +![2 linhas em estilo vazio](./9.png) + +![3 filas em estilo contornado, com um painel de detalhes](./10.png) + +![3 linhas com uma linha de entrada em stilo contornado](./11.png) + +![2 linhas em estilo preenchido](./12.png) + +## Mas de que lado o token deve ficar? {#but-which-side-should-the-token-go-on} + +O ponto principal é que isso provavelmente não faz uma grande diferença na usabilidade. No entanto, há alguns aspectos que você deve ter em mente que podem fazer você decidir de uma forma ou de outra. + +Tem sido um pouco interessante ver a mudança de comportamento com o tempo. Inicialmente, o Uniswap tinha o token à esquerda, mas desde então o moveu para a direita. O Sushiswap também fez essa alteração durante uma atualização de design. A maioria dos protocolos, mas não todos, seguiu o exemplo. + +A convenção financeira tradicionalmente coloca o símbolo da moeda antes do número, p. ex., $50, €50, £50, mas nós _dizemos_ 50 dólares, 50 euros, 50 libras. + +Para o usuário em geral, especialmente alguém que lê da esquerda para a direita, de cima para baixo, o token à direita provavelmente parece mais natural. + +![A IU com tokens à esquerda](./13.png) + +Colocar o token à esquerda e todos os números à direita parece agradavelmente simétrico, o que é uma vantagem, mas há uma desvantagem neste layout. + +A lei da proximidade afirma que os itens que estão próximos são percebidos como relacionados. Dessa forma, nós queremos colocar os itens relacionados próximos uns dos outros. O saldo do token está diretamente relacionado ao próprio token e será alterado sempre que um novo token for selecionado. Portanto, faz um pouco mais de sentido que o saldo do token esteja próximo ao botão de seleção do token. Ele poderia ser movido para debaixo do token, mas isso quebraria a simetria do layout. + +Em última análise, há vantagens e desvantagens em ambas as opções, mas é interessante como a tendência parece estar se voltando para o token à direita. + +## Comportamento do botão {#button-behavior} + +Não tenha um botão separado para Aprovar. Também não tenha um clique separado para Aprovar. O usuário deseja trocar, então basta dizer “trocar” no botão e iniciar a aprovação como primeiro passo. Um modal pode mostrar o progresso com um passo a passo ou uma simples notificação “tx 1 de 2 - aprovando”. + +![IU com botões separados para Aprovar e Trocar](./14.png) + +![IU com um botão que diz "Aprovar"](./15.png) + +### Botão como ajuda contextual {#button-as-contextual-help} + +O botão também pode servir de alerta! + +Esse é, na verdade, um padrão de design bastante incomum fora da Web3, mas que se tornou padrão dentro dela. Essa é uma boa inovação, pois economiza espaço e mantém a atenção focalizada. + +Se a ação principal – SWAP – não está disponível devido a um erro, o motivo pode ser explicado com o botão, por exemplo.: + +- trocar de rede +- conectar carteira +- vários erros + +O botão também pode ser **correlacionado à ação** que precisa ser executada. Por exemplo, se o usuário não puder trocar porque está na rede errada, o botão deverá dizer “mudar para Ethereum” e, quando o usuário clicar no botão, ele deverá mudar a rede para Ethereum. Isso acelera significativamente o fluxo do usuário. + +![Ações fundamentais sendo iniciadas na chamada para ação principal](./16.png) + +![Mensagem de erro mostrada na chamada para ação principal](./17.png) + +## Construa o seu próprio com este arquivo figma {#build-your-own-with-this-figma-file} + +Graças ao trabalho intenso de vários protocolos, o design do DEX melhorou muito. Sabemos quais informações o usuário precisa, como devemos mostrá-las e como tornar o fluxo o mais fluido possível. +Esperamos que este artigo forneça uma visão geral sólida dos princípios de UX. + +Se você quiser experimentar, sinta-se à vontade para usar o kit de wireframe (diagramas) do Figma. Ele é mantido o mais simples possível, mas tem flexibilidade suficiente para construir a estrutura básica de várias maneiras. + +[Kit de wireframe Figma](https://www.figma.com/community/file/1393606680816807382/dex-wireframes-kit) + +O DeFi continuará a evoluir e sempre há espaço para melhorias. + +Boa sorte! diff --git a/public/content/translations/pt-br/developers/docs/design-and-ux/heuristics-for-web3/index.md b/public/content/translations/pt-br/developers/docs/design-and-ux/heuristics-for-web3/index.md new file mode 100644 index 00000000000..28efb3ac3e5 --- /dev/null +++ b/public/content/translations/pt-br/developers/docs/design-and-ux/heuristics-for-web3/index.md @@ -0,0 +1,138 @@ +--- +title: "Sete heurísticas para o design da interface Web3" +description: "Princípios para melhorar a usabilidade do Web3" +lang: pt-br +--- + +As heurísticas de usabilidade são “regras gerais” que você pode usar para medir a usabilidade do seu site. +As 7 heurísticas apresentadas aqui são especificamente adaptadas para Web3 e devem ser usadas em conjunto com os [10 princípios gerais de design de interação](https://www.nngroup.com/articles/ten-usability-heuristics/) de Jakob Nielsen. + +## Sete heurísticas de usabilidade para web3 {#seven-usability-heuristics-for-web3} + +1. O feedback vem depois da ação +2. Segurança e confiança +3. A informação mais importante é evidente +4. Terminologia clara +5. As ações são tão curtas quanto possível +6. As conexões de rede são visíveis e flexíveis +7. Controle pelo aplicativo, não pela carteira + +## Definições e exemplos {#definitions-and-examples} + +### 1. O feedback vem depois da ação {#feedback-follows-action} + +**Deve ser óbvio quando algo aconteceu ou está acontecendo.** + +Os usuários decidem as próximas etapas com base no resultado das etapas anteriores. Portanto, é essencial que eles permaneçam informados sobre o status do sistema. Isso é especialmente importante na Web3, pois às vezes as transações podem levar um curto período de tempo para serem confirmadas na blockchain. Se não houver nenhum feedback informando para esperar, os usuários não terão certeza se algo aconteceu. + +**Dicas:** + +- Informe o usuário por meio de mensagens, notificações e outros alertas. +- Comunique claramente os tempos de espera. +- Se uma ação demorar mais do que alguns segundos, tranquilize o usuário com um cronômetro ou uma animação para fazê-lo sentir que algo está acontecendo. +- Se houver várias etapas em um processo, mostre cada etapa. + +**Exemplo:** +Mostrar cada etapa envolvida em uma transação ajuda os usuários a saber onde estão no processo. Ícones apropriados permitem que o usuário saiba o status de suas ações. + +![Informando o usuário sobre cada etapa da troca de tokens](./Image1.png) + +### 2. A segurança e a confiança são incorporadas {#security-and-trust-are-backed-in} + +A segurança deve ser priorizada, e isso deve ser enfatizado para o usuário. +As pessoas se importam profundamente com seus dados. A segurança é frequentemente uma preocupação principal para os usuários, por isso deve ser considerada em todos os níveis do design. Você deve sempre tentar ganhar a confiança dos seus usuários, mas a maneira como você faz isso pode significar coisas diferentes em aplicativos diferentes. Isso não deve ser uma reflexão tardia, mas sim algo planejado conscientemente ao longo de todo o processo de design. Crie confiança em toda a experiência do usuário, inclusive nos canais sociais e na documentação, bem como na interface do usuário final. Aspectos como o nível de descentralização, o status de multi-sig da tesouraria e se os membros da equipe são conhecidos publicamente afetam a confiança dos usuários. + +**Dicas:** + +- Liste suas auditorias com orgulho +- Obtenha várias auditorias +- Anuncie quaisquer recursos de segurança que você projetou +- Destaque os possíveis riscos, incluindo integrações subjacentes +- Comunique a complexidade das estratégias +- Considere questões além da interface que possam influenciar a percepção de segurança dos seus usuários + +**Exemplo:** +Inclua suas auditorias no rodapé, em um tamanho destacado. + +![Auditorias referenciadas no rodapé do site](./Image2.png) + +### 3. A informação mais importante é evidente {#the-most-important-info-is-obvious} + +Para sistemas complexos, mostre apenas os dados mais relevantes. Determine o que é mais importante e priorize sua exibição. +O excesso de informações é esmagador e os usuários geralmente se concentram em uma única informação ao tomar decisões. No DeFi, isso provavelmente será APR em aplicativos de rendimento e LTV em aplicativos de empréstimo. + +**Dicas:** + +- A pesquisa com usuários revelará a métrica mais importante +- Faça com que as informações principais sejam grandes e os outros detalhes sejam pequenos e discretos +- As pessoas não leem, elas escaneiam; garanta que seu design seja escaneável + +**Exemplo:** Tokens grandes e coloridos são fáceis de encontrar ao escanear. O APR é grande e destacado em uma cor de destaque. + +![O token e a APR são fáceis de encontrar](./Image3.png) + +### 4. Terminologia clara {#clear-terminology} + +A terminologia deve ser compreensível e apropriada. +O jargão técnico pode ser um grande obstáculo, porque exige a construção de um modelo mental completamente novo. Os usuários não conseguem relacionar o design a palavras, frases e conceitos que já conhecem. Tudo parece confuso e desconhecido, e há uma curva de aprendizado íngreme antes mesmo que eles tentem usá-lo. Um usuário pode abordar o DeFi querendo economizar algum dinheiro, e o que ele encontra é: Mineração, farming, staking, emissões, subornos, cofres, armários, veTokens, vesting, épocas, algoritmos descentralizados, liquidez de propriedade do protocolo. +Tente usar termos simples que sejam compreendidos pelo maior número possível de pessoas. Não invente termos novos apenas para o seu projeto. + +**Dicas:** + +- Use terminologia simples e consistente +- Use a linguagem existente o máximo possível +- Não invente seus próprios termos +- Siga as convenções conforme elas aparecem +- Eduque os usuários o máximo possível + +**Exemplo:** +“Suas recompensas” é um termo amplamente compreendido e neutro; não é uma palavra nova inventada para este projeto. As recompensas são denominadas em dólares americanos para corresponder aos modelos mentais do mundo real, mesmo que as recompensas em si estejam em outro token. + +![Recompensas de token, exibidas em dólares americanos](./Image4.png) + +### 5. As ações são tão curtas quanto possível {#actions-are-as-short-as-possible} + +Acelere as interações do usuário agrupando subações. +Isso pode ser feito no nível do contrato inteligente, bem como na interface do usuário. O usuário não deve ter que se mover de uma parte do sistema para outra – ou sair do sistema completamente – para concluir uma ação comum. + +**Dicas:** + +- Combine “Aprovar” com outras ações sempre que possível +- Agrupe as etapas de assinatura o mais próximo possível umas das outras + +**Exemplo:** Combinar “adicionar liquidez” e “stake” é um exemplo simples de um acelerador que economiza tempo e combustível para o usuário. + +![Modal mostrando um interruptor para combinar as ações de depósito e stake](./Image5.png) + +### 6. As conexões de rede são visíveis e flexíveis {#network-connections-are-visible-and-flexible} + +Informe ao usuário a qual rede ele está conectado e forneça atalhos claros para alterar a rede. +Isto é especialmente importante em aplicativos multichain. As principais funções do aplicativo ainda devem estar visíveis quando desconectado ou conectado a uma rede não suportada. + +**Dicas:** + +- Mostre o máximo possível do aplicativo enquanto estiver desconectado +- Mostre a qual rede o usuário está conectado no momento +- Não faça o usuário ir até a carteira para trocar de rede +- Se o aplicativo exigir que o usuário troque de rede, que essa ação possa ser feita na chamada para ação principal +- Se o aplicativo contiver mercados ou cofres para várias redes, indique claramente qual conjunto o usuário está visualizando no momento + +**Exemplo:** Mostre ao usuário a qual rede ele está conectado e permita que ele a altere na barra de aplicativos. + +![Botão suspenso mostrando a rede conectada](./Image6.png) + +### 7. Controle pelo aplicativo, não pela carteira {#control-from-the-app-not-the-wallet} + +A interface do usuário deve informar ao usuário tudo o que ele precisa saber e dar a ele controle sobre tudo o que ele precisa fazer. +No Web3, há ações que você realiza na interface do usuário e ações que você realiza na carteira. Geralmente, você inicia uma ação na interface do usuário e depois a confirma na carteira. Os usuários podem se sentir desconfortáveis ​​se essas duas janelas não forem integradas cuidadosamente. + +**Dicas:** + +- Comunique o status do sistema por meio de feedback na IU +- Mantenha um histórico das ações do usuário +- Forneça links para exploradores de blocos de transações antigas +- Forneça atalhos para alterar redes + +**Exemplo:** Um contêiner sutil mostra ao usuário quais tokens relevantes ele tem em sua carteira, e a CTA principal fornece um atalho para alterar a rede. + +![A CTA principal está solicitando que o usuário troque de rede](./Image7.png) diff --git a/public/content/translations/pt-br/developers/docs/design-and-ux/index.md b/public/content/translations/pt-br/developers/docs/design-and-ux/index.md new file mode 100644 index 00000000000..68989ae4dc7 --- /dev/null +++ b/public/content/translations/pt-br/developers/docs/design-and-ux/index.md @@ -0,0 +1,86 @@ +--- +title: Design e UX em web3 +description: "Introdução ao design UX e pesquisa no espaço web3 e Ethereum" +lang: pt-br +--- + +Você é novo em design com Ethereum? Este é o lugar certo para você. A comunidade Ethereum tem escrito recursos para apresentá-lo aos conceitos básicos de design web3 e pesquisa. Você irá aprender sobre os principais conceitos que podem diferir de outros designs de aplicativos com os quais você está familiarizado. + +Precisa de uma compreensão mais básica da web3 primeiro? Confira o [**Hub de Aprendizagem**](/learn/). + +## Comece com a pesquisa de usuário {#start-with-user-research} + +O design eficaz vai além de criar interfaces de usuário visualmente atraentes. Ele envolve adquirir uma compreensão profunda das necessidades, objetivos e fatores determinantes do usuário. Portanto, recomendamos fortemente que todos os designers adotem um processo de design, como o [**processo do diamante duplo**](https://en.wikipedia.org/wiki/Double_Diamond_\(design_process_model\)), para garantir que seu trabalho seja deliberado e intencional. + +- [A Web3 precisa de mais pesquisadores e designers de UX](https://blog.akasha.org/akasha-conversations-9-web3-needs-more-ux-researchers-and-designers) - Uma visão geral da maturidade atual do design +- [Um guia simples para pesquisa de UX na web3](https://uxplanet.org/a-complete-guide-to-ux-research-for-web-3-0-products-d6bead20ebb1) - Guia simples de como fazer pesquisa +- [Como abordar as decisões de UX na Web3](https://archive.devcon.org/archive/watch/6/data-empathy-how-to-approach-ux-decisions-in-web3/) - Uma breve visão geral da pesquisa quantitativa e qualitativa e as diferenças entre as duas (vídeo, 6 min) +- [Ser um pesquisador de UX na web3](https://medium.com/@georgia.rakusen/what-its-like-being-a-user-researcher-in-web3-6a4bcc096849) - Uma visão pessoal sobre como é ser um pesquisador de UX na web3 + +## Estudos de pesquisa na web3 {#research-in-web3} + +Esta é uma lista selecionada de pesquisa de usuários feita na web3, que podem ajudar nas decisões de design e produto ou servir de inspiração para realizar um estudo próprio. + +| Área de foco | Nome | +| :--------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Integração em cripto | [The Reown Pulse 2024: sentimento e uso do consumidor de cripto](https://reown.com/blog/unveiling-walletconnects-consumer-crypto-report) | +| Integração em cripto | [CRADL: UX em Criptomoedas](https://docs.google.com/presentation/d/1s2OPSH5sMJzxRYaJSSRTe8W2iIoZx0PseIV-WeZWD1s/edit?usp=sharing) | +| Integração em cripto | [CRADL: Integração em Criptomoedas](https://docs.google.com/presentation/d/1R9nFuzA-R6SxaGCKhoMbE4Vxe0JxQSTiHXind3LVq_w/edit?usp=sharing) | +| Integração em cripto | [Relatório de UX do Bitcoin](https://github.com/patestevao/BitcoinUX-report/blob/master/report.md) | +| Integração em cripto | [ConSensys: O estado da percepção da Web3 ao redor do mundo 2023](https://consensys.io/insight-report/web3-and-crypto-global-survey-2023) | +| Integração em cripto | [NEAR: acelerando a jornada rumo à adoção](https://drive.google.com/file/d/1VuaQP4QSaQxR5ddQKTMGI0b0rWdP7uGn/view) | +| Staking | [OpenUX: UX do Operador de Nó da Rocket Pool](https://storage.googleapis.com/rocketpool/RocketPool-NodeOperator-UX-Report-Jan-2024.pdf) | +| Staking | [Staking: principais tendências, conclusões e previsões - Eth Staker](https://lookerstudio.google.com/u/0/reporting/cafcee00-e1af-4148-bae8-442a88ac75fa/page/p_ja2srdhh2c?s=hmbTWDh9hJo) | +| Staking | [Staking em múltiplos aplicativos](https://github.com/threshold-network/UX-User-Research/blob/main/Multi-App%20Staking%20\(MAS\)/iterative-user-study/MAS%20Iterative%20User%20Study.pdf) | +| DAO | [Atualização da pesquisa DAO de 2022: Do que os construtores de DAO precisam?](https://blog.aragon.org/2022-dao-research-update/) | +| DeFi | [Pools de cobertura](https://github.com/threshold-network/UX-User-Research/tree/main/Keep%20Coverage%20Pool) | +| DeFi | [ConSensys: Relatório de pesquisa de usuário DeFi 2022](https://cdn2.hubspot.net/hubfs/4795067/ConsenSys%20Codefi-Defi%20User%20ResearchReport.pdf) | +| Metaverso | [Metaverso: relatório de pesquisa do usuário](https://www.politico.com/f/?id=00000187-7685-d820-a7e7-7e85d1420000) | +| Metaverso | [Fazendo um safári: pesquisando usuários no Metaverso](https://archive.devcon.org/archive/watch/6/going-on-safari-researching-users-in-the-metaverse/?tab=YouTube) (vídeo, 27 min) | + +## Design para a web3 {#design-for-web3} + +- [Manual de design de UX da Web3](https://web3ux.design/) - Guia prático para projetar aplicativos da Web3 +- [Princípios de design da Web3](https://medium.com/@lyricalpolymath/web3-design-principles-f21db2f240c1) - Uma estrutura de regras de UX para dapps baseados em cadeia de blocos +- [Princípios de design da cadeia de blocos](https://medium.com/design-ibm/blockchain-design-principles-599c5c067b6e) - Lições aprendidas pela equipe de design da cadeia de blocos da IBM +- [Neueux.com](https://neueux.com/apps) - Biblioteca de UI de fluxos de usuário com diversas opções de filtragem +- [Crise de usabilidade da Web3: o que você PRECISA saber!](https://www.youtube.com/watch?v=oBSXT_6YDzg) - Um painel de discussão sobre as armadilhas da criação de projetos com foco no desenvolvedor (vídeo, 34 min) + +## Primeiros passos {#getting-started} + +- [Heurísticas para a Web3](/developers/docs/design-and-ux/heuristics-for-web3/) - 7 heurísticas para o design de interface da Web3 +- [Melhores práticas de design para DEX](/developers/docs/design-and-ux/dex-design-best-practice/) - Um guia para projetar Corretoras Descentralizadas + +## Estudos de caso de design da Web3 {#design-case-studies} + +- [Deep Work Studio](https://www.deepwork.studio/case-studies) +- [Vendendo um NFT na OpenSea](https://builtformars.com/case-studies/opensea) +- [Análise detalhada de UX da carteira: como as carteiras precisam mudar](https://www.youtube.com/watch?v=oTpuxYj8JWI&ab_channel=ETHDenver) (vídeo, 20 min) + +## Recompensas de design {#bounties} + +- [Dework](https://app.dework.xyz/bounties) +- [Buildbox hackathons](https://app.buidlbox.io/) +- [ETHGlobal hackathons](https://ethglobal.com/) + +## DAOs e comunidades de design {#design-daos-and-communities} + +Se envolva em organizações profissionais dirigidas à comunidade ou junte-se a grupos de desenho para discutir com outros membros tópicos relacionados a desenho e pesquisa, e tendências. + +- [Vectordao.com](https://vectordao.com/) +- [Deepwork.studio](https://www.deepwork.studio/) +- [We3.co](https://we3.co/) +- [Openux.xyz](https://openux.xyz/) + +## Sistemas de design e outros recursos de design {#design-systems-and-resources} + +- [Optimism Design](https://www.figma.com/@optimism) (Figma) +- [Sistema de design do Ethereum.org](https://www.figma.com/@ethdotorg) (Figma) +- [Finity, um sistema de design da Polygon](https://www.figma.com/community/file/1073921725197233598/finity-design-system) (Figma) +- [Sistema de design da Kleros](https://www.figma.com/community/file/999852250110186964/kleros-design-system) (Figma) +- [Sistema de design da Safe](https://www.figma.com/community/file/1337417127407098506/safe-design-system) (Figma) +- [Sistema de design do ENS](https://thorin.ens.domains/) +- [Sistema de design do Mirror](https://degen-xyz.vercel.app/) + +**Os artigos e projetos listados nesta página não são endossos oficiais e são fornecidos apenas para fins informativos.** +Adicionamos links a esta página com base nos critérios de nossa [política de listagem](/contributing/design/adding-design-resources). Se você quiser que adicionemos um projeto/artigo, edite esta página no [GitHub](https://github.com/ethereum/ethereum-org-website/blob/dev/public/content/developers/docs/design-and-ux/index.md). diff --git a/public/content/translations/pt-br/developers/docs/development-networks/index.md b/public/content/translations/pt-br/developers/docs/development-networks/index.md index cf9d77c18f8..00d8d4b49c5 100644 --- a/public/content/translations/pt-br/developers/docs/development-networks/index.md +++ b/public/content/translations/pt-br/developers/docs/development-networks/index.md @@ -1,6 +1,6 @@ --- title: Redes de desenvolvimento -description: Uma visão geral das redes de desenvolvimento e ferramentas disponíveis para ajudar a construir aplicativos Ethereum. +description: "Uma visão geral das redes de desenvolvimento e ferramentas disponíveis para ajudar a construir aplicativos Ethereum." lang: pt-br --- @@ -10,7 +10,7 @@ Assim como é possível executar um servidor local do seu computador para desenv ## Pré-requisitos {#prerequisites} -Você precisa entender conceitos [básicos da pilha de Ethereum](/developers/docs/ethereum-stack/) e [das redes de Ethereum](/developers/docs/networks/) antes de mergulhar nas redes de desenvolvimento. +Você deve entender os [conceitos básicos da pilha de Ethereum](/developers/docs/ethereum-stack/) e das [redes Ethereum](/developers/docs/networks/) antes de mergulhar nas redes de desenvolvimento. ## O que é uma rede de desenvolvimento? {#what-is-a-development-network} @@ -18,15 +18,15 @@ Redes de desenvolvimento são essencialmente clientes Ethereum (implementações **Por quê não executar somente um nó Ethereum localmente?** -Você _poderia_ [executar um nó](/developers/docs/nodes-and-clients/#running-your-own-node), mas como as redes de desenvolvimento são criadas especificamente para o desenvolvimento, elas geralmente vêm com recursos convenientes, como: +Você _poderia_ [executar um nó](/developers/docs/nodes-and-clients/#running-your-own-node), mas como as redes de desenvolvimento são criadas especificamente para o desenvolvimento, elas geralmente vêm repletas de recursos convenientes, como: -- Semeando deterministicamente sua blockchain local com dados (por exemplo, contas com saldo ETH) +- Semeando deterministicamente sua cadeia de blocos local com dados (por exemplo, contas com saldos de ETH) - Produzir instantaneamente blocos com cada transação que receber, em ordem e sem atraso - Funcionalidade de depuração e registro aprimorado ## Ferramentas disponíveis {#available-projects} -**Nota**: [A maioria dos frameworks desenvolvidos](/developers/docs/frameworks/) incluem uma rede de desenvolvimento integrada. Recomendamos começar com um framework para [configurar seu ambiente de desenvolvimento local](/developers/local-environment/). +**Observação**: a maioria dos [frameworks de desenvolvimento](/developers/docs/frameworks/) inclui uma rede de desenvolvimento integrada. Recomendamos começar com um framework para [configurar seu ambiente de desenvolvimento local](/developers/local-environment/). ### Rede Hardhat {#hardhat-network} @@ -34,23 +34,21 @@ Uma rede local Ethereum concebida para desenvolvedores. Isso permite que você i A rede Hardhat vem integrada com Hardhat, um ambiente de desenvolvimento para profissionais. -- [Website](https://hardhat.org/) -- [GitHub](https://github.com/nomiclabs/hardhat) +- [Site](https://hardhat.org/) +- [GitHub](https://github.com/NomicFoundation/hardhat) -### Beacon Chains Locais {#local-beacon-chains} +### Beacon Chains locais {#local-beacon-chains} Alguns clientes de consenso têm ferramentas integradas para ativar as cadeias Beacon locais para fins de teste. Instruções para Lighthouse, Nimbus e Lodestar estão disponíveis: -- [Testnet local usando Lodestar](https://chainsafe.github.io/lodestar/contribution/advanced-topics/setting-up-a-testnet#post-merge-local-testnet/) -- [Testnet local usando Lighthouse](https://lighthouse-book.sigmaprime.io/setup.html#local-testnets) +- [Rede de teste local usando Lodestar](https://chainsafe.github.io/lodestar/contribution/advanced-topics/setting-up-a-testnet#post-merge-local-testnet/) +- [Rede de teste local usando Lighthouse](https://lighthouse-book.sigmaprime.io/setup.html#local-testnets) -### Cadeias de teste públicas do Ethereum {#public-beacon-testchains} +### Redes de teste públicas da Ethereum {#public-beacon-testchains} -Existem também duas implementações públicas de testes da Ethereum: Sepolia e Hoodi. Sepolia é a rede de testes padrão recomendada para o desenvolvimento de aplicativos, com um conjunto fechado de validadores para sincronização rápida. Hoodi é uma rede de testes para validação e staking, que usa um conjunto aberto de validadores e permite potencialmente que qualquer pessoa valide. +Há também duas implementações de testes públicos mantidas do Ethereum: Sepolia e Hoodi. A rede de testes recomendada com suporte de longo prazo é a Hoodi, que qualquer pessoa pode validar livremente. Sepolia usa um conjunto de validadores com permissão, o que significa que não há acesso geral a novos validadores nesta rede de teste. -- [Plataforma de lançamento de staking Hoodi](https://hoodi.launchpad.ethereum.org/en/) -- [Website Sepolia](https://sepolia.dev/) -- [Website Hoodi](https://hoodi.ethpandaops.io/) +- [Plataforma de lançamento de participação da Hoodi](https://hoodi.launchpad.ethereum.org/) ### Pacote Kurtosis do Ethereum {#kurtosis} @@ -59,15 +57,15 @@ Kurtosis é um sistema de construção para ambientes de teste em vários contê O pacote Ethereum Kurtosis pode ser usado para instanciar rapidamente uma rede de teste Ethereum parametrizável, altamente dimensionável e privada no Docker ou no Kubernetes. O pacote é compatível com todos os principais clientes da camada de execução (EL) e da camada de consenso (CL). A Kurtosis lida com todos os mapeamentos de portas locais e conexões de serviço para uma rede representativa a ser usada em fluxos de trabalho de validação e teste relacionados à infraestrutura principal do Ethereum. - [Pacote de rede Ethereum](https://github.com/kurtosis-tech/ethereum-package) -- [Website](https://www.kurtosis.com/) +- [Site](https://www.kurtosis.com/) - [GitHub](https://github.com/kurtosis-tech/kurtosis) - [Documentação](https://docs.kurtosis.com/) ## Leitura adicional {#further-reading} -_Conhece um recurso da comunidade que te ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ ## Tópicos relacionados {#related-topics} -- [Estruturas de desenvolvimento](/developers/docs/frameworks/) -- [Configure um ambiente de desenvolvimento](/developers/local-environment/) +- [Frameworks de desenvolvimento](/developers/docs/frameworks/) +- [Configure um ambiente de desenvolvimento local](/developers/local-environment/) diff --git a/public/content/translations/pt-br/developers/docs/ethereum-stack/index.md b/public/content/translations/pt-br/developers/docs/ethereum-stack/index.md index 6d06607dc29..89965186446 100644 --- a/public/content/translations/pt-br/developers/docs/ethereum-stack/index.md +++ b/public/content/translations/pt-br/developers/docs/ethereum-stack/index.md @@ -1,5 +1,5 @@ --- -title: Introdução à pilha de Ethereum +title: "Introdução à pilha de Ethereum" description: Um passo a passo de diferentes camadas de pilha de Ethereum e como elas se encaixam. lang: pt-br --- @@ -10,41 +10,41 @@ Entretanto, existem tecnologias centrais da Ethereum que ajudam a fornecer um mo ## Nível 1: Máquina Virtual Ethereum {#ethereum-virtual-machine} -A [Ethereum Virtual Machine (EVM)](/developers/docs/evm/) é o ambiente de execução para contratos inteligentes na Ethereum. Todos os contratos inteligentes e alterações de estado na blockchain Ethereum são executados por [transações](/developers/docs/transactions/). A EVM controla todo o processamento de transações na rede Ethereum. +A [Máquina Virtual Ethereum (EVM)](/developers/docs/evm/) é o ambiente de execução para contratos inteligentes na Ethereum. Todos os contratos inteligentes e alterações de estado na blockchain Ethereum são executados por [transações](/developers/docs/transactions/). A EVM controla todo o processamento de transações na rede Ethereum. Como em qualquer máquina virtual, a EVM cria um nível de abstração entre o código de execução e a máquina de execução (um nó Ethereum). Atualmente, a EVM está executando em milhares de nós distribuídos pelo mundo. -Por trás das cortinas, a EVM utiliza um conjunto de instruções opcode para executar tarefas específicas. Esses opcodes (140 exclusivos) permitem que a EVM seja [Turing-complete](https://en.wikipedia.org/wiki/Turing_completeness), o que significa que a EVM é capaz de computar praticamente qualquer coisa, com recursos suficientes. +Por trás das cortinas, a EVM utiliza um conjunto de instruções opcode para executar tarefas específicas. Esses opcodes (140 únicos) permitem que a EVM seja [Turing-complete](https://en.wikipedia.org/wiki/Turing_completeness), o que significa que a EVM é capaz de computar praticamente qualquer coisa, com recursos suficientes. Como um desenvolvedor dapp, você não precisa saber muito sobre a EVM que não existe e isso alimenta de forma confiável todos os aplicativos na Ethereum sem interrupções. -## Nível 2: Contratos Inteligentes {#smart-contracts} +## Nível 2: Contratos inteligentes {#smart-contracts} -[Contratos inteligentes](/developers/docs/smart-contracts/) são os programas executáveis que funcionam na blockchain Ethereum. +[Contratos inteligentes](/developers/docs/smart-contracts/) são os programas executados na blockchain Ethereum. -Os contratos inteligentes são escritos usando [linguagens de programação](/developers/docs/smart-contracts/languages/) que compilam para bytecode EVM (instruções de máquina de baixo nível chamadas códigos de operação). +Os contratos inteligentes são escritos usando [linguagens de programação](/developers/docs/smart-contracts/languages/) específicas que compilam para bytecode da EVM (instruções de máquina de baixo nível chamadas de códigos de operação). -Não só os contratos inteligentes servem como bibliotecas de código aberto, eles são essencialmente serviços de API abertos que rodam 24/7 e não podem ser derrubados. Os contratos inteligentes fornecem funções públicas com as quais os aplicativos ([dapps](/developers/docs/dapps/)) podem interagir sem precisar de permissão. Qualquer aplicativo pode se integrar com contratos inteligentes implantados para compor funcionalidade, como adicionar [feeds de dados](/developers/docs/oracles/) ou suportar trocas de token. Qualquer um pode implantar novos contratos inteligentes para a Ethereum, a fim de adicionar funcionalidade personalizada para atender às necessidades do aplicativo. +Não só os contratos inteligentes servem como bibliotecas de código aberto, eles são essencialmente serviços de API abertos que rodam 24/7 e não podem ser derrubados. Os contratos inteligentes fornecem funções públicas com as quais usuários e aplicativos ([dapps](/developers/docs/dapps/)) podem interagir, sem precisar de permissão. Qualquer aplicativo pode se integrar com contratos inteligentes implantados para compor funcionalidades, como adicionar [feeds de dados](/developers/docs/oracles/) ou para suportar trocas de tokens. Qualquer um pode implantar novos contratos inteligentes para a Ethereum, a fim de adicionar funcionalidade personalizada para atender às necessidades do aplicativo. Como um desenvolvedor dapp, você só precisará escrever contratos inteligentes se desejar adicionar funcionalidade personalizada na blockchain Ethereum. Você pode encontrar que pode alcançar a maior parte ou todas as necessidades do seu projeto simplesmente integrando com contratos inteligentes existentes, por exemplo, se você deseja apoiar pagamentos em stablecoins ou habilitar o câmbio descentralizado de tokens. -## Nível 3: Nós Ethereum {#ethereum-nodes} +## Nível 3: Nós da Ethereum {#ethereum-nodes} -Para um aplicativo interagir com a blockchain Ethereum, ele deve se conectar a um [nó Ethereum](/developers/docs/nodes-and-clients/). Conectar-se a um nó permite que você leia dados da blockchain (cadeia de blocos) e/ou envie transações para a rede. +Para que um aplicativo interaja com a blockchain Ethereum, ele deve se conectar a um [nó Ethereum](/developers/docs/nodes-and-clients/). Conectar-se a um nó permite que você leia dados da blockchain (cadeia de blocos) e/ou envie transações para a rede. -Os nós Ethereum são computadores executando um software - um cliente Ethereum. Um cliente é uma implementação da Ethereum que verifica todas as transações em cada bloco, mantendo a rede segura e os dados precisos. **Os nós Ethereum são a blockchain (cadeia de blocos) Ethereum**. Eles armazenam coletivamente o estado da blockchain Ethereum e alcançam consenso sobre transações para alterar o estado da blockchain. +Os nós Ethereum são computadores executando um software - um cliente Ethereum. Um cliente é uma implementação do Ethereum que verifica todas as transações em cada bloco, mantendo a rede segura e os dados precisos. **Os nós Ethereum são a blockchain (cadeia de blocos) Ethereum**. Eles armazenam coletivamente o estado da blockchain Ethereum e alcançam consenso sobre transações para alterar o estado da blockchain. -Conectando seu aplicativo a um nó Ethereum (via [JSON-RPC API](/developers/docs/apis/json-rpc/)), sua aplicação é capaz de ler dados da blockchain (como os saldos das contas de usuários) bem como transmitir novas transações para a rede (como a transferência do ETH entre as contas de usuários ou a execução de funções de contratos inteligentes). +Ao conectar seu aplicativo a um nó Ethereum (via [API JSON-RPC](/developers/docs/apis/json-rpc/)), seu aplicativo pode ler dados da blockchain (como saldos de contas de usuário), bem como transmitir novas transações para a rede (como transferir ETH entre contas de usuário ou executar funções de contratos inteligentes). -## Nível 4: API de Cliente Ethereum {#ethereum-client-apis} +## Nível 4: APIs de cliente Ethereum {#ethereum-client-apis} Muitas bibliotecas de conveniência (desenvolvidas e mantidas pela comunidade de código aberto da Ethereum) permitem que seus aplicativos de usuário finais se conectem e se comuniquem com a blockchain Ethereum. -Se seu aplicativo voltado para o usuário for um aplicativo web, você pode optar por `instalar o npm` uma [API JavaScript](/developers/docs/apis/javascript/) diretamente no seu frontend. Ou talvez você escolha implementar esta funcionalidade do lado do servidor usando uma API [Python](/developers/docs/programming-languages/python/) ou [Java](/developers/docs/programming-languages/java/). +Se o seu aplicativo voltado para o usuário for um aplicativo da web, você pode optar por fazer o `npm install` de uma [API JavaScript](/developers/docs/apis/javascript/) diretamente em seu frontend. Ou talvez você opte por implementar essa funcionalidade no lado do servidor, usando uma API em [Python](/developers/docs/programming-languages/python/) ou [Java](/developers/docs/programming-languages/java/). -Embora essas APIs não sejam uma parte necessária da pilha, elas abstraem muito da complexidade de interagir diretamente com um nó Ethereum. Eles também fornecem funções de utilidade (por exemplo, Convertendo ETH para Gwei) para que como desenvolvedor você possa passar menos tempo lidando com as complexidades de clientes da Ethereum e mais tempo focado na funcionalidade única do seu aplicativo. +Embora essas APIs não sejam uma parte necessária da pilha, elas abstraem muito da complexidade de interagir diretamente com um nó Ethereum. Elas também fornecem funções utilitárias (p. ex., converter ETH para Gwei) para que, como desenvolvedor, você possa passar menos tempo lidando com as complexidades dos clientes Ethereum e mais tempo focado na funcionalidade específica de seu aplicativo. -## Nível 5: Aplicativos para o usuário final {#end-user-applications} +## Nível 5: Aplicativos de usuário final {#end-user-applications} No nível superior da pilha estão as aplicações voltadas para o usuário. Esses são os aplicativos padrão que você regularmente usa e constrói hoje: principalmente web e mobile apps. @@ -56,6 +56,6 @@ Confira o nosso guia para [configurar um ambiente de desenvolvimento local](/dev ## Leitura adicional {#further-reading} -- [A Arquitetura de uma aplicação Web 3.0](https://www.preethikasireddy.com/post/the-architecture-of-a-web-3-0-application) - _Preethi Kasireddy_ +- [A Arquitetura de um aplicativo Web 3.0](https://www.preethikasireddy.com/post/the-architecture-of-a-web-3-0-application) - _Preethi Kasireddy_ -_Conhece um recurso da comunidade que ajudou você? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ diff --git a/public/content/translations/pt-br/developers/docs/evm/index.md b/public/content/translations/pt-br/developers/docs/evm/index.md index c2a58be1975..78ea61961ee 100644 --- a/public/content/translations/pt-br/developers/docs/evm/index.md +++ b/public/content/translations/pt-br/developers/docs/evm/index.md @@ -1,62 +1,72 @@ --- -title: Máquina virtual do Ethereum (EVM) -description: Uma introdução à máquina virtual do Ethereum e como ela se relaciona com o estado, as transações e os contratos inteligentes. +title: "Máquina virtual Ethereum (EVM)" +description: "Uma introdução à máquina virtual do Ethereum e como ela se relaciona com o estado, as transações e os contratos inteligentes." lang: pt-br --- -A Máquina Virtual Ethereum (EVM, em inglês) é um ambiente virtual descentralizado que executa códigos de forma consistente e segura em todos os nós do Ethereum. Os "nós" executam a EVM para executar contratos inteligentes, usando "[gas](/gas/)" para medir o esforço computacional necessário para [operações](/developers/docs/evm/opcodes/), garantindo a alocação eficiente de recursos e a segurança da rede. +A Máquina Virtual Ethereum (EVM, em inglês) é um ambiente virtual descentralizado que executa códigos de forma consistente e segura em todos os nós do Ethereum. Os nós executam a EVM para executar contratos inteligentes, usando "[gás](/developers/docs/gas/)" para medir o esforço computacional necessário para [operações](/developers/docs/evm/opcodes/), garantindo a alocação eficiente de recursos e a segurança da rede. ## Pré-requisitos {#prerequisites} -Alguma familiaridade básica com a terminologia comum em ciência da computação, como [bytes](https://wikipedia.org/wiki/Byte), [memória](https://wikipedia.org/wiki/Computer_memory) e [pilha](https://wikipedia.org/wiki/Stack_(abstract_data_type)) é necessária para entender a EVM. Também recomendamos se familiarizar com conceitos de criptografia/cadeia de blocos, como [funções hash](https://wikipedia.org/wiki/Cryptographic_hash_function) e a [árvore Merkle](https://wikipedia.org/wiki/Merkle_tree). +É necessária uma familiaridade básica com a terminologia comum da ciência da computação, como [bytes](https://wikipedia.org/wiki/Byte), [memória](https://wikipedia.org/wiki/Computer_memory) e [pilha](https://wikipedia.org/wiki/Stack_\(abstract_data_type\)) para entender a EVM. Também seria útil estar familiarizado com conceitos de criptografia/blockchain, como [funções de hash](https://wikipedia.org/wiki/Cryptographic_hash_function) e a [árvore de Merkle](https://wikipedia.org/wiki/Merkle_tree). -## Do livro-razão para a máquina de estado {#from-ledger-to-state-machine} +## Do livro-razão à máquina de estado {#from-ledger-to-state-machine} A analogia de um 'livro-razão distribuído' é muitas vezes usada para descrever blockchains como o Bitcoin, que permite uma moeda descentralizada usando ferramentas fundamentais de criptografia. O livro-razão mantém um registro de atividades que deve aderir a um conjunto de regras que regem o que alguém pode e não pode fazer para modificar o livro-razão. Por exemplo, um endereço de Bitcoin não pode gastar mais Bitcoin do que o recebido previamente. Essas regras sustentam todas as transações em Bitcoin e em muitas outras blockchains. -Embora Ethereum tenha sua própria criptomoeda nativa (Ether), que segue quase exatamente as mesmas regras intuitivas, ele também permite dispor de uma função muito mais poderosa: [os contratos inteligentes](/developers/docs/smart-contracts/). Para este recurso mais complexo, uma analogia mais sofisticada é necessária. Em vez de um livro-razão distribuído, Ethereum é uma [máquina de estado distribuída](https://wikipedia.org/wiki/Finite-state_machine). O estado do Ethereum é uma grande estrutura de dados que contém não apenas todas as contas e saldos, mas também um _estado da máquina_, que pode mudar de bloco para bloco de acordo com um conjunto predefinido de regras, as quais podem executar código de máquina arbitrário. As regras específicas para mudar o estado de bloco em bloco são definidas pela EVM. +Embora o Ethereum tenha sua própria criptomoeda nativa (ether) que segue quase exatamente as mesmas regras intuitivas, ele também permite uma função muito mais poderosa: [contratos inteligentes](/developers/docs/smart-contracts/). Para este recurso mais complexo, uma analogia mais sofisticada é necessária. Em vez de um livro-razão distribuído, o Ethereum é uma [máquina de estado](https://wikipedia.org/wiki/Finite-state_machine) distribuída. O estado do Ethereum é uma grande estrutura de dados que contém não apenas todas as contas e saldos, mas também um _estado da máquina_, que pode mudar de bloco para bloco de acordo com um conjunto predefinido de regras e que pode executar um código de máquina arbitrário. As regras específicas para mudar o estado de bloco em bloco são definidas pela EVM. -![Um diagrama mostrando a criação da EVM](./evm.png) _Diagrama adaptado do [Ethereum EVM ilustrado](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ +![Um diagrama que mostra a composição da EVM](./evm.png) +_Diagrama adaptado de [Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ -## A função de transição do estado Ethereum {#the-ethereum-state-transition-function} +## A função de transição de estado do Ethereum {#the-ethereum-state-transition-function} -A EVM se comporta como uma função matemática seria: de acordo com a entrada, ele produz uma saída determinística. Portanto, é bastante útil descrever mais formalmente o Ethereum como tendo uma **função de transição de estado**: +A EVM se comporta como uma função matemática seria: de acordo com a entrada, ele produz uma saída determinística. Portanto, é muito útil descrever mais formalmente o Ethereum como tendo uma **função de transição de estado**: ``` Y(S, T)= S' ``` -Dado um antigo estado `(S)` e um novo conjunto de transações válidas `(T)`, a função de transição de estado de Ethereum `Y(S, T)` produz um novo estado de saída válido `S'` +Dado um estado válido antigo `(S)` e um novo conjunto de transações válidas `(T)`, a função de transição de estado do Ethereum `Y(S, T)` produz um novo estado de saída válido `S'` ### Estado {#state} -No contexto do Ethereum, o estado é uma enorme estrutura de dados chamada [árvore de Merkle Patricia modificada](/developers/docs/data-structures-and-encoding/patricia-merkle-trie/), que mantém todas as [contas](/developers/docs/accounts/) vinculadas por hashes e redutíveis a um único hash raiz armazenado na cadeia de blocos. +No contexto do Ethereum, o estado é uma enorme estrutura de dados chamada de [árvore de Merkle Patricia modificada](/developers/docs/data-structures-and-encoding/patricia-merkle-trie/), que mantém todas as [contas](/developers/docs/accounts/) vinculadas por hashes e redutíveis a um único hash raiz armazenado na cadeia de blocos. ### Transações {#transactions} Transações são instruções assinadas criptograficamente de contas. Existem dois tipos de transações: as que resultam em chamadas de mensagem e as que resultam na criação de contratos. -A criação do contrato resulta na criação de uma nova conta de contrato que contém o bytecode compilado do [contrato inteligente](/developers/docs/smart-contracts/anatomy/). Sempre que outra conta faz uma mensagem de chamada a esse contrato, ele executa seu bytecode. +A criação de contrato resulta na criação de uma nova conta de contrato contendo o bytecode compilado do [contrato inteligente](/developers/docs/smart-contracts/anatomy/). Sempre que outra conta faz uma mensagem de chamada a esse contrato, ele executa seu bytecode. ## Instruções da EVM {#evm-instructions} -A EVM é executada como uma [máquina de pilha](https://wikipedia.org/wiki/Stack_machine) com uma profundidade de 1.024 itens. Cada item é uma palavra de 256 bits, que foi escolhida para facilitar o uso com criptografia de 256 bits (como hashes Keccak-256 ou assinaturas secp256k1). +A EVM é executada como uma [máquina de pilha](https://wikipedia.org/wiki/Stack_machine) com uma profundidade de 1024 itens. Cada item é uma palavra de 256 bits, que foi escolhida para facilitar o uso com criptografia de 256 bits (como hashes Keccak-256 ou assinaturas secp256k1). -Durante a execução, a EVM mantém uma _memória transiente_ (como um array de bytes direcionado por palavra) que não persiste entre as transações. +Durante a execução, a EVM mantém uma _memória_ transiente (como um array de bytes endereçado por palavra), que não persiste entre transações. -Os contratos, no entanto, contêm uma árvore Merkle Patricia de _armazenamento_ (como um array direcionado por palavras) associada com a conta em questão e parte do estado global. +### Armazenamento transitório -O bytecode compilado do contrato inteligente executa como um número de [opcodes de EVM](/developers/docs/evm/opcodes), que realizam operações padrão de stake como `XOR`, `AND`, `ADD`, `SUB` etc. A EVM também implementa um número de operações de stake específicas da blockchain, como `ADDRESS`, `BALANCE`, `BLOCKHASH` etc. +O armazenamento transitório é um repositório de chave-valor por transação, acessado através dos opcodes `TSTORE` e `TLOAD`. Ele persiste em todas as chamadas internas durante a mesma transação, mas é apagado no final da transação. Diferentemente da memória, o armazenamento transitório é modelado como parte do estado da EVM, e não do quadro de execução, e ainda assim não é confirmado no estado global. O armazenamento transitório permite o compartilhamento temporário de estado com uso eficiente de gás entre as chamadas internas durante uma transação. -![Diagrama mostrando onde o consumo de gás é utilizado para as operações da EVM](../gas/gas.png) _Diagrama adaptado do [Ethereum EVM ilustrado](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ +### Armazenamento + +Os contratos contêm uma trie de _armazenamento_ Merkle Patricia (como um array de palavras endereçável por palavra), associada à conta em questão e parte do estado global. Este armazenamento persistente difere do armazenamento transitório, que está disponível apenas durante uma única transação e não faz parte da trie de armazenamento persistente da conta. + +### OpCodes + +O bytecode de contrato inteligente compilado é executado como uma série de [opcodes](/developers/docs/evm/opcodes) da EVM, que realizam operações de pilha padrão como `XOR`, `AND`, `ADD`, `SUB`, etc. A EVM também implementa várias operações de pilha específicas da blockchain, como `ADDRESS`, `BALANCE`, `BLOCKHASH`, etc. O conjunto de opcodes também inclui `TSTORE` e `TLOAD`, que fornecem acesso ao armazenamento transitório. + +![Um diagrama mostrando onde o gás é necessário para as operações da EVM](../gas/gas.png) +_Diagramas adaptados de [Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ ## Implementações da EVM {#evm-implementations} Todas as implementações da EVM devem aderir à especificação descrita no Ethereum Yellowpaper. -Durante o histórico de 9 anos do Ethereum, a EVM passou por várias revisões e existem várias implementações da EVM em várias linguagens de programação. +Ao longo dos dez anos de história do Ethereum, a EVM passou por diversas revisões, e existem várias implementações da EVM em diversas linguagens de programação. -Os [clientes de execução Ethereum](/developers/docs/nodes-and-clients/#execution-clients) incluem uma implementação EVM. Além disso, existem várias implementações independentes, incluindo: +Os [clientes de execução do Ethereum](/developers/docs/nodes-and-clients/#execution-clients) incluem uma implementação da EVM. Além disso, existem várias implementações independentes, incluindo: - [Py-EVM](https://github.com/ethereum/py-evm) - _Python_ - [evmone](https://github.com/ethereum/evmone) - _C++_ @@ -65,13 +75,13 @@ Os [clientes de execução Ethereum](/developers/docs/nodes-and-clients/#executi ## Leitura adicional {#further-reading} -- [Ethereum Yellowpaper](https://ethereum.github.io/yellowpaper/paper.pdf) -- [Jellopaper também conhecido como KEVM: semânticos de EVM em K](https://jellopaper.org/) -- [O Beigepaper](https://github.com/chronaeon/beigepaper) -- [Códigos de operação da EVM](https://www.ethervm.io/) -- [Referência interativa dos códigos de operação da máquina virtual Ethereum](https://www.evm.codes/) -- [Uma breve introdução à documentação do Solidy](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html#index-6) -- [Dominando Ethereum - A Máquina Virtual Ethereum](https://github.com/ethereumbook/ethereumbook/blob/openedition/13evm.asciidoc) +- [Yellowpaper do Ethereum](https://ethereum.github.io/yellowpaper/paper.pdf) +- [Jellopaper, também conhecido como KEVM: Semântica da EVM em K](https://jellopaper.org/) +- [The Beigepaper](https://github.com/chronaeon/beigepaper) +- [Opcodes da Máquina Virtual do Ethereum](https://www.ethervm.io/) +- [Referência interativa dos opcodes da Máquina Virtual Ethereum](https://www.evm.codes/) +- [Uma breve introdução na documentação do Solidity](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html#index-6) +- [Mastering Ethereum – A Máquina Virtual do Ethereum](https://github.com/ethereumbook/ethereumbook/blob/openedition/13evm.asciidoc) ## Tópicos relacionados {#related-topics} diff --git a/public/content/translations/pt-br/developers/docs/evm/opcodes/index.md b/public/content/translations/pt-br/developers/docs/evm/opcodes/index.md index 9f31f9c451c..a98c0050a02 100644 --- a/public/content/translations/pt-br/developers/docs/evm/opcodes/index.md +++ b/public/content/translations/pt-br/developers/docs/evm/opcodes/index.md @@ -1,174 +1,177 @@ --- title: Opcodes para o EVM -description: Uma lista de todos os opcodes disponíveis para a máquina virtual do Ethereum. +description: "Uma lista de todos os opcodes disponíveis para a máquina virtual do Ethereum." lang: pt-br --- ## Visão geral {#overview} -Essa é uma versão atualizada da página de referência EVM em [wolflo/evm-opcodes](https://github.com/wolflo/evm-opcodes). Também extraído do [Papel Amarelo](https://ethereum.github.io/yellowpaper/paper.pdf), do [Jello Paper](https://jellopaper.org/evm/) e da implementação [geth](https://github.com/ethereum/go-ethereum). Este artigo tem o intuito de ser uma referência acessível, mas não é particularmente rigorosa. Se quiser se certificar da exatidão e consciência de todos os casos extremos, é aconselhável usar o Jello Paper ou uma implementação do cliente. +Esta é uma versão atualizada da página de referência da EVM em [wolflo/evm-opcodes](https://github.com/wolflo/evm-opcodes). +Também extraído do [Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf), do [Jello Paper](https://jellopaper.org/evm/) e da implementação do [geth](https://github.com/ethereum/go-ethereum). +Este artigo tem o intuito de ser uma referência acessível, mas não é particularmente rigorosa. +Se quiser se certificar da exatidão e consciência de todos os casos extremos, é aconselhável usar o Jello Paper ou uma implementação do cliente. Procurando uma referência interativa? Confira [evm.codes](https://www.evm.codes/). -Para operações com custos de gás dinâmico, consulte [gas.md](https://github.com/wolflo/evm-opcodes/blob/main/gas.md). +Para operações com custos de gás dinâmicos, consulte [gas.md](https://github.com/wolflo/evm-opcodes/blob/main/gas.md). -💡 Dica rápida: Para ver linhas inteiras, use `[shift] + scroll` para rolar horizontalmente na área de trabalho. +💡 Dica rápida: Para ver linhas inteiras, use [shift] + scroll para rolar horizontalmente na área de trabalho. -| Pilha | Nome | Gás | Pilha inicial | Pilha resultante | Memória / Armazenamento | Observações | -|:-----:|:-------------- |:-----------------------------------------------------------------------------------------------:|:------------------------------------------------ |:-------------------------------------------- |:----------------------------------------------------------------------------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 00 | STOP | 0 | | | | halt execution | -| 01 | ADD | 3 | `a, b` | `a + b` | | (u)int256 addition modulo 2\*\*256 | -| 02 | MUL | 5 | `a, b` | `a * b` | | (u)int256 multiplication modulo 2\*\*256 | -| 03 | SUB | 3 | `a, b` | `a - b` | | (u)int256 addition modulo 2\*\*256 | -| 04 | DIV | 5 | `a, b` | `a // b` | | uint256 division | -| 05 | SDIV | 5 | `a, b` | `a // b` | | int256 division | -| 06 | MOD | 5 | `a, b` | `a % b` | | uint256 modulus | -| 07 | SMOD | 5 | `a, b` | `a % b` | | int256 modulus | -| 08 | ADDMOD | 8 | `a, b, N` | `(a + b) % N` | | (u)int256 addition modulo N | -| 09 | MULMOD | 8 | `a, b, N` | `(a * b) % N` | | (u)int256 multiplication modulo N | -| 0A | EXP | [A1](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a1-exp) | `a, b` | `a ** b` | | uint256 exponentiation modulo 2\*\*256 | -| 0B | SIGNEXTEND | 5 | `b, x` | `SIGNEXTEND(x, b)` | | [sign extend](https://wikipedia.org/wiki/Sign_extension) `x` from `(b+1)` bytes to 32 bytes | -| 0C-0F | _invalid_ | | | | | | -| 10 | LT | 3 | `a, b` | `a < b` | | uint256 less-than | -| 11 | GT | 3 | `a, b` | `a > b` | | uint256 greater-than | -| 12 | SLT | 3 | `a, b` | `a < b` | | int256 less-than | -| 13 | SGT | 3 | `a, b` | `a > b` | | int256 greater-than | -| 14 | EQ | 3 | `a, b` | `a == b` | | (u)int256 equality | -| 15 | ISZERO | 3 | `a` | `a == 0` | | (u)int256 iszero | -| 16 | AND | 3 | `a, b` | `a && b` | | bitwise AND | -| 17 | OR | 3 | `a, b` | `a \|\| b` | | bitwise OR | -| 18 | XOR | 3 | `a, b` | `a ^ b` | | bitwise XOR | -| 19 | NOT | 3 | `a` | `~a` | | bitwise NOT | -| 1A | BYTE | 3 | `i, x` | `(x >> (248 - i * 8)) && 0xFF` | | `i`th byte of (u)int256 `x`, from the left | -| 1B | SHL | 3 | `shift, val` | `val << shift` | | shift left | -| 1C | SHR | 3 | `shift, val` | `val >> shift` | | logical shift right | -| 1D | SAR | 3 | `shift, val` | `val >> shift` | | arithmetic shift right | -| 1E-1F | _invalid_ | | | | | | -| 20 | KECCAK256 | [A2](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a2-sha3) | `ost, len` | `keccak256(mem[ost:ost+len-1])` | | keccak256 | -| 21-2F | _invalid_ | | | | | | -| 30 | ADDRESS | 2 | `.` | `address(this)` | | address of executing contract | -| 31 | BALANCE | [A5](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a5-balance-extcodesize-extcodehash) | `addr` | `addr.balance` | | balance, in wei | -| 32 | ORIGIN | 2 | `.` | `tx.origin` | | address that originated the tx | -| 33 | CALLER | 2 | `.` | `msg.sender` | | address of msg sender | -| 34 | CALLVALUE | 2 | `.` | `msg.value` | | msg value, in wei | -| 35 | CALLDATALOAD | 3 | `idx` | `msg.data[idx:idx+32]` | | read word from msg data at index `idx` | -| 36 | CALLDATASIZE | 2 | `.` | `len(msg.data)` | | length of msg data, in bytes | -| 37 | CALLDATACOPY | [A3](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a3-copy-operations) | `dstOst, ost, len` | `.` | mem[dstOst:dstOst+len-1] := msg.data[ost:ost+len-1] | copy msg data | -| 38 | CODESIZE | 2 | `.` | `len(this.code)` | | length of executing contract's code, in bytes | -| 39 | CODECOPY | [A3](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a3-copy-operations) | `dstOst, ost, len` | `.` | | mem[dstOst:dstOst+len-1] := this.code[ost:ost+len-1] | copy executing contract's bytecode | -| 3A | GASPRICE | 2 | `.` | `tx.gasprice` | | gas price of tx, in wei per unit gas [\*\*](https://eips.ethereum.org/EIPS/eip-1559#gasprice) | -| 3B | EXTCODESIZE | [A5](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a5-balance-extcodesize-extcodehash) | `addr` | `len(addr.code)` | | size of code at addr, in bytes | -| 3C | EXTCODECOPY | [A4](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a4-extcodecopy) | `addr, dstOst, ost, len` | `.` | mem[dstOst:dstOst+len-1] := addr.code[ost:ost+len-1] | copy code from `addr` | -| 3D | RETURNDATASIZE | 2 | `.` | `size` | | size of returned data from last external call, in bytes | -| 3E | RETURNDATACOPY | [A3](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a3-copy-operations) | `dstOst, ost, len` | `.` | mem[dstOst:dstOst+len-1] := returndata[ost:ost+len-1] | copy returned data from last external call | -| 3F | EXTCODEHASH | [A5](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a5-balance-extcodesize-extcodehash) | `addr` | `hash` | | hash = addr.exists ? keccak256(addr.code) : 0 | -| 40 | BLOCKHASH | 20 | `blockNum` | `blockHash(blockNum)` | | | -| 41 | COINBASE | 2 | `.` | `block.coinbase` | | endereço do proponente do bloco atual | -| 42 | TIMESTAMP | 2 | `.` | `block.timestamp` | | timestamp of current block | -| 43 | NUMBER | 2 | `.` | `block.number` | | number of current block | -| 44 | PREVRANDAO | 2 | `.` | `randomness beacon` | | randomness beacon | -| 45 | GASLIMIT | 2 | `.` | `block.gaslimit` | | gas limit of current block | -| 46 | CHAINID | 2 | `.` | `chain_id` | | push current [chain id](https://eips.ethereum.org/EIPS/eip-155) onto stack | -| 47 | SELFBALANCE | 5 | `.` | `address(this).balance` | | balance of executing contract, in wei | -| 48 | BASEFEE | 2 | `.` | `block.basefee` | | base fee of current block | -| 49 | BLOBHASH | 3 | `idx` | `tx.blob_versioned_hashes[idx]` | | [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) | -| 4A | BLOBBASEFEE | 2 | `.` | `block.blobbasefee` | | blob base fee of current block ([EIP-7516](https://eips.ethereum.org/EIPS/eip-7516)) | -| 4B-4F | _invalid_ | | | | | | -| 50 | POP | 2 | `_anon` | `.` | | remove item from top of stack and discard it | -| 51 | MLOAD | 3[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost` | `mem[ost:ost+32]` | | read word from memory at offset `ost` | -| 52 | MSTORE | 3[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost, val` | `.` | mem[ost:ost+32] := val | write a word to memory | -| 53 | MSTORE8 | 3[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost, val` | `.` | mem[ost] := val && 0xFF | write a single byte to memory | -| 54 | SLOAD | [A6](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a6-sload) | `key` | `storage[key]` | | read word from storage | -| 55 | SSTORE | [A7](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a7-sstore) | `key, val` | `.` | storage[key] := val | write word to storage | -| 56 | JUMP | 8 | `dst` | `.` | | `$pc := dst` mark that `pc` is only assigned if `dst` is a valid jumpdest | -| 57 | JUMPI | 10 | `dst, condition` | `.` | | `$pc := condition ? dst : $pc + 1` | -| 58 | PC | 2 | `.` | `$pc` | | program counter | -| 59 | MSIZE | 2 | `.` | `len(mem)` | | size of memory in current execution context, in bytes | -| 5A | GAS | 2 | `.` | `gasRemaining` | | | -| 5B | JUMPDEST | 1 | | | mark valid jump destination | a valid jump destination for example a jump destination not inside the push data | -| 5C | TLOAD | 100 | `key` | `tstorage[key]` | | read word from transient storage ([EIP-1153](https://eips.ethereum.org/EIPS/eip-1153)) | -| 5D | TSTORE | 100 | `key, val` | `.` | tstorage[key] := val | write word to transient storage ([EIP-1153](https://eips.ethereum.org/EIPS/eip-1153)) | -| 5E | MCOPY | 3+3\*words+[A0](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `dstOst, ost, len` | `.` | mem[dstOst] := mem[ost:ost+len] | copy memory from one area to another ([EIP-5656](https://eips.ethereum.org/EIPS/eip-5656)) | -| 5F | PUSH0 | 2 | `.` | `uint8` | | empurra o valor constante 0 para a pilha | -| 60 | PUSH1 | 3 | `.` | `uint8` | | push 1-byte value onto stack | -| 61 | PUSH2 | 3 | `.` | `uint16` | | push 2-byte value onto stack | -| 62 | PUSH3 | 3 | `.` | `uint24` | | push 3-byte value onto stack | -| 63 | PUSH4 | 3 | `.` | `uint32` | | push 4-byte value onto stack | -| 64 | PUSH5 | 3 | `.` | `uint40` | | push 5-byte value onto stack | -| 65 | PUSH6 | 3 | `.` | `uint48` | | push 6-byte value onto stack | -| 66 | PUSH7 | 3 | `.` | `uint56` | | push 7-byte value onto stack | -| 67 | PUSH8 | 3 | `.` | `uint64` | | push 8-byte value onto stack | -| 68 | PUSH9 | 3 | `.` | `uint72` | | push 9-byte value onto stack | -| 69 | PUSH10 | 3 | `.` | `uint80` | | push 10-byte value onto stack | -| 6A | PUSH11 | 3 | `.` | `uint88` | | push 11-byte value onto stack | -| 6B | PUSH12 | 3 | `.` | `uint96` | | push 12-byte value onto stack | -| 6C | PUSH13 | 3 | `.` | `uint104` | | push 13-byte value onto stack | -| 6D | PUSH14 | 3 | `.` | `uint112` | | push 14-byte value onto stack | -| 6E | PUSH15 | 3 | `.` | `uint120` | | push 15-byte value onto stack | -| 6F | PUSH16 | 3 | `.` | `uint128` | | push 16-byte value onto stack | -| 70 | PUSH17 | 3 | `.` | `uint136` | | push 17-byte value onto stack | -| 71 | PUSH18 | 3 | `.` | `uint144` | | push 18-byte value onto stack | -| 72 | PUSH19 | 3 | `.` | `uint152` | | push 19-byte value onto stack | -| 73 | PUSH20 | 3 | `.` | `uint160` | | push 20-byte value onto stack | -| 74 | PUSH21 | 3 | `.` | `uint168` | | push 21-byte value onto stack | -| 75 | PUSH22 | 3 | `.` | `uint176` | | push 22-byte value onto stack | -| 76 | PUSH23 | 3 | `.` | `uint184` | | push 23-byte value onto stack | -| 77 | PUSH24 | 3 | `.` | `uint192` | | push 24-byte value onto stack | -| 78 | PUSH25 | 3 | `.` | `uint200` | | push 25-byte value onto stack | -| 79 | PUSH26 | 3 | `.` | `uint208` | | push 26-byte value onto stack | -| 7A | PUSH27 | 3 | `.` | `uint216` | | push 27-byte value onto stack | -| 7B | PUSH28 | 3 | `.` | `uint224` | | push 28-byte value onto stack | -| 7C | PUSH29 | 3 | `.` | `uint232` | | push 29-byte value onto stack | -| 7D | PUSH30 | 3 | `.` | `uint240` | | push 30-byte value onto stack | -| 7E | PUSH31 | 3 | `.` | `uint248` | | push 31-byte value onto stack | -| 7F | PUSH32 | 3 | `.` | `uint256` | | push 32-byte value onto stack | -| 80 | DUP1 | 3 | `a` | `a, a` | | clone 1st value on stack | -| 81 | DUP2 | 3 | `_, a` | `a, _, a` | | clone 2nd value on stack | -| 82 | DUP3 | 3 | `_, _, a` | `a, _, _, a` | | clone 3rd value on stack | -| 83 | DUP4 | 3 | `_, _, _, a` | `a, _, _, _, a` | | clone 4th value on stack | -| 84 | DUP5 | 3 | `..., a` | `a, ..., a` | | clone 5th value on stack | -| 85 | DUP6 | 3 | `..., a` | `a, ..., a` | | clone 6th value on stack | -| 86 | DUP7 | 3 | `..., a` | `a, ..., a` | | clone 7th value on stack | -| 87 | DUP8 | 3 | `..., a` | `a, ..., a` | | clone 8th value on stack | -| 88 | DUP9 | 3 | `..., a` | `a, ..., a` | | clone 9th value on stack | -| 89 | DUP10 | 3 | `..., a` | `a, ..., a` | | clone 10th value on stack | -| 8A | DUP11 | 3 | `..., a` | `a, ..., a` | | clone 11th value on stack | -| 8B | DUP12 | 3 | `..., a` | `a, ..., a` | | clone 12th value on stack | -| 8C | DUP13 | 3 | `..., a` | `a, ..., a` | | clone 13th value on stack | -| 8D | DUP14 | 3 | `..., a` | `a, ..., a` | | clone 14th value on stack | -| 8E | DUP15 | 3 | `..., a` | `a, ..., a` | | clone 15th value on stack | -| 8F | DUP16 | 3 | `..., a` | `a, ..., a` | | clone 16th value on stack | -| 90 | SWAP1 | 3 | `a, b` | `b, a` | | | -| 91 | SWAP2 | 3 | `a, _, b` | `b, _, a` | | | -| 92 | SWAP3 | 3 | `a, _, _, b` | `b, _, _, a` | | | -| 93 | SWAP4 | 3 | `a, _, _, _, b` | `b, _, _, _, a` | | | -| 94 | SWAP5 | 3 | `a, ..., b` | `b, ..., a` | | | -| 95 | SWAP6 | 3 | `a, ..., b` | `b, ..., a` | | | -| 96 | SWAP7 | 3 | `a, ..., b` | `b, ..., a` | | | -| 97 | SWAP8 | 3 | `a, ..., b` | `b, ..., a` | | | -| 98 | SWAP9 | 3 | `a, ..., b` | `b, ..., a` | | | -| 99 | SWAP10 | 3 | `a, ..., b` | `b, ..., a` | | | -| 9A | SWAP11 | 3 | `a, ..., b` | `b, ..., a` | | | -| 9B | SWAP12 | 3 | `a, ..., b` | `b, ..., a` | | | -| 9C | SWAP13 | 3 | `a, ..., b` | `b, ..., a` | | | -| 9D | SWAP14 | 3 | `a, ..., b` | `b, ..., a` | | | -| 9E | SWAP15 | 3 | `a, ..., b` | `b, ..., a` | | | -| 9F | SWAP16 | 3 | `a, ..., b` | `b, ..., a` | | | -| A0 | LOG0 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len` | `.` | | LOG0(memory[ost:ost+len-1]) | -| A1 | LOG1 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len, topic0` | `.` | | LOG1(memory[ost:ost+len-1], topic0) | -| A2 | LOG2 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len, topic0, topic1` | `.` | | LOG2(memory[ost:ost+len-1], topic0, topic1) | -| A3 | LOG3 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len, topic0, topic1, topic2` | `.` | | LOG3(memory[ost:ost+len-1], topic0, topic1, topic2) | -| A4 | LOG4 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len, topic0, topic1, topic2, topic3` | `.` | | LOG4(memory[ost:ost+len-1], topic0, topic1, topic2, topic3) | -| A5-EF | _invalid_ | | | | | | -| F0 | CREATE | [A9](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a9-create-operations) | `val, ost, len` | `addr` | | addr = keccak256(rlp([address(this), this.nonce])) | -| F1 | CALL | [AA](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-call-operations) | gas, addr, val, argOst, argLen, retOst, retLen | `success` | mem[retOst:retOst+retLen-1] := returndata | | -| F2 | CALLCODE | [AA](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-call-operations) | `gas, addr, val, argOst, argLen, retOst, retLen` | `success` | mem[retOst:retOst+retLen-1] = returndata | same as DELEGATECALL, but does not propagate original msg.sender and msg.value | -| F3 | RETURN | 0[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost, len` | `.` | | return mem[ost:ost+len-1] | -| F4 | DELEGATECALL | [AA](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-call-operations) | `gas, addr, argOst, argLen, retOst, retLen` | `success` | mem[retOst:retOst+retLen-1] := returndata | | -| F5 | CREATE2 | [A9](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a9-create-operations) | `val, ost, len, salt` | `addr` | | addr = keccak256(0xff ++ address(this) ++ salt ++ keccak256(mem[ost:ost+len-1]))[12:] | -| F6-F9 | _invalid_ | | | | | | -| FA | STATICCALL | [AA](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-call-operations) | `gas, addr, argOst, argLen, retOst, retLen` | `success` | mem[retOst:retOst+retLen-1] := returndata | | -| FB-FC | _invalid_ | | | | | | -| FD | REVERT | 0[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost, len` | `.` | | revert(mem[ost:ost+len-1]) | -| FE | INVALID | [AF](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#af-invalid) | | | designated invalid opcode - [EIP-141](https://eips.ethereum.org/EIPS/eip-141) | | -| FF | SELFDESTRUCT | [AB](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#ab-selfdestruct) | `addr` | `.` | | sends all ETH to `addr`; if executed in the same transaction as a contract was created it destroys the contract | +| Pilha | Nome | Gás | Pilha inicial | Pilha resultante | Memória / Armazenamento | Observações | | +| :---: | :------------- | :---------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | +| 00 | STOP | 0 | | | | interromper execução | | +| 01 | ADD | 3 | `a, b` | `a + b` | | adição de (u)int256 módulo 2\*\*256 | | +| 02 | MUL | 5 | `a, b` | `a * b` | | multiplicação de (u)int256 módulo 2\*\*256 | | +| 03 | SUB | 3 | `a, b` | `a - b` | | subtração de (u)int256 módulo 2\*\*256 | | +| 04 | DIV | 5 | `a, b` | `a // b` | | divisão de uint256 | | +| 05 | SDIV | 5 | `a, b` | `a // b` | | divisão de int256 | | +| 06 | MOD | 5 | `a, b` | `a % b` | | módulo uint256 | | +| 07 | SMOD | 5 | `a, b` | `a % b` | | módulo int256 | | +| 08 | ADDMOD | 8 | `a, b, N` | `(a + b) % N` | | adição de (u)int256 módulo N | | +| 09 | MULMOD | 8 | `a, b, N` | `(a * b) % N` | | multiplicação de (u)int256 módulo N | | +| 0A | EXP | [A1](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a1-exp) | `a, b` | `a ** b` | | exponenciação de uint256 módulo 2\*\*256 | | +| 0B | SIGNEXTEND | 5 | `b, x` | `SIGNEXTEND(x, b)` | | [estender sinal](https://wikipedia.org/wiki/Sign_extension) de `x` de `(b+1)` bytes para 32 bytes | | +| 0C-0F | _inválido_ | | | | | | | +| 10 | LT | 3 | `a, b` | `a < b` | | uint256 menor que | | +| 11 | GT | 3 | `a, b` | `a > b` | | uint256 maior que | | +| 12 | SLT | 3 | `a, b` | `a < b` | | int256 menor que | | +| 13 | SGT | 3 | `a, b` | `a > b` | | int256 maior que | | +| 14 | EQ | 3 | `a, b` | `a == b` | | igualdade de (u)int256 | | +| 15 | ISZERO | 3 | `a` | `a == 0` | | (u)int256 é zero | | +| 16 | AND | 3 | `a, b` | `a && b` | | AND bit a bit | | +| 17 | OR | 3 | `a, b` | `a \\|\\| b` | | OR bit a bit | | +| 18 | XOR | 3 | `a, b` | `a ^ b` | | XOR bit a bit | | +| 19 | NOT | 3 | `a` | `~a` | | NOT bit a bit | | +| 1A | BYTE | 3 | `i, x` | `(x >> (248 - i * 8)) && 0xFF` | | `i`-ésimo byte de (u)int256 `x`, da esquerda | | +| 1B | SHL | 3 | `shift, val` | `val << shift` | | deslocamento à esquerda | | +| 1C | SHR | 3 | `shift, val` | `val >> shift` | | deslocamento lógico à direita | | +| 1D | SAR | 3 | `shift, val` | `val >> shift` | | deslocamento aritmético à direita | | +| 1E-1F | _inválido_ | | | | | | | +| 20 | KECCAK256 | [A2](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a2-sha3) | `ost, len` | `keccak256(mem[ost:ost+len-1])` | | keccak256 | | +| 21-2F | _inválido_ | | | | | | | +| 30 | ADDRESS | 2 | `.` | `address(this)` | | endereço do contrato em execução | | +| 31 | BALANCE | [A5](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a5-balance-extcodesize-extcodehash) | `addr` | `addr.balance` | | saldo, em wei | | +| 32 | ORIGIN | 2 | `.` | `tx.origin` | | endereço que originou a tx | | +| 33 | CALLER | 2 | `.` | `msg.sender` | | endereço do remetente da msg | | +| 34 | CALLVALUE | 2 | `.` | `msg.value` | | valor da msg, em wei | | +| 35 | CALLDATALOAD | 3 | `idx` | `msg.data[idx:idx+32]` | | lê a palavra dos dados da msg no índice `idx` | | +| 36 | CALLDATASIZE | 2 | `.` | `len(msg.data)` | | comprimento dos dados da msg, em bytes | | +| 37 | CALLDATACOPY | [A3](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a3-copy-operations) | `dstOst, ost, len` | `.` | mem[dstOst:dstOst+len-1] := msg.data[ost:ost+len-1] | copiar dados da msg | | +| 38 | CODESIZE | 2 | `.` | `len(this.code)` | | comprimento do código do contrato em execução, em bytes | | +| 39 | CODECOPY | [A3](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a3-copy-operations) | `dstOst, ost, len` | `.` | | mem[dstOst:dstOst+len-1] := this.code[ost:ost+len-1] | copia o bytecode do contrato em execução | +| 3A | GASPRICE | 2 | `.` | `tx.gasprice` | | preço do gás da transação, em wei por unidade de gás [\*\*](https://eips.ethereum.org/EIPS/eip-1559#gasprice) | | +| 3B | EXTCODESIZE | [A5](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a5-balance-extcodesize-extcodehash) | `addr` | `len(addr.code)` | | tamanho do código no endereço (addr), em bytes | | +| 3C | EXTCODECOPY | [A4](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a4-extcodecopy) | `addr, dstOst, ost, len` | `.` | mem[dstOst:dstOst+len-1] := addr.code[ost:ost+len-1] | copia o código de `addr` | | +| 3D | RETURNDATASIZE | 2 | `.` | `size` | | tamanho dos dados retornados da última chamada externa, em bytes | | +| 3E | RETURNDATACOPY | [A3](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a3-copy-operations) | `dstOst, ost, len` | `.` | mem[dstOst:dstOst+len-1] := returndata[ost:ost+len-1] | copia os dados retornados da última chamada externa | | +| 3F | EXTCODEHASH | [A5](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a5-balance-extcodesize-extcodehash) | `addr` | `hash` | | hash = addr.exists ? keccak256(addr.code) : 0 | | +| 40 | BLOCKHASH | 20 | `blockNum` | `blockHash(blockNum)` | | | | +| 41 | COINBASE | 2 | `.` | `block.coinbase` | | endereço do proponente do bloco atual | | +| 42 | TIMESTAMP | 2 | `.` | `block.timestamp` | | carimbo de data/hora do bloco atual | | +| 43 | NUMBER | 2 | `.` | `block.number` | | número do bloco atual | | +| 44 | PREVRANDAO | 2 | `.` | `sinalizador de aleatoriedade` | | sinalizador de aleatoriedade | | +| 45 | GASLIMIT | 2 | `.` | `block.gaslimit` | | limite de gás do bloco atual | | +| 46 | CHAINID | 2 | `.` | `chain_id` | | envia o [ID da cadeia](https://eips.ethereum.org/EIPS/eip-155) atual para a pilha | | +| 47 | SELFBALANCE | 5 | `.` | `address(this).balance` | | saldo do contrato em execução, em wei | | +| 48 | BASEFEE | 2 | `.` | `block.basefee` | | taxa base do bloco atual | | +| 49 | BLOBHASH | 3 | `idx` | `tx.blob_versioned_hashes[idx]` | | [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) | | +| 4A | BLOBBASEFEE | 2 | `.` | `block.blobbasefee` | | taxa base do blob do bloco atual ([EIP-7516](https://eips.ethereum.org/EIPS/eip-7516)) | | +| 4B-4F | _inválido_ | | | | | | | +| 50 | POP | 2 | `_anon` | `.` | | remove o item do topo da pilha e o descarta | | +| 51 | MLOAD | 3[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost` | `mem[ost:ost+32]` | | lê uma palavra da memória no deslocamento `ost` | | +| 52 | MSTORE | 3[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost, val` | `.` | mem[ost:ost+32] := val | escreve uma palavra na memória | | +| 53 | MSTORE8 | 3[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost, val` | `.` | mem[ost] := val && 0xFF | escreve um único byte na memória | | +| 54 | SLOAD | [A6](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a6-sload) | `key` | `storage[key]` | | lê a palavra do armazenamento | | +| 55 | SSTORE | [A7](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a7-sstore) | `key, val` | `.` | storage[key] := val | escreve uma palavra no armazenamento | | +| 56 | JUMP | 8 | `dst` | `.` | | `$pc := dst` marca que `pc` só é atribuído se `dst` for um jumpdest válido | | +| 57 | JUMPI | 10 | `dst, condition` | `.` | | `$pc := condition ? dst : $pc + 1` | | +| 58 | PC | 2 | `.` | `$pc` | | contador de programa | | +| 59 | MSIZE | 2 | `.` | `len(mem)` | | tamanho da memória no contexto de execução atual, em bytes | | +| 5A | GAS | 2 | `.` | `gasRemaining` | | | | +| 5B | JUMPDEST | 1 | | | marca um destino de salto válido | um destino de salto válido, por exemplo, um destino de salto que não esteja dentro dos dados push | | +| 5C | TLOAD | 100 | `key` | `tstorage[key]` | | lê palavra do armazenamento transiente ([EIP-1153](https://eips.ethereum.org/EIPS/eip-1153)) | | +| 5D | TSTORE | 100 | `key, val` | `.` | tstorage[key] := val | escreve palavra no armazenamento transiente ([EIP-1153](https://eips.ethereum.org/EIPS/eip-1153)) | | +| 5E | MCOPY | 3+3\*words+[A0](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `dstOst, ost, len` | `.` | mem[dstOst] := mem[ost:ost+len] | copia memória de uma área para outra ([EIP-5656](https://eips.ethereum.org/EIPS/eip-5656)) | | +| 5F | PUSH0 | 2 | `.` | `uint8` | | empurra o valor constante 0 para a pilha | | +| 60 | PUSH1 | 3 | `.` | `uint8` | | envia um valor de 1 byte para a pilha | | +| 61 | PUSH2 | 3 | `.` | `uint16` | | envia um valor de 2 bytes para a pilha | | +| 62 | PUSH3 | 3 | `.` | `uint24` | | envia um valor de 3 bytes para a pilha | | +| 63 | PUSH4 | 3 | `.` | `uint32` | | envia um valor de 4 bytes para a pilha | | +| 64 | PUSH5 | 3 | `.` | `uint40` | | envia um valor de 5 bytes para a pilha | | +| 65 | PUSH6 | 3 | `.` | `uint48` | | envia um valor de 6 bytes para a pilha | | +| 66 | PUSH7 | 3 | `.` | `uint56` | | envia um valor de 7 bytes para a pilha | | +| 67 | PUSH8 | 3 | `.` | `uint64` | | envia um valor de 8 bytes para a pilha | | +| 68 | PUSH9 | 3 | `.` | `uint72` | | envia um valor de 9 bytes para a pilha | | +| 69 | PUSH10 | 3 | `.` | `uint80` | | envia um valor de 10 bytes para a pilha | | +| 6A | PUSH11 | 3 | `.` | `uint88` | | envia um valor de 11 bytes para a pilha | | +| 6B | PUSH12 | 3 | `.` | `uint96` | | envia um valor de 12 bytes para a pilha | | +| 6C | PUSH13 | 3 | `.` | `uint104` | | envia um valor de 13 bytes para a pilha | | +| 6D | PUSH14 | 3 | `.` | `uint112` | | envia um valor de 14 bytes para a pilha | | +| 6E | PUSH15 | 3 | `.` | `uint120` | | envia um valor de 15 bytes para a pilha | | +| 6F | PUSH16 | 3 | `.` | `uint128` | | envia um valor de 16 bytes para a pilha | | +| 70 | PUSH17 | 3 | `.` | `uint136` | | envia um valor de 17 bytes para a pilha | | +| 71 | PUSH18 | 3 | `.` | `uint144` | | envia um valor de 18 bytes para a pilha | | +| 72 | PUSH19 | 3 | `.` | `uint152` | | envia um valor de 19 bytes para a pilha | | +| 73 | PUSH20 | 3 | `.` | `uint160` | | envia um valor de 20 bytes para a pilha | | +| 74 | PUSH21 | 3 | `.` | `uint168` | | envia um valor de 21 bytes para a pilha | | +| 75 | PUSH22 | 3 | `.` | `uint176` | | envia um valor de 22 bytes para a pilha | | +| 76 | PUSH23 | 3 | `.` | `uint184` | | envia um valor de 23 bytes para a pilha | | +| 77 | PUSH24 | 3 | `.` | `uint192` | | envia um valor de 24 bytes para a pilha | | +| 78 | PUSH25 | 3 | `.` | `uint200` | | envia um valor de 25 bytes para a pilha | | +| 79 | PUSH26 | 3 | `.` | `uint208` | | envia um valor de 26 bytes para a pilha | | +| 7A | PUSH27 | 3 | `.` | `uint216` | | envia um valor de 27 bytes para a pilha | | +| 7B | PUSH28 | 3 | `.` | `uint224` | | envia um valor de 28 bytes para a pilha | | +| 7C | PUSH29 | 3 | `.` | `uint232` | | envia um valor de 29 bytes para a pilha | | +| 7D | PUSH30 | 3 | `.` | `uint240` | | envia um valor de 30 bytes para a pilha | | +| 7E | PUSH31 | 3 | `.` | `uint248` | | envia um valor de 31 bytes para a pilha | | +| 7F | PUSH32 | 3 | `.` | `uint256` | | envia um valor de 32 bytes para a pilha | | +| 80 | DUP1 | 3 | `a` | `a, a` | | clona o 1º valor na pilha | | +| 81 | DUP2 | 3 | `_, a` | `a, _, a` | | clona o 2º valor na pilha | | +| 82 | DUP3 | 3 | `_, _, a` | `a, _, _, a` | | clona o 3º valor na pilha | | +| 83 | DUP4 | 3 | `_, _, _, a` | `a, _, _, _, a` | | clona o 4º valor na pilha | | +| 84 | DUP5 | 3 | `..., a` | `a, ..., a` | | clona o 5º valor na pilha | | +| 85 | DUP6 | 3 | `..., a` | `a, ..., a` | | clona o 6º valor na pilha | | +| 86 | DUP7 | 3 | `..., a` | `a, ..., a` | | clona o 7º valor na pilha | | +| 87 | DUP8 | 3 | `..., a` | `a, ..., a` | | clona o 8º valor na pilha | | +| 88 | DUP9 | 3 | `..., a` | `a, ..., a` | | clona o 9º valor na pilha | | +| 89 | DUP10 | 3 | `..., a` | `a, ..., a` | | clona o 10º valor na pilha | | +| 8A | DUP11 | 3 | `..., a` | `a, ..., a` | | clona o 11º valor na pilha | | +| 8B | DUP12 | 3 | `..., a` | `a, ..., a` | | clona o 12º valor na pilha | | +| 8C | DUP13 | 3 | `..., a` | `a, ..., a` | | clona o 13º valor na pilha | | +| 8D | DUP14 | 3 | `..., a` | `a, ..., a` | | clona o 14º valor na pilha | | +| 8E | DUP15 | 3 | `..., a` | `a, ..., a` | | clona o 15º valor na pilha | | +| 8F | DUP16 | 3 | `..., a` | `a, ..., a` | | clona o 16º valor na pilha | | +| 90 | SWAP1 | 3 | `a, b` | `b, a` | | | | +| 91 | SWAP2 | 3 | `a, _, b` | `b, _, a` | | | | +| 92 | SWAP3 | 3 | `a, _, _, b` | `b, _, _, a` | | | | +| 93 | SWAP4 | 3 | `a, _, _, _, b` | `b, _, _, _, a` | | | | +| 94 | SWAP5 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 95 | SWAP6 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 96 | SWAP7 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 97 | SWAP8 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 98 | SWAP9 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 99 | SWAP10 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 9A | SWAP11 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 9B | SWAP12 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 9C | SWAP13 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 9D | SWAP14 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 9E | SWAP15 | 3 | `a, ..., b` | `b, ..., a` | | | | +| 9F | SWAP16 | 3 | `a, ..., b` | `b, ..., a` | | | | +| A0 | LOG0 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len` | `.` | | LOG0(memory[ost:ost+len-1]) | | +| A1 | LOG1 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len, topic0` | `.` | | LOG1(memory[ost:ost+len-1], topic0) | | +| A2 | LOG2 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len, topic0, topic1` | `.` | | LOG2(memory[ost:ost+len-1], topic0, topic1) | | +| A3 | LOG3 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len, topic0, topic1, topic2` | `.` | | LOG3(memory[ost:ost+len-1], topic0, topic1, topic2) | | +| A4 | LOG4 | [A8](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations) | `ost, len, topic0, topic1, topic2, topic3` | `.` | | LOG4(memory[ost:ost+len-1], topic0, topic1, topic2, topic3) | | +| A5-EF | _inválido_ | | | | | | | +| F0 | CREATE | [A9](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a9-create-operations) | `val, ost, len` | `addr` | | addr = keccak256(rlp([address(this), this.nonce])) | | +| F1 | CALL | [AA](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-call-operations) | gás, addr, val, argOst, argLen, retOst, retLen | `sucesso` | mem[retOst:retOst+retLen-1] := returndata | | | +| F2 | CALLCODE | [AA](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-call-operations) | `gás, addr, val, argOst, argLen, retOst, retLen` | `sucesso` | mem[retOst:retOst+retLen-1] = returndata | o mesmo que DELEGATECALL, mas não propaga o msg.sender e o msg.value originais | | +| F3 | RETURN | 0[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost, len` | `.` | | retorna mem[ost:ost+len-1] | | +| F4 | DELEGATECALL | [AA](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-call-operations) | `gás, addr, argOst, argLen, retOst, retLen` | `sucesso` | mem[retOst:retOst+retLen-1] := returndata | | | +| F5 | CREATE2 | [A9](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a9-create-operations) | `val, ost, len, salt` | `addr` | | addr = keccak256(0xff ++ address(this) ++ salt ++ keccak256(mem[ost:ost+len-1]))[12:] | | +| F6-F9 | _inválido_ | | | | | | | +| FA | STATICCALL | [AA](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-call-operations) | `gás, addr, argOst, argLen, retOst, retLen` | `sucesso` | mem[retOst:retOst+retLen-1] := returndata | | | +| FB-FC | _inválido_ | | | | | | | +| FD | REVERT | 0[\*](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-1-memory-expansion) | `ost, len` | `.` | | revert(mem[ost:ost+len-1]) | | +| FE | INVALID | [AF](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#af-invalid) | | | opcode inválido designado - [EIP-141](https://eips.ethereum.org/EIPS/eip-141) | | | +| FF | SELFDESTRUCT | [AB](https://github.com/wolflo/evm-opcodes/blob/main/gas.md#ab-selfdestruct) | `addr` | `.` | | envia todo o ETH para `addr`; se executado na mesma transação em que um contrato foi criado, destrói o contrato | | diff --git a/public/content/translations/pt-br/developers/docs/frameworks/index.md b/public/content/translations/pt-br/developers/docs/frameworks/index.md index 344059241c4..6e40d7e2737 100644 --- a/public/content/translations/pt-br/developers/docs/frameworks/index.md +++ b/public/content/translations/pt-br/developers/docs/frameworks/index.md @@ -1,32 +1,39 @@ --- title: Frameworks de Desenvolvimento de Dapp -description: Explore as vantagens de frameworks e compare as opções disponíveis. +description: "Explore as vantagens de frameworks e compare as opções disponíveis." lang: pt-br --- ## Introdução aos frameworks {#introduction-to-frameworks} -Criar um aplicativo completo requer diferentes peças de tecnologia. Os frameworks de software incluem muitos dos recursos necessários ou fornecem sistemas de plugins fáceis para escolher as ferramentas que você deseja. +Criar um aplicativo completo requer +diferentes peças de tecnologia. Os frameworks de software incluem muitos dos recursos +necessários ou fornecem sistemas de plugins fáceis para escolher as ferramentas que você +deseja. Esses frameworks vêm com muitas funcionalidades prontas para usar, como: -- Recursos para ativar uma instância local do blockchain. +- Recursos para ativar uma instância local de blockchain. - Utilitários para compilar e testar seus contratos inteligentes. -- Complementos de desenvolvimento de cliente para criar seu aplicativo do usuário dentro do mesmo projeto/repositório. -- Configuração para se conectar a redes Ethereum e implantar contratos, seja para uma instância em execução local ou uma das redes públicas da Ethereum. -- Distribuição descentralizada de aplicativos - integrações com opções de armazenamento como o IPFS. +- Complementos de desenvolvimento de cliente para criar seu aplicativo voltado para o usuário + no mesmo projeto/repositório. +- Configuração para se conectar às redes Ethereum e implantar + contratos, seja em uma instância em execução local ou em uma das + redes públicas da Ethereum. +- Distribuição de aplicativos descentralizados: integrações com opções de armazenamento + como o IPFS. ## Pré-requisitos {#prerequisites} -Antes de mergulhar em frameworks, recomendamos que você primeiro leia a nossa introdução aos [dapps](/developers/docs/dapps/) e a [pilha de Ethereum](/developers/docs/ethereum-stack/). +Antes de mergulhar nos frameworks, recomendamos que você leia primeiro nossa introdução aos [dapps](/developers/docs/dapps/) e à [pilha Ethereum](/developers/docs/ethereum-stack/). ## Frameworks disponíveis {#available-frameworks} -**Foundry** - **_Foundry é um kit de ferramentas incrivelmente rápido, portátil e modular para desenvolvimento de aplicativos Ethereum_** +**Foundry** - **_O Foundry é um kit de ferramentas incrivelmente rápido, portátil e modular para o desenvolvimento de aplicativos Ethereum_** -- [Instalar Foundry](https://book.getfoundry.sh/) -- [Livro sobre Foundry](https://book.getfoundry.sh/) -- [Bate-papo da comunidade Foundry no Telegram](https://t.me/foundry_support) +- [Instalar o Foundry](https://book.getfoundry.sh/) +- [Livro do Foundry](https://book.getfoundry.sh/) +- [Chat da comunidade Foundry no Telegram](https://t.me/foundry_support) - [Awesome Foundry](https://github.com/crisgarner/awesome-foundry) **Hardhat -** **_Ambiente de desenvolvimento da Ethereum para profissionais._** @@ -34,12 +41,12 @@ Antes de mergulhar em frameworks, recomendamos que você primeiro leia a nossa i - [hardhat.org](https://hardhat.org) - [GitHub](https://github.com/nomiclabs/hardhat) -**Macaco -** **_A ferramenta de desenvolvimento de contratos inteligentes para Pythonistas, Cientistas de Dados e Profissionais de Segurança._** +**Ape -** **_A ferramenta de desenvolvimento de contratos inteligentes para Pythonistas, cientistas de dados e profissionais de segurança._** - [Documentação](https://docs.apeworx.io/ape/stable/) - [GitHub](https://github.com/ApeWorX/ape) -**Web3j -** **_Uma plataforma para desenvolver aplicativos blockchain na JVM._** +**Web3j -** **_Uma plataforma para desenvolver aplicativos de blockchain na JVM._** - [Página inicial](https://www.web3labs.com/web3j-sdk) - [Documentação](https://docs.web3j.io) @@ -51,23 +58,23 @@ Antes de mergulhar em frameworks, recomendamos que você primeiro leia a nossa i - [Exemplos](https://github.com/Kr1ptal/ethers-kt/tree/master/examples) - [Discord](https://discord.gg/rx35NzQGSb) -**Criar um app Eth-** **_Crie aplicativos com a tecnologia Ethereum com apenas um comando. Vem com uma ampla oferta de estruturas de interface do usuário e modelos DeFi para escolher._** +**Create Eth App -** **_Crie aplicativos baseados em Ethereum com um comando._** Vem com uma ampla oferta de estruturas de interface do usuário e modelos DeFi para escolher._\*\* - [GitHub](https://github.com/paulrberg/create-eth-app) - [Modelos](https://github.com/PaulRBerg/create-eth-app/tree/develop/templates) -**Scaffold-Eth -** **_componentes e hooks Ethers.js + Hardhat + React para web3: tudo o que você precisa para começar a criar aplicativos descentralizados com tecnologia de contratos inteligentes._** +**Scaffold-Eth -** **_Ethers.js + Hardhat + componentes e hooks React para web3: tudo o que você precisa para começar a construir aplicativos descentralizados com tecnologia de contratos inteligentes._** - [GitHub](https://github.com/scaffold-eth/scaffold-eth-2) -**Tenderly -** **_Plataforma de desenvolvimento web3 que permite aos desenvolvedores de blockchain criar, testar, depurar, monitorar e operar contratos inteligentes e melhorar a UX do dapp._** +**Tenderly -** **_Plataforma de desenvolvimento Web3 que permite aos desenvolvedores de blockchain construir, testar, depurar, monitorar e operar contratos inteligentes e melhorar a UX do dapp._** -- [Website](https://tenderly.co/) +- [Site](https://tenderly.co/) - [Documentação](https://docs.tenderly.co/) -**The Graph -** **_The Graph para consultar dados de blockchain com eficiência._** +**The Graph -** **_O The Graph para consultar dados de blockchain com eficiência._** -- [Website](https://thegraph.com/) +- [Site](https://thegraph.com/) - [Tutorial](/developers/tutorials/the-graph-fixing-web3-data-querying/) **Alchemy -** **_Plataforma de Desenvolvimento Ethereum._** @@ -82,7 +89,7 @@ Antes de mergulhar em frameworks, recomendamos que você primeiro leia a nossa i - [GitHub](https://github.com/node-real) - [Discord](https://discord.gg/V5k5gsuE) -**thirdweb SDK -** **_Crie aplicativos web3 que podem interagir com seus contratos inteligentes usando nossos SDKs e CLI avançados._** +**thirdweb SDK -** **_Crie aplicativos web3 que possam interagir com seus contratos inteligentes usando nossos poderosos SDKs e CLI._** - [Documentação](https://portal.thirdweb.com/sdk/) - [GitHub](https://github.com/thirdweb-dev/) @@ -93,44 +100,46 @@ Antes de mergulhar em frameworks, recomendamos que você primeiro leia a nossa i - [GitHub](https://github.com/chainstack) - [Discord](https://discord.gg/BSb5zfp9AT) -**Crossmint-****_A plataforma web3 de desenvolvimento a nível empresarial que permite a criação de NFTs nas principais cadeias EVM (entre outras)._** +**Crossmint -** **_Plataforma de desenvolvimento web3 de nível empresarial, que permite criar aplicativos NFT em todas as principais cadeias EVM (e outras)._** -- [Website](https://www.crossmint.com) +- [Site](https://www.crossmint.com) - [Documentação](https://docs.crossmint.com) - [Discord](https://discord.com/invite/crossmint) -**Brownie -** **_Ambiente de desenvolvimento e framework de testes em Python._** +**Brownie -** **_Ambiente de desenvolvimento e framework de testes baseado em Python._** - [Documentação](https://eth-brownie.readthedocs.io/en/latest/) - [GitHub](https://github.com/eth-brownie/brownie) - **Brownie deixou de ser desenvolvido** -**OpenZeppelin SDK -** **_The Ultimate Smart Contract Toolkit: um conjunto de ferramentas para ajudar você a desenvolver, compilar, atualizar, implantar e interagir com contratos inteligentes._** +**OpenZeppelin SDK -** **_O kit de ferramentas definitivo para contratos inteligentes: um conjunto de ferramentas para ajudar você a desenvolver, compilar, atualizar, implantar e interagir com contratos inteligentes._** -- [SDK da OpenZeppelin](https://openzeppelin.com/sdk/) +- [SDK do OpenZeppelin Defender](https://docs.openzeppelin.com/defender/sdk) - [GitHub](https://github.com/OpenZeppelin/openzeppelin-sdk) -- [Fórum da Comunidade](https://forum.openzeppelin.com/c/support/17) +- [Fórum da comunidade](https://forum.openzeppelin.com/c/support/17) - **O desenvolvimento do SDK da OpenZeppelin foi finalizado** -**Catapulta -** **_Ferramenta de contrato inteligente em várias cadeias que automatiza a verificação em exploradores de blocos, monitora os contratos inteligentes e compartilha relatórios de implementação desse contratos plug-n-play para projetos Foundry e Hardhat._** +**Catapulta -** **_Ferramenta de implantação de contratos inteligentes multi-chain, automatiza verificações em exploradores de blocos, acompanha contratos inteligentes implantados e compartilha relatórios de implantação, plug-n-play para projetos Foundry e Hardhat._** +- [Site](https://catapulta.sh/) +- [Documentação](https://catapulta.sh/docs) - [GitHub](https://github.com/catapulta-sh) -**Covalent -** **_APIs de blockchain enriquecidas para mais de 200 redes._** +**GoldRush (desenvolvido por Covalent) -** **_O GoldRush oferece o mais completo conjunto de APIs de dados de blockchain para desenvolvedores, analistas e empresas._** Esteja você construindo um painel DeFi, uma carteira, um bot de negociação, um agente de IA ou uma plataforma de conformidade, as APIs de dados fornecem acesso rápido, preciso e amigável ao desenvolvedor para os dados essenciais na cadeia de que você precisa_\*\* -- [covalenthq.com](https://www.covalenthq.com/) -- [Documentação](https://www.covalenthq.com/docs/api/) +- [Site](https://goldrush.dev/) +- [Documentação](https://goldrush.dev/docs/chains/ethereum) - [GitHub](https://github.com/covalenthq) - [Discord](https://www.covalenthq.com/discord/) -**Wake -** **_Tudo em um Framework Python completo para testes de contratos, fuzzing, implantação, varredura de vulnerabilidades e navegação no código._** +**Wake -** **_Framework Python completo para teste de contratos, fuzzing, implantação, varredura de vulnerabilidades e navegação de código._** - [Página inicial](https://getwake.io/) - [Documentação](https://ackeeblockchain.com/wake/docs/latest/) - [GitHub](https://github.com/Ackee-Blockchain/wake) -- [Extensão VS Code](https://marketplace.visualstudio.com/items?itemName=AckeeBlockchain.tools-for-solidity) +- [Extensão do VS Code](https://marketplace.visualstudio.com/items?itemName=AckeeBlockchain.tools-for-solidity) -**Veramo -** **_Framework de código aberto, modular e agnóstico que facilita para os desenvolvedores de aplicativos descentralizados a integração de identidades descentralizadas e credenciais verificáveis em suas aplicações._** +**Veramo -** **_Framework de código aberto, modular e agnóstico que facilita para desenvolvedores de aplicativos descentralizados criarem identidades descentralizadas e credenciais verificáveis em seus aplicativos._** - [Página inicial](https://veramo.io/) - [Documentação](https://veramo.io/docs/basics/introduction) @@ -140,8 +149,8 @@ Antes de mergulhar em frameworks, recomendamos que você primeiro leia a nossa i ## Leitura adicional {#further-reading} -_Conhece um recurso da comunidade que te ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ ## Tópicos relacionados {#related-topics} -- [Configure um ambiente de desenvolvimento](/developers/local-environment/) +- [Configure um ambiente de desenvolvimento local](/developers/local-environment/) diff --git a/public/content/translations/pt-br/developers/docs/gas/index.md b/public/content/translations/pt-br/developers/docs/gas/index.md index 19e848e668f..70727aab724 100644 --- a/public/content/translations/pt-br/developers/docs/gas/index.md +++ b/public/content/translations/pt-br/developers/docs/gas/index.md @@ -1,6 +1,7 @@ --- -title: Gás e taxas -description: +title: "Gás e taxas" +metaTitle: "Ethereum despesas: visão geral tecnológica" +description: "Saiba mais sobre a taxa de gás Ethereum, como eles são calculados e seu papel na segurança da rede e processamento de transações." lang: pt-br --- @@ -8,7 +9,7 @@ O gás é essencial para a rede Ethereum. É o combustível que permite que ele ## Pré-requisitos {#prerequisites} -Para entender melhor esta página, recomendamos que você leia primeiro sobre [transações](/developers/docs/transactions/) e [EVM](/developers/docs/evm/). +Para entender melhor esta página, recomendamos que você leia primeiro sobre [transações](/developers/docs/transactions/) e a [EVM](/developers/docs/evm/). ## O que é gás? {#what-is-gas} @@ -16,25 +17,26 @@ Gás refere-se à unidade que mede a quantidade de esforço computacional necess Como cada transação Ethereum requer recursos computacionais para executar, estes recursos têm de ser pagos para garantir que o Ethereum não seja vulnerável a spam e não possa ficar preso em loops computacionais infinitos. Pagamentos por computação são feitos na forma de uma taxa de gas. -A taxa de gas é **a quantia de gas usada para fazer alguma operação, multiplicada pelo custo da unidade de gas**. A taxa é paga independentemente da transação ter sucesso ou falhar. +A taxa de gás é **a quantidade de gás usada para fazer alguma operação, multiplicada pelo custo por unidade de gás**. A taxa é paga independentemente da transação ter sucesso ou falhar. -![Diagrama mostrando onde o consumo de gás é utilizado para as operações da EVM](./gas.png) _Diagrama adaptado do [Ethereum EVM ilustrado](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ +![Um diagrama mostrando onde o gás é necessário nas operações da EVM](./gas.png) +_Diagrama adaptado de [Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ Taxas de gas tem que ser pagas na moeda nativa do Ethereum, ether (ETH). Preços de gas são geralmente cotados em gwei, que é uma denominação do ETH. Cada gwei é igual a um bilionésimo de um ETH (0,000000001 ETH ou 10-9 ETH). Por exemplo, em vez de dizer que seu gás custa 0.000000001 Ether, pode-se dizer que ele custa 1 Gwei. -A palavra 'gwei' é uma contração de 'giga-wei', significando 'bilhão de wei'. Um gwei é igual a um bilhão de wei. O próprio Wei (nomeado em homenagem a [Wei Dai](https://wikipedia.org/wiki/WeiDai), criador do [B-Money](https://www.investopedia.com/terms/b/bmoney.asp)) é a menor unidade de ETH. +A palavra 'gwei' é uma contração de 'giga-wei', significando 'bilhão de wei'. Um gwei é igual a um bilhão de wei. O próprio Wei (nomeado em homenagem a [Wei Dai](https://wikipedia.org/wiki/Wei_Dai), criador do [b-money](https://www.investopedia.com/terms/b/bmoney.asp)) é a menor unidade de ETH. ## Como são calculadas as taxas de gás? {#how-are-gas-fees-calculated} Você pode definir a quantidade de gás que está disposto a pagar ao enviar uma transação. Ao oferecer uma certa quantidade de gás, você está fazendo um lance para que sua transação seja incluída no próximo bloco. Se você oferecer muito pouco, é menos provável que os validadores escolham sua transação para inclusão, o que significa que sua transação pode ser executada com atraso ou simplesmente não. Se você oferecer muito, pode desperdiçar algum ETH. Então, como você pode saber quanto deve pagar? -O total de gás que você paga é dividido em dois componentes: a `base_fee` e a `priority fee` (gorjeta). +O gás total que você paga é dividido em dois componentes: a `taxa base` e a `taxa de prioridade` (gorjeta). -A `base_fee` é definida pelo protocolo - você tem que pagar pelo menos este valor para que sua transação seja considerada válida. A `priority fee` é uma gorjeta que você adiciona à taxa base (base fee) para tornar sua transação atrativa para os validadores, para que eles a escolham para inclusão no próximo bloco. +A `taxa base` é definida pelo protocolo — você precisa pagar pelo menos esse valor para que sua transação seja considerada válida. A `taxa de prioridade` é uma gorjeta que você adiciona à `taxa base` para tornar sua transação atrativa para os validadores, para que eles a escolham para inclusão no próximo bloco. -Uma transação que paga apenas a `base_fee` é tecnicamente válida, mas é improvável que seja incluída, porque não oferece incentivo aos validadores para a escolhê-la em detrimento de qualquer outra transação. A taxa de `priority` 'correta' é determinada pelo uso da rede no momento em que você envia sua transação - se houver muita demanda, então você pode ter que definir sua taxa de `priority` maior, mas quando há menos demanda você pode pagar menos. +Uma transação que paga apenas a `taxa base` é tecnicamente válida, mas é improvável que seja incluída, pois não oferece incentivo aos validadores para escolhê-la em vez de qualquer outra transação. A taxa de `prioridade` 'correta' é determinada pelo uso da rede no momento do envio da sua transação — se houver muita demanda, talvez você precise definir sua taxa de `prioridade` mais alta, mas quando houver menos demanda, você poderá pagar menos. Por exemplo, digamos que Jordan tem que pagar a Taylor 1 ETH. Uma transferência de ETH requer 21.000 unidades de gás e a taxa básica é de 10 gwei. João inclui uma gorjeta de 2 gwei. @@ -42,44 +44,44 @@ A taxa total agora seria igual a: `unidades de gás usadas * (taxa de base + taxa de prioridade)` -onde a `base_fee` é um valor definido pelo protocolo e a `priority fee` é um valor definido pelo usuário como gorjeta ao validador. +onde a `taxa base` é um valor definido pelo protocolo e a `taxa de prioridade` é um valor definido pelo usuário como uma gorjeta para o validador. -ou seja, `21.000 * (10 + 2) = 252.000 gwei` (0.000252 ETH). +p. ex., `21.000 * (10 + 2) = 252.000 gwei` (0,000252 ETH). -Quando João enviar o dinheiro, 1,000252 ETH serão deduzidos da conta de João. Tomé receberá 1,0000 ETH. O validador recebe a gorjeta de 0,000042 ETH. A `taxa base` de 0,00021 ETH foi queimada. +Quando João enviar o dinheiro, 1,000252 ETH serão deduzidos da conta de João. Tomé receberá 1,0000 ETH. O validador recebe a gorjeta de 0,000042 ETH. A `taxa base` de 0,00021 ETH é queimada. ### Taxa base {#base-fee} -Cada bloco tem uma taxa base que funciona como um preço de reserva. Para ser elegível para inclusão em um bloco, o preço oferecido por gás deve ser pelo menos igual à taxa base. A taxa base é calculada independentemente do bloco atual e, em vez disso, é determinada pelos blocos anteriores, tornando as taxas de transação mais previsíveis para os usuários. Quando o bloco é criado, esta **taxa base é "queimada"**, removendo-a de circulação. +Cada bloco tem uma taxa base que funciona como um preço de reserva. Para ser elegível para inclusão em um bloco, o preço oferecido por gás deve ser pelo menos igual à taxa base. A taxa base é calculada independentemente do bloco atual e, em vez disso, é determinada pelos blocos anteriores, tornando as taxas de transação mais previsíveis para os usuários. Quando o bloco é criado, esta **taxa base é "queimada"**, sendo removida de circulação. -A taxa base é calculada por uma fórmula que compara o tamanho do bloco anterior (a quantidade de gás utilizada para todas as transações) com o tamanho do alvo. A taxa base aumentará em um máximo de 12,5% por bloco se o tamanho do bloco de destino for excedido. Esse crescimento exponencial torna economicamente inviável que o tamanho do bloco permaneça elevado indefinidamente. +A taxa base é calculada por uma fórmula que compara o tamanho do bloco anterior (a quantidade de gás usada para todas as transações) com o tamanho alvo (metade do limite de gás). A taxa base aumentará ou diminuirá em no máximo 12,5% por bloco se o tamanho do bloco alvo estiver acima ou abaixo do alvo, respectivamente. Esse crescimento exponencial torna economicamente inviável que o tamanho do bloco permaneça elevado indefinidamente. -| Número do bloco | Gás incluído | Aumento de taxa | Taxa base atual | -| --------------- | ------------:| ---------------:| ---------------:| -| 1 | 15M | 0% | 100 gwei | -| 2 | 30M | 0% | 100 gwei | -| 3 | 30M | 12,5% | 112,5 gwei | -| 4 | 30M | 12,5% | 126,6 gwei | -| 5 | 30M | 12,5% | 142,4 gwei | -| 6 | 30M | 12,5% | 160,2 gwei | -| 7 | 30M | 12,5% | 180,2 gwei | -| 8 | 30M | 12,5% | 202,7 gwei | - -Conforme a tabela acima, para criar uma transação no bloco número 9, uma carteira informará o usuário que a **taxa base máxima** a ser adicionada ao próximo bloco é a `taxa base atual * 112,5%` ou `202,7 gwei * 112,5% = 228,1 gwei`. +| Número do bloco | Gás incluído | Aumento da taxa | Taxa base atual | +| --------------- | -----------: | --------------: | --------------: | +| 1 | 18M | 0% | 100 gwei | +| 2 | 36M | 0% | 100 gwei | +| 3 | 36M | 12,5% | 112,5 gwei | +| 4 | 36M | 12,5% | 126,6 gwei | +| 5 | 36M | 12,5% | 142,4 gwei | +| 6 | 36M | 12,5% | 160,2 gwei | +| 7 | 36M | 12,5% | 180,2 gwei | +| 8 | 36M | 12,5% | 202,7 gwei | + +Na tabela acima, um exemplo é demonstrado usando 36 milhões como o limite de gás. Seguindo este exemplo, para criar uma transação no bloco de número 9, uma carteira informará ao usuário com certeza que a **taxa base máxima** a ser adicionada ao próximo bloco é `taxa base atual * 112,5%` ou `202,7 gwei * 112,5% = 228,1 gwei`. Também é importante notar que, é improvável que veremos picos prolongados de blocos completos, devido à velocidade com que a taxa base aumenta antes de um bloco completo. -| Número do bloco | Gás incluído | Aumento da taxa | Taxa base atual | -| --------------- | ------------:| ---------------:| ---------------:| -| 30 | 30M | 12,5% | 2705,6 gwei | -| ... | ... | 12,5% | ... | -| 50 | 30M | 12,5% | 28531,3 gwei | -| ... | ... | 12,5% | ... | -| 100 | 30M | 12,5% | 10302608,6 gwei | +| Número do bloco | Gás incluído | Aumento da taxa | Taxa base atual | +| --------------------------------------------------- | --------------------------------------------------: | --------------: | --------------------------------------------------: | +| 30 | 36M | 12,5% | 2705,6 gwei | +| ... | ... | 12,5% | ... | +| 50 | 36M | 12,5% | 28531,3 gwei | +| ... | ... | 12,5% | ... | +| 100 | 36M | 12,5% | 10302608,6 gwei | ### Taxa de prioridade (gorjetas) {#priority-fee} -A taxa de prioridade (gorjeta) incentiva os validadores a incluir uma transação no bloco. Sem gorjetas, os validadores achariam economicamente viável minerar blocos vazios, pois receberiam a mesma recompensa pelo bloco. Pequenas gorjetas dão aos validadores um incentivo mínimo para incluir uma transação. Para que as transações sejam executadas preferencialmente antes de outras transações no mesmo bloco, uma gorjeta maior pode ser adicionada para tentar ultrapassar as transações concorrentes. +A taxa de prioridade (gorjeta) incentiva os validadores a maximizar o número de transações em um bloco, limitado apenas pelo limite de gás do bloco. Sem gorjetas, um validador racional poderia incluir menos — ou até mesmo zero — transações sem qualquer penalidade direta da camada de execução ou da camada de consenso, já que as recompensas de staking são independentes de quantas transações estão em um bloco. Além disso, as gorjetas permitem que os usuários superem as ofertas de outros por prioridade dentro do mesmo bloco, sinalizando efetivamente a urgência. ### Taxa máxima {#maxfee} @@ -87,9 +89,13 @@ Para executar uma transação na rede, os usuários podem especificar um limite ### Tamanho do bloco {#block-size} -Cada bloco tem um tamanho alvo de 30 milhões de gás, mas o tamanho dos blocos aumentará ou diminuirá de acordo com a demanda da rede, até o limite do bloco de 60 milhões de gás (2x o tamanho do bloco alvo). O protocolo atinge um tamanho de bloco de equilíbrio de 30 milhões em média através do processo de _tentativa e erro_. Isso significa que se o tamanho do bloco for maior que o tamanho do bloco alvo, o protocolo aumentará a taxa base para o bloco a seguir. Da mesma forma, o protocolo diminuirá a taxa base se o tamanho do bloco for menor que o tamanho do bloco de destino. A quantidade pela qual a taxa base é ajustada é proporcional ao quão longe o tamanho do bloco atual está do alvo. [Mais sobre blocos](/developers/docs/blocks/). +Cada bloco tem um tamanho alvo de metade do limite de gás atual, mas o tamanho dos blocos aumentará ou diminuirá de acordo com a demanda da rede, até que o limite do bloco seja atingido (2x o tamanho do bloco alvo). O protocolo atinge um tamanho médio de bloco de equilíbrio no alvo através do processo de _tâtonnement_. Isso significa que se o tamanho do bloco for maior que o tamanho do bloco alvo, o protocolo aumentará a taxa base para o bloco a seguir. Da mesma forma, o protocolo diminuirá a taxa base se o tamanho do bloco for menor que o tamanho do bloco de destino. -### Calculando taxas de gás na prática {#calculating-fees-in-practice} +A quantidade pela qual a taxa base é ajustada é proporcional ao quão longe o tamanho do bloco atual está do alvo. Este é um cálculo linear de -12,5% para um bloco vazio, 0% no tamanho alvo, até +12,5% para um bloco que atinge o limite de gás. O limite de gás pode flutuar ao longo do tempo com base na sinalização do validador, bem como por meio de atualizações de rede. Você pode [ver as alterações no limite de gás ao longo do tempo aqui](https://eth.blockscout.com/stats/averageGasLimit?interval=threeMonths). + +[Mais sobre blocos](/developers/docs/blocks/) + +### Calculando as taxas de gás na prática {#calculating-fees-in-practice} Você pode explicitamente declarar o quanto está disposto a pagar para que sua transação seja executada. No entanto, a maioria dos provedores de carteira definirá automaticamente uma taxa de transação recomendada (taxa base + taxa prioritária recomendada) para reduzir a quantidade de complexidade que pesa sobre seus usuários. @@ -97,42 +103,49 @@ Você pode explicitamente declarar o quanto está disposto a pagar para que sua Em resumo, as taxas de gás ajudam a manter a rede Ethereum segura. Ao exigir uma taxa para cada cálculo executado na rede, evitamos que os maus atores enviem spam para a rede. Para evitar loops infinitos acidentais ou hostis ou outro desperdício de cálculo no código, cada transação deve definir um limite para quantas etapas de cálculo de execução de código ela pode usar. A unidade fundamental de cálculo é "gás". -Embora uma transação inclua um limite, qualquer gás não usado em uma transação é devolvido ao usuário (ou seja, `taxa máxima - (taxa base + gorjeta)` é retornada). +Embora uma transação inclua um limite, qualquer gás não utilizado em uma transação é devolvido ao usuário (p. ex., `taxa máxima - (taxa base + gorjeta)` é devolvido). -![Diagrama que mostra como o gás não utilizado é reembolsado](../transactions/gas-tx.png) _Diagrama adaptado do [Ethereum EVM ilustrado](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ +![Diagrama mostrando como o gás não utilizado é reembolsado](../transactions/gas-tx.png) +_Diagrama adaptado de [Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ ## Qual é o limite de gás? {#what-is-gas-limit} -O limite de gás se refere à quantidade máxima de gás que você está disposto a consumir em uma transação. Transações mais complicadas envolvendo [contratos inteligentes](/developers/docs/smart-contracts/) exigem mais trabalho de cálculo, portanto, exigem um limite de gás mais alto do que um simples pagamento. Uma transferência ETH padrão requer um limite de gás de 21.000 unidades de gás. +O limite de gás se refere à quantidade máxima de gás que você está disposto a consumir em uma transação. Transações mais complicadas que envolvem [contratos inteligentes](/developers/docs/smart-contracts/) exigem mais trabalho computacional, portanto, exigem um limite de gás mais alto do que um simples pagamento. Uma transferência ETH padrão requer um limite de gás de 21.000 unidades de gás. -Por exemplo, se você colocar um limite de gás de 50.000 para uma simples transferência de ETH, a EVM consumirá 21.000 e você receberá de volta os 29.000 restantes. No entanto, se você especificar muito pouco gás, por exemplo, um limite de gás de 20.000 para uma simples transferência de ETH, a EVM consumirá suas 20.000 unidades de gás tentando cumprir a transação, mas não será concluída. A EVM então reverte quaisquer alterações, mas como o validador já fez 20 mil unidades de gás de trabalho, esse gás é consumido. +Por exemplo, se você colocar um limite de gás de 50.000 para uma simples transferência de ETH, a EVM consumirá 21.000 e você receberá de volta os 29.000 restantes. No entanto, se você especificar muito pouco gás, por exemplo, menor do limite mínimo de gás de 20.000 para uma transferência do ETH, a transação falhará. Será rejeitado antes de ser em bloco. Por outro lado, se uma transação estava sem gás durante a execução (por exemplo, um contrato inteligente usa todo o gás em processo), o EVM cancelará alterações, mas todo o gás ainda será consumido. ## Por que as taxas de gás são tão altas? {#why-can-gas-fees-get-so-high} As altas taxas de gás são devidas à popularidade do Ethereum. Se houver muita demanda, os usuários devem oferecer valores mais altos de gorjeta e tentar superar as transações de outros usuários. Uma gorjeta mais alta pode aumentar a probabilidade de sua transação entrar no próximo bloco. Além disso, aplicativos de contratos inteligentes mais complexos podem estar realizando muitas operações para dar suporte a suas funções, fazendo com que consumam muito combustível. -## Iniciativas para reduzir os custos do gás {#initiatives-to-reduce-gas-costs} +## Iniciativas para reduzir os custos de gás {#initiatives-to-reduce-gas-costs} + +As [atualizações de escalabilidade](/roadmap/) do Ethereum devem, em última análise, resolver alguns dos problemas da taxa de gás, o que, por sua vez, permitirá que a plataforma processe milhares de transações por segundo e escale globalmente. -As [atualizações de escalabilidade](/roadmap/) do Ethereum deverão em última análise resolver algumas das questões de taxas de gás que, por sua vez, permitirá que a plataforma processe milhares de transações por segundo e escale globalmente. +A escalabilidade da camada 2 é uma iniciativa primária para melhorar significativamente os custos do gás, a experiência do usuário e a escalabilidade. -A escalabilidade da camada 2 é uma iniciativa primária para melhorar significativamente os custos do gás, a experiência do usuário e a escalabilidade. [Mais sobre a escalabilidade de camada 2](/developers/docs/scaling/#layer-2-scaling). +[Mais sobre escalabilidade de camada 2](/developers/docs/scaling/#layer-2-scaling) ## Monitoramento de taxas de gás {#monitoring-gas-fees} Se você deseja monitorar os preços do gás, para poder enviar seu ETH por menos, pode usar muitas ferramentas diferentes, como: -- [Etherscan Gas Tracker](https://etherscan.io/gastracker): _calculadora do preço do gas de uma transação_ -- [Blocknative ETH Gas Estimator](https://chrome.google.com/webstore/detail/blocknative-eth-gas-estim/ablbagjepecncofimgjmdpnhnfjiecfm): _uma extensão do Chrome para estimar o preço do gás e que suporta transações do tipo 0 e do tipo 2 EIP-1559._ -- [Calculadora de taxas de gás Cryptoneur](https://www.cryptoneur.xyz/gas-fees-calculator) _Calcule as taxas de gás em sua moeda local para diferentes tipos de transação na Rede principal, no Arbitrum e Polygon._ +- [Etherscan](https://etherscan.io/gastracker) _Estimador de preço do gás da transação_ +- [Blockscout](https://eth.blockscout.com/gas-tracker) _Estimador de preço do gás de transação de código aberto_ +- [ETH Gas Tracker](https://www.ethgastracker.com/) _Monitore e acompanhe os preços do gás do Ethereum e da L2 para reduzir as taxas de transação e economizar dinheiro_ +- [Blocknative ETH Gas Estimator](https://chrome.google.com/webstore/detail/blocknative-eth-gas-estim/ablbagjepecncofimgjmdpnhnfjiecfm) _Extensão do Chrome para estimativa de gás que suporta tanto transações legadas do Tipo 0 quanto transações do Tipo 2 EIP-1559._ +- [Cryptoneur Gas Fees Calculator](https://www.cryptoneur.xyz/gas-fees-calculator) _Calcule as taxas de gás em sua moeda local para diferentes tipos de transação na Rede Principal, Arbitrum e Polygon._ ## Ferramentas relacionadas {#related-tools} -- [Gas Platform da Blocknative](https://www.blocknative.com/gas): _API para estimativas do gás desenvolvida pela plataforma global de dados mempool da Blocknative_ +- [Plataforma de Gás da Blocknative](https://www.blocknative.com/gas) _API de estimativa de gás alimentada pela plataforma global de dados do mempool da Blocknative_ +- [Gas Network](https://gas.network) Oráculos de Gás na Cadeia. Suporte para mais de 35 redes. ## Leitura adicional {#further-reading} -- [Explicação sobre o gás de Ethereum](https://defiprime.com/gas) -- [Reduzindo o consumo de gás de seus Contratos Inteligentes](https://medium.com/coinmonks/8-ways-of-reducing-the-gas-consumption-of-your-smart-contracts-9a506b339c0a) -- [Estratégias de otimização de gás para desenvolvedores](https://www.alchemy.com/overviews/solidity-gas-optimization) -- [Documentos EIP-1559](https://eips.ethereum.org/EIPS/eip-1559). -- [Recursos EIP-1559 de Tim Beiko](https://hackmd.io/@timbeiko/1559-resources). +- [O Gás do Ethereum Explicado](https://defiprime.com/gas) +- [Reduzindo o consumo de gás dos seus Contratos Inteligentes](https://medium.com/coinmonks/8-ways-of-reducing-the-gas-consumption-of-your-smart-contracts-9a506b339c0a) +- [Estratégias de Otimização de Gás para Desenvolvedores](https://www.alchemy.com/overviews/solidity-gas-optimization) +- [Documentação do EIP-1559](https://eips.ethereum.org/EIPS/eip-1559). +- [Recursos sobre o EIP-1559 de Tim Beiko](https://hackmd.io/@timbeiko/1559-resources) +- [EIP-1559: Separando Mecanismos de Memes](https://web.archive.org/web/20241126205908/https://research.2077.xyz/eip-1559-separating-mechanisms-from-memes) diff --git a/public/content/translations/pt-br/developers/docs/ides/index.md b/public/content/translations/pt-br/developers/docs/ides/index.md index e2ee2caa51f..c79ad51ec72 100644 --- a/public/content/translations/pt-br/developers/docs/ides/index.md +++ b/public/content/translations/pt-br/developers/docs/ides/index.md @@ -1,43 +1,43 @@ --- title: Ambientes de Desenvolvimento Integrado (IDEs) -description: +description: "Aprenda sobre IDEs baseados na rede e desktop para desenvolvimento do Ethereum, incluindo Remix, código VS e plugins populares." lang: pt-br --- -Quando se trata de desenvolver um [ambiente de trabalho integrado (IDE)](https://pt.wikipedia.org/wiki/Ambiente_de_desenvolvimento_integrado) programar em Ethereum é similar a programar qualquer outro projeto de software. Há muitas opções para escolher, então simplesmente escolha o IDE ou editor de código que melhor se adapta a suas preferências. A melhor escolha para o seu desenvolvimento em Ethereum provavelmente vai ser o IDE que você já usa para o desenvolvimento tradicional de softwares. +Quando se trata de configurar um [ambiente de desenvolvimento integrado (IDE)](https://wikipedia.org/wiki/Integrated_development_environment), programar aplicações na Ethereum é semelhante a programar qualquer outro projeto de software. Há muitas opções para escolher, então simplesmente escolha o IDE ou editor de código que melhor se adapta a suas preferências. A melhor escolha para o seu desenvolvimento em Ethereum provavelmente vai ser o IDE que você já usa para o desenvolvimento tradicional de softwares. ## IDEs baseados na Web {#web-based-ides} -Se você quer brincar com o código antes de [configurar um ambiente de desenvolvimento local](/developers/local-environment/), esses aplicativos na web são personalizados para o desenvolvimento de contratos inteligentes em Ethereum. +Se você deseja mexer no código antes de [configurar um ambiente de desenvolvimento local](/developers/local-environment/), estes aplicativos da web são feitos sob medida para o desenvolvimento de contratos inteligentes da Ethereum. -**[Remix](https://remix.ethereum.org/)** - **_IDE baseada na Web com análise estática integrada e uma máquina virtual de blockchain de teste_** +**[Remix](https://remix.ethereum.org/)** - **_IDE baseado na Web com análise estática integrada e uma máquina virtual de blockchain de teste_** - [Documentação](https://remix-ide.readthedocs.io/en/latest/#) - [Gitter](https://gitter.im/ethereum/remix) -**[ChainIDE](https://chainide.com/)** - **_Uma IDE multicadeia baseada na nuvem_** +**[ChainIDE](https://chainide.com/)** - **_Uma IDE multichain baseada em nuvem_** - [Documentação](https://chainide.gitbook.io/chainide-english-1/) - [Fórum de ajuda](https://forum.chainide.com/) -**[Replit (Solidity Starter - Beta)](https://replit.com/@replit/Solidity-starter-beta)** - **_Um ambiente de desenvolvimento personalizável para Ethereum com hot reloading, verificação de erros e suporte a rede de testes de primeira classe_** +**[Replit (Solidity Starter - Beta)](https://replit.com/@replit/Solidity-starter-beta)** - **_Um ambiente de desenvolvimento personalizável para Ethereum com hot reloading, verificação de erros e suporte de primeira classe à rede de teste_** - [Documentação](https://docs.replit.com/) **[Tenderly Sandbox](https://sandbox.tenderly.co/)** - **_Um ambiente de prototipagem rápida onde você pode escrever, executar e depurar contratos inteligentes no navegador usando Solidity e JavaScript_** -**[EthFiddle](https://ethfiddle.com/)** - **_IDE baseada na Web que permite escrever, compilar e depurar seu contrato inteligente_** +**[EthFiddle](https://ethfiddle.com/)** - **_IDE baseado na Web que permite escrever, compilar e depurar seu contrato inteligente_** - [Gitter](https://gitter.im/loomnetwork/ethfiddle) -## Aplicativos IDEs {#desktop-ides} +## IDEs de desktop {#desktop-ides} -A maioria dos IDEs estabelecidos possuem plugins integrados para melhorar a experiência de desenvolvimento em Ethereum. No mínimo, eles fornecem destaque de sintaxe para [linguagens de contrato inteligentes](/developers/docs/smart-contracts/languages/). +A maioria dos IDEs estabelecidos possuem plugins integrados para melhorar a experiência de desenvolvimento em Ethereum. No mínimo, eles fornecem realce de sintaxe para [linguagens de contratos inteligentes](/developers/docs/smart-contracts/languages/). -**Visual Studio Code -** **_IDE profissional multiplataforma com suporte oficial da Ethereum._** +**Visual Studio Code -** **_IDE profissional multiplataforma com suporte oficial da Ethereum_** - [Visual Studio Code](https://code.visualstudio.com/) -- [Amostras de código](https://github.com/Azure-Samples/blockchain/blob/master/blockchain-workbench/application-and-smart-contract-samples/readme.md) +- [Exemplos de código](https://github.com/Azure-Samples/blockchain/blob/master/blockchain-workbench/application-and-smart-contract-samples/readme.md) - [GitHub](https://github.com/microsoft/vscode) **IDEs de JetBrains (IntelliJ IDEA etc.) -** **_Ferramentas essenciais para desenvolvedores de software e equipes_** @@ -46,19 +46,19 @@ A maioria dos IDEs estabelecidos possuem plugins integrados para melhorar a expe - [GitHub](https://github.com/JetBrains) - [IntelliJ Solidity](https://github.com/intellij-solidity/intellij-solidity/) -**Remix Desktop -** **_Experimente o Remix IDE na sua máquina local_** +**Remix Desktop -** **_Experimente o Remix IDE em sua máquina local_** - [Baixar](https://github.com/ethereum/remix-desktop/releases) - [GitHub](https://github.com/ethereum/remix-desktop) ## Plugins e extensões {#plugins-extensions} -- [Solidity](https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity) - Linguagem Ethereum Solidity para Visual Studio Code -- [Solidity + Hardhat para VS Code](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity) - Suporte Solidity e Hardhat oferecido pela equipe Hardhat -- [Prettier Solidity](https://github.com/prettier-solidity/prettier-plugin-solidity) - Formatador de código que faz uso do Prettier +- [solidity](https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity) - Linguagem Solidity do Ethereum para Visual Studio Code +- [Solidity + Hardhat para VS Code](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity) - Suporte para Solidity e Hardhat pela equipe do Hardhat +- [Prettier Solidity](https://github.com/prettier-solidity/prettier-plugin-solidity) - Formatador de código usando o prettier ## Leitura adicional {#further-reading} -- [Ethereum IDEs](https://www.alchemy.com/list-of/web3-ides-on-ethereum) _- Lista de IDEs para o Ethereum da Alchemy_ +- [IDEs da Ethereum](https://www.alchemy.com/list-of/web3-ides-on-ethereum) _- Lista da Alchemy de IDEs da Ethereum_ -_Conhece algum recurso da comunidade que o ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ diff --git a/public/content/translations/pt-br/developers/docs/index.md b/public/content/translations/pt-br/developers/docs/index.md index f2a2066354c..438e104595c 100644 --- a/public/content/translations/pt-br/developers/docs/index.md +++ b/public/content/translations/pt-br/developers/docs/index.md @@ -1,12 +1,12 @@ --- -title: Documentação sobre o desenvolvimento do Ethereum -description: Introduzindo a documentação sobre o desenvolvimento da rede Ethereum. +title: "Documentação sobre o desenvolvimento do Ethereum" +description: "Introduzindo a documentação sobre o desenvolvimento da rede Ethereum." lang: pt-br --- O objetivo dessa documentação é ajudar você a criar utilizando o Ethereum. Ela cobre o Ethereum como um conceito, explica a tecnologia de pilha do Ethereum e documenta tópicos avançados para aplicativos e casos de uso mais complexos. -Este é um esforço da comunidade de código aberto, então, não hesite em sugerir novos tópicos, adicionar novo conteúdo e fornecer exemplos sempre que você julgar ser útil. Toda a documentação é editável através do GitHub. Se não souber como, [siga estas instruções](https://github.com/ethereum/ethereum-org-website/blob/dev/docs/editing-markdown.md). +Este é um esforço da comunidade de código aberto, então, não hesite em sugerir novos tópicos, adicionar novo conteúdo e fornecer exemplos sempre que você julgar ser útil. Toda a documentação pode ser editada via GitHub – se você não tiver certeza de como fazer, [siga estas instruções](https://github.com/ethereum/ethereum-org-website/blob/dev/docs/editing-markdown.md). ## Módulos de desenvolvimento {#development-modules} diff --git a/public/content/translations/pt-br/developers/docs/intro-to-ether/index.md b/public/content/translations/pt-br/developers/docs/intro-to-ether/index.md index 3b5239ff2c0..55451923c8a 100644 --- a/public/content/translations/pt-br/developers/docs/intro-to-ether/index.md +++ b/public/content/translations/pt-br/developers/docs/intro-to-ether/index.md @@ -1,6 +1,6 @@ --- -title: Introdução ao Ether -description: Introdução de um desenvolvedor à criptomoeda ETHER. +title: "Introdução técnica ao ether" +description: "Introdução de um desenvolvedor à criptomoeda ETHER." lang: pt-br --- @@ -18,35 +18,35 @@ A primeira criptomoeda foi o Bitcoin, criado por Satoshi Nakamoto. Desde o lanç ## O que é ether? {#what-is-ether} -**Ether (ETH)** é a criptomoeda usada para muitas coisas na rede Ethereum. Fundamentalmente, essa é a única forma de pagamento aceitável para taxas de transação e, após [A Fusão](/roadmap/merge) (The Merge), é necessário ether para validar e propor blocos na Rede principal (Mainnet). O ether também é usado como uma forma primária de garantia nos mercados de crédito de [DeFi](/defi) como unidade de conta nos mercados NFT, como o pagamento ganho pela realização de serviços ou a venda de produtos do mundo real, entre outros. +**Ether (ETH)** é a criptomoeda usada para muitas coisas na rede Ethereum. Fundamentalmente, é a única forma de pagamento aceitável para taxas de transação e, após [A Fusão](/roadmap/merge), o ether é necessário para validar e propor blocos na Mainnet. O Ether também é usado como forma principal de garantia nos mercados de empréstimo de [DeFi](/defi), como uma unidade de conta nos mercados de NFT, como pagamento recebido por prestação de serviços ou venda de bens do mundo real, e muito mais. -Ethereum permite que os desenvolvedores criem [**aplicativos descentralizados (dapps)**](/developers/docs/dapps), que compartilham um conjunto de capacidades de computação. Este pool compartilhado é finito, portanto Ethereum precisa de um mecanismo para determinar quem vai usá-lo. Caso contrário, um dapp poderia acidental ou maliciosamente consumir todos os recursos de rede, o que bloquearia o acesso de outros. +O Ethereum permite que os desenvolvedores criem [**aplicativos descentralizados (dapps)**](/developers/docs/dapps), que compartilham um pool de poder computacional. Este pool compartilhado é finito, portanto Ethereum precisa de um mecanismo para determinar quem vai usá-lo. Caso contrário, um dapp poderia acidental ou maliciosamente consumir todos os recursos de rede, o que bloquearia o acesso de outros. -A criptomoeda oferece suporte a um mecanismo de preços para o poder de computação do Ethereum. Quando os usuários querem fazer uma transação, devem pagar uma certa quantia em Ether para que sua transação seja reconhecida na blockchain. Estes custos de uso são conhecidos como [taxas de gás](/developers/docs/gas/), e a taxa de gás depende da quantidade de poder de computação necessária para executar a transação e a demanda em toda a rede por poder de computação no momento. +A criptomoeda oferece suporte a um mecanismo de preços para o poder de computação do Ethereum. Quando os usuários querem fazer uma transação, devem pagar uma certa quantia em Ether para que sua transação seja reconhecida na blockchain. Esses custos de uso são conhecidos como [taxas de gás](/developers/docs/gas/), e a taxa de gás depende da quantidade de poder computacional necessário para executar a transação e da demanda de toda a rede por poder computacional no momento. Portanto, mesmo que um aplicativo malicioso tenha enviado um ciclo infinito, a transação acabaria sem ether e terminaria, permitindo que a rede voltasse ao normal. -É [comum confundir](https://abcnews.go.com/Business/bitcoin-slumps-week-low-amid-renewed-worries-chinese/story?id=78399845) Ethereum e ether — quando as pessoas se referem ao "preço do Ethereum", estão descrevendo o preço do ether. +É [comum confundir](https://abcnews.go.com/Business/bitcoin-slumps-week-low-amid-renewed-worries-chinese/story?id=78399845) Ethereum e ether — quando as pessoas se referem ao "preço do Ethereum", elas estão descrevendo o preço do ether. -## Como cunhar ether {#minting-ether} +## Mintagem de ether {#minting-ether} A cunhagem é o processo no qual o novo ether é criado no livro-razão do Ethereum. O protocolo Ethereum subjacente cria o novo ether. Não é possível que um usuário crie ether. O Ether é cunhado como recompensa para cada bloco proposto e em cada ponto de verificação da época para outras atividades de validação relacionadas à obtenção de consenso. O valor total emitido depende do número de validadores e do quanto de ether eles têm colocado. Essa emissão total é dividida igualmente entre os validadores no caso ideal de que todos os validadores são honestos e estão online, mas, na realidade, ele varia com base no desempenho do validador. Cerca de 1/8 da emissão total vai para o proponente do bloco; o restante é distribuído entre os outros validadores. Os proponentes do bloco também recebem gorjetas das taxas de transação e receitas relacionadas ao MEV, mas estas vêm de ether reciclado, não de novas emissões. -## Como "queimar" ether {#burning-ether} +## Queima de ether {#burning-ether} Além de criar ether por meio de recompensas de bloco, o ether pode ser destruído por um processo chamado "burning". Quando o ether é queimado, ele é removido de circulação permanentemente. -A queima de ether ocorre em todas as transações no Ethereum. Quando os usuários pagam por suas transações, uma taxa base de gás, definida pela rede de acordo com a demanda transacional, é destruída. Isso, juntamente com tamanhos de blocos variáveis e uma taxa máxima de gás, simplifica a estimativa da taxa de transação no Ethereum. Quando a demanda da rede é alta, os [blocos](https://etherscan.io/block/12965263) podem queimar mais ether do que gerar, compensando efetivamente a emissão de ether. +A queima de ether ocorre em todas as transações no Ethereum. Quando os usuários pagam por suas transações, uma taxa base de gás, definida pela rede de acordo com a demanda transacional, é destruída. Isso, juntamente com tamanhos de blocos variáveis e uma taxa máxima de gás, simplifica a estimativa da taxa de transação no Ethereum. Quando a demanda da rede é alta, os [blocos](https://eth.blockscout.com/block/22580057) podem queimar mais ether do que cunham, compensando efetivamente a emissão de ether. -Queimar a taxa base dificulta a capacidade de os produtores de blocos de manipular transações. Por exemplo, se os produtores de blocos recebessem a taxa base, eles poderiam incluir suas próprias transações gratuitamente e aumentar a taxa base para todos os demais. Como alternativa, eles poderiam reembolsar a taxa base para alguns usuários fora da cadeia, gerando um mercado de taxas de transação mais opaco e complexo. +A queima da taxa base dificulta a capacidade de um produtor de bloco de manipular transações. Por exemplo, se os produtores de blocos recebessem a taxa base, eles poderiam incluir suas próprias transações gratuitamente e aumentar a taxa base para todos os demais. Como alternativa, eles poderiam reembolsar a taxa básica para alguns usuários off-chain, levando a um mercado de taxas de transação mais opaco e complexo. ## Denominações do ether {#denominations} Uma vez que muitas transações no Ethereum são pequenas, o ether tem várias denominações que podem ser referenciadas por unidades menores de conta. Dessas denominações, Wei e gwei são particularmente importantes. -Wei é a menor quantidade possível de ether, e, como resultado, muitas implementações técnicas, como o [Ethereum Yellowpaper](https://ethereum.github.io/yellowpaper/paper.pdf), irão basear todos os cálculos em Wei. +Wei é a menor quantidade possível de ether e, como resultado, muitas implementações técnicas, como o [Ethereum Yellowpaper](https://ethereum.github.io/yellowpaper/paper.pdf), basearão todos os cálculos em Wei. Gwei, abreviado de giga-wei, é frequentemente usado para descrever os custos de gás no Ethereum. @@ -55,24 +55,24 @@ Gwei, abreviado de giga-wei, é frequentemente usado para descrever os custos de | Wei | 10-18 | Implementações técnicas | | Gwei | 10-9 | Taxas de gás legíveis por humanos | -## Como transferir ether {#transferring-ether} +## Transferência de ether {#transferring-ether} -Cada transação no Ethereum contém um campo `valor` que especifica a quantidade de ether a ser transferido, denominado em wei, para enviar do endereço do remetente para o endereço do destinatário. +Cada transação no Ethereum contém um campo `value`, que especifica a quantidade de ether a ser transferida, denominada em wei, para ser enviada do endereço do remetente para o endereço do destinatário. -Quando o endereço do destinatário é um [contrato inteligente](/developers/docs/smart-contracts/), o ether transferido pode ser usado para pagar gás quando o contrato inteligente executa seu código. +Quando o endereço do destinatário é um [contrato inteligente](/developers/docs/smart-contracts/), esse ether transferido pode ser usado para pagar pelo gás quando o contrato inteligente executa seu código. [Mais sobre transações](/developers/docs/transactions/) -## Como consultar saldos de ether {#querying-ether} +## Consulta de ether {#querying-ether} -Os usuários podem consultar o saldo de ether de qualquer [conta](/developers/docs/accounts/) inspecionando o campo `saldo` da conta que mostra participações de ether denominadas em wei. +Os usuários podem consultar o saldo de ether de qualquer [conta](/developers/docs/accounts/) inspecionando o campo `balance` da conta, que mostra as posses de ether denominadas em wei. -[Etherscan](https://etherscan.io) é uma ferramenta popular para consultar saldos de endereços através de um aplicativo baseado na Web. Por exemplo, [esta página Etherscan](https://etherscan.io/address/0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae) mostra o saldo da Fundação Ethereum. Os saldos das contas também podem ser consultados usando carteiras ou diretamente fazendo solicitações aos nós. +[Etherscan](https://etherscan.io) e [Blockscout](https://eth.blockscout.com) são ferramentas populares para inspecionar saldos de endereços por meio de aplicativos baseados na web. Por exemplo, [esta página do Blockscout](https://eth.blockscout.com/address/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe) mostra o saldo da Ethereum Foundation. Os saldos das contas também podem ser consultados usando carteiras ou diretamente fazendo solicitações aos nós. ## Leitura adicional {#further-reading} -- [Definindo Ether e Ethereum](https://www.cmegroup.com/education/courses/introduction-to-ether/defining-ether-and-ethereum.html): _CME Group_ -- [Ethereum Whitepaper](/whitepaper/): a proposta original para o Ethereum. Este documento inclui uma descrição do ether e os motivos subjacentes à sua criação. -- [Calculadora Gwei](https://www.alchemy.com/gwei-calculator): use esta calculadora gwei para converter facilmente wei, gwei e ether. Basta conectar qualquer quantidade de wei, gwei ou ETH e calcular automaticamente a conversão. +- [Definindo ether e Ethereum](https://www.cmegroup.com/education/courses/introduction-to-ether/defining-ether-and-ethereum.html) – _CME Group_ +- [Whitepaper do Ethereum](/whitepaper/): A proposta original para o Ethereum. Este documento inclui uma descrição do ether e os motivos subjacentes à sua criação. +- [Calculadora de Gwei](https://www.alchemy.com/gwei-calculator): Use esta calculadora de gwei para converter facilmente wei, gwei e ether. Basta conectar qualquer quantidade de wei, gwei ou ETH e calcular automaticamente a conversão. -_Conhece algum recurso da comunidade que o ajudou? Edite esta página e adicione-o!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ diff --git a/public/content/translations/pt-br/developers/docs/intro-to-ethereum/index.md b/public/content/translations/pt-br/developers/docs/intro-to-ethereum/index.md index e614c273198..ebd0f797c09 100644 --- a/public/content/translations/pt-br/developers/docs/intro-to-ethereum/index.md +++ b/public/content/translations/pt-br/developers/docs/intro-to-ethereum/index.md @@ -1,10 +1,10 @@ --- -title: Introdução à Ethereum -description: Uma introdução do desenvolvedor de dapps aos conceitos principais do Ethereum. +title: "Introdução técnica ao Ethereum" +description: "Uma introdução do desenvolvedor de dapps aos conceitos principais do Ethereum." lang: pt-br --- -## O que é uma blockchain? {#what-is-a-blockchain} +## O que é uma cadeia de blocos? {#what-is-a-blockchain} Uma blockchain é melhor descrita como um banco de dados público atualizado e compartilhado entre muitos computadores em uma rede. @@ -14,15 +14,15 @@ Uma blockchain é melhor descrita como um banco de dados público atualizado e c Todos os computadores da rede têm de chegar a um acordo sobre cada novo bloco e sobre a cadeia como um todo. Estes computadores são conhecidos como "nós". Os nós garantem que todos interagindo com a blockchain tenham os mesmos dados. Para cumprir este acordo distribuído, as blockchains precisam de um mecanismo de consenso. -O Ethereum utiliza um mecanismo de consenso baseado em [prova de participação](/developers/docs/consensus-mechanisms/pos/). Qualquer um que queira adicionar novos blocos à cadeia deve colocar ETH – a moeda nativa no Ethereum – como garantia e executar um software validador. Esses “validadores” podem então ser selecionados aleatoriamente para propor blocos que outros validadores verificam e adicionam à blockchain. Há um sistema de recompensas e penalidades que fortemente incentiva os participantes a serem honestos e estarem disponíveis online o máximo possível. +O Ethereum usa um [mecanismo de consenso baseado em prova de participação](/developers/docs/consensus-mechanisms/pos/). Qualquer um que queira adicionar novos blocos à cadeia deve colocar ETH – a moeda nativa no Ethereum – como garantia e executar um software validador. Esses “validadores” podem então ser selecionados aleatoriamente para propor blocos que outros validadores verificam e adicionam à blockchain. Há um sistema de recompensas e penalidades que fortemente incentiva os participantes a serem honestos e estarem disponíveis online o máximo possível. -Se você quiser ver como a cadeia de blocos faz hash dos dados e, subsequentemente, ao histórico de referência aos blocos, confira [esta demonstração](https://andersbrownworth.com/blockchain/blockchain) de Anders Brownworth e assista ao vídeo abaixo. +Se você quiser ver como os dados da cadeia de blocos recebem hash e são subsequentemente anexados ao histórico de referências de bloco, não deixe de conferir [esta demonstração](https://andersbrownworth.com/blockchain/blockchain) de Anders Brownworth e assistir ao vídeo que a acompanha abaixo. Assista a Anders explicando hashes em cadeias de blocos: -## O que é o Ethereum? {#what-is-ethereum} +## O que é a Ethereum? {#what-is-ethereum} O Ethereum é uma cadeia de blocos com um computador embutido nela. Ele é a base para criar aplicativos e organizações de maneira descentralizada, sem permissão e resistente à censura. @@ -34,19 +34,19 @@ Os mecanismos criptográficos garantem que, uma vez que as transações são ver ## O que é ether? {#what-is-ether} -**Ether (ETH)** é a criptomoeda nativa do Ethereum. O objetivo do ETH é possibilitar um mercado para cálculo. Tal mercado fornece um incentivo econômico para os participantes verificarem ou executarem solicitações de transação e fornecerem recursos computacionais para a rede. +**O Ether (ETH)** é a criptomoeda nativa do Ethereum. O objetivo do ETH é possibilitar um mercado para cálculo. Tal mercado fornece um incentivo econômico para os participantes verificarem ou executarem solicitações de transação e fornecerem recursos computacionais para a rede. Qualquer participante que transmita uma solicitação de transação também deve oferecer alguma quantidade de ETH à rede como recompensa. A rede queimará parte da recompensa e concederá o restante a quem eventualmente fizer o trabalho de verificar a transação, executá-la, confirmá-la na blockchain e transmiti-la para a rede. O valor de ETH pago corresponde aos recursos necessários para fazer o cálculo. Essas recompensas também impedem que participantes mal-intencionados entupam intencionalmente a rede, ao solicitar a execução de computação infinita ou outros scripts com uso intensivo de recursos, pois esses participantes devem pagar pelos recursos de cálculo. -O ETH também é usado para fornecer segurança criptoeconômica à rede de três maneiras principais: 1) é usado como meio de recompensar validadores que propõem bloqueios ou denunciam comportamento desonesto de outros validadores; 2) é envolvido pelos validadores, atuando como garantia contra comportamento desonesto – se os validadores tentarem se comportar mal, seu ETH pode ser destruído; 3) é usado para ponderar o peso dos "votos" para novos blocos propostos, alimentando a parte de escolha da bifurcação do mecanismo de consenso. +O ETH também é usado para fornecer segurança criptoeconômica à rede de três maneiras principais: 1) é usado como um meio de recompensar os validadores que propõem blocos ou denunciam o comportamento desonesto de outros validadores; 2) é colocado em stake pelos validadores, atuando como garantia contra comportamento desonesto — se os validadores tentarem se comportar mal, seu ETH pode ser destruído; 3) é usado para ponderar os 'votos' para blocos recém-propostos, alimentando a parte de escolha da bifurcação do mecanismo de consenso. ## O que são contratos inteligentes? {#what-are-smart-contracts} -Na prática, os participantes não escrevem um novo código toda vez que querem solicitar um cálculo da EVM. Em vez disso, os desenvolvedores de aplicativos carregam os programas (trechos de código reutilizáveis) para serem armazenados na EVM, para que os usuários solicitem a execução desses trechos de código com parâmetros variáveis. Precisamente, chamamos de contratos inteligentes a todos esses programas que são enviados e executados na rede. +Na prática, os participantes não escrevem um novo código toda vez que querem solicitar um cálculo da EVM. Em vez disso, os desenvolvedores de aplicativos carregam os programas (trechos de código reutilizáveis) para serem armazenados na EVM, para que os usuários solicitem a execução desses trechos de código com parâmetros variáveis. Chamamos os programas carregados e executados pela rede de "contratos inteligentes". -Em um nível muito básico, você pode pensar em um contrato inteligente como uma espécie de máquina de venda automática: um script que, quando chamado com determinados parâmetros, executa algumas ações ou cálculos se certas condições forem satisfeitas. Por exemplo, um simples contrato inteligente do fornecedor poderia criar e atribuir a propriedade de um ativo digital se o chamador enviar ETH para um destinatário específico. +Em termos gerais, você pode pensar em um contrato inteligente como uma espécie de máquina de venda automática: um script que, quando chamado com determinados parâmetros, executa algumas ações ou cálculos se certas condições forem satisfeitas. Por exemplo, um simples contrato inteligente do fornecedor poderia criar e atribuir a propriedade de um ativo digital se o chamador enviar ETH para um destinatário específico. Qualquer desenvolvedor pode criar um contrato inteligente e torná-lo público na rede, usando a cadeia de blocos como sua camada de dados, por uma taxa paga à rede. Qualquer usuário pode chamar um contrato inteligente para executar seu código, sendo necessário pagar uma nova taxa à rede. @@ -54,13 +54,13 @@ Assim, com contratos inteligentes, os desenvolvedores podem criar e implantar ar ## Terminologia {#terminology} -### Blockchain {#blockchain} +### Cadeia de blocos {#blockchain} A sequência de todos os blocos que foram registrados na rede Ethereum no histórico da rede. Assim chamado porque cada bloco contém uma referência ao bloco anterior, o que nos ajuda a manter uma ordenação sobre todos os blocos (e, portanto, sobre o histórico preciso). ### ETH {#eth} -**Ether (ETH)** é a criptomoeda nativa do Ethereum. Os usuários pagam ETH a outros usuários para que suas solicitações de execução de código sejam atendidas. +**O Ether (ETH)** é a criptomoeda nativa do Ethereum. Os usuários pagam ETH a outros usuários para que suas solicitações de execução de código sejam atendidas. [Mais sobre ETH](/developers/docs/intro-to-ether/) @@ -98,19 +98,27 @@ O volume de transações é muito alto, portanto, as transações são "autoriza [Mais sobre blocos](/developers/docs/blocks/) -### Smart Contracts {#smart-contracts} +### Contratos inteligentes {#smart-contracts} -Um trecho de código reutilizável (um programa) que um desenvolvedor publica no estado da EVM. Qualquer um pode solicitar que o código de contrato inteligente seja executado fazendo uma solicitação de transação. Como desenvolvedores podem escrever aplicativos executáveis arbitrários na EVM (jogos, mercados, instrumentos financeiros, etc.) ao publicar contratos inteligentes, esses geralmente também são chamados de [dapps, ou apps descentralizados](/developers/docs/dapps/). +Um trecho de código reutilizável (um programa) que um desenvolvedor publica no estado da EVM. Qualquer um pode solicitar que o código de contrato inteligente seja executado fazendo uma solicitação de transação. Como os desenvolvedores podem escrever aplicativos executáveis arbitrários na EVM (jogos, marketplaces, instrumentos financeiros, etc.) ao publicar contratos inteligentes, estes também são frequentemente chamados de [dapps, ou Aplicativos Descentralizados](/developers/docs/dapps/). [Mais sobre contratos inteligentes](/developers/docs/smart-contracts/) ## Leitura adicional {#further-reading} - [Whitepaper do Ethereum](/whitepaper/) -- [Afinal, como funciona o Ethereum?](https://medium.com/@preethikasireddy/how-does-ethereum-work-anyway-22d1df506369) - _Preethi Kasireddy_ (**NB** este recurso ainda é valioso, mas esteja ciente de que é anterior à [Fusão](/roadmap/merge) (The Merge) e, portanto, ainda se refere ao mecanismo de prova de trabalho do Ethereum, que agora é protegido pelo uso da [prova de participação](/developers/docs/consensus-mechanisms/pos)) +- [Afinal, como o Ethereum funciona?](https://medium.com/@preethikasireddy/how-does-ethereum-work-anyway-22d1df506369) - _Preethi Kasireddy_ (**Observação**: este recurso ainda é valioso, mas esteja ciente de que é anterior a [The Merge](/roadmap/merge) e, portanto, ainda se refere ao mecanismo de prova de trabalho do Ethereum; na verdade, o Ethereum agora é protegido usando [prova de participação](/developers/docs/consensus-mechanisms/pos)) -_Conhece um recurso da comunidade que ajudou você? Edite essa página e adicione-o!_ +### Você é o tipo de pessoa que aprende mais com recursos visuais? {#visual-learner} + +Essa série de vídeo oferece uma exploração completa de tópicos fundamentais: + + + +[Playlist de Fundamentos do Ethereum](https://youtube.com/playlist?list=PLqgutSGloqiJyyoL0zvLVFPS-GMD2wKa5&si=kZTf5I7PKGTXDsOZ) + +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ ## Tutoriais relacionados {#related-tutorials} -- [Um guia do desenvolvedor para Ethereum, parte 1](/developers/tutorials/a-developers-guide-to-ethereum-part-one/) _– uma exploração muito simples para iniciantes do Ethereum usando Python e web3.py_ +- [Guia do desenvolvedor para o Ethereum, parte 1](/developers/tutorials/a-developers-guide-to-ethereum-part-one/) _– Uma exploração do Ethereum muito amigável para iniciantes, usando Python e web3.py_ diff --git a/public/content/translations/pt-br/developers/docs/mev/index.md b/public/content/translations/pt-br/developers/docs/mev/index.md index 2ea3af8b45f..2601987a1ef 100644 --- a/public/content/translations/pt-br/developers/docs/mev/index.md +++ b/public/content/translations/pt-br/developers/docs/mev/index.md @@ -1,32 +1,32 @@ --- -title: Valor máximo extraível (MEV) -description: Uma introdução ao valor máximo extraível (MEV) +title: "Valor máximo extraível (MEV)" +description: "Uma introdução ao valor máximo extraível (MEV)" lang: pt-br --- Valor Máximo Extraível (MEV, na sigla em inglês) expressa o valor máximo que pode ser extraído da produção de blocos que excede a recompensa padrão do bloco e sua taxa de gás através da inclusão, exclusão e alteração da ordem de transações em um determinado bloco. -## Valor máximo extraível {#miner-extractable-value} +## Valor máximo extraível {#maximal-extractable-value} -O valor máximo extraível foi aplicado pela primeira vez no contexto de [prova de trabalho](/developers/docs/consensus-mechanisms/pow/) e inicialmente referido como "valor extraível do minerador". Isto porque na prova de trabalho, os mineradores controlam a inclusão, exclusão e ordenação das transações. No entanto, desde a transição para a prova de participação por meio do [The Merge (A Fusão)](/roadmap/merge), os validadores têm sido responsáveis por essas funções, e a mineração não faz mais parte do protocolo Ethereum. Como os métodos de extração de valor ainda existem, o termo "valor máximo extraível" agora é usado. +O valor máximo extraível foi aplicado pela primeira vez no contexto de [prova de trabalho](/developers/docs/consensus-mechanisms/pow/) e, inicialmente, referido como "valor extraível do minerador". Isto porque na prova de trabalho, os mineradores controlam a inclusão, exclusão e ordenação das transações. No entanto, desde a transição para prova de participação através do [The Merge](/roadmap/merge), os validadores têm sido responsáveis por essas funções, e a mineração não faz mais parte do protocolo Ethereum. Como os métodos de extração de valor ainda existem, o termo "valor máximo extraível" agora é usado. -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -Certifique-se de estar familiarizado com [transações](/developers/docs/transactions/), [blocos](/developers/docs/blocks/), [prova de participação](/developers/docs/consensus-mechanisms/pos) e [gás](/developers/docs/gas/). Conhecer outros detalhes como [dapps](/apps/) ou [DeFi](/defi/) também seria útil. +Certifique-se de que está familiarizado com [transações](/developers/docs/transactions/), [blocos](/developers/docs/blocks/), [prova de participação](/developers/docs/consensus-mechanisms/pos) e [gás](/developers/docs/gas/). A familiaridade com [dapps](/apps/) e [DeFi](/defi/) também é útil. -## Extração via MEV {#mev-extraction} +## Extração de MEV {#mev-extraction} Em teoria, o MEV é revertido inteiramente para os validadores porque eles são a única parte que pode garantir a execução de uma oportunidade lucrativa de MEV. Na prática, porém, uma grande parte do MEV é extraída por participantes independentes da rede chamados "buscadores". Os buscadores executam algoritmos complexos nos dados da blockchain para detectar oportunidades de MEV lucrativas e usam bots para enviar automaticamente essas transações rentáveis para a rede. Os validadores recebem uma parte do valor total do MEV de qualquer maneira, porque os pesquisadores estão dispostos a pagar altas taxas de gás (que vão para o validador) em troca de maior probabilidade de inclusão de suas transações lucrativas em um bloco. Assumindo que os buscadores são economicamente racionais, a taxa de gás que um buscador está disposto a pagar será uma quantia de até 100% do MEV do buscador (porque se a taxa de gás fosse maior, o buscador perderia dinheiro). -Com isso, para algumas oportunidades de MEV altamente competitivas, como [arbitragem DEX](#mev-examples-dex-arbitrage), os buscadores podem ter que pagar 90% ou até mais de sua receita total de MEV, em taxas de gás para o validador, porque muitas pessoas querem executar a mesma operação de arbitragem lucrativa. Isto porque a única maneira de garantir que a sua transação de arbitragem seja executada é submetendo a transação com o preço de gás mais elevado. +Com isso, para algumas oportunidades de MEV altamente competitivas, como a [arbitragem de DEX](#mev-examples-dex-arbitrage), os pesquisadores podem ter que pagar 90% ou até mais de sua receita total de MEV em taxas de gás para o validador, porque muitas pessoas querem executar a mesma operação de arbitragem lucrativa. Isto porque a única maneira de garantir que a sua transação de arbitragem seja executada é submetendo a transação com o preço de gás mais elevado. -### Redução do consumo de gás dos contratos (gas golfing) {#mev-extraction-gas-golfing} +### Gas golfing {#mev-extraction-gas-golfing} Esta dinâmica fez do "gas-golfing" — o fato de programar as transações para que elas usem a menor quantidade de gás possível — una vantagem competitiva, porque ela permite que os buscadores fixem um preço de gás superior sem deixar de manter as taxas de gás constantes (já que as taxas de gás = preço do gás \* gás usado). -Algumas técnicas de "gas-golfing" conhecidas incluem: o uso de endereços que começam com uma longa série de zeros (por exemplo, [0x0000000000C521824EaFf97Eac7B73B084ef9306](https://etherscan.io/address/0x0000000000c521824eaff97eac7b73b084ef9306)), já que consomem menos espaço (e, portanto, gás); e deixar pequenos saldos de token de [ERC-20](/developers/docs/standards/tokens/erc-20/) em contratos, já que é mais caro inicializar um slot de armazenamento (o que acontece se o saldo for 0) que atualizá-lo. Encontrar mais técnicas para reduzir o uso de gás é uma área ativa de pesquisa entre pesquisadores. +Algumas técnicas de gas golf conhecidas incluem: usar endereços que começam com uma longa sequência de zeros (ex.: [0x0000000000C521824EaFf97Eac7B73B084ef9306](https://eth.blockscout.com/address/0x0000000000C521824EaFf97Eac7B73B084ef9306)), pois ocupam menos espaço (e, portanto, gás) para armazenar; e deixar pequenos saldos de token [ERC-20](/developers/docs/standards/tokens/erc-20/) em contratos, pois custa mais gás para inicializar um slot de armazenamento (o que ocorre se o saldo for 0) do que para atualizar um slot de armazenamento. Encontrar mais técnicas para reduzir o uso de gás é uma área ativa de pesquisa entre pesquisadores. ### Frontrunners generalizados {#mev-extraction-generalized-frontrunners} @@ -40,23 +40,23 @@ Flashbots é um projeto independente que estende clientes de execução com um s O MEV surge na blockchain de diferentes maneiras. -### Arbitragem DEX {#mev-examples-dex-arbitrage} +### Arbitragem de DEX {#mev-examples-dex-arbitrage} -A arbitragem em [exchanges descentralizadas](/glossary/#dex) (DEX) é a oportunidade mais simples e mais conhecida de MEV. Por conseguinte, é também a mais competitiva. +A arbitragem em [corretora descentralizada](/glossary/#dex) (DEX) é a oportunidade de MEV mais simples e mais conhecida. Por conseguinte, é também a mais competitiva. Isso funciona assim: se dois DEXes estão oferecendo um token a dois preços diferentes, alguém pode comprar o token na DEX com preços mais baixos e vendê-lo nas DEX com preços mais altos em uma única transação atômica. Graças ao mecanismo da blockchain, está é sem dúvidas uma arbitragem sem risco. -[Aqui está um exemplo](https://etherscan.io/tx/0x5e1657ef0e9be9bc72efefe59a2528d0d730d478cfc9e6cdd09af9f997bb3ef4) de uma transação de arbitragem lucrativa onde um buscador transformou 1.00 ETH em 1.045 ETH aproveitando os diferentes preços do par ETH/DAI no Uniswap vs. Sushiswap. +[Aqui está um exemplo](https://eth.blockscout.com/tx/0x5e1657ef0e9be9bc72efefe59a2528d0d730d478cfc9e6cdd09af9f997bb3ef4) de uma transação de arbitragem lucrativa em que um pesquisador transformou 1.000 ETH em 1.045 ETH, aproveitando os diferentes preços do par ETH/DAI na Uniswap vs. Sushiswap. ### Liquidações {#mev-examples-liquidations} As liquidações do protocolo de empréstimo oferecem outra oportunidade conhecida de MEV. -Protocolos de empréstimo como Maker e Aave exigem que os usuários depositem algumas garantias (por exemplo, ETH). Essa garantia depositada é então usada para emprestar a outros usuários. +Protocolos de empréstimo como Maker e Aave exigem que os usuários depositem alguma garantia (ex.: ETH). Esse colateral depositado é então usado para emprestar a outros usuários. -Os usuários podem então pedir emprestado ativos e tokens de outros, dependendo do que eles precisarem (por exemplo, você pode pedir emprestado MKR, se quiser votar em uma proposta de governança do MakerDAO) até um certo percentual de suas garantias depositadas. Por exemplo, se a quantia emprestada for um máximo de 30%, um usuário que depositar 100 DAI no protocolo poderá emprestar até 30 DAI de outro ativo. O protocolo determina a porcentagem exata do poder de empréstimo. +Os usuários podem então tomar emprestado ativos e tokens de outros, dependendo do que precisam (ex.: você pode tomar emprestado MKR se quiser votar em uma proposta de governança do MakerDAO) até uma certa porcentagem da garantia depositada. Por exemplo, se a quantia emprestada for um máximo de 30%, um usuário que depositar 100 DAI no protocolo poderá emprestar até 30 DAI de outro ativo. O protocolo determina a porcentagem exata do poder de empréstimo. -O valor das garantias de quem pede o emprestado flutua, assim como sua capacidade de pedir empréstimo. Se, por causa das flutuações de mercado, o valor dos ativos emprestados excede, por exemplo, 30% do valor de suas garantias (novamente, a porcentagem exata é determinada pelo protocolo), o protocolo normalmente permite que qualquer pessoa liquide a garantia, pagando imediatamente os mutuantes (isso é semelhante a como [chamada de margem](https://www.investopedia.com/terms/m/margincall.asp) funciona nas finanças tradicionais). Se liquidado, o mutuário geralmente tem de pagar uma taxa de liquidação elevada, parte da qual vai para o liquidador. É aí que se encontra a oportunidade de MEV. +O valor das garantias de quem pede o emprestado flutua, assim como sua capacidade de pedir empréstimo. Se, devido às flutuações do mercado, o valor dos ativos emprestados exceder, digamos, 30% do valor da sua garantia (novamente, a porcentagem exata é determinada pelo protocolo), o protocolo normalmente permite que qualquer pessoa liquide a garantia, pagando instantaneamente aos credores (isso é semelhante a como as [chamadas de margem](https://www.investopedia.com/terms/m/margincall.asp) funcionam nas finanças tradicionais). Se liquidado, o mutuário geralmente tem de pagar uma taxa de liquidação elevada, parte da qual vai para o liquidador. É aí que se encontra a oportunidade de MEV. Os buscadores competem para analisar os dados da blockchain o mais rápido possível para determinar quais mutuários podem ser liquidados e ser o primeiro a enviar uma transação de liquidação e coletar a taxa de liquidação para si mesmos. @@ -66,89 +66,89 @@ Sandwich trading é outro método comum de extração MEV. Para usar o método sandwich, um buscador observará o mempool para encontrar grandes negociações DEX. Por exemplo, suponha que alguém queira comprar 10.000 UNI com DAI na Uniswap. Uma transação desta magnitude causará um impacto significativo no par UNI/DAI, ocasionando aumento significativo no preço da UNI em relação ao DAI. -Um buscador pode calcular o efeito de preço aproximado desta grande negociação no par UNI/DAI e executar uma ordem de compra ideal imediatamente _antes_ da grande negociação, comprando UNI mais barato e, em seguida, executar uma ordem de venda imediatamente _após_ a grande negociação, vendendo-a pelo preço mais alto causado pelo grande pedido. +Um pesquisador pode calcular o efeito aproximado no preço dessa grande negociação no par UNI/DAI e executar uma ordem de compra ideal imediatamente _antes_ da negociação grande, comprando UNI barato e, em seguida, executar uma ordem de venda imediatamente _após_ a negociação grande, vendendo por um preço mais alto causado pela ordem grande. -No entanto, o método sandwich é mais arriscado, pois não é atômico (ao contrário da arbitragem DEX, como descrito acima) e é propenso a um [ataque "salmonela"](https://github.com/Defi-Cartel/salmonella). +O sanduíche, no entanto, é mais arriscado, pois não é atômico (ao contrário da arbitragem de DEX, conforme descrito acima) e está propenso a um [ataque de salmonela](https://github.com/Defi-Cartel/salmonella). -### MEV com NFT {#mev-examples-nfts} +### MEV de NFT {#mev-examples-nfts} O MEV no espaço de NFT é um fenômeno emergente e não é necessariamente lucrativo. No entanto, uma vez que as transações NFT acontecem na mesma blockchain compartilhada por todas as outras transações Ethereum, buscadores podem usar técnicas similares como as usadas em oportunidades de MEV tradicionais também no mercado NFT. -Por exemplo, se há o lançamento de um NFT popular e um buscador quer um determinado NFT ou um determinado conjunto de NFTs, ele pode programar uma transação de tal forma a ser o primeiro a comprar a NFT ou ele pode comprar todo o conjunto de NFTs em uma única transação. Ou se um NFT estiver [listado por um preço baixo de maneira equivocada](https://www.theblockcrypto.com/post/113546/mistake-sees-69000-cryptopunk-sold-for-less-than-a-cent), um buscador pode se adiantar por meio de frontrun a outros compradores e adquiri-lo por baixo custo. +Por exemplo, se há o lançamento de um NFT popular e um buscador quer um determinado NFT ou um determinado conjunto de NFTs, ele pode programar uma transação de tal forma a ser o primeiro a comprar a NFT ou ele pode comprar todo o conjunto de NFTs em uma única transação. Ou se um NFT for [listado por engano a um preço baixo](https://www.theblockcrypto.com/post/113546/mistake-sees-69000-cryptopunk-sold-for-less-than-a-cent), um pesquisador pode aplicar frontrun em outros compradores e adquiri-lo por um valor baixo. -Um exemplo proeminente de NFT com MEV ocorreu quando um buscador gastou US$ 7 milhões para [comprar](https://etherscan.io/address/0x650dCdEB6ecF05aE3CAF30A70966E2F395d5E9E5) cada Cryptopunk ao preço mínimo. Um pesquisador de blockchain [explicou no Twitter](https://twitter.com/IvanBogatyy/status/1422232184493121538) como o comprador trabalhou com um provedor de MEV para manter a compra em segredo. +Um exemplo proeminente de MEV de NFT ocorreu quando um pesquisador gastou 7 milhões de dólares para [comprar](https://eth.blockscout.com/address/0x650dCdEB6ecF05aE3CAF30A70966E2F395d5E9E5?tab=txs) todos os Cryptopunks ao preço mínimo. Um pesquisador de blockchain [explicou no Twitter](https://twitter.com/IvanBogatyy/status/1422232184493121538) como o comprador trabalhou com um provedor de MEV para manter sua compra em segredo. ### A cauda longa {#mev-examples-long-tail} Arbitragem DEX, liquidações e o método sandwich trading são todos oportunidades de MEV muito conhecidas e são improváveis de serem lucrativas para novos buscadores. No entanto, há uma longa cauda de oportunidades de MEV menos conhecidas. MEV com NFT é, indiscutivelmente, uma dessas oportunidades. -Os buscadores que estão apenas começando talvez consigam ter mais sucesso procurando MEV nesta cauda mais longa. O [quadro de trabalhos MEV](https://github.com/flashbots/mev-job-board) do Flashbot enumera algumas oportunidades emergentes. +Os buscadores que estão apenas começando talvez consigam ter mais sucesso procurando MEV nesta cauda mais longa. O [quadro de vagas de MEV](https://github.com/flashbots/mev-job-board) da Flashbots lista algumas oportunidades emergentes. ## Efeitos do MEV {#effects-of-mev} Nem tudo sobre o MEV é negativo. Há consequências positivas e negativas com respeito ao MEV no Ethereum. -### As vantagens {#effects-of-mev-the-good} +### O lado bom {#effects-of-mev-the-good} Muitos projetos DeFi dependem de atores economicamente racionais para assegurar a utilidade e a estabilidade dos seus protocolos. Por exemplo, a arbitragem DEX garante que os usuários obtenham os melhores preços corretos por seus totens, e os protocolos de empréstimo dependem de liquidações rápidas quando os mutuários caem abaixo das proporções de garantia para garantir que os mutuários recebam de volta. Sem buscadores racionais procurando e corrigindo as ineficiências econômicas e aproveitando os incentivos econômicos dos protocolos, os protocolos de DeFI e dApps podem, em geral, não ser tão robustos como são hoje. -### As desvantagens {#effects-of-mev-the-bad} +### O lado ruim {#effects-of-mev-the-bad} Na camada de aplicativo, algumas formas de MEV, como o método "sandwich trading", resultam em uma experiência inequivocamente pior para os usuários. Usuários que sofrem o método "sandwich trading" enfrentam maior slippage (derrapagem) e uma pior execução nas suas transações. Na camada de rede, os frontrunners generalizados e os leilões de preço do gás nos quais eles costumam participar (quando dois ou mais frontrunners competem para que sua transação seja incluída no bloco seguinte, aumentando progressivamente o preço do gás das suas próprias transações) resultam em congestionamento da rede e em elevados preços do gás para todos os outros que tentam realizar transações regulares. -Além do que está acontecendo _nos_ blocos, o MEV pode ter efeitos prejudiciais _entre_ os blocos. Se o MEV disponível em um bloco excede significativamente a recompensa do bloco padrão, os validadores podem ser incentivados a reorganizar os blocos e capturar o MEV para si mesmos, causando reorganização da blockchain e instabilidade do consenso. +Além do que está acontecendo _dentro_ dos blocos, o MEV pode ter efeitos deletérios _entre_ os blocos. Se o MEV disponível em um bloco excede significativamente a recompensa do bloco padrão, os validadores podem ser incentivados a reorganizar os blocos e capturar o MEV para si mesmos, causando reorganização da blockchain e instabilidade do consenso. -Essa possibilidade de reorganização da blockchain foi [previamente explorada na blockchain Bitcoin](https://dl.acm.org/doi/10.1145/2976749.2978408). Como a recompensa de bloco do Bitcoin é reduzida pela metade e as recompensas de transação representam uma parte cada vez maior da recompensa do bloco, surgem situações nas quais é mais economicamente racional para os mineradores desistirem da recompensa do próximo bloco e, em vez disso, minarem novamente blocos passados com taxas mais elevadas. Com o crescimento do MEV, o mesmo tipo de situação poderia ocorrer com o Ethereum, ameaçando a integridade da blockchain. +Essa possibilidade de reorganização da blockchain foi [previamente explorada na blockchain do Bitcoin](https://dl.acm.org/doi/10.1145/2976749.2978408). Como a recompensa de bloco do Bitcoin é reduzida pela metade e as recompensas de transação representam uma parte cada vez maior da recompensa do bloco, surgem situações nas quais é mais economicamente racional para os mineradores desistirem da recompensa do próximo bloco e, em vez disso, minarem novamente blocos passados com taxas mais elevadas. Com o crescimento do MEV, o mesmo tipo de situação poderia ocorrer com o Ethereum, ameaçando a integridade da blockchain. ## Estado do MEV {#state-of-mev} -A extração MEV teve um grande crescimento no início de 2021, o que resultou em preços de gás extremamente elevados nos primeiros meses do ano. O surgimento do relé MEV de Flashbots reduziu a efetividade dos frontrunners generalizados e tirou os leilões de preço de gás da cadeia, baixando os preços do gás para os utilizadores comuns. +A extração MEV teve um grande crescimento no início de 2021, o que resultou em preços de gás extremamente elevados nos primeiros meses do ano. O surgimento do relay de MEV da Flashbots reduziu a eficácia dos piorneiros generalizados e levou os leilões de preço do gás para offchain, diminuindo os preços do gás para os usuários comuns. Enquanto muitos buscadores ainda estão ganhando um bom dinheiro com o MEV, à medida que as oportunidades se tornam mais conhecidas e mais e mais buscadores competem pela mesma oportunidade, os validadores irão capturar cada vez mais receita total do MEV (porque o mesmo tipo de leilão de gás descrito originalmente acima também ocorre em Flashbots, embora de forma particular, e os validadores irão capturar a receita de gás resultante). O MEV também não é exclusivo da Ethereum, e conforme as oportunidades se tornam mais competitivas no Ethereum, os buscadores estão migrando para blockchains alternativas, como a Binance Smart Chain, onde oportunidades de MEV semelhantes às que estão na Ethereum existem com menos concorrência. -Por outro lado, a transição da prova de trabalho para prova de participação e o esforço contínuo para escalar o Ethereum usando rollups mudam todo o panorama do MEV de maneiras que ainda não estão claras. Ainda não se sabe bem de que maneira ter proponentes de bloco garantidos conhecidos com pouca antecedência altera a dinâmica da extração de MEV em comparação com o modelo probabilístico na prova de trabalho ou como isso será interrompido quando [a eleição de líder secreto único](https://ethresear.ch/t/secret-non-single-leader-election/11789) e [a tecnologia de validador distribuído](/staking/dvt/) forem implementados. Da mesma forma, resta saber quais são as oportunidades de MEV existentes quando a maioria das atividades do usuário é transferida do Ethereum para seus rollups e fragmentos de camada 2. +Por outro lado, a transição da prova de trabalho para prova de participação e o esforço contínuo para escalar o Ethereum usando rollups mudam todo o panorama do MEV de maneiras que ainda não estão claras. Ainda não se sabe bem como ter proponentes de bloco garantidos, conhecidos com um pouco de antecedência, altera a dinâmica da extração de MEV em comparação com o modelo probabilístico na prova de trabalho, ou como isso será interrompido quando a [eleição de líder secreto único](https://ethresear.ch/t/secret-non-single-leader-election/11789) e a [tecnologia de validador distribuído](/staking/dvt/) forem implementadas. Da mesma forma, resta saber quais são as oportunidades de MEV existentes quando a maioria das atividades do usuário é transferida do Ethereum para seus rollups e fragmentos de camada 2. ## MEV na prova de participação (PoS) do Ethereum {#mev-in-ethereum-proof-of-stake} Conforme explicado, o MEV tem implicações negativas para a experiência geral do usuário e para a segurança da camada de consenso. Mas a transição do Ethereum para um consenso de prova de participação (denominado "A Fusão") introduz potencialmente novos riscos relacionados ao MEV: -### Centralização do validador {#validator-centralization} +### Centralização de validadores {#validator-centralization} -No Ethereum pós-fusão, os validadores (tendo feito depósitos de segurança de 32 ETH) chegam a um consenso sobre a validade dos blocos adicionados à Beacon Chain. Como 32 ETH podem estar fora do alcance de muitos, [entrar em um staking pool](/staking/pools/) pode ser uma opção mais viável. No entanto, uma distribuição saudável de [stakers individuais](/staking/solo/) é ideal, pois mitiga a centralização dos validadores e melhora a segurança do Ethereum. +No Ethereum pós-fusão, os validadores (tendo feito depósitos de segurança de 32 ETH) chegam a um consenso sobre a validade dos blocos adicionados à Beacon Chain. Como 32 ETH podem estar fora do alcance de muitos, [juntar-se a um pool de staking](/staking/pools/) pode ser uma opção mais viável. No entanto, uma distribuição saudável de [stakers individuais](/staking/solo/) é ideal, pois mitiga a centralização de validadores e melhora a segurança do Ethereum. -No entanto, acredita-se que a extração MEV seja capaz de acelerar a centralização de validadores. Isso se deve em parte porque, como os validadores [ganham menos por propor blocos](/roadmap/merge/issuance/#how-the-merge-impacts-ETH-supply) do que os mineradores atualmente, a extração de MEV pode em muito [influenciar os ganhos do validador](https://github.com/flashbots/eth2-research/blob/main/notebooks/mev-in-eth2/eth2-mev-calc.ipynb) após o The Merge (A Fusão). +No entanto, acredita-se que a extração MEV seja capaz de acelerar a centralização de validadores. Isso ocorre em parte porque, como os validadores [ganham menos por propor blocos](/roadmap/merge/issuance/#how-the-merge-impacts-ETH-supply) do que os mineradores anteriormente, a extração de MEV tem [influenciado muito os ganhos dos validadores](https://github.com/flashbots/eth2-research/blob/main/notebooks/mev-in-eth2/eth2-mev-calc.ipynb) desde o [The Merge](/roadmap/merge/). -Staking pools maiores provavelmente terão mais recursos para investir em otimizações necessárias para capturar oportunidades de MEV. Quanto mais MEV essas pools extraem, mais recursos eles têm para melhorar suas capacidades de extração MEV (e aumentar a receita geral), criando essencialmente [economias de escala](https://www.investopedia.com/terms/e/economiesofscale.asp#). +Staking pools maiores provavelmente terão mais recursos para investir em otimizações necessárias para capturar oportunidades de MEV. Quanto mais MEV esses pools extraem, mais recursos eles têm para melhorar suas capacidades de extração de MEV (e aumentar a receita geral), criando essencialmente [economias de escala](https://www.investopedia.com/terms/e/economiesofscale.asp#). Com menos recursos à sua disposição, os stakers individuais podem ser incapazes de lucrar com oportunidades de MEV. Isso pode aumentar a pressão sobre validadores independentes para se unirem a staking pools poderosas para aumentar os ganhos, reduzindo a descentralização no Ethereum. -### Mempools autorizados {#permissioned-mempools} +### Mempools permissionados {#permissioned-mempools} -Em resposta aos ataques "sandwiching" e "frontrunning", os traders podem começar a realizar negócios off-chain com validadores para privacidade de transação. Em vez de enviar uma potencial transação MEV para o mempool público, o trader a envia diretamente ao validador, que a inclui em um bloco e divide os lucros com o trader. +Em resposta aos ataques de "sandwiching" e "frontrunning", os traders podem começar a conduzir acordos off-chain com validadores para privacidade de transações. Em vez de enviar uma potencial transação MEV para o mempool público, o trader a envia diretamente ao validador, que a inclui em um bloco e divide os lucros com o trader. "Dark pools" são uma versão maior deste arranjo e funcionam como mempools autorizados só de acesso, abertas para usuários dispostos a pagar determinadas taxas. Esta tendência diminuiria a ausência de permissão e falta de confiança no Ethereum, e potencialmente transformaria a blockchain em um mecanismo "pay-to-play" que favorece a maior oferta. Mempools autorizados também acelerariam os riscos de centralização descritos na seção anterior. Grandes pools que executam vários validadores provavelmente se beneficiarão ao oferecer privacidade de transação a traders e usuários, aumentando as receitas MEV deles. -A luta contra esses problemas relacionados ao MEV no Ethereum pós-Fusão é uma área central de pesquisa. Até hoje, duas soluções propostas para reduzir o impacto negativo do MEV na descentralização e na segurança do Ethereum, depois da Fusão são **Separação Proponente-Construtor (PBS)** e **Builder API**. +A luta contra esses problemas relacionados ao MEV no Ethereum pós-Fusão é uma área central de pesquisa. Até o momento, duas soluções propostas para reduzir o impacto negativo do MEV na descentralização e segurança do Ethereum após o The Merge são a [**Separação Propositor-Construtor (PBS)**](/roadmap/pbs/) e a [**Builder API**](https://github.com/ethereum/builder-specs). -### Separação Proponente/Construtor {#proposer-builder-separation} +### Separação Propositor-Construtor {#proposer-builder-separation} -Em ambas prova de trabalho e prova de participação, um nó que cria um bloco o propõe para ser adicionado à cadeia para outros nós que participam do consenso. Um novo bloco se torna parte da cadeia canônica depois que outro minerador constrói com base nele (na prova de trabalho) ou recebe atestados da maioria dos validadores (na prova de participação). +Em ambas prova de trabalho e prova de participação, um nó que cria um bloco o propõe para ser adicionado à cadeia para outros nós que participam do consenso. Um novo bloco se torna parte da cadeia canônica depois que outro minerador cria com base nele (em PoW) ou recebe atestados da maioria dos validadores (em PoS). -A combinação de funções de produtor de bloco e de proponente de bloco é o que introduz a maioria dos problemas relacionados com o MEV descritos anteriormente. Por exemplo, nós de consenso são incentivados a desencadear reorganizações da cadeia em ataques time-bandit para maximizar os ganhos MEV. +A combinação de funções de produtor de bloco e de proponente de bloco é o que introduz a maioria dos problemas relacionados com o MEV descritos anteriormente. Por exemplo, os nós de consenso são incentivados a acionar reorganizações da cadeia em [ataques time-bandit](https://www.mev.wiki/attack-examples/time-bandit-attack) para maximizar os ganhos de MEV. -A [Separação Proponente/Construtor](https://ethresear.ch/t/proposer-block-builder-separation-friendly-fee-market-designs/9725) (PBS) foi criada para mitigar o impacto do MEV, especialmente na camada de consenso. A principal característica do PBS é a separação entre o produtor de bloco e as regras do proponente de bloco. Os validadores ainda são responsáveis por propor e votar nos blocos, mas uma nova classe de entidades especializadas, chamada de **construtores de blocos**, é encarregada de ordenar transações e construir blocos. +A [Separação Propositor-Construtor](https://ethresear.ch/t/proposer-block-builder-separation-friendly-fee-market-designs/9725) (PBS) foi projetada para mitigar o impacto do MEV, especialmente na camada de consenso. A principal característica do PBS é a separação entre o produtor de bloco e as regras do proponente de bloco. Os validadores ainda são responsáveis por propor e votar em blocos, mas uma nova classe de entidades especializadas, chamadas **construtores de blocos**, tem a tarefa de ordenar transações e construir blocos. Em PBS, um construtor de blocos cria um pacote de transações e faz um lance para sua inclusão em um bloco da Beacon Chain (como o “payload de execução”). O validador selecionado para propor o próximo bloco verifica então os diferentes lances e escolhe o pacote com a taxa mais alta. O PBS cria essencialmente um mercado de leilão, no qual os construtores negociam com os validadores vendendo o espaço no bloco. -O design de PBS atual usa um [esquema commit-reveal](https://gitcoin.co/blog/commit-reveal-scheme-on-ethereum/) no qual os construtores só publicam um compromisso criptográfico com o conteúdo de um bloco (header do bloco), juntamente com seus lances. Após aceitar o lance vencedor, o proponente cria uma proposta de bloco assinado que inclui o cabeçalho do bloco. O construtor do bloco deve publicar o corpo completo do bloco após ver a proposta do bloco assinado, e também deve receber [atestações](/glossary/#attestation) suficientes dos validadores antes de ser finalizado. +Os designs atuais do PBS usam um [esquema de commit-reveal](https://gitcoin.co/blog/commit-reveal-scheme-on-ethereum/) no qual os construtores publicam apenas um compromisso criptográfico com o conteúdo de um bloco (cabeçalho do bloco) juntamente com suas propostas. Após aceitar o lance vencedor, o proponente cria uma proposta de bloco assinado que inclui o cabeçalho do bloco. Espera-se que o construtor de blocos publique o corpo completo do bloco depois de ver a proposta de bloco assinada, e também deve receber [atestados](/glossary/#attestation) suficientes dos validadores antes de ser finalizado. #### Como a separação proponente-construtor atenua o impacto do MEV? {#how-does-pbs-curb-mev-impact} @@ -156,15 +156,15 @@ O protocolo de separação proponente-construtor reduz o efeito do MEV sobre o c Isso não exclui totalmente os validadores das receitas relacionadas ao MEV, já que os construtores devem dar lances altos para conseguir que seus blocos sejam aceitos pelos validadores. No entanto, com validadores não mais focados diretamente na otimização de renda MEV, a ameaça de ataques time-bandit diminui. -A separação proponente-construtor também reduz os riscos de centralização do MEV. Por exemplo, o uso de um esquema commit-reveal remove a necessidade de os construtores confiarem nos validadores para não roubarem a oportunidade MEV ou expô-la a outros construtores. Isso reduz a barreira para os stakers individuais se beneficiarem do MEV, caso contrário os construtores tenderiam a favorecer grandes pools com reputação off-chain e a conduzir acordos off-chain com eles. +A separação proponente-construtor também reduz os riscos de centralização do MEV. Por exemplo, o uso de um esquema commit-reveal remove a necessidade de os construtores confiarem nos validadores para não roubarem a oportunidade MEV ou expô-la a outros construtores. Isso reduz a barreira para que os stakers solo se beneficiem do MEV, caso contrário, os construtores tenderiam a favorecer grandes pools com reputação off-chain e a conduzir acordos off-chain com eles. De forma similar, os validadores não têm que confiar que os construtores não vão reter os corpos de blocos ou publicar blocos inválidos porque o pagamento é incondicional. A taxa do validador ainda processa mesmo que o bloco proposto esteja indisponível ou seja declarado inválido por outros validadores. No último caso, o bloco é simplesmente descartado, forçando o construtor de blocos a perder todas as taxas de transação e a receita MEV. -### Builder API {#builder-api} +### API de Construtor {#builder-api} -Embora a separação proponente-construtor prometa reduzir os efeitos da extração do MEV, a sua implementação requer alterações no protocolo de consenso. Especificamente, a regra de [escolha de fork](/developers/docs/consensus-mechanisms/pos/#fork-choice) na Beacon Chain precisaria ser atualizada. A [Builder API](https://github.com/ethereum/builder-specs) é uma solução temporária destinada a fornecer uma implementação funcional da separação proponente-construtor, embora com hipóteses mais confiáveis. +Embora a separação proponente-construtor prometa reduzir os efeitos da extração do MEV, a sua implementação requer alterações no protocolo de consenso. Especificamente, a regra de [escolha de bifurcação](/developers/docs/consensus-mechanisms/pos/#fork-choice) na Beacon Chain precisaria ser atualizada. A [API de Construtor](https://github.com/ethereum/builder-specs) é uma solução temporária destinada a fornecer uma implementação funcional da separação propositor-construtor, embora com maiores premissas de confiança. -A Builder API é uma versão modificada da [Engine API](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md) usada por clientes da camada de consenso para solicitar payloads de execução de clientes da camada de execução. Conforme descrito na [especificação do validador honesto](https://github.com/ethereum/consensus-specs/blob/master/specs/bellatrix/validator.md), validadores selecionados para funções de proposta de bloco solicitam um pacote de transação de um cliente de execução conectado, que eles incluem no bloco proposto da Beacon Chain. +A API de Construtor é uma versão modificada da [API de Engine](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md) usada por clientes da camada de consenso para solicitar cargas de execução de clientes da camada de execução. Conforme descrito na [especificação do validador honesto](https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/validator.md), os validadores selecionados para as tarefas de proposição de blocos solicitam um pacote de transações de um cliente de execução conectado, que eles incluem no bloco proposto da Beacon Chain. A Builder API também atua como um middleware entre validadores e clientes da camada de execução; mas é diferente porque permite aos validadores na Beacon Chain originar blocos de entidades externas (em vez de construir um bloco localmente usando um cliente de execução). @@ -178,15 +178,16 @@ Veja abaixo uma resumo geral de como a Builder API funciona: 4. O construtor que executa a Builder API deverá responder com a carga completa de execução após ver a proposta de bloco cega. Isso permite que o validador crie um bloco Beacon "assinado" que eles propagam por toda a rede. -5. Ainda é esperado que um validador usando a Builder API construa um bloco localmente caso o construtor de blocos não responda prontamente, para que não percam as recompensas de proposta de bloco. No entanto, o validador não pode criar outro bloco usando as transações agora reveladas ou outro conjunto, pois equivaleria a _equívoco_ (assinar dois blocos dentro do mesmo slot), o que é uma infração passível de advertência. +5. Ainda é esperado que um validador usando a Builder API construa um bloco localmente caso o construtor de blocos não responda prontamente, para que não percam as recompensas de proposta de bloco. No entanto, o validador não pode criar outro bloco usando as transações agora reveladas ou outro conjunto, pois isso equivaleria a _equivocação_ (assinar dois blocos no mesmo slot), que é uma ofensa passível de slashing. -Uma implementação de exemplo da Builder API é [MEV Boost](https://github.com/flashbots/mev-boost), uma melhoria no mecanismo de leilão [Flashbots](https://docs.flashbots.net/flashbots-auction/overview/) projetada para limitar as externalidades negativas de MEV no Ethereum. O leilão Flashbots permite que os mineradores em prova de trabalho externalizem o trabalho de construção de blocos lucrativos a partes especializadas chamadas de **buscadores**. +Um exemplo de implementação da API de Construtor é o [MEV Boost](https://github.com/flashbots/mev-boost), uma melhoria no [mecanismo de leilão da Flashbots](https://docs.flashbots.net/Flashbots-auction/overview) projetada para conter as externalidades negativas do MEV no Ethereum. O leilão da Flashbots permite que validadores em prova de participação terceirizem o trabalho de construção de blocos lucrativos para partes especializadas chamadas **pesquisadores**. +![Um diagrama mostrando o fluxo de MEV em detalhes](./mev.png) -Os buscadores procuram oportunidades de MEV lucrativas e enviam pacotes de transação para os mineradores, juntamente com uma [oferta de preço selada](https://en.wikipedia.org/wiki/First-price_sealed-bid_auction) para inclusão no bloco. O minerador executando mev-geth, uma versão bifurcada do cliente go-ethereum (Geth) só precisa escolher o pacote com mais lucro e minerá-lo como parte do novo bloco. Para proteger os mineradores de transações de spam e inválidas, os pacotes de transações passam por **retransmissores** (relayers) para validação antes de chegar aos mineradores. +Os pesquisadores procuram oportunidades lucrativas de MEV e enviam pacotes de transações para os propositores de bloco juntamente com uma [proposta de preço selado](https://en.wikipedia.org/wiki/First-price_sealed-bid_auction) para inclusão no bloco. O validador que executa o mev-geth, uma versão bifurcada do cliente go-ethereum (Geth), só precisa escolher o pacote com mais lucro e incluí-lo como parte do novo bloco. Para proteger os propositores de bloco (validadores) de spam e transações inválidas, os pacotes de transações passam por **retransmissores** para validação antes de chegar ao propositor. -O MEV Boost mantém o mesmo funcionamento do leilão original de Flashbots, embora com novos recursos projetados para a mudança à prova de participação do Ethereum. Os buscadores ainda consideram transações MEV lucrativas para inclusão em blocos, mas uma nova classe de partes especializadas, chamada de **construtores**, é responsável pela agregação de transações e pacotes em blocos. Um construtor aceita ofertas de preço seladas pelos buscadores e executa otimizações para encontrar o pedido mais lucrativo. +O MEV Boost mantém o mesmo funcionamento do leilão original de Flashbots, embora com novos recursos projetados para a mudança à prova de participação do Ethereum. Os pesquisadores ainda encontram transações de MEV lucrativas para inclusão em blocos, mas uma nova classe de partes especializadas, chamadas **construtores**, é responsável por agregar transações e pacotes em blocos. Um construtor aceita ofertas de preço seladas pelos buscadores e executa otimizações para encontrar o pedido mais lucrativo. -O retransmissor ainda é responsável por validar pacotes de transações antes de passá-los para o proponente. No entanto, o MEV Boost introduz **escrows** responsáveis por fornecer [disponibilidade de dados](/developers/docs/data-availability/) ao armazenar corpos de blocos enviados por construtores e cabeçalhos de bloco enviados por validadores. Aqui, um validador conectado a um relay pede por payloads de execução disponíveis e usa o algoritmo de ordenação MEV Boost para selecionar o cabeçalho de payload com as maiores ofertas + valores MEV. +O retransmissor ainda é responsável por validar pacotes de transações antes de passá-los para o proponente. No entanto, o MEV Boost introduz **escrows** responsáveis por fornecer [disponibilidade de dados](/developers/docs/data-availability/), armazenando os corpos dos blocos enviados pelos construtores e os cabeçalhos dos blocos enviados pelos validadores. Aqui, um validador conectado a um relay pede por payloads de execução disponíveis e usa o algoritmo de ordenação MEV Boost para selecionar o cabeçalho de payload com as maiores ofertas + valores MEV. #### Como a Builder API atenua o impacto do MEV? {#how-does-builder-api-curb-mev-impact} @@ -202,19 +203,19 @@ Alguns projetos, como MEV Boost, usam a Builder API como parte de uma estrutura ## Recursos relacionados {#related-resources} -- [Documentação sobre Flashbots (links em inglês)](https://docs.flashbots.net/) -- [Flashbots GitHub](https://github.com/flashbots/pm) -- [mevboost.org](https://www.mevboost.org/) - _Rastreador com estatísticas em tempo real para relays MEV-Boost e construtores de blocos_ +- [Documentação da Flashbots](https://docs.flashbots.net/) +- [GitHub da Flashbots](https://github.com/flashbots/pm) +- [mevboost.org](https://www.mevboost.org/) - _Rastreador com estatísticas em tempo real para relays e construtores de blocos do MEV-Boost_ ## Leitura adicional {#further-reading} -- [Valor extraível da mineração (MEV)?](https://blog.chain.link/what-is-miner-extractable-value-mev/) -- [MEV e Mim](https://www.paradigm.xyz/2021/02/mev-and-me) -- [O Ethereum é uma Floresta Sombria](https://www.paradigm.xyz/2020/08/ethereum-is-a-dark-forest/) -- [Escapando da Floresta Sombria](https://samczsun.com/escaping-the-dark-forest/) -- [Flashbots: Superando a crise MEV](https://medium.com/flashbots/frontrunning-the-mev-crisis-40629a613752) -- [Tópicos sobre MEV de @bertcmiller](https://twitter.com/bertcmiller/status/1402665992422047747) -- [MEV-Boost: Arquitetura Flashbots pronta para a Fusão](https://ethresear.ch/t/mev-boost-merge-ready-flashbots-architecture/11177) +- [O que é o Valor Extraível do Minerador (MEV)?](https://blog.chain.link/what-is-miner-extractable-value-mev/) +- [MEV e Eu](https://www.paradigm.xyz/2021/02/mev-and-me) +- [Ethereum é uma Floresta Escura](https://www.paradigm.xyz/2020/08/ethereum-is-a-dark-forest/) +- [Escapando da Floresta Escura](https://samczsun.com/escaping-the-dark-forest/) +- [Flashbots: Aplicando frontrunning na crise do MEV](https://medium.com/flashbots/frontrunning-the-mev-crisis-40629a613752) +- [Threads sobre MEV de @bertcmiller](https://twitter.com/bertcmiller/status/1402665992422047747) +- [MEV-Boost: Arquitetura Flashbots pronta para o Merge](https://ethresear.ch/t/mev-boost-merge-ready-flashbots-architecture/11177) - [O que é MEV Boost](https://www.alchemy.com/overviews/mev-boost) -- [Por que executar mev-boost?](https://writings.flashbots.net/writings/why-run-mevboost/) -- [O Guia do Mochileiro sobre o Ethereum](https://members.delphidigital.io/reports/the-hitchhikers-guide-to-ethereum) +- [Por que executar o mev-boost?](https://writings.flashbots.net/writings/why-run-mevboost/) +- [O Guia do Mochileiro para o Ethereum](https://members.delphidigital.io/reports/the-hitchhikers-guide-to-ethereum) diff --git a/public/content/translations/pt-br/developers/docs/networking-layer/index.md b/public/content/translations/pt-br/developers/docs/networking-layer/index.md index 10aed4cc705..84e6399cf40 100644 --- a/public/content/translations/pt-br/developers/docs/networking-layer/index.md +++ b/public/content/translations/pt-br/developers/docs/networking-layer/index.md @@ -1,6 +1,6 @@ --- -title: Camada da Rede -description: Introdução à camada de rede Ethereum +title: Camada de rede +description: "Introdução à camada de rede Ethereum" lang: pt-br sidebarDepth: 2 --- @@ -13,7 +13,7 @@ Clientes de execução transmitem transações na rede ponto a ponto na camada d ## Pré-requisitos {#prerequisites} -Alguns conhecimentos dos [nós e clientes](/developers/docs/nodes-and-clients/) do Ethereum serão úteis para entender esta página. +Algum conhecimento sobre [nós e clientes](/developers/docs/nodes-and-clients/) do Ethereum será útil para entender esta página. ## A camada de execução {#execution-layer} @@ -27,33 +27,33 @@ Ambas as pilhas funcionam em paralelo. A pilha de descoberta alimenta novos part ### Descoberta {#discovery} -Descoberta é o processo de encontrar outros nós na rede. Isso é inicializado usando um pequeno conjunto de bootnodes (nós cujos endereços são [hardcoded](https://github.com/ethereum/go-ethereum/blob/master/params/bootnodes.go) dentro do cliente para que possam ser encontrados imediatamente e conectar o cliente aos pares). Estes bootnodes (nós de inicialização) existem apenas para introduzir um novo nó a um conjunto de pares. Esse é o único objetivo deles; eles não participam de tarefas normais do cliente como sincronizar a cadeia e são usados somente na primeira vez que um cliente é ativado. +Descoberta é o processo de encontrar outros nós na rede. Isso é inicializado usando um pequeno conjunto de bootnodes (nós cujos endereços são [codificados](https://github.com/ethereum/go-ethereum/blob/master/params/bootnodes.go) no cliente, para que possam ser encontrados imediatamente e conectar o cliente aos pares). Estes bootnodes (nós de inicialização) existem apenas para introduzir um novo nó a um conjunto de pares. Esse é o único objetivo deles; eles não participam de tarefas normais do cliente como sincronizar a cadeia e são usados somente na primeira vez que um cliente é ativado. -O protocolo usado para as interações de node-bootnode (nós de inicialização) é uma forma modificada de [Kademlia](https://medium.com/coinmonks/a-brief-overview-of-kademlia-and-its-use-in-various-decentralized-platforms-da08a7f72b8f) que usa uma [tabela de hash distribuída](https://en.wikipedia.org/wiki/Distributed_hash_table) para compartilhar listas de nós. Cada nó tem uma versão desta tabela contendo as informações necessárias para se conectar aos seus pares mais próximos. Essa 'proximidade' não é geográfica. A distância é definida pela semelhança do ID de nós. A tabela de cada nó é atualizada regularmente como um recurso de segurança. Por exemplo, no [Discv5](https://github.com/ethereum/devp2p/tree/master/discv5), os nós do protocolo de descoberta também podem enviar 'anúncios' que exibem os subprotocolos que o cliente suporta, permitindo que os pares negociem sobre os protocolos que ambos podem usar para se comunicar. +O protocolo usado para as interações nó-bootnode é uma forma modificada do [Kademlia](https://medium.com/coinmonks/a-brief-overview-of-kademlia-and-its-use-in-various-decentralized-platforms-da08a7f72b8f) que usa uma [tabela de hash distribuída](https://en.wikipedia.org/wiki/Distributed_hash_table) para compartilhar listas de nós. Cada nó tem uma versão desta tabela contendo as informações necessárias para se conectar aos seus pares mais próximos. Essa 'proximidade' não é geográfica. A distância é definida pela semelhança do ID de nós. A tabela de cada nó é atualizada regularmente como um recurso de segurança. Por exemplo, no [Discv5](https://github.com/ethereum/devp2p/tree/master/discv5), os nós do protocolo de descoberta também podem enviar 'anúncios' que exibem os subprotocolos que o cliente suporta, permitindo que os pares negociem sobre os protocolos que ambos podem usar para se comunicar. -A descoberta começa com um jogo de PING-PONG. Um PING-PONG bem-sucedido "liga" o novo nó a um bootnode (nó de inicialização). A mensagem inicial que alerta um bootnode sobre a existência de um novo nó entrando na rede é um `PING`. Este `PING` inclui informações em hash sobre o novo nó, o bootnode e um carimbo de data/hora de expiração. O bootnode recebe o `PING` e retorna um `PONG` contendo o hash `PING`. Se os hashes `PING` e `PONG` corresponderem, então a conexão entre o novo nó e o bootnode será verificada e diz-se que eles têm "vínculo". +A descoberta começa com um jogo de PING-PONG. Um PING-PONG bem-sucedido "liga" o novo nó a um bootnode (nó de inicialização). A mensagem inicial que alerta um bootnode sobre a existência de um novo nó entrando na rede é um `PING`. Este `PING` inclui informações com hash sobre o novo nó, o bootnode e um carimbo de data/hora de expiração. O bootnode recebe o `PING` e retorna um `PONG` contendo o hash do `PING`. Se os hashes de `PING` e `PONG` corresponderem, a conexão entre o novo nó e o bootnode é verificada e diz-se que eles estão "vinculados". -Uma vez vinculado, o novo nó pode enviar uma solicitação `FIND-NEIGHBOURS` para o bootnode. Os dados retornados pelo bootnode incluem uma lista de peers aos quais o novo nó pode se conectar. Se os nós não estiverem vinculados, a solicitação `FIND-NEIGHBOURS` falhará, então o novo nó não poderá entrar na rede. +Uma vez vinculado, o novo nó pode enviar uma solicitação `FIND-NEIGHBOURS` para o bootnode. Os dados retornados pelo bootnode incluem uma lista de peers aos quais o novo nó pode se conectar. Se os nós não estiverem vinculados, a solicitação `FIND-NEIGHBOURS` falhará, e o novo nó não conseguirá entrar na rede. Uma vez que o novo nó recebe uma lista de vizinhos do bootnode, ele inicia uma troca de PING-PONG com cada um deles. PING-PONGs bem-sucedidos unem o novo nó com seus vizinhos, permitindo a troca de mensagens. ``` -start client --> connect to bootnode --> bond to bootnode --> find neighbours --> bond to neighbours +iniciar cliente --> conectar ao bootnode --> vincular ao bootnode --> encontrar vizinhos --> vincular aos vizinhos ``` Os clientes de execução estão usando atualmente o protocolo de descoberta [Discv4](https://github.com/ethereum/devp2p/blob/master/discv4.md) e há um esforço ativo para migrar para o protocolo [Discv5](https://github.com/ethereum/devp2p/tree/master/discv5). -#### ENR: Registros de Nó Ethereum {#enr} +#### ENR: Registros de Nós do Ethereum {#enr} -O [Registro de Nó Ethereum (ENR)](/developers/docs/networking-layer/network-addresses/) é um objeto que contém três elementos básicos: uma assinatura (hash do conteúdo do registro feito de acordo com algum esquema de identidade acordado), um número de sequência que rastreia as alterações no registro e uma lista arbitrária de pares chave:valor. Este é um formato moderno que permite uma troca mais fácil de informações de identificação entre novos pares e é o formato de [endereço de rede](/developers/docs/networking-layer/network-addresses) preferido dos nós Ethereum. +O [Registro de Nó Ethereum (ENR)](/developers/docs/networking-layer/network-addresses/) é um objeto que contém três elementos básicos: uma assinatura (hash do conteúdo do registro feito de acordo com algum esquema de identidade acordado), um número de sequência que rastreia as alterações no registro e uma lista arbitrária de pares chave:valor. Este é um formato à prova de futuro que permite uma troca mais fácil de informações de identificação entre novos pares e é o formato de [endereço de rede](/developers/docs/networking-layer/network-addresses) preferido para os nós do Ethereum. -#### Por que a descoberta é construída no UDP? {#why-udp} +#### Por que a descoberta é construída no UDP? Por que UDP? {#why-udp} O UDP não suporta nenhuma verificação de erros, reenvio de pacotes com falha ou abertura e fechamento de conexões dinamicamente. Em vez disso, ele apenas dispara um fluxo contínuo de informações em um destino, independentemente de ter sido recebido com sucesso. Essa funcionalidade mínima também se traduz em sobrecarga mínima, tornando esse tipo de conexão muito rápida. Para descoberta, onde um nó simplesmente quer tornar sua presença conhecida, para depois estabelecer uma conexão formal com um par, o UDP é suficiente. No entanto, para o restante da pilha de rede, o UDP não é adequado. A troca de informações entre nós é bastante complexa e, portanto, precisa de um protocolo mais completo que possa suportar reenvio, verificação de erros etc. A sobrecarga adicional associada ao TCP vale a funcionalidade adicional. Portanto, a maioria da pilha P2P opera sobre TCP. ### DevP2P {#devp2p} -O DevP2P é em si uma pilha inteira de protocolos que o Ethereum implementa para estabelecer e manter a rede ponto a ponto. Depois que novos nós entram na rede, suas interações são regidas por protocolos na pilha [DevP2P](https://github.com/ethereum/devp2p). Todos eles ficam em cima do TCP e incluem o protocolo de transporte RLPx, o protocolo de fio e vários subprotocolos. [RLPx](https://github.com/ethereum/devp2p/blob/master/rlpx.md) é o protocolo que controla o início, a autenticação e a manutenção de sessões entre nós. O RLPx codifica mensagens usando RLP (Prefixo de Comprimento Recursivo), que é um método muito eficiente de codificação de dados em uma estrutura mínima para envio entre nós. +O DevP2P é em si uma pilha inteira de protocolos que o Ethereum implementa para estabelecer e manter a rede ponto a ponto. Depois que novos nós entram na rede, suas interações são regidas por protocolos na pilha [DevP2P](https://github.com/ethereum/devp2p). Todos eles ficam em cima do TCP e incluem o protocolo de transporte RLPx, o protocolo de fio e vários subprotocolos. [RLPx](https://github.com/ethereum/devp2p/blob/master/rlpx.md) é o protocolo que rege o início, a autenticação e a manutenção de sessões entre nós. O RLPx codifica mensagens usando RLP (Prefixo de Comprimento Recursivo), que é um método muito eficiente de codificação de dados em uma estrutura mínima para envio entre nós. Uma sessão RLPx entre dois nós começa com um acerto criptográfico inicial. Isso envolve o nó enviando uma mensagem de autenticação que é então verificada pelo par. Na verificação bem-sucedida, o para gera uma mensagem de confirmação de autenticação para retornar ao nó inicializador. Este é um processo de troca de chaves que permite que os nós se comuniquem de forma privada e segura. Um aperto de mão criptográfico bem-sucedido aciona ambos os nós para enviar uma mensagem "hello" um ao outro "na rede". O protocolo de transmissão é iniciado por uma troca bem-sucedida de mensagens de saudação. @@ -73,19 +73,19 @@ Junto com as mensagens de saudação, o protocolo de transmissão também pode e #### Protocolo de transmissão {#wire-protocol} -Uma vez que os pares estão conectados e uma sessão RLPx foi iniciada, o protocolo de transmissão define como os pares se comunicam. Inicialmente, o protocolo de transmissão definiu três tarefas principais: sincronização de cadeia, propagação de bloco e troca de transação. No entanto, uma vez que o Ethereum mudou para a prova de participação, a propagação do bloco e a sincronização da cadeia tornaram-se parte da camada de consenso. A troca de transações ainda é da responsabilidade dos clientes de execução. A troca de transações refere-se à troca de transações pendentes entre nós para que os construtores de blocos possam selecionar algumas delas para inclusão no próximo bloco. Informações detalhadas sobre essas tarefas estão disponíveis [aqui](https://github.com/ethereum/devp2p/blob/master/caps/eth.md). Os clientes que oferecem suporte a esses subprotocolos os expõem por meio do [JSON-RPC](/developers/docs/apis/json-rpc/). +Uma vez que os pares estão conectados e uma sessão RLPx foi iniciada, o protocolo de transmissão define como os pares se comunicam. Inicialmente, o protocolo de transmissão definiu três tarefas principais: sincronização de cadeia, propagação de bloco e troca de transação. No entanto, uma vez que o Ethereum mudou para a prova de participação, a propagação do bloco e a sincronização da cadeia tornaram-se parte da camada de consenso. A troca de transações ainda é da responsabilidade dos clientes de execução. A troca de transações refere-se à troca de transações pendentes entre nós para que os construtores de blocos possam selecionar algumas delas para inclusão no próximo bloco. Informações detalhadas sobre essas tarefas estão disponíveis [aqui](https://github.com/ethereum/devp2p/blob/master/caps/eth.md). Clientes que suportam esses subprotocolos os expõem através do [JSON-RPC](/developers/docs/apis/json-rpc/). -#### les (subprotocolo ethereum leve) {#les} +#### les (subprotocolo leve do Ethereum) {#les} -Este é um protocolo mínimo para sincronizar clientes leves. Esse protocolo raramente é usado porque são necessários nós completos para fornecer dados a clientes leves sem serem incentivados. O comportamento padrão dos clientes de execução é não transmitir dados de clientes leves sobre subprotocolos ethereum leve (les). Mais informações estão disponíveis nas [especificações](https://github.com/ethereum/devp2p/blob/master/caps/les.md). +Este é um protocolo mínimo para sincronizar clientes leves. Esse protocolo raramente é usado porque são necessários nós completos para fornecer dados a clientes leves sem serem incentivados. O comportamento padrão dos clientes de execução não é servir dados de clientes leves por meio do les. Mais informações estão disponíveis na [especificação](https://github.com/ethereum/devp2p/blob/master/caps/les.md) do les. -#### Captura {#snap} +#### Snap {#snap} -O [protocolo de captura](https://github.com/ethereum/devp2p/blob/master/caps/snap.md#ethereum-snapshot-protocol-snap) é uma extensão opcional que permite que pares troquem instantâneos de estados recentes, permitindo que os pares verifiquem dados de conta e armazenamento sem precisar baixar nós intermediários da árvore Merkle. +O [protocolo snap](https://github.com/ethereum/devp2p/blob/master/caps/snap.md#ethereum-snapshot-protocol-snap) é uma extensão opcional que permite que os pares troquem snapshots de estados recentes, permitindo que os pares verifiquem os dados da conta e do armazenamento sem ter que baixar os nós intermediários da árvore de Merkle. #### Wit (protocolo de testemunha) {#wit} -O [protocolo de testemunha](https://github.com/ethereum/devp2p/blob/master/caps/wit.md#ethereum-witness-protocol-wit) é uma extensão opcional que permite a troca de testemunhas de estado entre os pares, ajudando a sincronizar os clientes com a ponta da cadeia. +O [protocolo de testemunha](https://github.com/ethereum/devp2p/blob/master/caps/wit.md#ethereum-witness-protocol-wit) é uma extensão opcional que permite a troca de testemunhas de estado entre pares, ajudando a sincronizar os clientes com a ponta da cadeia. #### Whisper {#whisper} @@ -97,11 +97,11 @@ Os clientes de consenso participam de uma rede ponto a ponto separada com uma es ### Descoberta {#consensus-discovery} -Semelhante aos clientes de execução, os clientes de consenso usam [discv5](https://github.com/ethereum/consensus-specs/blob/master/specs/phase0/p2p-interface.md#the-discovery-domain-discv5) sobre UDP para encontrar pares. A implementação da camada de consenso do discv5 difere daquela dos clientes de execução apenas porque inclui um adaptador conectando o discv5 em uma pilha [libP2P](https://libp2p.io/), descontinuando o DevP2P. As sessões RLPx da camada de execução foram descontinuadas a favor do handshake (acerto) de canal seguro de ruído da libP2P. +Semelhante aos clientes de execução, os clientes de consenso usam o [discv5](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#the-discovery-domain-discv5) sobre UDP para encontrar pares. A implementação da camada de consenso do discv5 difere da dos clientes de execução apenas por incluir um adaptador que conecta o discv5 a uma pilha [libP2P](https://libp2p.io/), descontinuando o DevP2P. As sessões RLPx da camada de execução foram descontinuadas a favor do handshake (acerto) de canal seguro de ruído da libP2P. ### ENRs {#consensus-enr} -O ENR para nós de consenso inclui a chave pública do nó, endereço IP, portas UDP e TCP e dois campos específicos de consenso: o campo de bits (bitfield) da sub-rede de atestado e a chave `eth2`. O primeiro torna mais fácil para os nós encontrarem pares que participam de sub-redes de gossip de atestado específicas. A chave `eth2` contém informações sobre qual versão do fork Ethereum o nó está usando, garantindo que os pares estejam se conectando ao Ethereum correto. +O ENR para nós de consenso inclui a chave pública do nó, o endereço IP, as portas UDP e TCP e dois campos específicos do consenso: o campo de bits da sub-rede de atestado e a chave `eth2`. O primeiro torna mais fácil para os nós encontrarem pares que participam de sub-redes de gossip de atestado específicas. A chave `eth2` contém informações sobre qual versão da bifurcação do Ethereum o nó está usando, garantindo que os pares estejam se conectando ao Ethereum correto. ### libP2P {#libp2p} @@ -109,9 +109,9 @@ A pilha libP2P suporta todas as comunicações após a descoberta. Os clientes p ### Gossip {#gossip} -O domínio gossip inclui todas as informações que precisam se espalhar rapidamente pela rede. Isso inclui blocos de sinalização, provas, atestados, saídas e cortes. Isso é transmitido usando libP2P gossipsub v1 e depende de vários metadados armazenados localmente em cada nó, incluindo o tamanho máximo de cargas de gossip para receber e transmitir. Informações detalhadas sobre o domínio gossip estão disponíveis [aqui](https://github.com/ethereum/consensus-specs/blob/master/specs/phase0/p2p-interface.md#the-gossip-domain-gossipsub). +O domínio gossip inclui todas as informações que precisam se espalhar rapidamente pela rede. Isso inclui blocos de sinalização, provas, atestados, saídas e cortes. Isso é transmitido usando libP2P gossipsub v1 e depende de vários metadados armazenados localmente em cada nó, incluindo o tamanho máximo de cargas de gossip para receber e transmitir. Informações detalhadas sobre o domínio gossip estão disponíveis [aqui](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#the-gossip-domain-gossipsub). -### Pedido-Resposta {#request-response} +### Solicitação-resposta {#request-response} O domínio de pedido-resposta contém protocolos para clientes que solicitam informações específicas de seus pares. Os exemplos incluem pedidos de blocos Beacon específicos que correspondam a determinados hashes raiz ou dentro de um intervalo de slots. As respostas são sempre retornadas como bytes codificados em SSZ compactados rapidamente. @@ -119,25 +119,25 @@ O domínio de pedido-resposta contém protocolos para clientes que solicitam inf SSZ significa serialização simples. Ela usa deslocamentos fixos que facilitam a decodificação de partes individuais de uma mensagem codificada sem ter que decodificar toda a estrutura, o que é muito útil para o cliente de consenso, pois pode capturar com eficiência informações específicas de mensagens codificadas. Ele também é projetado especificamente para integração com protocolos Merkle, com ganhos de eficiência relacionados para Merkleization (transformação resultante de árvores de Merkle). Como todos os hashes na camada de consenso são raízes de Merkle, isso resulta em uma melhoria significativa. A SSZ também garante representações únicas de valores. -## Conexão a execução e consensos de clientes {#connecting-clients} +## Conectando os clientes de execução e de consenso {#connecting-clients} Ambos os clientes de consenso e execução executam em paralelo. Eles precisam estar conectados para que o cliente de consenso possa fornecer instruções ao cliente de execução, e o cliente de execução possa passar pacotes de transações para o cliente de consenso para incluir nos blocos Beacon. A comunicação entre os dois clientes pode ser realizada usando uma conexão RPC local. Uma API conhecida como ['Engine-API'](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md) define as instruções enviadas entre os dois clientes. Como ambos os clientes estão atrás de uma única identidade de rede, eles compartilham um ENR (registro de nó Ethereum) que contém uma chave separada para cada cliente (chave eth1 e chave eth2). Um resumo do fluxo de controle é mostrado abaixo, com a pilha de rede relevante entre colchetes. -### Quando o cliente de consenso não é produtor de bloco: {#when-consensus-client-is-not-block-producer} +### Quando o cliente de consenso não é o produtor do bloco: {#when-consensus-client-is-not-block-producer} - O cliente de consenso recebe um bloco através do protocolo gossip do bloco (consenso p2p) -- O cliente de consenso pré-valida o bloco, ou seja, garante que chegou de um remetente válido com metadados corretos +- O cliente de consenso pré-valida o bloco, ou seja, garante que ele chegou de um remetente válido com os metadados corretos. - As transações no bloco são enviadas para a camada de execução como um payload (carga de dados) de execução (conexão RPC local) -- A camada de execução executa as transações e valida o estado no cabeçalho do bloco (ou seja, verifica a correspondência de hashes) +- A camada de execução executa as transações e valida o estado no cabeçalho do bloco (ou seja, verifica se os hashes correspondem). - A camada de execução passa os dados de validação de volta para a camada de consenso, bloco agora considerado validado (conexão RPC local) - A camada de consenso adiciona bloco no nício de sua própria blockchain e o atesta, transmitindo o atestado pela rede (consenso p2p) -### Quando o cliente de consenso é produtor de blocos: {#when-consensus-client-is-block-producer} +### Quando o cliente de consenso é o produtor de blocos: {#when-consensus-client-is-block-producer} - O cliente de consenso recebe o aviso de que é o próximo produtor de bloco (consenso p2p) -- A camada de consenso chama o método `create block` no cliente de execução (RPC local) +- A camada de consenso chama o método `create block` no cliente de execução (RPC local). - A camada de execução acessa o mempool da transação que foi preenchido pelo protocolo gossip de transação (execução p2p) - O cliente de execução agrupa as transações em um bloco, executa as transações e gera um hash de bloco - O cliente de consenso pega as transações e bloqueia o hash do cliente de execução e o adiciona ao bloco beacon (RPC local) @@ -146,10 +146,18 @@ Um resumo do fluxo de controle é mostrado abaixo, com a pilha de rede relevante Uma vez que o bloco tenha sido atestado por validadores suficientes, ele é adicionado ao cabeçalho da cadeia, justificado e finalmente finalizado. -![](cons_client_net_layer.png) ![](exe_client_net_layer.png) +![](cons_client_net_layer.png) +![](exe_client_net_layer.png) -Esquema da camada de rede para clientes de consenso e execução, de [ethresear.ch](https://ethresear.ch/t/eth1-eth2-client-relationship/7248) +Esquema da camada de rede para clientes de consenso e de execução, de [ethresear.ch](https://ethresear.ch/t/eth1-eth2-client-relationship/7248) -## Leitura Adicional {#further-reading} +## Leitura adicional {#further-reading} -[DevP2P](https://github.com/ethereum/devp2p) [LibP2p](https://github.com/libp2p/specs) [Especificações de rede da camada de consenso](https://github.com/ethereum/consensus-specs/blob/master/specs/phase0/p2p-interface.md#enr-structure) [Kademlia para Discv5](https://vac.dev/kademlia-to-discv5) [Paper Kademlia](https://pdos.csail.mit.edu/~petar/papers/maymounkov-kademlia-lncs.pdf) [Introdução ao Ethereum p2p](https://p2p.paris/en/talks/intro-ethereum-networking/) [Relacionamento eth1/eth2](http://ethresear.ch/t/eth1-eth2-client-relationship/7248) [Fusão e vídeo com detalhes do cliente eth2](https://www.youtube.com/watch?v=zNIrIninMgg) +[DevP2P](https://github.com/ethereum/devp2p) +[LibP2p](https://github.com/libp2p/specs) +[Especificações de rede da camada de consenso](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#enr-structure) +[De Kademlia para discv5](https://vac.dev/kademlia-to-discv5) +[Artigo sobre o Kademlia](https://pdos.csail.mit.edu/~petar/papers/maymounkov-kademlia-lncs.pdf) +[Introdução à rede P2P do Ethereum](https://p2p.paris/en/talks/intro-ethereum-networking/) +[Relação ETH1/ETH2](http://ethresear.ch/t/eth1-eth2-client-relationship/7248) +[Vídeo com detalhes sobre a The Merge e clientes ETH2](https://www.youtube.com/watch?v=zNIrIninMgg) diff --git a/public/content/translations/pt-br/developers/docs/networking-layer/network-addresses/index.md b/public/content/translations/pt-br/developers/docs/networking-layer/network-addresses/index.md index ccbbc951b6f..3fd183cb432 100644 --- a/public/content/translations/pt-br/developers/docs/networking-layer/network-addresses/index.md +++ b/public/content/translations/pt-br/developers/docs/networking-layer/network-addresses/index.md @@ -1,19 +1,19 @@ --- -title: Endereço de rede -description: Uma introdução aos endereços de rede +title: "Endereço de rede" +description: "Uma introdução aos endereços de rede" lang: pt-br sidebarDepth: 2 --- Nós Ethereum precisam se identificar com algumas informações básicas para se conectar a pares. Para garantir que qualquer para potencial possa interpretar esta informação, ela é transmitida em um dos três formatos padronizados que qualquer nó Ethereum pode entender: multiaddr, enode ou Ethereum Node Records (ENRs). ENRs são o padrão atual para endereços de rede Ethereum. -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -É necessário ter algum entendimento sobre a [camada de rede](/developers/docs/networking-layer/)do Ethereum para entender esta página. +É necessário ter algum entendimento sobre a [camada de rede](/developers/docs/networking-layer/) do Ethereum para entender esta página. ## Multiaddr {#multiaddr} -O formato original do endereço de nó Ethereum era o 'multiaddr' (abreviação de 'multi-endereços'). O Multiaddr é um formato universal desenhado para redes peer-to-peer. Os endereços são representados como pares chave-valor com chaves e valores separados por uma barra. Por exemplo, o multiaddr para um nó com endereço IPv4 `192.168.22.27` escutando a porta TCP `33000` será: +O formato original do endereço de nó Ethereum era o 'multiaddr' (abreviação de 'multi-endereços'). O Multiaddr é um formato universal desenhado para redes peer-to-peer. Os endereços são representados como pares chave-valor com chaves e valores separados por uma barra. Por exemplo, o multiaddr para um nó com endereço IPv4 `192.168.22.27` escutando a porta TCP `33000` tem a seguinte aparência: `/ip4/192.168.22.27/tcp/33000` @@ -23,17 +23,17 @@ Para um nó Ethereum, o multiaddr contém o node-ID (um hash de sua chave públi ## Enode {#enode} -Um enode é uma maneira de identificar um nó Ethereum usando um formato de endereço de URL. O ID hexadecimal do nó é codificado na porção do nome de usuário do URL separado do host usando um sinal @. O nome de host só pode ser dado como um endereço IP; nomes DNS não são permitidos. A porta na seção hostname é a porta de escuta TCP. Se as portas TCP e UDP (descoberta) são diferentes, a porta UDP é especificada como um parâmetro de consulta "discport" +Um enode é uma maneira de identificar um nó Ethereum usando um formato de endereço de URL. O ID hexadecimal do nó é codificado na porção do nome de usuário do URL separado do host usando um sinal @. O nome de host só pode ser dado como um endereço IP; nomes DNS não são permitidos. A porta na seção hostname é a porta de escuta TCP. Se as portas TCP e UDP (descoberta) são diferentes, a porta UDP é especificada como um parâmetro de consulta "discport". -No exemplo a seguir, o URL do nó descreve um nó com endereço IP `10.3.58.`, porta TCP `30303` e porta de descoberta UDP `30301`. +No exemplo a seguir, a URL do nó descreve um nó com endereço IP `10.3.58.6`, porta TCP `30303` e porta de descoberta UDP `30301`. `enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@10.3.58.6:30303?discport=30301` -## Registros de Nó Ethereum {#enr} +## Registros de Nós Ethereum (ENRs) {#enr} -Registros de Nó Ethereum (ENRs, pela sigla em inglês) são um formato padronizado para endereços de rede no Ethereum. Eles substituem multiaddrs e enodes. Estes são especialmente úteis porque permitem um maior intercâmbio de informações entre nós. O ENR contém uma assinatura, um número de sequência e campos detalhando o esquema de identidade usado para gerar e validar assinaturas. O ENR também pode ser populado com dados arbitrários organizados como pares de valor-chave. Estes pares chave-valor contêm o endereço IP do nó e as informações sobre os subprotocolos que o nó pode usar. Os clientes de consenso usam uma [estrutura ENR específica](https://github.com/ethereum/consensus-specs/blob/master/specs/phase0/p2p-interface.md#enr-structure) para identificar nós de inicialização e também incluem um campo `eth2` contendo informações sobre o atual fork do Ethereum e o atestado da sub-rede gossip (isso conecta o nó a um determinado conjunto de pares cujas atestações são agregadas juntos). +Registros de Nó Ethereum (ENRs, pela sigla em inglês) são um formato padronizado para endereços de rede no Ethereum. Eles substituem multiaddrs e enodes. Estes são especialmente úteis porque permitem um maior intercâmbio de informações entre nós. O ENR contém uma assinatura, um número de sequência e campos detalhando o esquema de identidade usado para gerar e validar assinaturas. O ENR também pode ser populado com dados arbitrários organizados como pares de valor-chave. Estes pares chave-valor contêm o endereço IP do nó e as informações sobre os subprotocolos que o nó pode usar. Os clientes de consenso usam uma [estrutura ENR específica](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#enr-structure) para identificar os nós de inicialização e também incluem um campo `eth2` que contém informações sobre a bifurcação atual do Ethereum e a sub-rede de gossip de atestados (que conecta o nó a um conjunto específico de pares cujos atestados são agregados). -## Leitura Adicional {#further-reading} +## Leitura adicional {#further-reading} -- [EIP-778: Registros de Nó Ethereum (ENR)](https://eips.ethereum.org/EIPS/eip-778) +- [EIP-778: Registros de Nós Ethereum (ENR)](https://eips.ethereum.org/EIPS/eip-778) - [LibP2P: Multiaddr-Enode-ENR?!](https://consensys.net/diligence/blog/2020/09/libp2p-multiaddr-enode-enr/) diff --git a/public/content/translations/pt-br/developers/docs/networking-layer/portal-network/index.md b/public/content/translations/pt-br/developers/docs/networking-layer/portal-network/index.md index 5223a43bb84..355585576f1 100644 --- a/public/content/translations/pt-br/developers/docs/networking-layer/portal-network/index.md +++ b/public/content/translations/pt-br/developers/docs/networking-layer/portal-network/index.md @@ -1,6 +1,6 @@ --- title: A Rede Portal -description: Uma visão geral da Rede Portal - uma rede em desenvolvimento para dar suporte a clientes com poucos recursos. +description: "Uma visão geral da Rede Portal - uma rede em desenvolvimento para dar suporte a clientes com poucos recursos." lang: pt-br --- @@ -12,23 +12,23 @@ A Rede Portal é um novo desenho de rede para o Ethereum que visa resolver o pro Mais sobre [nós e clientes](/developers/docs/nodes-and-clients/) -## Por que nós precisamos da Rede Portal {#why-do-we-need-portal-network} +## Por que precisamos da Portal Network {#why-do-we-need-portal-network} Os nódulos da Ethereum armazenam sua própria cópia total ou parcial do blockchain Ethereum. Esta cópia local é usada para validar transações e garantir que o nódulo está seguindo a cadeia correta. Este dado armazenado localmente permite aos nódulos verificarem de maneira independente que os dados de chegada são válidos e corretos sem precisar acreditar em nenhuma outra entidade. Esta cópia local do blockchain, além de seu estado associado e do recebimento de dados tomam muito espaço no disco rígido do nódulo. Por exemplo, um disco rígido de 2TB é recomendado para rodar um nó utilizando [Geth](https://geth.ethereum.org) pareado com um cliente de consenso. Usando sincronização instantânea, que armazena apenas dados da cadeia de um conjunto de blocos relativamente recente, Geth tipicamente ocupa cerca de 650GB de espaço em disco, mas cresce cerca de 14GB/semana (você pode podar o nó de volta a 650GB periodicamente). -Isto significa que rodar nódulos pode ser caro, porque uma grande quantidade de espaço em disco tem de ser dedicada ao Ethereum. Há diversas soluções para este problema no roadmap do Ethereum, incluindo [expiração de histórico](/roadmap/statelessness/#history-expiry), [expiração de estado](/roadmap/statelessness/#state-expiry) e [falta de estado](/roadmap/statelessness/). Entretanto, ainda há muito até que eles sejam implementados. Há também [nódulos leves](/developers/docs/nodes-and-clients/light-clients/) que não gravam suas próprias cópias dos dados da cadeia, eles solicitam os dados que eles precisam dos nódulos completos. Entretanto, isso significa que nódulos leves tem que acreditar em nódulos completos para fornecer dados honestos e também estressa os nódulos completos que tem que servir os dados para as necessidades dos nódulos leves. +Isto significa que rodar nódulos pode ser caro, porque uma grande quantidade de espaço em disco tem de ser dedicada ao Ethereum. Existem várias soluções para esse problema no planejamento do Ethereum, incluindo [expiração de histórico](/roadmap/statelessness/#history-expiry), [expiração de estado](/roadmap/statelessness/#state-expiry) e [ausência de estado](/roadmap/statelessness/). Entretanto, ainda há muito até que eles sejam implementados. Existem também [nós leves](/developers/docs/nodes-and-clients/light-clients/) que não salvam sua própria cópia dos dados da cadeia, eles solicitam os dados de que precisam de nós completos. Entretanto, isso significa que nódulos leves tem que acreditar em nódulos completos para fornecer dados honestos e também estressa os nódulos completos que tem que servir os dados para as necessidades dos nódulos leves. A Rede Portal visa fornecer uma maneira alternativa para nós leves terem seus dados que sem requerer confiança ou adicionar significantemente ao trabalho que tem de ser feito pelos nós completos. Isto será feito com a introdução de uma nova maneira dos nós Ethereum compartilharem dados através da rede. ## Como a Rede Portal funciona? {#how-does-portal-network-work} -Nós Ethereum tem protocolos estritos que definem como eles se comunicam com os outros. Clientes de execução se comunicam usando um conjunto de sub-protocolos conhecidos como [DevP2P](/developers/docs/networking-layer/#devp2p), enquanto clientes de consenso usam uma pilha diferente de sub-protocolos chamada [libP2P](/developers/docs/networking-layer/#libp2p). Eles definem os tipos de dados que podem ser passados entre nós. +Nós Ethereum tem protocolos estritos que definem como eles se comunicam com os outros. Clientes de execução se comunicam usando um conjunto de subprotocolos conhecido como [DevP2P](/developers/docs/networking-layer/#devp2p), enquanto os clientes de consenso usam uma pilha diferente de subprotocolos chamada [libP2P](/developers/docs/networking-layer/#libp2p). Eles definem os tipos de dados que podem ser passados entre nós. ![devP2P e libP2P](portal-network-devp2p-libp2p.png) -Os nós podem também servir dados específicos através da [API JSON-RPC](/developers/docs/apis/json-rpc/), que é como apps e carteiras trocam informações com os nós Ethereum. Entretanto, nenhum destes são protocolos ideias para servir dados para clientes leves. +Os nós também podem servir dados específicos através da [API JSON-RPC](/developers/docs/apis/json-rpc/), que é como os aplicativos e carteiras trocam informações com os nós do Ethereum. Entretanto, nenhum destes são protocolos ideias para servir dados para clientes leves. Clientes leves não podem atualmente requisitar pedaços específicos da cadeia de dados pelo DevP2P ou libP2P, porque estes protocolos são desenhados somente para habilitar sincronização de cadeias e transmissão de blocos e transações. Clientes leves não querem fazer o download desta informação, porque deixariam de ser 'leves'. @@ -36,7 +36,7 @@ A API JSON-RPC não é a escolha ideal para requisições de dados de clientes l A meta da Rede Portal é repensar todo o desenho, construindo especificamente para leveza, fora das limitações de desenho dos clientes Ethereum existentes. -A ideia central da Rede Portal é pegar os melhores bits da pilha da rede atual habilitando informações necessárias pelos clientes leves, como dados históricos e a identidade da cabeça atual da cadeia para ser servida através de um estilo DevP2P peso leve ponto-a-ponto em uma rede descentralizada, usando um [DHT](https://en.wikipedia.org/wiki/Distributed_hash_table) (similar à Bittorrent). +A ideia principal da Portal Network é aproveitar as melhores partes da pilha de rede atual, permitindo que informações necessárias para clientes leves, como dados históricos e a identidade do cabeçalho atual da cadeia, sejam servidas através de uma rede descentralizada ponto a ponto leve, no estilo DevP2P, usando uma [DHT](https://en.wikipedia.org/wiki/Distributed_hash_table) (semelhante ao Bittorrent). A ideia é adicionar pequenas partes do histórico de dados total do Ethereum e algumas responsabilidades específicas de nós para cada nó. Então, requisições são servidas procurando os nós que armazenam o dado específico que foi requisitado e recuperando-o deles. @@ -57,27 +57,33 @@ Os benefícios deste desenho de rede são: - minimizar ou zerar a sincronia - Acessível a dispositivos com recursos limitados (\<1 GB de RAM, \<100 MB de espaço em disco, 1 CPU) -O diagrama abaixo mostra as funções dos clientes existentes que podem ser entregues pela Rede Portal, habilitando ao usuários acessar estas funções em dispositivos com muito poucos recursos. +A tabela abaixo mostra as funções dos clientes existentes que podem ser oferecidas pela Portal Network, permitindo que os usuários acessem essas funções em dispositivos com pouquíssimos recursos. -![tabela rede portal](portal-network-table2.png) +### The Portal Networks -## Diversidade de cliente por padrão {#client-diversity-as-default} +| Beacon light client | State network | Propagação de Transações | History network | +| ------------------- | ---------------------------- | ------------------------ | --------------- | +| Beacon chain light | Account and contract storage | Lightweight mempool | Headers | +| Protocol data | | | Block bodies | +| | | | Receipts | -Os desenvolvedores da Rede Portal também fizeram com que o design assumido construísse três clientes separados na Rede Portal desde o primeiro dia. +## Diversidade de clientes por padrão {#client-diversity-as-default} + +Os desenvolvedores da Portal Network também fizeram a escolha de design de construir quatro clientes da Portal Network separados desde o primeiro dia. Os clientes da Rede Portal são: - [Trin](https://github.com/ethereum/trin): escrito em Rust -- [Fluffy](https://nimbus.team/docs/fluffy.html): escrito em Nim +- [Fluffy](https://fluffy.guide): escrito em Nim - [Ultralight](https://github.com/ethereumjs/ultralight): escrito em Typescript -- [Shisui](https://github.com/GrapeBaBa/shisui): escrito em Go +- [Shisui](https://github.com/zen-eth/shisui): escrito em Go Ter várias implementações de clientes independentes melhora a resiliência e descentralização da rede Ethereum. Se um cliente enfrenta problemas de vulnerabilidades, outros clientes podem continuar a operar tranquilamente, evitando o ponto único de falha. Adicionalmente, diversidade na implementação de clientes fomenta inovação e competição, conduzindo melhorias e reduzindo risco de monocultura dentro do ecossistema. -## Leitura adicional {#futher-reading} +## Leitura adicional {#further-reading} -- [A Rede Portal (Piper Merriam na Devcon Bogota)](https://www.youtube.com/watch?v=0stc9jnQLXA). -- [O desacordo da Rede Portal](https://discord.gg/CFFnmE7Hbs) -- [O website da Rede Portal](https://www.ethportal.net/) +- [A Portal Network (Piper Merriam na Devcon Bogota)](https://www.youtube.com/watch?v=0stc9jnQLXA). +- [Discord da Portal Network](https://discord.gg/CFFnmE7Hbs) +- [Site da Portal Network](https://www.ethportal.net/) diff --git a/public/content/translations/pt-br/developers/docs/networks/index.md b/public/content/translations/pt-br/developers/docs/networks/index.md index 31fafe90f64..5c2d50d1d21 100644 --- a/public/content/translations/pt-br/developers/docs/networks/index.md +++ b/public/content/translations/pt-br/developers/docs/networks/index.md @@ -1,6 +1,6 @@ --- title: Redes -description: Uma visão geral das redes Ethereum e onde obter ether (ETH) da rede de testes para testar seu aplicativo. +description: "Uma visão geral das redes Ethereum e onde obter ether (ETH) da rede de testes para testar seu aplicativo." lang: pt-br --- @@ -10,19 +10,19 @@ Sua conta Ethereum funcionará nas diferentes redes, mas o saldo da sua conta e ## Pré-requisitos {#prerequisites} -Você deveria entender as [noções básicas do Ethereum](/developers/docs/intro-to-ethereum/) antes de ler sobre as diferentes redes, pois as redes de teste lhe darão uma versão barata e segura do Ethereum para brincar. +Você deve entender os [conceitos básicos do Ethereum](/developers/docs/intro-to-ethereum/) antes de ler sobre as diferentes redes, pois as redes de teste lhe darão uma versão barata e segura do Ethereum para experimentar. ## Redes públicas {#public-networks} As redes públicas são acessíveis a qualquer pessoa no mundo com uma conexão à Internet. Qualquer um pode ler ou criar transações em uma blockchain pública e validar as transações que estão sendo executadas. O consenso entre os pares decide sobre a inclusão de transações e o estado da rede. -### Rede Principal Ethereum {#ethereum-mainnet} +### Mainnet do Ethereum {#ethereum-mainnet} A rede principal é a blockchain de produção Ethereum pública primária, onde as transações de valor real ocorrem no livro-razão distribuído. Quando as pessoas e as exchanges discutem os preços do ETH, eles estão falando sobre a rede principal ETH. -### Redes de Testes Ethereum {#ethereum-testnets} +### Redes de teste do Ethereum {#ethereum-testnets} Além da rede principal, existem redes de teste públicas. Essas são redes usadas por desenvolvedores de protocolo ou desenvolvedores de contrato inteligente para testar as atualizações de protocolo e também os contratos inteligentes em potencial em um ambiente de produção antes da implantação na rede principal. Pense nisso como um análogo a servidores de produção versus servidores de teste. @@ -34,19 +34,15 @@ ETH em redes de teste (testnets) supostamente não tem valor real; entretanto, t #### Qual rede de testes devo usar? -As duas redes de testes públicas que os desenvolvedores dos clientes estão atualmente mantendo são Sepolia e Hoodi. Sepolia é uma rede para desenvolvedores de contrato e aplicativos para testar seus aplicativos. A rede Hoodi permite que os desenvolvedores de protocolo testem atualizações de rede e permite que os participantes façam testes usando validadores. +As duas redes de teste públicas que os desenvolvedores do cliente estão mantendo atualmente são Sepolia e Hoodi. Sepolia é uma rede para desenvolvedores de contrato e aplicativos para testar seus aplicativos. A rede Hoodi permite que desenvolvedores de protocolo testem atualizações de rede e que stakers testem validadores em execução. #### Sepolia {#sepolia} -**Sepolia é a rede de teste padrão recomendada para desenvolvimento de aplicativos**. A rede Sepolia usa um conjunto de validadores autorizados. É bastante novo, o que significa que seu estado e história são bastante pequenos. Isso significa que a rede é rápida para sincronizar e que a execução de um nó requer menos armazenamento. Isso é útil para usuários que desejam ativar rapidamente um nó e interagir diretamente com a rede. - -- Conjunto de validadores fechado, controlado pelo cliente & equipes de teste -- Nova rede de teste, menos aplicativos implantados que outras redes de teste -- A sincronização rápida e a execução de um nó exigem um espaço de disco mínimo +**Sepolia é a rede de teste padrão recomendada para desenvolvimento de aplicativos**. A rede Sepolia usa um conjunto de validadores permissionado controlado por equipes de clientes e de testes. ##### Recursos -- [Website](https://sepolia.dev/) +- [Site](https://sepolia.dev/) - [GitHub](https://github.com/eth-clients/sepolia) - [Otterscan](https://sepolia.otterscan.io/) - [Etherscan](https://sepolia.etherscan.io) @@ -54,22 +50,22 @@ As duas redes de testes públicas que os desenvolvedores dos clientes estão atu ##### Faucets -- [Faucet do QuickNode Sepolia](https://faucet.quicknode.com/drip) +- [Faucet da Sepolia da Alchemy](https://www.alchemy.com/faucets/ethereum-sepolia) +- [Faucet da Sepolia da Chain Platform](https://faucet.chainplatform.co/faucets/ethereum-sepolia/) +- [Faucet da Sepolia da Chainstack](https://faucet.chainstack.com/sepolia-testnet-faucet) +- [Faucet do Ecossistema Ethereum](https://www.ethereum-ecosystem.com/faucets/ethereum-sepolia) +- [Faucet da Sepolia ethfaucet.com](https://ethfaucet.com/networks/ethereum) +- [Faucet da Sepolia do Google Cloud Web3](https://cloud.google.com/application/web3/faucet/ethereum/sepolia) - [Grabteeth](https://grabteeth.xyz/) -- [Faucet de PoW](https://sepolia-faucet.pk910.de/) -- [Faucet da Carteira Coinbase | Sepolia](https://coinbase.com/faucets/ethereum-sepolia-faucet) -- [Faucet do Alchemy Sepolia](https://sepoliafaucet.com/) -- [Faucet do Infura Sepolia](https://www.infura.io/faucet) -- [Faucet da Chainstack Sepolia](https://faucet.chainstack.com/sepolia-testnet-faucet) -- [Faucet do ecossistema Ethereum](https://www.ethereum-ecosystem.com/faucets/ethereum-sepolia) +- [Faucet da Sepolia da Infura](https://www.infura.io/faucet) +- [Faucet PoW](https://sepolia-faucet.pk910.de/) +- [Faucet da Sepolia do QuickNode](https://faucet.quicknode.com/ethereum/sepolia) #### Hoodi {#hoodi} -_Nota: [a rede de testes Goerli está obsoleta](https://ethereum-magicians.org/t/proposal-predictable-ethereum-testnet-lifecycle/11575/17) e foi substituída por Hoodi. Considere migrar seus aplicativos para a Sepolia._ - -Hoodi é a rede de testes usada para testar a validação e staking. A rede Hoodi está aberta para usuários que queiram executar um validador na rede de testes. Os participantes que desejam testar atualizações de protocolo antes de serem implantados na rede principal devem, portanto, usar a Hoodi. +Hoodi é uma testnet para testes de validação e staking. A rede Hoodi está aberta para usuários que desejam executar um validador na rede de testes. Os participantes que desejam testar atualizações de protocolo antes de implantá-las na rede principal devem usar o Hoodi. -- Conjunto de validadores abertos, com o qual os participantes podem testar atualizações de rede +- Conjunto de validadores abertos, onde participantes podem testar atualizações da rede - Estado grande, útil para testar interações complexas de contratos inteligentes - Mais longo para sincronizar e requer mais armazenamento para executar um nó @@ -77,48 +73,102 @@ Hoodi é a rede de testes usada para testar a validação e staking. A rede Hood - [Site](https://hoodi.ethpandaops.io/) - [GitHub](https://github.com/eth-clients/hoodi) -- [Explorer](https://explorer.hoodi.ethpandaops.io/) -- [Checkpoint Sync](https://checkpoint-sync.hoodi.ethpandaops.io/) +- [Explorador](https://explorer.hoodi.ethpandaops.io/) +- [Sincronização de Checkpoint](https://checkpoint-sync.hoodi.ethpandaops.io/) +- [Otterscan](https://hoodi.otterscan.io/) +- [Etherscan](https://hoodi.etherscan.io/) ##### Faucets -- [Faucet Hoodi](https://hoodi.ethpandaops.io/) +- [Faucet da Hoodi da Chain Platform](https://faucet.chainplatform.co/faucets/ethereum-hoodi/) +- [Faucet da Hoodi](https://hoodi.ethpandaops.io/) +- [Faucet PoW](https://hoodi-faucet.pk910.de/) + +#### Ephemery {#ephemery} + +Ephemery é um tipo exclusivo de rede de testes que é totalmente reiniciada todo mês. O estado de execução e consenso retorna ao estado de gênese a cada 28 dias, o que significa que tudo o que acontece na rede de teste é efêmero. Isso o torna ideal para testes de curto prazo, bootstrap rápido de nós e aplicativos do tipo "olá, mundo" que não precisam de permanência. + +- Estado sempre novo, testes de curto prazo de validadores e aplicativos +- Inclui apenas o conjunto básico de contratos +- Conjunto de validadores abertos e fácil acesso a grandes quantias de fundos +- Menores requisitos de nó e sincronização mais rápida, <5GB em média + +##### Recursos + +- [Site](https://ephemery.dev/) +- [GitHub](https://github.com/ephemery-testnet/ephemery-resources) +- [Chat da comunidade](https://matrix.to/#/#staker-testnet:matrix.org) +- [Blockscout](https://explorer.ephemery.dev/) +- [Otterscan](https://otter.bordel.wtf/) +- [Explorador da Beacon](https://beaconlight.ephemery.dev/) +- [Sincronização de Checkpoint](https://checkpoint-sync.ephemery.ethpandaops.io) +- [Plataforma de lançamento](https://launchpad.ephemery.dev/) -Para iniciar um Validador na rede de testes Hoodi, use a [plataforma de lançamento Hoodi](https://hoodi.launchpad.ethereum.org/en/). +#### Faucets -### Redes de testes de camada 2 {#layer-2-testnets} +- [Faucet Bordel](https://faucet.bordel.wtf/) +- [Faucet PoW Pk910](https://ephemery-faucet.pk910.de/) + +#### Holesky (obsoleta) {#holesky} + +A rede de teste Holesky está obsoleta a partir de setembro de 2025. Operadores de staking e provedores de infraestrutura devem usar Hoodi para testes de validadores. + +- [Anúncio de Desligamento da Rede de Teste Holesky](https://blog.ethereum.org/2025/09/01/holesky-shutdown-announcement) - _Blog da EF, 1 de setembro de 2025_ +- [Atualizações das Redes de Teste Holesky e Hoodi](https://blog.ethereum.org/en/2025/03/18/hoodi-holesky) - _Blog da EF, 18 de março de 2025_ + +### Redes de teste de camada 2 {#layer-2-testnets} [Camada 2 (L2)](/layer-2/) é um termo coletivo para descrever um conjunto específico de soluções de escalabilidade do Ethereum. Uma camada 2 é uma cadeia de blocos separada que estende o Ethereum e herda as garantias de segurança do Ethereum. Normalmente, as redes de teste de camada 2 estão fortemente associadas às redes de testes públicas do Ethereum. #### Arbitrum Sepolia {#arbitrum-sepolia} -Uma rede de testes para [Arbitrum](https://arbitrum.io/). +Uma rede de teste para o [Arbitrum](https://arbitrum.io/). + +##### Recursos + +- [Etherscan](https://sepolia.arbiscan.io/) +- [Blockscout](https://sepolia-explorer.arbitrum.io/) ##### Faucets -- [Faucet do Chainlink](https://faucets.chain.link/arbitrum-sepolia) -- [Faucet do Alchemy](https://www.alchemy.com/faucets/arbitrum-sepolia) +- [Faucet da Arbitrum Sepolia da Alchemy](https://www.alchemy.com/faucets/arbitrum-sepolia) +- [Faucet da Arbitrum Sepolia da Chainlink](https://faucets.chain.link/arbitrum-sepolia) +- [Faucet da Arbitrum Sepolia ethfaucet.com](https://ethfaucet.com/networks/arbitrum) +- [Faucet da Arbitrum Sepolia do QuickNode](https://faucet.quicknode.com/arbitrum/sepolia) #### Optimistic Sepolia {#optimistic-sepolia} -Uma rede de testes para [Optimism](https://www.optimism.io/). +Uma rede de teste para o [Optimism](https://www.optimism.io/). + +##### Recursos + +- [Etherscan](https://sepolia-optimistic.etherscan.io/) +- [Blockscout](https://optimism-sepolia.blockscout.com/) ##### Faucets -- [Faucet do Chainlink](https://faucets.chain.link/optimism-sepolia) -- [Faucet do Alchemy](https://www.alchemy.com/faucets/optimism-sepolia) +- [Faucet da Alchemy](https://www.alchemy.com/faucets/optimism-sepolia) +- [Faucet da Chainlink](https://faucets.chain.link/optimism-sepolia) +- [Faucet da Optimism Sepolia ethfaucet.com](https://ethfaucet.com/networks/optimism) +- [Faucet da rede de teste](https://docs.optimism.io/builders/tools/build/faucets) #### Starknet Sepolia {#starknet-sepolia} -Uma rede de teste para [Starknet](https://www.starknet.io). +Uma rede de teste para a [Starknet](https://www.starknet.io). + +##### Recursos + +- [Starkscan](https://sepolia.starkscan.co/) ##### Faucets -- [Faucet do Alchemy](https://www.alchemy.com/faucets/starknet-sepolia) +- [Faucet da Alchemy](https://www.alchemy.com/faucets/starknet-sepolia) +- [Faucet da Starknet Sepolia do Blast](https://blastapi.io/faucets/starknet-sepolia-eth) +- [Faucet da Starknet](https://starknet-faucet.vercel.app/) ## Redes privadas {#private-networks} -Uma rede Ethereum é uma rede privada se seus nódulos não estiverem conectados a uma rede pública (ex: Rede principal e rede de testes). Neste contexto, privado significa apenas reservado ou isolado, em vez de protegido ou seguro. +Uma rede Ethereum é uma rede privada se seus nós não estiverem conectados a uma rede pública (ou seja, a Mainnet ou uma rede de teste). Neste contexto, privado significa apenas reservado ou isolado, em vez de protegido ou seguro. ### Redes de desenvolvimento {#development-networks} @@ -132,12 +182,35 @@ O processo de consenso é controlado por um conjunto predefinido de nódulos con Se uma rede pública Ethereum é como a internet pública, uma rede de consórcio é como uma intranet privada. +## Por que as redes de teste do Ethereum recebem nomes de estações de metrô? {#why-naming} + +Muitas redes de teste do Ethereum recebem nomes de estações de metrô ou de trem do mundo real. Essa tradição de nomenclatura começou cedo e reflete as cidades globais onde os contribuidores viveram ou trabalharam. É simbólico, memorável e prático. Assim como as redes de teste são isoladas da mainnet do Ethereum, as linhas de metrô funcionam separadamente do tráfego da superfície. + +### Redes de teste legadas e de uso comum {#common-and-legacy-testnets} + +- **Sepolia** - Um bairro conectado por metrô em Atenas, Grécia. Atualmente usada para testes de contratos inteligentes e dApps. +- **Hoodi** - Nomeada em homenagem à estação de metrô Hoodi em Bengaluru, Índia. Usada para testes de validadores e de atualização de protocolo. +- **Goerli** _(obsoleta)_ - Nomeada em homenagem a Görlitzer Bahnhof em Berlim, Alemanha. +- **Rinkeby** _(obsoleta)_ - Nomeada em homenagem a um subúrbio de Estocolmo com uma estação de metrô. +- **Ropsten** _(obsoleta)_ - Refere-se a uma área e antigo terminal de balsa/metrô em Estocolmo. +- **Kovan** _(obsoleta)_ - Nomeada em homenagem a uma estação MRT de Singapura. +- **Morden** _(obsoleta)_ - Nomeada em homenagem a uma estação do metrô de Londres. A primeira rede de teste pública do Ethereum. + +### Outras redes de teste especializadas {#other-testnets} + +Algumas redes de teste foram criadas para testes de curto prazo ou específicos de atualização e não são necessariamente temáticas de metrô: + +- **Holesky** _(obsoleta)_ - Nomeada em homenagem à estação Holešovice em Praga. Usada para testes de validadores; obsoleta em 2025. +- **Kiln**, **Zhejiang**, **Shandong**, **Prater**, **Pyrmont**, **Olympic** _(todas obsoletas)_ e **Ephemery** - Construídas especificamente para simulações de atualização como A Fusão, Xangai ou experimentos de validadores. Alguns nomes são regionais ou temáticos, em vez de baseados em metrô. + +O uso de nomes de estações de metrô ajuda os desenvolvedores a identificar e lembrar rapidamente as redes de teste sem precisar depender de IDs de cadeia numéricos. Isso também reflete a cultura do Ethereum: prática, global e centrada no ser humano. + ## Ferramentas relacionadas {#related-tools} -- [Chainlist](https://chainlist.org/) _Lista de redes EVM para conectar carteiras e fornecedores aos identificadores de cadeia e rede apropriados_ -- [/Cadeias baseadas em EVM](https://github.com/ethereum-lists/chains) _Repositório do GitHub com metadados de cadeias que alimenta a Chainlist_ +- [Chainlist](https://chainlist.org/) _lista de redes EVM para conectar carteiras e provedores aos IDs de cadeia e de rede apropriados_ +- [Cadeias baseadas em EVM](https://github.com/ethereum-lists/chains) _repositório do GitHub com metadados de cadeias que alimenta o Chainlist_ ## Leitura adicional {#further-reading} -- [Proposta: Ciclo de vida previsível da rede de testes do Ethereum](https://ethereum-magicians.org/t/proposal-predictable-ethereum-testnet-lifecycle/11575/17) -- [A evolução das redes de testes do Ethereum](https://etherworld.co/2022/08/19/the-evolution-of-ethereum-testnet/) +- [Proposta: Ciclo de vida previsível da rede de teste do Ethereum](https://ethereum-magicians.org/t/proposal-predictable-ethereum-testnet-lifecycle/11575/17) +- [A Evolução das Redes de Teste do Ethereum](https://etherworld.co/2022/08/19/the-evolution-of-ethereum-testnet/) diff --git a/public/content/translations/pt-br/developers/docs/nodes-and-clients/archive-nodes/index.md b/public/content/translations/pt-br/developers/docs/nodes-and-clients/archive-nodes/index.md index ee85cd86aab..f87427b6af7 100644 --- a/public/content/translations/pt-br/developers/docs/nodes-and-clients/archive-nodes/index.md +++ b/public/content/translations/pt-br/developers/docs/nodes-and-clients/archive-nodes/index.md @@ -1,6 +1,6 @@ --- -title: Nó de arquivo Ethereum -description: Uma visão geral dos nós de arquivo +title: "Nó de arquivo Ethereum" +description: "Uma visão geral dos nós de arquivo" lang: pt-br sidebarDepth: 2 --- @@ -9,21 +9,21 @@ Um nó de arquivo é uma instância de um cliente Ethereum configurado para cons ## Pré-requisitos {#prerequisites} -Você deve entender o conceito de um [nó Ethereum](/developers/docs/nodes-and-clients/), [a arquitetura deles, assim como suas](/developers/docs/nodes-and-clients/node-architecture/) [estratégias de sincronização](/developers/docs/nodes-and-clients/#sync-modes), práticas de [execução](/developers/docs/nodes-and-clients/run-a-node/), e como [usá-los](/developers/docs/apis/json-rpc/). +Você deve entender o conceito de um [nó Ethereum](/developers/docs/nodes-and-clients/), [sua arquitetura](/developers/docs/nodes-and-clients/node-architecture/), [estratégias de sincronização](/developers/docs/nodes-and-clients/#sync-modes), práticas de [executá-los](/developers/docs/nodes-and-clients/run-a-node/) e [usá-los](/developers/docs/apis/json-rpc/). ## O que é um nó de arquivo -Para compreender a importância de um nó de arquivo, vamos esclarecer o conceito de "estado". O Ethereum pode ser chamado de _máquina de estado baseada em transações_. Consiste em contas e aplicativos que executam transações que estão mudando o seu estado. Os dados globais com informações sobre cada conta e contrato são armazenados em uma árvore de banco de dados chamado estado. Isso é tratado pelo cliente da camada de execução (EL) e inclui: +Para compreender a importância de um nó de arquivo, vamos esclarecer o conceito de "estado". O Ethereum pode ser chamado de uma _máquina de estado baseada em transações_. Consiste em contas e aplicativos que executam transações que estão mudando o seu estado. Os dados globais com informações sobre cada conta e contrato são armazenados em uma árvore de banco de dados chamado estado. Isso é tratado pelo cliente da camada de execução (EL) e inclui: - Saldos de conta e nonces - Código do contrato e armazenamento - Dados relacionados ao consenso, por exemplo, Contrato de Depósito de Staking -Para interagir com a rede, verificar e produzir novos blocos, os clientes Ethereum precisam acompanhar as mudanças mais recentes (a ponta da cadeia) e, portanto, o estado atual. Um cliente da camada de execução configurado como um nó completo verifica e segue o último estado da rede, mas apenas armazena em cache os últimos estados, por exemplo, o estado associado aos últimos 128 blocos, para ele que possa lidar com a reorganização da cadeia e fornecer acesso rápido a dados recentes. O estado recente é o que todos os clientes precisam para verificar as transações recebidas e usar a rede. +Para interagir com a rede, verificar e produzir novos blocos, os clientes Ethereum precisam acompanhar as mudanças mais recentes (a ponta da cadeia) e, portanto, o estado atual. Um cliente da camada de execução configurado como um nó completo verifica e segue o estado mais recente da rede, mas armazena em cache apenas alguns dos estados passados, por exemplo, o estado associado aos últimos 128 blocos, para que possa lidar com as reorganizações da cadeia e fornecer acesso rápido aos dados recentes. O estado recente é o que todos os clientes precisam para verificar as transações recebidas e usar a rede. Você pode imaginar o estado como uma captura de rede em um determinado bloco e o arquivo como uma repetição do histórico. -Os estados históricos podem ser podados com segurança porque não são necessários para operar a rede e, seria inútil para o cliente manter todos os dados desatualizados. Os estados que existiam antes de algum bloco recente (por exemplo, 128 blocos antes da ponta) são efetivamente jogados fora. Os nós completos só mantêm dados históricos da blockchain (blocos e transações) e capturas históricas ocasionais, que eles podem usar para regenerar estados mais antigos mediante solicitação. Eles fazem isso reexecutando transações passadas no EVM, que podem ser computacionalmente rigorosos quando o estado desejado está longe da imagem instantânea mais próxima. +Os estados históricos podem ser podados com segurança porque não são necessários para operar a rede e, seria inútil para o cliente manter todos os dados desatualizados. Estados que existiram antes de um bloco recente (por exemplo, 128 blocos antes do cabeçalho) são efetivamente descartados. Os nós completos só mantêm dados históricos da blockchain (blocos e transações) e capturas históricas ocasionais, que eles podem usar para regenerar estados mais antigos mediante solicitação. Eles fazem isso reexecutando transações passadas no EVM, que podem ser computacionalmente rigorosos quando o estado desejado está longe da imagem instantânea mais próxima. No entanto, isso significa que acessar um estado histórico em um nó completo consome muita computação. O cliente pode precisar executar todas as transações passadas e calcular um estado histórico desde a origem. Os nós de arquivo resolvem isso armazenando não apenas os estados mais recentes, mas cada estado histórico criado após cada bloco. Basicamente, isso implica um compromisso com um maior requisito de espaço em disco. @@ -35,10 +35,10 @@ O uso regular do Ethereum, como envio de transações, implantação de contrato O principal benefício do arquivo de estado é um acesso rápido a consultas sobre estados históricos. Por exemplo, o nó de arquivo retornaria prontamente resultados como: -- _Qual era o saldo da conta ETH 0x1337... no bloco 15537393?_ +- _Qual era o saldo de ETH da conta 0x1337... no bloco 15537393?_ - _Qual é o saldo do token 0x no contrato 0x no bloco 1920000?_ -Conforme explicado acima, um nó completo precisaria gerar esses dados pela execução do EVM, que usa a CPU e leva tempo. Os nós de arquivo os acessam no disco e fornecem respostas imediatamente. Esse recurso é útil para certas partes da infraestrutura, por exemplo: +Conforme explicado acima, um nó completo precisaria gerar esses dados pela execução do EVM, que usa a CPU e leva tempo. Os nós de arquivo os acessam no disco e servem respostas imediatamente. Este é um recurso útil para certas partes da infraestrutura, por exemplo: - Provedores de serviços como exploradores de blocos - Pesquisadores @@ -46,35 +46,36 @@ Conforme explicado acima, um nó completo precisaria gerar esses dados pela exec - Desenvolvedores de Dapp - Auditoria e conformidade -Existem vários [serviços](/developers/docs/nodes-and-clients/nodes-as-a-service/) gratuitos que também permitem acesso a dados históricos. Como é mais exigente administrar um nó de arquivo, esse acesso é, na maioria das vezes, limitado e funciona apenas para acesso ocasional. Se o seu projeto requer acesso constante a dados históricos, considere a possibilidade de executar um você mesmo. +Existem vários [serviços](/developers/docs/nodes-and-clients/nodes-as-a-service/) gratuitos que também permitem o acesso a dados históricos. Como é mais exigente administrar um nó de arquivo, esse acesso é, na maioria das vezes, limitado e funciona apenas para acesso ocasional. Se o seu projeto requer acesso constante a dados históricos, considere a possibilidade de executar um você mesmo. ## Implementações e uso O nó de arquivo, neste contexto, significa dados servidos pelos clientes da camada de execução voltados para o usuário, enquanto eles lidam com o banco de dados de estado e fornecem pontos de extremidade JSON-RPC. As opções de configuração, tempo de sincronização e tamanho do banco de dados podem variar conforme o cliente. Para mais detalhes, consulte a documentação fornecida pelo seu cliente. -Antes de iniciar seu próprio nó de arquivo, aprenda sobre as diferenças entre os clientes e especialmente os vários [requisitos de hardware](/developers/docs/nodes-and-clients/run-a-node/#requirements). A maioria dos clientes não é otimizada para esse recurso e seus arquivos exigem mais de 12 TB de espaço. Por outro lado, implementações como Erigon podem armazenar os mesmos dados em menos de 3 TB, o que as torna a forma mais eficaz de executar um nó de arquivo. +Antes de iniciar seu próprio nó de arquivo, aprenda sobre as diferenças entre os clientes e especialmente os vários [requisitos de hardware](/developers/docs/nodes-and-clients/run-a-node/#requirements). A maioria dos clientes não estão otimizados para este recurso e seus arquivos exigem mais de 12 TB de espaço. Por outro lado, implementações como Erigon podem armazenar os mesmos dados em menos de 3 TB, o que as torna a forma mais eficaz de executar um nó de arquivo. ## Práticas recomendadas -Além das [recomendações gerais para executar um nó](/developers/docs/nodes-and-clients/run-a-node/), um nó de arquivo pode exigir mais hardware e manutenção. Considerando as [principais funcionalidades](https://github.com/ledgerwatch/erigon#key-features) do Erigon, a abordagem mais prática é usar a implementação cliente do [Erigon](/developers/docs/nodes-and-clients/#erigon). +Além das [recomendações gerais para executar um nó](/developers/docs/nodes-and-clients/run-a-node/), um nó de arquivo pode exigir mais hardware e manutenção. Considerando os [principais recursos](https://github.com/ledgerwatch/erigon#key-features) do Erigon, a abordagem mais prática é usar a implementação do cliente [Erigon](/developers/docs/nodes-and-clients/#erigon). ### Hardware -Sempre verifique os requisitos de hardware para um determinado modo na documentação de um cliente. O maior requisito para nós de arquivo é o espaço em disco. Dependendo do cliente, varia de 3 TB a 12 TB. Mesmo que o HDD possa ser considerado uma solução melhor para grandes quantidades de dados, sincronizá-lo e atualizar constantemente o topo da cadeia exigirá unidades SSD. As unidades [SATA](https://www.cleverfiles.com/help/sata-hard-drive.html) são boas o suficiente, mas devem ser de qualidade confiável, pelo menos [TLC](https://blog.synology.com/tlc-vs-qlc-ssds-what-are-the-differences). Os discos podem ser inseridos em um computador ou servidor com slots suficientes. Esses dispositivos dedicados são ideais para executar um nó de alto tempo de atividade. É totalmente possível executá-lo em um laptop, mas a portabilidade virá com um custo adicional. +Sempre verifique os requisitos de hardware para um determinado modo na documentação de um cliente. +O maior requisito para nós de arquivo é o espaço em disco. Dependendo do cliente, varia de 3 TB a 12 TB. Mesmo que o HDD possa ser considerado uma solução melhor para grandes quantidades de dados, sincronizá-lo e atualizar constantemente o topo da cadeia exigirá unidades SSD. Unidades [SATA](https://www.cleverfiles.com/help/sata-hard-drive.html) são boas o suficiente, mas devem ser de qualidade confiável, pelo menos [TLC](https://blog.synology.com/tlc-vs-qlc-ssds-what-are-the-differences). Os discos podem ser inseridos em um computador ou servidor com slots suficientes. Esses dispositivos dedicados são ideais para executar um nó de alto tempo de atividade. É totalmente possível executá-lo em um laptop, mas a portabilidade virá com um custo adicional. -Todos os dados precisam se encaixar em um volume, portanto, os discos devem estar unidos, por exemplo, com [RAID0](https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_0) ou LVM. Também pode valer a pena considerar o uso de [ZFS](https://en.wikipedia.org/wiki/ZFS), pois ele suporta "Copy-on-write", que garante que os dados sejam gravados corretamente no disco sem quaisquer erros de baixo nível. +Todos os dados precisam caber em um único volume, portanto, os discos precisam ser unidos, por exemplo, com [RAID0](https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_0) ou LVM. Também pode valer a pena considerar o uso de [ZFS](https://en.wikipedia.org/wiki/ZFS), pois ele suporta "Copy-on-write", que garante que os dados sejam gravados corretamente no disco sem erros de baixo nível. -Para obter mais estabilidade e segurança na prevenção de corrupção acidental do banco de dados, especialmente em uma configuração profissional, considere usar [memória ECC](https://en.wikipedia.org/wiki/ECC_memory) se o seu sistema a suportar. O tamanho de RAM é geralmente recomendado para ser o mesmo de um nó completo, mas mais RAM pode ajudar a acelerar a sincronização. +Para maior estabilidade e segurança na prevenção da corrupção acidental do banco de dados, especialmente em uma configuração profissional, considere o uso de [memória ECC](https://en.wikipedia.org/wiki/ECC_memory) se o seu sistema for compatível. O tamanho de RAM é geralmente recomendado para ser o mesmo de um nó completo, mas mais RAM pode ajudar a acelerar a sincronização. Durante a sincronização inicial, os clientes no modo arquivo executarão todas as transações desde a origem. A velocidade de execução é limitada principalmente pela CPU, portanto, uma CPU mais rápida pode ajudar com o tempo de sincronização inicial. Em um computador de consumo médio, a sincronização inicial pode levar até um mês. ## Leitura adicional {#further-reading} -- [Nó completo Ethereum vs Nó de arquivo](https://www.quicknode.com/guides/infrastructure/ethereum-full-node-vs-archive-node) — *QuickNode, setembro de 2022* -- [Construindo seu próprio nó de arquivo Ethereum](https://tjayrush.medium.com/building-your-own-ethereum-archive-node-72c014affc09) — _Thomas Jay Rush, agosto de 2021_ -- [Como configurar Erigon, o RPC do Erigon e TrueBlocks (extração e API) como serviços](https://magnushansson.xyz/blog_posts/crypto_defi/2022-01-10-Erigon-Trueblocks) _– Magnus Hansson, atualizado em setembro de 2022_ +- [Nó completo Ethereum vs Nó de arquivamento](https://www.quicknode.com/guides/infrastructure/ethereum-full-node-vs-archive-node) - _QuickNode, setembro de 2022_ +- [Construindo seu próprio nó de arquivamento Ethereum](https://tjayrush.medium.com/building-your-own-ethereum-archive-node-72c014affc09) - _Thomas Jay Rush, agosto de 2021_ +- [Como configurar Erigon, o RPC do Erigon e TrueBlocks (scrape e API) como serviços](https://magnushansson.xyz/blog_posts/crypto_defi/2022-01-10-Erigon-Trueblocks) _– Magnus Hansson, atualizado em setembro de 2022_ ## Tópicos relacionados {#related-topics} -- [ Nós e clientes](/developers/docs/nodes-and-clients/) +- [Nós e clientes](/developers/docs/nodes-and-clients/) - [Executando um nó](/developers/docs/nodes-and-clients/run-a-node/) diff --git a/public/content/translations/pt-br/developers/docs/nodes-and-clients/bootnodes/index.md b/public/content/translations/pt-br/developers/docs/nodes-and-clients/bootnodes/index.md index 20511b0ae30..172fee784da 100644 --- a/public/content/translations/pt-br/developers/docs/nodes-and-clients/bootnodes/index.md +++ b/public/content/translations/pt-br/developers/docs/nodes-and-clients/bootnodes/index.md @@ -1,6 +1,6 @@ --- -title: Introdução aos bootnodes Ethereum -description: As informações básicas de que você precisa para entender os bootnodes +title: "Introdução aos bootnodes Ethereum" +description: "As informações básicas de que você precisa para entender os bootnodes" lang: pt-br --- @@ -8,7 +8,7 @@ Quando um novo nó se junta à rede Ethereum, ele precisa se conectar aos nós q ## Conectar-se a um bootnode {#connect-to-a-bootnode} -A maioria dos clientes tem uma lista de bootnodes construídos, mas você também pode querer executar seu próprio bootnode ou usar um que não faça parte da lista codificada do cliente. Nesse caso, você pode especificá-los ao iniciar seu cliente, como a seguir (este exemplo é para Geth. Verifique a documentação do seu cliente): +A maioria dos clientes tem uma lista de bootnodes embutida, mas você também pode querer executar seu próprio bootnode, ou usar um que não faz parte da lista codificada do cliente. Nesse caso, você pode especificá-los ao iniciar seu cliente, como a seguir (este exemplo é para Geth. Verifique a documentação do seu cliente): ``` geth --bootnodes "enode://@:" @@ -16,9 +16,9 @@ geth --bootnodes "enode://@:" ## Executar um bootnode {#run-a-bootnode} -Bootnodes são nós completos que não estão por trás de um NAT ([Conversão de Endereços de Rede](https://www.geeksforgeeks.org/network-address-translation-nat/)). Cada nó completo pode atuar como um bootnode, desde que esteja disponível publicamente. +Bootnodes são nós completos que não estão por trás de um NAT ([Tradução de Endereços de Rede](https://www.geeksforgeeks.org/network-address-translation-nat/)). Cada nó completo pode atuar como um bootnode, desde que esteja disponível publicamente. -Quando você inicia um nó, ele deve registrar o seu [enode](/developers/docs/networking-layer/network-addresses/#enode), que é um identificador público que outras pessoas podem usar para se conectar ao seu nó. +Quando você inicia um nó, ele deve registrar seu [enode](/developers/docs/networking-layer/network-addresses/#enode), que é um identificador público que outras pessoas podem usar para se conectar ao seu nó. Normalmente, o enode é regenerado a cada reinicialização, portanto, verifique a documentação do seu cliente sobre como gerar um enode persistente para o seu bootnode. @@ -26,6 +26,6 @@ Para ter um bom bootnode, recomenda-se aumentar o número máximo de pares que p ## Bootnodes disponíveis {#available-bootnodes} -Uma lista de bootnodes integrados ao go-ethereum pode ser encontrada [aqui](https://github.com/ethereum/go-ethereum/blob/master/params/bootnodes.go#L23). Esses bootnodes são mantidos pela Ethereum Foundation e pela equipe go-ethereum. +Uma lista de bootnodes integrados no go-ethereum pode ser encontrada [aqui](https://github.com/ethereum/go-ethereum/blob/master/params/bootnodes.go#L23). Esses bootnodes são mantidos pela Ethereum Foundation e pela equipe go-ethereum. Existem outras listas de bootnodes mantidas por voluntários disponíveis. Certifique-se de sempre incluir pelo menos um bootnode oficial, caso contrário, você poderá sofrer um ataque eclipse. diff --git a/public/content/translations/pt-br/developers/docs/nodes-and-clients/client-diversity/index.md b/public/content/translations/pt-br/developers/docs/nodes-and-clients/client-diversity/index.md index 6afc3cddb5d..27b79d91ec1 100644 --- a/public/content/translations/pt-br/developers/docs/nodes-and-clients/client-diversity/index.md +++ b/public/content/translations/pt-br/developers/docs/nodes-and-clients/client-diversity/index.md @@ -1,6 +1,6 @@ --- title: Diversidade dos clientes -description: Uma explicação de alto nível sobre a importância da diversidade de clientes do Ethereum. +description: "Uma explicação de alto nível sobre a importância da diversidade de clientes do Ethereum." lang: pt-br sidebarDepth: 2 --- @@ -9,7 +9,7 @@ O comportamento de um nó Ethereum é controlado pelo software do cliente que el ## Pré-requisitos {#prerequisites} -Se você ainda não entende o que são nós e clientes, confira [nós e clientes](/developers/docs/nodes-and-clients/). As camadas de [execução](/glossary/#execution-layer) e [consenso](/glossary/#consensus-layer) estão definidas no glossário. +Se você ainda não entende o que são nós e clientes, confira [nós e clientes](/developers/docs/nodes-and-clients/). As camadas de [execução](/glossary/#execution-layer) e de [consenso](/glossary/#consensus-layer) são definidas no glossário. ## Por que existem vários clientes? {#why-multiple-clients} @@ -25,13 +25,13 @@ Um bug em um cliente individual é um risco menor para a rede ao representar uma ### Resiliência a ataques {#resilience} -A diversidade de clientes também oferece resiliência a ataques. Por exemplo, um ataque que [engana um determinado cliente](https://twitter.com/vdWijden/status/1437712249926393858) em um determinado ramo da cadeia, provavelmente não será bem-sucedido porque é improvável que outros clientes sejam explorados da mesma forma e a cadeia canônica permanece incorruptível. A baixa diversidade de clientes aumenta o risco associado a um hack no cliente dominante. A diversidade de clientes já provou ser uma defesa importante contra ataques maliciosos na rede, por exemplo, o ataque de negação de serviço do Shanghai em 2016 foi possível porque os invasores foram capazes de enganar o cliente dominante (Geth) para executar uma operação lenta de E/S de disco dezenas de milhares de vezes por bloco. Como clientes alternativos também estavam online e não compartilharam a vulnerabilidade, o Ethereum foi capaz de resistir ao ataque e continuar operando enquanto a vulnerabilidade no Geth foi corrigida. +A diversidade de clientes também oferece resiliência a ataques. Por exemplo, um ataque que [engana um determinado cliente](https://twitter.com/vdWijden/status/1437712249926393858) em um determinado ramo da cadeia tem poucas chances de ser bem-sucedido, pois é improvável que outros clientes sejam exploráveis da mesma forma e a cadeia canônica permanece incorrupta. A baixa diversidade de clientes aumenta o risco associado a um hack no cliente dominante. A diversidade de clientes já provou ser uma defesa importante contra ataques maliciosos na rede, por exemplo, o ataque de negação de serviço de Xangai em 2016 foi possível porque os invasores conseguiram enganar o cliente dominante (Geth) para executar uma operação lenta de E/S de disco dezenas de milhares de vezes por bloco. Como clientes alternativos também estavam online e não compartilharam a vulnerabilidade, o Ethereum foi capaz de resistir ao ataque e continuar operando enquanto a vulnerabilidade no Geth foi corrigida. ### Finalidade da prova de participação {#finality} Um erro em um cliente de consenso com mais de 33% dos nós Ethereum poderia impedir a finalização da camada de consenso, e isso deixaria os utilizadores em dúvida com respeito à probabilidade de as transações não serem revertidas ou alteradas em algum momento. Isso seria muito problemático para muitos dos aplicativos construídos em cima do Ethereum, particularmente o DeFi. - Pior ainda, um bug crítico em um cliente com uma maioria de dois terços poderia fazer com que a cadeia se dividisse e finalizasse incorretamente, gerando um grande conjunto de validadores que ficam presos em uma cadeia inválida. Se quiserem voltar a integrar à cadeia correta, esses validadores enfrentam cortes ou uma lenta e cara retirada e reativação voluntária. A magnitude de uma escala de remoção com o número de nós culpáveis com uma maioria de dois terços reduzido ao máximo (32 ETH). + Pior ainda, um bug crítico em um cliente com uma maioria de dois terços poderia fazer com que a cadeia se dividisse e finalizasse incorretamente, levando a um grande conjunto de validadores que ficariam presos em uma cadeia inválida. Se quiserem voltar a integrar à cadeia correta, esses validadores enfrentam cortes ou uma lenta e cara retirada e reativação voluntária. A magnitude de uma escala de remoção com o número de nós culpáveis com uma maioria de dois terços reduzido ao máximo (32 ETH). Embora estes sejam cenários improváveis, o ecossistema Ethereum pode mitigar seus riscos nivelando a distribuição de clientes entre os nós ativos. Idealmente, nenhum cliente de consenso chegaria a uma participação de 33% dos nós totais. @@ -39,45 +39,66 @@ Embora estes sejam cenários improváveis, o ecossistema Ethereum pode mitigar s Há também um custo humano para ter a maioria dos clientes. Isso coloca excesso de tensão e responsabilidade em uma pequena equipe de desenvolvimento. Quanto menor a diversidade de clientes, maior a carga de responsabilidade para os desenvolvedores que mantêm a maioria dos clientes. Promover essa responsabilidade em várias equipes é bom tanto para a saúde da rede de nós do Ethereum quanto para sua rede de pessoas. -## Diversidade do cliente atual {#current-client-diversity} +## Diversidade atual de clientes {#current-client-diversity} -![Gráfico de pizza mostrando a diversidade do cliente](./client-diversity.png) _Dados do diagrama de [ethernodes.org](https://ethernodes.org) e [clientdiversity.org](https://clientdiversity.org/)_ +### Clientes de Execução {#execution-clients-breakdown} -Os dois gráficos de pizza acima mostram imagens da diversidade atual do cliente para as camadas de execução e consenso (no momento da escrita em janeiro de 2022). A camada de execução é dominada esmagadoramente por [Geth](https://geth.ethereum.org/), com [Open Ethereum](https://openethereum.github.io/) a um segundo de distância, [Erigon](https://github.com/ledgerwatch/erigon) em terceiro e [Nethermind](https://nethermind.io/) em quarto, com outros clientes compostos por menos de 1% da rede. O cliente mais comumente usado na camada de consenso – [Prysm](https://prysmaticlabs.com/#projects) – não é tão dominante quanto o Geth, mas ainda representa mais de 60% da rede. [Lighthouse](https://lighthouse.sigmaprime.io/) e [Teku](https://consensys.net/knowledge-base/ethereum-2/teku/) compõem ~20% e ~14% respectivamente, e outros clientes são raramente usados. + -Os dados da camada de execução foram obtidos de [Ethernodes](https://ethernodes.org) em 23 de janeiro de 2022. Os dados para clientes de consenso foram obtidos de [Michael Sproul](https://github.com/sigp/blockprint). Os dados dos clientes de consenso são mais difíceis de obter porque os clientes da camada de consenso nem sempre têm traços inequívocos que possam ser utilizados para identificá-los. Os dados foram gerados usando um algoritmo de classificação que confunde às vezes alguns dos clientes minoritários (consulte [aqui](https://twitter.com/sproulM_/status/1440512518242197516) para obter mais detalhes). No diagrama acima, essas classificações ambíguas são tratadas com um rótulo (por exemplo, Nimbus/Teku). No entanto, é claro que a maior parte da rede está executando o Prysm. Os dados são um retrato sobre um conjunto fixo de blocos (neste caso, blocos Beacon nos espaços 2048001 a 2164916) e o domínio do Prysm às vezes foi maior, excedendo 68%. Apesar de serem apenas capturas, os valores no diagrama fornecem uma boa noção geral do estado atual da diversidade do cliente. +### Clientes de Consenso {#consensus-clients-breakdown} -Os dados da diversidade do cliente atualizados para a camada de consenso agora estão disponíveis em [clientdiversity.org](https://clientdiversity.org/). + -## Camada de execução {#execution-layer} - -Até agora, a conversação em torno da diversidade do cliente tem se concentrado principalmente na camada de consenso. No entanto, o cliente de execução [Geth](https://geth.ethereum.org) atualmente representa cerca de 85% de todos os nós. Essa porcentagem é problemática pelos mesmos motivos dos clientes de consenso. Por exemplo, um bug no Geth afetando a manipulação de transações ou a construção de cargas de execução pode fazer com que clientes de consenso finalizem transações problemáticas ou com bugs. Portanto, o Ethereum seria mais saudável com uma distribuição mais uniforme dos clientes de execução, idealmente sem nenhum cliente representando mais de 33% da rede. +Este diagrama pode estar desatualizado — acesse [ethernodes.org](https://ethernodes.org) e [clientdiversity.org](https://clientdiversity.org) para obter informações atualizadas. -## Use um cliente minoritário {#use-minority-client} +Os dois gráficos de pizza acima mostram um panorama da diversidade atual de clientes para as camadas de execução e de consenso (no momento da redação, em outubro de 2025). A diversidade de clientes melhorou ao longo dos anos, e a camada de execução viu uma redução no domínio do [Geth](https://geth.ethereum.org/), com o [Nethermind](https://www.nethermind.io/nethermind-client) em segundo lugar, o [Besu](https://besu.hyperledger.org/) em terceiro e o [Erigon](https://github.com/ledgerwatch/erigon) em quarto, com outros clientes compreendendo menos de 3% da rede. O cliente mais comumente usado na camada de consenso — [Lighthouse](https://lighthouse.sigmaprime.io/) — está bem próximo do segundo mais usado. [Prysm](https://prysmaticlabs.com/#projects) e [Teku](https://consensys.net/knowledge-base/ethereum-2/teku/) representam ~31% e ~14%, respectivamente, e outros clientes são raramente usados. -Endereçar a diversidade do cliente requer mais do que usuários individuais para escolher clientes minoritários – requer pools de mineração/validadores e instituições como os principais dapps e exchanges para mudar também os clientes. No entanto, todos os usuários podem fazer sua parte para reparar o desequilíbrio atual e normalizar o uso de todo o software Ethereum disponível. Após A Fusão, todos os operadores de nó serão obrigados a executar um cliente de execução e um cliente de consenso. Escolher combinações dos clientes sugeridos abaixo ajudará a aumentar a diversidade do cliente. +Os dados da camada de execução foram obtidos de [supermajority.info](https://supermajority.info/) em 26 de outubro de 2025. Os dados para clientes de consenso foram obtidos de [Michael Sproul](https://github.com/sigp/blockprint). Os dados dos clientes de consenso são mais difíceis de obter porque os clientes da camada de consenso nem sempre têm traços inequívocos que possam ser utilizados para identificá-los. Os dados foram gerados usando um algoritmo de classificação que às vezes confunde alguns dos clientes minoritários (veja mais detalhes [aqui](https://twitter.com/sproulM_/status/1440512518242197516)). No diagrama acima, essas classificações ambíguas são tratadas com um rótulo do tipo ou/ou (p. ex., Nimbus/Teku). No entanto, é claro que a maior parte da rede está executando o Prysm. Apesar de serem apenas capturas, os valores no diagrama fornecem uma boa noção geral do estado atual da diversidade do cliente. -### Clientes de execução {#execution-clients} +Dados atualizados sobre a diversidade de clientes para a camada de consenso estão agora disponíveis em [clientdiversity.org](https://clientdiversity.org/). -[Besu](https://www.hyperledger.org/use/besu) - -[Nethermind](https://downloads.nethermind.io/) - -[Erigon](https://github.com/ledgerwatch/erigon) +## Camada de execução {#execution-layer} -[Go-Ethereum](https://geth.ethereum.org/) +Até agora, a conversação em torno da diversidade do cliente tem se concentrado principalmente na camada de consenso. No entanto, o cliente de execução [Geth](https://geth.ethereum.org) representa atualmente cerca de 85% de todos os nós. Essa porcentagem é problemática pelos mesmos motivos dos clientes de consenso. Por exemplo, um bug no Geth afetando a manipulação de transações ou a construção de cargas de execução pode fazer com que clientes de consenso finalizem transações problemáticas ou com bugs. Portanto, o Ethereum seria mais saudável com uma distribuição mais uniforme dos clientes de execução, idealmente sem nenhum cliente representando mais de 33% da rede. -### Clientes de consenso {#consensus-clients} +## Use um cliente minoritário {#use-minority-client} -[Nimbus](https://nimbus.team/) +Endereçar a diversidade do cliente requer mais do que usuários individuais para escolher clientes minoritários – requer pools de validadores e instituições como os principais dapps e exchanges para mudar também os clientes. No entanto, todos os usuários podem fazer sua parte para reparar o desequilíbrio atual e normalizar o uso de todo o software Ethereum disponível. Após A Fusão, todos os operadores de nó serão obrigados a executar um cliente de execução e um cliente de consenso. Escolher combinações dos clientes sugeridos abaixo ajudará a aumentar a diversidade do cliente. -[Lighthouse](https://github.com/sigp/lighthouse) +### Clientes de execução {#execution-clients} -[Teku](https://consensys.net/knowledge-base/ethereum-2/teku/) +- [Besu](https://www.hyperledger.org/use/besu) +- [Nethermind](https://downloads.nethermind.io/) +- [Erigon](https://github.com/ledgerwatch/erigon) +- [Go-Ethereum](https://geth.ethereum.org/) +- [Reth](https://reth.rs/) -[Lodestar](https://github.com/ChainSafe/lodestar) +### Clientes de consenso {#consensus-clients} -[Prysm](https://prysm.offchainlabs.com/docs/) +- [Nimbus](https://nimbus.team/) +- [Lighthouse](https://github.com/sigp/lighthouse) +- [Teku](https://consensys.io/teku) +- [Lodestar](https://github.com/ChainSafe/lodestar) +- [Prysm](https://prysm.offchainlabs.com/docs/) +- [Grandine](https://docs.grandine.io/) Os usuários técnicos podem ajudar a acelerar esse processo escrevendo mais tutoriais e documentações para clientes minoritários e encorajando seus pares operacionais de nó a migrar para longe dos clientes dominantes. Guias para mudar para um cliente de consenso minoritário estão disponíveis em [clientdiversity.org](https://clientdiversity.org/). @@ -88,7 +109,9 @@ Vários painéis fornecem estatísticas de diversidade de cliente em tempo real **Camada de consenso:** - [Rated.network](https://www.rated.network/) -- [clientdiversity.org](https://clientdiversity.org/) **Camada de execução:** +- [clientdiversity.org](https://clientdiversity.org/) + +**Camada de execução:** - [supermajority.info](https://supermajority.info//) - [Ethernodes](https://ethernodes.org/) @@ -96,14 +119,14 @@ Vários painéis fornecem estatísticas de diversidade de cliente em tempo real ## Leitura adicional {#further-reading} - [Diversidade de clientes na camada de consenso do Ethereum](https://mirror.xyz/jmcook.eth/S7ONEka_0RgtKTZ3-dakPmAHQNPvuj15nh0YGKPFriA) -- [A Fusão do Ethereume: execute o cliente majoritário por sua conta e risco!](https://dankradfeist.de/ethereum/2022/03/24/run-the-majority-client-at-your-own-peril.html) – _Dankrad Fest, 24 de março de 2022_ -- [Importância da diversidade de cliente](https://our.status.im/the-importance-of-client-diversity/) -- [Lista dos serviços de nós Ethereum](https://ethereumnodes.com/) -- ["Cinco porquês" do problema da diversidade de clientes](https://notes.ethereum.org/@afhGjrKfTKmksTOtqhB9RQ/BJGj7uh08) +- [Ethereum Merge: Use o cliente majoritário por sua conta e risco!](https://dankradfeist.de/ethereum/2022/03/24/run-the-majority-client-at-your-own-peril.html) – _Dankrad Fiest, 24 de março de 2022_ +- [Importância da diversidade de clientes](https://our.status.im/the-importance-of-client-diversity/) +- [Lista de serviços de nós Ethereum](https://ethereumnodes.com/) +- [Os "Cinco Porquês" do problema da diversidade de clientes](https://notes.ethereum.org/@afhGjrKfTKmksTOtqhB9RQ/BJGj7uh08) - [Diversidade do Ethereum e como resolvê-la (YouTube)](https://www.youtube.com/watch?v=1hZgCaiqwfU) - [clientdiversity.org](https://clientdiversity.org/) ## Tópicos relacionados {#related-topics} -- [Executando um nó Ethereum](/run-a-node/) +- [Execute um nó Ethereum](/run-a-node/) - [Nós e clientes](/developers/docs/nodes-and-clients/) diff --git a/public/content/translations/pt-br/developers/docs/nodes-and-clients/index.md b/public/content/translations/pt-br/developers/docs/nodes-and-clients/index.md index 7b84fb8b028..ef65a88db65 100644 --- a/public/content/translations/pt-br/developers/docs/nodes-and-clients/index.md +++ b/public/content/translations/pt-br/developers/docs/nodes-and-clients/index.md @@ -1,6 +1,6 @@ --- -title: Nós e clientes -description: Uma visão geral dos nós do Ethereum e do software do cliente, além de como configurar um nó e por que você deve fazer isso. +title: " Nós e clientes" +description: "Uma visão geral dos nós do Ethereum e do software do cliente, além de como configurar um nó e por que você deve fazer isso." lang: pt-br sidebarDepth: 2 --- @@ -9,9 +9,9 @@ O Ethereum é uma rede distribuída de computadores (conhecidos como nós) execu ## Pré-requisitos {#prerequisites} -Você deve entender o conceito de uma rede peer-to-peer e os conceitos básicos [do EVM](/developers/docs/evm/) antes de mergulhar mais fundo e executar a sua própria instância de um cliente Ethereum. Veja nossa [introdução ao Ethereum](/developers/docs/intro-to-ethereum/). +Você deve entender o conceito de uma rede ponto a ponto e os [fundamentos da EVM](/developers/docs/evm/) antes de se aprofundar e executar sua própria instância de um cliente Ethereum. Dê uma olhada em nossa [introdução ao Ethereum](/developers/docs/intro-to-ethereum/). -Se você é novo no tema dos nós, recomendamos primeiro verificar nossa introdução amigável no [rodando um nó Ethereum](/run-a-node). +Se você é novo no tópico de nós, recomendamos primeiro conferir nossa introdução amigável sobre [como executar um nó do Ethereum](/run-a-node). ## O que são nós e clientes? {#what-are-nodes-and-clients} @@ -20,40 +20,44 @@ Um "nó" é qualquer instância de software do cliente Ethereum que esteja conec - O cliente de execução (também conhecido como Execution Engine, cliente EL ou anteriormente cliente Eth1) ouve novas transações transmitidas na rede, executa-as na EVM e mantém o estado mais recente e o banco de dados de todos os dados atuais do Ethereum. - O cliente de consenso (também conhecido como Beacon Node, cliente CL ou anteriormente cliente Eth2) implementa o algoritmo de consenso de prova de participação, o qual permite que a rede realize um acordo com base nos dados validados do cliente de execução. Há também um terceiro pedaço de software, conhecido como 'validador' que pode ser adicionado ao cliente de consenso, permitindo que um nó participe na segurança da rede. -Estes clientes trabalham juntos para manter rastreabilidade da cabeça da cadeia Ethereum e permitir usuários interagir com a rede Ethereum. O desenho modular com várias peças de software trabalhando em conjunto é chamado de [complexidade encapsulada](https://vitalik.eth.limo/general/2022/02/28/complexity.html). Esta abordagem facilitou executar o [The Merge](/roadmap/merge) perfeitamente, faz softwares clientes mais fáceis de manter e desenvolver, e permite reusar clientes individuais, por exemplo, no [ecossistema camada 2](/layer-2/). +Estes clientes trabalham juntos para manter rastreabilidade da cabeça da cadeia Ethereum e permitir usuários interagir com a rede Ethereum. O design modular com várias peças de software trabalhando juntas é chamado de [complexidade encapsulada](https://vitalik.eth.limo/general/2022/02/28/complexity.html). Essa abordagem tornou mais fácil executar [A Fusão](/roadmap/merge) de forma transparente, facilita a manutenção e o desenvolvimento do software do cliente e permite a reutilização de clientes individuais, por exemplo, no [ecossistema de camada 2](/layer-2/). -![Execução de acoplamento e clientes de consenso](./eth1eth2client.png) Diagrama simplificado de uma execução associada e de um cliente de consenso. +![Clientes de execução e de consenso acoplados](./eth1eth2client.png) +Diagrama simplificado de um cliente de execução e de consenso acoplado. -### Diversidade dos clientes {#client-diversity} +### Diversidade de clientes {#client-diversity} -Tanto [clientes de execução](/developers/docs/nodes-and-clients/#execution-clients) quanto [clientes de consenso](/developers/docs/nodes-and-clients/#consensus-clients) existem em uma variedade de linguagens de programação desenvolvidas por diferentes equipes. +Tanto os [clientes de execução](/developers/docs/nodes-and-clients/#execution-clients) quanto os [clientes de consenso](/developers/docs/nodes-and-clients/#consensus-clients) existem em uma variedade de linguagens de programação desenvolvidas por equipes diferentes. -As implementações de vários clientes podem tornar a rede mais forte, reduzindo sua dependência de uma única base de código. O objetivo ideal é alcançar a diversidade sem que nenhum cliente domine a rede, eliminando assim um ponto único de falha potencial. A variedade de idiomas também convida uma comunidade de desenvolvedores mais ampla e permite que eles criem integrações em seu idioma preferido. +As implementações de vários clientes podem tornar a rede mais forte, reduzindo sua dependência de uma única base de código. O objetivo ideal é alcançar a diversidade sem que nenhum cliente domine a rede, eliminando assim um ponto único de falha potencial. +A variedade de idiomas também convida uma comunidade de desenvolvedores mais ampla e permite que eles criem integrações em seu idioma preferido. -Saiba mais sobre a [diversidade do cliente](/developers/docs/nodes-and-clients/client-diversity/). +Saiba mais sobre a [diversidade de clientes](/developers/docs/nodes-and-clients/client-diversity/). O que essas implementações têm em comum é que todas seguem uma única especificação. As especificações ditam como a rede Ethereum e a cadeia de blocos funcionam. Cada detalhe técnico é definido e as especificações podem ser encontradas como: -- Originalmente, o [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) +- Originalmente, o [Livro Amarelo do Ethereum](https://ethereum.github.io/yellowpaper/paper.pdf) - [Especificações de execução](https://github.com/ethereum/execution-specs/) - [Especificações de consenso](https://github.com/ethereum/consensus-specs) -- [EIPs](https://eips.ethereum.org/) implementados em várias [atualizações de rede](/ethereum-forks/) +- [EIPs](https://eips.ethereum.org/) implementados em várias [melhorias da rede](/ethereum-forks/) -### Rastreamento de nós na rede {#network-overview} +### Rastreando nós na rede {#network-overview} Vários rastreadores oferecem uma visão geral em tempo real dos nós na rede Ethereum. Observe que, devido à natureza das redes descentralizadas, esses rastreadores podem fornecer apenas uma visão limitada da rede e podem relatar resultados diferentes. -- Mapa de nós pela Etherscan -- Ethernodes da Bitfly -- [Nodewatch](https://www.nodewatch.io/) por Chainsafe, rastreando nós de consenso +- [Mapa de nós](https://etherscan.io/nodetracker) da Etherscan +- [Ethernodes](https://ethernodes.org/) da Bitfly +- [Nodewatch](https://www.nodewatch.io/) da Chainsafe, rastreando nós de consenso +- [Monitoreth](https://monitoreth.io/) - da MigaLabs, uma ferramenta de monitoramento de rede distribuída +- [Relatórios Semanais de Saúde da Rede](https://probelab.io) - da ProbeLab, usando o [rastreador Nebula](https://github.com/dennis-tra/nebula) e outras ferramentas ## Tipos de nó {#node-types} -Se você quer [executar o seu próprio nó](/developers/docs/nodes-and-clients/run-a-node/), você deve entender que existem diferentes tipos de nós que consomem dados de modo diferente. Na verdade, os clientes podem executar 3 tipos diferentes de nó: leve, completo e arquivo. Existem também opções de diferentes estratégias de sincronização que permitem um tempo de sincronização mais rápida. A sincronização se refere ao quão rápido ele pode obter as informações mais atualizadas sobre o estado do Ethereum. +Se você quiser [executar seu próprio nó](/developers/docs/nodes-and-clients/run-a-node/), deve entender que existem diferentes tipos de nó que consomem dados de maneiras diferentes. Na verdade, os clientes podem executar 3 tipos diferentes de nó: leve, completo e arquivo. Existem também opções de diferentes estratégias de sincronização que permitem um tempo de sincronização mais rápida. A sincronização se refere ao quão rápido ele pode obter as informações mais atualizadas sobre o estado do Ethereum. ### Nó completo {#full-node} -Nós completos fazem uma validação bloco-a-bloco do blockchain, incluindo baixar e verificar o corpo do bloco e dados de estado para cada bloco. Há diferentes classes de nó completo - algumas começam do bloco gênesis e verificam cada bloco no histórico inteiro do blockchain. Outras começam sua verificação em um bloco mais recente que eles confiam ser válido (por exemplo, o 'snap sync' do Geth). Independente de onde a verificação começa, nós completos somente mantém uma cópia local de dados relativamente recentes (tipicamente os 128 blocos mais recentes), permitindo dados mais antigos serem excluídos para economizar espaço em disco. Dados mais antigos podem ser regerados quando necessário. +Nós completos fazem uma validação bloco-a-bloco do blockchain, incluindo baixar e verificar o corpo do bloco e dados de estado para cada bloco. Existem diferentes classes de nó completo - alguns começam a partir do bloco gênese e verificam cada bloco em todo o histórico da cadeia de blocos. Outros começam a verificação a partir de um bloco mais recente que consideram válido (p. ex., o 'snap sync' do Geth). Independentemente de onde a verificação começa, os nós completos mantêm apenas uma cópia local de dados relativamente recentes (normalmente os 128 blocos mais recentes), permitindo que dados mais antigos sejam excluídos para economizar espaço em disco. Dados mais antigos podem ser regerados quando necessário. - Armazena os dados completos da cadeia de blocos (embora isso seja periodicamente reduzido para que um nó completo não armazene todos os dados de estado de volta à origem) - Participa na validação de bloco, verifica todos os blocos e estados. @@ -64,60 +68,61 @@ Nós completos fazem uma validação bloco-a-bloco do blockchain, incluindo baix Nós de arquivo são nós completos que verificam cada bloco desde o gênese e nunca excluem nada dos dados baixados. -- Armazena tudo o que é mantido no nó completo e constrói um arquivo de estados históricos. Ele é necessário se você quiser consultar algo como um saldo de conta no bloco #4.000.000, ou testar de forma simples e confiável seu próprio conjunto de transações sem minerá-las usando rastreamento. +- Armazena tudo o que é mantido no nó completo e constrói um arquivo de estados históricos. É necessário se você quiser consultar algo como um saldo de conta no bloco #4.000.000, ou simplesmente testar de forma confiável seu próprio conjunto de transações sem validá-las usando rastreamento. - Esses dados representam unidades de terabytes, o que torna os nós de arquivo menos atraentes para usuários comuns, mas pode ser útil para serviços como exploradores de blocos, fornecedores de carteiras e análises da cadeia. Sincronizar clientes em qualquer modo que não seja o de arquivo resultará na remoção de dados da cadeia de blocos. Isso significa que não há arquivo de todo o estado histórico, mas o nó completo é capaz de criá-lo sob demanda. -Saiba mais sobre [Nós de arquivo](/developers/docs/nodes-and-clients/archive-nodes). +Saiba mais sobre [nós de arquivo](/developers/docs/nodes-and-clients/archive-nodes). ### Nó leve {#light-node} -Em vez de baixar cada bloco, nós leves baixam somente os cabeçalhos dos blocos. Esses cabeçalhos contêm informações resumidas sobre o conteúdo dos blocos. Qualquer outra informação necessária pelo nó leve é solicitada de um nó completo. O nó leve pode então verificar de modo independente os dados que ele recebe em relação às raízes de estado nos cabeçalhos de bloco. Os nós leves permitem que os usuários participem da rede Ethereum sem o hardware poderoso ou a alta largura de banda necessária para executar nós completos. Por fim, os nós leves podem ser executados em telefones celulares ou dispositivos embutidos. Os nós leves não participam do consenso (ou seja, eles não podem ser mineradores/validadores), mas podem acessar a cadeia de blocos Ethereum com as mesmas funcionalidades e garantias de segurança de um nó completo. +Em vez de baixar cada bloco, nós leves baixam somente os cabeçalhos dos blocos. Esses cabeçalhos contêm informações resumidas sobre o conteúdo dos blocos. Qualquer outra informação necessária pelo nó leve é solicitada de um nó completo. O nó leve pode então verificar de modo independente os dados que ele recebe em relação às raízes de estado nos cabeçalhos de bloco. Os nós leves permitem que os usuários participem da rede Ethereum sem o hardware poderoso ou a alta largura de banda necessária para executar nós completos. Por fim, os nós leves podem ser executados em telefones celulares ou dispositivos embutidos. Os nós leves não participam do consenso (ou seja, não podem ser validadores), mas podem acessar a cadeia de blocos do Ethereum com a mesma funcionalidade e garantias de segurança que um nó completo. -Clientes leves são uma área de desenvolvimento ativo para o Ethereum e esperamos ver em breve novos clientes leves para a camada de consenso e a camada de execução. Também existem rotas em potencial para fornecer dados de clientes leves pela [rede gossip](https://www.ethportal.net/). Isso é vantajoso porque a rede gossip pode suportar uma rede de nós leves sem exigir nós completos para atender às solicitações. +Clientes leves são uma área de desenvolvimento ativo para o Ethereum e esperamos ver em breve novos clientes leves para a camada de consenso e a camada de execução. +Também existem rotas potenciais para fornecer dados de clientes leves pela [rede gossip](https://www.ethportal.net/). Isso é vantajoso porque a rede gossip pode suportar uma rede de nós leves sem exigir nós completos para atender às solicitações. -O Ethereum ainda não suporta uma grande quantidade de nós leves, mas o suporte a nós leves é uma área que deve se desenvolver rapidamente em um futuro próximo. Em particular, clientes como [Nimbus](https://nimbus.team/), [Hélios](https://github.com/a16z/helios), e [LodeStar](https://lodestar.chainsafe.io/) atualmente estão bastante concentrados em nós leves. +O Ethereum ainda não suporta uma grande quantidade de nós leves, mas o suporte a nós leves é uma área que deve se desenvolver rapidamente em um futuro próximo. Em particular, clientes como [Nimbus](https://nimbus.team/), [Helios](https://github.com/a16z/helios) e [LodeStar](https://lodestar.chainsafe.io/) estão atualmente muito focados em nós leves. ## Por que devo executar um nó Ethereum? {#why-should-i-run-an-ethereum-node} A execução de um nó permite que você use o Ethereum de forma direta, confiável e privada, enquanto dá suporte à rede, mantendo-a mais robusta e descentralizada. -### Vantagens para você {#benefits-to-you} +### Benefícios para você {#benefits-to-you} A execução de seu próprio nó permite que você use o Ethereum de maneira privada, autossuficiente e confiável. Você não precisa confiar na rede porque você pode verificar os dados por conta própria com seu cliente. “Não confie, verifique” é um mantra popular da cadeia de blocos. - Seu nó verifica todas as transações e blocos contra as regras de consenso por si só. Isso significa que você não precisa confiar em nenhum outro nó da rede nem confiar totalmente neles. -- Você pode usar uma carteira Ethereum com seu próprio nó. Você pode usar dapps com mais segurança e privacidade porque você não precisará vazar seus endereços e saldos para intermediários. Tudo pode ser verificado com seu próprio cliente. [MetaMask](https://metamask.io), [Frame](https://frame.sh/) e [muitas outras carteiras](/wallets/find-wallet/) oferecem importação de RPC, permitindo que elas usem seu nó. +- Você pode usar uma carteira Ethereum com seu próprio nó. Você pode usar dapps com mais segurança e privacidade porque você não precisará vazar seus endereços e saldos para intermediários. Tudo pode ser verificado com seu próprio cliente. [MetaMask](https://metamask.io), [Frame](https://frame.sh/) e [muitas outras carteiras](/wallets/find-wallet/) oferecem importação de RPC, permitindo que usem seu nó. - Você pode executar e auto-hospedar outros serviços que dependem de dados do Ethereum. Por exemplo, isso pode ser um validador Beacon Chain, software como camada 2, infraestrutura, exploradores de bloco, processadores de pagamento etc. -- Você pode fornecer seus próprios [pontos de extremidade RPC](/developers/docs/apis/json-rpc/) personalizados. Você pode até oferecer endpoints publicamente para a comunidade para ajudá-los a evitar fornecedores grandes centralizados. -- Você pode se conectar ao seu nó usando **Comunicações entre processos (IPC)** ou reescrever o nó para carregar seu programa como um plugin. Isso garante baixa latência, o que ajuda muito, por exemplo, ao processar muitos dados usando bibliotecas Web3 ou quando você precisa substituir suas transações o mais rápido possível (isto é, de forma acelerada). -- Você pode colocar ETH diretamente para proteger a rede e ganhar recompensas. Veja [participação solo](/staking/solo/) para começar. +- Você pode fornecer seus próprios [endpoints de RPC](/developers/docs/apis/json-rpc/) personalizados. Você pode até oferecer endpoints publicamente para a comunidade para ajudá-los a evitar fornecedores grandes centralizados. +- Você pode se conectar ao seu nó usando **Comunicações entre processos (IPC)** ou reescrever o nó para carregar seu programa como um plugin. Isso garante baixa latência, o que ajuda muito, por exemplo, ao processar muitos dados usando bibliotecas web3 ou quando você precisa substituir suas transações o mais rápido possível (ou seja, frontrunning). +- Você pode colocar ETH diretamente para proteger a rede e ganhar recompensas. Veja [staking solo](/staking/solo/) para começar. -![Como você acessar o Ethereum através do seu aplicativo e nós](./nodes.png) +![Como você acessa o Ethereum por meio de seu aplicativo e nós](./nodes.png) ### Benefícios da rede {#network-benefits} Um conjunto diversificado de nós é importante para a integridade, segurança e resiliência operacional do Ethereum. - Os nós completos impõem as regras de consenso para que não possam ser induzidos a aceitar blocos que não as seguem. Isso fornece segurança extra na rede, pois se todos os nós fossem nós leves, que não fazem a verificação completa, os validadores poderiam atacar a rede. -- No caso de um ataque que supere as defesas criptoeconômicas de [prova de participação](/developers/docs/consensus-mechanisms/pos/#what-is-pos), uma recuperação social pode ser realizada por nós completos escolhendo seguir a cadeia honesta. +- No caso de um ataque que supere as defesas criptoeconômicas da [prova de participação](/developers/docs/consensus-mechanisms/pos/#what-is-pos), uma recuperação social pode ser realizada por nós completos que escolherem seguir a cadeia honesta. - Mais nós na rede resultam em uma rede mais diversificada e robusta, o objetivo final da descentralização, que permite um sistema confiável e resistente à censura. -- Nós completos fornecem acesso a dados do blockchain para clientes leves que dependem disso. Os nós leves não armazenam toda a cadeia de blocos. Em vez disso, eles verificam dados por meio das [raízes do estado nos cabeçalhos de blocos](/developers/docs/blocks/#block-anatomy). Eles podem solicitar mais informações dos nós completos, se precisarem. +- Nós completos fornecem acesso a dados do blockchain para clientes leves que dependem disso. Nós leves não armazenam toda a cadeia de blocos, em vez disso, eles verificam dados por meio das [raízes de estado nos cabeçalhos de bloco](/developers/docs/blocks/#block-anatomy). Eles podem solicitar mais informações dos nós completos, se precisarem. Se você rodar um nó completo, toda a rede Ethereum se beneficia dele, mesmo se você não rodar um validador. -## Executando seu próprio nó {#running-your-own-node} +## Executar seu próprio nó {#running-your-own-node} Interessado em executar o seu próprio cliente Ethereum? -Para ver uma introdução simplificada para iniciantes, visite a nossa página [Executar um nó](/run-a-node) para saber mais. +Para uma introdução amigável para iniciantes, visite nossa página [executar um nó](/run-a-node) para saber mais. -Se você é mais que um usuário técnico, mergulhe em mais detalhes e opções sobre como [executar o seu próprio nó](/developers/docs/nodes-and-clients/run-a-node/). +Se você for um usuário mais técnico, mergulhe em mais detalhes e opções sobre como [criar seu próprio nó](/developers/docs/nodes-and-clients/run-a-node/). ## Alternativas {#alternatives} -Configurar seu próprio nó pode custar tempo e recursos, mas nem sempre você precisa executar sua própria instância. Nesse caso, é possível usar um provedor de APIs externo. Para obter uma visão geral do uso desses serviços, confira [nós como serviço](/developers/docs/nodes-and-clients/nodes-as-a-service/). +Configurar seu próprio nó pode custar tempo e recursos, mas nem sempre você precisa executar sua própria instância. Nesse caso, é possível usar um provedor de APIs externo. Para uma visão geral do uso desses serviços, confira [nós como serviço](/developers/docs/nodes-and-clients/nodes-as-a-service/). Se alguém executar um nó do Ethereum com uma API pública em sua comunidade, você pode apontar suas carteiras para um nó da comunidade por meio de um RPC personalizado. @@ -125,20 +130,20 @@ Por outro lado, se você executar um cliente, você pode compartilhá-lo com que ## Clientes de execução {#execution-clients} -A comunidade do Ethereum mantém vários clientes de execução (previamente conhecidos como clientes “Eth1”, ou apenas “clientes Ethereum”) de código aberto, desenvolvidos por diferentes equipes usando diferentes linguagens de programação. Isso torna a rede mais forte e [diversificada](/developers/docs/nodes-and-clients/client-diversity/). O objetivo ideal é alcançar a diversidade sem que nenhum cliente predomine, a fim de reduzir os pontos únicos de falha. +A comunidade do Ethereum mantém vários clientes de execução (previamente conhecidos como clientes “Eth1”, ou apenas “clientes Ethereum”) de código aberto, desenvolvidos por diferentes equipes usando diferentes linguagens de programação. Isso torna a rede mais forte e mais [diversa](/developers/docs/nodes-and-clients/client-diversity/). O objetivo ideal é alcançar a diversidade sem que nenhum cliente predomine, a fim de reduzir os pontos únicos de falha. -Essa tabela resume os diferentes clientes. Todos eles passam por [testes de cliente](https://github.com/ethereum/tests) e são mantidos ativamente para ter as atualizações de rede em dia. +Essa tabela resume os diferentes clientes. Todos eles passam nos [testes de cliente](https://github.com/ethereum/tests) e são mantidos ativamente para se manterem atualizados com as melhorias da rede. -| Client | Linguagem de programação | Sistemas operacionais | Redes | Estratégias de sincronização | Limpeza de estado | -| ------------------------------------------------------------------------ | ------------------------ | --------------------- | -------------------------------- | ----------------------------------------------------------------------- | ----------------- | -| [Geth](https://geth.ethereum.org/) | Go | Linux, Windows, macOS | Rede principal, Sepolia, Holesky | [Instantânea](#snap-sync), [Completa](#full-sync) | Arquivo, Removido | -| [Nethermind](https://www.nethermind.io/) | C#, .NET | Linux, Windows, macOS | Rede principal, Sepolia, Holesky | [Instantânea](#snap-sync) (sem serviço), Rápida, [Completa](#full-sync) | Arquivo, Removido | -| [Besu](https://besu.hyperledger.org/en/stable/) | Java | Linux, Windows, macOS | Rede principal, Sepolia, Holesky | [Instantânea](#snap-sync), [Rápida](#fast-sync), [Completa](#full-sync) | Arquivo, Removido | -| [Erigon](https://github.com/ledgerwatch/erigon) | Go | Linux, Windows, macOS | Rede principal, Sepolia, Holesky | [Completo](#full-sync) | Arquivo, Removido | -| [Reth](https://reth.rs/) | Rust | Linux, Windows, macOS | Rede principal, Sepolia, Holesky | [Completo](#full-sync) | Arquivo, Removido | -| [EthereumJS](https://github.com/ethereumjs/ethereumjs-monorepo) _(beta)_ | TypeScript | Linux, Windows, macOS | Sepolia, Holesky | [Completo](#full-sync) | Removido | +| Client | Linguagem de programação | Sistemas operacionais | Redes | Estratégias de sincronização | State pruning | +| ------------------------------------------------------------------------------------------- | ------------------------ | --------------------- | -------------------------------- | ---------------------------------------------------------------------------------- | ----------------- | +| [Geth](https://geth.ethereum.org/) | Go | Linux, Windows, macOS | Rede Principal, Sepolia, Holesky | [Snap](#snap-sync), [Completa](#full-sync) | Arquivo, Removido | +| [Nethermind](https://www.nethermind.io/) | C#, .NET | Linux, Windows, macOS | Rede Principal, Sepolia, Holesky | [Snap](#snap-sync) (sem servir), Rápida, [Completa](#full-sync) | Arquivo, Removido | +| [Besu](https://besu.hyperledger.org/en/stable/) | Java | Linux, Windows, macOS | Rede Principal, Sepolia, Holesky | [Snap](#snap-sync), [Rápida](#fast-sync), [Completa](#full-sync) | Arquivo, Removido | +| [Erigon](https://github.com/ledgerwatch/erigon) | Go | Linux, Windows, macOS | Rede Principal, Sepolia, Holesky | [Completa](#full-sync) | Arquivo, Removido | +| [Reth](https://reth.rs/) | Rust | Linux, Windows, macOS | Rede Principal, Sepolia, Holesky | [Completa](#full-sync) | Arquivo, Removido | +| [EthereumJS](https://github.com/ethereumjs/ethereumjs-monorepo) _(beta)_ | TypeScript | Linux, Windows, macOS | Sepolia, Holesky | [Completa](#full-sync) | Removido | -Para saber mais sobre redes suportadas, leia sobre as [redes Ethereum](/developers/docs/networks/). +Para saber mais sobre as redes compatíveis, leia sobre as [redes Ethereum](/developers/docs/networks/). Cada cliente tem casos de uso e vantagens exclusivas, então você deve escolher um com base nas suas próprias preferências. A diversidade permite que as implementações se concentrem em diferentes recursos e públicos de usuários. Você pode escolher um cliente baseado em recursos, suporte, linguagem de programação ou licenças. @@ -156,7 +161,7 @@ Erigon, anteriormente conhecido como Turbo-Geth, começou como uma bifurcação Go Ethereum (Geth, para abreviar) é uma das implementações originais do protocolo Ethereum. Atualmente, ele é o cliente mais difundido, com a maior base de usuários e variedade de ferramentas para usuários e desenvolvedores. Ele está escrito em Go, é totalmente de código aberto e sob licença GNU LGPL v3. -Saiba mais sobre Geth em sua [documentação](https://geth.ethereum.org/docs/). +Saiba mais sobre o Geth em sua [documentação](https://geth.ethereum.org/docs/). ### Nethermind {#nethermind} @@ -166,7 +171,7 @@ Nethermind é uma implementação do Ethereum criada com a pilha de tecnologia C - acesso ao estado - rede e recursos avançados, como painéis Prometheus/Grafana, suporte a registro de logs com Seq. Enterprise, rastreamento JSON-RPC e plugins de análise. -Nethermind também tem uma [documentação detalhada](https://docs.nethermind.io), um suporte eficaz ao desenvolvedor, uma comunidade online e suporte 24 horas por dia disponível para usuários Premium. +O Nethermind também tem [documentação detalhada](https://docs.nethermind.io), forte suporte para desenvolvedores, uma comunidade online e suporte 24/7 disponível para usuários premium. ### Reth {#reth} @@ -174,7 +179,7 @@ O Reth (abreviação de Rust Ethereum) é uma implementação de nó completo do O Reth está pronto para produção e é adequado para uso em ambientes de essenciais, como staking ou serviços que exigem um tempo de atividade alto. Apresenta bom desempenho em casos de uso em que é necessário alto desempenho com grandes margens, como RPC, MEV, indexação, simulações e atividades P2P. -Para saber mais, consulte o [Reth Book](https://reth.rs/) ou o repositório [Reth GitHub](https://github.com/paradigmxyz/reth?tab=readme-ov-file#reth). +Saiba mais consultando o [Reth Book](https://reth.rs/) ou o [repo GitHub do Reth](https://github.com/paradigmxyz/reth?tab=readme-ov-file#reth). ### Em desenvolvimento {#execution-in-development} @@ -184,37 +189,38 @@ Esses clientes ainda estão em estágios iniciais de desenvolvimento e ainda nã O cliente de execução EthereumJS (EthereumJS) foi escrito em TypeScript e é composto de vários pacotes, incluindo os principais primitivos do Ethereum representados pelas classes Block, Transaction e Merkle-Patricia Trie e os principais componentes do cliente, incluindo uma implementação da Máquina Virtual do Ethereum (EVM), uma classe de blockchain, e a pilha de rede DevP2P. -Saiba mais sobre ele lendo a [documentação](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master) correspondente +Saiba mais sobre ele lendo sua [documentação](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master) ## Clientes de consenso {#consensus-clients} -Existem vários clientes de consenso (anteriormente conhecidos como clientes “Eth2”) para oferecer suporte às [atualizações de consenso](/roadmap/beacon-chain/). Eles são responsáveis por toda lógica de consenso, incluindo o algoritmo de escolha de fork, atestados de processamento e gerenciamento de recompensas e penalidades [proof-of-stake](/developers/docs/consensus-mechanisms/pos). +Existem vários clientes de consenso (anteriormente conhecidos como clientes 'Eth2') para dar suporte às [melhorias de consenso](/roadmap/beacon-chain/). Eles são responsáveis por toda a lógica relacionada ao consenso, incluindo o algoritmo de escolha de bifurcação, o processamento de atestações e o gerenciamento de recompensas e penalidades da [prova de participação](/developers/docs/consensus-mechanisms/pos). -| Cliente | Linguagem de programação | Sistemas operacionais | Redes | -| ------------------------------------------------------------- | ------------------------ | --------------------- | -------------------------------------------------------------- | -| [Lighthouse](https://lighthouse.sigmaprime.io/) | Rust | Linux, Windows, macOS | Beacon Chain, Goerli, Pyrmont, Sepolia, Ropsten e mais | -| [Lodestar](https://lodestar.chainsafe.io/) | TypeScript | Linux, Windows, macOS | Beacon Chain, Goerli, Sepolia, Ropsten e mais | -| [Nimbus](https://nimbus.team/) | Nim | Linux, Windows, macOS | Beacon Chain, Goerli, Sepolia, Ropsten e mais | -| [Prysm](https://prysm.offchainlabs.com/docs/) | Go | Linux, Windows, macOS | Beacon Chain, Gnosis, Goerli, Pyrmont, Sepolia, Ropsten e mais | -| [Teku](https://consensys.net/knowledge-base/ethereum-2/teku/) | Java | Linux, Windows, macOS | Beacon Chain, Gnosis, Goerli, Sepolia, Ropsten e mais | +| Client | Linguagem de programação | Sistemas operacionais | Redes | +| ------------------------------------------------------------- | ------------------------ | --------------------- | ------------------------------------------------------ | +| [Lighthouse](https://lighthouse.sigmaprime.io/) | Rust | Linux, Windows, macOS | Beacon Chain, Holesky, Pyrmont, Sepolia e mais | +| [Lodestar](https://lodestar.chainsafe.io/) | TypeScript | Linux, Windows, macOS | Beacon Chain, Holesky, Sepolia e mais | +| [Nimbus](https://nimbus.team/) | Nim | Linux, Windows, macOS | Beacon Chain, Holesky, Sepolia e mais | +| [Prysm](https://prysm.offchainlabs.com/docs/) | Go | Linux, Windows, macOS | Beacon Chain, Gnosis, Holesky, Pyrmont, Sepolia e mais | +| [Teku](https://consensys.net/knowledge-base/ethereum-2/teku/) | Java | Linux, Windows, macOS | Beacon Chain, Gnosis, Holesky, Sepolia e mais | +| [Grandine](https://docs.grandine.io/) | Rust | Linux, Windows, macOS | Beacon Chain, Holesky, Sepolia e mais | ### Lighthouse {#lighthouse} Lighthouse é uma implementação de cliente de consenso escrita em Rust sob licença Apache-2.0. Ele é mantido pela Sigma Prime e tem estado estável e pronto para produção desde a origem da Beacon Chain. Ele é utilizado por várias empresas, pools de participação (staking) e indivíduos. Ela visa ser segura, eficiente e interoperável em uma ampla variedade de ambientes, de PCs desktop a implantações automatizadas sofisticadas. -A documentação está disponível no [Livro da Lighthouse](https://lighthouse-book.sigmaprime.io/) +A documentação pode ser encontrada no [Lighthouse Book](https://lighthouse-book.sigmaprime.io/) ### Lodestar {#lodestar} Lodestar é uma implementação de cliente de consenso pronta para produção escrita em Typescript sob a licença LGPL-3.0. Ele é mantido pela ChainSafe Systems e é o mais novo dos clientes de consenso para participantes-solo (solo-stakers), desenvolvedores e pesquisadores. A Lodestar consiste em um nó beacon e um cliente validador alimentado por implementações JavaScript de protocolos Ethereum. O Lodestar visa melhorar a usabilidade do Ethereum com clientes leves, expandir a acessibilidade a um grupo maior de desenvolvedores e contribuir ainda mais para a diversidade do ecossistema. -Mais informações podem ser encontradas em nosso [site da Lodestar](https://lodestar.chainsafe.io/) +Mais informações podem ser encontradas no [site do Lodestar](https://lodestar.chainsafe.io/). ### Nimbus {#nimbus} Nimbus é uma implementação de cliente de consenso escrita em Nim sob a licença Apache-2.0. Ele é um cliente pronto para produção em uso por participantes-solo e pools de participação (staking). A Nimbus foi projetada para eficiência de recursos, facilitando a execução em dispositivos com recursos restritos e infraestrutura corporativa com a mesma facilidade, sem comprometer a estabilidade ou o desempenho da recompensa. Uma memória de recursos mais leve significa que o cliente tem uma maior margem de segurança quando a rede está sob estresse. -Saiba mais na [documentação da Nimbus](https://nimbus.guide/) +Saiba mais na [documentação do Nimbus](https://nimbus.guide/) ### Prysm {#prysm} @@ -226,17 +232,23 @@ Visite a [documentação do Prysm](https://prysm.offchainlabs.com/docs/) para sa Teku é um dos clientes originais da origem da Beacon Chain. Além dos objetivos habituais (segurança, robustez, estabilidade, usabilidade, desempenho), o Teku visa especificamente cumprir integralmente todos os padrões de cliente de consenso. -O Teku oferece opções de implantação muito flexíveis. O nó beacon e o cliente validador podem ser executados juntos como um único processo, o que é extremamente conveniente para participantes solo (solo stakers), ou os nós podem ser executados separadamente para operações de participação sofisticadas. Além disso, o Teku é totalmente interoperável com o [Web3Signer](https://github.com/ConsenSys/web3signer/) para proteger as chaves de assinatura e protegê-las contra remoções. +O Teku oferece opções de implantação muito flexíveis. O nó beacon e o cliente validador podem ser executados juntos como um único processo, o que é extremamente conveniente para participantes solo (solo stakers), ou os nós podem ser executados separadamente para operações de participação sofisticadas. Além disso, o Teku é totalmente interoperável com o [Web3Signer](https://github.com/ConsenSys/web3signer/) para segurança da chave de assinatura e proteção contra slashing. O Teku é escrito em Java e sob a licença Apache 2.0. Ele é desenvolvido pela equipe de Protocolos da ConsenSys, que também é responsável pelo Besu e Web3Signer. Saiba mais na [documentação do Teku](https://docs.teku.consensys.net/en/latest/). +### Grandine {#grandine} + +Grandine é uma implementação de cliente de consenso, escrita em Rust sob a licença GPL-3.0. É mantido pela Equipe Central da Grandine e é rápido, de alto desempenho e leve. Ele atende a uma ampla gama de stakers, desde stakers solo utilizando dispositivos de baixa capacidade, como o Raspberry Pi, até grandes instituições que operam dezenas de milhares de validadores. + +A documentação pode ser encontrada no [Grandine Book](https://docs.grandine.io/) + ## Modos de sincronização {#sync-modes} Para acompanhar e verificar os dados atuais na rede, o cliente Ethereum precisa sincronizar com o estado da rede mais recente. Para isso, é necessário baixar dados de pares, verificar criptograficamente sua integridade e construir um banco de dados local da cadeia de blocos. Os modos de sincronização representam diferentes abordagens para esse processo com várias compensações. Os clientes também variam em sua implementação de algoritmos de sincronização. Sempre consulte a documentação oficial do cliente escolhido para obter detalhes sobre a implementação. -### Modos de sincronização na camada de execução {#execution-layer-sync-modes} +### Modos de sincronização da camada de execução {#execution-layer-sync-modes} A camada de execução pode ser executada em diferentes modos para se adequar a diferentes casos de uso, desde a reexecução do estado geral da blockchain até a sincronização apenas com a parte inicial da cadeia a partir de um ponto de verificação confiável. @@ -247,7 +259,7 @@ Uma sincronização completa faz o download de todos os blocos (incluindo cabeç - Minimiza a confiança e oferece a mais alta segurança, verificando cada transação. - Com um número crescente de transações, pode levar dias ou semanas para processar todas as transações. -Os [nós de arquivo](#archive-node) realizam uma sincronização completa para criar (e manter) um histórico completo das alterações de estado feitas por cada transação em cada bloco. +[Nós de arquivo](#archive-node) realizam uma sincronização completa para construir (e manter) um histórico completo das alterações de estado feitas por cada transação em cada bloco. #### Sincronização rápida {#fast-sync} @@ -256,14 +268,14 @@ Assim como uma sincronização completa, uma sincronização rápida baixa todos - Estratégia de sincronização rápida. - Reduz a demanda de processamento em favor do uso da largura de banda. -#### Sincronização instantânea {#snap-sync} +#### Sincronização Snap {#snap-sync} As sincronizações instantâneas também verificam a cadeia bloco a bloco. No entanto, em vez de começar no bloco de gênese, uma sincronização instantânea começa em um ponto de verificação "confiável" mais recente conhecido por fazer parte da verdadeira blockchain. O nó grava pontos de checagem periódicos enquanto exclui dados mais velhos que uma certa idade. Esses instantâneos são usados para regenerar os dados de estado conforme necessário, em vez de armazená-los para sempre. - Estratégia de sincronização mais rápida, atualmente padrão na rede principal Ethereum. - Economiza muito uso de disco e largura de banda de rede sem sacrificar a segurança. -[Mais sobre sincronização instantânea](https://github.com/ethereum/devp2p/blob/master/caps/snap.md). +[Mais sobre a sincronização Snap](https://github.com/ethereum/devp2p/blob/master/caps/snap.md). #### Sincronização leve {#light-sync} @@ -272,30 +284,30 @@ O modo cliente leve baixa todos os cabeçalhos de bloco, dados de bloco e verifi - Obtém apenas o estado mais recente, enquanto conta com a confiança dos desenvolvedores e o mecanismo de consenso. - Cliente pronto para uso com o estado atual da rede em poucos minutos. -**NB** A sincronização leve ainda não funciona com a prova de participação do Ethereum — novas versões de sincronização leve deverão ser lançadas em breve! +**OBS.:** a sincronização leve ainda não funciona com o Ethereum de prova de participação - novas versões da sincronização leve devem ser lançadas em breve! [Mais sobre clientes leves](/developers/docs/nodes-and-clients/light-clients/) -### Modos de sincronização de camada de consenso {#consensus-layer-sync-modes} +### Modos de sincronização da camada de consenso {#consensus-layer-sync-modes} #### Sincronização otimista {#optimistic-sync} -A sincronização otimista é uma estratégia de sincronização pós-fusão projetada para ser compatível por aceitação (opt-in) e com versões anteriores, permitindo que os nós de execução sincronizem por meio de métodos estabelecidos. O mecanismo de execução pode, de modo _otimista_, importar blocos beacon sem verificá-los completamente, encontrar o cabeçalho mais recente e começar a sincronizar a cadeia com os métodos acima. Em seguida, após a atualização do cliente de execução, ele informará ao cliente de consenso sobre a validade das transações na Beacon Chain. +A sincronização otimista é uma estratégia de sincronização pós-fusão projetada para ser compatível por aceitação (opt-in) e com versões anteriores, permitindo que os nós de execução sincronizem por meio de métodos estabelecidos. O mecanismo de execução pode importar blocos beacon _otimisticamente_ sem verificá-los totalmente, encontrar o cabeçalho mais recente e, em seguida, começar a sincronizar a cadeia com os métodos acima. Em seguida, após a atualização do cliente de execução, ele informará ao cliente de consenso sobre a validade das transações na Beacon Chain. -[Mais sobre sincronização otimista](https://github.com/ethereum/consensus-specs/blob/master/sync/optimistic.md) +[Mais sobre a sincronização otimista](https://github.com/ethereum/consensus-specs/blob/dev/sync/optimistic.md) -#### Sincronização de ponto de verificação {#checkpoint-sync} +#### Sincronização de checkpoint {#checkpoint-sync} -Uma sincronização de ponto de verificação, também conhecida como sincronização de subjetividade fraca, cria uma experiência de usuário superior para a sincronização de um Beacon Node. Ela se baseia em suposições de [subjetividade fraca](/developers/docs/consensus-mechanisms/pos/weak-subjectivity/) que permitem a sincronização da Beacon Chain a partir de um ponto de verificação recente de subjetividade fraca em vez da gênese. As sincronizações de ponto de verificação tornam o tempo de sincronização inicial significativamente mais rápido com suposições de confiança semelhantes às da sincronização de [gênese](/glossary/#genesis-block). +Uma sincronização de ponto de verificação, também conhecida como sincronização de subjetividade fraca, cria uma experiência de usuário superior para a sincronização de um Beacon Node. É baseada em suposições de [subjetividade fraca](/developers/docs/consensus-mechanisms/pos/weak-subjectivity/) que permitem sincronizar a Beacon Chain a partir de um checkpoint recente de subjetividade fraca, em vez do bloco gênese. Sincronizações de checkpoint tornam o tempo de sincronização inicial significativamente mais rápido, com suposições de confiança semelhantes às da sincronização a partir do [bloco gênese](/glossary/#genesis-block). Na prática, isso significa que seu nó se conecta a um serviço remoto para baixar os estados finalizados recentes e continua verificando os dados a partir desse ponto. O terceiro que fornece os dados é confiável e deve ser escolhido com cuidado. -Mais sobre [sincronização do ponto de verificação](https://notes.ethereum.org/@djrtwo/ws-sync-in-practice) +Mais sobre [sincronização de checkpoint](https://notes.ethereum.org/@djrtwo/ws-sync-in-practice) ## Leitura adicional {#further-reading} -- [Ethereum 101 – Parte 2 – Entendendo os nós](https://kauri.io/ethereum-101-part-2-understanding-nodes/48d5098292fd4f11b251d1b1814f0bba/a) _–Wil Barnes, 13 de fevereiro de 2019_ -- [Executando nós completos do Ethereum: um guia para os pouco motivados](https://medium.com/@JustinMLeroux/running-ethereum-full-nodes-a-guide-for-the-barely-motivated-a8a13e7a0d31) _— Justin Leroux, 7 de novembro de 2019_ +- [Ethereum 101 - Parte 2 - Entendendo os Nós](https://kauri.io/ethereum-101-part-2-understanding-nodes/48d5098292fd4f11b251d1b1814f0bba/a) _– Wil Barnes, 13 de fevereiro de 2019_ +- [Executando Nós Completos de Ethereum: Um Guia para os Pouco Motivados](https://medium.com/@JustinMLeroux/running-ethereum-full-nodes-a-guide-for-the-barely-motivated-a8a13e7a0d31) _– Justin Leroux, 7 de novembro de 2019_ ## Tópicos relacionados {#related-topics} @@ -304,4 +316,4 @@ Mais sobre [sincronização do ponto de verificação](https://notes.ethereum.or ## Tutoriais relacionados {#related-tutorials} -- [Transforme seu Raspberry Pi 4 em um nó validador apenas instalando o cartão MicroSD – Guia de instalação](/developers/tutorials/run-node-raspberry-pi/) _– Ligue seu Raspberry Pi 4, conecte um cabo Ethernet, conecte o disco SSD e ligue o dispositivo para transformar o Raspberry Pi 4 em um nó Ethereum completo executando a camada de execução (Rede principal) e/ou a camada de consenso (Beacon Chain / validador)._ +- [Transforme seu Raspberry Pi 4 em um nó validador simplesmente gravando a imagem no cartão MicroSD – Guia de instalação](/developers/tutorials/run-node-raspberry-pi/) _– Grave a imagem no seu Raspberry Pi 4, conecte um cabo de ethernet, conecte o disco SSD e ligue o dispositivo para transformar o Raspberry Pi 4 em um nó completo do Ethereum, executando a camada de execução (Rede Principal) e/ou a camada de consenso (Beacon Chain / validador)._ diff --git a/public/content/translations/pt-br/developers/docs/nodes-and-clients/light-clients/index.md b/public/content/translations/pt-br/developers/docs/nodes-and-clients/light-clients/index.md index 5ed3da6c93c..ef90a8aeed8 100644 --- a/public/content/translations/pt-br/developers/docs/nodes-and-clients/light-clients/index.md +++ b/public/content/translations/pt-br/developers/docs/nodes-and-clients/light-clients/index.md @@ -1,6 +1,6 @@ --- title: Clientes leves -description: Introdução aos clientes leves Ethereum. +description: "Introdução aos clientes leves Ethereum." lang: pt-br --- @@ -12,7 +12,7 @@ Um nó leve é um nó executando um software de cliente leve. Em vez de manter c ## Como funcionam os clientes leves? {#how-do-light-clients-work} -Quando o Ethereum começou a usar um mecanismo de consenso baseado em prova de participação, uma nova infraestrutura foi introduzida especificamente para dar suporte a clientes leves. Isso funciona selecionando aleatoriamente um subconjunto de 512 validadores a cada 1,1 dias para atuar como um **comitê de sincronização**. O comitê de sincronização assina o cabeçalho dos blocos recentes. Cada cabeçalho de bloco contém a assinatura agregada dos validadores no comitê de sincronização e um "bitfield" que mostra quais validadores assinaram e quais não. Cada cabeçalho também inclui uma lista de validadores esperados a participar da assinatura do bloco seguinte. Isso significa que um cliente leve pode ver rapidamente que o comitê de sincronização assinou os dados recebidos, e também pode verificar se o comitê de sincronização é o genuíno, comparando o que ele recebeu em relação ao que era previsto no bloco anterior. Dessa forma, o cliente leve pode continuar atualizando seu conhecimento do último bloco Ethereum, sem realmente baixar o bloco em si, apenas o cabeçalho que contém informações resumidas. +Quando o Ethereum começou a usar um mecanismo de consenso baseado em prova de participação, uma nova infraestrutura foi introduzida especificamente para dar suporte a clientes leves. A forma como funciona é selecionando aleatoriamente um subconjunto de 512 validadores a cada 1,1 dias para atuar como um **comitê de sincronização**. O comitê de sincronização assina o cabeçalho dos blocos recentes. Cada cabeçalho de bloco contém a assinatura agregada dos validadores no comitê de sincronização e um "bitfield" que mostra quais validadores assinaram e quais não. Cada cabeçalho também inclui uma lista de validadores esperados a participar da assinatura do bloco seguinte. Isso significa que um cliente leve pode ver rapidamente que o comitê de sincronização assinou os dados recebidos, e também pode verificar se o comitê de sincronização é o genuíno, comparando o que ele recebeu em relação ao que era previsto no bloco anterior. Dessa forma, o cliente leve pode continuar atualizando seu conhecimento do último bloco Ethereum, sem realmente baixar o bloco em si, apenas o cabeçalho que contém informações resumidas. Na camada de execução não há uma especificação única para um cliente de execução leve. O escopo de um cliente de execução leve pode variar de um "modo leve" de um cliente de execução completo com todas as funcionalidades EVM e de rede de um nó completo. No entanto, ele apenas verifica cabeçalhos de bloco, sem baixar os dados associados, ou pode ser um cliente mais enxuto, que depende muito do encaminhamento de solicitações a um provedor RPC para interagir com o Ethereum. @@ -32,7 +32,7 @@ O principal benefício de clientes leves é permitir que mais pessoas acessem o A capacidade de executar nós Ethereum em dispositivos com armazenamento, memória e poder de processamento muito pequenos é uma das principais áreas de inovação desbloqueadas por clientes leves. Enquanto hoje os nós do Ethereum exigem muitos recursos de computação, os clientes leves podem ser incorporados em navegadores, executados em telefones celulares e talvez até em dispositivos menores, como relógios inteligentes. Isso significa que as carteiras Ethereum com clientes embutidos poderiam funcionar em um telefone celular. Isso significa que as carteiras móveis poderiam ser muito mais descentralizadas, já que elas não teriam que confiar em provedores de dados centralizados para seus dados. -Isso pode ser expandido com a ativação de dispositivos para a **internet das coisas (IoT)**. Um cliente leve pode estar acostumado a provar rapidamente a propriedade de algum saldo de token ou NFT, com todas as garantias de segurança fornecidas pelos comitês de sincronização, disparando alguma ação em uma rede IoT. Imagine um [serviço de aluguel de bicicletas](https://youtu.be/ZHNrAXf3RDE?t=929), que usa um aplicativo com um cliente leve integrado para verificar rapidamente se você possui o NFT do serviço de aluguel e, em caso afirmativo, desbloqueia uma bicicleta para você pedalar! +Uma extensão disso é a habilitação de dispositivos de **Internet das Coisas (IoT)**. Um cliente leve pode estar acostumado a provar rapidamente a propriedade de algum saldo de token ou NFT, com todas as garantias de segurança fornecidas pelos comitês de sincronização, disparando alguma ação em uma rede IoT. Imagine um [serviço de aluguel de bicicletas](https://youtu.be/ZHNrAXf3RDE?t=929) que usa um aplicativo com um cliente leve integrado para verificar rapidamente que você possui o NFT do serviço de aluguel e, em caso afirmativo, destrava uma bicicleta para você sair pedalando! Os rollups do Ethereum também se beneficiariam de clientes leves. Um dos grandes problemas para os rollups são os hacks direcionados às pontes, que permitem a transferência de fundos da rede principal Ethereum para um rollup. Uma vulnerabilidade são os oráculos que os rollups usam para detectar que um usuário fez um depósito na ponte. Se um oráculo fornecer dados ruins, eles poderão enganar o rollup a pensar que houve um depósito para a ponte e liberar fundos incorretamente. Um cliente leve embutido no rollup poderia ser usado para proteger contra oráculos corrompidos, pois o depósito na ponte poderia vir com uma prova que pode ser verificada pelo rollup antes de liberar qualquer token. O mesmo conceito também poderia ser aplicado a outras pontes entre cadeias. @@ -42,20 +42,20 @@ Os clientes leves também poderiam ser usados para atualizar carteiras Ethereum. Existem vários clientes leves em desenvolvimento, incluindo clientes leves de execução, de consenso e de execução/consenso combinados. Estas são as implementações de cliente leve que conhecemos no momento em que escrevemos esta página: -- [Lodestar](https://github.com/ChainSafe/lodestar/tree/unstable/packages/light-client): cliente leve de consenso no TypeScript -- [Helios](https://github.com/a16z/helios): cliente leve de execução e consenso combinado no Rust -- [Geth](https://github.com/ethereum/go-ethereum/tree/master/light): modo leve para cliente de execução (em desenvolvimento) no Go -- [Nimbus](https://nimbus.guide/el-light-client.html): cliente leve de consenso no Nim +- [Lodestar](https://github.com/ChainSafe/lodestar/tree/unstable/packages/light-client): cliente de consenso leve em TypeScript +- [Helios](https://github.com/a16z/helios): cliente leve de execução e consenso combinado em Rust +- [Geth](https://github.com/ethereum/go-ethereum/tree/master/beacon/light): modo leve para cliente de execução (em desenvolvimento) em Go +- [Nimbus](https://nimbus.guide/el-light-client.html): cliente de consenso leve em Nim Até onde sabemos, nenhum deles ainda é considerado pronto para produção. -Também há muito trabalho sendo feito para melhorar as formas pelas quais os clientes leves podem acessar os dados do Ethereum. Atualmente, os clientes leves dependem de solicitações RPC para nós completos usando um modelo cliente/servidor. Porém, no futuro, os dados poderão ser solicitados de maneira mais descentralizada usando uma rede dedicada como o [Portal Network](https://www.ethportal.net/), que pode servir os dados para clientes leves usando um protocolo de propagação ponto a ponto. +Também há muito trabalho sendo feito para melhorar as formas pelas quais os clientes leves podem acessar os dados do Ethereum. Atualmente, os clientes leves dependem de solicitações RPC para nós completos usando um modelo cliente/servidor, mas no futuro os dados poderão ser solicitados de maneira mais descentralizada usando uma rede dedicada como a [Portal Network](https://www.ethportal.net/) que poderia servir os dados para clientes leves usando um protocolo de gossip ponto a ponto. -Outros itens do [roteiro](/roadmap/) como [árvores Verkle](/roadmap/verkle-trees/) e [ausência de estado](/roadmap/statelessness/) acabarão por trazer as garantias de segurança de clientes leves iguais às de clientes completos. +Outros itens do [roteiro](/roadmap/), como árvores Verkle e a [ausência de estado](/roadmap/statelessness/), acabarão por equiparar as garantias de segurança dos clientes leves às dos clientes completos. ## Leitura adicional {#further-reading} -- [Zsolt Felfodhi sobre clientes leves do Geth](https://www.youtube.com/watch?v=EPZeFXau-RE) -- [Etan Kissling sobre redes de clientes leves](https://www.youtube.com/watch?v=85MeiMA4dD8) -- [Etan Kissling sobre clientes leves após o The Merge](https://www.youtube.com/watch?v=ZHNrAXf3RDE) -- [Piper Merriam: A estrada sinuosa rumo a clientes leves e funcionais](https://snakecharmers.ethereum.org/the-winding-road-to-functional-light-clients/) +- [Zsolt Felfodhi sobre os clientes leves Geth](https://www.youtube.com/watch?v=EPZeFXau-RE) +- [Etan Kissling sobre a rede de clientes leves](https://www.youtube.com/watch?v=85MeiMA4dD8) +- [Etan Kissling sobre clientes leves após A Fusão](https://www.youtube.com/watch?v=ZHNrAXf3RDE) +- [Piper Merriam: O caminho sinuoso para clientes leves funcionais](https://snakecharmers.ethereum.org/the-winding-road-to-functional-light-clients/) diff --git a/public/content/translations/pt-br/developers/docs/nodes-and-clients/node-architecture/index.md b/public/content/translations/pt-br/developers/docs/nodes-and-clients/node-architecture/index.md index 67dc5ea5181..360ef33aac3 100644 --- a/public/content/translations/pt-br/developers/docs/nodes-and-clients/node-architecture/index.md +++ b/public/content/translations/pt-br/developers/docs/nodes-and-clients/node-architecture/index.md @@ -1,26 +1,28 @@ --- -title: Arquitetura do nó -description: Introdução de como os nós Ethereum são organizados. +title: "Arquitetura do nó" +description: "Introdução de como os nós Ethereum são organizados." lang: pt-br --- -Um nó Ethereum é composto por dois clientes: um [cliente de execução](/developers/docs/nodes-and-clients/#execution-clients) e um [cliente de consenso](/developers/docs/nodes-and-clients/#consensus-clients). +Um nó do Ethereum é composto por dois clientes: um [cliente de execução](/developers/docs/nodes-and-clients/#execution-clients) e um [cliente de consenso](/developers/docs/nodes-and-clients/#consensus-clients). Para um nó propor um novo bloco, ele também deve executar um [cliente validador](#validators). -Quando o Ethereum estava usando [prova de trabalho](/developers/docs/consensus-mechanisms/pow/), um cliente de execução era suficiente para executar um nó completo Ethereum. No entanto, desde a implementação da [prova de participação](/developers/docs/consensus-mechanisms/pow/), o cliente de execução precisa ser usado com outro software, chamado [“cliente de consenso”](/developers/docs/nodes-and-clients/#consensus-clients). +Quando o Ethereum estava usando [prova de trabalho](/developers/docs/consensus-mechanisms/pow/), um cliente de execução era suficiente para executar um nó completo do Ethereum. No entanto, desde a implementação da [prova de participação](/developers/docs/consensus-mechanisms/pow/), o cliente de execução deve ser usado juntamente com outra parte do software chamada [cliente de consenso](/developers/docs/nodes-and-clients/#consensus-clients). O diagrama abaixo mostra a relação entre os dois clientes Ethereum. Os dois clientes se conectam às suas respectivas redes ponto a ponto (P2P). As redes P2P separadas são necessárias à medida que os clientes de execução espalham transações em sua rede P2P, permitindo que eles gerenciem seu pool de transações local, enquanto os clientes de consenso distribuem blocos em sua rede P2P, permitindo consenso e crescimento da cadeia. -![](node-architecture-text-background.png) +![Diagrama da arquitetura do nó Ethereum mostrando camadas de execução e consenso](node-architecture-text-background.png) -Para que essa estrutura de dois clientes funcione, os clientes de consenso devem ser capazes de passar pacotes de transações para o cliente de execução. Executar transações localmente é como o cliente valida que as transações não violam nenhuma regra do Ethereum e que a atualização proposta para o estado do Ethereum está correta. Da mesma forma, quando o nó é selecionado para ser um produtor de bloco, o cliente de consenso deve ser capaz de solicitar pacotes de transações ao Geth para incluir no novo bloco e executá-los para atualizar o estado global. Essa comunicação entre clientes é tratada por uma conexão RPC local usando a [API engine](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md). +_Tem várias opções para a execução do cliente, incluindo Erigon, Nethermind e Besu_. + +Para esta estrutura de dois clientes funcionar, os clientes consensuais devem passar os pacotes de transição ao cliente de execução. O cliente de execução realiza as transações localmente para validar que as transações não violem nenhuma regra do Ethereum e que a atualização proposta para o estado do Ethereum esteja correta. Quando um node é selecionado para ser um produtor de blocos sua instância de cliente de consenso solicita pacotes de transações do cliente de execução para incluir no novo bloco e executa-los para atualizar o estado global. O cliente de consenso aciona o cliente de execução por meio de uma conexão RPC local usando a [Engine API](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md). ## O que o cliente de execução faz? {#execution-client} -O cliente de execução é responsável pelo tratamento de transações, transmissão de transações, gerenciamento de estado e suporte à Máquina Virtual Ethereum ([EVM](/developers/docs/evm/)). No entanto, ele **não** é responsável pela construção de blocos, transmissão de blocos ou tratamento da lógica de consenso. Eles estão no âmbito do cliente de consenso. +O cliente de execução é responsável pela validação, manuseio e disseminação de transações, juntamente com o gerenciamento de estado e o suporte à máquina virtual ethereum ([EVM](/developers/docs/evm/)). Ele **não** é responsável pela construção de blocos, pela transmissão de blocos ou pelo tratamento da lógica de consenso. Eles estão no âmbito do cliente de consenso. -O cliente de execução cria payloads (cargas) de execução — a lista de transações, triagem de estado atualizada e outros dados relacionados à execução. Os clientes de consenso incluem o payload em cada bloco. O cliente de execução também é responsável por reexecutar transações em novos blocos, para garantir que eles sejam válidos. A execução das transações é feita no computador embutido do cliente de execução, conhecido como [Máquina Virtual Ethereum (EVM)](/developers/docs/evm). +O cliente de execução cria payloads (cargas) de execução — a lista de transações, triagem de estado atualizada e outros dados relacionados à execução. Os clientes de consenso incluem o payload em cada bloco. O cliente de execução também é responsável por reexecutar transações em novos blocos, para garantir que eles sejam válidos. A execução de transações é feita no computador embutido do cliente de execução, conhecido como a [máquina virtual ethereum (EVM)](/developers/docs/evm/). -O cliente de execução também oferece uma interface de usuário para Ethereum por meio de [métodos RPC](/developers/docs/apis/json-rpc), que permitem aos usuários consultar a blockchain Ethereum, enviar transações e implantar contratos inteligentes. É comum que as chamadas RPC sejam tratadas por uma biblioteca como [Web3js](https://docs.web3js.org/), [Web3py](https://web3py.readthedocs.io/en/v5/) ou por uma interface de usuário, como uma carteira de navegador. +O cliente de execução também oferece uma interface de usuário para o Ethereum por meio de [métodos RPC](/developers/docs/apis/json-rpc) que permitem aos usuários consultar a blockchain do Ethereum, enviar transações e implantar contratos inteligentes. É comum que as chamadas RPC sejam tratadas por uma biblioteca como [Web3js](https://docs.web3js.org/), [Web3py](https://web3py.readthedocs.io/en/v5/) ou por uma interface de usuário, como uma carteira de navegador. Em resumo, o cliente de execução é: @@ -35,23 +37,23 @@ O cliente de consenso não participa do atestado ou da proposta de blocos — is ## Validadores {#validators} -Os operadores de nó podem adicionar um validador aos seus clientes de consenso depositando 32 ETH no contrato de depósito. O cliente validador vem em conjunto com o cliente de consenso e pode ser adicionado a um nó a qualquer momento. O validador trata atestações e propostas de blocos. Eles permitem que um nó acumule recompensas ou perca ETH por meio de penalidades ou remoções. Executar o software do validador também torna um nó qualificado para propor um novo bloco. +Fazer o stake e executar o software de validação torna um nó elegível para ser selecionado para propor um novo bloco. Os operadores de nó podem adicionar um validador aos seus clientes de consenso depositando 32 ETH no contrato de depósito. O cliente validador vem em conjunto com o cliente de consenso e pode ser adicionado a um nó a qualquer momento. O validador trata atestações e propostas de blocos. Ele também permite que um nó acumule recompensas ou perca ETH por meio de penalidades ou cortes. -[Mais sobre staking](/staking/). +[Mais sobre participação](/staking/). ## Comparação de componentes de um nó {#node-comparison} -| Cliente de execução | Cliente de consenso | Validador | -| -------------------------------------------------- | ----------------------------------------------------------------------- | -------------------------------------- | -| Transmissão de transações em sua rede p2p | Transmissão de blocos e atestações em sua rede p2p | Propõe blocos | -| Executa/reexecuta transações | Executa o algoritmo de escolha do fork | Acumula recompensas/penalizações | -| Verifica mudanças de estado recebidas | Mantém o controle da ponta da cadeia | Faz atestações | -| Gerencia tentativas de estado e recibos | Gerencia o estado do Beacon (contém informações de consenso e execução) | Requer 32 ETH para participar em stake | -| Cria payload de execução | Mantém o rastreamento da aleatoriedade acumulada no RANDAO | Pode ser removido | -| Expõe a API JSON-RPC para interagir com o Ethereum | Mantém o rastreamento de justificativa e finalização | | +| Cliente de execução | Cliente de consenso | Validador | +| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | +| Transmissão de transações em sua rede p2p | Transmissão de blocos e atestações em sua rede p2p | Propõe blocos | +| Executa/reexecuta transações | Executa o algoritmo de escolha do fork | Acumula recompensas/penalizações | +| Verifica mudanças de estado recebidas | Mantém o controle da ponta da cadeia | Faz atestações | +| Gerencia tentativas de estado e recibos | Gerencia o estado do Beacon (contém informações de consenso e execução) | Requer 32 ETH para participar em stake | +| Cria payload de execução | Mantém o controle da aleatoriedade acumulada no RANDAO (um algoritmo que fornece aleatoriedade verificável para seleção de validadores e outras operações de consenso) | Pode ser removido | +| Expõe a API JSON-RPC para interagir com o Ethereum | Mantém o rastreamento de justificativa e finalização | | ## Leitura adicional {#further-reading} - [Prova de participação](/developers/docs/consensus-mechanisms/pos) -- [Proposta de bloqueio](/developers/docs/consensus-mechanisms/pos/block-proposal) +- [Proposta de bloco](/developers/docs/consensus-mechanisms/pos/block-proposal) - [Recompensas e penalidades do validador](/developers/docs/consensus-mechanisms/pos/rewards-and-penalties) diff --git a/public/content/translations/pt-br/developers/docs/nodes-and-clients/nodes-as-a-service/index.md b/public/content/translations/pt-br/developers/docs/nodes-and-clients/nodes-as-a-service/index.md index c3c8158aab5..ac64c92f23a 100644 --- a/public/content/translations/pt-br/developers/docs/nodes-and-clients/nodes-as-a-service/index.md +++ b/public/content/translations/pt-br/developers/docs/nodes-and-clients/nodes-as-a-service/index.md @@ -1,23 +1,23 @@ --- -title: Nós como serviço -description: Uma visão inicial dos nós como um serviço, os prós e contras e os provedores mais populares. +title: "Nós como serviço" +description: "Uma visão inicial dos nós como um serviço, os prós e contras e os provedores mais populares." lang: pt-br sidebarDepth: 2 --- ## Introdução {#Introduction} -Executar o seu próprio [nó Ethereum](/developers/docs/nodes-and-clients/#what-are-nodes-and-clients) pode ser desafiador, especialmente quando for iniciado ou escalando rápido. Há [vários serviços](#popular-node-services) que executam a infraestrutura do nó otimizada para você, para que você possa se concentrar no desenvolvimento da sua aplicação ou produto. Vamos explicar como os serviços de nó funcionam, os prós e os contras para usá-los e listar provedores se você estiver interessado em começar. +Executar seu próprio [nó Ethereum](/developers/docs/nodes-and-clients/#what-are-nodes-and-clients) pode ser desafiador, especialmente ao começar ou durante uma escalada rápida. Há [vários serviços](#popular-node-services) que executam infraestruturas de nós otimizadas para você, para que possa se concentrar no desenvolvimento de seu aplicativo ou produto. Vamos explicar como os serviços de nó funcionam, os prós e os contras para usá-los e listar provedores se você estiver interessado em começar. ## Pré-requisitos {#prerequisites} -Se você ainda não sabe o que são os nós e os clientes e como eles funcionam, confira [Nós e clientes](/developers/docs/nodes-and-clients/). +Se você ainda não entende o que são nós e clientes, confira [Nós e clientes](/developers/docs/nodes-and-clients/). -## Participantes {#stakoooooooooooooors} +## Stakers {#stakoooooooooooooors} -Os participantes individuais devem executar sua própria infraestrutura, em vez de depender de provedores de terceiros. Isso significa executar um cliente de execução acoplado a um cliente de consenso. Antes da [Fusão](/roadmap/merge) (The Merge), era possível executar apenas um cliente de consenso e usar um provedor centralizado para dados de execução. Porém, isso não é mais possível: um participante individual deve executar ambos os clientes. No entanto, há serviços disponíveis para facilitar este processo. +Os participantes individuais devem executar sua própria infraestrutura, em vez de depender de provedores de terceiros. Isso significa executar um cliente de execução acoplado a um cliente de consenso. Antes d'[A Fusão](/roadmap/merge), era possível executar apenas um cliente de consenso e usar um provedor centralizado para dados de execução; isso não é mais possível — um staker individual deve executar ambos os clientes. No entanto, há serviços disponíveis para facilitar este processo. -[Leia mais sobre execução de um nó](/developers/docs/nodes-and-clients/run-a-node/). +[Leia mais sobre como executar um nó](/developers/docs/nodes-and-clients/run-a-node/). Os serviços descritos nesta página são para nós não participantes. @@ -25,13 +25,13 @@ Os serviços descritos nesta página são para nós não participantes. Os provedores de nós disponibilizam sua infraestrutura para você não precisar de uma. -Esses serviços são geralmente fornecem uma chave API que você pode usar para gravar e ler as informações dentro da cadeia de blocos. Muitas vezes, incluindo acesso a [redes de testes Ethereum](/developers/docs/networks/#ethereum-testnets) além da rede principal. +Esses serviços são geralmente fornecem uma chave API que você pode usar para gravar e ler as informações dentro da cadeia de blocos. Eles geralmente incluem acesso a [redes de teste da Ethereum](/developers/docs/networks/#ethereum-testnets) além da Mainnet. Alguns serviços oferecem a você o seu próprio nó dedicado que eles gerenciam para você, enquanto outros usam os balanceadores de carga para distribuir atividade entre nós. Quase todos os serviços de nó são extremamente fáceis de integrar, envolvendo uma alteração de linha no seu código para trocar seu nó hospedado, ou até mesmo alternar entre os próprios serviços. -Muitas vezes os serviços de nó executam uma variedade de [clientes de nó](/developers/docs/nodes-and-clients/#execution-clients) e [tipos](/developers/docs/nodes-and-clients/#node-types), permitindo que você acesse nós completos e arquive, além dos métodos específicos do cliente em uma API. +Muitas vezes, os serviços de nó executam uma variedade de [clientes de nó](/developers/docs/nodes-and-clients/#execution-clients) e [tipos](/developers/docs/nodes-and-clients/#node-types), permitindo que você acesse nós completos e de arquivo, além de métodos específicos do cliente em uma única API. É importante notar que os serviços de nós não armazenam nem devem armazenar suas chaves ou informações privadas. @@ -45,14 +45,14 @@ Executar seus próprios nós pode ser muito caro, quer seja de armazenamento, la Usando um serviço nó você está centralizando o aspecto da infraestrutura do seu produto. Por esse motivo, os projetos que dão à descentralização a maior importância podem preferir nós de auto-hospedagem a terceirizar o serviço a terceiros. -Leia mais sobre os [benefícios de executar o seu próprio nó](/developers/docs/nodes-and-clients/#benefits-to-you). +Leia mais sobre os [benefícios de executar seu próprio nó](/developers/docs/nodes-and-clients/#benefits-to-you). ## Serviços de nós populares {#popular-node-services} Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. Sinta-se à vontade para adicionar qualquer um que estiver faltando! Cada nó de serviço oferece diferentes benefícios e recursos, além de níveis gratuitos ou pagos. Você deve analisar quais deles melhor se adaptam às suas necessidades antes de tomar uma decisão. - [**Alchemy**](https://alchemy.com/) - - [Documentos](https://docs.alchemyapi.io/) + - [Documentação](https://www.alchemy.com/docs/) - Recursos - Maior camada gratuita com 300M unidades de computação por mês (aproximadamente 30M solicitações getLatestBlock) - Suporte multicadeia para Polygon, Starknet, Otimizm, Arbitrum @@ -64,9 +64,22 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - Acesso à torneira para testes integrados - Comunidade ativa de construtores do Discord com 18 mil usuários -- [**Todo esse nó**](https://allthatnode.com/) - - [Documentos](https://docs.allthatnode.com/) - - Funcionalidades +- [**Allnodes**](https://www.allnodes.com/) + - [Documentação](https://docs.allnodes.com/) + - Recursos + - Sem limites de taxa com o token PublicNode criado na página do portfólio da Allnodes. + - Endpoints RPC gratuitos com foco em privacidade (mais de 100 blockchains) no [PublicNode](https://www.publicnode.com) + - Nós dedicados sem limites de taxa para mais de 90 blockchains + - Nós de arquivo dedicados para mais de 30 blockchains + - Disponível em 3 regiões (EUA, UE, Ásia) + - Snapshots para mais de 100 blockchains no [PublicNode](https://www.publicnode.com/snapshots) + - Suporte técnico 24/7 com SLA de disponibilidade de 99.90%-99.98% (depende do plano). + - Valor do pagamento por hora + - Pague com cartão de crédito, PayPal ou Cripto + +- [**All That Node**](https://allthatnode.com/) + - [Documentação](https://docs.allthatnode.com/) + - Recursos - 50.000 solicitações por dia com o nível gratuito - Suporte para mais de 40 protocolos - APIs JSON-RPC (EVM, Tendermint), REST e Websocket suportadas @@ -125,14 +138,14 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - [**BlockPI**](https://blockpi.io/) - [Documentação](https://docs.blockpi.io/) - Recursos - - Estrutura de nós robusta & distribuída + - Estrutura de nós robusta e distribuída - Até 40 pontos de extremidade HTTPS e WSS - Pacote gratuito de inscrição e pacote mensal - Método de rastreamento + suporte aos dados de arquivos - Validade dos pacotes até 90 dias, - Plano personalizado e pagamento conforme o uso - Pague em criptomoedas - - Suporte direto & Suporte técnico + - Suporte direto e suporte técnico - [**Chainbase**](https://www.chainbase.com/) - [Documentação](https://docs.chainbase.com) @@ -150,46 +163,46 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - Arquivos compartilhados de nós - Suporte ao GraphQL - Pontos de extremidade RPC e WSS - - Nós dedicados completos e arquivados + - Nós dedicados e arquivados - Tempo de sincronização rápido para implantações dedicadas - Traga sua própria nuvem - Valor do pagamento por hora - Suporte direto 24/7 -- [**DRPC**](https://drpc.org/) - - [Documentação](https://docs.drpc.org/) - - Recursos - - Nós RPC descentralizados - - Mais de 15 provedores de nós - - Balanceamento de nós - - Unidades de computação ilimitadas por mês na camada gratuita - - Verificação de dados - - Pontos de extremidade personalizados - - Endpoints HTTP e WSS - - Chaves ilimitadas (camada paga e gratuita) - - Opções de fallback flexíveis - - [Endpoint público](https://eth.drpc.org) - - Nós de arquivos compartilhados gratuitos +- [**dRPC**](https://drpc.org/) + - [Documentação](https://drpc.org/docs) + - NodeCloud: Infraestrutura RPC plug-n-play a partir de US$ 10 — velocidade total, sem limites + - Recursos do NodeCloud: + - Suporte de API para 185 redes + - Pool distribuído de mais de 40 provedores + - Cobertura global com nove (9) geo-clusters + - Sistema de balanceamento de carga com tecnologia de IA + - Preço fixo pré-pago — sem aumentos, sem expiração, sem fidelidade + - Chaves ilimitadas, ajustes granulares de chaves, funções de equipe, proteção de front-end + - Taxa fixa de métodos de 20 unidades de computação (CUs) por método + - [Lista de chains de endpoints públicos](https://drpc.org/chainlist) + - [Calculadora de preços](https://drpc.org/pricing#calculator) + - NodeCore: stack de código aberto para organizações que desejam controle total - [**GetBlock**](https://getblock.io/) - [Documentação](https://getblock.io/docs/get-started/authentication-with-api-key/) - Recursos - Acesso a mais de 40 nós de blockchain - - 40.000 solicitações diárias gratuitas + - 40K solicitações diárias grátis - Número ilimitado de chaves de API - Alta velocidade de conexão em 1GB/segundo - - Rastrear+Arquivar + - Rastreamento+Arquivar - Análises avançadas - Atualizações automatizadas - Suporte técnico - [**InfStones**](https://infstones.com/) - Recursos - - Opção de nível gratuito + - Opção de nível livre - Dimensione conforme suas necessidades - Análise - Painel - - Terminais de API únicos + - Pontos de extremidade de API únicos - Nós completos dedicados - Tempo de sincronização rápido para implantações dedicadas - Suporte direto 24/7 @@ -198,7 +211,7 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - [**Infura**](https://infura.io/) - [Documentação](https://infura.io/docs) - Recursos - - Opção de nível gratuito + - Opção de nível livre - Dimensione conforme suas necessidades - Dados de arquivos pagos - Suporte direto @@ -209,18 +222,18 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - Recursos - Nível inicial gratuito - Implementação do nó Ethereum em um clique - - Clientes e algoritmos personalizáveis (Geth, Quorum e Besu || PoA, IBFT e Raft) + - Clientes e algoritmos personalizáveis (Geth, Quorum & Besu || PoA, IBFT & Raft) - Mais de 500 APIs administrativas e de serviço - Interface RESTful para envio de transação Ethereum (com Apache Kafka) - Fluxos de saída para entrega de eventos (com Apache Kafka) - - Profunda coleção de serviços “fora da cadeia” e auxiliares (por exemplo, transporte de mensagens criptografadas bilaterais) + - Ampla coleção de serviços "offchain" e auxiliares (por exemplo, transporte de mensagens criptografadas bilaterais) - Integração de rede direta com controle de governança e acesso baseado em funções - Gerenciamento de usuários sofisticado para administradores e usuários finais - Infraestrutura altamente escalonável, resiliente e de nível empresarial - Gerenciamento de chaves privadas HSM - Compartilhamento de Internet da Mainnet (Rede principal) Ethereum - Certificações de tipo 2, ISO 27k e SOC 2 - - Configuração dinâmica de execução (por exemplo, adicionar integrações na nuvem, alterar entradas do nó, etc.) + - Configuração dinâmica de tempo de execução (por exemplo, adição de integrações em nuvem, alteração de entradas de nós, etc.) - Suporte a orquestrações multinuvem, multirregião e de implantação híbrida - Preços simples baseados em SaaS por hora - SLAs e suporte 24x7 @@ -247,7 +260,7 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - Dimensione conforme suas necessidades - Painel - SDK único do Ethereum - - Terminais de API únicos + - Pontos de extremidade de API únicos - Suporte técnico direto - [**NodeReal MegaNode**](https://nodereal.io/) @@ -259,6 +272,7 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - Comece gratuitamente - [**NOWNodes**](https://nownodes.io/) + - [Documentação](https://documenter.getpostman.com/view/13630829/TVmFkLwy) - Recursos - Acesso a mais de 50 nós da blockchain - Chave de API gratuita @@ -269,15 +283,16 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - Nós compartilhados, de arquivo, de cópia de segurança e dedicados - [**Pocket Network**](https://www.pokt.network/) - - [Documentos](https://docs.pokt.network/) + - [Documentação](https://docs.pokt.network/home/) - Recursos - Protocolo RPC descentralizado e mercado - 1 milhão de solicitações gratuitas por dia (por ponto de extremidade, máx. 2) + - [Endpoints públicos](https://docs.pokt.network/developers/public-endpoints) - Programa Pre-Stake+ (se você precisar de mais de 1 milhão de solicitações por dia) - Mais de 15 blockchains compatíveis - Mais de 6.400 nós com ganhos de POKT a serviço dos aplicativos - - Nó de arquivamento, nó de arquivamento com rastreamento e suporte a nós na rede de teste - - Diversidade do cliente do nó da rede principal Ethereum + - Nó de arquivamento, Nó de arquivamento com rastreamento e Suporte a nó de rede de teste + - Diversidade do cliente do nó da Mainnet (Rede principal) Ethereum - Nenhum ponto único de falha - Sem tempo de inatividade - Tokenomics rentáveis e perto de zero (participação de POKT uma vez para a largura de banda da rede) @@ -286,12 +301,12 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - Dimensione infinitamente o número de solicitações por dia e nós por hora conforme o uso - A opção mais particular e resistente à censura - Suporte prático para desenvolvedores - - Painel e ferramentas de análise do [Pocket Portal](https://bit.ly/ETHorg_POKTportal) + - Painel e análises do [Pocket Portal](https://bit.ly/ETHorg_POKTportal) - [**QuickNode**](https://www.quicknode.com) - - [Documentos](https://www.quicknode.com/docs/) + - [Documentação](https://www.quicknode.com/docs/) - Recursos - - Suporte técnico 24/7 e comunidade de desenvolvedores do Discord + - Suporte técnico 24/7 e comunidade de desenvolvedores no Discord - Rede de baixa latência, geograficamente equilibrada e multinuvem/metal - Suporte multicadeia (Optimism, Arbitrum, Polygon + 11 outros) - Camadas intermediárias para velocidade e estabilidade (roteamento de chamadas, cache, indexação) @@ -303,13 +318,13 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - Adequado para desenvolvedores e empresas - [**Rivet**](https://rivet.cloud/) - - [Documentos](https://rivet.readthedocs.io/en/latest/) + - [Documentação](https://rivet.readthedocs.io/en/latest/) - Recursos - - Opção de nível gratuito + - Opção de nível livre - Dimensione conforme suas necessidades - [**SenseiNode**](https://senseinode.com) - - [Documentos](https://docs.senseinode.com/) + - [Documentação](https://docs.senseinode.com/) - Recursos - Nós dedicados e compartilhados - Painel @@ -317,7 +332,7 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - Clientes Prysm e Lighthouse - [**SettleMint**](https://console.settlemint.com/) - - [Documentos](https://docs.settlemint.com/) + - [Documentação](https://docs.settlemint.com/) - Recursos - Avaliação gratuita - Dimensione conforme suas necessidades @@ -331,7 +346,7 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - Suporte direto - [**Tenderly**](https://tenderly.co/web3-gateway) - - [Documentos](https://docs.tenderly.co/web3-gateway/web3-gateway) + - [Documentação](https://docs.tenderly.co/web3-gateway/web3-gateway) - Recursos - Nível gratuito, incluindo 25 milhões de unidades Tenderly por mês - Acesso gratuito aos dados históricos @@ -346,9 +361,9 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - Suporte técnico dedicado via chat, e-mail e Discord - [**Tokenview**](https://services.tokenview.io/) - - [Documentos](https://services.tokenview.io/docs?type=nodeService) + - [Documentação](https://services.tokenview.io/docs?type=nodeService) - Recursos - - Suporte técnico 24/7 & comunidade Telegram de desenvolvedores + - Suporte técnico 24/7 e comunidade de desenvolvedores no Telegram - Suporte multichain (Bitcoin, Ethereum, Tron, BNB Smart Chain, Ethereum Classic) - Ambos endpoints RPC e WSS estão disponíveis para uso - Acesso ilimitado para a API de dados de arquivo @@ -358,7 +373,7 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - Suporte externo para requisitos extras de comportamento - [**Watchdata**](https://watchdata.io/) - - [Documentos](https://docs.watchdata.io/) + - [Documentação](https://docs.watchdata.io/) - Recursos - Confiabilidade dos dados - Conexão ininterrupta sem tempo de inatividade @@ -370,7 +385,7 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - Velocidades de processamento altas - [**ZMOK**](https://zmok.io/) - - [Documentos](https://docs.zmok.io/) + - [Documentação](https://docs.zmok.io/) - Recursos - Front-running como serviço - Mempool de transações globais com métodos de pesquisa/filtragem @@ -379,26 +394,25 @@ Segue uma lista de alguns dos fornecedores de nós para Ethereum mais populares. - O melhor preço garantido por chamada de API - [**Zeeve**](https://www.zeeve.io/) - - [Documentos](https://www.zeeve.io/docs/) + - [Documentação](https://www.zeeve.io/docs/) - Recursos - Plataforma de automação sem código de nível empresarial que fornece implantação, monitoramento e gerenciamento de nós e redes da Blockchain - - Mais de 30 protocolos e integrações, e adicionando mais + - Mais de 30 protocolos e integrações compatíveis, e adicionando mais - Valor adicionado à infraestrutura de serviços web3 como armazenamento decentralizado, identidade decentralizada e APIs de dados do Blockchain Ledger para casos reais - Suporte 24/7 e monitoramento proativo garantem a saúde dos nós o tempo todo. - Os endpoints RPC oferecem acesso autenticado às APIs, gerenciamento sem complicações com painel intuitivo e análise. - Fornece nuvem gerenciada e traz suas próprias opções de nuvem para escolher, além de oferecer suporte a todos os maiores provedores de nuvem como AWS, Azure, Google Cloud, Digital Ocean e local. - Usamos roteamento inteligente para sempre atingir o nó mais próximo de seu usuário - ## Leitura adicional {#further-reading} -- [Lista dos serviços de nós Ethereum](https://ethereumnodes.com/) +- [Lista de serviços de nós Ethereum](https://ethereumnodes.com/) ## Tópicos relacionados {#related-topics} -- [ Nós e clientes](/developers/docs/nodes-and-clients/) +- [Nós e clientes](/developers/docs/nodes-and-clients/) ## Tutoriais relacionados {#related-tutorials} -- [Introdução ao desenvolvimento de Ethereum usando Alchemy](/developers/tutorials/getting-started-with-ethereum-development-using-alchemy/) +- [Guia de introdução ao desenvolvimento da Ethereum usando Alchemy](/developers/tutorials/getting-started-with-ethereum-development-using-alchemy/) - [Guia para enviar transações usando web3 e Alchemy](/developers/tutorials/sending-transactions-using-web3-and-alchemy/) diff --git a/public/content/translations/pt-br/developers/docs/nodes-and-clients/run-a-node/index.md b/public/content/translations/pt-br/developers/docs/nodes-and-clients/run-a-node/index.md index 021644d17c2..c272a88025c 100644 --- a/public/content/translations/pt-br/developers/docs/nodes-and-clients/run-a-node/index.md +++ b/public/content/translations/pt-br/developers/docs/nodes-and-clients/run-a-node/index.md @@ -1,33 +1,33 @@ --- -title: Execute seu próprio nó Ethereum -description: Introdução geral para a execução da sua própria instância de um cliente Ethereum. +title: "Execute seu próprio nó Ethereum" +description: "Introdução geral para a execução da sua própria instância de um cliente Ethereum." lang: pt-br sidebarDepth: 2 --- Exdcutar um nó próprio proporciona vários benefícios, abre novas possibilidades e ajuda a dar suporte ao ecossistema. Esta página vai ajudar você a iniciar seu próprio nó, para assim participar na validação das transações de Ethereum. -Observe que após [A Fusão](/roadmap/merge) (The Merge), são necessários dois clientes para executar um nó Ethereum; um cliente da **camada de execução (EL)** e um cliente da **camada de consenso (CL)**. Esta página mostrará como instalar, configurar e conectar esses dois clientes para executar um nó Ethereum. +Observe que, após [A Fusão](/roadmap/merge), são necessários dois clientes para executar um nó Ethereum: um cliente da **camada de execução (EL)** e um cliente da **camada de consenso (CL)**. Esta página mostrará como instalar, configurar e conectar esses dois clientes para executar um nó Ethereum. ## Pré-requisitos {#prerequisites} -Você deve entender o que é um nó Ethereum e por que é importante executar um cliente. Isso é abordado em [Nós e clientes](/developers/docs/nodes-and-clients/). +Você deve entender o que é um nó Ethereum e por que é importante executar um cliente. Isto é abordado em [Nós e clientes](/developers/docs/nodes-and-clients/). -Se você é novo no tópico de executar um nó ou está procurando um caminho menos técnico, recomendamos primeiro verificar nossa introdução simplificada sobre como [executar um nó Ethereum](/run-a-node). +Se você é novo no tópico de executar um nó ou está procurando um caminho menos técnico, recomendamos primeiro verificar nossa introdução simplificada sobre [como executar um nó do Ethereum](/run-a-node). -## Escolhendo um método {#choosing-approach} +## Escolhendo uma abordagem {#choosing-approach} O primeiro passo para iniciar um nó é escolher sua abordagem. Com base nos requisitos e várias possibilidades, você deve selecionar a implementação do cliente (de ambos os clientes de execução e consenso), o ambiente (hardware, sistema) e os parâmetros para as configurações do cliente. Esta página guiará você por essas decisões e ajudará você a encontrar a maneira mais adequada para executar sua instância do Ethereum. -Para escolher entre as implementações de cliente, veja todos os [clientes de execução](/developers/docs/nodes-and-clients/#execution-clients) prontos para a Rede principal disponíveis, [clientes de consenso](/developers/docs/nodes-and-clients/#consensus-clients) e saiba mais sobre a [diversidade de clientes](/developers/docs/nodes-and-clients/client-diversity). +Para escolher entre as implementações de cliente, veja todos os [clientes de execução](/developers/docs/nodes-and-clients/#execution-clients) e [clientes de consenso](/developers/docs/nodes-and-clients/#consensus-clients) prontos para a Mainnet e saiba mais sobre a [diversidade de clientes](/developers/docs/nodes-and-clients/client-diversity). -Decida se deseja executar o software em seu próprio [hardware ou na nuvem](#local-vs-cloud), considerando os [requisitos](#requirements) dos clientes. +Decida se quer executar o software em seu próprio [hardware ou na nuvem](#local-vs-cloud), considerando os [requisitos](#requirements) dos clientes. -Após preparar o ambiente, instale os clientes escolhidos com [interface simples para iniciantes](#automatized-setup) ou [manualmente](#manual-setup) usando um terminal com opções avançadas. +Depois de preparar o ambiente, instale os clientes escolhidos com uma [interface amigável para iniciantes](#automatized-setup) ou [manualmente](#manual-setup) usando um terminal com opções avançadas. -Quando o nó estiver em execução e sincronização, você estará pronto para [usá-lo](#using-the-node), mas fique de olho em sua [manutenção](#operating-the-node). +Quando o nó estiver em execução e sincronizando, você estará pronto para [usá-lo](#using-the-node), mas certifique-se de ficar de olho na sua [manutenção](#operating-the-node). ![Configuração do cliente](./diagram.png) @@ -35,7 +35,8 @@ Quando o nó estiver em execução e sincronização, você estará pronto para #### Local ou nuvem {#local-vs-cloud} -Os clientes Ethereum são capazes de executar em computadores de grau de consumo e não exigem nenhum hardware especial, como máquinas de mineração, por exemplo. Portanto, você tem várias opções para implantar o nó de acordo com suas necessidades. Para simplificar, vamos analisar como executar um nó em uma máquina física local e um servidor na nuvem: +Os clientes Ethereum são capazes de executar em computadores de grau de consumo e não exigem nenhum hardware especial, como máquinas de mineração, por exemplo. Portanto, você tem várias opções para implantar o nó de acordo com suas necessidades. +Para simplificar, vamos analisar como executar um nó em uma máquina física local e um servidor na nuvem: - Nuvem - Os provedores oferecem alto tempo de atividade do servidor e endereços IP públicos estáticos @@ -48,11 +49,11 @@ Os clientes Ethereum são capazes de executar em computadores de grau de consumo - Existe a opção para comprar máquinas pré-configuradas - Você tem que fisicamente preparar, manter e solucionar os problemas potenciais que surgirem -Ambas as opções têm vantagens e desvantagens, as quais foram resumidas acima. Caso estiver procurando uma solução para a nuvem, além de muitos provedores tradicionais de computação na nuvem, também existem serviços focados em executar nós. Confira [nós como serviço](/developers/docs/nodes-and-clients/nodes-as-a-service/) para obter mais opções de nós hospedados. +Ambas as opções têm vantagens e desvantagens, as quais foram resumidas acima. Caso estiver procurando uma solução para a nuvem, além de muitos provedores tradicionais de computação na nuvem, também existem serviços focados em executar nós. Confira [nós como serviço](/developers/docs/nodes-and-clients/nodes-as-a-service/) para mais opções de nós hospedados. #### Hardware {#hardware} -No entanto, uma rede descentralizada que resiste à censura não deve depender de provedores na nuvem. Em vez disso, executar seu nó em seu próprio hardware local é mais saudável para o ecossistema. As [estimativas](https://www.ethernodes.org/network-types) mostram uma grande parte dos nós executados na nuvem, o que pode se tornar um único ponto de falha. +No entanto, uma rede descentralizada que resiste à censura não deve depender de provedores na nuvem. Em vez disso, executar seu nó em seu próprio hardware local é mais saudável para o ecossistema. [Estimativas](https://www.ethernodes.org/networkType/cl/Hosting) mostram que uma grande parte dos nós é executada na nuvem, o que poderia se tornar um único ponto de falha. Os clientes Ethereum podem ser executados no seu computador, laptop, servidor ou até mesmo em um computador de placa única. Enquanto for possível executar clientes em seu computador pessoal, ter um computador dedicado apenas para seu nó poderá melhorar significativamente seu desempenho e segurança, ao mesmo tempo que minimiza o impacto em seu computador principal. @@ -64,11 +65,11 @@ Os requisitos de hardware diferem conforme o cliente, mas geralmente não são t Antes de instalar qualquer cliente, verifique se o seu computador tem recursos suficientes para executá-lo. Você pode encontrar os requisitos mínimos e recomendados abaixo. -O afunilamento do seu hardware é, geralmente, o espaço em disco. Sincronizar a blockchain Ethereum é muito intensivo em termos de entrada/saída e requer muito espaço. É melhor ter uma **unidade de estado sólido (SSD)** com centenas de GBs de espaço livre para economizar, mesmo após a sincronização. +O afunilamento do seu hardware é, geralmente, o espaço em disco. Sincronizar a blockchain Ethereum é muito intensivo em termos de entrada/saída e requer muito espaço. É melhor ter uma **unidade de estado sólido (SSD)** com centenas de GBs de espaço livre sobrando mesmo após a sincronização. O tamanho do banco de dados e a velocidade da sincronização inicial dependem do cliente escolhido, sua configuração e [estratégia de sincronização](/developers/docs/nodes-and-clients/#sync-modes). -Verifique também se sua conexão de Internet não está limitada devido a um [limite de largura de banda](https://wikipedia.org/wiki/Data_cap). É recomendado usar uma conexão ilimitada para que a sincronização inicial e os dados transmitidos à rede possam exceder seu limite. +Certifique-se também de que sua conexão com a internet não seja limitada por um [limite de largura de banda](https://wikipedia.org/wiki/Data_cap). É recomendado usar uma conexão ilimitada para que a sincronização inicial e os dados transmitidos à rede possam exceder seu limite. ##### Sistema operacional @@ -90,19 +91,19 @@ Todos os clientes dão suporte aos principais sistemas operacionais: Linux, MacO O modo de sincronização e o cliente que você escolher afetará os requisitos de espaço, mas estimamos o espaço em disco necessário para cada cliente abaixo. -| Cliente | Tamanho do disco (sincronização rápida) | Tamanho do disco (arquivo completo) | -| ---------- | --------------------------------------- | ----------------------------------- | -| Besu | + de 800 GB | + de 12 TB | -| Erigon | N/D | + de 2,5 TB | -| Geth | + de 500 GB | + de 12 TB | -| Nethermind | + de 500 GB | + 12 TB | -| Reth | N/D | 2.2TB+ | +| Client | Tamanho do disco (sincronização rápida) | Tamanho do disco (arquivo completo) | +| ---------- | ---------------------------------------------------------- | ------------------------------------------------------ | +| Besu | + de 800 GB | + 12 TB | +| Erigon | N/D | + de 2,5 TB | +| Geth | + de 500 GB | + 12 TB | +| Nethermind | + de 500 GB | + 12 TB | +| Reth | N/D | 2.2TB+ | -- Nota: Erigon e Reth não oferecem sincronização instantânea, mas é possível fazer o Full Pruning (~2 Tb para Erigon, ~1,2 Tb para Reth) +- Nota: Erigon e Reth não oferecem sincronização instantânea, mas é possível fazer o Full Pruning (\~2 Tb para Erigon, ~1,2 Tb para Reth) -Para clientes de consenso, o requisito de espaço também depende da implementação do cliente e dos recursos habilitados (por exemplo, removedor de validador), mas geralmente contam com outros 200 GB necessários para dados do beacon. Com um grande número de validadores, a carga de largura de banda também aumenta. Você pode encontrar [detalhes sobre os requisitos do cliente de consenso nesta análise](https://mirror.xyz/0x934e6B4D7eee305F8C9C42b46D6EEA09CcFd5EDc/b69LBy8p5UhcGJqUAmT22dpvdkU-Pulg2inrhoS9Mbc). +Para clientes de consenso, o requisito de espaço também depende da implementação do cliente e dos recursos habilitados (p. ex., slasher de validador), mas geralmente conte com outros 200 GB necessários para dados de beacon. Com um grande número de validadores, a carga de largura de banda também aumenta. Você pode encontrar [detalhes sobre os requisitos do cliente de consenso nesta análise](https://mirror.xyz/0x934e6B4D7eee305F8C9C42b46D6EEA09CcFd5EDc/b69LBy8p5UhcGJqUAmT22dpvdkU-Pulg2inrhoS9Mbc). -#### Soluções "Plug-and-play" {#plug-and-play} +#### Soluções plug-and-play {#plug-and-play} A opção mais fácil para executar um nó com seu próprio hardware é usando ferramentas plug-and-play. Máquinas pré-configuradas de fornecedores oferecem a experiência mais direta: pedir, conectar, executar. Tudo é pré-configurado e roda automaticamente com um guia intuitivo e painel de controle para monitorar e controlar o software. @@ -111,29 +112,30 @@ A opção mais fácil para executar um nó com seu próprio hardware é usando f #### Ethereum em um computador de placa única {#ethereum-on-a-single-board-computer} -Uma maneira fácil e barata de executar um nó Ethereum é usar um computador de placa única, mesmo com uma arquitetura ARM como o Raspberry Pi. O [Ethereum no ARM](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/) fornece imagens fáceis de executar de múltipla execução e cliente de consenso para Raspberry Pi e outras placas ARM. +Uma maneira fácil e barata de executar um nó Ethereum é usar um computador de placa única, mesmo com uma arquitetura ARM como o Raspberry Pi. [Ethereum on ARM](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/) fornece imagens fáceis de executar de vários clientes de execução e de consenso para Raspberry Pi e outras placas ARM. Dispositivos pequenos, acessíveis e eficientes como esses são ideais para executar um nó em casa, porém, lembre-se de seu desempenho limitado. -## Executando seu nó {#spinning-up-node} +## Iniciando o nó {#spinning-up-node} A configuração real do cliente pode ser feita com programas automatizados ou manualmente, configurando o software do cliente diretamente. Para usuários menos avançados, a abordagem recomendada é usar um programa, ou seja, um software que orienta você durante a instalação e automatiza o processo de configuração do cliente. No entanto, se você tiver alguma experiência em usar um terminal, as etapas da configuração manual deverão ser simples de seguir. -### Guia de configuração {#automatized-setup} +### Configuração guiada {#automatized-setup} Vários projetos de fácil utilização visam melhorar a experiência de configuração de um cliente. Esses programas fornecem instalação e configuração automáticas de cliente, com alguns até oferecendo uma interface gráfica para configuração guiada e monitoramento de clientes. Abaixo estão alguns projetos que podem ajudar você a instalar e controlar clientes com apenas alguns cliques: -- [DappNode](https://docs.dappnode.io/docs/user/getting-started/choose-your-path) — O DappNode não vem apenas com o computador de um fornecedor. O software, o verdadeiro inicializador de nós e o centro de controle com muitos recursos podem ser usados em hardwares aleatórios. -- [eth-docker](https://eth-docker.net/) — Configuração automatizada usando o Docker, focada em participação (staking) fácil e segura. Requer conhecimento básico de terminal e Docker, sendo recomendada para usuários um pouco mais avançados. -- [Stereum](https://stereum.net/ethereum-node-setup/) — Inicializador para instalar clientes em um servidor remoto via conexão SSH com um guia de configuração GUI, centro de controle e muitos outros recursos. -- [NiceNode](https://www.nicenode.xyz/) — Programa com uma experiência de usuário simples para executar um nó em seu computador. Basta escolher os clientes e iniciá-los em alguns cliques. Ainda em desenvolvimento. -- [Sedge](https://docs.sedge.nethermind.io/docs/intro) — Ferramenta de configuração de nós que gera automaticamente uma configuração do Docker usando o assistente da CLI. Escrito em Go pela Nethermind. +- [DappNode](https://docs.dappnode.io/docs/user/getting-started/choose-your-path) - DappNode não vem apenas com uma máquina de um fornecedor. O software, o verdadeiro inicializador de nós e o centro de controle com muitos recursos podem ser usados em hardwares aleatórios. +- [EthPillar](https://www.coincashew.com/coins/overview-eth/ethpillar) - A maneira mais rápida e fácil de configurar um nó completo. Ferramenta de configuração linear e gerenciamento de nó TUI. Gratuito. Código aberto. Bons públicos para Ethereum por solistas. Apoio de ARM64 e AMD64. +- [eth-docker](https://eth-docker.net/) - Configuração automatizada usando Docker focada em staking fácil e seguro, requer conhecimento básico de terminal e Docker, recomendado para usuários um pouco mais avançados. +- [Stereum](https://stereum-dev.github.io/ethereum-node-web-docs) - Iniciador para instalar clientes em um servidor remoto via conexão SSH com um guia de configuração da GUI, centro de controle e muitos outros recursos. +- [NiceNode](https://www.nicenode.xyz/) - Iniciador com uma experiência de usuário simples para executar um nó em seu computador. Basta escolher os clientes e iniciá-los em alguns cliques. Ainda em desenvolvimento. +- [Sedge](https://docs.sedge.nethermind.io/docs/intro) - Ferramenta de configuração de nó que gera automaticamente uma configuração do Docker usando o assistente da CLI. Escrito em Go pela Nethermind. -### Configuração manual do cliente {#manual-setup} +### Configuração manual de clientes {#manual-setup} A outra opção é baixar, verificar e configurar o software cliente manualmente. Mesmo que alguns clientes ofereçam uma interface gráfica, uma configuração manual ainda requer habilidades básicas com o terminal, mas oferece muito mais versatilidade. @@ -141,7 +143,7 @@ Conforme explicado anteriormente, configurar seu próprio nó Ethereum exigirá #### Obtendo o software do cliente {#getting-the-client} -Primeiro, você precisa obter o software do [cliente de execução](/developers/docs/nodes-and-clients/#execution-clients) e do [cliente de consenso](/developers/docs/nodes-and-clients/#consensus-clients) de sua preferência. +Primeiro, você precisa obter o software de sua preferência de [cliente de execução](/developers/docs/nodes-and-clients/#execution-clients) e [cliente de consenso](/developers/docs/nodes-and-clients/#consensus-clients). Você pode simplesmente baixar um aplicativo executável ou um pacote de instalação que se adapte ao seu sistema operacional e à sua arquitetura. Sempre verifique as assinaturas e as somas de verificação dos pacotes baixados. Alguns clientes também oferecem repositórios ou imagens do Docker para instalação e atualizações mais fáceis. Todos os clientes são de código aberto, portanto, você também pode construí-los a partir do código-fonte. Esse método é mais avançado, mas, em alguns casos, pode ser necessário. @@ -157,17 +159,17 @@ Aqui estão as páginas de lançamento dos clientes, nas quais você pode encont - [Nethermind](https://downloads.nethermind.io/) - [Reth](https://reth.rs/installation/installation.html) -Também é relevante observar que a diversidade de clientes é um [problema na camada de execução](/developers/docs/nodes-and-clients/client-diversity/#execution-layer). Recomenda-se que os leitores considerem a execução de um cliente de execução minoritário. +Também vale a pena notar que a diversidade de clientes é um [problema na camada de execução](/developers/docs/nodes-and-clients/client-diversity/#execution-layer). Recomenda-se que os leitores considerem a execução de um cliente de execução minoritário. ##### Clientes de consenso - [Lighthouse](https://github.com/sigp/lighthouse/releases/latest) -- [Lodestar](https://chainsafe.github.io/lodestar/run/getting-started/installation#build-from-source/) (não fornece um binário pré-compilado, apenas uma imagem do Docker ou para ser compilado a partir da fonte) +- [Lodestar](https://chainsafe.github.io/lodestar/run/getting-started/installation#build-from-source) (Não fornece um binário pré-compilado, apenas uma imagem Docker ou para ser construído a partir do código-fonte) - [Nimbus](https://github.com/status-im/nimbus-eth2/releases/latest) - [Prysm](https://github.com/prysmaticlabs/prysm/releases/latest) - [Teku](https://github.com/ConsenSys/teku/releases) -A [diversidade de clientes](/developers/docs/nodes-and-clients/client-diversity/) é fundamental para nós de consenso executando validadores. Se a maioria dos validadores estiver executando uma única implementação do cliente, a segurança da rede estará em risco. Portanto, é recomendável considerar a escolha de um cliente minoritário. +A [diversidade de clientes](/developers/docs/nodes-and-clients/client-diversity/) é fundamental para nós de consenso que executam validadores. Se a maioria dos validadores estiver executando uma única implementação do cliente, a segurança da rede estará em risco. Portanto, é recomendável considerar a escolha de um cliente minoritário. [Veja o uso mais recente do cliente de rede](https://clientdiversity.org/) e saiba mais sobre a [diversidade de clientes](/developers/docs/nodes-and-clients/client-diversity). @@ -175,7 +177,7 @@ A [diversidade de clientes](/developers/docs/nodes-and-clients/client-diversity/ Ao baixar o software da Internet, é recomendável verificar sua integridade. Essa etapa é opcional, mas, especialmente com uma parte de infraestrutura crucial como o cliente Ethereum, é importante estar ciente dos possíveis vetores de ataque e evitá-los. Se você baixou um binário pré-compilado, você precisa confiar nele e correr o risco de um invasor substituir o executável por um malicioso. -Os desenvolvedores assinam binários lançados com suas chaves PGP para que você possa verificar criptograficamente se está executando exatamente o software que eles criaram. Você só precisa obter as chaves públicas usadas pelos desenvolvedores, que podem ser encontradas nas páginas de lançamento do cliente ou na documentação. Após baixar a versão do cliente e sua assinatura, você pode usar uma implementação PGP, por exemplo, [GnuPG](https://gnupg.org/download/index.html) para verificá-los facilmente. Confira um tutorial sobre como verificar software de código aberto usando `GPG` no [Linux](https://www.tecmint.com/verify-pgp-signature-downloaded-software/) ou [Windows/MacOS](https://freedom.press/training/verifying-open-source-software/). +Os desenvolvedores assinam binários lançados com suas chaves PGP para que você possa verificar criptograficamente se está executando exatamente o software que eles criaram. Você só precisa obter as chaves públicas usadas pelos desenvolvedores, que podem ser encontradas nas páginas de lançamento do cliente ou na documentação. Após baixar a versão do cliente e sua assinatura, você pode usar uma implementação PGP, por exemplo, [GnuPG](https://gnupg.org/download/index.html) para verificá-los facilmente. Confira um tutorial sobre como verificar software de código aberto usando `gpg` no [linux](https://www.tecmint.com/verify-pgp-signature-downloaded-software/) ou [Windows/MacOS](https://freedom.press/training/verifying-open-source-software/). Outra forma de verificação é garantir que o hash, uma impressão digital criptográfica exclusiva do software que você baixou, corresponde ao fornecido pelos desenvolvedores. Isso é ainda mais fácil do que usar o PGP, e alguns clientes oferecem apenas essa opção. Basta executar a função de hash no software baixado e compará-lo com o da página de lançamento. Por exemplo: @@ -189,15 +191,15 @@ sha256sum teku-22.6.1.tar.gz Depois de instalar, baixar ou compilar o software cliente, você estará pronto para executá-lo. Isso só significa que ele tem de ser executado com a configuração adequada. Os clientes oferecem opções de configuração variadas, que podem habilitar vários recursos. -Vamos começar com opções que podem influenciar significativamente o desempenho do cliente e o uso de dados. Os [modos de sincronização](/developers/docs/nodes-and-clients/#sync-modes) representam diferentes métodos de download e validação de dados da blockchain. Antes de iniciar o nó, você deve decidir que rede e modo de sincronização deve ser usado. As coisas mais importantes a considerar são o espaço em disco e o tempo de sincronização de que o cliente precisará. Preste atenção nos documentos do cliente para determinar qual modo de sincronização é o padrão. Se não for adequado para você, escolha outro com base no nível de segurança, nos dados disponíveis e no custo. Além do algoritmo de sincronização, você também pode definir a remoção de diferentes tipos de dados antigos. A limpeza habilita a exclusão de dados desatualizados, por exemplo, a remoção de nós de árvore de estado inacessíveis em blocos recentes. +Vamos começar com opções que podem influenciar significativamente o desempenho do cliente e o uso de dados. [Modos de sincronização](/developers/docs/nodes-and-clients/#sync-modes) representam diferentes métodos de baixar e validar dados da blockchain. Antes de iniciar o nó, você deve decidir que rede e modo de sincronização deve ser usado. As coisas mais importantes a considerar são o espaço em disco e o tempo de sincronização de que o cliente precisará. Preste atenção nos documentos do cliente para determinar qual modo de sincronização é o padrão. Se não for adequado para você, escolha outro com base no nível de segurança, nos dados disponíveis e no custo. Além do algoritmo de sincronização, você também pode definir a remoção de diferentes tipos de dados antigos. A poda (pruning) permite excluir dados desatualizados, ou seja, remover nós da árvore de estado que são inacessíveis a partir de blocos recentes. -Outras opções básicas de configuração são, por exemplo, escolher uma rede, Mainnet (Rede principal) ou redes de teste, habilitando o ponto de extremidade HTTP para RPC ou WebSockets, etc. Você pode encontrar todos os recursos e opções na documentação do cliente. Várias configurações de cliente podem ser definidas executando o cliente com os marcadores correspondentes diretamente na CLI ou no arquivo de configuração. Cada cliente é um pouco diferente, por isso, sempre consulte a documentação oficial ou a página de ajuda do cliente para obter detalhes sobre as opções de configuração. +Outras opções básicas de configuração são, por exemplo, escolher uma rede - Mainnet ou redes de teste, habilitar o endpoint HTTP para RPC ou WebSockets, etc. Você pode encontrar todos os recursos e opções na documentação do cliente. Várias configurações de cliente podem ser definidas executando o cliente com os marcadores correspondentes diretamente na CLI ou no arquivo de configuração. Cada cliente é um pouco diferente, por isso, sempre consulte a documentação oficial ou a página de ajuda do cliente para obter detalhes sobre as opções de configuração. Para fins de teste, você pode preferir executar um cliente em uma das redes de testes. [Veja a visão geral das redes suportadas](/developers/docs/nodes-and-clients/#execution-clients). Exemplos de execução de clientes de execução com configuração básica podem ser encontrados na próxima seção. -#### Iniciando a execução do cliente {#starting-the-execution-client} +#### Iniciando o cliente de execução {#starting-the-execution-client} Antes de iniciar o software cliente do Ethereum, faça uma última verificação para ter certeza de que seu ambiente está pronto. Por exemplo, verifique se: @@ -211,34 +213,34 @@ Execute seu cliente primeiro em uma rede de testes para garantir que tudo esteja Ao iniciar, você precisa declarar alguma configuração de cliente que não seja a padrão. Você pode usar sinalizadores ou o arquivo de configuração para declarar sua configuração preferida. O conjunto de recursos e a sintaxe de configuração de cada cliente diferem. Confira a documentação do seu cliente para ver as especificações. -Os clientes de execução e consenso se comunicam por meio de um terminal autenticado especificado na [API Engine](https://github.com/ethereum/execution-apis/tree/main/src/engine). Para se conectar a um cliente de consenso, o cliente de execução deve gerar um [`jwtsecret`](https://jwt.io/) em um caminho conhecido. Por razões de segurança e estabilidade, os clientes devem ser executados no mesmo computador e ambos os clientes devem conhecer esse caminho, pois ele é usado para autenticar uma conexão RPC local entre eles. O cliente de execução também deve definir uma porta de escuta para APIs autenticadas. +Os clientes de execução e de consenso se comunicam por meio de um ponto de extremidade autenticado especificado na [API do Motor (Engine API)](https://github.com/ethereum/execution-apis/tree/main/src/engine). Para se conectar a um cliente de consenso, o cliente de execução deve gerar um [`jwtsecret`](https://jwt.io/) em um caminho conhecido. Por razões de segurança e estabilidade, os clientes devem ser executados no mesmo computador e ambos os clientes devem conhecer esse caminho, pois ele é usado para autenticar uma conexão RPC local entre eles. O cliente de execução também deve definir uma porta de escuta para APIs autenticadas. -Esse token é gerado automaticamente pelo software cliente, mas, em alguns casos, talvez você precise fazer isso sozinho. Você pode gerá-lo usando o [OpenSSL](https://www.openssl.org/): +Esse token é gerado automaticamente pelo software cliente, mas, em alguns casos, talvez você precise fazer isso sozinho. Você pode gerá-lo usando [OpenSSL](https://www.openssl.org/): ```sh openssl rand -hex 32 > jwtsecret ``` -#### Iniciando a execução do cliente {#running-an-execution-client} +#### Executando um cliente de execução {#running-an-execution-client} Esta seção guiará você na inicialização dos clientes de execução. Ela serve apenas como exemplo de configuração básica, que iniciará o cliente com estas configurações: - Especifica a rede para conectar. A rede principal, em nossos exemplos - - Em vez disso, você pode escolher [uma das redes de teste](/developers/docs/networks/) para fazer um teste preliminar da sua configuração + - Você pode, em vez disso, escolher [uma das redes de teste](/developers/docs/networks/) para testes preliminares de sua configuração - Define o diretório de dados, no qual todos os dados, incluindo a blockchain, serão armazenados - Certifique-se de substituir o caminho por um real, por exemplo, apontando para sua unidade externa - Habilita interfaces para comunicação com o cliente - Incluindo JSON-RPC e Engine API para comunicação com o cliente de consenso -- Define o caminho até `jwtsecret` para a API autenticada +- Define o caminho para `jwtsecret` para a API autenticada - Certifique-se de substituir o caminho de exemplo por um real que possa ser acessado pelos clientes, por exemplo, `/tmp/jwtsecret` Lembre-se de que este é apenas um exemplo básico, todas as outras configurações serão definidas como padrão. Preste atenção na documentação de cada cliente para saber mais sobre valores padrão, configurações e recursos. Para mais recursos, por exemplo, para executar validadores, monitoramento, etc., consulte a documentação específica do cliente. -> Observe que as barras invertidas `\` nos exemplos são apenas para fins de formatação; marcadores de configuração podem ser definidos em uma única linha. +> Observe que as barras invertidas `` nos exemplos são apenas para fins de formatação; os sinalizadores de configuração podem ser definidos em uma única linha. ##### Executando o Besu -Este exemplo inicia o Besu na rede principal, armazena dados da blockchain no formato padrão em `/data/ethereum` e habilita o RPC JSON e o RPC Engine para conectar o cliente de consenso. A API Engine é autenticada com o token `jwtsecret` e somente chamadas de `localhost` são permitidas. +Este exemplo inicia o Besu na Mainnet, armazena dados da blockchain no formato padrão em `/data/ethereum`, habilita o JSON-RPC e o Engine RPC para conectar o cliente de consenso. A Engine API é autenticada com o token `jwtsecret` e somente chamadas de `localhost` são permitidas. ```sh besu --network=mainnet \ @@ -256,11 +258,11 @@ O Besu também vem com uma opção de inicializador, que fará uma série de per besu --Xlauncher ``` -A [documentação do Besu](https://besu.hyperledger.org/public-networks/get-started/start-node/) contém opções adicionais e detalhes de configuração. +A [documentação do Besu](https://besu.hyperledger.org/public-networks/get-started/start-node/) contém opções e detalhes de configuração adicionais. ##### Executando o Erigon -Este exemplo inicia o Erigon na rede principal, armazena dados da blockchain em `/data/ethereum`, habilita o RPC JSON, define quais namespaces são permitidos e habilita a autenticação para conectar o cliente de consenso, definido pelo caminho `jwtsecret`. +Este exemplo inicia o Erigon na Mainnet, armazena dados da blockchain em `/data/ethereum`, habilita o JSON-RPC, define quais namespaces são permitidos e habilita a autenticação para conectar o cliente de consenso que é definido pelo caminho `jwtsecret`. ```sh erigon --chain mainnet \ @@ -269,11 +271,11 @@ erigon --chain mainnet \ --authrpc.jwtsecret=/path/to/jwtsecret ``` -O Erigon, por padrão, executa uma sincronização completa com um HDD de 8 GB, que resultará em mais de 2 TB de dados de arquivo. Verifique se o `datadir` está apontando para o disco com espaço livre suficiente ou olha para o sinalizador `--prune`, que pode ajustar diferentes tipos de dados. Verifique o `--help` do Erigon para saber mais. +O Erigon, por padrão, executa uma sincronização completa com um HDD de 8 GB, que resultará em mais de 2 TB de dados de arquivo. Certifique-se de que `datadir` aponta para um disco com espaço livre suficiente ou veja o sinalizador `--prune` que pode reduzir diferentes tipos de dados. Verifique o `--help` do Erigon para saber mais. ##### Executando o Geth -Este exemplo inicia o Geth na rede principal, armazena os dados da blockchain em `/data/ethereum`, habilita o RPC JSON e define quais namespaces são permitidos. Ele também habilita a autenticação para conectar o cliente de consenso, que requer o caminho para `jwtsecret` e também a opção que define quais conexões são permitidas, em nosso exemplo apenas no `localhost`. +Este exemplo inicia o Geth na Mainnet, armazena os dados da blockchain em `/data/ethereum`, habilita o JSON-RPC e define quais namespaces são permitidos. Também habilita a autenticação para conectar o cliente de consenso, o que requer o caminho para `jwtsecret` e também uma opção que define quais conexões são permitidas, em nosso exemplo apenas de `localhost`. ```sh geth --mainnet \ @@ -284,7 +286,7 @@ geth --mainnet \ --authrpc.jwtsecret=/path/to/jwtsecret ``` -Confira a [documentação para todas as opções de configuração](https://geth.ethereum.org/docs/fundamentals/command-line-options) e saiba mais sobre [como executar Geth com um cliente de consenso](https://geth.ethereum.org/docs/getting-started/consensus-clients). +Verifique a [documentação para todas as opções de configuração](https://geth.ethereum.org/docs/fundamentals/command-line-options) e saiba mais sobre [como executar o Geth com um cliente de consenso](https://geth.ethereum.org/docs/getting-started/consensus-clients). ##### Executando o Nethermind @@ -296,13 +298,13 @@ Nethermind.Runner --config mainnet \ --JsonRpc.JwtSecretFile=/path/to/jwtsecret ``` -Os documentos do Nethermind oferecem um [guia completo](https://docs.nethermind.io/get-started/running-node/) sobre como executar o Nethermind com o cliente de consenso. +A documentação do Nethermind oferece um [guia completo](https://docs.nethermind.io/get-started/running-node/) sobre como executar o Nethermind com um cliente de consenso. Um cliente de execução iniciará suas funções principais, pontos de extremidade escolhidos e começará a procurar por pares. Após conseguir descobrir os pares, o cliente inicia a sincronização. O cliente de execução aguardará uma conexão do cliente de consenso. Os dados atuais da cadeia de blocos estarão disponíveis assim que o cliente for sincronizado com sucesso com o estado atual. ##### Executando o Reth -Este exemplo inicia o Reth na rede principal, usando o local de dados padrão. Habilita a autenticação JSON-RPC e Engine RPC para conectar o cliente de consenso definido pelo caminho `jwtsecret`, permitindo chamadas somente de `localhost`. +Este exemplo inicia o Reth na rede principal, usando o local de dados padrão. Habilita a autenticação JSON-RPC e Engine RPC para conectar o cliente de consenso que é definido pelo caminho `jwtsecret`, com somente chamadas de `localhost` sendo permitidas. ```sh reth node \ @@ -311,23 +313,23 @@ reth node \ --authrpc.port 8551 ``` -Consulte [Configuração do Reth](https://reth.rs/run/config.html?highlight=data%20directory#configuring-reth) para saber mais sobre os diretórios de dados padrão. A [documentação do Reth](https://reth.rs/run/mainnet.html) contém opções adicionais e detalhes de configuração. +Veja [Configurando o Reth](https://reth.rs/run/config.html?highlight=data%20directory#configuring-reth) para saber mais sobre os diretórios de dados padrão. [A documentação do Reth](https://reth.rs/run/mainnet.html) contém opções e detalhes de configuração adicionais. -#### Iniciando um cliente de consenso {#starting-the-consensus-client} +#### Iniciando o cliente de consenso {#starting-the-consensus-client} O cliente de consenso deve ser iniciado com a configuração de porta correta para estabelecer uma conexão RPC local com o cliente de execução. Os clientes de consenso têm de ser executados com a porta do cliente de execução exposta como argumento de configuração. O cliente de consenso também precisa do caminho para o `jwt-secret` do cliente de execução para autenticar a conexão RPC entre eles. Semelhante aos exemplos de execução acima, cada cliente de consenso tem um parâmetro de configuração que usa o caminho do arquivo do token jwt como argumento. Isso deve ser consistente com o caminho `jwtsecret` fornecido ao cliente de execução. -Se você planeja executar um validador, certifique-se de adicionar um marcador de configuração especificando o endereço Ethereum do destinatário da taxa. É aí que as recompensas do ether para o validador se acumulam. Cada cliente de consenso tem uma opção, por exemplo, `--suggested-fee-recipient=0xabcd1`, que recebe um endereço Ethereum como argumento. +Se você planeja executar um validador, certifique-se de adicionar um marcador de configuração especificando o endereço Ethereum do destinatário da taxa. É aí que as recompensas do ether para o validador se acumulam. Cada cliente de consenso tem uma opção, por exemplo, `--suggested-fee-recipient=0xabcd1`, que usa um endereço Ethereum como argumento. -Ao iniciar um Beacon Node em uma rede de testes, você pode economizar um tempo de sincronização significativo usando um ponto de extremidade público para [sincronização de ponto de verificação](https://notes.ethereum.org/@launchpad/checkpoint-sync). +Ao iniciar um nó Beacon em uma rede de teste, você pode economizar um tempo de sincronização significativo usando um endpoint público para [Sincronização de Ponto de verificação (Checkpoint sync)](https://notes.ethereum.org/@launchpad/checkpoint-sync). #### Executando um cliente de consenso {#running-a-consensus-client} ##### Executando o Lighthouse -Antes de executar o Lighthouse, saiba mais sobre como instalá-lo e configurá-lo na [Documentação do Lighthouse](https://lighthouse-book.sigmaprime.io/installation.html). +Antes de executar o Lighthouse, saiba mais sobre como instalá-lo e configurá-lo no [Lighthouse Book](https://lighthouse-book.sigmaprime.io/installation.html). ```sh lighthouse beacon_node \ @@ -344,16 +346,17 @@ Instale o software Lodestar compilando-o ou baixando a imagem do Docker. Saiba m ```sh lodestar beacon \ - --rootDir="/data/ethereum" \ + --dataDir="/data/ethereum" \ --network=mainnet \ --eth1.enabled=true \ - --execution.urls="http://127.0.1:8551" \ + --execution.urls="http://127.0.0.1:8551" \ --jwt-secret="/path/to/jwtsecret" ``` ##### Executando o Nimbus -O Nimbus vem com ambos os clientes de consenso e de execução. Ele pode ser executado em vários dispositivos, até mesmo com um poder de computação bem modesto. Após [instalar as dependências e o próprio Nimbus](https://nimbus.guide/quick-start.html), você pode executar seu cliente de consenso: +O Nimbus vem com ambos os clientes de consenso e de execução. Ele pode ser executado em vários dispositivos, até mesmo com um poder de computação bem modesto. +Após [instalar as dependências e o próprio Nimbus](https://nimbus.guide/quick-start.html), você pode executar seu cliente de consenso: ```sh nimbus_beacon_node \ @@ -365,7 +368,7 @@ nimbus_beacon_node \ ##### Executando o Prysm -O Prysm vem com um script que permite uma instalação automática fácil. Os detalhes podem ser encontrados na [documentação do Prysm](https://prysm.offchainlabs.com/docs/install-prysm/install-with-script/). +O Prysm vem com um script que permite uma instalação automática fácil. Detalhes podem ser encontrados na [documentação do Prysm](https://prysm.offchainlabs.com/docs/install-prysm/install-with-script/). ```sh ./prysm.sh beacon-chain \ @@ -384,51 +387,51 @@ teku --network mainnet \ --ee-jwt-secret-file "/path/to/jwtsecret" ``` -Quando um cliente de consenso se conecta ao cliente de execução para ler o contrato de depósito e identificar validadores, ele também se conecta a outros pares do Beacon Node e começa a sincronizar os slots de consenso da origem. Quando o Beacon Node atinge a época atual, a API Beacon se torna utilizável para seus validadores. Saiba mais sobre [APIs do Beacon Node](https://eth2docs.vercel.app/). +Quando um cliente de consenso se conecta ao cliente de execução para ler o contrato de depósito e identificar validadores, ele também se conecta a outros pares do Beacon Node e começa a sincronizar os slots de consenso da origem. Quando o Beacon Node atinge a época atual, a API Beacon se torna utilizável para seus validadores. Saiba mais sobre as [APIs do nó Beacon](https://eth2docs.vercel.app/). ### Adicionando validadores {#adding-validators} Um cliente de consenso serve como um Beacon Node para os validadores se conectarem. Cada cliente de consenso tem seu próprio software de validador descrito em detalhes em sua respectiva documentação. -Executar seu próprio validador permite a [participação individual](/staking/solo/), o método mais impactante e não confiável para dar suporte à rede Ethereum. No entanto, isso requer um depósito de 32 ETH. Para executar um validador em seu próprio nó com uma quantidade menor, um pool descentralizado com operadores de nós sem permissão, como [Rocket Pool](https://rocketpool.net/node-operators), poderá ser interessante. +Executar seu próprio validador permite o [staking individual](/staking/solo/), o método de maior impacto e sem necessidade de confiança para apoiar a rede Ethereum. No entanto, isso requer um depósito de 32 ETH. Para executar um validador em seu próprio nó com uma quantia menor, um pool descentralizado com operadores de nós sem permissão, como o [Rocket Pool](https://rocketpool.net/node-operators), pode ser do seu interesse. -A maneira mais fácil de começar a usar a geração de chaves de validação e staking é usar o [Holesky Testnet Staking Launchpad](https://holesky.launchpad.ethereum.org/), que permite testar sua configuração ao [executar nós no Holesky](https://notes.ethereum.org/@launchpad/holesky). Quando você estiver pronto para a Mainnet (Rede principal), você poderá repetir essas etapas usando a [Plataforma de lançamento de participação da Mainnet](https://launchpad.ethereum.org/). +A maneira mais fácil de começar com o staking e a geração de chaves de validador é usar a [Plataforma de Lançamento de Staking da Rede de Teste Hoodi](https://hoodi.launchpad.ethereum.org/), que permite testar sua configuração [executando nós na Hoodi](https://notes.ethereum.org/@launchpad/hoodi). Quando estiver pronto para a Mainnet, você poderá repetir essas etapas usando a [Plataforma de Lançamento de Staking da Mainnet](https://launchpad.ethereum.org/). -Consulte a [página de staking (participação)](/staking) para obter uma visão geral sobre as opções de participação. +Consulte a [página de staking](/staking) para ter uma visão geral sobre as opções de staking. ### Usando o nó {#using-the-node} -Os clientes de execução oferecem [pontos de extremidade da API RPC](/developers/docs/apis/json-rpc/) que você pode usar para enviar transações, interagir ou implantar contratos inteligentes na rede Ethereum de várias maneiras: +Os clientes de execução oferecem [endpoints da API RPC](/developers/docs/apis/json-rpc/) que você pode usar para enviar transações, interagir ou implantar contratos inteligentes na rede Ethereum de várias maneiras: - Chamando-os manualmente com um protocolo adequado (por exemplo, usando `curl`) -- Anexando um console (por exemplo, `geth attach`) -- Implementá-los em aplicações usando bibliotecas da Web3, por exemplo, [web3.py](https://web3py.readthedocs.io/en/stable/overview.html#overview), [ethers](https://github.com/ethers-io/ethers.js/) +- Anexando um console fornecido (por exemplo, `geth attach`) +- Implementando-os em aplicativos usando bibliotecas web3, por exemplo, [web3.py](https://web3py.readthedocs.io/en/stable/overview.html#overview), [ethers](https://github.com/ethers-io/ethers.js/) -Diferentes clientes têm diferentes implementações dos pontos de extremidade RPC. Porém, existe um JSON-RPC padrão que você pode usar com cada cliente. Para obter uma visão geral, [leia a documentação sobre JSON-RPC](/developers/docs/apis/json-rpc/). Os aplicativos que precisam de informações da rede Ethereum podem usar esse RPC. Por exemplo, a popular carteira MetaMask permite que você [se conecte ao seu próprio ponto de extremidade RPC](https://metamask.zendesk.com/hc/en-us/articles/360015290012-Using-a-Local-Node), que conta com grandes benefícios de privacidade e segurança. +Diferentes clientes têm diferentes implementações dos pontos de extremidade RPC. Porém, existe um JSON-RPC padrão que você pode usar com cada cliente. Para uma visão geral, [leia a documentação do JSON-RPC](/developers/docs/apis/json-rpc/). Os aplicativos que precisam de informações da rede Ethereum podem usar esse RPC. Por exemplo, a popular carteira MetaMask permite que você [se conecte ao seu próprio endpoint RPC](https://metamask.zendesk.com/hc/en-us/articles/360015290012-Using-a-Local-Node), o que tem fortes benefícios de privacidade e segurança. -Todos os clientes de consenso expõem uma [API Beacon](https://ethereum.github.io/beacon-APIs), que pode ser usada para verificar o status do cliente de consenso ou baixar blocos e dados de consenso enviando solicitações usando ferramentas como [Curl](https://curl.se). Mais informações sobre isso podem ser encontradas na documentação de cada cliente de consenso. +Todos os clientes de consenso expõem uma [API Beacon](https://ethereum.github.io/beacon-APIs) que pode ser usada para verificar o status do cliente de consenso ou baixar blocos e dados de consenso, enviando solicitações usando ferramentas como o [Curl](https://curl.se). Mais informações sobre isso podem ser encontradas na documentação de cada cliente de consenso. -#### Comunicação com o RPC {#reaching-rpc} +#### Acessando o RPC {#reaching-rpc} -A porta padrão para o cliente de execução JSON-RPC é `8545`, mas você pode modificar as portas dos pontos de extremidade locais na configuração. Por padrão, a interface RPC só pode ser acessada no host local do seu computador. Para torná-lo acessível remotamente, você pode expô-lo ao público alterando o endereço para `0.0.0.0`. Isso o tornará acessível pela rede local e endereços IP públicos. Na maioria dos casos, você também precisará configurar o encaminhamento de porta no seu roteador. +A porta padrão para o JSON-RPC do cliente de execução é `8545`, mas você pode modificar as portas dos endpoints locais na configuração. Por padrão, a interface RPC só pode ser acessada no host local do seu computador. Para torná-lo acessível remotamente, você pode querer expô-lo ao público alterando o endereço para `0.0.0.0`. Isso o tornará acessível pela rede local e endereços IP públicos. Na maioria dos casos, você também precisará configurar o encaminhamento de porta no seu roteador. Tenha cuidado ao expor as portas à Internet, pois isso permitirá que qualquer pessoa na Internet controle seu nó. Atores maliciosos poderão acessar seu nó para derrubar seu sistema ou roubar seus fundos se você estiver usando seu cliente como uma carteira. Uma forma de contornar isso é evitar que métodos RPC potencialmente nocivos sejam modificáveis. Por exemplo, com o Geth, você pode declarar métodos modificáveis com um sinalizador: `--http.api web3,eth,txpool`. -O acesso à interface RPC pode ser estendido por meio do desenvolvimento de APIs da camada de borda ou aplicativos de servidor Web, como o Nginx, e conectando-os ao endereço e porta locais do seu cliente. A utilização de uma camada intermediária também pode permitir que os desenvolvedores configurem um certificado para conexões `https` seguras na interface RPC. +O acesso à interface RPC pode ser estendido por meio do desenvolvimento de APIs da camada de borda ou aplicativos de servidor Web, como o Nginx, e conectando-os ao endereço e porta locais do seu cliente. Aproveitar uma camada intermediária também pode permitir que os desenvolvedores configurem um certificado para conexões `https` seguras com a interface RPC. -Configurar um servidor Web, um proxy ou uma API Rest externa não é a única maneira de fornecer acesso ao ponto de extremidade RPC do seu nó. Outra maneira de preservar a privacidade para configurar um ponto de extremidade publicamente acessível é hospedar o nó em seu próprio serviço onion da rede [Tor](https://www.torproject.org/). Isso permitirá que você se comunique com o RPC fora da sua rede local sem um endereço público estático de IP ou portas abertas. No entanto, usar essa configuração só permitirá que o ponto de extremidade RPC seja acessível pela da rede Tor, que não é suportada por todos os aplicativos e poderá resultar em problemas de conexão. +Configurar um servidor Web, um proxy ou uma API Rest externa não é a única maneira de fornecer acesso ao ponto de extremidade RPC do seu nó. Outra maneira de preservar a privacidade para configurar um endpoint publicamente acessível é hospedar o nó em seu próprio serviço onion do [Tor](https://www.torproject.org/). Isso permitirá que você se comunique com o RPC fora da sua rede local sem um endereço público estático de IP ou portas abertas. No entanto, usar essa configuração só permitirá que o ponto de extremidade RPC seja acessível pela da rede Tor, que não é suportada por todos os aplicativos e poderá resultar em problemas de conexão. -Para fazer isso, você precisa criar seu próprio [serviço onion](https://community.torproject.org/onion-services/). Confira [a documentação](https://community.torproject.org/onion-services/setup/) sobre a configuração do serviço onion para hospedar o seu próprio serviço. Você pode direcioná-lo para um servidor Web com proxy para a porta RPC ou apenas diretamente para o RPC. +Para fazer isso, você precisa criar seu próprio [serviço onion](https://community.torproject.org/onion-services/). Confira [a documentação](https://community.torproject.org/onion-services/setup/) sobre a configuração do serviço onion para hospedar o seu próprio. Você pode direcioná-lo para um servidor Web com proxy para a porta RPC ou apenas diretamente para o RPC. -Por fim, e uma das formas mais populares de fornecer acesso a redes internas, é por meio de uma conexão VPN. Dependendo do seu caso de uso e da quantidade de usuários que precisam de acesso ao seu nó, uma conexão VPN segura pode ser uma opção. [OpenVPN](https://openvpn.net/) é uma VPN SSL completa que implementa a extensão de rede segura da camada OSI 2 ou 3 usando o protocolo SSL/TLS padrão da indústria, dá suporte a métodos flexíveis de autenticação de cliente com base em certificados, cartões inteligentes e/ou credenciais de usuário/senha e permite políticas de controle de acesso específicas de usuário ou grupo usando regras de firewall aplicadas à interface virtual VPN. +Por fim, e uma das formas mais populares de fornecer acesso a redes internas, é por meio de uma conexão VPN. Dependendo do seu caso de uso e da quantidade de usuários que precisam de acesso ao seu nó, uma conexão VPN segura pode ser uma opção. [OpenVPN](https://openvpn.net/) é uma VPN SSL completa que implementa a extensão de rede segura da camada 2 ou 3 da OSI usando o protocolo SSL/TLS padrão da indústria, suporta métodos flexíveis de autenticação de cliente baseados em certificados, cartões inteligentes e/ou credenciais de nome de usuário/senha, e permite políticas de controle de acesso específicas de usuário ou grupo usando regras de firewall aplicadas à interface virtual da VPN. ### Operando o nó {#operating-the-node} Você deve monitorar regularmente seu nó para garantir que ele esteja funcionando corretamente. Talvez seja necessário realizar manutenções ocasionais. -#### Mantendo o nó online {#keeping-node-online} +#### Mantendo um nó online {#keeping-node-online} Seu nó não precisa estar online o tempo todo, mas você deve mantê-lo online o máximo possível para mantê-lo sincronizado com a rede. Você pode desligá-lo para reiniciá-lo, mas lembre-se de que: @@ -436,17 +439,17 @@ Seu nó não precisa estar online o tempo todo, mas você deve mantê-lo online - Encerramentos forçados podem danificar o banco de dados, exigindo que você ressincronize todo o nó. - Seu cliente ficará dessincronizado com a rede e precisará ser ressincronizado quando você o reiniciar. Embora o nó possa começar a sincronizar a partir do ponto do último encerramento, o processo pode demorar dependendo de quanto tempo ele esteve offline. -_Isso não se aplica a nós validadores da camada de consenso._ Colocar seu nó offline afetará todos os serviços dependentes dele. Se você estiver rodando um nó para fins de _staking (participação)_, você deve tentar minimizar o tempo de inatividade tanto quanto possível. +_Isso não se aplica aos nós validadores da camada de consenso._ Deixar seu nó offline afetará todos os serviços que dependem dele. Se você estiver executando um nó para fins de _staking_, deve tentar minimizar o tempo de inatividade o máximo possível. -#### Criando serviços de clientes {#creating-client-services} +#### Criando serviços de cliente {#creating-client-services} -Considere criar um serviço para executar seus clientes automaticamente na inicialização. Por exemplo, em servidores Linux, a boa prática seria criar um serviço, por exemplo, com `systemd`, que executa o cliente com a configuração adequada em um usuário com privilégios limitados, e reiniciar automaticamente. +Considere criar um serviço para executar seus clientes automaticamente na inicialização. Por exemplo, em servidores Linux, uma boa prática seria criar um serviço, por exemplo, com `systemd`, que executa o cliente com a configuração adequada, sob um usuário com privilégios limitados e reinicia automaticamente. #### Atualizando clientes {#updating-clients} -Você precisa manter seu software cliente atualizado com os patches de segurança, recursos e [EIPs](/eips/) mais recentes. Sobretudo antes das [bifurcações permanentes](/ethereum-forks/), verifique se você está executando as versões corretas do cliente. +Você precisa manter o software do seu cliente atualizado com os patches de segurança, recursos e [EIPs](/eips/) mais recentes. Especialmente antes de [bifurcações permanentes (hard forks)](/ethereum-forks/), certifique-se de que está executando as versões corretas do cliente. -> Antes de atualizações importantes da rede, a EF publica uma postagem em seu [blog](https://blog.ethereum.org). Você pode [fazer a inscrição nesses anúncios](https://blog.ethereum.org/category/protocol#subscribe) para receber uma notificação no seu e-mail quando o seu nó precisar de uma atualização. +> Antes de atualizações importantes da rede, a EF publica um post em seu [blog](https://blog.ethereum.org). Você pode [se inscrever nesses anúncios](https://blog.ethereum.org/category/protocol#subscribe) para receber uma notificação por e-mail quando seu nó precisar de uma atualização. Atualizar clientes é muito simples. Cada cliente tem instruções específicas em sua documentação, mas o processo geralmente é apenas baixar a versão mais recente e reiniciar o cliente com o novo executável. O cliente deve continuar de onde parou, mas com as atualizações aplicadas. @@ -454,27 +457,28 @@ Cada implementação de cliente tem uma cadeia de caracteres de versão legível #### Executando serviços adicionais {#running-additional-services} -Executar seu próprio nó permite que você use serviços que exigem acesso direto ao cliente RPC do Ethereum. Estes são serviços construídos em cima do Ethereum, como [soluções de camada 2](/developers/docs/scaling/#layer-2-scaling), back-end para carteiras, exploradores de blocos, ferramentas de desenvolvimento e outras infraestruturas do Ethereum. +Executar seu próprio nó permite que você use serviços que exigem acesso direto ao cliente RPC do Ethereum. São serviços construídos sobre o Ethereum, como [soluções de camada 2](/developers/docs/scaling/#layer-2-scaling), backend para carteiras, exploradores de blocos, ferramentas de desenvolvedor e outras infraestruturas do Ethereum. #### Monitorando o nó {#monitoring-the-node} Para monitorar seu nó corretamente, considere coletar métricas. Os clientes fornecem pontos de extremidade de métricas para que você possa obter dados abrangentes sobre seu nó. Use ferramentas como [InfluxDB](https://www.influxdata.com/get-influxdb/) ou [Prometheus](https://prometheus.io/) para criar bancos de dados que você pode transformar em visualizações e gráficos em softwares como o [Grafana](https://grafana.com/). Existem muitas configurações para usar esse software e diferentes painéis do Grafana para você visualizar seu nó e a rede como um todo. Por exemplo, confira o [tutorial sobre como monitorar o Geth](/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/). -Como parte do seu monitoramento, fique de olho no desempenho do seu computador. Durante a sincronização inicial do seu nó, o software cliente pode sobrecarregar muito a CPU e a memória RAM. Para fazer isso, além do Grafana, você pode usar as ferramentas que seu sistema operacional oferece, como `htop` ou `uptime`. +Como parte do seu monitoramento, fique de olho no desempenho do seu computador. Durante a sincronização inicial do seu nó, o software cliente pode sobrecarregar muito a CPU e a memória RAM. Além do Grafana, você pode usar as ferramentas que seu sistema operacional oferece, como `htop` ou `uptime`, para fazer isso. ## Leitura adicional {#further-reading} -- [Guias de participação do Ethereum](https://github.com/SomerEsat/ethereum-staking-guides) — _Somer Esat, atualizado regularmente_ -- [Guia | Como configurar um validador para participação do Ethereum na rede principal](https://www.coincashew.com/coins/overview-eth/guide-or-how-to-setup-a-validator-on-eth2-mainnet) _— CoinCashew, atualizado regularmente_ -- [Guias do ETHStaker sobre como executar validadores em redes de teste](https://github.com/remyroy/ethstaker#guides) — _ETHStaker, atualizado regularmente_ -- [Perguntas frequentes sobre o The Merge para operadores de nós](https://notes.ethereum.org/@launchpad/node-faq-merge) — _julho de 2022_ -- [Analisando os requisitos de hardware para tornar um nó totalmente validado no Ethereum](https://medium.com/coinmonks/analyzing-the-hardware-requirements-to-be-an-ethereum-full-validated-node-dc064f167902) _– Albert Palau, 24 de setembro de 2018_ -- [Executando nós completos do Ethereum: um guia para os pouco motivados](https://medium.com/@JustinMLeroux/running-ethereum-full-nodes-a-guide-for-the-barely-motivated-a8a13e7a0d31) _— Justin Leroux, 7 de novembro de 2019_ -- [Executando um nó do Hyperledger Besu na Mainnet (Rede principal) do Ethereum: benefícios, requisitos e configurações](https://pegasys.tech/running-a-hyperledger-besu-node-on-the-ethereum-mainnet-benefits-requirements-and-setup/) _— Felipe Faraggi, 7 de maio de 2020_ -- [Implantando o cliente Nethermind do Ethereum com uma pilha de monitoramento](https://medium.com/nethermind-eth/deploying-nethermind-ethereum-client-with-monitoring-stack-55ce1622edbd) _— Nethermind.eth, 8 de julho de 2020_ +- [Guias de Staking do Ethereum](https://github.com/SomerEsat/ethereum-staking-guides) - _Somer Esat, atualizado com frequência_ +- [Guia | Como configurar um validador para staking de Ethereum na mainnet](https://www.coincashew.com/coins/overview-eth/guide-or-how-to-setup-a-validator-on-eth2-mainnet) _– CoinCashew, atualizado com frequência_ +- [Guias do ETHStaker sobre como executar validadores em redes de teste](https://github.com/remyroy/ethstaker#guides) – _ETHStaker, atualizado regularmente_ +- [Aplicativo de exemplo AWS Blockchain Node Runner para nós Ethereum](https://aws-samples.github.io/aws-blockchain-node-runners/docs/Blueprints/Ethereum) - _AWS, atualizado com frequência_ +- [FAQ da Fusão para operadores de nós](https://notes.ethereum.org/@launchpad/node-faq-merge) - _Julho de 2022_ +- [Analisando os requisitos de hardware para ser um nó Ethereum totalmente validado](https://medium.com/coinmonks/analyzing-the-hardware-requirements-to-be-an-ethereum-full-validated-node-dc064f167902) _– Albert Palau, 24 de setembro de 2018_ +- [Executando Nós Completos de Ethereum: Um Guia para os Pouco Motivados](https://medium.com/@JustinMLeroux/running-ethereum-full-nodes-a-guide-for-the-barely-motivated-a8a13e7a0d31) _– Justin Leroux, 7 de novembro de 2019_ +- [Executando um nó Hyperledger Besu na Mainnet do Ethereum: benefícios, requisitos e configuração](https://pegasys.tech/running-a-hyperledger-besu-node-on-the-ethereum-mainnet-benefits-requirements-and-setup/) _– Felipe Faraggi, 7 de maio de 2020_ +- [Implantando o cliente Nethermind do Ethereum com a pilha de monitoramento](https://medium.com/nethermind-eth/deploying-nethermind-ethereum-client-with-monitoring-stack-55ce1622edbd) _– Nethermind.eth, 8 de julho de 2020_ ## Tópicos relacionados {#related-topics} -- [ Nós e clientes](/developers/docs/nodes-and-clients/) +- [Nós e clientes](/developers/docs/nodes-and-clients/) - [Blocos](/developers/docs/blocks/) - [Redes](/developers/docs/networks/) diff --git a/public/content/translations/pt-br/developers/docs/oracles/index.md b/public/content/translations/pt-br/developers/docs/oracles/index.md index c9a684095b1..da2b0e6bc82 100644 --- a/public/content/translations/pt-br/developers/docs/oracles/index.md +++ b/public/content/translations/pt-br/developers/docs/oracles/index.md @@ -1,64 +1,64 @@ --- -title: Oráculos -description: Oráculos fornecem contratos inteligentes Ethereum com acesso a dados do mundo real, desbloqueando mais casos de uso e maior valor para os usuários. +title: "Oráculos" +description: "Oráculos fornecem contratos inteligentes Ethereum com acesso a dados do mundo real, desbloqueando mais casos de uso e maior valor para os usuários." lang: pt-br --- -Oráculos são feeds de dados que trazem dados de fontes de dados fora da blockchain (off-chain) e os colocam na blockchain (on-chain) para uso em contratos inteligentes. Isso é necessário porque os contratos inteligentes executados no Ethereum não podem acessar informações armazenadas fora da rede blockchain. +Oráculos são aplicações que produzem data feeds que fazem dados offchain disponíveis aos contratos inteligentes. Isso é necessário porque os contratos inteligentes baseados em Ethereum não podem, por padrão, acessar informações armazenadas fora da rede blockchain. -Dar aos contratos inteligentes a capacidade de executar usando entradas de dados fora da cadeia aumenta o valor dos aplicativos descentralizados. Por exemplo, os mercados de previsão descentralizados dependem de oráculos para fornecer informações sobre os resultados com os quais podem validar as previsões do usuário. Suponha que Alice aposte 20 ETH em quem se tornará o próximo presidente americano. Nesse caso, o dapp do mercado de previsão precisa de um oráculo para confirmar os resultados das eleições e determinar se Alice é elegível para um pagamento. +Dar aos contratos inteligentes a capacidade de utilizar dados offchain amplia a utilidade e o valor das aplicações descentralizadas. Por exemplo, os onchain prediction markets dependem de oráculos para fornecer resultados que eles utilizam para validar as previsões aos usuários. Suponha que Alice aposte 20 ETH em quem se tornará o próximo presidente americano. Nesse caso, o dapp do mercado de previsão precisa de um oráculo para confirmar os resultados das eleições e determinar se Alice é elegível para um pagamento. ## Pré-requisitos {#prerequisites} -Esta página assume que o leitor está familiarizado com os fundamentos do Ethereum, incluindo [nós](/developers/docs/nodes-and-clients/), [mecanismos de consenso](/developers/docs/consensus-mechanisms/) e a [EVM](/developers/docs/evm/). Você também deve ter uma boa compreensão de [contratos inteligentes](/developers/docs/smart-contracts/) e [anatomia de contratos inteligentes](/developers/docs/smart-contracts/anatomy/), especialmente de [eventos](/glossary/#events). +Esta página pressupõe que o leitor esteja familiarizado com os fundamentos do Ethereum, incluindo [nós](/developers/docs/nodes-and-clients/), [mecanismos de consenso](/developers/docs/consensus-mechanisms/) e a [EVM](/developers/docs/evm/). Você também deve ter um bom conhecimento de [contratos inteligentes](/developers/docs/smart-contracts/) e da [anatomia de contratos inteligentes](/developers/docs/smart-contracts/anatomy/), especialmente [eventos](/glossary/#events). ## O que é um oráculo blockchain? {#what-is-a-blockchain-oracle} -Oráculos são aplicativos que fornecem, verificam e transmitem informações externas (ou seja, informações armazenadas fora da cadeia) para contratos inteligentes em execução na blockchain. Além de “puxar” dados off-chain e transmiti-los no Ethereum, os oráculos também podem “enviar” informações da blockchain para sistemas externos. Um exemplo deste último poderia ser um oráculo que desbloqueia um bloqueio de contrato inteligente assim que o usuário envia a taxa por meio de uma transação Ethereum. +Oráculos são aplicações que obtêm, verificam e transmitem informações externas (ou seja, informações armazenadas fora da cadeia) para contratos inteligentes em execução na cadeia de blocos. Além de 'puxar' dados off-chain e transmiti-los no Ethereum, oráculos também podem 'empurrar' informações da blockchain para sistemas externos, por exemplo, destravando um bloqueio inteligente assim que o usuário envia uma taxa por meio de uma transação Ethereum. -Oráculos atuam como uma "ponte" conectando contratos inteligentes em blockchains a provedores de dados off-chain. Sem os oráculos, os aplicativos de contratos inteligentes só poderiam acessar dados on-chain. Um oráculo fornece um mecanismo para acionar funções de contrato inteligente usando dados off-chain. +Sem oráculo, um contrato inteligente estaria totalmente limitado aos dados on-chain. -Oráculos diferem com base na fonte de dados (uma ou várias fontes), modelos de confiança (centralizados ou descentralizados) e arquitetura do sistema (leitura imediata, publicação-assinatura e solicitação-resposta). Também podemos distinguir entre oráculos baseados em se eles recuperam dados externos para uso por contratos em cadeia (oráculos de entrada), enviam informações da blockchain para os aplicativos fora de cadeia (oráculos de saída) ou executam tarefas computacionais fora de cadeia (oráculos computacionais). +Oráculos diferem com base na fonte de dados (uma ou várias fontes), modelos de confiança (centralizados ou descentralizados) e arquitetura do sistema (leitura imediata, publicação-assinatura e solicitação-resposta). Também podemos distinguir oráculos baseados em se eles recuperam dados externos por contratos onchain (oráculos de entrada), enviam informações do blockchain para as aplicações offchain (oráculos de saída) ou executam tarefas computacionais offchain (oráculos computacionais). ## Por que os contratos inteligentes precisam de oráculos? {#why-do-smart-contracts-need-oracles} -A maioria dos desenvolvedores vê os contratos inteligentes como simples pedaços de código rodando em endereços específicos na blockchain. No entanto uma visão mais geral [dos contratos inteligentes](/smart-contracts/) é que eles são programas de software autoexecutáveis capazes de forçar acordos entre as partes uma vez que as condições específicas sejam cumpridas, o que explica o termo "contratos inteligentes". +Muitos desenvolvedores veem os contratos inteligentes como código executado em endereços específicos na blockchain. No entanto, uma [visão mais geral dos contratos inteligentes](/smart-contracts/) é que eles são programas de software autoexecutáveis capazes de aplicar acordos entre as partes assim que condições específicas forem atendidas - daí o termo “contratos inteligentes”. -Mas usar contratos inteligentes para aplicar acordos entre pessoas não é fácil, uma vez que o Ethereum é determinístico. Um [sistema determinístico](https://en.wikipedia.org/wiki/Deterministic_algorithm) é aquele que sempre produz os mesmos resultados dado um estado inicial e uma entrada em particular – não há aleatoriedade ou variação no processo de computar as saídas das entradas. +Mas usar contratos inteligentes para aplicar acordos entre pessoas não é fácil, uma vez que o Ethereum é determinístico. Um [sistema determinístico](https://en.wikipedia.org/wiki/Deterministic_algorithm) é aquele que sempre produz os mesmos resultados, dado um estado inicial e uma entrada específica, o que significa que não há aleatoriedade ou variação no processo de computação das saídas a partir das entradas. -Para alcançar a execução determinística, as blockchains limitam os nós para alcançar consenso sobre questões binárias simples (verdadeiro/falso) usando _somente_ dados armazenados na própria blockchain. Exemplos de tais perguntas incluem: +Para alcançar a execução determinística, as cadeias de blocos limitam os nós a alcançar um consenso sobre questões binárias simples (verdadeiro/falso) usando _somente_ dados armazenados na própria cadeia de blocos. Exemplos de tais perguntas incluem: - “O proprietário da conta (identificado por uma chave pública) assinou esta transação com a chave privada emparelhada?” - “Esta conta tem fundos suficientes para cobrir a transação?” - “Esta transação é válida no contexto deste contrato inteligente?” etc. -Se blockchains recebessem informações de fontes externas (ou seja, do mundo real), seria impossível alcançar o determinismo, impedindo que os nós concordassem com a validade das mudanças no estado da blockchain. Tomemos, por exemplo, um contrato inteligente que executa uma transação baseada na taxa de câmbio atual ETH-USD obtida de uma API de preço tradicional. Esse número provavelmente mudaria frequentemente (sem mencionar que a API poderia ser depreciada ou hackeada), o que significa que os nós que executam o mesmo código de contrato chegariam a resultados diferentes. +Se blockchains recebessem informações de fontes externas (ou seja, do mundo real), seria impossível alcançar o determinismo, impedindo que os nós concordassem com a validade das mudanças no estado da blockchain. Tomemos, por exemplo, um contrato inteligente que executa uma transação baseada na taxa de câmbio atual ETH-USD obtida de uma API de preço tradicional. Essa informação provavelmente mudará com frequência (sem mencionar que a API pode ser descontinuada ou hackeada), o que significa que os nós executando o mesmo código de contrato chegariam a resultados diferentes. -Para uma blockchain pública, como a Ethereum, com milhares de nós em todo o mundo processando transações, o determinismo é crítico. Sem nenhuma autoridade central servindo como fonte da verdade, é esperado que os nós devam chegar ao mesmo estado após aplicar as mesmas transações. Um caso em que o nó A executa um código de um contrato inteligente e obtém "3" como resultado, enquanto o nó B obtém "7" após executar a mesma transação causaria a quebra do consenso e eliminaria o valor do Ethereum como uma plataforma de computação descentralizada. +Para uma blockchain pública como o Ethereum, com milhares de nós ao redor do mundo processando transações, o determinismo é crucial. Sem uma autoridade central servindo como fonte da verdade, os nós precisam de mecanismos para chegar ao mesmo estado após aplicar as mesmas transações. Um caso em que o nó A executa um código de um contrato inteligente e obtém "3" como resultado, enquanto o nó B obtém "7" após executar a mesma transação causaria a quebra do consenso e eliminaria o valor do Ethereum como uma plataforma de computação descentralizada. -O cenário descrito anteriormente também destaca o problema de projetar blockchains para extrair informações de fontes externas. Os oráculos, no entanto, resolvem esse problema pegando informações de fontes off-chain e armazenando-as na blockchain para consumo de contratos inteligentes. Como as informações armazenadas na cadeia são inalteráveis e disponíveis publicamente, os nós do Ethereum podem usar com segurança os dados off-chain importados do oráculo para calcular as mudanças de estado sem quebrar o consenso. +Esse cenário também destaca o problema de projetar blockchains para obter informações de fontes externas. Oráculos, no entanto, resolvem este problema pegando informações off-chain e armazenando-as no blockchain por contratos inteligentes. As informações armazenadas onchain são inalteráveis e disponíveis publicamente, por isso os nós do Ethereum podem usar com segurança os dados off-chain importados por oráculo para calcular as mudanças de estado sem quebrar o consenso. -Para fazer isso, um oráculo é normalmente composto de um contrato inteligente executado on-chain e alguns componentes off-chain. O contrato on-chain recebe solicitações de dados de outros contratos inteligentes, que ele passa para o componente off-chain (chamado nó oráculo). Esse nó oráculo pode consultar fontes de dados – usando interfaces de programação de aplicativos (APIs), por exemplo – e enviar transações para armazenar os dados solicitados no armazenamento do contrato inteligente. +Por isto, um oráculo é normalmente composto de um contrato inteligente executado on-chain e alguns componentes off-chain. O contrato on-chain recebe pedido de dados de outros contratos inteligentes e ele passa os pedidos para off-chain (chamado nó de oráculo). Esse nó oráculo pode consultar fontes de dados – usando interfaces de programação de aplicativos (APIs), por exemplo – e enviar transações para armazenar os dados solicitados no armazenamento do contrato inteligente. -Essencialmente, um oráculo da blockchain preenche a lacuna de informações entre a blockchain e o ambiente externo, criando “contratos inteligentes híbridos”. Um contrato inteligente híbrido é aquele que funciona baseado em uma combinação de código de contrato on-chain e infraestrutura off-chain. Os mercados de previsão descentralizados, descritos na introdução, são um excelente exemplo de contratos inteligentes híbridos. Outros exemplos podem incluir contratos inteligentes de seguro de colheitas que pagam quando um conjunto de oráculos determina que certos fenômenos climáticos ocorreram. +Essencialmente, um oráculo da blockchain preenche a lacuna de informações entre a blockchain e o ambiente externo, criando “contratos inteligentes híbridos”. Um contrato inteligente híbrido é a combinação de código de contrato on-chain e infraestrutura off-chain. Mercados de previsão descentralizados são um excelente exemplo de contratos inteligentes híbridos. Outros exemplos podem incluir contratos inteligentes de seguro de colheitas que pagam quando um conjunto de oráculos determina que certos fenômenos climáticos ocorreram. -## Qual é o problema do oráculo? {#the-oracle-problem} +## Qual é o problema do oráculo? O problema do oráculo {#the-oracle-problem} -É fácil fornecer aos contratos inteligentes acesso a dados off-chain, contando com uma entidade (ou várias entidades) para introduzir informações extrínsecas à blockchain, armazenando os dados no corpo de uma transação. Mas isso traz novos problemas: +Os oráculos resolvem um problema importante, mas também introduzem algumas complicações, por ex.,: - Como verificamos que as informações injetadas foram extraídas da fonte correta ou não foram adulteradas? - Como garantimos que esses dados estejam sempre disponíveis e atualizados regularmente? -O chamado “problema do oráculo” demonstra os problemas que surgem com o uso de oráculos da blockchain para enviar entradas para contratos inteligentes. É fundamental garantir que os dados de um oráculo estejam corretos ou a execução do contrato inteligente produzirá resultados errados. Também é importante a necessidade da falta de confiança - ter que "confiar" nos operadores do oráculo para fornecer informações precisas de forma confiável rouba dos contratos inteligentes suas qualidades mais importantes. +O chamado “problema do oráculo” demonstra os problemas que surgem com o uso de oráculos da blockchain para enviar entradas para contratos inteligentes. Dados de um oráculo devem estar corretos para um contrato inteligente executar corretamente. Além disso, ter que "confiar" em operadores de oráculos para prover informação precisa mitiga o aspecto "incerto" dos contratos inteligentes. -Diferentes oráculos diferem na sua abordagem para resolver o problema do oráculo, e exploramos estas abordagens mais tarde. Embora nenhum oráculo seja perfeito, os méritos de um oráculo devem ser medidos com base em como ele lida com os seguintes desafios: +Diferentes oráculos oferecem diferentes soluções para o problema do oráculo, algo que veremos depois. Os oráculos são geralmente avaliados de acordo com a capacidade deles de lidar com os seguintes desafios: -1. **Exatidão**: um oráculo não deve fazer com que contratos inteligentes acionem mudanças de estado com base em dados inválidos off-chain. Por esse motivo, um oráculo deve garantir a _autenticidade_ e a _integridade_ dos dados – autenticidade significa que os dados foram obtidos da fonte correta, enquanto a integridade significa que os dados permaneceram intactos (ou seja, não foram alterados) antes de serem enviados on-chain. +1. **Correção**: Um oráculo não deve fazer com que contratos inteligentes acionem alterações de estado com base em dados inválidos fora da cadeia. Um oráculo deve garantir a _autenticidade_ e a _integridade_ dos dados. Autenticidade significa que os dados foram obtidos da fonte correta, enquanto integridade significa que os dados permaneceram intactos (ou seja, não foram alterados) antes de serem enviados para a cadeia. -2. **Disponibilidade**: um oráculo não deve atrasar ou impedir os contratos inteligentes de executar ações e acionar alterações de estado. Essa qualidade exige que os dados de um oráculo estejam _disponíveis mediante solicitação_ sem interrupção. +2. **Disponibilidade**: Um oráculo não deve atrasar ou impedir que contratos inteligentes executem ações e acionem alterações de estado. Isso significa que os dados de um oráculo devem estar _disponíveis sob demanda_ sem interrupção. -3. **Compatibilidade de incentivos**: um oráculo deve incentivar provedores de dados off-chain a enviar informações corretas para contratos inteligentes. A compatibilidade de incentivo envolve _atribuição_ e _responsabilidade_. A atribuição permite correlacionar um pedaço da informação externa ao seu provedor, enquanto a responsabilidade vincula os provedores de dados às informações que eles fornecem, de modo que podem ser recompensados ou penalizados com base na qualidade das informações fornecidas. +3. **Compatibilidade de incentivos**: Um oráculo deve incentivar os provedores de dados fora da cadeia a enviar informações corretas para contratos inteligentes. A compatibilidade de incentivos envolve _atribuibilidade_ e _responsabilização_. A capacidade de atribuição permite vincular uma parte da informação externa para o provedor dela, enquanto responsabilidade liga provedores de dados às informações fornecidas, de forma que sejam recompensados ou penalizados baseado na qualidade da informação provida. ## Como funciona um serviço de oráculo na blockchain? {#how-does-a-blockchain-oracle-service-work} @@ -66,7 +66,7 @@ Diferentes oráculos diferem na sua abordagem para resolver o problema do orácu Usuários são entidades (ou seja, contratos inteligentes) que precisam de informação externa à blockchain para completar ações específicas. O fluxo de trabalho básico de um serviço oráculo começa com o usuário enviando uma requisição de dados para o contrato oracle. Os pedidos de dados geralmente respondem a algumas ou todas as seguintes perguntas: -1. Que fontes podem os nós off-chain consultar para conseguir as informações solicitadas? +1. What sources can offchain nodes consult for the requested information? 2. Como os informantes processam informações de fontes de dados e extraem pontos de dados úteis? @@ -76,41 +76,41 @@ Usuários são entidades (ou seja, contratos inteligentes) que precisam de infor 5. Qual método deve ser implementado na filtragem de submissões e agregações dos relatórios em um único valor? -### Contrato de oráculo {#oracle-contract} +### Contrato do oráculo {#oracle-contract} -O contrato de um oráculo é o componente on-chain para o serviço do oráculo: ele escuta solicitações de dados de outros contratos, retransmite consultas de dados para nós oráculos e transmite dados retornados para contratos de clientes. Este contrato também pode executar alguma computação sobre os pontos de dados retornados para produzir um valor agregado que envia ao contrato solicitante. +O contrato de oráculo é componente onchain por serviço de oráculo. Esse aguarda requisitos de dados de outros contratos, encaminha consultas de dados para nós oráculos e transmite os dados retornados para os contratos dos clientes. Este contrato também pode realizar alguns cálculos nos dados retornados para produzir um valor agregado a ser enviado para o contrato solicitante. -O contrato oráculo expõe algumas funções que os contratos do cliente chamam ao fazer uma solicitação de dados. Ao receber uma nova consulta, o contrato inteligente emitirá um [evento de log](/developers/docs/smart-contracts/anatomy/#events-and-logs) com detalhes da solicitação de dados. Isso notifica os nós off-chain inscritos no log (geralmente usando algo como o comando JSON-RPC `eth_subscribe`), que procedem a recuperar os dados definidos no evento de log. +O contrato oráculo expõe algumas funções que os contratos do cliente chamam ao fazer uma solicitação de dados. Ao receber uma nova consulta, o contrato inteligente emitirá um [evento de log](/developers/docs/smart-contracts/anatomy/#events-and-logs) com detalhes da solicitação de dados. Isso notifica os nós fora da cadeia inscritos no log (geralmente usando algo como o comando JSON-RPC `eth_subscribe`), que então recuperam os dados definidos no evento de log. -Abaixo está um [exemplo de contrato oráculo](https://medium.com/@pedrodc/implementing-a-blockchain-oracle-on-ethereum-cedc7e26b49e) por Pedro Costa. Este é um serviço simples de oráculo que pode consultar APIs off-chain mediante solicitação de outros contratos inteligentes e armazenar as informações solicitadas na blockchain: +Abaixo está um [exemplo de contrato de oráculo](https://medium.com/@pedrodc/implementing-a-blockchain-oracle-on-ethereum-cedc7e26b49e) por Pedro Costa. É um serviço de oráculo consultar APIs off-chain e armazenar as informações no blockchain: ```solidity pragma solidity >=0.4.21 <0.6.0; contract Oracle { - Request[] requests; //list of requests made to the contract - uint currentId = 0; //increasing request id - uint minQuorum = 2; //minimum number of responses to receive before declaring final result - uint totalOracleCount = 3; // Hardcoded oracle count + Request[] requests; //lista de solicitações feitas ao contrato + uint currentId = 0; //id da solicitação crescente + uint minQuorum = 2; //número mínimo de respostas a serem recebidas antes de declarar o resultado final + uint totalOracleCount = 3; // Contagem de oráculos codificada - // defines a general api request + // define uma solicitação de API geral struct Request { - uint id; //request id - string urlToQuery; //API url - string attributeToFetch; //json attribute (key) to retrieve in the response - string agreedValue; //value from key - mapping(uint => string) answers; //answers provided by the oracles - mapping(address => uint) quorum; //oracles which will query the answer (1=oracle hasn't voted, 2=oracle has voted) + uint id; //id da solicitação + string urlToQuery; //URL da API + string attributeToFetch; //atributo json (chave) a ser recuperado na resposta + string agreedValue; //valor da chave + mapping(uint => string) answers; //respostas fornecidas pelos oráculos + mapping(address => uint) quorum; //oráculos que consultarão a resposta (1=oráculo não votou, 2=oráculo votou) } - //event that triggers oracle outside of the blockchain + //evento que aciona o oráculo fora da cadeia de blocos event NewRequest ( uint id, string urlToQuery, string attributeToFetch ); - //triggered when there's a consensus on the final result + //acionado quando há um consenso sobre o resultado final event UpdatedRequest ( uint id, string urlToQuery, @@ -127,23 +127,23 @@ contract Oracle { uint length = requests.push(Request(currentId, _urlToQuery, _attributeToFetch, "")); Request storage r = requests[length-1]; - // Hardcoded oracles address + // Endereço dos oráculos codificado r.quorum[address(0x6c2339b46F41a06f09CA0051ddAD54D1e582bA77)] = 1; r.quorum[address(0xb5346CF224c02186606e5f89EACC21eC25398077)] = 1; r.quorum[address(0xa2997F1CA363D11a0a35bB1Ac0Ff7849bc13e914)] = 1; - // launch an event to be detected by oracle outside of blockchain + // lança um evento a ser detectado pelo oráculo fora da cadeia de blocos emit NewRequest ( currentId, _urlToQuery, _attributeToFetch ); - // increase request id + // aumenta o id da solicitação currentId++; } - //called by the oracle to record its answer + //chamado pelo oráculo para registrar sua resposta function updateRequest ( uint _id, string memory _valueRetrieved @@ -151,18 +151,18 @@ contract Oracle { Request storage currRequest = requests[_id]; - //check if oracle is in the list of trusted oracles - //and if the oracle hasn't voted yet + //verifica se o oráculo está na lista de oráculos confiáveis + //e se o oráculo ainda não votou if(currRequest.quorum[address(msg.sender)] == 1){ - //marking that this address has voted + //marcando que este endereço votou currRequest.quorum[msg.sender] = 2; - //iterate through "array" of answers until a position if free and save the retrieved value + //itera através do "array" de respostas até que uma posição esteja livre e salva o valor recuperado uint tmpI = 0; bool found = false; while(!found) { - //find first empty slot + //encontra o primeiro espaço vazio if(bytes(currRequest.answers[tmpI]).length == 0){ found = true; currRequest.answers[tmpI] = _valueRetrieved; @@ -172,8 +172,8 @@ contract Oracle { uint currentQuorum = 0; - //iterate through oracle list and check if enough oracles(minimum quorum) - //have voted the same answer has the current one + //itera através da lista de oráculos e verifica se há oráculos suficientes (quórum mínimo) + //votaram na mesma resposta que a atual for(uint i = 0; i < totalOracleCount; i++){ bytes memory a = bytes(currRequest.answers[i]); bytes memory b = bytes(_valueRetrieved); @@ -196,63 +196,59 @@ contract Oracle { } ``` -### Nós oráculos {#oracle-nodes} +### Nós de oráculo {#oracle-nodes} -O nó oráculo é o componente off-chain de serviço do oráculo: ele extrai as informações de fontes externas, como APIs hospedadas em servidores de terceiros, e as coloca on-chain para consumo por contratos inteligentes. Os nós oráculos escutam eventos do contrato oráculo on-chain e prosseguem para completar a tarefa descrita no log. +O nó de oráculo é o componente off-chain do serviço de oráculo. Ele extrai informações externas e as coloca onchain para serem usadas por contratos inteligentes. Os nós de oráculo seguem contratos de oráculo on-chain para completar a tarefa no log. -Uma tarefa comum para nós oráculos é enviar uma solicitação [HTTP GET](https://www.w3schools.com/tags/ref_httpmethods.asp) para um serviço de API, analisar a resposta para extrair dados relevantes, formatar em uma saída legível para blockchain e enviá-la on-chain incluindo-a em uma transação para o contrato do oráculo. Também é possível que seja solicitado ao nó oráculo atestar a validade e a integridade das informações enviadas usando “provas de autenticidade”, que veremos mais adiante. +Uma tarefa comum para nós de oráculo é enviar uma solicitação [HTTP GET](https://www.w3schools.com/tags/ref_httpmethods.asp) para um serviço de API, analisar a resposta para extrair dados relevantes, formatá-la em uma saída legível pela cadeia de blocos e enviá-la para a cadeia, incluindo-a em uma transação para o contrato do oráculo. Também é possível que seja solicitado ao nó oráculo atestar a validade e a integridade das informações enviadas usando “provas de autenticidade”, que veremos mais adiante. -Os oráculos computacionais também dependem de nós off-chain para executar tarefas computacionais intensivas, o qual seria impraticável de executar on-chain, devido aos custos de gás e aos limites de tamanho do bloco. Por exemplo, o nó oráculo pode ser encarregado de gerar uma figura verificável aleatória (por exemplo, para jogos baseados em blockchain). +Oráculos computacionais também dependem de nós off-chain para executar tarefas computacionais que seriam impraticáveis de realizar on-chain, devido aos custos de gás e aos limites de tamanho dos blocos. Por exemplo, o nó oráculo pode ser encarregado de gerar uma figura verificável aleatória (por exemplo, para jogos baseados em blockchain). -## Padrões de projeto em oráculos {#oracle-design-patterns} +## Padrões de design de oráculos {#oracle-design-patterns} -Oráculos vêm em diferentes tipos, incluindo _leitura imediata_, _publicação-assinatura_ e _solicitação-resposta_, com os dois últimos sendo os mais populares entre os contratos inteligentes do Ethereum. Abaixo está uma breve descrição dos dois tipos de serviços de oráculos: +Os oráculos vêm em diferentes tipos, incluindo _leitura imediata_, _publicação-assinatura_ e _solicitação-resposta_, sendo os dois últimos os mais populares entre os contratos inteligentes do Ethereum. Aqui descrevemos brevemente os modelos de "publicação-assinatura" e "solicitação-resposta". -### Publicação-assinatura de oráculos {#publish-subscribe-oracles} +### Oráculos de publicação-assinatura {#publish-subscribe-oracles} -Um serviço de oráculo baseado em um mecanismo de publicação-assinatura expõe um “feed de dados” que outros contratos podem ler regularmente para obter informações. Neste caso, espera-se que os dados mudem com frequência, portanto, os contratos do cliente devem ouvir as atualizações dos dados no armazenamento do oráculo. Um excelente exemplo é um oráculo que fornece informações sobre o último preço ETH-USD para os usuários. +Este tipo de oráculo expõe um “feed de dados” que outros contratos podem ler regularmente para obter informações. Neste caso, espera-se que os dados mudem com frequência, portanto, os contratos do cliente devem ouvir as atualizações dos dados no armazenamento do oráculo. Um exemplo é um oráculo que fornece as informações mais recentes sobre o preço ETH-USD aos usuários. -### Solicitação-resposta de oráculos {#request-response-oracles} +### Oráculos de solicitação-resposta {#request-response-oracles} -Uma configuração de solicitação-resposta permite que o contrato do cliente solicite dados arbitrários diferentes daqueles fornecidos por um oráculo de publicação-assinatura. Oráculos de solicitação-resposta são ideais nas seguintes condições: +Uma configuração de solicitação-resposta permite que o contrato do cliente solicite dados arbitrários diferentes daqueles fornecidos por um oráculo de publicação-assinatura. Os oráculos de solicitação-resposta são ideais quando o conjunto de dados é muito grande para ser guardado no armazenamento de um contrato inteligente e/ou os usuários precisarão apenas de uma pequena parte dos dados em qualquer momento. -- O conjunto de dados é muito grande para ser armazenado em um contrato inteligente +Embora mais complexos do que os modelos de publicação-assinatura, os oráculos de solicitação-resposta são basicamente o que descrevemos na seção anterior. O oráculo vai ter um componente on-chain que recebe uma solicitação de dados e a passa para nó off-chain para processamento. -- Os usuários só precisarão de uma pequena parte dos dados a qualquer momento +Os usuários que requerem dados devem pagar as informações off-chain. O contrato do cliente também deve fornecer fundos para cobrir os custos de gás incorridos pelo contrato do oráculo ao retornar a resposta por meio de uma função de callback (função de retorno da chamada) na solicitação. -Embora mais complexos do que os modelos de publicação-assinatura, os oráculos de solicitação-resposta são basicamente o que descrevemos na seção anterior. O oráculo terá um componente on-chain que recebe uma solicitação de dados e a passa para um nó off-chain para processamento. - -Os usuários que iniciam consultas de dados devem cobrir o custo de obter informações da fonte off-chain. O contrato do cliente também deve fornecer fundos para cobrir os custos de gás incorridos pelo contrato do oráculo ao retornar a resposta por meio de uma função de callback (função de retorno da chamada) na solicitação. - -## Tipos de oráculos {#types-of-oracles} +## Oráculos centralizados vs. descentralizados {#types-of-oracles} ### Oráculos centralizados {#centralized-oracles} -Um oráculo centralizado é controlado por uma única entidade responsável por agregar informações off-chain e atualizar os dados do contrato do oráculo conforme solicitado. Os oráculos centralizados são eficientes uma vez que dependem de uma única fonte de verdade. Eles podem até ser preferíveis nos casos em que os conjuntos de dados proprietários são publicados diretamente pelo proprietário com uma assinatura amplamente aceita. No entanto, usar um oráculo centralizado traz vários problemas. +Oráculo centralizado é controlado por uma única entidade responsável por agregar informações off-chain e atualizar os dados de contrato de oráculo conforme solicitado. Os oráculos centralizados são eficientes uma vez que dependem de uma única fonte de verdade. Eles podem funcionar melhor em casos em que conjuntos de dados proprietários são publicados diretamente pelo proprietário com uma assinatura amplamente aceita. No entanto, eles também trazem benefícios: -#### Garantias de baixa exatidão {#low-correctness-guarantees} +#### Baixas garantias de correção {#low-correctness-guarantees} -Com oráculos centralizados, não há como confirmar se as informações prestadas estão corretas ou não. O provedor oracle pode ser "conceituado", mas isso não elimina a possibilidade de alguém se tornar desonesto ou um hacker adulterar o sistema. Se o oráculo se tornar corrompido, os contratos inteligentes serão executados com base em dados ruins. +Com oráculos centralizados, não há como confirmar se as informações prestadas estão corretas ou não. Até mesmo provedores "respeitáveis" podem se tornar desonestos ou ser hackeados. Se o oráculo se tornar corrompido, os contratos inteligentes serão executados com base em dados ruins. #### Baixa disponibilidade {#poor-availability} -Os oráculos centralizados não garantem sempre disponibilizar dados off-chain para outros contratos inteligentes. Se o provedor decidir desligar o serviço ou um hacker sequestrar o componente off-chain do oráculo, seu contrato inteligente correrá o risco de um ataque de negação de serviço (DoS). +Os oráculos centralizados não garantem sempre disponibilizar dados off-chain por outros contratos inteligentes. Se o provedor decidir desligar o serviço ou um hacker sequestrar componente off-chain de oráculo, seu contrato inteligente terá o risco de DoS. -#### Incentivo insuficiente de compatibilidade {#poor-incentive-compatibility} +#### Baixa compatibilidade de incentivos {#poor-incentive-compatibility} -Oráculos centralizados muitas vezes têm incentivos mal projetados ou inexistentes para que o provedor de dados envie informações precisas/inalteradas. Pagar o oráculo por seus serviços pode encorajar um comportamento honesto, mas isso pode não ser suficiente. Com contratos inteligentes controlando enormes quantidades de valor, a recompensa pela manipulação de dados do oráculo é maior do que nunca. +Oráculos centralizados muitas vezes têm incentivos mal projetados ou inexistentes para que o provedor de dados envie informações precisas/inalteradas. Pagar um oráculo pela exatidão dele não garante honestidade. Esse problema aumenta à medida que a quantidade de valor controlado pelos contratos inteligentes aumenta. ### Oráculos descentralizados {#decentralized-oracles} -Os oráculos descentralizados são concebidos para superar as limitações dos oráculos centralizados, eliminando pontos únicos de fracasso. Um serviço oráculo descentralizado inclui vários participantes em uma rede peer-to-peer que formam consenso sobre dados off-chain antes de enviá-los para um contrato inteligente. +Os oráculos descentralizados são concebidos para superar as limitações dos oráculos centralizados, eliminando pontos únicos de fracasso. Um serviço de oráculo descentralizado inclui vários participantes em rede peer-to-peer que formam consenso sobre dados off-chain antes de os enviar por contrato inteligente. Um oráculo descentralizado deveria (idealmente) ser sem permissão, sem confiança e livre de administração por uma parte central; na realidade, a descentralização entre os oráculos é um espectro. Existem redes de oráculos semidescentralizadas onde qualquer um pode participar, mas com um "proprietário" que aprova e remove nós com base no desempenho histórico. Redes oráculas totalmente descentralizadas também existem: elas geralmente são executadas como blockchains autônomas e possuem mecanismos de consenso definidos para coordenar nós e punir o comportamento errado. O uso de oráculos descentralizados vem com os seguintes benefícios: -### Garantias de alta exatidão {#high-correctness-guarantees} +### Altas garantias de correção {#high-correctness-guarantees} -Oráculos descentralizados tentam alcançar a exatidão dos dados utilizando diferentes abordagens. Isso inclui o uso de provas de autenticidade e integridade das informações retornadas e a exigência de que várias entidades concordem coletivamente com a validade dos dados off-chain. +Oráculos descentralizados tentam alcançar a exatidão dos dados utilizando diferentes abordagens. Isto inclui provas de autenticidade e integridade das informações retornadas e a exigência de que várias entidades concordem coletivamente com a validade dos dados off-chain. #### Provas de autenticidade {#authenticity-proofs} @@ -260,15 +256,15 @@ As provas de autenticidade são mecanismos de criptografia que permitem a verifi Exemplos de provas de autenticidade incluem: -**Provas de Transport Layer Security (TLS)**: os nós oráculos geralmente recuperam dados de fontes externas usando uma conexão HTTP segura baseada no protocolo Transport Layer Security (TLS). Alguns oráculos descentralizados usam provas de autenticidade para verificar as sessões TLS (ou seja, confirmar a troca de informações entre um nó e um servidor específico) e confirmar que o conteúdo da sessão não foi alterado. +**Provas de Transport Layer Security (TLS)**: Os nós de oráculo geralmente recuperam dados de fontes externas usando uma conexão HTTP segura com base no protocolo Transport Layer Security (TLS). Alguns oráculos descentralizados usam provas de autenticidade para verificar as sessões TLS (ou seja, confirmar a troca de informações entre um nó e um servidor específico) e confirmar que o conteúdo da sessão não foi alterado. -**Atestados de ambiente de execução confiável (TEE)**: um [ambiente de execução confiável](https://en.wikipedia.org/wiki/Trusted_execution_environment) (TEE) é um ambiente computacional reservado em área restrita isolado dos processos operacionais de seu sistema host. TEEs garantem que qualquer código de aplicativo ou dados armazenados/usados no ambiente de computação mantenham integridade, confidencialidade e imutabilidade. Os usuários também podem gerar um atestado para provar que uma instância do aplicativo está em execução no ambiente de execução confiável. +**Atestados do Ambiente de Execução Confiável (TEE)**: Um [ambiente de execução confiável](https://en.wikipedia.org/wiki/Trusted_execution_environment) (TEE) é um ambiente computacional em área restrita que é isolado dos processos operacionais do seu sistema anfitrião. TEEs garantem que qualquer código de aplicativo ou dados armazenados/usados no ambiente de computação mantenham integridade, confidencialidade e imutabilidade. Os usuários também podem gerar um atestado para provar que uma instância do aplicativo está em execução no ambiente de execução confiável. Certas classes de oráculos descentralizados exigem que os operadores de nós oráculos forneçam atestados TEE. Isto confirma para um usuário que o operador do nó está executando uma instância de cliente oráculo em um ambiente de execução confiável. TEEs impedem que processos externos alterem ou leiam o código e os dados de um aplicativo, portanto, estes atestados provam que o nó oráculo manteve as informações intactas e confidenciais. -#### Validação de informações baseadas em consenso {#consensus-based-validation-of-information} +#### Validação de informações baseada em consenso {#consensus-based-validation-of-information} -Os oráculos centralizados dependem de uma única fonte de verdade ao fornecer dados para contratos inteligentes, que introduz a possibilidade de publicar informações imprecisas. Oráculos descentralizados resolvem este problema confiando em vários nós oráculos para consultar informações off-chain. Ao comparar dados de múltiplas fontes, os oráculos descentralizados reduzem o risco de passar informações inválidas para contratos on-chain. +Os oráculos centralizados dependem de uma única fonte de verdade ao fornecer dados para contratos inteligentes, que introduz a possibilidade de publicar informações imprecisas. Oráculos descentralizados resolvem este problema confiando em vários nós de oráculo por consultar informações off-chain. Comparando dados de múltiplas fontes, os oráculos descentralizados reduzem o risco de passar informações inválidas para contratos on-chain. Oráculos descentralizados, entretanto, devem lidar com discrepâncias nas informações recuperadas de múltiplas fontes off-chain. Para minimizar diferenças nas informações e garantir que os dados passados para o contrato do oráculo reflitam a opinião coletiva dos nós do oráculo, os oráculos descentralizados usam os seguintes mecanismos: @@ -278,33 +274,33 @@ Algumas redes oráculos descentralizadas exigem que os participantes votem ou ap Os nós cujas respostas se desviam da maioria são penalizados, tendo seus tokens distribuídos para outros que fornecem valores mais corretos. Forçar os nós a fornecer uma caução antes de proporcionar dados incentiva respostas honestas, pois se supõe que eles são atores econômicos racionais com intenção de maximizar os retornos. -O staking/votação também protege oráculos descentralizados de "ataques Sybil", em que agentes maliciosos criam várias identidades para driblar o sistema de consenso. No entanto, o staking não pode impedir o "freeloading" (nós de oráculo copiando informações dos outros) e a "validação tardia" (nós de oráculos seguindo a maioria sem verificar eles mesmos as informações). +O staking/votação também protege os oráculos descentralizados de [ataques Sybil](/glossary/#sybil-attack), em que agentes mal-intencionados criam várias identidades para manipular o sistema de consenso. No entanto, o staking não pode impedir o "freeloading" (nós de oráculo copiando informações dos outros) e a "validação tardia" (nós de oráculos seguindo a maioria sem verificar eles mesmos as informações). ##### Mecanismos de ponto Schelling -O [ponto de Schelling]() é um conceito da teoria dos jogos que assume que várias entidades encontrarão sempre por padrão uma solução comum para um problema na ausência de qualquer comunicação. Os mecanismos do ponto de Schelling são frequentemente utilizados em redes descentralizadas de oráculos para permitir que os nós cheguem a consenso sobre as respostas às solicitações de dados. +O [ponto de Schelling](https://en.wikipedia.org/wiki/Focal_point_\(game_theory\)) é um conceito da teoria dos jogos que pressupõe que várias entidades sempre adotarão uma solução comum para um problema na ausência de qualquer comunicação. Os mecanismos do ponto de Schelling são frequentemente utilizados em redes descentralizadas de oráculos para permitir que os nós cheguem a consenso sobre as respostas às solicitações de dados. -Um exemplo inicial é o [SchellingCoin](https://blog.ethereum.org/2014/03/28/schellingcoin-a-minimal-trust-universal-data-feed), uma proposta de feed de dados (oráculo), na qual os participantes submetem respostas para "escalar" perguntas (perguntas cujas respostas são descritas por magnitude, por exemplo, "qual é o preço do ETH?"), juntamente com um depósito. Os usuários que fornecem valores entre o 25º e 75º [percentil](https://en.wikipedia.org/wiki/Percentile) são recompensados, enquanto aqueles cujos valores se desviam amplamente da mediana são penalizados. +Uma ideia inicial para isso foi o [SchellingCoin](https://blog.ethereum.org/2014/03/28/schellingcoin-a-minimal-trust-universal-data-feed/), um feed de dados proposto onde os participantes enviam respostas para perguntas "escalares" (perguntas cujas respostas são descritas por magnitude, por exemplo, "qual é o preço do ETH?"), juntamente com um depósito. Os usuários que fornecem valores entre o 25º e o 75º [percentil](https://en.wikipedia.org/wiki/Percentile) são recompensados, enquanto aqueles cujos valores se desviam muito do valor mediano são penalizados. -Embora o SchellingCoin não exista hoje, uma série de oráculos descentralizados, principalmente [Oráculos do Maker Protocol](https://docs.makerdao.com/smart-contract-modules/oracle-module), usam o mecanismo schelling-point para melhorar a precisão dos dados do oráculo. Cada Maker Oracle consiste de uma rede off-chain P2P de nós ("relayers" e "feeds") que submetem preços de mercado para ativos colaterais e um contrato on-chain "Medianizer" que calcula a mediana de todos os valores fornecidos. Quando o período de atraso especificado acaba, esta mediana se torna o novo preço de referência para o ativo associado. +Embora o SchellingCoin não exista hoje, vários oráculos descentralizados — notavelmente os [Oráculos do Protocolo Maker](https://docs.makerdao.com/smart-contract-modules/oracle-module) — usam o mecanismo de ponto de Schelling para melhorar a precisão dos dados do oráculo. Cada Maker Oracle tem uma rede off-chain P2P de nós ("relayers" e "feeds") que submetem market prices para colaterais e um contrato on-chain "Medianizer" que calcula a mediana de todos os valores fornecidos. Quando o período de atraso especificado acaba, esta mediana se torna o novo preço de referência para o ativo associado. -Outros exemplos de oráculos que usam mecanismos de ponto de Schelling incluem [Chainlink Off-Chain Reporting](https://docs.chain.link/docs/off-chain-reporting/) e Witnet. Em ambos os sistemas, as respostas de nós oráculos da rede peer-to-peer são agregadas em um único valor agregado, como uma média ou mediana. Os nós são recompensados ou punidos de acordo com o grau de exatidão ou imprecisão de suas respostas com relação ao valor agregado. +Outros exemplos de oráculos que usam mecanismos de ponto de Schelling incluem o [Chainlink Offchain Reporting](https://docs.chain.link/architecture-overview/off-chain-reporting) e o [Witnet](https://witnet.io/). Em ambos os sistemas, as respostas de nós oráculos da rede peer-to-peer são agregadas em um único valor agregado, como uma média ou mediana. Os nós são recompensados ou punidos de acordo com o grau de exatidão ou imprecisão de suas respostas com relação ao valor agregado. -Os mecanismos de ponto de Schelling são atrativos porque minimizam a pegada on-chain (apenas uma transação precisa ser enviada) enquanto garantem a descentralização. O último é possível porque os nós devem aprovar a lista de respostas submetidas antes que ela seja introduzida no algoritmo que produz o valor médio/mediano. +O Schelling point é atrativo porque minimiza o espaço ocupado on-chain (apenas uma transação precisa ser enviada) enquanto garante a descentralização. O último é possível porque os nós devem aprovar a lista de respostas submetidas antes que ela seja introduzida no algoritmo que produz o valor médio/mediano. ### Disponibilidade {#availability} -Serviços de oráculo descentralizados garantem uma elevada disponibilidade de dados off-chain para contratos inteligentes. Isso é conseguido através da descentralização tanto da fonte de informação off-chain como dos nós responsáveis pela transferência da informação on-chain. +Serviços de oráculo descentralizados garantem disponibilidade de dados off-chain por contratos inteligentes. Isto é o resultado da descentralização da fonte de informação off-chain e dos nós responsáveis pela transferência da informação on-chain. -Isto garante tolerância a falhas, uma vez que o contrato do oráculo pode depender de vários nós (que também dependem de múltiplas fontes de dados) para executar consultas a partir de outros contratos. A descentralização no nível de origem _e_ operador de nó é crucial — uma rede de nós oráculos servindo informações recuperadas da mesma fonte irá enfrentar o mesmo problema que um oráculo centralizado. +Isto garante tolerância a falhas, uma vez que o contrato do oráculo pode depender de vários nós (que também dependem de múltiplas fontes de dados) para executar consultas a partir de outros contratos. A descentralização no nível da fonte _e_ do operador de nó é crucial — uma rede de nós de oráculo servindo informações recuperadas da mesma fonte enfrentará o mesmo problema que um oráculo centralizado. -Também é possível que os oráculos baseados em stake consigam cortar operadores de nó que não respondam rapidamente a solicitações de dados. Isto incentiva significativamente os nós oráculos a investirem em infraestruturas tolerantes a falhas e fornecerem dados em tempo hábil. +Também é possível que os stake-based oráculos consigam cortar operadores de nó que não respondam rapidamente a solicitações de dados. Isto incentiva significativamente os nós oráculos a investirem em infraestruturas tolerantes a falhas e fornecerem dados em tempo hábil. -### Boa compatibilidade com incentivos {#good-incentive-compatibility} +### Boa compatibilidade de incentivos {#good-incentive-compatibility} -Oráculos descentralizados implementam vários designs de incentivo para evitar o comportamento [bizantino](https://en.wikipedia.org/wiki/Byzantine_fault) entre os nós oráculos. Especificamente, eles alcançam a _atribuibilidade_ e _responsabilidade_: +Oráculos descentralizados implementam vários projetos de incentivo para evitar o comportamento [bizantino](https://en.wikipedia.org/wiki/Byzantine_fault) entre os nós do oráculo. Especificamente, eles alcançam _atribuibilidade_ e _responsabilização_: -1. Nós oráculos descentralizados são frequentemente obrigados a assinar os dados que eles fornecem em resposta a solicitações de dados. Essa informação ajuda a avaliar o desempenho histórico de nós oráculos, para que os usuários possam filtrar nós oráculos não confiáveis ao fazer solicitações de dados. Um exemplo é o [Sistema de Reputação de Algoritmos](https://docs.witnet.io/intro/about/architecture#algorithmic-reputation-system) da Witnet. +1. Nós oráculos descentralizados são frequentemente obrigados a assinar os dados que eles fornecem em resposta a solicitações de dados. Essa informação ajuda a avaliar o desempenho histórico de nós oráculos, para que os usuários possam filtrar nós oráculos não confiáveis ao fazer solicitações de dados. Um exemplo é o [Sistema de Reputação Algorítmica](https://docs.witnet.io/intro/about/architecture#algorithmic-reputation-system) do Witnet. 2. Os oráculos descentralizados, conforme explicado anteriormente, podem exigir que os nós façam stake confiando somente na verdade dos dados que eles submetem. Se a reivindicação é confirmada, esse staking pode ser restituído juntamente com recompensas por um serviço honesto. Mas também pode ser reduzido no caso de a informação ser incorreta, o que impões certa responsabilização. @@ -312,13 +308,15 @@ Oráculos descentralizados implementam vários designs de incentivo para evitar Os seguintes são casos de uso comuns para oráculos no Ethereum: -### Como recuperar dados financeiros {#retrieving-financial-data} +### Recuperando dados financeiros {#retrieving-financial-data} -As aplicações de [finanças descentralizadas](/defi/) (DeFi) permitem conceder empréstimos, pedir empréstimos e fazer trading de ativos. Tudo isso peer-to-peer. Isto muitas vezes requer obter diferentes informações relacionadas a finanças, incluindo dados de taxa de exchanges (para calcular o valor fiat de criptomoedas ou comparar preços de dois tokens) e dados de mercados de capital (para calcular o valor de ativos tokenizados, tais como ouro ou dólar americano). +Aplicações de [finanças descentralizadas](/defi/) (DeFi) permitem empréstimos, recebimentos e negociação de ativos peer-to-peer. Isso geralmente requer a obtenção de diferentes informações financeiras, incluindo dados de taxa de câmbio (para calcular o valor fiduciário de criptomoedas ou comparar preços de tokens) e dados de mercados de capitais (para calcular o valor de ativos tokenizados, como ouro ou dólar americano). -Se você planeja criar um protocolo de crédito DeFi, por exemplo, você precisará consultar os preços atuais de mercado dos ativos (por exemplo, ETH) depositados como garantia. Isso é para que o seu contrato inteligente possa determinar o valor dos ativos colaterais e determinar o quanto eles podem pedir emprestado no sistema. +Um protocolo de empréstimo DeFi, por exemplo, precisa consultar os preços de mercado atuais para ativos (por exemplo, ETH) depositados como garantia. Isso permite que o contrato determine o valor dos ativos colaterais e determine quanto ele pode tomar emprestado do sistema. -Os "oráculos de preços" populares (como costumam ser chamados) em DeFi incluem Chainlink Price Feeds, o protocolo composto [Open Price Feed](https://compound.finance/docs/prices), [Time-Weighted Average Prices (TWAPs)](https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles) da Uniswap e [Maker Oracles](https://docs.makerdao.com/smart-contract-modules/oracle-module). É aconselhável entender as advertências que vêm com esses oráculos de preço antes de integrá-los no seu projeto. Este [artigo](https://blog.openzeppelin.com/secure-smart-contract-guidelines-the-dangers-of-price-oracles/) fornece uma análise detalhada do que deve ser considerado ao planejar usar qualquer um dos oráculos de preço mencionados. +Os “oráculos de preços” populares (como são frequentemente chamados) no DeFi incluem os Feeds de Preços da Chainlink, o [Open Price Feed](https://compound.finance/docs/prices) do Protocolo Compound, os [Preços Médios Ponderados no Tempo (TWAPs)](https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles) da Uniswap e os [Oráculos da Maker](https://docs.makerdao.com/smart-contract-modules/oracle-module). + +Os construtores devem entender as ressalvas que acompanham esses oráculos de preços antes de integrá-los ao seu projeto. Este [artigo](https://blog.openzeppelin.com/secure-smart-contract-guidelines-the-dangers-of-price-oracles/) fornece uma análise detalhada do que considerar ao planejar usar qualquer um dos oráculos de preço mencionados. Abaixo é um exemplo de como obter o preço ETH mais recente em seu contrato inteligente usando um feed de preço da Chainlink: @@ -357,69 +355,80 @@ contract PriceConsumerV3 { } ``` -### Geração aleatória verificável {#generating-verifiable-randomness} +### Gerando aleatoriedade verificável {#generating-verifiable-randomness} -Certas aplicações da blockchain, como jogos baseados em blockchain ou esquemas de loteria, requerem um alto nível de imprevisibilidade e aleatoriedade para funcionar efetivamente. No entanto, a execução determinística de blockchains elimina qualquer fonte de aleatoriedade. +Certas aplicativos blockchain, como jogos baseados em blockchain ou esquemas de loteria, requerem um alto nível de imprevisibilidade e aleatoriedade para funcionar efetivamente. Entretanto, a execução determinística de blockchains elimina a aleatoriedade. -A abordagem habitual é usar funções criptográficas pseudoaleatórias, como o `blockhash`, mas isso é passível de [manipulação por outros atores](https://ethereum.stackexchange.com/questions/3140/risk-of-using-blockhash-other-miners-preventing-attack#:~:text=So%20while%20the%20miners%20can,to%20one%20of%20the%20players.), nomeadamente mineradores resolvendo o algoritmo de prova de trabalho. Além disso, a [mudança para a prova de participação](/roadmap/merge/) do Ethereum significa que os desenvolvedores não podem mais confiar em `blockhash` para obter aleatoriedade on-chain (no entanto, o [mecanismo RANDAO](https://eth2book.info/altair/part2/building_blocks/randomness) da Beacon Chain fornece uma fonte alternativa de aleatoriedade). +A abordagem original era usar funções criptográficas pseudoaleatórias, como `blockhash`, mas estas podiam ser [manipuladas por mineradores](https://ethereum.stackexchange.com/questions/3140/risk-of-using-blockhash-other-miners-preventing-attack#:~:text=So%20while%20the%20miners%20can,to%20one%20of%20the%20players.) resolvendo o algoritmo de prova de trabalho. Além disso, a [mudança do Ethereum para prova de participação](/roadmap/merge/) significa que os desenvolvedores não podem mais confiar no `blockhash` para aleatoriedade na cadeia. O [mecanismo RANDAO](https://eth2book.info/altair/part2/building_blocks/randomness) da Beacon Chain fornece uma fonte alternativa de aleatoriedade. -É possível gerar o valor aleatório off-chain e enviá-lo on-chain, mas fazer isso impõe requisitos de confiança elevados aos usuários. Eles devem acreditar que o valor foi verdadeiramente gerado através de mecanismos imprevisíveis e não foi alterado em trânsito. +É possível gerar valor aleatório off-chain e enviá-lo on-chain, mas fazer isso requer confiança elevada aos usuários. Eles devem acreditar que o valor foi verdadeiramente gerado através de mecanismos imprevisíveis e não foi alterado em trânsito. -Oráculos projetados para computação off-chain resolvem esse problema gerando com segurança resultados aleatórios off-chain que eles emitem on-chain juntamente com provas criptográficas que atestam a imprevisibilidade do processo. Um exemplo é [Chainlink VRF](https://docs.chain.link/docs/chainlink-vrf/) (função aleatória verificável), que é um gerador de números aleatórios (RNG, pela sigla em inglês) com prova verificável e inviolável útil para a construção de contratos inteligentes confiáveis para aplicações que dependem de resultados imprevisíveis. +Os oráculos por computação off-chain resolvem este problema. Gerando com segurança resultados aleatórios off-chain, eles os emitem on-chain juntamente com provas criptográficas que atestam a imprevisibilidade do processo. Um exemplo é o [Chainlink VRF](https://docs.chain.link/docs/chainlink-vrf/) (Função Aleatória Verificável), que é um gerador de números aleatórios (RNG) comprovadamente justo e à prova de adulteração, útil para criar contratos inteligentes confiáveis para aplicações que dependem de resultados imprevisíveis. -### Como obter resultados para eventos {#getting-outcomes-for-events} +### Obtendo resultados para eventos {#getting-outcomes-for-events} -Com oráculos, é fácil criar contratos inteligentes que respondam a eventos do mundo real. Os serviços de oráculo tornam isso possível, permitindo que os contratos se conectem a APIs externas através de componentes off-chain e consumam informações dessas fontes de dados. Por exemplo, o dapp de previsão mencionado anteriormente pode solicitar um oráculo para retornar resultados eleitorais de uma fonte confiável off-chain (por exemplo, a Associated Press). +Com oráculos, é fácil criar contratos inteligentes que respondam a eventos do mundo real. Os serviços de oráculo tornam isto possível permitindo que os contratos se conectem a APIs externas através de componentes off-chain e consumam informações dessas fontes de dados. Por exemplo, o dapp por previsão pode solicitar um oráculo por retornar resultados eleitorais de uma fonte confiável off-chain (por exemplo, Associated Press). -O uso de oráculos para recuperar dados baseados em resultados do mundo real permite outros novos casos de uso, incluindo aplicações de seguro descentralizadas. Um contrato inteligente de seguro que será pago aos usuários precisará de informações precisas (por exemplo, dados meteorológicos, relatórios de desastres, etc.) para funcionar eficazmente. +Usar oráculos para recuperar dados com base em resultados do mundo real permite outros novos casos de uso; por exemplo, um produto de seguro descentralizado precisa de informações precisas sobre clima, desastres, etc. para funcionar de forma eficaz. -### Como automatizar contratos inteligentes {#automating-smart-contracts} +### Automatizando contratos inteligentes {#automating-smart-contracts} -Contrariamente às descrições populares, os contratos inteligentes não funcionam automaticamente. Uma conta de propriedade externa (EOA, pela sigla em inglês), ou outra conta de contrato, deve acionar as funções certas para executar o código do contrato. Na maioria dos casos, a maior parte das funções do contrato são públicas e podem ser invocadas pelas EOAs e por outros contratos. +Os contratos inteligentes não são executados automaticamente; em vez disso, uma conta de propriedade externa (EOA), ou outra conta de contrato, deve acionar as funções corretas para executar o código do contrato. Na maioria dos casos, a maior parte das funções do contrato são públicas e podem ser invocadas pelas EOAs e por outros contratos. -Mas também existem _funções privadas_ dentro de um contrato que são inacessíveis a outros; estas são geralmente essenciais para a funcionalidade geral do dapp. Exemplos potenciais incluem uma função `mintERC721Token()` que minta periodicamente novas NFT para os usuários, uma função para a atribuição de pagamentos em um mercado de previsões, ou uma função para desbloquear tokens em stake em uma DEX. +Mas também existem _funções privadas_ dentro de um contrato que são inacessíveis para outros; mas que são críticas para a funcionalidade geral de um dapp. Exemplos incluem uma função `mintERC721Token()` que periodicamente cria novos NFTs para usuários, uma função para conceder pagamentos em um mercado de previsão ou uma função para desbloquear tokens em staking em uma DEX. Os desenvolvedores precisarão acionar essas funções em intervalos para manter o aplicativo executando sem problemas. No entanto, isso pode fazer com que os desenvolvedores passem mais tempo em tarefas corriqueiras, e é por isso que a automação da execução de contratos inteligentes é atraente. -Algumas redes descentralizadas de oráculos oferecem serviços de automação, que permitem que nós de oráculos off-chain acionem funções de contrato inteligente de acordo com parâmetros definidos pelo usuário. Normalmente, isso requer "registrar" o contrato-alvo com o serviço oráculo, fornecendo fundos para pagar o operador do oráculo, e especificar as condições ou horários para disparar o contrato. +Algumas redes descentralizadas de oráculo oferecem serviços de automação, que permitem que nós de oráculo off-chain abrirem funções de contrato inteligente de acordo com parâmetros definidos por usuário. Normalmente, isso requer "registrar" o contrato-alvo com o serviço oráculo, fornecendo fundos para pagar o operador do oráculo, e especificar as condições ou horários para disparar o contrato. -Um exemplo é a [Keeper Network](https://chain.link/keepers) da rede Chainlink, que fornece opções para que os contratos inteligentes terceirizem tarefas de manutenção regulares de maneira minimizada e descentralizada. Leia a [documentação oficial do Keeper](https://docs.chain.link/docs/chainlink-keepers/introduction/) para obter informações sobre como tornar seu contrato compatível com o Keeper e usar o serviço Upkeep. +A [Keeper Network](https://chain.link/keepers) da Chainlink fornece opções para que contratos inteligentes terceirizem tarefas de manutenção regulares de uma maneira descentralizada e com confiança minimizada. Leia a [documentação oficial do Keeper](https://docs.chain.link/docs/chainlink-keepers/introduction/) para obter informações sobre como tornar seu contrato compatível com o Keeper e usar o serviço Upkeep. -## Usar oráculos da blockchain {#use-blockchain-oracles} +## Como usar oráculos de cadeia de blocos {#use-blockchain-oracles} Existem vários aplicativos de oráculos que você pode integrar no seu dapp Ethereum: -**[Chainlink](https://chain.link/)**: _a rede Chainlink de oráculos descentralizados fornece entradas, saídas e computação à prova de adulteração para suportar contratos inteligentes avançados em qualquer blockchain._ +**[Chainlink](https://chain.link/)** - _As redes de oráculos descentralizados da Chainlink fornecem entradas, saídas e cálculos à prova de violação para dar suporte a contratos inteligentes avançados em qualquer cadeia de blocos._ + +**[RedStone Oracles](https://redstone.finance/)** - _A RedStone é um oráculo modular descentralizado que fornece feeds de dados otimizados para o gás._ Ela oferece price feeds por ativos emergentes, como os LSTs, LRTs e resultado da participação de Bitcoin._ + +**[Chronicle](https://chroniclelabs.org/)** - _A Chronicle supera as limitações atuais de transferência de dados na cadeia, desenvolvendo oráculos verdadeiramente escaláveis, econômicos, descentralizados e verificáveis._ + +**[Witnet](https://witnet.io/)** - _Witnet é um oráculo sem permissão, descentralizado e resistente à censura que ajuda os contratos inteligentes a reagir a eventos do mundo real com fortes garantias criptoeconômicas._ + +**[Oráculo da UMA](https://uma.xyz)** - _O oráculo otimista da UMA permite que contratos inteligentes recebam rapidamente qualquer tipo de dados para diferentes aplicações, incluindo seguros, derivativos financeiros e mercados de previsão._ + +**[Tellor](https://tellor.io/)** - _Tellor é um protocolo de oráculo transparente e sem permissão para que seu contrato inteligente obtenha facilmente quaisquer dados sempre que precisar._ -**[Witnet](https://witnet.io/)**: _Witnet é um óraculo sem permissão, descentralizado e resistente à censura, que ajuda os contratos inteligentes a reagir a eventos do mundo real com fortes garantias criptoeconômicas._ +**[Band Protocol](https://bandprotocol.com/)** - _O Band Protocol é uma plataforma de oráculo de dados de cadeia cruzada que agrega e conecta dados do mundo real e APIs a contratos inteligentes._ -**[UMA Oracle](https://uma.xyz)** – _UMA é um oráculo otimista que permite contratos de receber, rapidamente, qualquer tipo de dados para diferentes aplicações, incluindo seguros, derivativos financeiros e mercados de previsão._ +**[Pyth Network](https://pyth.network/)** - _A rede Pyth é uma rede de oráculos financeiros de primeira parte, projetada para publicar dados contínuos do mundo real na cadeia em um ambiente autossustentável, descentralizado e resistente a adulterações._ -**[Tellor](https://tellor.io/)**: _Tellor é um protocolo de oráculo transparente e sem permissão para que seu contrato inteligente obtenha facilmente quaisquer dados sempre que precisar._ +**[API3 DAO](https://www.api3.org/)** - _A API3 DAO está fornecendo soluções de oráculos primários que oferecem maior transparência, segurança e escalabilidade da fonte em uma solução descentralizada para contratos inteligentes_ -**[Band Protocol](https://bandprotocol.com/)**: _Band Protocol é uma plataforma de dados de oráculos cross-chain que agrega e conecta dados do mundo real e APIs a contratos inteligentes._ +**[Supra](https://supra.com/)** - Um conjunto de ferramentas verticalmente integrado de soluções de cadeia cruzada que interligam todas as cadeias de blocos, públicas (L1s e L2s) ou privadas (empresariais), fornecendo feeds de preços de oráculos descentralizados que podem ser usados para casos de uso na cadeia e fora da cadeia. -**[Rede Pyth](https://pyth.network/)** — _A rede Pyth é uma rede de oráculos financeiros internos projetada para publicar dados contínuos do mundo real em cadeia em um ambiente autossustentável, descentralizado e inviolável._ +**[Gas Network](https://gas.network/)** - Uma plataforma de oráculo distribuída que fornece dados de preços de gás em tempo real em toda a cadeia de blocos. Ao trazer dados dos principais provedores de dados de preços de gás para a cadeia, a Gas Network está ajudando a impulsionar a interoperabilidade. A Gas Network oferece suporte a dados para mais de 35 cadeias, incluindo a Rede Principal Ethereum e muitas L2s líderes. -## Leitura Adicional {#further-reading} +## Leitura adicional {#further-reading} **Artigos** -- [O que é um oráculo blockchain?](https://chain.link/education/blockchain-oracles) - _Chainlink_ (todos os links em inglês) -- [O que é um oráculo blockchain?](https://betterprogramming.pub/what-is-a-blockchain-oracle-f5ccab8dbd72) - _Patrick Collins_ -- [Oráculos descentralizados: um panorama abrangente](https://medium.com/fabric-ventures/decentralised-oracles-a-comprehensive-overview-d3168b9a8841) – _Julien Thevenard_ -- [Como implementar um oráculo blockchain no Ethereum](https://medium.com/@pedrodc/implementing-a-blockchain-oracle-on-ethereum-cedc7e26b49e) – _Pedro Costa_ -- [Por que os contratos inteligentes não podem fazer chamadas à API?](https://ethereum.stackexchange.com/questions/301/why-cant-contracts-make-api-calls) - _StackExchange_ -- [Você quer usar um oráculo para preços](https://samczsun.com/so-you-want-to-use-a-price-oracle/) -_samczsun_ +- [O que é um oráculo de cadeia de blocos?](https://chain.link/education/blockchain-oracles) — _Chainlink_ +- [O que é um oráculo de cadeia de blocos?](https://medium.com/better-programming/what-is-a-blockchain-oracle-f5ccab8dbd72) — _Patrick Collins_ +- [Oráculos descentralizados: uma visão geral abrangente](https://medium.com/fabric-ventures/decentralised-oracles-a-comprehensive-overview-d3168b9a8841) — _Julien Thevenard_ +- [Implementando um Oráculo de Cadeia de Blocos na Ethereum](https://medium.com/@pedrodc/implementing-a-blockchain-oracle-on-ethereum-cedc7e26b49e) – _Pedro Costa_ +- [Por que contratos inteligentes não podem fazer chamadas de API?](https://ethereum.stackexchange.com/questions/301/why-cant-contracts-make-api-calls) — _StackExchange_ +- [Então você quer usar um oráculo de preços](https://samczsun.com/so-you-want-to-use-a-price-oracle/) — _samczsun_ **Vídeos** -- [Oráculos e a expansão da utilidade da blockchain](https://youtu.be/BVUZpWa8vpw) — _Real Vision Finance_ +- [Oráculos e a expansão da utilidade da cadeia de blocos](https://youtu.be/BVUZpWa8vpw) — _Real Vision Finance_ **Tutoriais** -- [Como obter o preço atual do Ethereum em Solidity](https://blog.chain.link/fetch-current-crypto-price-data-solidity/) - _Chainlink_ +- [Como buscar o preço atual do Ethereum em Solidity](https://blog.chain.link/fetch-current-crypto-price-data-solidity/) — _Chainlink_ +- [Consumindo dados de oráculos](https://docs.chroniclelabs.org/Developers/tutorials/Remix) — _Chronicle_ **Exemplos de projetos** -- [Projeto Chainlink inicial completo para Ethereum em Solidity](https://github.com/hackbg/chainlink-fullstack) - _HackBG_ +- [Projeto inicial completo da Chainlink para Ethereum em Solidity](https://github.com/hackbg/chainlink-fullstack) — _HackBG_ diff --git a/public/content/translations/pt-br/developers/docs/programming-languages/dart/index.md b/public/content/translations/pt-br/developers/docs/programming-languages/dart/index.md index f4b1b45db48..480360f6bed 100644 --- a/public/content/translations/pt-br/developers/docs/programming-languages/dart/index.md +++ b/public/content/translations/pt-br/developers/docs/programming-languages/dart/index.md @@ -5,24 +5,29 @@ lang: pt-br incomplete: true --- -## Introdução aos contratos inteligentes e linguagem Solidity {#getting-started-with-smart-contracts-and-solidity} +## Começando com contratos inteligentes e a linguagem Solidity {#getting-started-with-smart-contracts-and-solidity} ## Tutoriais {#tutorials} -- [Flutter and Blockchain – Hello World Dapp](https://www.geeksforgeeks.org/flutter-and-blockchain-hello-world-dapp/) leva você através de todos os passos para iniciar: - 1. Escrevendo um contrato inteligente em [Solidity](https://soliditylang.org/) - 2. Escrevendo uma interface de usuário no Dart -- [Construir um dapp para dispositivos móveis com Flutter](https://medium.com/dash-community/building-a-mobile-dapp-with-flutter-be945c80315a) é muito mais curto, o que pode ser melhor -- Se você preferir aprender assistindo a um vídeo, acesse [Criando seu primeiro app blockchain com Flutter](https://www.youtube.com/watch?v=3Eeh3pJ6PeA), que dura 1 hora -- Se você é impaciente, talvez prefira o [Building a Blockchain Decentralized-app with Flutter and Dart on Ethereum](https://www.youtube.com/watch?v=jaMFEOCq_1s), que leva apenas vinte minutos -- [Integrando MetaMask no aplicativo Flutter com Web3Modal da WalletConnect](https://www.youtube.com/watch?v=v_M2buHCpc4) - este vídeo curto mostra as etapas de integração do MetaMask dentro do aplicativo Flutter com a biblioteca da WalletConnect [Web3Modal](https://pub.dev/packages/web3modal_flutter) -- [Curso Bootcamp para Desenvolvedores de Blockchain Móvel com Solidity e Flutter](https://youtube.com/playlist?list=PL4V4Unlk5luhQ26ERO6hWEbcUwHDSSmVH) - playlist de cursos para desenvolvedores de blockchain móvel full stack +- [Flutter e Blockchain – Dapp Olá Mundo](https://www.geeksforgeeks.org/flutter-and-blockchain-hello-world-dapp/) mostra todas as etapas para começar: + 1. Escrevendo um contrato inteligente em [Solidity](https://soliditylang.org/) + 2. Escrevendo uma interface de usuário no Dart +- [Construindo um dapp móvel com Flutter](https://medium.com/dash-community/building-a-mobile-dapp-with-flutter-be945c80315a) é bem mais curto, o que pode ser melhor + se você já conhece o básico +- Se preferir aprender assistindo a um vídeo, pode assistir a [Construa seu primeiro aplicativo blockchain com Flutter](https://www.youtube.com/watch?v=3Eeh3pJ6PeA), que tem cerca de uma hora de duração +- Se você for impaciente, talvez prefira [Construindo um aplicativo descentralizado de blockchain com Flutter e Dart na Ethereum](https://www.youtube.com/watch?v=jaMFEOCq_1s), que dura apenas cerca de vinte minutos +- [Integrando o MetaMask no aplicativo Flutter com o Web3Modal da WalletConnect](https://www.youtube.com/watch?v=v_M2buHCpc4) - este vídeo curto mostra as etapas para integrar o MetaMask em seus aplicativos Flutter com a biblioteca [Web3Modal](https://pub.dev/packages/web3modal_flutter) da WalletConnect +- [Curso Bootcamp para Desenvolvedor de Blockchain Móvel com Solidity e Flutter](https://youtube.com/playlist?list=PL4V4Unlk5luhQ26ERO6hWEbcUwHDSSmVH) - playlist do curso para desenvolvedor de blockchain móvel full-stack ## Trabalhando com clientes Ethereum {#working-with-ethereum-clients} -Você pode usar Ethereum para criar aplicativos descentralizados (ou "dapps") que utilizam os benefícios da tecnologia de criptomoedas e cadeia de blocos. Atualmente existem pelo menos duas bibliotecas mantidas para Dart que usam a [API JSON-RPC](/developers/docs/apis/json-rpc/) para o Ethereum. +Você pode usar Ethereum para criar aplicativos descentralizados (ou "dapps") que utilizam os benefícios da tecnologia de criptomoedas e cadeia de blocos. +Atualmente, existem pelo menos duas bibliotecas mantidas para Dart para usar a +[API JSON-RPC](/developers/docs/apis/json-rpc/) para o Ethereum. -1. [Web3dart de simonbutler.eu](https://pub.dev/packages/web3dart) -1. [Ethereum 5.0.0 de darticulate.com](https://pub.dev/packages/ethereum) +1. [Web3dart de pwa.ir](https://pub.dev/packages/web3dart) +2. [Ethereum 5.0.0 de darticulate.com](https://pub.dev/packages/ethereum) -Existem também bibliotecas adicionais que permitem que você manipule endereços específicos de Ethereum, ou que permitem que você recupere os preços de várias criptomoedas. [Veja a lista completa aqui](https://pub.dev/dart/packages?q=ethereum). +Existem também bibliotecas adicionais que permitem que você manipule endereços específicos de Ethereum, +ou que permitem que você recupere os preços de várias criptomoedas. +[Você pode ver a lista completa aqui](https://pub.dev/dart/packages?q=ethereum). diff --git a/public/content/translations/pt-br/developers/docs/programming-languages/delphi/index.md b/public/content/translations/pt-br/developers/docs/programming-languages/delphi/index.md index 4d0abe5f506..949230dfb27 100644 --- a/public/content/translations/pt-br/developers/docs/programming-languages/delphi/index.md +++ b/public/content/translations/pt-br/developers/docs/programming-languages/delphi/index.md @@ -1,6 +1,6 @@ --- title: Ethereum para desenvolvedores Delphi -description: Aprenda a desenvolver para o Ethereum usando a linguagem de programação Delphi +description: "Aprenda a desenvolver para o Ethereum usando a linguagem de programação Delphi" lang: pt-br incomplete: true --- @@ -11,46 +11,48 @@ Aprenda a desenvolver para o Ethereum usando a linguagem de programação Delphi -Utilize Ethereum para criar aplicações descentralizadas ("dapps") que utilizam os benefícios das criptomoedas e tecnologias de cadeia de blocos. Esses dapps podem ser muito confiáveis, o que significa que uma vez que eles são implantados na rede Ethereum, sempre serão executados como programados. Eles podem controlar ativos digitais a fim de criar novos tipos de aplicações financeiras. Eles podem ser descentralizados, o que significa que nenhuma entidade ou pessoa os controla sendo portanto praticamente impossíves de serem censurados. +Utilize Ethereum para criar aplicações descentralizadas ("dapps") que utilizam os benefícios das criptomoedas e tecnologias de cadeia de blocos. Esses dapps podem ser muito confiáveis, o que significa que uma vez que eles são implantados na rede Ethereum, sempre serão executados como programados. +Eles podem controlar ativos digitais a fim de criar novos tipos de aplicações financeiras. Eles podem ser descentralizados, o que significa que nenhuma entidade ou pessoa os controla sendo, portanto, praticamente impossíveis de serem censurados. Crie aplicações descentralizadas sobre a Ethereum e interaja com contratos inteligentes usando a linguagem de programação Delphi! -## Introdução aos contratos inteligentes e linguagem Solidity {#getting-started-with-smart-contracts-and-the-solidity-language} +## Começando com contratos inteligentes e a linguagem Solidity {#getting-started-with-smart-contracts-and-the-solidity-language} **Dê o seus primeiros passos para integrar Delphi com a Ethereum** -Precisa de uma introdução geral? Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers](/developers/). +Precisa de uma introdução geral? +Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers](/developers/). -- [Cadeia de blocos explicada](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) -- [Entendendo os contratos inteligentes](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) -- [Escreva seu primeiro contrato inteligente](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) -- [Aprenda como Compilar e Implantar em Solidity](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) +- [Blockchain Explicada](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) +- [Entendendo Contratos Inteligentes](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [Escreva seu Primeiro Contrato Inteligente](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [Aprenda a Compilar e Implantar o Solidity](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) -## Referências e Links para Iniciantes {#beginner-references-and-links} +## Referências e links para iniciantes {#beginner-references-and-links} **Apresentando a biblioteca Delphereum** - [O que é Delphereum?](https://github.com/svanas/delphereum/blob/master/README.md) -- [Conectando Delphi a uma blockchain local (na memória)](https://medium.com/@svanas/connecting-delphi-to-a-local-in-memory-blockchain-9a1512d6c5b0) -- [Conectando Delphi à rede principal Ethereum](https://medium.com/@svanas/connecting-delphi-to-the-ethereum-main-net-5faf1feffd83) -- [Conectando Delphi com Contratos Inteligentes](https://medium.com/@svanas/connecting-delphi-to-smart-contracts-3146b12803a1) +- [Conectando o Delphi a uma blockchain local (em memória)](https://medium.com/@svanas/connecting-delphi-to-a-local-in-memory-blockchain-9a1512d6c5b0) +- [Conectando o Delphi à rede principal da Ethereum](https://medium.com/@svanas/connecting-delphi-to-the-ethereum-main-net-5faf1feffd83) +- [Conectando o Delphi a contratos inteligentes](https://medium.com/@svanas/connecting-delphi-to-smart-contracts-3146b12803a1) **Deseja ignorar a configuração por enquanto e pular direto para as amostras?** -- [Um Contrato Inteligente em 3 minutos e Dilphi - Parte 1](https://medium.com/@svanas/a-3-minute-smart-contract-and-delphi-61d998571d) -- [Um Contrato Inteligente Delphi em 3 minutos - Parte 2](https://medium.com/@svanas/a-3-minute-smart-contract-and-delphi-part-2-446925faa47b) +- [Um contrato inteligente de 3 minutos e Delphi - Parte 1](https://medium.com/@svanas/a-3-minute-smart-contract-and-delphi-61d998571d) +- [Um contrato inteligente de 3 minutos e Delphi - Parte 2](https://medium.com/@svanas/a-3-minute-smart-contract-and-delphi-part-2-446925faa47b) -## Artigos intermediários {#intermediate-articles} +## Artigos Intermediários {#intermediate-articles} -- [Gerando uma mensagem Ethereum assinada em Delphi](https://medium.com/@svanas/generating-an-ethereum-signed-message-signature-in-delphi-75661ce5031b) -- [Transferindo o ether com Delphi](https://medium.com/@svanas/transferring-ether-with-delphi-b5f24b1a98a4) +- [Gerando uma assinatura de mensagem assinada pela Ethereum em Delphi](https://medium.com/@svanas/generating-an-ethereum-signed-message-signature-in-delphi-75661ce5031b) +- [Transferindo ether com Delphi](https://medium.com/@svanas/transferring-ether-with-delphi-b5f24b1a98a4) - [Transferindo tokens ERC-20 com Delphi](https://medium.com/@svanas/transferring-erc-20-tokens-with-delphi-bb44c05b295d) -## Padrões de uso avançado {#advanced-use-patterns} +## Padrões de uso avançados {#advanced-use-patterns} -- [Delphi e nomes de serviço Ethereum (ENS)](https://medium.com/@svanas/delphi-and-ethereum-name-service-ens-4443cd278af7) +- [Delphi e o Ethereum Name Service (ENS)](https://medium.com/@svanas/delphi-and-ethereum-name-service-ens-4443cd278af7) - [QuikNode, Ethereum e Delphi](https://medium.com/@svanas/quiknode-ethereum-and-delphi-f7bfc9671c23) -- [Delphi e Dark Forest do Ethereum](https://svanas.medium.com/delphi-and-the-ethereum-dark-forest-5b430da3ad93) -- [Trocar um token por outro em Delphi](https://svanas.medium.com/swap-one-token-for-another-in-delphi-bcb999c47f7) +- [Delphi e a Floresta Escura da Ethereum](https://svanas.medium.com/delphi-and-the-ethereum-dark-forest-5b430da3ad93) +- [Troca de um token por outro em Delphi](https://svanas.medium.com/swap-one-token-for-another-in-delphi-bcb999c47f7) Procurando por mais recursos? Confira [ethereum.org/developers](/developers/). diff --git a/public/content/translations/pt-br/developers/docs/programming-languages/dot-net/index.md b/public/content/translations/pt-br/developers/docs/programming-languages/dot-net/index.md index 70bd887d3e5..2e7c010c661 100644 --- a/public/content/translations/pt-br/developers/docs/programming-languages/dot-net/index.md +++ b/public/content/translations/pt-br/developers/docs/programming-languages/dot-net/index.md @@ -5,82 +5,84 @@ lang: pt-br incomplete: true --- -Aprenda a desenvolver para Ethereum utilizando projetos e ferramentas baseados em .NET +Aprenda a desenvolver para Ethereum usando projetos e ferramentas baseadas em .NET -Utilize Ethereum para criar aplicações descentralizadas ("dapps") que utilizam os benefícios das criptomoedas e tecnologias de cadeia de blocos. Esses dapps podem ser muito confiáveis, o que significa que uma vez que eles são implantados na rede Ethereum, sempre serão executados como programados. Eles podem controlar ativos digitais a fim de criar novos tipos de aplicações financeiras. Eles podem ser descentralizados, o que significa que nenhuma entidade ou pessoa os controla sendo portanto praticamente impossíves de serem censurados. +Utilize Ethereum para criar aplicações descentralizadas ("dapps") que utilizam os benefícios das criptomoedas e tecnologias de cadeia de blocos. Esses dapps podem ser muito confiáveis, o que significa que uma vez que eles são implantados na rede Ethereum, sempre serão executados como programados. +Eles podem controlar ativos digitais a fim de criar novos tipos de aplicações financeiras. Eles podem ser descentralizados, o que significa que nenhuma entidade ou pessoa os controla sendo, portanto, praticamente impossíveis de serem censurados. Crie aplicativos descentralizados sobre a Ethereum e interaja com contratos inteligentes usando ferramentas e linguagens da pilha de tecnologias da Microsoft - suportando C#, # Visual Basic .NET, F#, em ferramentas como VSCode e Visual Studio, através do .NET Framework/.NET Core/.NET Standard. Implemente uma cadeia de blocos Ethereum no Azure usando a cadeia de blocos Microsoft Azure em minutos. Traga o amor ao .NET para a Ethereum! -## Começando com contratos inteligentes e linguagem Solidity {#getting-started-with-smart-contracts-and-the-solidity-language} +## Começando com contratos inteligentes e a linguagem Solidity {#getting-started-with-smart-contracts-and-the-solidity-language} **Dê seus primeiros passos para integrar o .NET com a Ethereum** -Precisa de uma introdução geral? Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers](/developers/). +Precisa de uma introdução geral? +Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers](/developers/). -- [Cadeia de blocos explicada](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) -- [Entendendo os contratos inteligentes](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) -- [Escreva seu primeiro contrato inteligente](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) -- [Aprenda como Compilar e Implantar Solidity](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) +- [Blockchain Explicada](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) +- [Entendendo Contratos Inteligentes](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [Escreva seu Primeiro Contrato Inteligente](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [Aprenda a Compilar e Implantar o Solidity](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) ## Referências e links para iniciantes {#beginner-references-and-links} **Introduzindo a biblioteca Nethereum e o VS Code Solidity** -- [Nethereum, primeiros passos](https://docs.nethereum.com/en/latest/getting-started/) -- [Instalar VS Code Solidity](https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity) -- [Fluxo de trabalho de um desenvolvedor .NET para criar e chamar Contratos Inteligentes Ethereum](https://medium.com/coinmonks/a-net-developers-workflow-for-creating-and-calling-ethereum-smart-contracts-44714f191db2) -- [Integração de contratos inteligentes com o Nethereum](https://kauri.io/#collections/Getting%20Started/smart-contracts-integration-with-nethereum/#smart-contracts-integration-with-nethereumm) -- [Contratos Inteligentes entre o .NET e a Ethereum Blockchain com a Nethereum](https://medium.com/my-blockchain-development-daily-journey/interfacing-net-and-ethereum-blockchain-smart-contracts-with-nethereum-2fa3729ac933), também em [├](https://medium.com/my-blockchain-development-daily-journey/%E4%BD%BF%E7%94%A8nethereum%E9%80%A3%E6%8E%A5-net%E5%92%8C%E4%BB%A5%E5%A4%AA%E7%B6%B2%E5%8D%80%E5%A1%8A%E9%8F%88%E6%99%BA%E8%83%BD%E5%90%88%E7%B4%84-4a96d35ad1e1) -- [Nethereum - Uma biblioteca de integração .NET de código aberto para cadeia de blocos](https://kauri.io/#collections/a%20hackathon%20survival%20guide/nethereum-an-open-source-.net-integration-library/) -- [Escrevendo transações Ethereum para a base de dados SQL usando Nethereum](https://medium.com/coinmonks/writing-ethereum-transactions-to-sql-database-using-nethereum-fd94e0e4fa36) -- [Veja o como é fácil implantar contratos inteligentes Ethereum usando C# e VirtualStudio](https://koukia.ca/deploy-ethereum-smart-contracts-using-c-and-visualstudio-5be188ae928c) +- [Nethereum, Primeiros Passos](https://docs.nethereum.com/en/latest/getting-started/) +- [Instalando o Solidity no VS Code](https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity) +- [O fluxo de trabalho de um desenvolvedor .NET para criar e chamar contratos inteligentes Ethereum](https://medium.com/coinmonks/a-net-developers-workflow-for-creating-and-calling-ethereum-smart-contracts-44714f191db2) +- [Integração de contratos inteligentes com Nethereum](https://kauri.io/#collections/Getting%20Started/smart-contracts-integration-with-nethereum/#smart-contracts-integration-with-nethereumm) +- [Criando uma interface entre .NET e contratos inteligentes da blockchain Ethereum com Nethereum](https://medium.com/my-blockchain-development-daily-journey/interfacing-net-and-ethereum-blockchain-smart-contracts-with-nethereum-2fa3729ac933), também em [中文版](https://medium.com/my-blockchain-development-daily-journey/%E4%BD%BF%E7%94%A8nethereum%E9%80%A3%E6%8E%A5-net%E5%92%8C%E4%BB%A5%E5%A4%AA%E7%B6%B2%E5%8D%80%E5%A1%8A%E9%8F%88%E6%99%BA%E8%83%BD%E5%90%88%E7%B4%84-4a96d35ad1e1) +- [Nethereum - Uma biblioteca de integração .NET de código aberto para blockchain](https://kauri.io/#collections/a%20hackathon%20survival%20guide/nethereum-an-open-source-.net-integration-library/) +- [Gravando transações da Ethereum em um banco de dados SQL usando Nethereum](https://medium.com/coinmonks/writing-ethereum-transactions-to-sql-database-using-nethereum-fd94e0e4fa36) +- [Veja como implantar facilmente contratos inteligentes da Ethereum usando C# e VisualStudio](https://koukia.ca/deploy-ethereum-smart-contracts-using-c-and-visualstudio-5be188ae928c) **Deseja ignorar a configuração por enquanto e pular direto para as amostras?** -- [Playground](http://playground.nethereum.com/) - Interaja com a Ethereum e aprenda como usar a Nethereum através do seu navegador. - - Consultar Saldo da Conta [C#](http://playground.nethereum.com/csharp/id/1001) [VB.NET](http://playground.nethereum.com/vb/id/2001) - - Consultar Saldo de contrato inteligente ERC20 [C#](http://playground.nethereum.com/csharp/id/1005) [VB.NET](http://playground.nethereum.com/vb/id/2004) - - Transfira ether para uma conta [C#](http://playground.nethereum.com/csharp/id/1003) [VB.NET](http://playground.nethereum.com/vb/id/2003) +- [Playground](http://playground.nethereum.com/) - Interaja com a Ethereum e aprenda a usar o Nethereum pelo navegador. + - Consultar saldo da conta [C#](http://playground.nethereum.com/csharp/id/1001) [VB.NET](http://playground.nethereum.com/vb/id/2001) + - Consultar saldo do contrato inteligente ERC20 [C#](http://playground.nethereum.com/csharp/id/1005) [VB.NET](http://playground.nethereum.com/vb/id/2004) + - Transferir ether para uma conta [C#](http://playground.nethereum.com/csharp/id/1003) [VB.NET](http://playground.nethereum.com/vb/id/2003) - ... E mais! -## Artigos intermediários {#intermediate-articles} +## Artigos Intermediários {#intermediate-articles} -- [Nethereum Workbook/Lista de amostras](http://docs.nethereum.com/en/latest/Nethereum.Workbooks/docs/) -- [Implantar seus próprios Testchains de Desenvolvimento](https://github.com/Nethereum/Testchains) -- [Plugin Codegen VSCode para Solidity](https://docs.nethereum.com/en/latest/nethereum-codegen-vscodesolidity/) -- [Unity e Ethereum: Porquê e Como](https://www.raywenderlich.com/5509-unity-and-ethereum-why-and-how) -- [Crie ASP.NET Core Web API para dapps Ethereum](https://tech-mint.com/blockchain/create-asp-net-core-web-api-for-ethereum-dapps/) -- [Usando a Nethereum Web3 para implementar um sistema de rastreamento de cadeia de suprimentos](http://blog.pomiager.com/post/using-nethereum-web3-to-implement-a-supply-chain-traking-system4) -- [Nethereum Block Processing](https://nethereum.readthedocs.io/en/latest/nethereum-block-processing-detail/), com [C# Playground sample](http://playground.nethereum.com/csharp/id/1025) -- [Nethereum Websocket Streaming](https://nethereum.readthedocs.io/en/latest/nethereum-subscriptions-streaming/) +- [Lista de exemplos/pasta de trabalho do Nethereum](http://docs.nethereum.com/en/latest/Nethereum.Workbooks/docs/) +- [Implante suas próprias Testchains de desenvolvimento](https://github.com/Nethereum/Testchains) +- [Plugin de geração de código para Solidity do VSCode](https://docs.nethereum.com/en/latest/nethereum-codegen-vscodesolidity/) +- [Unity e Ethereum: por que e como](https://www.raywenderlich.com/5509-unity-and-ethereum-why-and-how) +- [Crie uma Web API ASP.NET Core para dapps da Ethereum](https://tech-mint.com/blockchain/create-asp-net-core-web-api-for-ethereum-dapps/) +- [Usando o Nethereum Web3 para implementar um sistema de rastreamento da cadeia de suprimentos](http://blog.pomiager.com/post/using-nethereum-web3-to-implement-a-supply-chain-traking-system4) +- [Processamento de blocos com Nethereum](https://nethereum.readthedocs.io/en/latest/nethereum-block-processing-detail/), com [amostra do C# Playground](http://playground.nethereum.com/csharp/id/1025) +- [Transmissão por WebSocket com Nethereum](https://nethereum.readthedocs.io/en/latest/nethereum-subscriptions-streaming/) - [Kaleido e Nethereum](https://kaleido.io/kaleido-and-nethereum/) -- [Quórum e Nethereum](https://github.com/Nethereum/Nethereum/blob/master/src/Nethereum.Quorum/README.md) +- [Quorum e Nethereum](https://github.com/Nethereum/Nethereum/blob/master/src/Nethereum.Quorum/README.md) ## Padrões de uso avançados {#advanced-use-patterns} - [Azure Key Vault e Nethereum](https://github.com/Azure-Samples/bc-community-samples/tree/master/akv-nethereum) - [Nethereum.DappHybrid](https://github.com/Nethereum/Nethereum.DappHybrid) -- [Arquitetura de backend do Ujo Nethereum](https://docs.nethereum.com/en/latest/nethereum-ujo-backend-sample/) +- [Arquitetura de referência de backend do Ujo Nethereum](https://docs.nethereum.com/en/latest/nethereum-ujo-backend-sample/) -## Projetos.NET, ferramentas e outras coisas divertidas {#dot-net-projects-tools-and-other-fun-stuff} +## Projetos .NET, ferramentas e outras coisas divertidas {#dot-net-projects-tools-and-other-fun-stuff} -- [Nethereum Playground](http://playground.nethereum.com/) - _Compile, crie e execute trechos de código Nethereum no navegador_ -- [Nethereum Codegen Blazor](https://github.com/Nethereum/Nethereum.CodeGen.Blazor) - _Gerador de código Nethereum com UI em Blazor_ -- [Nethereum Blazor](https://github.com/Nethereum/NethereumBlazor) - _Um explorador de blockchain leve e uma carteira simples em .NET Wasm SPA_ -- [Wonka Business Rules Engine](https://docs.nethereum.com/en/latest/wonka/) - _Um mecanismo de regras de negócio (para a plataforma .NET e para a plataforma Ethereum) que é inerentemente orientado a metadados_ -- [Nethermind](https://github.com/NethermindEth/nethermind) - _Um cliente .NET Core Ethereum para Linux, Windows, MacOS_ -- [eth-utils](https://github.com/ethereum/eth-utils/) - _funções de utilidade para trabalhar com bases de código relacionadas com a Ethereum_ -- [TestChains](https://github.com/Nethereum/TestChains) - _Devchains .NET pré-configuradas para respostas rápidas (PoA)_ +- [Nethereum Playground](http://playground.nethereum.com/) - _Compile, crie e execute trechos de código do Nethereum no navegador_ +- [Nethereum Codegen Blazor](https://github.com/Nethereum/Nethereum.CodeGen.Blazor) - _Codegen do Nethereum com interface do usuário em Blazor_ +- [Nethereum Blazor](https://github.com/Nethereum/NethereumBlazor) - _Um explorador de blockchain leve e uma carteira simples de SPA em .NET Wasm_ +- [Wonka Business Rules Engine](https://docs.nethereum.com/en/latest/wonka/) - _Um mecanismo de regras de negócio (para a plataforma .NET e para a plataforma Ethereum) que é inerentemente orientado por metadados_ +- [Nethermind](https://github.com/NethermindEth/nethermind) - _Um cliente Ethereum .NET Core para Linux, Windows, MacOS_ +- [eth-utils](https://github.com/ethereum/eth-utils/) – _funções utilitárias para trabalhar com bases de código relacionadas à Ethereum_ +- [TestChains](https://github.com/Nethereum/TestChains) - _Devchains .NET pré-configuradas para resposta rápida (PoA)_ Procurando por mais recursos? Confira [ethereum.org/developers](/developers/). -## Colaboradores comunitários .NET {#dot-net-community-contributors} +## Contribuidores da comunidade .NET {#dot-net-community-contributors} -Na Nethereum, nós geralmente nos encontramos no [Gitter](https://gitter.im/Nethereum/Nethereum) onde todos são bem vindos para fazer e responder perguntas, obter ajuda ou simplesmente relaxar. Sinta-se à vontade para fazer uma PR ou abrir uma questão no [repositório da Nethereum no Github](https://github.com/Nethereum), ou apenas para navegar pelos vários projetos paralelos e exemplos que temos. Você também pode nos encontrar em [Discord](https://discord.gg/jQPrR58FxX)! +No Nethereum, costumamos nos encontrar no [Gitter](https://gitter.im/Nethereum/Nethereum), onde todos são bem-vindos para fazer/responder perguntas, obter ajuda ou simplesmente relaxar. Sinta-se à vontade para fazer um PR ou abrir uma issue no [repositório GitHub do Nethereum](https://github.com/Nethereum), ou simplesmente navegar pelos muitos projetos paralelos/de amostra que temos. Você também pode nos encontrar no [Discord](https://discord.gg/jQPrR58FxX)! -Se você é novo no Nethermind e precisa de ajuda para começar, junte-se ao nosso [Discord](http://discord.gg/PaCMRFdvWT). Os nossos desenvolvedores estão prontos para responder às suas perguntas. Para PRs ou problemas, confira o [repositório do Github da Nethermind](https://github.com/NethermindEth/nethermind). +Se você é novo no Nethermind e precisa de ajuda para começar, junte-se ao nosso [Discord](http://discord.gg/PaCMRFdvWT). Os nossos desenvolvedores estão prontos para responder às suas perguntas. Não hesite em abrir um PR ou levantar qualquer problema no [repositório do Nethermind no GitHub](https://github.com/NethermindEth/nethermind). ## Outras listas agregadas {#other-aggregated-lists} -[Site Oficial Nethereum](https://nethereum.com/) -[Site Oficial Nethermind](https://nethermind.io/) +[Site oficial do Nethereum](https://nethereum.com/) +[Site oficial do Nethermind](https://nethermind.io/) diff --git a/public/content/translations/pt-br/developers/docs/programming-languages/elixir/index.md b/public/content/translations/pt-br/developers/docs/programming-languages/elixir/index.md index d5792e6d1d6..9b699629701 100644 --- a/public/content/translations/pt-br/developers/docs/programming-languages/elixir/index.md +++ b/public/content/translations/pt-br/developers/docs/programming-languages/elixir/index.md @@ -7,7 +7,7 @@ incomplete: false Aprenda a desenvolver para Ethereum usando projetos e ferramentas baseadas em Elixir. -Utilize Ethereum para criar aplicações descentralizadas ("dapps") que utilizam os benefícios das criptomoedas e tecnologias de cadeia de blocos. Esses dapps podem ser confiáveis, o que significa que, uma vez implantados na Ethereum, eles sempre serão executados conforme programado. Eles podem controlar ativos digitais para criar novos tipos de aplicações financeiros. Eles podem ser descentralizados, o que significa que nenhuma entidade ou pessoa os controla, sendo portanto praticamente impossíves de serem censurados. +Utilize Ethereum para criar aplicações descentralizadas ("dapps") que utilizam os benefícios das criptomoedas e tecnologias de cadeia de blocos. Esses dapps podem ser confiáveis, o que significa que, uma vez implantados na Ethereum, eles sempre serão executados conforme programado. Eles podem controlar ativos digitais para criar novos tipos de aplicações financeiros. Eles podem ser descentralizados, o que significa que nenhuma entidade ou pessoa os controla sendo, portanto, praticamente impossíveis de serem censurados. ## Começando com contratos inteligentes e a linguagem Solidity {#getting-started-with-smart-contracts-and-solidity} @@ -49,7 +49,7 @@ Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers](/developers/) - [exw3](https://github.com/hswick/exw3) - _Cliente RPC Ethereum de alto nível para Elixir_ - [mana](https://github.com/mana-ethereum/mana) - _Implementação de nó completo do Ethereum escrita em Elixir_ -Procurando por mais recursos? Confira [nossa página para Desenvolvedores](/developers/). +Procurando mais recursos? Confira [nossa página para Desenvolvedores](/developers/). ## Contribuidores da comunidade Elixir {#elixir-community-contributors} diff --git a/public/content/translations/pt-br/developers/docs/programming-languages/golang/index.md b/public/content/translations/pt-br/developers/docs/programming-languages/golang/index.md index 9a6d1a947b1..42d201a88da 100644 --- a/public/content/translations/pt-br/developers/docs/programming-languages/golang/index.md +++ b/public/content/translations/pt-br/developers/docs/programming-languages/golang/index.md @@ -5,80 +5,82 @@ lang: pt-br incomplete: true --- -Aprenda a desenvolver para Ethereum usando projetos e ferramentas baseados no Go +Aprenda a desenvolver para o Ethereum usando projetos e ferramentas baseados em Go -Use Ethereum para criar aplicativos descentralizados (ou "dapps"). Esses dapps podem ser muito confiáveis, o que significa que uma vez que eles são implantados na rede Ethereum, sempre serão executados como programados. São descentralizados, o que significa que funcionam em uma rede peer-to-peer e não há um único ponto de fracasso. Nenhuma entidade ou pessoa os controla e é praticamente impossível censurar. Podem controlar os activos digitais para criar novos tipos de aplicações financeiras. +Use Ethereum para criar aplicativos descentralizados (ou "dapps"). Esses dapps podem ser muito confiáveis, o que significa que uma vez que eles são implantados na rede Ethereum, sempre serão executados como programados. +São descentralizados, o que significa que funcionam em uma rede peer-to-peer e não há um único ponto de fracasso. Nenhuma entidade ou pessoa os controla e é praticamente impossível censurar. Podem controlar os activos digitais para criar novos tipos de aplicações financeiras. -## Começando com contratos inteligentes e linguagem Solidity {#getting-started-with-smart-contracts-and-solidity} +## Começando com contratos inteligentes e a linguagem Solidity {#getting-started-with-smart-contracts-and-solidity} **Dê os seus primeiros passos para integrar o Go com a Ethereum** -Precisa de uma introdução geral? Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers](/developers/). +Precisa de uma introdução geral? +Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers](/developers/). -- [Cadeia de blocos explicada](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) -- [Entendendo os contratos inteligentes](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) -- [Escreva seu primeiro contrato inteligente](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) -- [Aprenda como Compilar e Implantar em Solidity](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) -- [Tutorial do contrato](https://github.com/ethereum/go-ethereum/wiki/Contract-Tutorial) +- [Blockchain Explicada](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) +- [Entendendo Contratos Inteligentes](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [Escreva seu Primeiro Contrato Inteligente](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [Aprenda a Compilar e Implantar o Solidity](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) +- [Tutorial de Contratos](https://github.com/ethereum/go-ethereum/wiki/Contract-Tutorial) ## Artigos e livros para iniciantes {#beginner-articles-and-books} - [Introdução ao Geth](https://medium.com/@tzhenghao/getting-started-with-geth-c1a30b8d6458) -- [Use Golang para conectar à Ethereum](https://www.youtube.com/watch?v=-7uChuO_VzM) -- [Implantar Contratos Inteligentes Ethereum Usando Golang](https://www.youtube.com/watch?v=pytGqQmDslE) -- [Um Guia de Passos Para Testar e Implantar Contratos Inteligentes Ethereum em Go](https://hackernoon.com/a-step-by-step-guide-to-testing-and-deploying-ethereum-smart-contracts-in-go-9fc34b178d78) -- [eBook: Ethereum Development with Go](https://goethereumbook.org/) - _Desenvolvendo aplicativos Ethereum com Go_ +- [Use Golang para se conectar ao Ethereum](https://www.youtube.com/watch?v=-7uChuO_VzM) +- [Implantar contratos inteligentes da Ethereum usando Golang](https://www.youtube.com/watch?v=pytGqQmDslE) +- [Um Guia Passo a Passo para Testar e Implantar Contratos Inteligentes Ethereum em Go](https://hackernoon.com/a-step-by-step-guide-to-testing-and-deploying-ethereum-smart-contracts-in-go-9fc34b178d78) +- [eBook: Desenvolvimento Ethereum com Go](https://goethereumbook.org/) - _Desenvolva aplicações Ethereum com Go_ -## Artigos e documentos de nível Intermediário {#intermediate-articles-and-docs} +## Artigos e documentos intermediários {#intermediate-articles-and-docs} -- [Documentação Ethereum em Go](https://geth.ethereum.org/docs/) - _A documentação da implementação oficial da Ethereum em Go_ -- [Guia do programador Erigon](https://github.com/ledgerwatch/erigon/blob/devel/docs/programmers_guide/guide.md) - _Guia ilustrado, incluindo a árvore de estado, comprovações múltiplas e processamento de transações_ -- [Erigon e Ethereum sem estado](https://youtu.be/3-Mn7OckSus?t=394) - _Conferência da Comunidade Ethereum 2020 (EthCC 3)_ -- [Erigon: Otimizando clientes Ethereum](https://www.youtube.com/watch?v=CSpc1vZQW2Q) - _2018 Devcon 4_ +- [Documentação do Go Ethereum](https://geth.ethereum.org/docs/) - _A documentação da implementação oficial do Ethereum em Go_ +- [Guia do Programador Erigon](https://github.com/ledgerwatch/erigon/blob/devel/docs/programmers_guide/guide.md) - _Guia ilustrado, incluindo a árvore de estado, provas múltiplas e processamento de transações_ +- [Erigon e Ethereum sem estado](https://youtu.be/3-Mn7OckSus?t=394) - _Conferência da Comunidade Ethereum de 2020 (EthCC 3)_ +- [Erigon: otimizando clientes Ethereum](https://www.youtube.com/watch?v=CSpc1vZQW2Q) - _Devcon 4, 2018_ - [Go Ethereum GoDoc](https://godoc.org/github.com/ethereum/go-ethereum) - [Criando um dapp em Go com Geth](https://kauri.io/#collections/A%20Hackathon%20Survival%20Guide/creating-a-dapp-in-go-with-geth/) -- [Trabalhe com uma rede privada Ethereum com Golang e Geth](https://myhsts.org/tutorial-learn-how-to-work-with-ethereum-private-network-with-golang-with-geth.php) -- [Testes unitários de contratos Solidity na Ethereum com Go](https://medium.com/coinmonks/unit-testing-solidity-contracts-on-ethereum-with-go-3cc924091281) -- [Referência rápida para usar Geth como biblioteca](https://medium.com/coinmonks/web3-go-part-1-31c68c68e20e) +- [Trabalhe com a Rede Privada Ethereum com Golang e Geth](https://myhsts.org/tutorial-learn-how-to-work-with-ethereum-private-network-with-golang-with-geth.php) +- [Teste de unidade de contratos Solidity no Ethereum com Go](https://medium.com/coinmonks/unit-testing-solidity-contracts-on-ethereum-with-go-3cc924091281) +- [Referência rápida para usar o Geth como uma biblioteca](https://medium.com/coinmonks/web3-go-part-1-31c68c68e20e) ## Padrões de uso avançados {#advanced-use-patterns} - [O Backend Simulado do GETH](https://kauri.io/#collections/An%20ethereum%20test%20toolkit%20in%20Go/the-geth-simulated-backend/#_top) -- [Aplicativos Blockchain-as-a-Service usando Ethereum e Quorum](https://blockchain.dcwebmakers.com/blockchain-as-a-service-apps-using-ethereum-and-quorum.html) -- [Armazenamento de dados distribuídos IPFS e Swarm em aplicações blockchain da Ethereum](https://blockchain.dcwebmakers.com/work-with-distributed-storage-ipfs-and-swarm-in-ethereum.html) -- [Clientes Móveis: Bibliotecas e Nós Ethereum Inproc](https://github.com/ethereum/go-ethereum/wiki/Mobile-Clients:-Libraries-and-Inproc-Ethereum-Nodes) -- [Dapps nativos: Go bindings a contratos Ethereum](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts) +- [Aplicações de Blockchain como Serviço usando Ethereum e Quorum](https://blockchain.dcwebmakers.com/blockchain-as-a-service-apps-using-ethereum-and-quorum.html) +- [Armazenamento Distribuído IPFS e Swarm em Aplicações de Blockchain Ethereum](https://blockchain.dcwebmakers.com/work-with-distributed-storage-ipfs-and-swarm-in-ethereum.html) +- [Clientes móveis: Bibliotecas e nós Ethereum Inproc](https://github.com/ethereum/go-ethereum/wiki/Mobile-Clients:-Libraries-and-Inproc-Ethereum-Nodes) +- [dApps nativos: bindings Go para contratos Ethereum](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts) -## Projetos e Ferramentas para Go {#go-projects-and-tools} +## Projetos e ferramentas Go {#go-projects-and-tools} -- [Geth / Go Ethereum](https://github.com/ethereum/go-ethereum) - _Implementação Oficial do protocolo da Ethereum_ -- [Go Ethereum Code Analysis](https://github.com/ZtesoftCS/go-ethereum-code-analysis) - _Revisão e analise do código-fonte do Go Ethereum_ +- [Geth / Go Ethereum](https://github.com/ethereum/go-ethereum) - _Implementação oficial em Go do protocolo da Ethereum_ +- [Análise de Código do Go Ethereum](https://github.com/ZtesoftCS/go-ethereum-code-analysis) - _Revisão e análise do código-fonte do Go Ethereum_ - [Erigon](https://github.com/ledgerwatch/erigon) - _Derivado mais rápido do Go Ethereum, com foco em nós de arquivo_ -- [Golem](https://github.com/golemfactory/golem) - _Golem está criando um mercado global para computação distribuída_ -- [Quorum](https://github.com/jpmorganchase/quorum) - _Uma implementação permissionada da Ethereum com suporte a privacidade de dados_ -- [Prysm](https://github.com/prysmaticlabs/prysm) - _Implementação em Go da Ethereum 'Serenity' 2.0_ -- [Eth Tweet](https://github.com/yep/eth-tweet) - _Twitter descentralizado: Um serviço de microblogging executado no blockchain da Ethereum_ -- [Plasma MVP Golang](https://github.com/kyokan/plasma) — _Implementação e extensão da especificação de Plasma minimamente Viável_ -- [Open Ethereum Mining Pool](https://github.com/sammy007/open-ethereum-pool) - _Um pool de mineração da Ethereum de código aberto_ -- [Ethereum HD Wallet](https://github.com/miguelmota/go-ethereum-hdwallet) - _Derivações de carteiras Ethereum em Go_ -- [Multi Geth](https://github.com/multi-geth/multi-geth) - _Suporte para muitos tipos de redes Ethereum_ -- [Geth Light Cliente](https://github.com/zsfelfoldi/go-ethereum/wiki/Geth-Light-Client) - _Implementação do Geth do Subprotocolo Light Ethereum_ -- [Ethereum Golang SDK](https://github.com/everFinance/goether) - _Uma implementação simples de carteira Ethereum e utilitários em Golang_ -- [Covalent Golang SDK](https://github.com/covalenthq/covalent-api-sdk-go) - _Acesso eficiente a dados blockchain via SDK Go para mais de 200 blockchains_ +- [Golem](https://github.com/golemfactory/golem) - _O Golem está criando um mercado global para poder de computação_ +- [Quorum](https://github.com/jpmorganchase/quorum) - _Uma implementação permissionada da Ethereum com suporte à privacidade de dados_ +- [Prysm](https://github.com/prysmaticlabs/prysm) - _Implementação em Go do Ethereum 'Serenity' 2.0_ +- [Eth Tweet](https://github.com/yep/eth-tweet) - _Twitter descentralizado: um serviço de microblogging executado na blockchain Ethereum_ +- [Plasma MVP Golang](https://github.com/kyokan/plasma) — _Implementação e extensão em Golang da especificação do Plasma Mínimo Viável_ +- [Open Ethereum Mining Pool](https://github.com/sammy007/open-ethereum-pool) - _Um pool de mineração Ethereum de código aberto_ +- [Carteira HD Ethereum](https://github.com/miguelmota/go-ethereum-hdwallet) - _Derivações de Carteira HD Ethereum em Go_ +- [Multi Geth](https://github.com/multi-geth/multi-geth) - _Suporte para vários tipos de redes Ethereum_ +- [Cliente Leve Geth](https://github.com/zsfelfoldi/go-ethereum/wiki/Geth-Light-Client) - _Implementação Geth do Subprotocolo Leve Ethereum_ +- [SDK Ethereum para Golang](https://github.com/everFinance/goether) - _Uma implementação simples de carteira Ethereum e utilitários em Golang_ +- [SDK Covalent para Golang](https://github.com/covalenthq/covalent-api-sdk-go) - _Acesso eficiente a dados de blockchain via SDK Go para mais de 200 blockchains_ Procurando por mais recursos? Confira [ethereum.org/developers](/developers/) -## Colaboradores da Comunidade Go {#go-community-contributors} +## Contribuidores da comunidade Go {#go-community-contributors} - [Geth Discord](https://discordapp.com/invite/nthXNEv) - [Geth Gist](https://gitter.im/ethereum/go-ethereum) -- [Gophers Slack](https://invite.slack.golangbridge.org/) - [#ethereum channel](https://gophers.slack.com/messages/C9HP1S9V2) +- [Slack dos Gophers](https://invite.slack.golangbridge.org/) - [canal #ethereum](https://gophers.slack.com/messages/C9HP1S9V2) - [StackExchange - Ethereum](https://ethereum.stackexchange.com/) - [Multi Geth Gitter](https://gitter.im/ethoxy/multi-geth) -- [Ethereum Gitter](https://gitter.im/ethereum/home) -- [Gitter cliente de Geth](https://gitter.im/ethereum/light-client) +- [Gitter do Ethereum](https://gitter.im/ethereum/home) +- [Gitter do Cliente Leve Geth](https://gitter.im/ethereum/light-client) ## Outras listas agregadas {#other-aggregated-lists} -- [Incrível Ethereum](https://github.com/btomashvili/awesome-ethereum) -- [Consensys: uma lista definitiva de ferramentas para desenvolvedores da Ethereum](https://media.consensys.net/an-definitive-list-of-ethereum-developer-tools-2159ce865974) ➜ [fonte GitHub](https://github.com/ConsenSys/ethereum-developer-tools-list) +- [Awesome Ethereum](https://github.com/btomashvili/awesome-ethereum) +- [Consensys: Uma Lista Definitiva de Ferramentas para Desenvolvedores Ethereum](https://media.consensys.net/an-definitive-list-of-ethereum-developer-tools-2159ce865974) | [Fonte no GitHub](https://github.com/ConsenSys/ethereum-developer-tools-list) diff --git a/public/content/translations/pt-br/developers/docs/programming-languages/index.md b/public/content/translations/pt-br/developers/docs/programming-languages/index.md index 2f2aba6889e..9652e265d60 100644 --- a/public/content/translations/pt-br/developers/docs/programming-languages/index.md +++ b/public/content/translations/pt-br/developers/docs/programming-languages/index.md @@ -1,10 +1,11 @@ --- -title: Linguagens de programação -description: +title: "Linguagens de programação" +description: "Descobrir recursos de desenvolvimento Ethereum para várias línguas de programação, incluindo JavaScript, Python, Go, Rust e muito mais." lang: pt-br --- -Um erro comum é que os desenvolvedores devem escrever [contratos inteligentes](/developers/docs/smart-contracts/) Para desenvolver na Ethereum. Isso é falso. Uma das belezas da rede e comunidade Ethereum é que você pode [participar](/community/)com apenas uma linguagem de programação. +Um equívoco comum é que os desenvolvedores precisam escrever [contratos inteligentes](/developers/docs/smart-contracts/) para construir no Ethereum. Isso é falso. +Uma das belezas da rede e da comunidade Ethereum é que você pode [participar](/community/) em praticamente qualquer linguagem de programação. Ethereum e sua comunidade abraçam código aberto. Você pode encontrar projetos da comunidade - implementação em cliente, APIs, frameworks de desenvolvimento, ferramentas de teste - em uma ampla variedade de linguagens. @@ -12,19 +13,21 @@ Ethereum e sua comunidade abraçam código aberto. Você pode encontrar projetos Selecione a sua linguagem de programação preferida para encontrar projetos, recursos e comunidades virtuais: -- [Ethereum para desenvolvedores Dart](/developers/docs/programming-languages/dart/) -- [Ethereum para desenvolvedores Delphi](/developers/docs/programming-languages/delphi/) -- [Ethereum para desenvolvedores .NET](/developers/docs/programming-languages/dot-net/) -- [Ethereum para desenvolvedores Elixir](/developers/docs/programming-languages/elixir/) -- [Ethereum para desenvolvedores Go](/developers/docs/programming-languages/golang/) -- [Ethereum para desenvolvedores Java](/developers/docs/programming-languages/java/) -- [Ethereum para desenvolvedores JavaScript](/developers/docs/programming-languages/javascript/) -- [Ethereum para desenvolvedores Python](/developers/docs/programming-languages/python/) -- [Ethereum para desenvolvedores Ruby](/developers/docs/programming-languages/ruby/) -- [Ethereum para desenvolvedores Rust](/developers/docs/programming-languages/rust/) +- [Ethereum para desenvolvedores de Dart](/developers/docs/programming-languages/dart/) +- [Ethereum para desenvolvedores de Delphi](/developers/docs/programming-languages/delphi/) +- [Ethereum para desenvolvedores de .NET](/developers/docs/programming-languages/dot-net/) +- [Ethereum para desenvolvedores de Elixir](/developers/docs/programming-languages/elixir/) +- [Ethereum para desenvolvedores de Go](/developers/docs/programming-languages/golang/) +- [Ethereum para desenvolvedores de Java](/developers/docs/programming-languages/java/) +- [Ethereum para desenvolvedores de JavaScript](/developers/docs/programming-languages/javascript/) +- [Ethereum para desenvolvedores de Python](/developers/docs/programming-languages/python/) +- [Ethereum para desenvolvedores de Ruby](/developers/docs/programming-languages/ruby/) +- [Ethereum para desenvolvedores de Rust](/developers/docs/programming-languages/rust/) ### E se minha linguagem não for suportada {#other-lang} -Se você deseja vincular a recursos ou apontar para uma comunidade virtual para uma linguagem de programação adicional, você pode solicitar uma nova página, [abrindo um problema](https://github.com/ethereum/ethereum-org-website/issues/new/choose). +Se você quiser criar um link para recursos ou indicar uma comunidade virtual para uma linguagem de programação adicional, poderá solicitar uma nova página [abrindo uma issue](https://github.com/ethereum/ethereum-org-website/issues/new/choose). -Se você quiser apenas escrever código para interface com a blockchain usando uma linguagem atualmente não compatível você pode usar a [interface JSON-RPC](/developers/docs/apis/json-rpc/) para se conectar à rede Ethereum. Qualquer linguagem de programação que pode usar TCP/IP pode usar essa interface. +Se você quer apenas escrever código para interagir com a blockchain usando uma linguagem atualmente não suportada, +você pode usar a [interface JSON-RPC](/developers/docs/apis/json-rpc/) para se conectar à rede Ethereum. Qualquer linguagem +de programação que pode usar TCP/IP pode usar essa interface. diff --git a/public/content/translations/pt-br/developers/docs/programming-languages/java/index.md b/public/content/translations/pt-br/developers/docs/programming-languages/java/index.md index 283176e1fc5..7cc8f901153 100644 --- a/public/content/translations/pt-br/developers/docs/programming-languages/java/index.md +++ b/public/content/translations/pt-br/developers/docs/programming-languages/java/index.md @@ -5,59 +5,62 @@ lang: pt-br incomplete: true --- -Aprenda a desenvolver para Ethereum utilizando projetos e ferramentas baseados em Java +Aprenda a desenvolver para Ethereum usando projetos e ferramentas baseadas em Java -Utilize Ethereum para criar aplicações descentralizadas ("dapps") que utilizam os benefícios das criptomoedas e tecnologias de cadeia de blocos. Esses dapps podem ser muito confiáveis, o que significa que uma vez que eles são implantados na rede Ethereum, sempre serão executados como programados. Eles podem controlar ativos digitais a fim de criar novos tipos de aplicações financeiras. Eles podem ser descentralizados, o que significa que nenhuma entidade ou pessoa os controla, sendo portanto praticamente impossíves de serem censurados. +Utilize Ethereum para criar aplicações descentralizadas ("dapps") que utilizam os benefícios das criptomoedas e tecnologias de cadeia de blocos. Esses dapps podem ser muito confiáveis, o que significa que uma vez que eles são implantados na rede Ethereum, sempre serão executados como programados. +Eles podem controlar ativos digitais a fim de criar novos tipos de aplicações financeiras. Eles podem ser descentralizados, o que significa que nenhuma entidade ou pessoa os controla sendo, portanto, praticamente impossíveis de serem censurados. -## Introdução aos contratos inteligentes e linguagem Solidity {#getting-started-with-smart-contracts-and-solidity} +## Começando com contratos inteligentes e a linguagem Solidity {#getting-started-with-smart-contracts-and-solidity} -**Dê seus primeiros passos para integrar Java com Ethereum ** +**Dê seus primeiros passos para integrar Java com Ethereum** -Precisa de uma introdução geral? Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers.](/developers/) +Precisa de uma introdução geral? +Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers.](/developers/) -- [Cadeia de blocos explicada](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) -- [Entender os Smart Contracts](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) -- [Escreva seu primeiro Smart Contract](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) -- [Aprenda como Compilar e Implementar Solidity](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) +- [Blockchain Explicada](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) +- [Entendendo Contratos Inteligentes](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [Escreva seu Primeiro Contrato Inteligente](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [Aprenda a Compilar e Implantar o Solidity](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) -## Trabalhando com clientes Ethereum {#working-with-ethereum-clients} +## Trabalhando com clientes Ethereum {#working-with-ethereum-clients} -Aprenda como usar [Web3J](https://github.com/web3j/web3j)e Besu Hiperregistro, dois principais clientes Java Ethereum +Aprenda a usar o [Web3J](https://github.com/web3j/web3j) e o Hyperledger Besu, dois dos principais clientes Java para Ethereum - [Conectando a um cliente Ethereum com Java, Eclipse e Web3J](https://kauri.io/article/b9eb647c47a546bc95693acc0be72546/connecting-to-an-ethereum-client-with-java-eclipse-and-web3j) -- [Gerenciando uma conta Ethereum com Java e Web3j](https://kauri.io/article/925d923e12c543da9a0a3e617be963b4/manage-an-ethereum-account-with-java-and-web3j) -- [Gerar um wrapper Java a partir do seu Smart Contract](https://kauri.io/article/84475132317d4d6a84a2c42eb9348e4b/generate-a-java-wrapper-from-your-smart-contract) -- [Interagindo com um Smart Contract Ethereum](https://kauri.io/article/14dc434d11ef4ee18bf7d57f079e246e/interacting-with-an-ethereum-smart-contract-in-java) -- [Monitorando Eventos de Smart Contracts Ethereum](https://kauri.io/article/760f495423db42f988d17b8c145b0874/listening-for-ethereum-smart-contract-events-in-java) -- [Usando Besu (Pantheon), o Cliente Ethereum Java com Linux](https://kauri.io/article/276dd27f1458443295eea58403fd6965/using-pantheon-the-java-ethereum-client-with-linux) -- [Executando um Nó de Hyperledger Besu (Pantheon) em testes de integração com Java](https://kauri.io/article/7dc3ecc391e54f7b8cbf4e5fa0caf780/running-a-pantheon-node-in-java-integration-tests) -- [Dicas Web3j](https://kauri.io/web3j-cheat-sheet-(java-ethereum)/5dfa1ea941ac3d0001ce1d90/c) - -Aprenda a usar [ethers-kt](https://github.com/Kr1ptal/ethers-kt), uma biblioteca Kotlin assíncrona e de alto desempenho para interagir com blockchains baseadas em EVM. Destinada às plataformas JVM e Android. +- [Gerenciar uma conta Ethereum com Java e Web3j](https://kauri.io/article/925d923e12c543da9a0a3e617be963b4/manage-an-ethereum-account-with-java-and-web3j) +- [Gerar um Wrapper Java a partir do seu Contrato Inteligente](https://kauri.io/article/84475132317d4d6a84a2c42eb9348e4b/generate-a-java-wrapper-from-your-smart-contract) +- [Interagindo com um Contrato Inteligente da Ethereum](https://kauri.io/article/14dc434d11ef4ee18bf7d57f079e246e/interacting-with-an-ethereum-smart-contract-in-java) +- [Escutando Eventos de Contratos Inteligentes da Ethereum](https://kauri.io/article/760f495423db42f988d17b8c145b0874/listening-for-ethereum-smart-contract-events-in-java) +- [Usando Besu (Pantheon), o cliente Java Ethereum com Linux](https://kauri.io/article/276dd27f1458443295eea58403fd6965/using-pantheon-the-java-ethereum-client-with-linux) +- [Executando um nó Hyperledger Besu (Pantheon) em testes de integração Java](https://kauri.io/article/7dc3ecc391e54f7b8cbf4e5fa0caf780/running-a-pantheon-node-in-java-integration-tests) +- [Folha de dicas do Web3j](https://kauri.io/web3j-cheat-sheet-\(java-ethereum\)/5dfa1ea941ac3d0001ce1d90/c) + +Aprenda a usar o [ethers-kt](https://github.com/Kr1ptal/ethers-kt), uma biblioteca Kotlin assíncrona e de alto desempenho para interagir com blockchains baseadas em EVM. Destinada às plataformas JVM e Android. + - [Transferir tokens ERC20](https://github.com/Kr1ptal/ethers-kt/blob/master/examples/src/main/kotlin/io/ethers/examples/abi/TransferERC20.kt) -- [Troca UniswapV2 com escuta de eventos](https://github.com/Kr1ptal/ethers-kt/blob/master/examples/src/main/kotlin/io/ethers/examples/tokenswapwitheventlistening/TokenSwapWithEventListening.kt) -- [Rastreador de saldo ETH / ERC20](https://github.com/Kr1ptal/ethers-kt/blob/master/examples/src/main/kotlin/io/ethers/examples/balancetracker/BalanceTracker.kt) +- [Swap no UniswapV2 com escuta de eventos](https://github.com/Kr1ptal/ethers-kt/blob/master/examples/src/main/kotlin/io/ethers/examples/tokenswapwitheventlistening/TokenSwapWithEventListening.kt) +- [Rastreador de saldo de ETH / ERC20](https://github.com/Kr1ptal/ethers-kt/blob/master/examples/src/main/kotlin/io/ethers/examples/balancetracker/BalanceTracker.kt) -## Artigos intermediários {#intermediate-articles} +## Artigos Intermediários {#intermediate-articles} - [Gerenciando o armazenamento em um aplicativo Java com IPFS](https://kauri.io/article/3e8494f4f56f48c4bb77f1f925c6d926/managing-storage-in-a-java-application-with-ipfs) -- [Gerenciando tokens ERC20 em Java com Web3j](https://kauri.io/article/d13e911bbf624108b1d5718175a5e0a0/manage-erc20-tokens-in-java-with-web3j) -- [Gerentes de Transações Web3j](https://kauri.io/article/4cb780bb4d0846438d11885a25b6d7e7/web3j-transaction-managers) +- [Gerenciar tokens ERC20 em Java com Web3j](https://kauri.io/article/d13e911bbf624108b1d5718175a5e0a0/manage-erc20-tokens-in-java-with-web3j) +- [Gerenciadores de transação do Web3j](https://kauri.io/article/4cb780bb4d0846438d11885a25b6d7e7/web3j-transaction-managers) -## Padrões de uso avançados {#advanced-use-patterns} +## Padrões de uso avançados {#advanced-use-patterns} -- [Usando o Eventeum para construir um cache de dados de Smart Contract em Java](https://kauri.io/article/fe81ee9612eb4e5a9ab72790ef24283d/using-eventeum-to-build-a-java-smart-contract-data-cache) +- [Usando o Eventeum para criar um cache de dados de contratos inteligentes em Java](https://kauri.io/article/fe81ee9612eb4e5a9ab72790ef24283d/using-eventeum-to-build-a-java-smart-contract-data-cache) -## Projetos e ferramentas em Java {#java-projects-and-tools} +## Projetos e ferramentas Java {#java-projects-and-tools} -- [Web3J (Biblioteca para Interagir com Clientes Ethereum)](https://github.com/web3j/web3j) +- [Web3J (Biblioteca para interagir com clientes Ethereum)](https://github.com/web3j/web3j) - [ethers-kt (Biblioteca Kotlin/Java/Android assíncrona e de alto desempenho para blockchains baseadas em EVM.)](https://github.com/Kr1ptal/ethers-kt) -- [Evento (Monitorador de eventos)](https://github.com/ConsenSys/eventeum) -- [Mahuta (Ferramenta de Desenvolvedor IPFS)](https://github.com/ConsenSys/mahuta) +- [Eventeum (ouvinte de eventos)](https://github.com/ConsenSys/eventeum) +- [Mahuta (Ferramentas de desenvolvimento para IPFS)](https://github.com/ConsenSys/mahuta) -Procurando por mais recursos? Leia [ethereum.org/developers.](/developers/) +Procurando por mais recursos? Confira [ethereum.org/developers.](/developers/) -## Colaboradores da comunidade Java {#java-community-contributors} +## Contribuidores da comunidade Java {#java-community-contributors} - [IO Builders](https://io.builders) - [Kauri](https://kauri.io) diff --git a/public/content/translations/pt-br/developers/docs/programming-languages/javascript/index.md b/public/content/translations/pt-br/developers/docs/programming-languages/javascript/index.md index 3fe8201fb9c..cc51948647e 100644 --- a/public/content/translations/pt-br/developers/docs/programming-languages/javascript/index.md +++ b/public/content/translations/pt-br/developers/docs/programming-languages/javascript/index.md @@ -4,35 +4,36 @@ description: Aprenda a desenvolver para Ethereum utilizando projetos e ferrament lang: pt-br --- -O JavaScript está entre as linguagens mais populares no ecossistema Ethereum. De fato, existe uma [equipe](https://github.com/ethereumjs) dedicada a levar o máximo da Ethereum ao JavaScript possível. +O JavaScript está entre as linguagens mais populares no ecossistema Ethereum. De fato, existe uma [equipe](https://github.com/ethereumjs) dedicada a trazer o máximo de Ethereum para o JavaScript possível. -Existem oportunidades para escrever JavaScript (ou algo parecido) em [todos os níveis de pilhas](/developers/docs/ethereum-stack/). +Existem oportunidades para escrever JavaScript (ou algo próximo) em [todos os níveis da pilha](/developers/docs/ethereum-stack/). -## Interagir com Ethereum {#interact-with-ethereum} +## Interagir com o Ethereum {#interact-with-ethereum} ### Bibliotecas de API JavaScript {#javascript-api-libraries} -Se você deseja escrever JavaScript para consultar a blockchain, enviar transações e muito mais, a maneira mais conveniente para fazer isso é usando uma [biblioteca de API JavaScript](/developers/docs/apis/javascript/). Estas APIs permitem que os desenvolvedores interajam facilmente com os [nós da rede Ethereum](/developers/docs/nodes-and-clients/). +Se você deseja escrever em JavaScript para consultar a blockchain, enviar transações e muito mais, a maneira mais conveniente de fazer isso é usando uma [biblioteca de API JavaScript](/developers/docs/apis/javascript/). Estas APIs permitem que os desenvolvedores interajam facilmente com os [nós na rede Ethereum](/developers/docs/nodes-and-clients/). Você pode usar essas bibliotecas para interagir com contratos inteligentes na Ethereum, assim é possível construir um dapp onde você só usa JavaScript para interagir com contratos preexistentes. **Confira** -- [Web3.js](https://web3js.readthedocs.io/) -- [Ethers.js](https://docs.ethers.io/)_— Implementação completa de uma carteira Ethereum e utilidades em JavaScript e TypeScript._ -- [viem](https://viem.sh) – uma interface TypeScript para Ethereum que fornece primitivas sem estado de baixo nível para interagir com Ethereum. +- [Web3.js](https://web3js.readthedocs.io) +- [Ethers.js](https://ethers.org) – _inclui implementação de carteira Ethereum e utilitários em JavaScript e TypeScript._ +- [viem](https://viem.sh) – _uma Interface TypeScript para o Ethereum que fornece primitivas de baixo nível e sem estado para interagir com o Ethereum._ +- [Drift](https://ryangoree.github.io/drift/) – _uma meta-biblioteca TypeScript com cache, hooks e mocks de teste integrados para um desenvolvimento Ethereum sem esforço em várias bibliotecas web3._ -### Smart Contracts {#smart-contracts} +### Contratos inteligentes {#smart-contracts} -Se você for um desenvolvedor JavaScript que deseja escrever seu próprio contrato inteligente, você pode querer se familiarizar com [Solidity](https://solidity.readthedocs.io). Esta é a linguagem de contrato inteligente mais popular e é sintaticamente semelhante ao JavaScript, o que pode torná-la mais fácil de aprender. +Se você é um desenvolvedor JavaScript e quer escrever seu próprio contrato inteligente, talvez queira se familiarizar com o [Solidity](https://solidity.readthedocs.io). Esta é a linguagem de contrato inteligente mais popular e é sintaticamente semelhante ao JavaScript, o que pode torná-la mais fácil de aprender. -Mais nos [contratos inteligentes](/developers/docs/smart-contracts/). +Mais sobre [contratos inteligentes](/developers/docs/smart-contracts/). -## Entender o protocolo {#understand-the-protocol} +## Entenda o protocolo {#understand-the-protocol} -### A Máquina Virtual da Ethereum {#the-ethereum-virtual-machine} +### A máquina virtual Ethereum {#the-ethereum-virtual-machine} -Há uma implementação JavaScript da [máquina virtual da Ethereum](/developers/docs/evm/). Apoia as regras de fork (bifurcação) mais recentes. As regras de bifurcação referem-se a alterações feitas na EVM como resultado de melhorias planejadas. +Existe uma implementação em JavaScript da [máquina virtual Ethereum](/developers/docs/evm/). Apoia as regras de fork (bifurcação) mais recentes. As regras de bifurcação referem-se a alterações feitas na EVM como resultado de melhorias planejadas. Divide-se em vários pacotes de JavaScript que você pode conferir para entender melhor: @@ -46,17 +47,15 @@ Isso ajudará você a entender coisas como "qual é a estrutura de dados de uma Se você prefere ler código, esse JavaScript poderia ser uma ótima alternativa à leitura em nossa documentação. -**Confira o monorepo** -[`ethereumjs`](https://github.com/ethereumjs/ethereumjs-vm) +**Confira a EVM** +[`@ethereumjs/evm`](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/evm) ### Nós e clientes {#nodes-and-clients} Um cliente Ethereumjs está em desenvolvimento ativo que permite você explorar como os clientes Ethereum funcionam em um idioma que você entende; JavaScript! -Ele costumava estar hospedado em um [`repositório`](https://github.com/ethereumjs/ethereumjs-client) autônomo, no entanto, foi posteriormente incorporado ao monorepo EthereumVM como um pacote. - -**Confira o monorepo** -[`ethereumjs`](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/client) +**Confira o cliente** +[`@ethereumjs/client`](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/client) ## Outros projetos {#other-projects} @@ -64,10 +63,10 @@ Há também muitas outras coisas acontecendo na terra da Ethereum JavaScript, in - bibliotecas de utilitários de carteira. - ferramentas para gerar, importar e exportar chaves da Ethereum. -- uma implementação da `merkle-patricia-tree` – uma estrutura de dados delineada no papel amarelo da Ethereum. +- uma implementação da `merkle-patricia-tree` – uma estrutura de dados descrita no Yellow Paper do Ethereum. Explore o que mais lhe interessa no [repositório EthereumJS](https://github.com/ethereumjs) ## Leitura adicional {#further-reading} -_Conhece um recurso da comunidade que te ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ diff --git a/public/content/translations/pt-br/developers/docs/programming-languages/python/index.md b/public/content/translations/pt-br/developers/docs/programming-languages/python/index.md index 3f1f12b822e..2c0c122da67 100644 --- a/public/content/translations/pt-br/developers/docs/programming-languages/python/index.md +++ b/public/content/translations/pt-br/developers/docs/programming-languages/python/index.md @@ -5,86 +5,97 @@ lang: pt-br incomplete: true --- -Aprenda a desenvolver para Ethereum utilizando projetos e ferramentas baseados em Python +Aprenda a desenvolver para o Ethereum usando projetos e ferramentas baseados em Python -Utilize Ethereum para criar aplicações descentralizadas ("dapps") que utilizam os benefícios das criptomoedas e tecnologias de cadeia de blocos. Esses dapps podem ser muito confiáveis, o que significa que uma vez que eles são implantados na rede Ethereum, sempre serão executados como programados. Eles podem controlar ativos digitais a fim de criar novos tipos de aplicações financeiras. Eles podem ser descentralizados, o que significa que nenhuma entidade ou pessoa os controla sendo, portanto, praticamente impossíveis de serem censurados. +Utilize Ethereum para criar aplicações descentralizadas ("dapps") que utilizam os benefícios das criptomoedas e tecnologias de cadeia de blocos. Esses dapps podem ser muito confiáveis, o que significa que uma vez que eles são implantados na rede Ethereum, sempre serão executados como programados. +Eles podem controlar ativos digitais a fim de criar novos tipos de aplicações financeiras. Eles podem ser descentralizados, o que significa que nenhuma entidade ou pessoa os controla sendo, portanto, praticamente impossíveis de serem censurados. -## Começando com contratos inteligentes e linguagem Solidity {#getting-started-with-smart-contracts-and-solidity} +## Começando com contratos inteligentes e a linguagem Solidity {#getting-started-with-smart-contracts-and-solidity} **Dê seus primeiros passos para integrar Python com Ethereum** -Precisa de uma introdução geral? Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers](/developers/). +Precisa de uma introdução geral? +Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers](/developers/). -- [Cadeia de blocos explicada](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) -- [Entendendo contratos inteligentes](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) -- [Escreva seu primeiro contrato inteligente](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) -- [Aprenda como Compilar e Implantar em Solidity](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) +- [Blockchain Explicada](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) +- [Entendendo Contratos Inteligentes](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [Escreva seu Primeiro Contrato Inteligente](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [Aprenda a Compilar e Implantar o Solidity](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) +- [Relatório O estado do Python na blockchain em 2023](https://tradingstrategy.ai/blog/the-state-of-python-in-blockchain-in-2023) -## Artigos para Iniciantes {#beginner-articles} +## Artigos para iniciantes {#beginner-articles} -- [Um (Python) Guia do desenvolvedor para Ethereum](https://snakecharmers.ethereum.org/a-developers-guide-to-ethereum-pt-1/) -- [O estado do Python no relatório de 2023 da blockchain](https://tradingstrategy.ai/blog/the-state-of-python-in-blockchain-in-2023) -- [Uma Introdução aos Smart Contracts com Vyper](https://kauri.io/#collections/Getting%20Started/an-introduction-to-smart-contracts-with-vyper/) -- [Instale seu próprio Token ERC20 com Python e Brownie](https://betterprogramming.pub/python-blockchain-token-deployment-tutorial-create-an-erc20-77a5fd2e1a58) -- [Como desenvolver um contrato Ethereum utilizando Python Flask?](https://medium.com/coinmonks/how-to-develop-ethereum-contract-using-python-flask-9758fe65976e) -- [Intro para Web3.py · Ethereum para desenvolvedores Python](https://www.dappuniversity.com/articles/web3-py-intro) -- [Como chamar uma função do Smart Contract utilizando Python e web3.py](https://stackoverflow.com/questions/57580702/how-to-call-a-smart-contract-function-using-python-and-web3-py) +- [Visão geral do web3.py](https://web3py.readthedocs.io/en/latest/overview.html) +- [Tour pelo Ecossistema Python da Ethereum](https://snakecharmers.ethereum.org/python-ecosystem/) +- [Um Guia do Desenvolvedor (Python) para Ethereum](https://snakecharmers.ethereum.org/a-developers-guide-to-ethereum-pt-1/) +- [Digno de prêmio: um guia de hackathon de Python para Ethereum](https://snakecharmers.ethereum.org/prize-worthy/) +- [Uma introdução aos contratos inteligentes com Vyper](https://kauri.io/#collections/Getting%20Started/an-introduction-to-smart-contracts-with-vyper/) +- [Como desenvolver um contrato Ethereum usando Python Flask?](https://medium.com/coinmonks/how-to-develop-ethereum-contract-using-python-flask-9758fe65976e) +- [Introdução ao Web3.py · Ethereum para desenvolvedores Python](https://www.dappuniversity.com/articles/web3-py-intro) +- [Como chamar uma função de contrato inteligente usando Python e web3.py](https://stackoverflow.com/questions/57580702/how-to-call-a-smart-contract-function-using-python-and-web3-py) -## Artigos intermediários {#intermediate-articles} +## Artigos Intermediários {#intermediate-articles} -- [Desenvolvimento de Dapp para programadores Python](https://www.youtube.com/watch?v=tE-8bG35VNw) -- [Criando uma Interface Python Ethereum: Parte 1](https://hackernoon.com/creating-a-python-ethereum-interface-part-1-4d2e47ea0f4d) -- [Contratos Inteligentes Ethereum em Python: um guia (mais ou menos) abrangente](https://hackernoon.com/ethereum-smart-contracts-in-python-a-comprehensive-ish-guide-771b03990988) -- [Usando Brownie e Python para implantar Contratos Inteligentes](https://dev.to/patrickalphac/using-brownie-for-to-deploy-smart-contracts-1kkp) -- [Criando NFTs no OpenSea com Brownie](https://www.freecodecamp.org/news/how-to-make-an-nft-and-render-on-opensea-marketplace/) +- [Amigos do web3.py: introdução ao Ape](https://snakecharmers.ethereum.org/intro-to-ape/) +- [Desenvolvimento de Dapp para Programadores Python](https://levelup.gitconnected.com/dapps-development-for-python-developers-f52b32b54f28) +- [Criando uma Interface Python para Ethereum: Parte 1](https://hackernoon.com/creating-a-python-ethereum-interface-part-1-4d2e47ea0f4d) +- [Contratos inteligentes da Ethereum em Python: um guia (quase) completo](https://hackernoon.com/ethereum-smart-contracts-in-python-a-comprehensive-ish-guide-771b03990988) ## Padrões de uso avançados {#advanced-use-patterns} -- [Compilando, implantando e chamando Contratos Inteligentes Ethereum utilizando Python](https://yohanes.gultom.id/2018/11/28/compiling-deploying-and-calling-ethereum-smartcontract-using-python/) -- [Analisando Smart Contracts em Solidity usando Slither](https://kauri.io/#collections/DevOps/analyze-solidity-smart-contracts-with-slither/#analyze-solidity-smart-contracts-with-slither) -- [Tutorial de blockchain Fintech: emprestar e pedir emprestado com Python](https://blog.chain.link/blockchain-fintech-defi-tutorial-lending-borrowing-python/) +- [Padrões do web3.py: inscrições de evento em tempo real](https://snakecharmers.ethereum.org/subscriptions/) +- [Padrões do web3.py: WebSocketProvider](https://snakecharmers.ethereum.org/websocketprovider/) +- [Compilando, implantando e chamando contratos inteligentes da Ethereum usando Python](https://yohanes.gultom.id/2018/11/28/compiling-deploying-and-calling-ethereum-smartcontract-using-python/) +- [Analisar contratos inteligentes em Solidity com o Slither](https://kauri.io/#collections/DevOps/analyze-solidity-smart-contracts-with-slither/#analyze-solidity-smart-contracts-with-slither) +- [Tutorial de Fintech em Blockchain: empréstimos e recebimento de empréstimos com Python](https://blog.chain.link/blockchain-fintech-defi-tutorial-lending-borrowing-python/) -## Projetos e ferramentas em Python {#python-projects-and-tools} +## Artigos Arquivados + +- [Implante seu próprio Token ERC20 com Python e Brownie](https://betterprogramming.pub/python-blockchain-token-deployment-tutorial-create-an-erc20-77a5fd2e1a58) +- [Usando o Brownie e o Python para implantar Contratos Inteligentes](https://dev.to/patrickalphac/using-brownie-for-to-deploy-smart-contracts-1kkp) +- [Criando NFTs no OpenSea com o Brownie](https://www.freecodecamp.org/news/how-to-make-an-nft-and-render-on-opensea-marketplace/) + +## Projetos e ferramentas Python {#python-projects-and-tools} ### Ativo: {#active} -- [Web3.py](https://github.com/ethereum/web3.py) - _Biblioteca em Python para interagir com Ethereum_ -- [Vyper](https://github.com/ethereum/vyper/) - _Linguagem de Smart Contract em Python para a Máquina Virtual Ethereum_ -- [Ape](https://github.com/ApeWorX/ape) - _A ferramenta de desenvolvimento de contrato inteligente (smart contract) para Pythonistas, Cientistas de Dados e Profissionais de Segurança_ -- [py-evm](https://github.com/ethereum/py-evm) - _Implementação de uma Máquina Virtual Ethereum_ -- [eth-tester](https://github.com/ethereum/eth-tester) - _ferramentas para testar aplicativos baseados na Ethereum_ -- [eth-utils](https://github.com/ethereum/eth-utils/) - _funções de utilidade para trabalhar com bases de código relacionadas com a Ethereum_ -- [py-solc-x](https://pypi.org/project/py-solc-x/) - _wrapper em Python em cima do compilador solc solidity com suporte à versão 0.5.x_ -- [pymaker](https://github.com/makerdao/pymaker) - _API em Python para contratos Maker_ -- [siwe](https://github.com/signinwithethereum/siwe-py) - _Registre-se com Ethereum (siwe) para Python_ -- [Web3 DeFi para integrações Ethereum](https://github.com/tradingstrategy-ai/web3-ethereum-defi) - _Um pacote Python com integrações prontas para ERC-20, Uniswap e outros projetos populares_ -- [Wake](https://getwake.io) - _Framework Python completo para teste de contratos, fuzzing, implantação, varredura de vulnerabilidades e navegação de código (servidor de linguagem - [Ferramentas para Solidez](https://marketplace.visualstudio.com/items?itemName=AckeeBlockchain.tools-for-solidity))_ +- [Web3.py](https://github.com/ethereum/web3.py) – _biblioteca Python para interagir com a Ethereum_ +- [Vyper](https://github.com/ethereum/vyper/) – _linguagem de contrato inteligente pythônica para a EVM_ +- [Ape](https://github.com/ApeWorX/ape) – _A ferramenta de desenvolvimento de contratos inteligentes para Pythonistas, cientistas de dados e profissionais de segurança_ +- [py-evm](https://github.com/ethereum/py-evm) – _implementação da Máquina Virtual Ethereum_ +- [eth-tester](https://github.com/ethereum/eth-tester) – _ferramentas para testar aplicativos baseados em Ethereum_ +- [eth-utils](https://github.com/ethereum/eth-utils/) – _funções utilitárias para trabalhar com bases de código relacionadas à Ethereum_ +- [py-solc-x](https://pypi.org/project/py-solc-x/) – _wrapper Python em torno do compilador solc Solidity com suporte a 0.5.x_ +- [pymaker](https://github.com/makerdao/pymaker) – _API em Python para contratos Maker_ +- [siwe](https://github.com/signinwithethereum/siwe-py) – _Sign in with Ethereum (siwe) para Python_ +- [Web3 DeFi para integrações com Ethereum](https://github.com/tradingstrategy-ai/web3-ethereum-defi) – _um pacote Python com integrações prontas para ERC-20, Uniswap e outros projetos populares_ +- [Wake](https://getwake.io) – _framework Python completo para teste de contratos, fuzzing, implantação, verificação de vulnerabilidades e navegação de código (servidor de linguagem - [Ferramentas para Solidity](https://marketplace.visualstudio.com/items?itemName=AckeeBlockchain.tools-for-solidity))_ ### Arquivado / Não mais mantido: {#archived--no-longer-maintained} -- [Trinity](https://github.com/ethereum/trinity) - _cliente Ethereum Python_ -- [Mamba](https://github.com/arjunaskykok/mamba) - _Framework para escrever, compilar e implantar contratos inteligentes escritos em linguagem Vyper_ -- [Brownie](https://github.com/eth-brownie/brownie) - _Framework em Python para implantar, testar e interagir com contratos inteligentes Ethereum_ -- [pydevp2p](https://github.com/ethereum/pydevp2p) - _Implementação de uma pilha P2P Ethereum_ -- [py-wasm](https://github.com/ethereum/py-wasm) - _implementação em Python de um intérprete de montagem web_ +- [Trinity](https://github.com/ethereum/trinity) – _cliente Python do Ethereum_ +- [Mamba](https://github.com/arjunaskykok/mamba) – _framework para escrever, compilar e implantar contratos inteligentes escritos na linguagem Vyper_ +- [Brownie](https://github.com/eth-brownie/brownie) – _framework Python para implantar, testar e interagir com contratos inteligentes da Ethereum_ +- [pydevp2p](https://github.com/ethereum/pydevp2p) – _implementação da pilha P2P da Ethereum_ +- [py-wasm](https://github.com/ethereum/py-wasm) – _implementação em Python do interpretador Web Assembly_ Procurando por mais recursos? Confira [ethereum.org/developers](/developers/). -## Projetos usando as ferramentas Python {#projects-using-python-tooling} +## Projetos que usam ferramentas Python {#projects-using-python-tooling} Os seguintes projetos baseados na Ethereum usam ferramentas mencionadas nesta página. Os repositórios de código aberto relacionados servem como uma boa referência para exemplos de código e melhores práticas. -- [Yearn Finance](https://yearn.finance/) e [Repositório de Contratos Vault](https://github.com/yearn/yearn-vaults) -- [Repositório de contratos inteligentes Curve](https://curve.fi/) e [Curve](https://github.com/curvefi/curve-contract) -- [BadgerDAO](https://badger.com/) e [contratos inteligentes usando ferramentas Brownie](https://github.com/Badger-Finance/badger-system) -- [Sushi](https://sushi.com/) usa [Python na gestão e implantação dos seus contratos adquiridos](https://github.com/sushiswap/sushi-vesting-protocols) -- [Alpha Venture DAO](https://alphaventuredao.io/), da Alpha Homora fame, usa [Brownie para testar e implantar contratos inteligentes](https://github.com/AlphaFinanceLab/alpha-staking-contract) +- [Yearn Finance](https://yearn.finance/) e [repositório de contratos do Yearn Vault](https://github.com/yearn/yearn-vaults) +- [Curve](https://www.curve.finance/) e [repositório de contratos inteligentes da Curve](https://github.com/curvefi/curve-contract) +- [BadgerDAO](https://badger.com/) e [contratos inteligentes que usam o conjunto de ferramentas do Brownie](https://github.com/Badger-Finance/badger-system) +- O [Sushi](https://sushi.com/) usa [Python no gerenciamento e na implantação de seus contratos de aquisição](https://github.com/sushiswap/sushi-vesting-protocols) +- A [Alpha Finance](https://alphafinance.io/), famosa pelo Alpha Homora, usa o [Brownie para testar e implantar contratos inteligentes](https://github.com/AlphaFinanceLab/alpha-staking-contract) -## Comunidade de discussão Python {#python-community-contributors} +## Discussão da comunidade Python {#python-community-contributors} -- [Comunidade Discord Python Ethereum](https://discord.gg/9zk7snTfWe) Para discussões sobre Web3.py e outros frameworks Python -- [Vyper Discord](https://discord.gg/SdvKC79cJk) Para discussões sobre a programação de contratos inteligentes com Vyper +- [Discord da Comunidade Python da Ethereum](https://discord.gg/9zk7snTfWe) para discussão sobre o Web3.py e outras estruturas Python +- [Discord do Vyper](https://discord.gg/SdvKC79cJk) para discussão sobre programação de contratos inteligentes em Vyper -## Demais listas agregadas {#other-aggregated-lists} +## Outras listas agregadas {#other-aggregated-lists} -A wiki Vyper tem uma [Lista incrível de recursos sobre Vyper](https://github.com/vyperlang/vyper/wiki/Vyper-tools-and-resources) \ No newline at end of file +A wiki do Vyper tem uma [lista incrível de recursos para o Vyper](https://github.com/vyperlang/vyper/wiki/Vyper-tools-and-resources) \ No newline at end of file diff --git a/public/content/translations/pt-br/developers/docs/programming-languages/ruby/index.md b/public/content/translations/pt-br/developers/docs/programming-languages/ruby/index.md index bdc3eddfb5f..a6b60411901 100644 --- a/public/content/translations/pt-br/developers/docs/programming-languages/ruby/index.md +++ b/public/content/translations/pt-br/developers/docs/programming-languages/ruby/index.md @@ -9,52 +9,53 @@ incomplete: false Utilize Ethereum para criar aplicações descentralizadas ("dapps") que utilizam os benefícios das criptomoedas e tecnologias de cadeia de blocos. Esses dapps podem ser confiáveis, o que significa que, uma vez implantados na Ethereum, eles sempre serão executados conforme programado. Eles podem controlar ativos digitais para criar novos tipos de aplicações financeiros. Eles podem ser descentralizados, o que significa que nenhuma entidade ou pessoa os controla sendo, portanto, praticamente impossíveis de serem censurados. -## Introdução aos contratos inteligentes e linguagem Solidity {#getting-started-with-smart-contracts-and-solidity} +## Começando com contratos inteligentes e a linguagem Solidity {#getting-started-with-smart-contracts-and-solidity} **Dê seus primeiros passos para integrar Ruby com Ethereum** -Precisa de uma introdução geral? Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers](/developers/). +Precisa de uma introdução geral? +Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers](/developers/). -- [Cadeia de blocos explicada](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) -- [Entendendo os contratos inteligentes](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) -- [Escreva seu primeiro contrato inteligente](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) -- [Aprenda como Compilar e Implantar Solidity](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) +- [Blockchain Explicada](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) +- [Entendendo Contratos Inteligentes](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [Escreva seu Primeiro Contrato Inteligente](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [Aprenda a Compilar e Implantar o Solidity](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) -## Artigos para Iniciantes {#beginner-articles} +## Artigos para iniciantes {#beginner-articles} -- [Finalmente entendendo as contas Ethereum](https://dev.to/q9/finally-understanding-ethereum-accounts-1kpe) -- [Finalmente autenticando usuários Rails com MetaMask](https://dev.to/q9/finally-authenticating-rails-users-with-metamask-3fj) +- [Finalmente entendendo as contas da Ethereum](https://dev.to/q9/finally-understanding-ethereum-accounts-1kpe) +- [Finalmente autenticando usuários do Rails com a MetaMask](https://dev.to/q9/finally-authenticating-rails-users-with-metamask-3fj) - [Como se conectar à rede Ethereum usando Ruby](https://www.quicknode.com/guides/web3-sdks/how-to-connect-to-the-ethereum-network-using-ruby) - [Como gerar um novo endereço Ethereum em Ruby](https://www.quicknode.com/guides/web3-sdks/how-to-generate-a-new-ethereum-address-in-ruby) -## Artigos intermediários {#intermediate-articles} +## Artigos Intermediários {#intermediate-articles} -- [Aplicativo Blockchain com Ruby](https://www.nopio.com/blog/blockchain-app-ruby/) -- [Use o Ruby, conectado à Ethereum, para executar o Smart Contract](https://titanwolf.org/Network/Articles/Article?AID=87285822-9b25-49d5-ba2a-7ad95fff7ef9) +- [Aplicativo de cadeia de blocos com Ruby](https://www.nopio.com/blog/blockchain-app-ruby/) +- [Use o Ruby, conectado ao Ethereum, para executar o Contrato Inteligente](https://titanwolf.org/Network/Articles/Article?AID=87285822-9b25-49d5-ba2a-7ad95fff7ef9) -## Projetos e ferramentas Ruby {#ruby-projects-and-tools} +## Projetos e ferramentas para Ruby {#ruby-projects-and-tools} -### Ativos {#active} +### Ativo {#active} - [eth.rb](https://github.com/q9f/eth.rb) - _Biblioteca Ruby e cliente RPC para lidar com contas, mensagens e transações Ethereum_ -- [keccak.rb](https://github.com/q9f/keccak.rb) - _O hash Keccak (SHA3) usado pela Ethereum_ -- [siwe-ruby](https://github.com/signinwithethereum/siwe-ruby) - _Implementação Ruby de Login com Ethereum_ -- [siwe-rails](https://github.com/signinwithethereum/siwe-rails) - _Gem do Rails que adiciona rotas de login local da SIWE_ -- [siwe-rails-examples](https://github.com/signinwithethereum/siwe-rails-examples) - _Exemplo SIWE usando Ruby on Rails com controlador_ -- [omniauth-siwe](https://github.com/signinwithethereum/omniauth-siwe) - _Estratégia OmniAuth para login com Ethereum (SIWE)_ -- [omniauth-nft](https://github.com/valthon/omniauth-nft) - _Estratégia OmniAuth para autenticação via propriedade NFT_ -- [ethereum-on-rails](https://github.com/q9f/ethereum-on-rails) - _Modelo Ethereum on Rails que permite conectar MetaMask para Ruby on Rails_ - -### Arquivado/Não mais mantido {#archived--no-longer-maintained} - -- [web3-eth](https://github.com/spikewilliams/vtada-ethereum) - _Chamando métodos RPC do nó Ethereum com Ruby_ -- [ethereum_tree](https://github.com/longhoangwkm/ethereum_tree) - _Biblioteca Ruby para gerar endereços ETH de uma carteira Determinística Hierárquica de acordo com o padrão BIP32 _ -- [etherlite](https://github.com/budacom/etherlite) - _Integração Ethereum para Ruby on Rails_ -- [ethereum.rb](https://github.com/EthWorks/ethereum.rb) - _Cliente Ruby Ethereum usando a interface JSON-RPC para enviar transações, criando e interagindo com contratos, assim como um kit de ferramentas útil para trabalhar com nó Ethereum_ +- [keccak.rb](https://github.com/q9f/keccak.rb) - _O hash Keccak (SHA3) usado pelo Ethereum_ +- [siwe-ruby](https://github.com/signinwithethereum/siwe-ruby) - _Implementação em Ruby do Sign-In with Ethereum_ +- [siwe-rails](https://github.com/signinwithethereum/siwe-rails) - _Gem do Rails que adiciona rotas de login local do SIWE_ +- [siwe-rails-examples](https://github.com/signinwithethereum/siwe-rails-examples) - _Exemplo de SIWE usando Ruby on Rails com um controlador personalizado_ +- [omniauth-siwe](https://github.com/signinwithethereum/omniauth-siwe) - _Estratégia OmniAuth para Sign In With Ethereum (SIWE)_ +- [omniauth-nft](https://github.com/valthon/omniauth-nft) - _Estratégia OmniAuth para autenticação via propriedade de NFT_ +- [ethereum-on-rails](https://github.com/q9f/ethereum-on-rails) - _Modelo do Ethereum on Rails que permite conectar a MetaMask ao Ruby on Rails_ + +### Arquivado / Não é mais mantido {#archived--no-longer-maintained} + +- [web3-eth](https://github.com/spikewilliams/vtada-ethereum) - _Chamando métodos RPC de um nó Ethereum com Ruby_ +- [ethereum_tree](https://github.com/longhoangwkm/ethereum_tree) - _Biblioteca Ruby para gerar endereços ETH de uma carteira Determinística Hierárquica de acordo com o padrão BIP32_ +- [etherlite](https://github.com/budacom/etherlite) - _Integração do Ethereum para Ruby on Rails_ +- [ethereum.rb](https://github.com/EthWorks/ethereum.rb) - _Cliente Ruby Ethereum que usa a interface JSON-RPC para enviar transações, criar e interagir com contratos, bem como um kit de ferramentas útil para trabalhar com o nó Ethereum_ - [omniauth-ethereum.rb](https://github.com/q9f/omniauth-ethereum.rb) - _Implementa a estratégia de provedor Ethereum para OmniAuth_ -Procurando por mais recursos? Confira a [A casa do nosso desenvolvedor](/developers/). +Procurando por mais recursos? Confira [nossa página para Desenvolvedores](/developers/). -## Colaboradores da comunidade Ruby {#ruby-community-contributors} +## Contribuidores da comunidade Ruby {#ruby-community-contributors} -O [Ethereum Ruby Telegram group](https://t.me/ruby_eth) hospeda uma comunidade em rápido crescimento e é o recurso dedicado para discussões sobre qualquer um dos projetos acima e tópicos relacionados. +O [grupo Ethereum Ruby no Telegram](https://t.me/ruby_eth) é o lar de uma comunidade em rápido crescimento e o recurso dedicado para discussões sobre quaisquer dos projetos acima e tópicos relacionados. diff --git a/public/content/translations/pt-br/developers/docs/programming-languages/rust/index.md b/public/content/translations/pt-br/developers/docs/programming-languages/rust/index.md index 778eeb53457..fe36a3fef86 100644 --- a/public/content/translations/pt-br/developers/docs/programming-languages/rust/index.md +++ b/public/content/translations/pt-br/developers/docs/programming-languages/rust/index.md @@ -5,57 +5,61 @@ lang: pt-br incomplete: true --- -Aprenda a desenvolver para Ethereum utilizando projetos e ferramentas baseados em Rust +Aprenda a desenvolver para Ethereum usando projetos e ferramentas baseados em Rust -Utilize Ethereum para criar aplicações descentralizadas ("dapps") que utilizam os benefícios das criptomoedas e tecnologias de cadeia de blocos. Esses dapps podem ser muito confiáveis, o que significa que uma vez que eles são implantados na rede Ethereum, sempre serão executados como programados. Eles podem controlar ativos digitais a fim de criar novos tipos de aplicações financeiras. Eles podem ser descentralizados, o que significa que nenhuma entidade ou pessoa os controla sendo portanto praticamente impossíves de serem censurados. +Utilize Ethereum para criar aplicações descentralizadas ("dapps") que utilizam os benefícios das criptomoedas e tecnologias de cadeia de blocos. Esses dapps podem ser muito confiáveis, o que significa que uma vez que eles são implantados na rede Ethereum, sempre serão executados como programados. +Eles podem controlar ativos digitais a fim de criar novos tipos de aplicações financeiras. Eles podem ser descentralizados, o que significa que nenhuma entidade ou pessoa os controla sendo, portanto, praticamente impossíveis de serem censurados. -## Introdução aos contratos inteligentes e linguagem Solidity {#getting-started-with-smart-contracts-and-solidity} +## Começando com contratos inteligentes e a linguagem Solidity {#getting-started-with-smart-contracts-and-solidity} **Dê seus primeiros passos para integrar Rust com Ethereum** -Precisa de uma introdução geral? Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers](/developers/). +Precisa de uma introdução geral? +Confira [ethereum.org/learn](/learn/) ou [ethereum.org/developers](/developers/). - [Blockchain Explicada](https://kauri.io/article/d55684513211466da7f8cc03987607d5/blockchain-explained) -- [Entendendo os Smart Contracts](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) -- [Escreva seu primeiro Smart Contract](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) -- [Aprenda como Compilar e Implantar em Solidity](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) +- [Entendendo Contratos Inteligentes](https://kauri.io/article/e4f66c6079e74a4a9b532148d3158188/ethereum-101-part-5-the-smart-contract) +- [Escreva seu Primeiro Contrato Inteligente](https://kauri.io/article/124b7db1d0cf4f47b414f8b13c9d66e2/remix-ide-your-first-smart-contract) +- [Aprenda a Compilar e Implantar o Solidity](https://kauri.io/article/973c5f54c4434bb1b0160cff8c695369/understanding-smart-contract-compilation-and-deployment) -## Artigos para Iniciantes {#beginner-articles} +## Artigos para iniciantes {#beginner-articles} -- [O cliente Rust Ethereum](https://openethereum.github.io/) /***Note que o OpenEthereum [foi descontinuado](https://medium.com/openethereum/gnosis-joins-erigon-formerly-turbo-geth-to-release-next-gen-ethereum-client-c6708dd06dd) e não está mais sendo mantido.** Use-o com cuidado e de preferência mude para outra implementação do cliente. -- [Enviando uma transação para Ethereum usando Rust](https://kauri.io/#collections/A%20Hackathon%20Survival%20Guide/sending-ethereum-transactions-with-rust/) -- [Um tutorial passo a passo sobre como criar contratos em Rust Wasm para Kovan](https://github.com/paritytech/pwasm-tutorial) +- [O Cliente Ethereum Rust](https://openethereum.github.io/) \* **Observação: o OpenEthereum [foi descontinuado](https://medium.com/openethereum/gnosis-joins-erigon-formerly-turbo-geth-to-release-next-gen-ethereum-client-c6708dd06dd) e não está mais sendo mantido.** Use-o com cautela e, de preferência, mude para outra implementação de cliente. +- [Enviando Transação para o Ethereum Usando Rust](https://kauri.io/#collections/A%20Hackathon%20Survival%20Guide/sending-ethereum-transactions-with-rust/) +- [Um tutorial passo a passo sobre como escrever contratos em Rust Wasm para a Kovan](https://github.com/paritytech/pwasm-tutorial) -## Artigos para intermediários {#intermediate-articles} +## Artigos Intermediários {#intermediate-articles} -## Padrões de utilização avançada {#advanced-use-patterns} +## Padrões de uso avançados {#advanced-use-patterns} -- [pwasm_ethereum: biblioteca externa para interagir com uma rede análoga a Ethereum](https://github.com/openethereum/pwasm-ethereum) -- [Construa um bate-papo descentralizado utilizando JavaScript e Rust](https://medium.com/perlin-network/build-a-decentralized-chat-using-javascript-rust-webassembly-c775f8484b52) -- [Construa um aplicativo descentralizado de tarefas utilizando Vue.js & Rust](https://medium.com/@jjmace01/build-a-decentralized-todo-app-using-vue-js-rust-webassembly-5381a1895beb) +- [biblioteca de externos pwasm_ethereum para interagir com redes do tipo Ethereum](https://github.com/openethereum/pwasm-ethereum) -- [Construir uma blockchain no Rust](https://blog.logrocket.com/how-to-build-a-blockchain-in-rust/) +- [Crie um bate-papo descentralizado usando JavaScript e Rust](https://medium.com/perlin-network/build-a-decentralized-chat-using-javascript-rust-webassembly-c775f8484b52) -## Projetos e ferramentas em Rust {#rust-projects-and-tools} +- [Crie um aplicativo de tarefas descentralizado usando Vue.js & Rust](https://medium.com/@jjmace01/build-a-decentralized-todo-app-using-vue-js-rust-webassembly-5381a1895beb) -- [pwasm-ethereum](https://github.com/paritytech/pwasm-ethereum) — _Coleção de externos para interagir com uma rede análoga ao Ethereum._ -- [Lighthouse](https://github.com/sigp/lighthouse) — _Cliente rápido da camada de consenso do Ethereum_ -- [Ethereum WebAssembly](https://ewasm.readthedocs.io/en/mkdocs/) — _Proposta de reformulação da camada de execução de contrato inteligente do Ethereum usando um subconjunto determinístico do WebAssembly_ -- [oasis_std](https://docs.rs/oasis-std/latest/oasis_std/index.html) - _referência da API OASIS_ -- [Solaris](https://github.com/paritytech/sol-rs) — _Agente de teste unitário dos contratos inteligentes no Solidity usando o EVM nativo do cliente Parity._ -- [SputnikVM](https://github.com/rust-blockchain/evm) — _Implementação da Máquina Virtual do Ethereum no Rust_ -- [Wavelet](https://wavelet.perlin.net/docs/smart-contracts) - _smart contract Wavelet em Rust_ -- [Foundry](https://github.com/foundey-rs/foundry) — _Conjunto de ferramentas para o desenvolvimento de aplicativos Ethereum_ -- [Alloy](https://alloy.rs) - _Bibliotecas de alto desempenho, bem testadas e documentadas para interagir com Ethereum e outras cadeias baseadas em EVM._ +- [Construa uma cadeia de blocos em Rust](https://blog.logrocket.com/how-to-build-a-blockchain-in-rust/) + +## Projetos e ferramentas Rust {#rust-projects-and-tools} + +- [pwasm-ethereum](https://github.com/paritytech/pwasm-ethereum) - _Coleção de externos para interagir com rede do tipo Ethereum_ +- [Lighthouse](https://github.com/sigp/lighthouse) - _Cliente rápido da camada de consenso do Ethereum_ +- [Ethereum WebAssembly](https://ewasm.readthedocs.io/en/mkdocs/) - _Proposta de reformulação da camada de execução de contrato inteligente do Ethereum usando um subconjunto determinístico de WebAssembly_ +- [oasis_std](https://docs.rs/oasis-std/latest/oasis_std/index.html) - _Referência da API do OASIS_ +- [Solaris](https://github.com/paritytech/sol-rs) - _Ferramenta de teste de unidade de contratos inteligentes Solidity usando o EVM nativo do cliente Parity._ +- [SputnikVM](https://github.com/rust-blockchain/evm) - _Implementação da Máquina Virtual Ethereum em Rust_ +- [Wavelet](https://wavelet.perlin.net/docs/smart-contracts) - _Contrato inteligente Wavelet em Rust_ +- [Foundry](https://github.com/foundry-rs/foundry) - _Kit de ferramentas para desenvolvimento de aplicativos Ethereum_ +- [Alloy](https://alloy.rs) - _Bibliotecas de alto desempenho, bem testadas e documentadas para interagir com o Ethereum e outras cadeias baseadas em EVM._ - [Ethers_rs](https://github.com/gakonst/ethers-rs) - _Biblioteca Ethereum e implementação de carteira_ -- [SewUp](https://github.com/second-state/SewUp) — _Uma biblioteca para ajudar você a construir seu contrato Webassembly do Ethereum com o Rust e desenvolvê-lo em um back-end comum_ -- [Substreams](https://github.com/streamingfast/substreams) - _Tecnologia de indexação de dados paralelizada em blockchain_ -- [Reth](https://github.com/paradigmxyz/reth) - Reth (abreviação de Rust Ethereum) é uma nova implementação de nó completo do Ethereum +- [SewUp](https://github.com/second-state/SewUp) - _Uma biblioteca para ajudar você a construir seu contrato webassembly do Ethereum com Rust, assim como desenvolver em um backend comum_ +- [Substreams](https://github.com/streamingfast/substreams) - _Tecnologia de indexação de dados de cadeia de blocos paralelizada_ +- [Reth](https://github.com/paradigmxyz/reth) Reth (abreviação de Rust Ethereum) é uma nova implementação de nó completo do Ethereum - [Awesome Ethereum Rust](https://github.com/Vid201/awesome-ethereum-rust) - _Uma coleção selecionada de projetos no ecossistema Ethereum escritos em Rust_ -Procurando por mais recursos? Leia [ethereum.org/developers.](/developers/) +Procurando por mais recursos? Confira [ethereum.org/developers.](/developers/) -## Colaboradores da comunidade Rust {#rust-community-contributors} +## Contribuidores da comunidade Rust {#rust-community-contributors} - [Ethereum WebAssembly](https://gitter.im/ewasm/Lobby) - [Oasis Gitter](https://gitter.im/Oasis-official/Lobby) diff --git a/public/content/translations/pt-br/developers/docs/scaling/index.md b/public/content/translations/pt-br/developers/docs/scaling/index.md index 827cb3d1d66..0ca69ae8865 100644 --- a/public/content/translations/pt-br/developers/docs/scaling/index.md +++ b/public/content/translations/pt-br/developers/docs/scaling/index.md @@ -1,52 +1,52 @@ --- -title: Dimensionamento -description: Uma introdução às diferentes opções de dimensionamento atualmente em desenvolvimento pela comunidade Ethereum. +title: Escalabilidade +description: "Uma introdução às diferentes opções de dimensionamento atualmente em desenvolvimento pela comunidade Ethereum." lang: pt-br sidebarDepth: 3 --- -## Visão geral do dimensionamento {#scaling-overview} +## Visão geral da escalabilidade {#scaling-overview} À medida que o número de usuários do Ethereum aumenta, a blockchain atinge certas limitações de capacidade. Isso tem elevado os custos de utilização da rede, criando a necessidade de "soluções de dimensionamento". Existem várias soluções sendo pesquisadas, testadas e implementadas que adotam diferentes abordagens para atingir metas semelhantes. -O principal objetivo da escalabilidade é aumentar a velocidade das transações (finalidade mais rápida) e a capacidade de transações (maior número de transações por segundo) sem sacrificar a descentralização ou a segurança. Na camada 1 da blockchain de Ethereum, a alta demanda leva a transações mais lentas e a [preços de gás](/developers/docs/gas/) inviáveis. Aumentar a capacidade da rede em termos de velocidade e taxa de transferência é fundamental para uma adoção significativa e massiva do Ethereum. +O principal objetivo da escalabilidade é aumentar a velocidade de transação (finalidade mais rápida) e a taxa de transferência de transações (maior número de transações por segundo), sem sacrificar a descentralização ou a segurança. Na blockchain de camada 1 da Ethereum, a alta demanda leva a transações mais lentas e [preços de gás](/developers/docs/gas/) inviáveis. Aumentar a capacidade da rede em termos de velocidade e taxa de transferência é fundamental para uma adoção significativa e massiva do Ethereum. Embora a velocidade e a taxa de transferência sejam importantes, é essencial que tais soluções de dimensionamento habilitadas para tais fins permaneçam descentralizadas e seguras. Manter a barreira de entrada baixa para os operadores de nó é fundamental para prevenir uma progressão rumo a um poder de computação centralizado e inseguro. -Conceitualmente, primeiro classificamos o dimensionamento como dimensionamento on-chain ou dimensionamento off-chain. +Conceptually we first categorize scaling as either onchain scaling or offchain scaling. ## Pré-requisitos {#prerequisites} Você deveria ter um bom entendimento de todos os tópicos fundamentais. Implementar soluções de dimensionamento é um conceito avançado, já que a tecnologia é menos testada e continua a ser pesquisada e desenvolvida. -## Dimensionamento on-chain {#on-chain-scaling} +## Escalabilidade na cadeia {#onchain-scaling} -A escalabilidade em cadeia requer mudanças no protocolo do Ethereum ([Mainnet](/glossary/#mainnet) de camada 1). A solução de fragmentação da blockchain era aguardada há muito tempo para escalar o Ethereum. Isso implicava dividir a blockchain em partes discretas (fragmentos), que seriam verificadas por subconjuntos de validadores. No entanto, a técnica de escalabilidade principal adotada foi a de escalar por rollups de camada 2. Ela é suportada pela adição de uma nova forma mais barata de dados anexados aos blocos Ethereum, que foi especialmente criada para tornar os rollups baratos para os usuários. +A escalabilidade na cadeia exige alterações no protocolo Ethereum (camada 1 da [Mainnet](/glossary/#mainnet)). A solução de fragmentação da blockchain era aguardada há muito tempo para escalar o Ethereum. Isso implicava dividir a blockchain em partes discretas (fragmentos), que seriam verificadas por subconjuntos de validadores. No entanto, a técnica de escalabilidade principal adotada foi a de escalar por rollups de camada 2. Ela é suportada pela adição de uma nova forma mais barata de dados anexados aos blocos Ethereum, que foi especialmente criada para tornar os rollups baratos para os usuários. -### Fragmentação {#sharding} +### Sharding {#sharding} -Fragmentação é o processo de dividir um banco de dados. Subconjuntos de validadores seriam responsáveis por seus próprios fragmentos, em vez de manter o controle de todo o Ethereum. A fragmentação esteve no [planejamento](/roadmap/) do Ethereum por muito tempo, com a intenção de ser enviada para prova de participação antes do The Merge (A Fusão). No entanto, o rápido desenvolvimento de [rollups de camada 2](#layer-2-scaling) e a invenção do [Danksharding](/roadmap/danksharding) (adicionando blobs de dados do rollup para blocos do Ethereum que podem ser verificados eficientemente pelos validadores) têm levado a comunidade Ethereum a preferir o dimensionamento centrado por rollup em vez do dimensionamento por fragmentação. Isso também ajudará a manter a lógica de consenso do Ethereum mais simples. +Fragmentação é o processo de dividir um banco de dados. Subconjuntos de validadores seriam responsáveis por seus próprios fragmentos, em vez de manter o controle de todo o Ethereum. O sharding esteve no [roadmap](/roadmap/) da Ethereum por um longo tempo e foi planejado para ser lançado antes do The Merge para prova de participação. No entanto, o rápido desenvolvimento de [rollups de camada 2](#layer-2-scaling) e a invenção do [Danksharding](/roadmap/danksharding) (adicionando blobs de dados de rollup a blocos da Ethereum que podem ser verificados de forma muito eficiente por validadores) levou a comunidade Ethereum a favorecer a escalabilidade centrada em rollups em vez da escalabilidade por sharding. Isso também ajudará a manter a lógica de consenso do Ethereum mais simples. -## Dimensionamento off-chain {#off-chain-scaling} +## Escalabilidade fora da cadeia {#offchain-scaling} -As soluções off-chain são implementadas separadamente da rede principal da camada 1. Ou seja, elas não requerem alterações no protocolo Ethereum existente. Algumas soluções, conhecidas como soluções de “camada 2”, obtêm sua segurança diretamente do consenso da camada 1 do Ethereum, por exemplo, os [rollups otimistas](/developers/docs/scaling/layer-2-rollups/), os [rollups de conhecimento zero](/developers/docs/scaling/zk-rollups/) ou os [canais de estado](/developers/docs/scaling/state-channels/). Outras soluções envolvem a criação de novas cadeias em várias formas, que obtêm sua segurança separadamente da Mainnet (Rede principal), como [cadeias laterais](#sidechains), [validiums](#validium) ou [cadeias Plasma](#plasma). Essas soluções se comunicam com a Mainnet (Rede principal), mas obtêm sua segurança de forma diferente para alcançar uma variedade de objetivos. +Os offchain solutions são separados do layer 1 Mainnet. Algumas soluções, conhecidas como soluções de "camada 2", derivam sua segurança diretamente do consenso da camada 1 do Ethereum, como os [optimistic rollups](/developers/docs/scaling/optimistic-rollups/), [rollups de conhecimento zero](/developers/docs/scaling/zk-rollups/) ou [canais de estado](/developers/docs/scaling/state-channels/). Outras soluções envolvem a criação de novas cadeias em várias formas que derivam sua segurança separadamente da Mainnet, como [sidechains](#sidechains), [validiums](#validium) ou [plasma chains](#plasma). Essas soluções se comunicam com a Mainnet, mas derivam sua segurança de forma diferente para atingir uma variedade de objetivos. -### Dimensionamento da camada 2 {#layer-2-scaling} +### Escalabilidade da Camada 2 {#layer-2-scaling} -Esta categoria de soluções off-chain obtém sua segurança da Mainnet (Rede principal) do Ethereum. +Esta categoria de offchain solutions obtém segurança da Rede principal do Ethereum. A camada 2 é um termo coletivo de soluções projetadas para ajudar a dimensionar os aplicativos, gerenciando transações fora da rede principal (camada 1) do Ethereum, aproveitando o robusto modelo de segurança descentralizada da Mainnet (Rede principal). A velocidade das transações é reduzida quando a rede está ocupada, o que pode tornar a experiência do usuário ruim para certos tipos de dapps. À medida que a rede fica mais movimentada, os preços do gás aumentam, pois os remetentes de transações tendem a oferecer mais para processar sua transação antes das dos outros. Isso pode tornar o uso do Ethereum bem mais caro. -A maioria das soluções de camada 2 são centralizadas em torno de um servidor ou cluster de servidores, cada um dos quais pode ser referenciado como um nó, validador, operador, sequenciador, produtor de bloco, ou um termo semelhante. Dependendo da implementação, esses nós da camada 2 podem ser executados pelos indivíduos, empresas ou entidades que os usam, por um operador de terceiros ou por um grande grupo de indivíduos (semelhante à Mainnet). Em geral, as transações são submetidas a esses nós de camada 2, em vez de serem enviadas diretamente para a camada 1 (Mainnet). Para algumas soluções, a instância da camada 2 agrupa-os em grupos antes de ancorá-los na camada 1, na qual ficam protegidos e não podem ser alterados. Os pormenores de como isso é feito variam significativamente entre diferentes tecnologias de camada 2 e implementações. +A maioria das soluções de camada 2 orbitam ao redor de um servidor, ou cluster de servidores, cada um dos quais pode ser referenciado como um nó, como um validador, como um operador, como um sequenciador de transações, como um produtor de blocos ou como algo semelhante. Dependendo da implementação, esses nós da camada 2 podem ser executados pelos indivíduos, empresas ou entidades que os usam, por um operador de terceiros ou por um grande grupo de indivíduos (semelhante à Mainnet). Em geral, ao invés de serem enviadas diretamente para a camada 1 (rede principal), as transações são submetidas a esses nós da camada 2. Para algumas soluções, o camada 2 agrupa-os antes de os transmitir ao camada 1, no qual ficam protegidos e não podem ser alterados. Os pormenores de como isso é feito variam significativamente entre diferentes tecnologias de camada 2 e implementações. Uma instância específica da camada 2 pode ser aberta e compartilhada por muitos aplicativos, ou pode ser implantada por um projeto e dedicada a dar suporte apenas ao seu aplicativo. #### Por que a camada 2 é necessária? {#why-is-layer-2-needed} - O aumento da quantidade de transações por segundo melhora significativamente a experiência de usuário e reduzem o congestionamento da rede na rede principal do Ethereum. -- As transações são agrupadas em única transação na rede principal do Ethereum, reduzindo assim as taxas de gás, tornando o Ethereum mais inclusivo e acessível para os usuários sem importar o lugar. +- As transações são agrupadas em uma única transação para a Mainnet da Ethereum, reduzindo as taxas de gás para os usuários e tornando a Ethereum mais inclusiva e acessível para pessoas em todos os lugares. - Quaisquer atualizações de dimensionamento não devem ser feitas às custas da descentralização ou da segurança – a camada 2 se baseia na rede principal do Ethereum. -- Existem redes de camada 2 específicas de aplicativos que trazem seu próprio conjunto de melhorias ao trabalhar com ativos em escala. +- Existem redes de camada 2 específicas para aplicativos que trazem seu próprio conjunto de eficiências ao trabalhar com ativos em escala. [Mais sobre a camada 2](/layer-2/). @@ -56,26 +56,26 @@ Os rollups executam a transação fora da camada 1 e, em seguida, os dados são Existem dois tipos de rollups com diferentes modelos de segurança: -- **Optimistic rollups**: assumem que as transações são válidas por padrão e só executam computação através de uma [**prova de fraude**](/glossary/#fraud-proof), caso alguém levante alguma objeção. [Mais sobre optimistic-rollups](/developers/docs/scaling/optimistic-rollups/). -- **Rollups de conhecimento zero**: executam a computação off-chain e enviam uma [**prova de validade**](/glossary/#validity-proof) para a cadeia. [Mais sobre rollups de conhecimento zero](/developers/docs/scaling/zk-rollups/). +- **Optimistic rollups**: presumem que as transações são válidas por padrão e só executam a computação, por meio de uma [**prova de fraude**](/glossary/#fraud-proof), no caso de uma contestação. [Mais sobre Optimistic rollups](/developers/docs/scaling/optimistic-rollups/). +- **Rollups de conhecimento zero**: executam a computação fora da cadeia e enviam uma [**prova de validade**](/glossary/#validity-proof) para a cadeia. [Mais sobre rollups de conhecimento zero](/developers/docs/scaling/zk-rollups/). -#### Canais de Estado {#channels} +#### State channels {#channels} -Os canais de estado utilizam contratos multisig para permitir que os participantes realizem transações de forma rápida e livre off-chain para, em seguida, liquidar a finalidade com a Mainnet. Isso minimiza o congestionamento, as taxas e os atrasos na rede. Atualmente, existem dois tipos de canais: canais de estado e canais de pagamento. +Os canais de estado utilizam multisig contracts para permitir que os participantes realizarem transações de forma rápida e livre off-chain por final settlement à rede principal. Isso minimiza o congestionamento, as taxas e os atrasos na rede. Atualmente, existem dois tipos de canais: canais de estado e canais de pagamento. -Aprenda mais sobre [canais de estado](/developers/docs/scaling/state-channels/). +Saiba mais sobre [canais de estado](/developers/docs/scaling/state-channels/). -### Correntes paralelas {#sidechains} +### Sidechains {#sidechains} -Uma sidechain (cadeia paralela) é uma blockchain independente e compatível com EVM que roda em paralelo à Mainnet (Rede principal). As sidechains são compatíveis com o Ethereum através de pontes bidirecionais e são executadas conforme as regras de consenso escolhidas e os parâmetros do bloco. +Uma sidechain é uma blockchain independente, compatível com a EVM, que funciona em paralelo à Mainnet. Elas são compatíveis com a Ethereum por meio de pontes bidirecionais e funcionam sob suas próprias regras de consenso e parâmetros de bloco. Saiba mais sobre [Sidechains](/developers/docs/scaling/sidechains/). ### Plasma {#plasma} -A cadeia plasma é uma blockchain separada que é ancorada à cadeia principal do Ethereum e usa provas de fraude (como os [rollups otimistas](/developers/docs/scaling/optimistic-rollups/)) para arbitrar litígios. +Uma plasma chain é uma blockchain separada que é ancorada à cadeia principal da Ethereum e usa provas de fraude (como os [optimistic rollups](/developers/docs/scaling/optimistic-rollups/)) para arbitrar disputas. -Aprenda mais sobre o [Plasma](/developers/docs/scaling/plasma/). +Saiba mais sobre o [Plasma](/developers/docs/scaling/plasma/). ### Validium {#validium} @@ -85,7 +85,7 @@ Saiba mais sobre o [Validium](/developers/docs/scaling/validium/). ## Por que tantas soluções de dimensionamento são necessárias? {#why-do-we-need-these} -- O fato de ter múltiplas soluções pode ajudar a reduzir o congestionamento geral de qualquer parte da rede e também a impedir pontos únicos de falha. +- Várias soluções podem ajudar a reduzir o congestionamento geral em qualquer parte da rede e também evitar pontos únicos de falha. - O todo é maior que a soma de suas partes. Diferentes soluções podem existir e ainda funcionar em harmonia, provocando um efeito exponencial na velocidade futura das transações e na quantidade de dados transferidos. - Nem todas as soluções exigem diretamente o uso do algoritmo de consenso do Ethereum, e algumas alternativas podem oferecer benefícios que, de outro modo, seriam difíceis de obter. @@ -93,20 +93,21 @@ Saiba mais sobre o [Validium](/developers/docs/scaling/validium/). -_Observe que a explicação no vídeo usa o termo “Camada 2" para se referir a todas as soluções de escalabilidade off-chain, enquanto nós diferenciamos a “Camada 2" como uma solução off-chain que deriva sua segurança a partir do consenso da Mainnet (Rede principal) de camada 1._ +_Vídeo usa o termo “Camada 2" para se referir a todas as soluções de escalabilidade off-chain, enquanto nós diferenciamos o “Camada 2" como solução offchain que obtém segurança do consenso da layer 1 Mainnet._ ## Leitura adicional {#further-reading} -- [Um cronograma do Ethereum centrado em rollups](https://ethereum-magicians.org/t/a-rollup-centric-ethereum-roadmap/4698) _Vitalik Buterin_ -- [Análises atualizadas sobre o dimensionamento da camada 2 para Ethereum](https://www.l2beat.com/) -- [Avaliando as soluções de dimensionamento da camada 2 de Ethereum: um esquema de comparação](https://medium.com/matter-labs/evaluating-ethereum-l2-scaling-solutions-a-comparison-framework-b6b2f410f955) +- [Um roteiro da Ethereum centrado em rollups](https://ethereum-magicians.org/t/a-rollup-centric-ethereum-roadmap/4698) _Vitalik Buterin_ +- [Análises atualizadas sobre soluções de escalabilidade de camada 2 para a Ethereum](https://www.l2beat.com/) +- [Avaliando as soluções de escalabilidade de camada 2 da Ethereum: uma estrutura de comparação](https://medium.com/matter-labs/evaluating-ethereum-l2-scaling-solutions-a-comparison-framework-b6b2f410f955) - [Um guia incompleto sobre rollups](https://vitalik.eth.limo/general/2021/01/05/rollup.html) -- [Ethereum com tecnologia de ZK-Rollups: campeões do mundo](https://hackmd.io/@canti/rkUT0BD8K) -- [Optimistic Rollups vs ZK Rollups](https://limechain.tech/blog/optimistic-rollups-vs-zk-rollups/) -- [Por que os rollups, junto com as fragmentações dos dados, são a única solução sustentável para atingir alto dimensionamento](https://polynya.medium.com/why-rollups-data-shards-are-the-only-sustainable-solution-for-high-scalability-c9aabd6fbb48) +- [ZK-Rollups com tecnologia da Ethereum: os melhores do mundo](https://hackmd.io/@canti/rkUT0BD8K) +- [Optimistic Rollups vs. ZK Rollups](https://limechain.tech/blog/optimistic-rollups-vs-zk-rollups/) +- [Por que rollups + data shards são a única solução sustentável para alta escalabilidade](https://polynya.medium.com/why-rollups-data-shards-are-the-only-sustainable-solution-for-high-scalability-c9aabd6fbb48) - [Que tipo de camada 3 faz sentido?](https://vitalik.eth.limo/general/2022/09/17/layer_3.html) -- [Disponibilidade de dados ou: como os rollups aprenderam a parar de se preocupar e amar o Ethereum](https://ethereum2077.substack.com/p/data-availability-in-ethereum-rollups) +- [Disponibilidade de Dados ou: Como os Rollups Aprenderam a Parar de Se Preocupar e Amar o Ethereum](https://web.archive.org/web/20250515194659/https://web.archive.org/web/20241108192208/https://research.2077.xyz/data-availability-or-how-rollups-learned-to-stop-worrying-and-love-ethereum) +- [O Guia Prático para Rollups da Ethereum](https://web.archive.org/web/20241108192208/https://research.2077.xyz/the-practical-guide-to-ethereum-rollups) -_Conhece um recurso da comunidade que te ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ diff --git a/public/content/translations/pt-br/developers/docs/scaling/optimistic-rollups/index.md b/public/content/translations/pt-br/developers/docs/scaling/optimistic-rollups/index.md index a514f55028d..2492160aba9 100644 --- a/public/content/translations/pt-br/developers/docs/scaling/optimistic-rollups/index.md +++ b/public/content/translations/pt-br/developers/docs/scaling/optimistic-rollups/index.md @@ -1,52 +1,52 @@ --- title: Optimistic Rollups -description: Uma introdução aos optimistic rollups, uma solução de dimensionamento usada pela comunidade Ethereum. +description: "Uma introdução aos optimistic rollups, uma solução de dimensionamento usada pela comunidade Ethereum." lang: pt-br --- -Os optimistic rollups são protocolos de camada 2 (L2) projetados para aumentar a taxa de transferência da camada base do Ethereum. Eles reduzem a computação na cadeia principal do Ethereum ao processar transações off-chain, oferecendo uma melhora significativa na velocidade de processamento. Diferentemente de outras soluções de dimensionamento, como [sidechains](/developers/docs/scaling/sidechains/), os optimistic rollups têm a sua segurança derivada da rede principal, pois publicam os resultados de suas transações on-chain. Os optimistic rollups também se diferem de [plasma chains](/developers/docs/scaling/plasma/). Estes também verificam transações no Ethereum com provas de fraude, mas fazem o armazenamento de dados em outro lugar. +Os optimistic rollups são protocolos de camada 2 (L2) projetados para aumentar a taxa de transferência da camada base do Ethereum. Eles reduzem a computação na cadeia principal do Ethereum processando transações offchain, oferecendo melhorias significativas nas velocidades de processamento. Diferentemente de outras soluções de escalabilidade, como [sidechains](/developers/docs/scaling/sidechains/), os optimistic rollups obtêm segurança da Rede Principal publicando resultados de transações na cadeia, ou [plasma chains](/developers/docs/scaling/plasma/), que também verificam transações no Ethereum com provas de fraude, mas armazenam os dados da transação em outro lugar. Como a computação é a parte lenta e cara de usar o Ethereum, os optimistic rollups podem oferecer uma melhora de dimensionamento de 10 a 100 vezes superior. Os optimistic rollups também gravam transações no Ethereum como `calldata` ou em [blobs](/roadmap/danksharding/), reduzindo os custos de gás para os usuários. -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -Você deve ter lido e compreendido nossas páginas sobre [dimensionamento do Ethereum](/developers/docs/scaling/) e [camada 2](/layer-2/). +Você deve ter lido e entendido nossas páginas aos [Ethereum scaling](/developers/docs/scaling/) e [layer 2](/layer-2/). ## O que é um optimistic rollup? {#what-is-an-optimistic-rollup} -Um optimistic rollup é uma maneira de dimensionara o Ethereum que evolve mover a computação e o armazenamento do estado off-chain. Optimistic rollups executam transações fora do Ethereum, mas publicam dados de transações na rede principal, como `calldata` ou em [blobs](/roadmap/danksharding/). +Um optimistic rollup é uma abordagem para dimensionar o Ethereum que envolve mover a computação e o armazenamento de estado para offchain. Os optimistic rollups executam transações fora do Ethereum, mas publicam dados de transação na Rede Principal como `calldata` ou em [blobs](/roadmap/danksharding/). -Os operadores de optimistic rollups agrupam várias transações off-chain em grandes lotes antes de as enviarem ao Ethereum. Esta abordagem permite dividir os custos entre várias transações em cada lote, reduzindo as taxas para os usuários finais. Os optimistic rollups também usam técnicas de compactação para reduzir a quantidade de dados publicados no Ethereum. +Operadores de optimistic rollup agrupam diversas transações offchain em grandes lotes antes de enviá-las ao Ethereum. Esta abordagem permite dividir os custos entre várias transações em cada lote, reduzindo as taxas para os usuários finais. Os optimistic rollups também usam técnicas de compactação para reduzir a quantidade de dados publicados no Ethereum. -Estes rollups são considerados "otimistas", pois assumem que as transações feitas off-chain são válidas e não publicam provas de validade para os lotes de transações publicados on-chain. Isso separa os optimistic rollups dos [zero-knowledge rollups](/developers/docs/scaling/zk-rollups) que publicam provas criptográficas [de validade](/glossary/#validity-proof) para transações realizadas off-chain. +Os optimistic rollup são considerados "otimistas" porque assumem que as transações offchain são válidas e não publicam provas de validade para lotes de transações postados onchain. Isso separa os optimistic rollups dos [rollups de conhecimento zero](/developers/docs/scaling/zk-rollups) que publicam [provas de validade](/glossary/#validity-proof) criptográficas para transações fora da cadeia. -Em vez disso, os optimistic rollups dependem de um esquema de comprovação de fraude para detectar casos em que as transações não são calculadas corretamente. Depois que um lote é enviado ao Ethereum, existe uma janela de tempo (chamada de período de disputa) em que qualquer pessoa pode questionar os resultados de uma transação de rollup computando uma [comprovação de fraude](/glossary/#fraud-proof). +Em vez disso, os optimistic rollups dependem de um esquema de comprovação de fraude para detectar casos em que as transações não são calculadas corretamente. Depois que um lote de rollup é enviado no Ethereum, há uma janela de tempo (chamada de período de desafio) durante a qual qualquer pessoa pode desafiar os resultados de uma transação de rollup, computando uma [prova de fraude](/glossary/#fraud-proof). Se a comprovação de fraude for bem-sucedida, o protocolo do rollup executa novamente as transações e atualiza o estado do rollup de forma adequada. O outro efeito de uma comprovação de fraude bem-sucedida é que o sequenciador responsável por incluir em um bloco a transação incorreta é penalizado. Se o lote de rollup permanecer sem desafio (ou seja, se todas as transações foram executadas corretamente) após o período de disputa expirar, ele será considerado válido e aceito no Ethereum. Outros podem continuar a construir sobre um bloco não confirmado do rollup, mas com uma ressalva: as transações serão revertidas se baseadas em uma transação executada incorretamente publicada anteriormente. -## Como os optimistic rollups interagem com o Ethereum? {#optimistic-rollups-and-Ethereum} +## Como os optimistic rollups interagem com o Ethereum? Optimistic rollups e o Ethereum {#optimistic-rollups-and-Ethereum} -Os optimistic rollups são [soluções de dimensionamento off-chain](/developers/docs/scaling/#off-chain-scaling) criadas para operar sobre o Ethereum. Cada optimistic rollup é gerenciado por um conjunto de contratos inteligentes implementados na rede Ethereum. Os optimistic rollups processam transações fora da rede principal do Ethereum, mas publicam transações off-chain (em lotes) em um contrato de rollup on-chain. Como na blockchain do Ethereum, esse registro de transações é imutável e compõe a cadeia do optimistic rollup. +Os optimistic rollups são [soluções de escalabilidade fora da cadeia](/developers/docs/scaling/#offchain-scaling) desenvolvidas para operar sobre o Ethereum. Cada optimistic rollup é gerenciado por um conjunto de contratos inteligentes implementados na rede Ethereum. Os Optimistic rollups processam transações fora da cadeia principal do Ethereum, mas lançam transações offchain (em lotes) em um contrato de rollup onchain. Como na blockchain do Ethereum, esse registro de transações é imutável e compõe a cadeia do optimistic rollup. A arquitetura de um optimistic rollup compreende as seguintes partes: -**Contratos on-chain**: a operação do optimistic rollup é controlada por contratos inteligentes em execução no Ethereum. Isso inclui contratos que armazenam blocos de rollup, monitoram atualizações de estado e rastreiam depósitos de usuário. Neste sentido o Ethereum serve como camada de base ou "camada 1" para os optimistic rollups. +**Contratos na cadeia**: a operação do optimistic rollup é controlada por contratos inteligentes em execução no Ethereum. Isso inclui contratos que armazenam blocos de rollup, monitoram atualizações de estado e rastreiam depósitos de usuário. Neste sentido o Ethereum serve como camada de base ou "camada 1" para os optimistic rollups. -**Máquina virtual (VM) off-chain**: embora os contratos gerenciando o protocolo de optimistic rollup executem no Ethereum, o protocolo de rollup executa a computação e o armazenamento de estado em outra máquina virtual separada da [Máquina Virtual do Ethereum (EVM, pela sigla em inglês)](/developers/docs/evm/). A VM off-chain é onde os aplicativos se encontram e as mudanças de estado são executadas; ela serve como a segunda camada ou "camada 2" para um optimistic rollup. +**Máquina virtual fora da cadeia (VM)**: embora os contratos que gerenciam o protocolo de optimistic rollup sejam executados no Ethereum, o protocolo de rollup realiza a computação e o armazenamento de estado em outra máquina virtual, separada da [Máquina Virtual Ethereum](/developers/docs/evm/). A VM offchain é onde os aplicativos ficam e as mudanças de estado são executadas; ela serve como a camada superior ou "layer 2" para um optimistic rollup. -Como os optimistic rollups são projetados para executar programas escritos ou compilados para a EVM, a máquina virtual off-chain acaba incorporando muitas especificações de design da EVM. Além disso, as comprovações de fraude computadas on-chain permitem que o Ethereum imponha a validade das mudanças de estado computadas na máquina virtual off-chain. +Assim como os optimistic rollups são projetados para executar programas escritos ou compilados para a EVM, a VM offchain incorpora muitas especificações de design da EVM. Além disso, as provas de fraude computadas na cadeia permitem que a rede Ethereum imponha a validade das alterações de estado computadas na VM fora da cadeia. -Os optimistic rollups são descritos como "soluções de dimesionamento híbrido", pois ao mesmo tempo que existem como protocolos separados, as propriedades de segurança deles são derivadas do Ethereum. Entre outras coisas, o Ethereum garante a exatidão da computação off-chain de um rollup e a disponibilidade de dados por trás desta. Isso torna os optimistic rollups mais seguros do que os protocolos de dimensionamento off-chain puros (por exemplo, [sidechains](/developers/docs/scaling/sidechains/)) que não dependem do Ethereum para sua segurança. +Os optimistic rollups são descritos como "soluções de dimesionamento híbrido", pois ao mesmo tempo que existem como protocolos separados, as propriedades de segurança deles são derivadas do Ethereum. Entre outras coisas, o Ethereum garante a correção do cálculo offchain de um rollup e a disponibilidade de dados por trás do cálculo. Isso torna os optimistic rollups mais seguros do que os protocolos de escalabilidade puramente fora da cadeia (p. ex., [sidechains](/developers/docs/scaling/sidechains/)) que não dependem do Ethereum para segurança. Os optimistic rollups dependem da rede principal do Ethereum para o seguinte: ### Disponibilidade de dados {#data-availability} -Conforme mencionado, os optimistic rollups publicam dados de transações no Ethereum como `calldata` ou [blobs](/roadmap/danksharding/). Como a execução na cadeia do rollup é baseada em transações enviadas, qualquer pessoa pode usar essa informação – ancorada na camada base do Ethereum – para executar o estado do rollup e verificar a exatidão das transições de estado. +Conforme mencionado, os optimistic rollups publicam dados de transação no Ethereum como `calldata` ou em [blobs](/roadmap/danksharding/). Como a execução na cadeia do rollup é baseada em transações enviadas, qualquer pessoa pode usar essa informação – ancorada na camada base do Ethereum – para executar o estado do rollup e verificar a exatidão das transições de estado. -A [disponibilidade de dados](/developers/docs/data-availability/) é fundamental porque, sem acesso a dados do estado, os desafiantes não podem criar provas de fraude para disputar operações de rollup inválidas. Com o Ethereum fornecendo disponibilidade de dados, o risco de os operadores de um rollup escaparem impunes de atos maliciosos (por exemplo, enviar blocos inválidos) é reduzido. +A [disponibilidade de dados](/developers/docs/data-availability/) é crítica, pois sem acesso aos dados de estado, os desafiantes não podem construir provas de fraude para contestar operações de rollup inválidas. Com o Ethereum fornecendo disponibilidade de dados, o risco de os operadores de um rollup escaparem impunes de atos maliciosos (por exemplo, enviar blocos inválidos) é reduzido. ### Resistência à censura {#censorship-resistance} @@ -56,7 +56,7 @@ Os optimistic rollups também contam com o Ethereum para resistência à censura - Os operadores de rollup podem impedir que os usuários retirem fundos depositados no contrato de rollup, através da retenção dos dados de estado necessários para provas de propriedade da Merkle. A retenção de dados de estado também pode ocultar o estado do rollup dos usuários e impedi-los de interagir com o rollup. -Os optimistic rollup resolvem esse problema forçando os operadores a publicar dados associados a atualizações de estado no Ethereum. A publicação de dados rollup on-chain (na cadeia) tem os seguintes benefícios: +Os optimistic rollup resolvem esse problema forçando os operadores a publicar dados associados a atualizações de estado no Ethereum. A publicação de dados de rollup onchain tem os seguintes benefícios: - Se um operador de optimistic rollup ficar offline ou parar de produzir lotes de transações, outro nó poderá usar os dados disponíveis para reproduzir o último estado do rollup e continuar a produção de blocos. @@ -68,45 +68,45 @@ Os optimistic rollup resolvem esse problema forçando os operadores a publicar d Outro papel que o Ethereum desempenha no contexto de optimistic rollup é o de uma camada de liquidação. Uma camada de liquidação ancora todo o ecossistema blockchain, estabelece segurança e proporciona finalidade objetiva caso ocorra uma disputa em outra cadeia (optimistic rollups neste caso) que exija arbitragem. -A rede principal do Ethereum fornece um hub para optimistic rollups, para verificar provas de fraude e resolver disputas. Além disso, as transações realizadas no rollup são apenas finais, _depois_ que o bloco de rollup é aceito no Ethereum. Uma vez que uma transação de rollup é confirmada na camada base do Ethereum, ela não pode ser revertida (exceto no caso altamente improvável de uma reorganização em cadeia). +A rede principal do Ethereum fornece um hub para optimistic rollups, para verificar provas de fraude e resolver disputas. Além disso, as transações realizadas no rollup só são finalizadas _depois_ que o bloco do rollup é aceito no Ethereum. Uma vez que uma transação de rollup é confirmada na camada base do Ethereum, ela não pode ser revertida (exceto no caso altamente improvável de uma reorganização em cadeia). ## Como funcionam os optimistic rollups? {#how-optimistic-rollups-work} -### Execução e agregação das transações {#transaction-execution-and-aggregation} +### Execução e agregação de transações {#transaction-execution-and-aggregation} Os usuários enviam transações para “operadores”, que são nós responsáveis pelo processamento de transações no optimistic rollup. Também conhecido como “validador” ou “agregador”, o operador agrega as transações, compacta os dados subjacentes e publica o bloco no Ethereum. -Embora qualquer pessoa possa se tornar um validador, os validadores do optimistic rollup devem fornecer um vínculo antes de produzir blocos, como um [sistema de prova de participação](/developers/docs/consensus-mechanisms/pos/). Esse vínculo pode ser compido se o validador postar um bloco inválido ou se basear em um bloco antigo, mas inválido (mesmo que seu bloco seja válido). Dessa forma, os optimistic rollups utilizam incentivos criptoeconômicos para garantir que os validadores ajam honestamente. +Embora qualquer um possa se tornar um validador, os validadores de optimistic rollup devem fornecer uma caução antes de produzir blocos, de forma muito parecida com um [sistema de prova de participação](/developers/docs/consensus-mechanisms/pos/). Esse vínculo pode ser compido se o validador postar um bloco inválido ou se basear em um bloco antigo, mas inválido (mesmo que seu bloco seja válido). Dessa forma, os optimistic rollups utilizam incentivos criptoeconômicos para garantir que os validadores ajam honestamente. Espera-se que outros validadores na cadeia de optimistic rollup executem as transações enviadas usando sua cópia do estado do rollup. Se o estado final de um validador for diferente do estado proposto pelo operador, ele poderá iniciar um desafio e computar uma prova de fraude. Alguns optimistic rollups podem renunciar a um sistema validador sem permissão e usar um único “sequenciador” para executar a cadeia. Como um validador, o sequenciador processa transações, produz blocos de rollup e envia transações de rollup para a cadeia L1 (Ethereum). -O sequenciador é diferente de um operador de rollup normal porque tem maior controle sobre a ordenação das transações. Além disso, o sequenciador tem acesso prioritário à cadeia de rollup e é a única entidade autorizada a submeter transações para o contrato on-chain. As transações de nós não sequenciadores ou usuários regulares são simplesmente enfileiradas em uma caixa de entrada separada até que o sequenciador as inclua em um novo lote. +O sequenciador é diferente de um operador de rollup normal porque tem maior controle sobre a ordenação das transações. Além disso, o sequenciador tem acesso prioritário à cadeia de rollup e é a única entidade autorizada a enviar transações ao contrato onchain. As transações de nós não sequenciadores ou usuários regulares são simplesmente enfileiradas em uma caixa de entrada separada até que o sequenciador as inclua em um novo lote. -#### Envio de blocos rollup para o Ethereum {#submitting-blocks-to-ethereum} +#### Enviando blocos de rollup para o Ethereum {#submitting-blocks-to-ethereum} -Como mencionado, o operador de um optimistic rollup agrupa as transações off-chain em um lote e o envia ao Ethereum para reconhecimento para notarização. Esse processo envolve compactar dados relacionados a transações e publicá-los no Ethereum como `calldata` ou em blobs. +Como mencionado, o operador de um optimistic rollups agrupa transações offchain em um lote e o envia ao Ethereum para reconhecimento para notarização. Esse processo envolve compactar dados relacionados a transações e publicá-los no Ethereum como `calldata` ou em blobs. -`calldata` é uma área não modificável e não persistente em um contrato inteligente que se comporta principalmente como [memória](/developers/docs/smart-contracts/anatomy/#memory). Enquanto `calldata` persiste na cadeia como parte do [histórico de logs](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html?highlight=memory#logs), ele não é armazenado como parte do estado do Ethereum. Como `calldata` não afeta nenhuma parte do estado do Ethereum, é mais barato do que o estado para armazenar dados na cadeia. +`calldata` é uma área não modificável e não persistente em um contrato inteligente que se comporta principalmente como a [memória](/developers/docs/smart-contracts/anatomy/#memory). Embora `calldata` persista na cadeia como parte dos [logs de histórico](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html?highlight=memory#logs) da blockchain, não é armazenado como parte do estado do Ethereum. Como `calldata` não toca em nenhuma parte do estado do Ethereum, é mais barato do que o estado para armazenar dados na cadeia. A palavra-chave `calldata` também é usada no Solidity para passar argumentos para uma função de contrato inteligente em tempo de execução. `calldata` identifica a função que está sendo chamada durante uma transação e mantém as entradas para a função na forma de uma sequência arbitrária de bytes. -No contexto de optimistic rollups, `calldata` é usado para enviar dados de transação compactados para o contrato on-chain. O operador de rollup adiciona um novo lote chamando a função necessária no contrato de rollup e passando os dados compactados como argumentos de função. O uso de `calldata` reduz as taxas do usuário, pois a maioria dos custos incorridos pelos rollups vem do armazenamento de dados on-chain. +No contexto de optimistic rollups, `calldata` é usado para enviar dados de transação compactados para o contrato na cadeia. O operador de rollup adiciona um novo lote chamando a função necessária no contrato de rollup e passando os dados compactados como argumentos de função. O uso de `calldata` reduz as taxas do usuário, pois a maioria dos custos que os rollups incorrem vem do armazenamento de dados na cadeia. -Aqui está um [um exemplo](https://etherscan.io/tx/0x9102bfce17c58b5fc1c974c24b6bb7a924fb5fbd7c4cd2f675911c27422a5591) de um envio de rollup em lote para mostrar como esse conceito funciona. O sequenciador invocou o método `appendSequencerBatch()` e passou os dados da transação compactados como entradas usando `calldata`. +Aqui está [um exemplo](https://eth.blockscout.com/tx/0x9102bfce17c58b5fc1c974c24b6bb7a924fb5fbd7c4cd2f675911c27422a5591) de um envio de lote de rollup para mostrar como este conceito funciona. O sequenciador invocou o método `appendSequencerBatch()` e passou os dados da transação compactados como entradas usando `calldata`. Alguns rollups agora usam blobs para postar lotes de transações no Ethereum. -Os blobs não são modificáveis ​​nem persistentes (assim como `calldata`), mas são removidos do histórico depois de 18 dias, aproximadamente. Para mais informações sobre blobs, consulte [Danksharding](/roadmap/danksharding). +Os blobs não são modificáveis e não são persistentes (assim como `calldata`), mas são removidos do histórico após ~18 dias. Para mais informações sobre blobs, consulte [Danksharding](/roadmap/danksharding). -### Compromissos com o estado {#state-commitments} +### Compromissos de estado {#state-commitments} -A qualquer momento, o estado do optimistic rollup (contas, saldos, código de contrato etc.) é organizado como uma [árvore Merkle](/whitepaper/#merkle-trees), chamada de "árvore de estado". A raiz dessa árvore Merkle (raiz do estado), que faz referência ao estado mais recente do rollup, é criptografada e armazenada no contrato rollup. Cada transição de estado na cadeia produz um novo estado de rollup, ao qual um operador se compromete calculando uma nova raiz de estado. +A qualquer momento, o estado do optimistic rollup (contas, saldos, código de contrato etc.) é organizado como uma [árvore de Merkle](/whitepaper/#merkle-trees) chamada de “árvore de estado”. A raiz dessa árvore Merkle (raiz do estado), que faz referência ao estado mais recente do rollup, é criptografada e armazenada no contrato rollup. Cada transição de estado na cadeia produz um novo estado de rollup, ao qual um operador se compromete calculando uma nova raiz de estado. -O operador é obrigado a enviar ambas as raízes de estado, antigas e novas, ao publicar lotes. Se a raiz do estado antigo corresponder à raiz do estado existente no contrato on-chain, o último será descartado e substituído pela nova raiz do estado. +O operador é obrigado a enviar ambas as raízes de estado, antigas e novas, ao publicar lotes. Se a raiz de estado antiga corresponder à raiz de estado existente no contrato onchain, esta última será descartada e substituída pela nova raiz de estado. -O operador de rollup também precisa confirmar uma raiz Merkle para o próprio lote de transações. Isso permite que qualquer pessoa comprove a inclusão de uma transação no lote (em L1) apresentando uma [prova Merkle](/developers/tutorials/merkle-proofs-for-offline-data-integrity/). +O operador de rollup também precisa confirmar uma raiz Merkle para o próprio lote de transações. Isso permite que qualquer pessoa prove a inclusão de uma transação no lote (na L1), apresentando uma [prova de Merkle](/developers/tutorials/merkle-proofs-for-offline-data-integrity/). Os compromissos de estado, especialmente raízes de estado, são necessários para provar a correção das mudanças de estado em um optimistic rollup. O contrato de rollup aceita novas raízes de estado de operadores imediatamente após serem publicadas, mas pode posteriormente excluir raízes de estado inválidas para restaurar o rollup ao seu estado correto. @@ -118,9 +118,9 @@ Se alguém contestar uma asserção, o protocolo de rollup iniciará o cálculo Os esquemas de prova interativa de rodada única refazem as transações disputadas na L1 para detectar asserções inválidas. O protocolo de rollup emula a reexecução da transação contestada na L1 (Ethereum) usando um contrato verificador, com a raiz do estado computada determinando quem vence o desafio. Se a alegação do desafiante sobre o estado correto do rollup estiver correto, o operador será penalizado ao ter seu vínculo cortado. -No entanto, a reexecução de transações na L1 para detectar fraudes requer a publicação de compromissos de estado para transações individuais e aumenta os rollups de dados que devem ser publicados on-chain. Refazer transações também implica custos de gás significativos. Por esses motivos, os optimistic rollups estão mudando para a prova interativa de múltiplas rodadas, que atinge o mesmo objetivo (ou seja, detectar operações de rollup inválidas) com mais eficiência. +No entanto, a reexecução de transações em L1 para detectar fraudes exige a publicação de compromissos de estado para transações individuais e aumenta os acúmulos de dados que devem ser publicados onchain. Refazer transações também implica custos de gás significativos. Por esses motivos, os optimistic rollups estão mudando para a prova interativa de múltiplas rodadas, que atinge o mesmo objetivo (ou seja, detectar operações de rollup inválidas) com mais eficiência. -#### Prova interativa de múltiplas rodadas {#multi-round-interactive-proving} +#### Comprovação interativa de múltiplas rodadas {#multi-round-interactive-proving} A prova interativa de múltiplas rodadas envolve um protocolo de vaivém entre o declarante e o desafiante supervisionado por um contrato de verificador L1, que finalmente decide a parte em questão. Depois que um nó L2 desafia uma asserção, o declarante é obrigado a dividir a asserção contestada em duas metades iguais. Cada asserção individual neste caso conterá tantos passos de computação quanto a outra. @@ -132,7 +132,7 @@ Algumas observações sobre este tipo de prova de fraude: 1. A prova de fraude interativa de múltiplas rodadas é considerada eficiente porque minimiza o trabalho que a cadeia L1 deve fazer na arbitragem de conflitos. Em vez de repetir a transação inteira, a cadeia L1 só precisa reexecutar uma etapa na execução dos rollups. -2. Os protocolos de bisseção reduzem a quantidade de dados postados on-chain (não há necessidade de publicar commits de estado para cada transação). Além disso, as transações de optimistic rollup não são restringidas pelo limite de gás do Ethereum. Por outro lado, os optimistic rollups reexecutando transações devem garantir que uma transação L2 tenha um limite de gás mais baixo para emular sua execução dentro de uma única transação Ethereum. +2. Os protocolos de bissecção reduzem a quantidade de dados publicados onchain (não há necessidade de publicar confirmações de estado para cada transação). Além disso, as transações de optimistic rollup não são restringidas pelo limite de gás do Ethereum. Por outro lado, os optimistic rollups reexecutando transações devem garantir que uma transação L2 tenha um limite de gás mais baixo para emular sua execução dentro de uma única transação Ethereum. 3. Parte do vínculo malicioso do declarante é atribuída ao desafiante, enquanto a outra parte é queimada. A queima evita a colisão entre validadores; se dois validadores conspirarem para iniciar desafios falsos, eles ainda perderão uma parte considerável de toda a participação (stake). @@ -140,39 +140,39 @@ Algumas observações sobre este tipo de prova de fraude: #### Por que as provas de fraude são importantes para os optimistic rollups {#fraud-proof-benefits} -As provas de fraude são importantes porque elas facilitam a _finalidade sem confiança_ em optimistic rollups. A finalidade sem confiança é uma qualidade dos optimistic rollups que garante que uma transação – desde que seja válida – será eventualmente confirmada. +As provas de fraude são importantes porque facilitam a _finalidade sem confiança_ nos optimistic rollups. A finalidade sem confiança é uma qualidade dos optimistic rollups que garante que uma transação – desde que seja válida – será eventualmente confirmada. Nós maliciosos podem tentar atrasar a confirmação de um bloco de rollup válido iniciando desafios falsos. No entanto, as provas de fraude eventualmente provarão a validade do bloco de rollup e fazer com que ele seja confirmado. -Isso também está relacionado a outra propriedade de segurança dos optimistic rollups: a validade da cadeia depende da existência de _um_ nó honesto. O nó honesto pode avançar na cadeia corretamente publicando asserções válidas ou disputando asserções inválidas. Seja qual for o caso, os nós maliciosos que entram em conflito com o nó honesto perderão suas participações (stakes) durante o processo de comprovação de fraude. +Isso também se relaciona com outra propriedade de segurança dos optimistic rollups: a validade da cadeia depende da existência de _um_ nó honesto. O nó honesto pode avançar na cadeia corretamente publicando asserções válidas ou disputando asserções inválidas. Seja qual for o caso, os nós maliciosos que entram em conflito com o nó honesto perderão suas participações (stakes) durante o processo de comprovação de fraude. ### Interoperabilidade L1/L2 {#l1-l2-interoperability} -Os optimistic rollups são projetados para interoperabilidade com a rede principal do Ethereum e permitem que os usuários passem mensagens e dados arbitrários entre as camadas L1 e L2. Eles também são compatíveis com o EVM, então você pode portar [dapps](/developers/docs/dapps/) existentes para optimistic rollups ou criar novos dapps usando ferramentas de desenvolvimento Ethereum. +Os optimistic rollups são projetados para interoperabilidade com a rede principal do Ethereum e permitem que os usuários passem mensagens e dados arbitrários entre as camadas L1 e L2. Eles também são compatíveis com a EVM, então você pode portar [dapps](/developers/docs/dapps/) existentes para optimistic rollups ou criar novos dapps usando as ferramentas de desenvolvimento do Ethereum. -#### 1. Movimento de Ativos {#asset-movement} +#### 1. Movimentação de ativos {#asset-movement} ##### Entrar no rollup -Para usar um optimistic rollup, os usuários depositam ETH, tokens ERC-20 e outros ativos aceitos no contrato [ponte](/developers/docs/bridges/) do rollup em L1. O contrato-ponte retransmitirá a transação para L2, onde uma quantidade equivalente de ativos é cunhada e enviada para o endereço escolhido pelo usuário no optimistic rollup. +Para usar um optimistic rollup, os usuários depositam ETH, tokens ERC-20 e outros ativos aceitos no contrato de [ponte](/developers/docs/bridges/) do rollup na L1. O contrato-ponte retransmitirá a transação para L2, onde uma quantidade equivalente de ativos é cunhada e enviada para o endereço escolhido pelo usuário no optimistic rollup. -As transações geradas pelo usuário (como um depósito L1 > L2) são geralmente enfileiradas até que o sequenciador as reenvie ao contrato de rollup. No entanto, para preservar a resistência à censura, os optimistic rollups permitem que os usuários enviem uma transação diretamente ao contrato de rollup on-chain, se ela tiver sido atrasada além do tempo máximo permitido. +As transações geradas pelo usuário (como um depósito L1 > L2) geralmente são enfileiradas até que o sequenciador as reenvie para o contrato de rollup. No entanto, para preservar a resistência à censura, os optimistic rollups permitem que os usuários enviem uma transação diretamente para o contrato de rollup onchain se ela tiver sido atrasada além do tempo máximo permitido. Alguns optimistic rollups adotam uma abordagem mais direta para evitar que os sequenciadores censurem os usuários. Aqui, um bloco é definido por todas as transações submetidas ao contrato L1 desde o bloco anterior (por exemplo, depósitos) além das transações processadas na cadeia de rollup. Se um sequenciador ignorar uma transação L1, ele publicará a raiz de estado errada (provavelmente); portanto, os sequenciadores não podem atrasar mensagens geradas pelo usuário uma vez publicadas na L1. ##### Sair do rollup -Sair de um optimistic rollup para o Ethereum é mais difícil devido ao esquema de provação de fraude. Se um usuário iniciar uma transação L2 > L1 para sacar fundos depositados em L1, eles deverão esperar até que o período de desafio – com duração de aproximadamente sete dias – termine. No entanto, o processo de retirada em si é bastante simples. +Sair de um optimistic rollup para o Ethereum é mais difícil devido ao esquema de provação de fraude. Se um usuário iniciar uma transação L2 > L1 para sacar fundos custodiados na L1, ele deverá esperar até que o período de desafio — que dura aproximadamente sete dias — termine. No entanto, o processo de retirada em si é bastante simples. Depois que o pedido de retirada é iniciado no rollup L2, a transação é incluída no próximo lote, enquanto os ativos do usuário no rollup são queimados. Uma vez que o lote é publicado no Ethereum, o usuário pode computar uma prova Merkle verificando a inclusão de sua transação de saída no bloco. Então, trata-se de esperar o período de atraso para finalizar a transação na L1 e retirar fundos para a rede principal. -Para evitar esperar uma semana antes de retirar fundos para o Ethereum, os usuários de optimistic rollups podem empregar um **provedor de liquidez** (LP). Um provedor de liquidez assume a propriedade de uma retirada na L2 pendente e paga ao usuário na L1 (em troca de uma taxa). +Para evitar esperar uma semana antes de sacar fundos para o Ethereum, os usuários de optimistic rollup podem empregar um **provedor de liquidez** (LP). Um provedor de liquidez assume a propriedade de uma retirada na L2 pendente e paga ao usuário na L1 (em troca de uma taxa). Os provedores de liquidez podem verificar a validade do pedido de retirada do usuário (executando a própria cadeia) antes de liberar fundos. Dessa forma, eles têm garantias de que a transação será confirmada eventualmente (ou seja, finalidade sem confiança). -#### 2. Compatibilidade EVM {#evm-compatibility} +#### 2. Compatibilidade com a EVM {#evm-compatibility} -Para os desenvolvedores, a vantagem dos optimistic rollups é sua compatibilidade — ou, melhor ainda, equivalência — com a [Máquina Virtual Ethereum (do inglês, Ethereum Virtual Machine, EVM)](/developers/docs/evm/). Os rollups compatíveis com a EVM cumprem as especificações do [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) e suportam a EVM no nível de bytecode. +Para os desenvolvedores, a vantagem dos optimistic rollups é a compatibilidade — ou, melhor ainda, a equivalência — com a [Máquina Virtual Ethereum (EVM)](/developers/docs/evm/). Os rollups compatíveis com a EVM cumprem as especificações do [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) e suportam a EVM no nível de bytecode. A compatibilidade com EVM em optimistic rollups tem os seguintes benefícios: @@ -182,7 +182,7 @@ ii. Desenvolvedores e equipes de projeto que usam optimistic rollups podem aprov O uso de ferramentas existentes é importante porque essas ferramentas foram amplamente auditadas, depuradas e melhoradas ao longo dos anos. Também elimina a necessidade de desenvolvedores Ethereum aprenderem a construir com uma pilha de desenvolvimento totalmente nova. -#### 3. Chamadas de contrato de cadeia cruzada {#cross-chain-contract-calls} +#### 3. Chamadas de contrato entre cadeias {#cross-chain-contract-calls} Usuários (contas de propriedade externa, da sigla EOA) interagem com contratos L2 enviando uma transação ao contrato de rollup ou fazendo com que um sequenciador ou validador faça isso por eles. Os optimistic rollups também permitem que contas de contrato Ethereum interajam com contratos L2 usando contratos de ponte para retransmitir mensagens e passar dados entre L1 e L2. Isso significa que você pode programar um contrato L1 na rede principal do Ethereum para invocar funções pertencentes a contratos em um optimistic rollup de L2. @@ -190,64 +190,64 @@ As chamadas de contrato de cadeia cruzada acontecem de forma assíncrona, o que Um exemplo de uma chamada de contrato de cadeia cruzada é o depósito de token descrito anteriormente. Um contrato em L1 deposita em caução os tokens do usuário e envia uma mensagem para um contrato L2 emparelhado para cunhar uma quantidade igual de tokens no rollup. -Como as chamadas de mensagens de cadeia cruzada resultam na execução do contrato, o remetente geralmente é obrigado a cobrir [custos de gás](/developers/docs/gas/) para computação. É aconselhável definir um limite de gás alto para evitar que a transação falhe na cadeia de destino. O cenário de ponte de token é um bom exemplo; se o lado L1 da transação (depositando os tokens) funcionar, mas o lado L2 (cunhando novos tokens) falhar devido ao baixo gás, o depósito se tornará irrecuperável. +Como as chamadas de mensagem entre cadeias resultam na execução do contrato, o remetente geralmente é obrigado a cobrir os [custos de gás](/developers/docs/gas/) para a computação. É aconselhável definir um limite de gás alto para evitar que a transação falhe na cadeia de destino. O cenário de ponte de token é um bom exemplo; se o lado L1 da transação (depositando os tokens) funcionar, mas o lado L2 (cunhando novos tokens) falhar devido ao baixo gás, o depósito se tornará irrecuperável. -Finalmente, devemos observar que as chamadas de mensagens L2 > L1 entre contratos precisam considerar os atrasos (chamadas L1 > L2 são normalmente executadas após alguns minutos). Isso ocorre porque as mensagens enviadas para a rede principal a partir do optimistic rollup não podem ser executadas até que a janela de desafio expire. +Finalmente, devemos observar que as chamadas de mensagem L2 > L1 entre contratos precisam levar em conta os atrasos (as chamadas L1 > L2 são normalmente executadas após alguns minutos). Isso ocorre porque as mensagens enviadas para a rede principal a partir do optimistic rollup não podem ser executadas até que a janela de desafio expire. ## Como funcionam as taxas de optimistic rollups? {#how-do-optimistic-rollup-fees-work} Os optimistic rollups usam um esquema de taxa de gás, muito parecido com o Ethereum, para denotar quanto os usuários pagam por transação. As taxas cobradas em optimistic rollups dependem dos seguintes componentes: -1. **Gravação de estado**: os optimistic rollups publicam dados de transações e cabeçalhos de bloco (consistindo no hash do cabeçalho do bloco anterior, raiz de estado, raiz de lote) no Ethereum como um `blob` ou "objeto binário grande". [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) apresentou uma solução econômica para incluir dados na cadeia. Um `blob` é um novo campo de transação que permite que rollups publiquem dados de transição de estado compactados no Ethereum L1. Ao contrário de `calldata`, que ficam permanentemente na cadeia, os blobs têm vida curta e podem ser removidos dos clientes após [4.096 épocas](https://github.com/ethereum/consensus-specs/blob/81f3ea8322aff6b9fb15132d050f8f98b16bdba4/configs/mainnet.yaml#L147) (aproximadamente 18 dias). Ao usar blobs para postar lotes de transações compactadas, os optimistic rollups podem reduzir significativamente o custo de gravação de transações na L1. +1. **Gravação de estado**: os optimistic rollups publicam dados de transação e cabeçalhos de bloco (compostos pelo hash do cabeçalho do bloco anterior, raiz do estado, raiz do lote) no Ethereum como um `blob`, ou "objeto binário grande". O [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) introduziu uma solução de baixo custo para incluir dados na cadeia. Um `blob` é um novo campo de transação que permite que os rollups publiquem dados de transição de estado compactados no Ethereum L1. Diferentemente do `calldata`, que permanece permanentemente na cadeia, os blobs são de curta duração e podem ser removidos dos clientes após [4096 épocas](https://github.com/ethereum/consensus-specs/blob/81f3ea8322aff6b9fb15132d050f8f98b16bdba4/configs/mainnet.yaml#L147) (aproximadamente 18 dias). Ao usar blobs para postar lotes de transações compactadas, os optimistic rollups podem reduzir significativamente o custo de gravação de transações na L1. -2. **Gás de blob usado**: transações que transportam blob empregam um mecanismo de taxa dinâmico semelhante ao introduzido pelo [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559). A taxa de gás para transações do tipo 3 leva em consideração a taxa base para blobs, que é determinada pela rede com base na demanda de espaço de blobs e no uso de espaço de blobs da transação que está sendo enviada. +2. **Gás de blob usado**: as transações que transportam blobs empregam um mecanismo de taxa dinâmico semelhante ao introduzido pelo [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559). A taxa de gás para transações do tipo 3 leva em consideração a taxa base para blobs, que é determinada pela rede com base na demanda de espaço de blobs e no uso de espaço de blobs da transação que está sendo enviada. -3. **Taxas do operador L2**: Este é o valor pago aos nódulos de rollup como compensação pelos custos computacionais decorrentes do processamento de transações, muito parecido com as taxas de Gas no Ethereum. Os nódulos de rollup cobram taxas de transação mais baixas, já que as L2s têm capacidades de processamento mais altas e não enfrentam os congestionamentos de rede, que forçam os validadores no Ethereum a priorizar transações com taxas mais altas. +3. **Taxas do operador da L2**: este é o valor pago aos nós do rollup como compensação pelos custos computacionais incorridos no processamento de transações, muito semelhante às taxas de gás no Ethereum. Os nódulos de rollup cobram taxas de transação mais baixas, já que as L2s têm capacidades de processamento mais altas e não enfrentam os congestionamentos de rede, que forçam os validadores no Ethereum a priorizar transações com taxas mais altas. -Os optimistic rollups aplicam vários mecanismos para reduzir as taxas para os usuários, incluindo transações em lote e compactando `calldata` para reduzir os custos de publicação de dados. Você pode verificar o [rastreador de taxas L2](https://l2fees.info/), para ter uma ideia geral real do custo de uso de optimistic rollups baseados em Ethereum. +Os optimistic rollups aplicam vários mecanismos para reduzir as taxas para os usuários, incluindo o processamento de transações em lote e a compressão de `calldata` para reduzir os custos de publicação de dados. Você pode consultar o [rastreador de taxas da L2](https://l2fees.info/) para ter uma visão geral em tempo real de quanto custa usar optimistic rollups baseados em Ethereum. ## Como os optimistic rollups dimensionam o Ethereum? {#scaling-ethereum-with-optimistic-rollups} -Conforme explicado, os optimistic rollups publicam dados de transações compactados no Ethereum para garantir a disponibilidade dos dados. A capacidade de compactar dados publicados on-chain é crucial para dimensionar a taxa de transferência no Ethereum com optimistic rollups. +Conforme explicado, os optimistic rollups publicam dados de transações compactados no Ethereum para garantir a disponibilidade dos dados. A capacidade de compactar dados publicados onchain é crucial para aumentar a produtividade no Ethereum com optimistic rollups. -A cadeia principal da Ethereum coloca limites sobre quantos blocos de dados podem conter, denominados em unidades de gás (o [tamanho médio do bloco](/developers/docs/blocks/#block-size) é de 15 milhões de gás). Embora isso restrinja quanto gás cada transação pode usar, também significa que podemos aumentar as transações processadas por bloco reduzindo os dados relacionados à transação, melhorando diretamenteo dimensionamento. +A cadeia principal do Ethereum impõe limites sobre a quantidade de dados que os blocos podem conter, denominados em unidades de gás (o [tamanho médio do bloco](/developers/docs/blocks/#block-size) é de 15 milhões de gás). Embora isso restrinja quanto gás cada transação pode usar, também significa que podemos aumentar as transações processadas por bloco reduzindo os dados relacionados à transação, melhorando diretamenteo dimensionamento. -Os optimistic rollups usam várias técnicas para obter a compressão de dados de transação e melhorar as taxas de TPS. Por exemplo, este [artigo](https://vitalik.eth.limo/general/2021/01/05/rollup.html) compara os dados que uma transação básica do usuário (enviando ether) gera na rede principal com a quantidade de dados que a mesma transação gera em um rollup: +Os optimistic rollups usam várias técnicas para obter a compressão de dados de transação e melhorar as taxas de TPS. Por exemplo, este [artigo](https://vitalik.eth.limo/general/2021/01/05/rollup.html) compara os dados que uma transação básica do usuário (enviando ether) gera na Rede Principal com a quantidade de dados que a mesma transação gera em um rollup: -| Parâmetro | Ethereum (L1) | Rollup (L2) | -| ---------- | ---------------------------- | ------------- | -| Nonce | ~3 | 0 | -| Gasprice | ~8 | 0-0.5 | -| Gás | 3 | 0-0.5 | -| Para | 21 | 4 | -| Valores | 9 | ~3 | -| Assinatura | ~68 (2 + 33 + 33) | ~0.5 | -| De | 0 (recuperado da assinatura) | 4 | -| **Total** | **~112 bytes** | **~12 bytes** | +| Parâmetro | Ethereum (L1) | Rollup (L2) | +| ---------- | ---------------------------------------------------- | ------------------------------------ | +| Nonce | ~3 | 0 | +| Gasprice | ~8 | 0-0.5 | +| Gás | 3 | 0-0.5 | +| Para | 21 | 4 | +| Valor | 9 | ~3 | +| Assinatura | ~68 (2 + 33 + 33) | ~0.5 | +| De | 0 (recuperado da assinatura) | 4 | +| **Total** | **\~112 bytes** | **\~12 bytes** | Fazer alguns cálculos aproximados sobre esses números pode ajudar a mostrar as melhorias de dimensionamento oferecidas por um optimistic rollup: -1. O tamanho-alvo para cada bloco é de 15 milhões de gás e custa 16 gás para verificar um byte de dados. Dividir o tamanho médio do bloco por 16 gás (15.000.000/16) mostra que o bloco médio pode conter **937.500 bytes de dados**. -2. Se uma transação de rollup básica usa 12 bytes, o bloco Ethereum médio pode processar **78.125 transações de rollup** (937.5000/12) ou **39 lotes de rollup** (se cada lote possuir uma média de 2.000 transações). -3. Se um novo bloco for produzido no Ethereum a cada 15 segundos, as velocidades de processamento do rollup serão de aproximadamente **5.208 transações por segundo**. Isso é feito dividindo o número de transações de rollup básicas que um bloco Ethereum pode manter, (**78.125**) pelo tempo médio de bloqueio (**15 segundos**). +1. O tamanho-alvo para cada bloco é de 15 milhões de gás e custa 16 gás para verificar um byte de dados. Dividir o tamanho médio do bloco por 16 de gás (15.000.000/16) mostra que o bloco médio pode conter **937.500 bytes de dados**. +2. Se uma transação de rollup básica usar 12 bytes, então o bloco médio do Ethereum pode processar **78.125 transações de rollup** (937.500/12) ou **39 lotes de rollup** (se cada lote contiver uma média de 2.000 transações). +3. Se um novo bloco é produzido no Ethereum a cada 15 segundos, então as velocidades de processamento do rollup chegariam a aproximadamente **5.208 transações por segundo**. Isso é feito dividindo o número de transações de rollup básicas que um bloco do Ethereum pode conter (**78.125**) pelo tempo médio do bloco (**15 segundos**). Esta é uma estimativa bastante otimista, uma vez que as transações de optimistic rollups não podem abranger um bloco inteiro no Ethereum. No entanto, pode dar uma ideia aproximada de quantos ganhos de dimensionamento os optimistic rollups podem proporcionar aos usuários do Ethereum (as implementações atuais oferecem até 2.000 TPS). -Espera-se que a introdução de [fragmentação (sharding) de dados](/roadmap/danksharding/) no Ethereum melhore o dimensionamento do rollup otimista. Como as transações de rollup devem compartilhar o espaço de blocos (blockspace) com outras transações não-rollup, sua capacidade de processamento é limitada pela taxa de transferência de dados na cadeia principal do Ethereum. Danksharding aumentará o espaço disponível para que cadeias L2 publiquem dados por bloco, usando armazenamento de “blob” impermanente e mais barato em vez de `CALLDATA`, que é permanente e caro. +Espera-se que a introdução da [fragmentação de dados](/roadmap/danksharding/) no Ethereum melhore a escalabilidade dos optimistic rollups. Como as transações de rollup devem compartilhar o espaço de blocos (blockspace) com outras transações não-rollup, sua capacidade de processamento é limitada pela taxa de transferência de dados na cadeia principal do Ethereum. O Danksharding aumentará o espaço disponível para as cadeias L2 publicarem dados por bloco, usando um armazenamento "blob" mais barato e não permanente, em vez do `CALLDATA` caro e permanente. ### Prós e contras dos optimistic rollups {#optimistic-rollups-pros-and-cons} -| Prós | Contras | -| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Prós | Contras | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Oferece grandes melhorias de dimensionamento sem sacrificar a segurança ou a falta de confiança. | Atrasos na finalização da transação devido a potenciais desafios de fraude. | -| Os dados da transação são armazenados na cadeia da camada 1, melhorando a transparência, segurança, resistência à censura e descentralização. | Operadores de rollup centralizados (sequenciadores) podem influenciar a ordenação de transações. | +| Os dados da transação são armazenados na cadeia da camada 1, melhorando a transparência, segurança, resistência à censura e descentralização. | Operadores de rollup centralizados (sequenciadores) podem influenciar a ordenação de transações. | | A comprovação de fraude garante uma finalidade sem confiança e permite que minorias honestas protejam a cadeia. | Se não houver nós honestos, um operador malicioso poderá roubar fundos publicando blocos inválidos e compromissos de estado. | -| A computação de provas de fraude está aberta ao nó L2 regular, ao contrário das provas de validade (usadas em ZK-rollups) que requerem hardware especial. | O modelo de segurança depende de pelo menos um nó honesto executando transações de rollup e enviando provas de fraude, para desafiar transições de estado inválidas. | -| Os rollups se beneficiam da "vida sem confiança" (qualquer um pode forçar a cadeia a avançar executando transações e publicando declarações) | Os usuários devem esperar que o período de desafio de uma semana expire antes de retirar os fundos de volta para o Ethereum. | -| Os optimistic rollups dependem de incentivos criptoeconômicos bem projetados para aumentar a segurança na cadeia. | Os rollups devem publicar todos os dados da transação on-chain, o que pode aumentar os custos. | -| A compatibilidade com EVM e Solidity permite aos desenvolvedores portar contratos inteligentes nativos do Ethereum para rollups ou usar ferramentas existentes para criar novos dapps. | | +| A computação de provas de fraude está aberta ao nó L2 regular, ao contrário das provas de validade (usadas em ZK-rollups) que requerem hardware especial. | O modelo de segurança depende de pelo menos um nó honesto executando transações de rollup e enviando provas de fraude, para desafiar transições de estado inválidas. | +| Os rollups se beneficiam da "vida sem confiança" (qualquer um pode forçar a cadeia a avançar executando transações e publicando declarações) | Os usuários devem esperar que o período de desafio de uma semana expire antes de retirar os fundos de volta para o Ethereum. | +| Os optimistic rollups dependem de incentivos criptoeconômicos bem projetados para aumentar a segurança na cadeia. | Os rollups devem publicar todos os dados de transações onchain, o que pode aumentar os custos. | +| A compatibilidade com EVM e Solidity permite aos desenvolvedores portar contratos inteligentes nativos do Ethereum para rollups ou usar ferramentas existentes para criar novos dapps. | | -### Uma explicação visual de optimistic rollups {#optimistic-video} +### Uma explicação visual dos optimistic rollups {#optimistic-video} Você é o tipo de pessoa que aprende mais com recursos visuais? Assista aos Finematics explicando os optimistic rollups: @@ -255,9 +255,11 @@ Você é o tipo de pessoa que aprende mais com recursos visuais? Assista aos Fin ## Leitura adicional sobre optimistic rollups -- [Como funcionam os optimistic rollups (o guia completo)](https://www.alchemy.com/overviews/optimistic-rollups) +- [Como os optimistic rollups funcionam (O guia completo)](https://www.alchemy.com/overviews/optimistic-rollups) - [O que é uma Blockchain Rollup? Uma introdução técnica](https://www.ethereum-ecosystem.com/blog/what-is-a-blockchain-rollup-a-technical-introduction) -- [O guia essencial do Arbitrum](https://www.bankless.com/the-essential-guide-to-arbitrum) -- [Como o optimistic rollup realmente funciona?](https://www.paradigm.xyz/2021/01/how-does-optimism-s-rollup-really-work) -- [OVM: aprofundamento](https://medium.com/ethereum-optimism/ovm-deep-dive-a300d1085f52) -- [O que é a máquina virtual otimista?](https://www.alchemy.com/overviews/optimistic-virtual-machine) +- [O Guia Essencial para o Arbitrum](https://www.bankless.com/the-essential-guide-to-arbitrum) +- [O guia prático para os rollups do Ethereum](https://web.archive.org/web/20241108192208/https://research.2077.xyz/the-practical-guide-to-ethereum-rollups) +- [O estado das provas de fraude nas L2s do Ethereum](https://web.archive.org/web/20241124154627/https://research.2077.xyz/the-state-of-fraud-proofs-in-ethereum-l2s) +- [Como o rollup da Optimism realmente funciona?](https://www.paradigm.xyz/2021/01/how-does-optimism-s-rollup-really-work) +- [Análise aprofundada da OVM](https://medium.com/ethereum-optimism/ovm-deep-dive-a300d1085f52) +- [O que é a Máquina Virtual Otimista?](https://www.alchemy.com/overviews/optimistic-virtual-machine) diff --git a/public/content/translations/pt-br/developers/docs/scaling/plasma/index.md b/public/content/translations/pt-br/developers/docs/scaling/plasma/index.md index 4c6ae6a3d7e..b4756982798 100644 --- a/public/content/translations/pt-br/developers/docs/scaling/plasma/index.md +++ b/public/content/translations/pt-br/developers/docs/scaling/plasma/index.md @@ -1,48 +1,48 @@ --- title: As cadeias Plasma -description: Uma introdução às cadeias plasma como uma solução de dimensionamento atualmente utilizada pela comunidade Ethereum. +description: "Uma introdução às cadeias plasma como uma solução de dimensionamento atualmente utilizada pela comunidade Ethereum." lang: pt-br incomplete: true sidebarDepth: 3 --- -Uma cadeia Plasma é uma blockchain separada ancorada à rede principal do Ethereum, mas executando transações off-chain com seu próprio mecanismo para validação de bloco. Cadeias Plasma são algumas vezes referenciadas como cadeias "filhas", essencialmente cópias menores da rede principal do Ethereum. As cadeias plasma usam [provas de fraude](/glossary/#fraud-proof) (como [optimistic rollups](/developers/docs/scaling/optimistic-rollups/)) para arbitrar conflitos. +A rede Plasma é uma blockchain separada ancorada à rede principal do Ethereum, mas executando transações off-chain com seu próprio mecanismo para validação de bloco. Cadeias Plasma são algumas vezes referenciadas como cadeias "filhas", essencialmente cópias menores da rede principal do Ethereum. As cadeias Plasma usam [provas de fraude](/glossary/#fraud-proof) (como os [optimistic rollups](/developers/docs/scaling/optimistic-rollups/)) para arbitrar disputas. As árvores Merkle permitem a criação de uma pilha sem fim dessas cadeias, que podem funcionar para descarregar a largura de banda das cadeias pai (incluindo a rede principal do Ethereum). No entanto, embora essas cadeias obtenham alguma segurança do Ethereum (por meio de provas de fraude), a segurança e eficiência que oferecem são afetadas por várias limitações de projeto. -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -Você deve ter um bom entendimento de todos os tópicos fundamentais e um entendimento mais geral sobre [Dimensionamento Ethereum](/developers/docs/scaling/). +Você deve ter um bom entendimento de todos os tópicos fundamentais e um entendimento de alto nível da [escalabilidade do Ethereum](/developers/docs/scaling/). ## O que é Plasma? -Plasma é uma estrutura para melhorar o dimensionamento em blockchains públicas como o Ethereum. Conforme descrito no [whitepaper do Plasma](http://plasma.io/plasma.pdf) original, cadeias Plasma são construídas sobre outra blockchain (chamada de "cadeia raiz"). Cada "cadeia filha" estende da cadeia raiz e geralmente é gerenciada por um contrato inteligente implantado na cadeia pai. +Plasma é uma estrutura para melhorar o dimensionamento em blockchains públicas como o Ethereum. Conforme descrito no [whitepaper original do Plasma](http://plasma.io/plasma.pdf), as cadeias Plasma são construídas sobre outra blockchain (chamada de "cadeia raiz"). Cada "cadeia filha" estende da cadeia raiz e geralmente é gerenciada por um contrato inteligente implantado na cadeia pai. -O contrato Plasma funciona, entre outras coisas, como uma [ponte](/developers/docs/bridges/) permitindo que os usuários movam ativos entre a rede principal do Ethereum e a cadeia plasma. Embora isso as torne semelhantes às [sidechains](/developers/docs/scaling/sidechains/), as cadeias plasma se beneficiam – pelo menos, até certo ponto – da segurança da rede principal do Ethereum. Isso é diferente das sidechains que são as únicas responsáveis pela segurança delas. +O contrato Plasma funciona, entre outras coisas, como uma [ponte](/developers/docs/bridges/) que permite aos usuários mover ativos entre a Rede Principal do Ethereum e a cadeia plasma. Embora isso as torne semelhantes às [sidechains](/developers/docs/scaling/sidechains/), as cadeias plasma se beneficiam — pelo menos, até certo ponto — da segurança da rede principal do Ethereum. Isso é diferente das sidechains que são as únicas responsáveis pela segurança delas. ## Como as cadeias Plasma funcionam? Os componentes básicos do framework Plasma são: -### Computação off-chain {#off-chain-computation} +### Computação fora da cadeia {#offchain-computation} -A velocidade de processamento atual do Ethereum é limitada a ~ 15-20 transações por segundo, reduzindo a possibilidade de dimensionamento de curto prazo para lidar com mais usuários. Esse problema existe principalmente porque o [mecanismo de consenso](/developers/docs/consensus-mechanisms/) de Ethereum requer muitos nós ponto a ponto para verificar cada atualização do estado da blockchain. +A velocidade de processamento atual do Ethereum é limitada a ~ 15-20 transações por segundo, reduzindo a possibilidade de dimensionamento de curto prazo para lidar com mais usuários. Este problema existe principalmente porque o [mecanismo de consenso](/developers/docs/consensus-mechanisms/) do Ethereum exige que muitos nós ponto a ponto verifiquem cada atualização do estado da blockchain. Embora o mecanismo de consenso de Ethereum seja necessário para segurança, ele pode não se aplicar a todos os casos de uso. Por exemplo, Alice pode não precisar de seus pagamentos diários a Bob, por uma xícara de café verificada por toda a rede Ethereum, pois existe alguma confiança entre ambas as partes. A cadeia Plasma supõe que a rede principal do Ethereum não precisa verificar todas as transações. Em vez disso, podemos processar transações fora da rede principal, liberando os nós da necessidade de validar cada transação. -A computação off-chain é necessária, pois as cadeias Plasma podem otimizar a velocidade e o custo. Por exemplo, uma cadeia plasma pode, na maioria das vezes, usar um único "operador" para gerenciar a ordenação e execução das transações. Com apenas uma entidade verificando transações, os tempos de processamento em uma cadeia plasma são mais rápidos que na rede principal do Ethereum. +A computação off-chain é necessária, pois as redes Plasma podem otimizar a velocidade e o custo. Por exemplo, uma cadeia plasma pode, na maioria das vezes, usar um único "operador" para gerenciar a ordenação e execução das transações. Com apenas uma entidade verificando transações, os tempos de processamento em uma cadeia plasma são mais rápidos que na rede principal do Ethereum. -### Compromissos com o estado {#state-commitments} +### Compromissos de estado {#state-commitments} -Enquanto cadeia Plasma executa transações off-chain, eles são estabelecidas na camada de execução principal do Ethereum, caso contrário as cadeias Plasma não podem se beneficiar das garantias de segurança do Ethereum. Mas finalizar transações off-chain sem saber o estado da cadeia plasma quebraria o modelo de segurança e permitiria a proliferação de transações inválidas. É por isso que o operador, entidade responsável pela produção de blocos na cadeia plasma, é obrigado a publicar periodicamente "compromissos de estado" no Ethereum. +Enquanto Plasma executa transações off-chain, eles são estabelecidas na camada de execução principal do Ethereum, caso contrário as redes Plasma não podem se beneficiar das garantias de segurança do Ethereum. Mas finalizar transações off-chain sem saber o estado da cadeia de plasma quebraria o modelo de segurança e permitiria a proliferação de transações inválidas. É por isso que o operador, entidade responsável pela produção de blocos na cadeia plasma, é obrigado a publicar periodicamente "compromissos de estado" no Ethereum. -Um [esquema de compromisso](https://en.wikipedia.org/wiki/Commitment_scheme) é uma técnica criptográfica para se comprometer com um valor ou declaração sem revelá-la a outra parte. Os compromissos são "vinculativos" no sentido de que você não pode alterar o valor ou a declaração depois de se comprometer com ele. Os compromissos de estado na cadeia Plasma assumem a forma de "raízes Merkle" (derivado de uma [árvore Merkle](/whitepaper/#merkle-trees)) o qual o operador envia em intervalos para o contrato Plasma na cadeia Ethereum. +Um [esquema de compromisso](https://en.wikipedia.org/wiki/Commitment_scheme) é uma técnica criptográfica para se comprometer com um valor ou declaração sem revelá-lo a outra parte. Os compromissos são "vinculativos" no sentido de que você não pode alterar o valor ou a declaração depois de se comprometer com ele. Os compromissos de estado no Plasma assumem a forma de "raízes Merkle" (derivadas de uma [árvore Merkle](/whitepaper/#merkle-trees)), que o operador envia em intervalos para o contrato Plasma na cadeia Ethereum. -As raízes Merkle são primitivas criptográficas que permitem a compactação de grandes quantidades de informações. Uma raiz Merkle (também chamada de "raiz de bloco" neste caso) poderia representar todas as transações em um bloco. As raízes Merkle também tornam mais fácil verificar se uma pequena parte de dados faz parte do conjunto de dados maior. Por exemplo, um usuário pode produzir uma [prova de Merkle](/developers/tutorials/merkle-proofs-for-offline-data-integrity/#main-content) para provar a inclusão de uma transação em um bloco específico. +As raízes Merkle são primitivas criptográficas que permitem a compactação de grandes quantidades de informações. Uma raiz Merkle (também chamada de "raiz de bloco" neste caso) poderia representar todas as transações em um bloco. As raízes Merkle também tornam mais fácil verificar se uma pequena parte de dados faz parte do conjunto de dados maior. Por exemplo, um usuário pode produzir uma [prova Merkle](/developers/tutorials/merkle-proofs-for-offline-data-integrity/#main-content) para provar a inclusão de uma transação em um bloco específico. -As raízes Merkle são importantes para fornecer informações sobre o estado off-chain para o Ethereum. Você pode pensar nas raízes de Merkle como "pontos salvos": o operador está dizendo, "Este é o estado da cadeia Plasma no ponto x no tempo, e esta é a raiz de Merkle como prova". O operador está se comprometendo com o _estado atual_ da cadeia plasma com uma raiz Merkle, por isso é chamado de "compromisso de estado". +As raízes de Merkle são importantes para fornecer informações sobre o estado offchain para o Ethereum. Você pode pensar nas raízes de Merkle como "pontos salvos": o operador está dizendo, "Este é o estado da cadeia Plasma no ponto x no tempo, e esta é a raiz de Merkle como prova". O operador está se comprometendo com o _estado atual_ da cadeia plasma com uma raiz Merkle, e é por isso que é chamado de "compromisso de estado". ### Entradas e saídas {#entries-and-exits} @@ -50,11 +50,11 @@ Para que os usuários do Ethereum aproveitem a cadeia Plasma, é necessário um Plasma usa um contrato principal em execução no Ethereum para processar entradas e saídas de usuários. Este contrato principal também é responsável por rastrear os compromissos do estado (explicado anteriormente) e punir o comportamento desonesto por meio de provas de fraude (mais sobre isso adiante). -#### Entrar na cadeia plasma {#entering-the-plasma-chain} +#### Entrando na cadeia plasma {#entering-the-plasma-chain} Para entrar na cadeia plasma, Alice (a usuária) terá que depositar ETH ou qualquer token ERC-20 no contrato plasma. A operadora de plasma, que observa os depósitos do contrato, recria uma quantia igual ao depósito inicial de Alice e o libera em seu endereço na cadeia plasma. Alice é obrigada a atestar o recebimento dos fundos na cadeia filha e pode então usar esses fundos para transações. -#### Sair da cadeia plasma {#exiting-the-plasma-chain} +#### Saindo da cadeia plasma {#exiting-the-plasma-chain} Sair da cadeia plasma é mais complexo do que entrar nela por várias razões. O maior delas é que, embora o Ethereum tenha informações sobre o estado da cadeia plasma, ele não pode verificar se as informações são verdadeiras ou não. Um usuário malicioso poderia fazer uma afirmação incorreta ("Eu tenho 1000 ETH") e fugir fornecendo provas falsas para sustentar a afirmação. @@ -62,17 +62,17 @@ Para evitar retiradas maliciosas, é introduzido um "período de desafio". Duran No entanto, normalmente os usuários são honestos e fazem reivindicações corretas sobre os fundos que possuem. Nesse cenário, Alice iniciará uma solicitação de retirada na cadeia raiz (Ethereum) enviando uma transação para o contrato de plasma. -Ela também deve fornecer uma prova Merkle verificando que, uma transação que criou seus fundos na cadeia Plasma foi incluída em um bloco. Isso é necessário para iterações de Plasma, como o [Plasma MVP](https://www.learnplasma.org/en/learn/mvp.html), que utiliza um modelo [Transação de Saída Não Gasta (Unspent Transaction Output, UTXO)](https://en.wikipedia.org/wiki/Unspent_transaction_output). +Ela também deve fornecer uma prova Merkle verificando que, uma transação que criou seus fundos na cadeia Plasma foi incluída em um bloco. Isso é necessário para iterações do Plasma, como o [Plasma MVP](https://www.learnplasma.org/en/learn/mvp.html), que usam um modelo de [Saída de Transação Não Gasta (UTXO)](https://en.wikipedia.org/wiki/Unspent_transaction_output). -Outros, como [Plasma Cash](https://www.learnplasma.org/en/learn/cash.html), representam fundos como [tokens não fungíveis](/developers/docs/standards/tokens/erc-721/) em vez de UTXOs. A retirada, neste caso, requer a prova de propriedade de tokens na cadeia Plasma. Isso é feito submetendo as duas últimas transações envolvendo o token e fornecendo uma prova Merkle verificando a inclusão dessas transações em um bloco. +Outros, como o [Plasma Cash](https://www.learnplasma.org/en/learn/cash.html), representam fundos como [tokens não fungíveis](/developers/docs/standards/tokens/erc-721/) em vez de UTXOs. A retirada, neste caso, requer a prova de propriedade de tokens na cadeia Plasma. Isso é feito submetendo as duas últimas transações envolvendo o token e fornecendo uma prova Merkle verificando a inclusão dessas transações em um bloco. O usuário também deve adicionar um vínculo ao pedido de retirada como garantia de comportamento honesto. Se um desafiante provar que o pedido de retirada de Alice é inválido, seu vínculo é reduzido e parte dele vai para o desafiante como recompensa. Se o período de desafio decorrer sem que ninguém forneça uma prova de fraude, o pedido de retirada de Alice é considerado válido, permitindo que ela recupere os depósitos do contrato Plasma no Ethereum. -### Arbitragem de disputa {#dispute-arbitration} +### Arbitragem de disputas {#dispute-arbitration} -Como qualquer blockchain, as cadeias plasma precisam de um mecanismo para impor a integridade das transações, caso os participantes ajam maliciosamente (por exemplo, gastos duplos de fundos). Para isso, as cadeias plasma usam provas de fraude para arbitrar disputas sobre a validade das transições de estado e penalizar o mau comportamento. As provas de fraude são utilizadas como um mecanismo através do qual uma cadeia-filho do Plasma apresenta uma queixa à sua cadeia pai ou à cadeia raiz. +Como qualquer blockchain, as cadeias plasma precisam de um mecanismo para impor a integridade das transações, caso os participantes ajam maliciosamente (por exemplo, gasto duplo de fundos). Para isso, as cadeias plasma usam provas de fraude para arbitrar disputas sobre a validade das transições de estado e penalizar o mau comportamento. As provas de fraude são utilizadas como um mecanismo através do qual uma cadeia-filho do Plasma apresenta uma queixa à sua cadeia pai ou à cadeia raiz. Uma prova de fraude é simplesmente uma alegação de que uma determinada transição de estado é inválida. Um exemplo é se um usuário (Alice) tentar gastar os mesmos fundos duas vezes. Talvez ela tenha gasto o UTXO em uma transação com Bob e quer gastar o mesmo UTXO (que agora é de Bob) em outra transação. @@ -80,17 +80,17 @@ Para evitar a retirada, Bob construirá uma prova de fraude fornecendo evidênci Se o desafio de Bob é bem-sucedido, o pedido de retirada de Alice é cancelado. No entanto, essa abordagem depende da capacidade de Bob de observar a cadeia em busca de pedidos de retirada. Se Bob estiver offline, então a Alice poderá processar a retirada maliciosa, assim que o período de desafio terminar. -## O problema da saída em massa da cadeia Plasma {#the-mass-exit-problem-in-plasma} +## O problema de saída em massa no plasma {#the-mass-exit-problem-in-plasma} -O problema da saída em massa ocorre quando um grande número de usuários tenta retirar de uma cadeia de plasma ao mesmo tempo. Este problema existe por conta de um dos maiores problemas da cadeia Plasma: **indisponibilidade de dados**. +O problema da saída em massa ocorre quando um grande número de usuários tenta retirar de uma cadeia de plasma ao mesmo tempo. A existência deste problema está relacionada a um dos maiores problemas do Plasma: a **indisponibilidade de dados**. A disponibilidade de dados é a capacidade de verificar se as informações de um bloco proposto foram de fato publicadas na rede blockchain. Um bloco está "indisponível" se o produtor publicar o bloco em si, mas retiver os dados usados para criar o bloco. -Blocos devem estar disponíveis se os nós estão aptos a baixar o bloco e verificar a validade das transações. As blockchains garantem a disponibilidade de dados, forçando os produtores do bloco a publicar todos os dados da transação na cadeia. +Blocos devem estar disponíveis se os nós estão aptos a baixar o bloco e verificar a validade das transações. As blockchains garantem a disponibilidade dos dados forçando os produtores do bloco a publicar todos os dados de transações onchain. -A disponibilidade de dados também ajuda a proteger os protocolos de dimensionamento off-chain que se baseiam na camada base do Ethereum. Ao forçar os operadores nessas cadeias a publicar dados de transação no Ethereum, qualquer um pode desafiar blocos inválidos construindo provas de fraude que referenciam o estado correto da cadeia. +A disponibilidade de dados também ajuda a proteger protocolos de dimensionamento off-chain que se baseiam na camada base do Ethereum. Ao forçar os operadores nessas cadeias a publicar dados de transação no Ethereum, qualquer um pode desafiar blocos inválidos construindo provas de fraude que referenciam o estado correto da cadeia. -Cadeias Plasma armazenam principalmente dados de transação com o operador e **não publicam nenhum dado na rede principal** (ou seja, além de compromissos de estado periódicos). Isso significa que os usuários devem confiar no operador para fornecer dados de bloqueio, se precisarem criar provas de fraude que desafiem transações inválidas. Se esse sistema funcionar, então os usuários poderão sempre usar provas de fraude para proteger os fundos. +As cadeias Plasma armazenam principalmente dados de transação com o operador e **não publicam dados na Rede Principal** (ou seja, além dos compromissos de estado periódicos). Isso significa que os usuários devem confiar no operador para fornecer dados de bloqueio, se precisarem criar provas de fraude que desafiem transações inválidas. Se esse sistema funcionar, então os usuários poderão sempre usar provas de fraude para proteger os fundos. O problema começa quando o operador, e não apenas qualquer usuário, é a parte que age maliciosamente. Como o operador está no controle exclusivo da blockchain, ele tem mais incentivo para avançar as transições de estado inválido em uma escala maior, como o roubo de fundos pertencentes a usuários na cadeia plasma. @@ -98,35 +98,35 @@ Neste caso, a utilização do sistema clássico de prova de fraude não funciona Portanto, a solução mais otimista é tentar uma "saída em massa" dos usuários da cadeia Plasma. A saída em massa torna mais lento o plano do operador malicioso de roubar fundos e fornece alguma medida de proteção para os usuários. Os pedidos de retirada são ordenados com base em quando cada UTXO (ou token) foi criado, impedindo que operadores mal-intencionados se antecipem (front-running) aos usuários honestos. -No entanto, os nós ainda precisamos de uma maneira para verificar a validade dos pedidos de retirada durante uma saída em massa, para evitar que indivíduos oportunistas lucrem com o caos processando saídas inválidas. A solução é simples: exigir que os usuários postem o último **estado válido da cadeia** para retirar o dinheiro. +No entanto, os nós ainda precisamos de uma maneira para verificar a validade dos pedidos de retirada durante uma saída em massa, para evitar que indivíduos oportunistas lucrem com o caos processando saídas inválidas. A solução é simples: exigir que os usuários postem o último **estado válido da cadeia** para retirar seu dinheiro. Mas essa abordagem ainda tem problemas. Por exemplo, se todos os usuários em uma cadeia Plasma precisarem sair (o que é possível no caso de um operador malicioso), então todo o estado válido da cadeia Plasma deverá ser despejado na camada base do Ethereum de uma só vez. Com o tamanho arbitrário de cadeias Plasma (alto rendimento = mais dados) e as restrições nas velocidades de processamento do Ethereum, esta não é uma solução ideal. Embora os jogos de saída pareçam OK em teoria, as saídas em massa da vida real provavelmente desencadearão um congestionamento de rede no próprio Ethereum. Além de prejudicar a funcionalidade do Ethereum, uma saída em massa mal coordenada significa que, os usuários podem não conseguir retirar fundos antes que o operador drene todas as contas da cadeia Plasma. -## Prós e contras da cadeia Plasma {#pros-and-cons-of-plasma} +## Prós e contras do plasma {#pros-and-cons-of-plasma} -| Prós | Contras | -| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Oferece alta taxa de transferência e baixo custo por transação. | Não suporta computação geral (não pode executar contratos inteligentes). Apenas transferências básicas de tokens, swaps e alguns outros tipos de transação são suportados através da lógica preditiva. | -| Bom para transações entre usuários arbitrários (sem sobrecarga por par de usuário, se ambos estiverem estabelecidos na cadeia Pasma). | É necessário monitorar periodicamente a rede (exigência de vitalidade) ou delegar essa responsabilidade a outra pessoa para garantir a segurança de seus fundos. | -| As cadeias Plasma podem ser adaptadas a casos de uso específicos que não estão relacionados com a cadeia principal. Qualquer pessoa, incluindo empresas, pode personalizar contratos inteligentes de Plasma para fornecer infraestrutura dimensionável que funciona em diferentes contextos. | Refere-se a um ou mais operadores para armazenar dados e atender a pedido. | -| Reduz a carga na rede principal do Ethereum movendo a computação e o armazenamento off-chain. | As retiradas são adiadas por vários dias para permitir desafios. Para ativos fungíveis isso pode ser mitigado por provedores de liquidez, mas existe um custo de capital associado. | -| | Se muitos usuários tentarem sair simultaneamente, a rede principal do Ethereum poderá ficar congestionada. | +| Prós | Contras | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Oferece alta taxa de transferência e baixo custo por transação. | Não suporta computação geral (não pode executar contratos inteligentes). Apenas transferências básicas de tokens, swaps e alguns outros tipos de transação são suportados através da lógica preditiva. | +| Bom para transações entre usuários arbitrários (sem sobrecarga por par de usuário, se ambos estiverem estabelecidos na cadeia Pasma). | É necessário monitorar periodicamente a rede (exigência de vitalidade) ou delegar essa responsabilidade a outra pessoa para garantir a segurança de seus fundos. | +| As cadeias Plasma podem ser adaptadas a casos de uso específicos que não estão relacionados com a cadeia principal. Qualquer pessoa, incluindo empresas, pode personalizar contratos inteligentes de Plasma para fornecer infraestrutura dimensionável que funciona em diferentes contextos. | Refere-se a um ou mais operadores para armazenar dados e atender a pedido. | +| Reduz a carga na rede principal do Ethereum movendo a computação e o armazenamento para offchain. | As retiradas são adiadas por vários dias para permitir desafios. Para ativos fungíveis isso pode ser mitigado por provedores de liquidez, mas existe um custo de capital associado. | +| | Se muitos usuários tentarem sair simultaneamente, a rede principal do Ethereum poderá ficar congestionada. | -## Plasma versus protocolos dimensionáveis de camada 2 {#plasma-vs-layer-2} +## Plasma vs. protocolos de escalabilidade de camada 2 {#plasma-vs-layer-2} -Embora a cadeia Plasma já tenha sido considerada uma solução dimensionável e útil para o Ethereum, ela tem sido dispensada em favor de protocolos dimensionáveis da [camada 2 (L2)](/layer-2/). Soluções dimensionáveis L2 resolvem vários problemas da cadeia Plasma: +Embora o Plasma já tenha sido considerado uma solução de escalabilidade útil para o Ethereum, desde então foi abandonado em favor dos [protocolos de escalabilidade da camada 2 (L2)](/layer-2/). Soluções dimensionáveis L2 resolvem vários problemas da cadeia Plasma: ### Eficiência {#efficiency} -[Rollups de conhecimento zero](/developers/docs/scaling/zk-rollups) geram provas criptográficas da validade de cada lote de transações processado off-chain. Isso evita que usuários (e operadores) avancem em transições de estado inválido, eliminando a necessidade de períodos de desafio e jogos de saída. Isto também significa que os usuários não precisam monitorar a cadeia periodicamente para garantir seus fundos. +[Rollups de conhecimento zero](/developers/docs/scaling/zk-rollups) geram provas criptográficas da validade de cada lote de transações processadas off-chain. Isso evita que usuários (e operadores) avancem em transições de estado inválido, eliminando a necessidade de períodos de desafio e jogos de saída. Isto também significa que os usuários não precisam monitorar a cadeia periodicamente para garantir seus fundos. ### Suporte para contratos inteligentes {#support-for-smart-contracts} -Outro problema com o framework Plasma foi [a incapacidade de suportar a execução dos contratos inteligentes do Ethereum](https://ethresear.ch/t/why-smart-contracts-are-not-feasible-on-plasma/2598/4). Como resultado, a maioria das implementações da cadeia Plasma foram desenvolvidas principalmente para pagamentos simples ou o intercâmbio de tokens ERC-20. +Outro problema com o framework do plasma foi [a incapacidade de suportar a execução de contratos inteligentes do Ethereum](https://ethresear.ch/t/why-smart-contracts-are-not-feasible-on-plasma/2598/4). Como resultado, a maioria das implementações da cadeia Plasma foram desenvolvidas principalmente para pagamentos simples ou o intercâmbio de tokens ERC-20. -Por outro lado, os optimistic rollups são compatíveis com a [Ethereum Virtual Machine](/developers/docs/evm/) e podem executar [contratos inteligentes](/developers/docs/smart-contracts/) nativos do Ethereum, tornando-os uma solução de dimensionamento útil e _segura_ para [aplicativos descentralizados](/developers/docs/dapps/). De maneira similar, há planos em andamento para [criar uma implementação de conhecimento-zero da EVM (zkEVM)](https://ethresear.ch/t/a-zk-evm-specification/11549) que permitiria aos ZK-rollups processar lógica arbitrária e executar contratos inteligentes. +Por outro lado, os optimistic rollups são compatíveis com a [Máquina Virtual Ethereum](/developers/docs/evm/) e podem executar [contratos inteligentes](/developers/docs/smart-contracts/) nativos do Ethereum, tornando-os uma solução útil e _segura_ para a escalabilidade de [aplicativos descentralizados](/developers/docs/dapps/). Da mesma forma, existem planos em andamento para [criar uma implementação de conhecimento zero da EVM (zkEVM)](https://ethresear.ch/t/a-zk-evm-specification/11549) que permitiria que os ZK-rollups processassem lógica arbitrária e executassem contratos inteligentes. ### Indisponibilidade de dados {#data-unavailability} @@ -142,13 +142,14 @@ De maneira similar, os optimistic rollups impõem um período de atraso em retir Plasma, sidechains e sharding são bastante semelhantes porque todos estão ligados à rede principal do Ethereum de alguma forma. No entanto, o nível e a força dessas ligações variam, o que afeta as propriedades de segurança de cada solução de dimensionamento. -### Plasma vs sidechains {#plasma-vs-sidechains} +### Plasma vs. sidechains {#plasma-vs-sidechains} -Uma [sidechain](/developers/docs/scaling/sidechains/) é uma blockchain operada de maneira independente conectado à rede principal do Ethereum através de uma bridge bidirecional. [Bridges](/bridges/) permitem que os usuários troquem tokens entre as duas blockchains para realizar transações na sidechain, reduzindo o congestionamento na rede principal do Ethereum e melhorando o dimensionamento. As sidechains usam um mecanismo separado de consenso e são normalmente muito menores do que a rede principal do Ethereum. Como resultado, fazer bridge de ativos para essas cadeias implica um maior risco. Dada a falta de garantias de segurança herdadas da rede principal do Ethereum no modelo sidechain, os usuários arriscam a perder fundos em um ataque à sidechain. +Uma [sidechain](/developers/docs/scaling/sidechains/) é uma blockchain operada de forma independente e conectada à Rede Principal do Ethereum por meio de uma ponte bidirecional. [Pontes](/bridges/) permitem que os usuários troquem tokens entre as duas blockchains para realizar transações na sidechain, reduzindo o congestionamento na Rede Principal do Ethereum e melhorando a escalabilidade. +As sidechains usam um mecanismo separado de consenso e são normalmente muito menores do que a rede principal do Ethereum. Como resultado, fazer bridge de ativos para essas cadeias implica um maior risco. Dada a falta de garantias de segurança herdadas da rede principal do Ethereum no modelo sidechain, os usuários arriscam a perder fundos em um ataque à sidechain. Inversamente, as cadeias Plasma derivam sua segurança da rede principal. Isto as torna amplamente mais seguras do que as sidechains. Tanto as cadeias de sidechains como as de Plasma podem ter diferentes protocolos de consenso, mas a diferença é que as cadeias Plasma publicam raízes Merkle para cada bloco na rede principal do Ethereum. As raízes dos blocos são pequenos pedaços de informação que podemos utilizar para verificar informações sobre as transações que acontecem em uma cadeia Plasma. Se um ataque acontecer em uma cadeia Plasma, os usuários podem retirar com segurança seus fundos de volta à rede principal usando as provas adequadas. -### Plasma vs fragmentação (sharding) {#plasma-vs-sharding} +### Plasma vs. fragmentação {#plasma-vs-sharding} Tanto as cadeias plasma quanto as cadeias de fragmentos periodicamente publicam provas criptográficas na Mainnet (Rede principal) do Ethereum. No entanto, ambas têm propriedades de segurança diferentes. @@ -156,20 +157,20 @@ As cadeias de shard gravam "cabeçalhos de agrupamento" na rede principal conten A cadeia Plasma é diferente porque a rede principal só recebe informação mínima sobre o estado das cadeias filhas. Isto significa que rede principal não pode verificar eficazmente as transações realizadas em cadeias filhas, tornando-as menos seguras. -**Observe** que fragmentar a blockchain Ethereum não está mais no roteiro. Ela foi substituída por escalabilidade via rollups e [Danksharding](/roadmap/danksharding). +**Observação**: a fragmentação da blockchain do Ethereum não está mais no planejamento. Ela foi substituída pela escalabilidade via rollups e pelo [Danksharding](/roadmap/danksharding). -### Usar a cadeia Plasma {#use-plasma} +### Usar Plasma {#use-plasma} Vários projetos fornecem implementações da cadeia Plasma que você pode integrar aos seus dapps: -- [Polygon](https://polygon.technology/) (anteriormente Matic Network) +- [Polygon](https://polygon.technology/) (anteriormente Rede Matic) ## Leitura adicional {#further-reading} -- [Aprenda sobre a cadeia Plasma](https://www.learnplasma.org/en/) -- [Um lembrete rápido do que significa "segurança compartilhada" e por que é tão importante](https://old.reddit.com/r/ethereum/comments/sgd3zt/a_quick_reminder_of_what_shared_security_means/) -- [Sidechains vs Plasma vs Sharding](https://vitalik.eth.limo/general/2019/06/12/plasma_vs_sharding.html) -- [Entenda a cadeia Plasma - parte 1: O básico](https://www.theblockcrypto.com/amp/post/10793/understanding-plasma-part-1-the-basics) -- [A vida e a morte da cadeia Plasma](https://medium.com/dragonfly-research/the-life-and-death-of-plasma-b72c6a59c5ad#) +- [Aprenda sobre Plasma](https://www.learnplasma.org/en/) +- [Um rápido lembrete do que significa "segurança compartilhada" e por que ela é tão importante](https://old.reddit.com/r/ethereum/comments/sgd3zt/a_quick_reminder_of_what_shared_security_means/) +- [Sidechains vs. Plasma vs. Sharding](https://vitalik.eth.limo/general/2019/06/12/plasma_vs_sharding.html) +- [Entendendo o Plasma, Parte 1: O Básico](https://www.theblockcrypto.com/amp/post/10793/understanding-plasma-part-1-the-basics) +- [A Vida e a Morte do Plasma](https://medium.com/dragonfly-research/the-life-and-death-of-plasma-b72c6a59c5ad#) -_Conhece um recurso da comunidade que te ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ diff --git a/public/content/translations/pt-br/developers/docs/scaling/sidechains/index.md b/public/content/translations/pt-br/developers/docs/scaling/sidechains/index.md index 540b4c07f19..7c4462c7e13 100644 --- a/public/content/translations/pt-br/developers/docs/scaling/sidechains/index.md +++ b/public/content/translations/pt-br/developers/docs/scaling/sidechains/index.md @@ -1,13 +1,13 @@ --- -title: Sidechains -description: Uma introdução às sidechains como solução de dimensionamento atualmente utilizada pela comunidade Ethereum +title: Cadeias laterais +description: "Uma introdução às sidechains como solução de dimensionamento atualmente utilizada pela comunidade Ethereum" lang: pt-br sidebarDepth: 3 --- -Uma sidechain é uma blockchain separada que se executa independente do Ethereum e está conectada à rede principal do Ethereum por uma bridge nos dois sentidos. As sidechains podem ter parâmetros de blocos separados e [algoritmos de consenso](/developers/docs/consensus-mechanisms/), que são geralmente projetados para um processamento eficiente de transações. Entretanto, usar uma sidechain tem vantagens e desvantagens, já que elas não herdam as propriedades de segurança do Ethereum. Ao contrário das [soluções de dimensionamento da camada 2](/layer-2/), as sidechains não publicam alterações no estado e dados de transação de volta à rede principal do Ethereum. +Uma sidechain é uma blockchain separada que se executa independente do Ethereum e está conectada à rede principal do Ethereum por uma bridge nos dois sentidos. As sidechains podem ter parâmetros de bloco e [algoritmos de consenso](/developers/docs/consensus-mechanisms/) separados, que são frequentemente projetados para o processamento eficiente de transações. Entretanto, usar uma sidechain tem vantagens e desvantagens, já que elas não herdam as propriedades de segurança do Ethereum. Diferentemente das [soluções de escalabilidade de camada 2](/layer-2/), as sidechains não publicam alterações de estado e dados de transação de volta para a Mainnet do Ethereum. -As sidechains também sacrificam alguma medida de descentralização ou segurança para alcançar alta vazão de dados ([trilema do dimensionamento](https://vitalik.eth.limo/general/2021/05/23/scaling.html)). O Ethereum, no entanto, comprometeu-se a dimensionar sem comprometer a descentralização e a segurança, conforme descrito na sua [declaração de visão](/roadmap/) relacionada a atualizações. +As sidechains também sacrificam um certo grau de descentralização ou segurança para alcançar um alto rendimento ([trilema da escalabilidade](https://vitalik.eth.limo/general/2021/05/23/scaling.html)). O Ethereum, no entanto, está comprometido com a escalabilidade sem comprometer a descentralização e a segurança. ## Como funcionam as sidechains? {#how-do-sidechains-work} @@ -23,38 +23,38 @@ Uma das qualidades que tornam as sidechains únicas (ou seja, diferentes do Ethe Como o Ethereum, as sidechains têm nós de validação que verificam e processam transações, produzem blocos e armazenam o estado da blockchain. Os validadores são também responsáveis por manterem o consenso em toda a rede e protegê-la contra ataques maliciosos. -#### Parâmetros do bloco {#block-parameters} +#### Parâmetros de bloco {#block-parameters} -O Ethereum coloca limites nos [tempos de bloco](/developers/docs/blocks/#block-time) (ou seja, o tempo que leva para produzir novos blocos) e os [tamanhos de blocos](/developers/docs/blocks/#block-size) (ou seja, a quantidade de dados contida por bloco denominada em gas). Inversamente, as sidechains muitas vezes adotam parâmetros diferentes, como tempos de bloco mais rápidos e limites de gás mais elevados, para alcançar altas transferências, transações rápidas e taxas baixas. +O Ethereum impõe limites aos [tempos de bloco](/developers/docs/blocks/#block-time) (ou seja, o tempo que leva para produzir novos blocos) e aos [tamanhos de bloco](/developers/docs/blocks/#block-size) (ou seja, a quantidade de dados contida por bloco, denominada em gás). Inversamente, as sidechains muitas vezes adotam parâmetros diferentes, como tempos de bloco mais rápidos e limites de gás mais elevados, para alcançar altas transferências, transações rápidas e taxas baixas. Embora isso tenha alguns benefícios, tem implicações críticas para a descentralização e segurança da rede. Parâmetros de bloco, como tempos de bloco rápidos e tamanhos grandes de blocos, aumentam a dificuldade de rodar um nó completo, deixando alguns "supernós" responsáveis pela segurança da cadeia. Em tal cenário, aumenta a possibilidade de colusão de validadores ou de uma tomada maliciosa da cadeia. -Para que as blockchains se dimensionem sem prejudicar a descentralização, executar um nó deve estar aberto a todos, e não necessariamente a terceiros com hardware especializado. É por isso que estão em curso esforços para garantir que todos possam [executar um nó completo](/developers/docs/nodes-and-clients/#why-should-i-run-an-ethereum-node) na rede Ethereum. +Para que as blockchains se dimensionem sem prejudicar a descentralização, executar um nó deve estar aberto a todos, e não necessariamente a terceiros com hardware especializado. É por isso que estão em andamento esforços para garantir que todos possam [executar um nó completo](/developers/docs/nodes-and-clients/#why-should-i-run-an-ethereum-node) na rede Ethereum. -### Compatibilidade com EVM {#evm-compatibility} +### Compatibilidade com a EVM {#evm-compatibility} -Algumas sidechains são compatíveis com EVM e podem executar contratos desenvolvidos para a [Ethereum Virtual Machine (EVM)](/developers/docs/evm/). As sidechains compatíveis com EVM suportam contratos inteligentes [escritos em Solidity](/developers/docs/smart-contracts/languages/), bem como outras linguagens de contratos inteligentes EVM, o que significa que contratos inteligentes escritos para a rede principal do Ethereum também funcionarão em sidechains compatíveis com EVM. +Algumas sidechains são compatíveis com a EVM e podem executar contratos desenvolvidos para a [Máquina Virtual do Ethereum (EVM)](/developers/docs/evm/). As sidechains compatíveis com a EVM suportam contratos inteligentes [escritos em Solidity](/developers/docs/smart-contracts/languages/), bem como outras linguagens de contratos inteligentes da EVM, o que significa que os contratos inteligentes escritos para a Mainnet do Ethereum também funcionarão em sidechains compatíveis com a EVM. -Isso significa que se você quer usar seu [dapp](/developers/docs/dapps/) na sidechain, é apenas uma questão de implantar seu [contrato inteligente](/developers/docs/smart-contracts/) nesta sidechain. A aparência e o comportamento dele se asemelham ao da rede principal. Você escreve contratos em Solidity e interage com a cadeia através da RPC da sidechain. +Isso significa que, se você quiser usar seu [dapp](/developers/docs/dapps/) em uma sidechain, basta implantar seu [contrato inteligente](/developers/docs/smart-contracts/) nessa sidechain. A aparência e o comportamento dele se asemelham ao da rede principal. Você escreve contratos em Solidity e interage com a cadeia através da RPC da sidechain. -Como as sidechains são compatíveis com EVM, elas são consideradas uma útil [solução de dimensionamento](/developers/docs/scaling/) para dapps nativos do Ethereum. Com o seu dapp em uma sidechain, os usuários podem aproveitar taxas de gás mais baixas e transações mais rápidas, especialmente se a rede principal estiver congestionada. +Como as sidechains são compatíveis com a EVM, elas são consideradas uma [solução de escalabilidade](/developers/docs/scaling/) útil para dapps nativos do Ethereum. Com o seu dapp em uma sidechain, os usuários podem aproveitar taxas de gás mais baixas e transações mais rápidas, especialmente se a rede principal estiver congestionada. No entanto, tal como foi explicado anteriormente, a utilização de uma sidechain envolve compromissos significativos. Cada sidechain é responsável pela sua segurança e não herda as propriedades de segurança do Ethereum. Isso aumenta a possibilidade de comportamentos maliciosos que possam afetar os usuários ou colocar seus fundos em risco. -### Movimento de ativos {#asset-movement} +### Movimentação de ativos {#asset-movement} -Para que uma blockchain separada se torne uma sidechain para a rede principal do Ethereum, ela precisa da capacidade de facilitar a transferência de ativos de e para a rede principal do Ethereum. Esta interoperabilidade com o Ethereum é alcançada usando uma bridge de blockchain. As [bridges](/bridges/) usam contratos inteligentes implementados na rede principal do Ethereum e uma sidechain para controlar a comunicação de fundos entre elas. +Para que uma blockchain separada se torne uma sidechain para a rede principal do Ethereum, ela precisa da capacidade de facilitar a transferência de ativos de e para a rede principal do Ethereum. Esta interoperabilidade com o Ethereum é alcançada usando uma bridge de blockchain. [As pontes](/bridges/) usam contratos inteligentes implantados na Mainnet do Ethereum e em uma sidechain para controlar a ponte de fundos entre elas. -Enquanto as bridges ajudam usuários a mover fundos entre o Ethereum e a sidechain, os ativos não são fisicamente movidos pelas duas cadeias. Em vez disso, os mecanismos que normalmente envolvem a mintagem (mint) e a queima (burn) são utilizados para transferir valor entre cadeias. Mais sobre [como as bridges funcionam](/developers/docs/bridges/#how-do-bridges-work). +Enquanto as bridges ajudam usuários a mover fundos entre o Ethereum e a sidechain, os ativos não são fisicamente movidos pelas duas cadeias. Em vez disso, os mecanismos que normalmente envolvem a mintagem (mint) e a queima (burn) são utilizados para transferir valor entre cadeias. Mais sobre [como as pontes funcionam](/developers/docs/bridges/#how-do-bridges-work). ## Prós e contras das sidechains {#pros-and-cons-of-sidechains} -| Prós | Contras | -| --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -| A tecnologia que sustenta as sidechains está bem estabelecida e se beneficia de uma pesquisa abrangente e de melhorias na concepção. | As sidechains abrem mão de alguma medida de descentralização e confiabilidade por dimensionamento. | -| As sidechains suportam computação geral e oferecem compatibilidade com EVM (elas podem executar dapps nativos do Ethereum). | Uma sidechain utiliza um mecanismo separado de consenso e não se beneficia das garantias de segurança do Ethereum. | -| As sidechains usam diferentes modelos de consenso para processar transações com eficiência e taxas de transação mais baixas para os usuários. | As sidechains requerem suposições de confiança mais elevados (por exemplo, um quórum de validadores maliciosos da sidechain pode cometer fraude). | -| As sidechains compatíveis com EVM permitem que dapps expandam seu ecossistema. | | +| Prós | Contras | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| A tecnologia que sustenta as sidechains está bem estabelecida e se beneficia de uma pesquisa abrangente e de melhorias na concepção. | As sidechains abrem mão de alguma medida de descentralização e confiabilidade por dimensionamento. | +| As sidechains suportam computação geral e oferecem compatibilidade com EVM (elas podem executar dapps nativos do Ethereum). | Uma sidechain utiliza um mecanismo separado de consenso e não se beneficia das garantias de segurança do Ethereum. | +| As sidechains usam diferentes modelos de consenso para processar transações com eficiência e taxas de transação mais baixas para os usuários. | As sidechains requerem suposições de confiança mais elevados (por exemplo, um quórum de validadores maliciosos da sidechain pode cometer fraude). | +| As sidechains compatíveis com EVM permitem que dapps expandam seu ecossistema. | | ### Usar sidechains {#use-sidechains} @@ -68,6 +68,6 @@ Vários projetos fornecem implementações da cadeia Plasma que você pode integ ## Leitura adicional {#further-reading} -- [Como dimensionar dapps do Ethereum por meio de sidechains](https://medium.com/loom-network/dappchains-scaling-ethereum-dapps-through-sidechains-f99e51fff447) _Georgios Konstantopoulos, 8 de fev., 2018 (em inglês))._ +- [Escalando dapps do Ethereum através de sidechains](https://medium.com/loom-network/dappchains-scaling-ethereum-dapps-through-sidechains-f99e51fff447) _8 de fevereiro de 2018 - Georgios Konstantopoulos_ -_Conhece algum recurso da comunidade que o ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ diff --git a/public/content/translations/pt-br/developers/docs/scaling/state-channels/index.md b/public/content/translations/pt-br/developers/docs/scaling/state-channels/index.md index c0667c73331..aab240312fa 100644 --- a/public/content/translations/pt-br/developers/docs/scaling/state-channels/index.md +++ b/public/content/translations/pt-br/developers/docs/scaling/state-channels/index.md @@ -1,71 +1,71 @@ --- title: Canais de estado -description: Uma introdução aos canais de estado e canais de pagamento como uma solução de dimensionamento atualmente utilizada pela comunidade Ethereum. +description: "Uma introdução aos canais de estado e canais de pagamento como uma solução de dimensionamento atualmente utilizada pela comunidade Ethereum." lang: pt-br sidebarDepth: 3 --- -Os canais de estado permitem que os participantes transacionem com segurança off-chain, com o mínimo de interação com a rede principal do Ethereum. Os peers do canal podem conduzir um número arbitrário de transações off-chain enquanto enviam apenas duas transações on-chain para abrir e fechar o canal. Isso permite uma taxa de transferência de transação extremamente alta e resulta em custos mais baixos para os usuários. +Os canais de estado permitem que os participantes realizem transações com segurança off-chain, com o mínimo de interação com a rede principal do Ethereum. Os pares do canal podem conduzir um número arbitrário de transações offchain, enviando apenas duas transações onchain para abrir e fechar o canal. Isso permite uma taxa de transferência de transação extremamente alta e resulta em custos mais baixos para os usuários. -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -Você deve ter lido e compreendido nossas páginas sobre [escalando o Ethereum](/developers/docs/scaling/) e [segunda camada](/layer-2/). +Você deve ter lido e entendido nossas páginas aos [Ethereum scaling](/developers/docs/scaling/) e [layer 2](/layer-2/). ## O que são canais? {#what-are-channels} -Blockchains públicas, como Ethereum, enfrentam desafios de dimensionamento devido à sua arquitetura distribuída: onde as transações on-chain devem ser executadas por todos os nós. Os nós devem ser capazes de lidar com o volume de transações em um bloco usando hardware modesto, impondo um limite na taxa de transferência da transação para manter a rede descentralizada. Os canais de blockchain resolvem esse problema permitindo que os usuários interajam off-chain enquanto ainda confiam na segurança da cadeia principal para a liquidação final. +Blockchains públicas, como Ethereum, enfrentam desafios de escalabilidade devido à sua arquitetura distribuída: transações onchain devem ser executadas por todos os nós. Os nós devem ser capazes de lidar com o volume de transações em um bloco usando hardware modesto, impondo um limite na taxa de transferência da transação para manter a rede descentralizada. Os canais de blockchain resolvem esse problema permitindo que os usuários interajam offchain enquanto ainda confiam na segurança da cadeia principal para a liquidação final. -Os canais são simples protocolos ponto a ponto que permitem que duas partes façam muitas transações entre si e depois publiquem apenas os resultados finais na blockchain. O canal usa criptografia para demonstrar que os dados de resumo gerados são realmente o resultado de um conjunto válido de transações intermediárias. Um contrato inteligente ["multisig"](/developers/docs/smart-contracts/#multisig) garante que as transações sejam assinadas pelas partes corretas. +Os canais são simples protocolos ponto a ponto que permitem que duas partes façam muitas transações entre si e depois publiquem apenas os resultados finais na blockchain. O canal usa criptografia para demonstrar que os dados de resumo gerados são realmente o resultado de um conjunto válido de transações intermediárias. Um contrato inteligente ["multisig"](/developers/docs/smart-contracts/#multisig) garante transações assinadas pelas pessoas corretas. Com os canais, as mudanças de estado são executadas e validadas pelas partes interessadas, minimizando a computação na camada de execução do Ethereum. Isso diminui o congestionamento no Ethereum e também aumenta a velocidade de processamento de transações para os usuários. -Cada canal é gerenciado por um [contrato inteligente multisig](/developers/docs/smart-contracts/#multisig) em execução no Ethereum. Para abrir um canal, os participantes implantam o contrato de canal on-chain e depositam fundos nele. Ambas as partes assinam coletivamente uma atualização de estado para inicializar o estado do canal, após o qual podem realizar transações rápidas e livres off-chain. +Cada canal é gerenciado por um [multisig smart contract](/developers/docs/smart-contracts/#multisig) no Ethereum. Para abrir um canal, os participantes implementam o contrato do canal onchain e depositam fundos nele. Ambas as partes assinam coletivamente uma atualização de estado para inicializar o estado do canal, após o qual podem realizar transações offchain de forma rápida e livre. -Para fechar o canal, os participantes submetem o último estado acordado do canal on-chain. Em seguida, o contrato inteligente distribui os fundos bloqueados de acordo com o saldo de cada participante no estado final do canal. +Para fechar o canal, os participantes enviam o último estado acordado do canal onchain. Em seguida, o contrato inteligente distribui os fundos bloqueados de acordo com o saldo de cada participante no estado final do canal. -Os canais ponto a ponto são particularmente úteis para situações em que alguns participantes predefinidos desejam realizar transações com alta frequência sem incorrer em sobrecarga visível. Os canais da blockchain se enquadram em duas categorias: **canais de pagamento** e **canais de estado**. +Os canais ponto a ponto são particularmente úteis para situações em que alguns participantes predefinidos desejam realizar transações com alta frequência sem incorrer em sobrecarga visível. Os canais de blockchain dividem-se em **payment channels** e **state channels**. -## Canais de pagamento {#payment-channels} +## Payment channels {#payment-channels} -Um canal de pagamento é melhor descrito como um "livro de duas vias" mantido coletivamente por dois usuários. O saldo inicial do livro é a soma dos depósitos bloqueados no contrato on-chain durante a fase de abertura do canal. Transferências do canal de pagamento podem ser realizadas instantaneamente e sem o envolvimento da própria blockchain, exceto a criação inicial de uma única vez on-chain e um eventual fechamento do canal. +Um canal de pagamento é melhor descrito como um "livro de duas vias" mantido coletivamente por dois usuários. O saldo inicial do livro razão é a soma dos depósitos bloqueados no contrato onchain durante a fase de abertura do canal. As transferências de canais de pagamento podem ser realizadas instantaneamente e sem o envolvimento da blockchain em si, exceto por uma criação inicial única onchain e um eventual fechamento do canal. As atualizações no saldo do livro (ou seja, o estado do canal de pagamento) requerem a aprovação de todas as partes do canal. Uma atualização de canal, assinada por todos os participantes do canal, é considerada finalizada, assim como uma transação no Ethereum. -Os canais de pagamento estavam entre as primeiras soluções de dimensionamento projetadas para minimizar atividades caras on-chain, em interações simples do usuário (por exemplo, transferências ETH, atomic swaps, micropagamentos). Os participantes do canal podem conduzir uma quantidade ilimitada de instâncias, transações sem valor entre si, desde que a soma líquida de suas transferências não exceda os tokens depositados. +Os canais de pagamento estavam entre as primeiras soluções de escalonamento projetadas para minimizar atividades onchain dispendiosas de interações simples do usuário (por exemplo, transferências de ETH, atomic swaps, micropagamentos). Os participantes do canal podem conduzir uma quantidade ilimitada de instâncias, transações sem valor entre si, desde que a soma líquida de suas transferências não exceda os tokens depositados. -## Canais de Estado {#state-channels} +## State channels {#state-channels} -Além de oferecer suporte a pagamentos off-chain, os canais de pagamento não têm se mostrado úteis para lidar com a lógica geral de transição de estado. Os canais de estado foram criados para resolver esse problema e torná-los úteis para dimensionar a computação de propósito geral. +Além de oferecer suporte a pagamentos offchain, os canais de pagamento não se mostraram úteis para lidar com a lógica geral de transição de estado. Os canais de estado foram criados para resolver esse problema e torná-los úteis para dimensionar a computação de propósito geral. Os canais de estado ainda têm muito em comum com os canais de pagamento. Por exemplo, os usuários interagem através da troca de mensagens (transações) assinadas criptograficamente, que os outros participantes do canal também devem assinar. Se uma proposta de atualização de estado não for assinada por todos os participantes, ela não será válida. No entanto, além de manter os saldos do usuário, o canal também rastreia o estado atual do armazenamento do contrato (ou seja, valores das variáveis do contrato). -Isso torna possível a execução de um contrato inteligente off-chain entre dois usuários. Nesse cenário, as atualizações para o estado interno do contrato inteligente exigem apenas a aprovação dos pares que criaram o canal. +Isso torna possível executar um contrato inteligente offchain entre dois usuários. Nesse cenário, as atualizações para o estado interno do contrato inteligente exigem apenas a aprovação dos pares que criaram o canal. -Embora isso resolva o problema de dimensionamento descrito anteriormente, tem implicações para a segurança. Na Ethereum, a validade das transições de estado no Ethereum é imposta pelo protocolo de consenso da rede. Isso torna impossível propor uma atualização inválida para o estado de um contrato inteligente ou alterar a execução do contrato inteligente. +Embora isso resolva o problema de dimensionamento descrito anteriormente, tem implicações para a segurança. No Ethereum, a validade das transições de estado é imposta pelo protocolo de consenso da rede. Isso torna impossível propor uma atualização inválida para o estado de um contrato inteligente ou alterar a execução do contrato inteligente. -Os canais de estado não têm as mesmas garantias de segurança. Até certo ponto, um canal de estado é uma versão miniatura da rede principal. Com um conjunto limitado de participantes aplicando regras, a possibilidade de comportamento malicioso (por exemplo, propondo atualizações de estado inválidas) aumenta. Canais de estado derivam sua segurança de um sistema de arbitragem de disputas baseado em [provas de fraude](/glossary/#fraud-proof). +Os canais de estado não têm as mesmas garantias de segurança. Até certo ponto, um canal de estado é uma versão miniatura da rede principal. Com um conjunto limitado de participantes aplicando regras, a possibilidade de comportamento malicioso (por exemplo, propondo atualizações de estado inválidas) aumenta. O state channels security baseia dispute arbitration system (/glossary/#fraud-proof). -## Como os canais de estado funcionam {#how-state-channels-work} +## Como os state channels funcionam {#how-state-channels-work} -Basicamente, a atividade em um canal de estado é uma sessão de interações envolvendo usuários e um sistema blockchain. Os usuários se comunicam principalmente off-chain e interagem apenas com a blockchain subjacente para abrir o canal, fechar o canal ou resolver possíveis disputas entre os participantes. +Basicamente, a atividade em um canal de estado é uma sessão de interações envolvendo usuários e um sistema blockchain. Os usuários se comunicam principalmente entre si offchain e interagem com a blockchain subjacente apenas para abrir o canal, fechar o canal ou resolver possíveis disputas entre os participantes. A seção a seguir descreve o fluxo de trabalho básico de um canal de estado: -### Abrir o canal {#opening-the-channel} +### Opening the channel {#opening-the-channel} -Abrir um canal exige que os participantes comprometam fundos a um contrato inteligente na rede principal. O depósito também funciona como uma tabulação virtual, de modo que os atores participantes podem transacionar livremente sem necessidade de liquidar os pagamentos imediatamente. Somente quando o canal estiver finalizado on-chain, as partes fazem o acerto e retiram o que corresponde a cada uma delas. +Abrir um canal exige que os participantes comprometam fundos a um contrato inteligente na rede principal. O depósito também funciona como uma tabulação virtual, de modo que os atores participantes podem transacionar livremente sem necessidade de liquidar os pagamentos imediatamente. Somente quando o canal é finalizado onchain as partes liquidam entre si e retiram o que sobrou de suas contas. Este depósito também serve como um vínculo para garantir um comportamento honesto de cada participante. Se os depositantes forem considerados culpados de ações maliciosas durante a fase de resolução de litígios, o contrato reduzirá o depósito deles. Os pares de canal devem assinar um acordo inicial, com o qual todos concordam. Isto serve como origem do canal de estado, após a qual os usuários poderão começar a realizar transações. -### Usar o canal {#using-the-channel} +### Using the channel {#using-the-channel} Depois de inicializar o estado do canal, os pares interagem assinando transações e enviando uns aos outros para aprovação. Os participantes iniciam atualizações de estado com essas transações e assinam atualizações de estados de outros. Cada transação é composta do seguinte: -- Um **nonce**, que atua como um ID único para transações e impede ataques de replay. Ele também identifica a ordem pela qual ocorreram as atualizações de estado (o que é importante para a resolução de litígios) +- **Nonce**, o ID só por transações, pode evitar replay attacks. Ele também identifica a ordem pela qual ocorreram as atualizações de estado (o que é importante para a resolução de litígios) - O estado antigo do canal @@ -73,13 +73,13 @@ Depois de inicializar o estado do canal, os pares interagem assinando transaçõ - A transação que aciona a transição de estado (por exemplo, Alice envia 5 ETH para Bob) -As atualizações de estado no canal não são transmitidas on-chain, como normalmente acontece quando os usuários interagem na rede principal, o que se alinha com o objetivo dos canais de estado de minimizar a pegada on-chain. Desde que os participantes concordem em atualizações de estado, elas são tão finais como uma transação Ethereum. Os participantes só têm de depender do consenso da rede principal se surgir uma disputa. +As atualizações de estado no canal não são transmitidas onchain, como normalmente acontece quando os usuários interagem na Mainnet, o que está alinhado com o objetivo dos canais de estado de minimizar o impacto onchain. Desde que os participantes concordem em atualizações de estado, elas são tão finais como uma transação Ethereum. Os participantes só têm de depender do consenso da rede principal se surgir uma disputa. -### Fechar o canal {#closing-the-channel} +### Closing the channel {#closing-the-channel} -Fechar um canal de estado requer o envio do estado final e acordado do canal para o contrato inteligente on-chain. Os detalhes referenciados na atualização do estado incluem o número de movimentos de cada participante e uma lista de transações aprovadas. +Para fechar um canal de estado, é necessário enviar o estado final acordado para o contrato inteligente onchain. Os detalhes referenciados na atualização do estado incluem o número de movimentos de cada participante e uma lista de transações aprovadas. -Após verificar que a atualização de estado é válida (ou seja, está assinada por todas as partes), o contrato inteligente finaliza o canal e distribui os fundos bloqueados de acordo com o resultado do canal. Pagamentos feitos off-chain são aplicados ao estado do Ethereum e cada participante recebe sua porção restante dos fundos bloqueados. +Após verificar que a atualização de estado é válida (ou seja, está assinada por todas as partes), o contrato inteligente finaliza o canal e distribui os fundos bloqueados de acordo com o resultado do canal. Os pagamentos feitos offchain são aplicados ao estado do Ethereum e cada participante recebe sua parte restante dos fundos bloqueados. O cenário descrito acima representa o que acontece caso tudo dê certo. Às vezes, os usuários podem não conseguir chegar a um acordo e finalizar o canal. Uma das seguintes poderia ser a verdadeira situação: @@ -87,87 +87,87 @@ O cenário descrito acima representa o que acontece caso tudo dê certo. Às vez - Os participantes se recusam-se a coassinar atualizações de estado válidas -- Os participantes tentam finalizar o canal propondo uma antiga atualização de estado para o contrato on-chain +- Os participantes tentam finalizar o canal propondo uma atualização de estado antiga para o contrato onchain - Os participantes propõem transições de estado inválidas para que outros assinem -Sempre que o consenso se divide entre os participantes em um canal, a última opção é contar com o consenso da rede principal para impor o estado final e válido do canal. Neste caso, o encerramento do canal de estado exige a resolução de litígios on-chain. +Sempre que o consenso se divide entre os participantes em um canal, a última opção é contar com o consenso da rede principal para impor o estado final e válido do canal. Nesse caso, fechar o canal de estado exige a resolução de disputas onchain. -### Resolução de disputas {#settling-disputes} +### Settling disputes {#settling-disputes} -Normalmente, as partes em um canal concordam em fechar o canal antecipadamente e coassinam a última transição de estado, que eles submetem ao contrato inteligente. Uma vez que a atualização é aprovada on-chain, a execução do contrato inteligente off-chain termina e os participantes saem do canal com o dinheiro deles. +Normalmente, as partes em um canal concordam em fechar o canal antecipadamente e coassinam a última transição de estado, que eles submetem ao contrato inteligente. Assim que a atualização for aprovada onchain, a execução do contrato inteligente offchain termina e os participantes saem do canal com seu dinheiro. -No entanto, uma das partes pode submeter uma solicitação on-chain para terminar a execução do contrato inteligente e finalizar o canal, sem esperar a aprovação da contraparte. Se alguma das situações de ruptura de consenso descritas anteriormente ocorrer, qualquer das partes poderá acionar o contrato on-chain para fechar o canal e distribuir fundos. Isso fornece a **não necessidade de confiança**, garantindo que partes honestas possam sair com seus depósitos a qualquer momento, independentemente das ações da outra parte. +No entanto, uma parte pode enviar uma solicitação onchain para encerrar a execução do contrato inteligente e finalizar o canal, sem esperar a aprovação da contraparte. Se ocorrer qualquer uma das situações de quebra de consenso descritas anteriormente, qualquer uma das partes pode acionar o contrato onchain para fechar o canal e distribuir os fundos. A parte mais honestada pode sair a qualquer momento. -Para processar a saída do canal, o usuário deve submeter a última atualização válida do estado do aplicativo para o contrato on-chain. Se esta verificação ocorrer (ou seja, ele tem a assinatura de todas as partes), então os fundos serão redistribuídos a seu favor. +Para processar a saída do canal, o usuário deve enviar a última atualização de estado válida do aplicativo para o contrato onchain. Se esta verificação ocorrer (ou seja, ele tem a assinatura de todas as partes), então os fundos serão redistribuídos a seu favor. -No entanto, há um atraso na execução de pedidos de saída de um único usuário. Se o pedido para concluir o canal foi aprovado unanimemente, então a transação de saída on-chain é executada imediatamente. +No entanto, há um atraso na execução de pedidos de saída de um único usuário. Se a solicitação para concluir o canal for aprovada por unanimidade, a transação de saída onchain será executada imediatamente. -O atraso entra em vigor na saída de um único usuário devido à possibilidade de ações fraudulentas. Por exemplo, um usuário do canal pode tentar finalizar o canal no Ethereum, submetendo uma atualização mais antiga do estado on-chain. +O atraso entra em vigor na saída de um único usuário devido à possibilidade de ações fraudulentas. Por exemplo, um participante do canal pode tentar finalizar o canal no Ethereum enviando uma atualização de estado mais antiga onchain. -Como contramedida, canais de estado permitem que usuários honestos desafiem atualizações de estado inválidas submetendo o mais recente estado válido do canal on-chain. Canais de estado são projetados para que as mais recentes, e acordadas, atualizações de estado vençam atualizações de estado mais antigas. +Como contramedida, os canais de estado permitem que usuários honestos contestem atualizações de estado inválidas enviando o estado mais recente e válido do canal onchain. Canais de estado são projetados para que as mais recentes, e acordadas, atualizações de estado vençam atualizações de estado mais antigas. -Uma vez que uma parte aciona o sistema de resolução de disputas on-chain, a outra parte precisa responder dentro de um limite de tempo (chamado de janela do desafio). Isso permite que os usuários desafiem a transação de saída, especialmente se a outra pessoa estiver aplicando uma atualização obsoleta. +Quando uma parte aciona o sistema de resolução de disputas onchain, a outra parte é obrigada a responder dentro de um limite de tempo (chamado de janela de desafio). Isso permite que os usuários desafiem a transação de saída, especialmente se a outra pessoa estiver aplicando uma atualização obsoleta. -Seja qual for o caso, usuários de canais sempre têm fortes garantias de finalidade: se a transição de estado em sua posse foi assinada por todos os membros e é a atualização mais recente, então tem a mesma finalidade de uma transação regular on-chain. Continuam a ter de desafiar a outra parte on-chain, mas o único resultado possível é a conclusão do último estado válido, que eles detêm. +Seja qual for o caso, os usuários do canal sempre têm fortes garantias de finalidade: se a transição de estado em sua posse foi assinada por todos os membros e é a atualização mais recente, então ela é de mesma finalidade que uma transação regular onchain. Eles ainda precisam desafiar a outra parte onchain, mas o único resultado possível é finalizar o último estado válido, que eles detêm. ### Como os canais de estado interagem com o Ethereum? {#how-do-state-channels-interact-with-ethereum} -Embora eles existam como protocolos off-chain, os canais de estado têm um componente on-chain: o contrato inteligente implantado no Ethereum ao abrir o canal. Este contrato controla os ativos depositados no canal, verifica atualizações de estado e arbitra disputas entre os participantes. +Embora existam como protocolos offchain, os canais de estado têm um componente onchain: o contrato inteligente implantado no Ethereum ao abrir o canal. Este contrato controla os ativos depositados no canal, verifica atualizações de estado e arbitra disputas entre os participantes. -Canais de estado não publicam dados de transação ou compromissos de estado na rede principal, ao contrário das soluções de dimensionamento da [camada 2](/layer-2/). No entanto, eles estão mais conectados à rede principal do que, digamos, as [sidechains](/developers/docs/scaling/sidechains/), tornando-os um pouco mais seguros. +Os State channels não mostram dados de transações ou compromissos no Mainnet, diferente da escalabilidade da [camada 2](/layer-2/). No entanto, eles estão mais conectados ao Mainnet do que, digamos, [sidechains](/developers/docs/scaling/sidechains/), o quê faz os State Channels um pouco mais seguros. As canais de estado dependem do protocolo principal do Ethereum para o seguinte: -#### 1. Vivacidade {#liveness} +#### 1. Liveness {#liveness} -O contrato on-chain implantado ao abrir o canal é responsável pela funcionalidade do canal. Se o contrato estiver em execução no Ethereum, então o canal estará sempre disponível para uso. Inversamente, uma sidechain sempre pode falhar, mesmo que a rede principal esteja operacional, colocando o dinheiro dos usuários em risco. +O contrato onchain implantado ao abrir o canal é responsável pela funcionalidade do canal. Se o contrato estiver em execução no Ethereum, então o canal estará sempre disponível para uso. Inversamente, uma sidechain sempre pode falhar, mesmo que a rede principal esteja operacional, colocando o dinheiro dos usuários em risco. #### 2. Segurança {#security} Até certo ponto, os canais de estado dependem do Ethereum para fornecer segurança e proteger usuários de pares maliciosos. Conforme discutido em outras seções, os canais usam um mecanismo de prova de fraude que permite aos usuários desafiarem tentativas de finalizar o canal com uma atualização inválida ou obsoleta. -Neste caso, a parte honesta fornece o mais recente estado válido do canal como uma prova de fraude do contrato on-chain para verificação. As provas de fraude permitem que partes mutuamente desconfiadas realizem transações off-chain sem arriscar os seus fundos no processo. +Nesse caso, a parte honesta fornece o estado válido mais recente do canal como prova de fraude ao contrato onchain para verificação. Provas de fraude permitem que partes mutuamente desconfiadas conduzam transações offchain sem arriscar seus fundos no processo. -#### 3. Finalidade {#finality} +#### 3. Finality {#finality} -Atualizações de estado assinadas coletivamente pelos usuários do canal são consideradas como boas transações on-chain. Ainda assim, toda a atividade dentro do canal só atinge a verdadeira finalidade quando o canal é fechado no Ethereum. +Atualizações de estado assinadas coletivamente pelos usuários do canal são consideradas tão boas quanto transações onchain. Ainda assim, toda a atividade dentro do canal só atinge a verdadeira finalidade quando o canal é fechado no Ethereum. -No caso otimista, ambas as partes podem cooperar e assinar a atualização final do estado e enviar on-chain para fechar o canal, após o qual os fundos são distribuídos de acordo com o estado final do canal. No caso pessimista, onde alguém tenta trapacear publicando uma atualização incorreta do estado on-chain, sua transação não é finalizada até que a janela do desafio termine. +No caso otimista, ambas as partes podem cooperar e assinar a atualização do estado final e enviar on-chain para fechar o canal, após o que os fundos são distribuídos de acordo com o estado final do canal. No caso pessimista, onde alguém tenta trapacear publicando uma atualização incorreta do estado on-chain, sua transação não é finalizada até que a janela do desafio termine. -## Canais de estado virtual {#virtual-state-channels} +## Virtual state channels {#virtual-state-channels} -A implementação ingênua de um canal de estado seria implantar um novo contrato quando dois usuários desejam executar um aplicativo off-chain. Isso não é apenas inviável, mas também anula a relação custo-benefício dos canais de estado (os custos de transação on-chain podem aumentar rapidamente). +A implementação ingênua de um canal de estado seria implantar um novo contrato quando dois usuários desejam executar um aplicativo offchain. Isso não é apenas inviável, mas também anula a relação custo-benefício dos canais de estado (os custos de transação onchain podem aumentar rapidamente). -Para resolver este problema, foram criados "canais virtuais". Ao contrário dos canais regulares que exigem transações on-chain para abrir e encerrar, um canal virtual pode ser aberto, executado e finalizado sem interagir com a cadeia principal. É até possível resolver conflitos off-chain usando esse método. +Para resolver este problema, foram criados "canais virtuais". Ao contrário dos canais regulares que exigem transações onchain para abrir e encerrar, um canal virtual pode ser aberto, executado e finalizado sem interagir com a cadeia principal. É até possível resolver disputas offchain usando esse método. -Este sistema se baseia na existência dos chamados "canais ledgers" (canais de livro razão distribuídos), que foram financiados on-chain. Canais virtuais entre duas partes podem ser construídos sobre um canal ledger existente, com o(s) proprietário(s) do canal ledger servindo como intermediário. +Este sistema depende da existência dos chamados "canais de livro razão", que foram financiados onchain. Canais virtuais entre duas partes podem ser construídos sobre um canal ledger existente, com o(s) proprietário(s) do canal ledger servindo como intermediário. Os usuários em cada canal virtual interagem por meio de uma nova instância de contrato, com o canal ledger capaz de suportar várias instâncias de contrato. O estado do canal ledger também contém mais de um estado de armazenamento de contrato, permitindo a execução paralela de aplicativos off-chain entre diferentes usuários. -Assim como os canais regulares, os usuários trocam atualizações de estado para progredir na máquina de estado. Exceto quando surge uma disputa, o intermediário só precisa ser contatado ao abrir ou encerrar o canal. +Assim como os canais regulares, os usuários trocam atualizações de estado para progredir na máquina de estado. A menos que surja uma disputa, o intermediário só precisa ser contatado ao abrir ou encerrar o canal. -### Canais de pagamento virtual {#virtual-payment-channels} +### Virtual payment channels {#virtual-payment-channels} Os canais virtuais de pagamento funcionam com a mesma ideia dos canais virtuais de estado: os participantes conectados à mesma rede podem passar mensagens sem a necessidade de abrir um novo canal on-chain. Nos canais virtuais de pagamento, as transferências de valores são roteadas por um ou mais intermediários, com a garantia de que somente o destinatário pretendido poderá receber os recursos transferidos. -## Aplicações de canais de estado {#applications-of-state-channels} +## Applications of state channels {#applications-of-state-channels} -### Pagamentos {#payments} +### Payments {#payments} Os canais de blockchain iniciais eram simples protocolos que permitiam a dois participantes realizarem transferências rápidas e de baixas taxas off-chain sem terem que pagar elevadas taxas de transação na rede principal. Hoje, os canais de pagamento ainda são úteis para os aplicativos projetados para a troca e depósitos de ether e tokens. Pagamentos baseados em canais possuem as seguintes vantagens: -1. **Taxa de transferência**: a quantidade de transações off-chain por canal não está conectada à taxa de transferência do Ethereum, que é influenciada por vários fatores, especialmente o tamanho dos blocos e tempo de bloco. Ao executar transações off-chain, os canais da blockchain podem alcançar uma taxa de transferência mais alta. +1. **Taxa de transferência**: a quantidade de transações off-chain por canal não está conectada à taxa de transferência do Ethereum, que é influenciada por vários fatores, especialmente o tamanho dos blocos e tempo de bloco. Ao executar transações offchain, os canais de blockchain podem atingir maior rendimento. -2. **Privacidade**: devido à existência de canais off-chain, os detalhes das interações entre participantes não são gravados na blockchain pública do Ethereum. Os usuários do canal só têm que interagir na on-chain quando financiam e fecham canais ou resolvem disputas. Assim, os canais são úteis para as pessoas que desejam transações mais particulares. +2. **Privacidade**: Como os canais existem offchain, os detalhes das interações entre os participantes não são registradas na blockchain pública do Ethereum. Os usuários dos canais só precisam interagir onchain quando financiam e fecham canais ou resolvem disputas. Assim, os canais são úteis para as pessoas que desejam transações mais particulares. -3. **Latência**: as transações off-chain conduzidas entre os participantes do canal podem ser resolvidas instantaneamente, se ambas as partes cooperarem, reduzindo atrasos. Em contraste, enviar uma transação para a rede principal requer esperar que os nós processem a transação, produzam um novo bloco com a transação e alcançem consenso. Os usuários podem também precisar esperar por mais confirmações de blocos antes de considerar uma transação finalizada. +3. **Latência**: transações offchain conduzidas entre os participantes do canal podem ser liquidadas instantaneamente, se ambas as partes cooperarem, reduzindo atrasos. Em contraste, enviar uma transação para a rede principal requer esperar que os nós processem a transação, produzam um novo bloco com a transação e alcançem consenso. Os usuários podem também precisar esperar por mais confirmações de blocos antes de considerar uma transação finalizada. -4. **Custo**: canais de estados são particularmente úteis em situações em que um conjunto de participantes intercambiará muitas atualizações de estado por um longo período. Os únicos custos incorridos são a abertura e o encerramento do canal de estado do contrato inteligente; cada mudança de estado entre a abertura e o encerramento do canal será mais barata do que a última, uma vez que o custo da liquidação é distribuído em conformidade. +4. **Custo**: Canais de estados são particularmente úteis em situações em que um conjunto de participantes intercambiará muitas atualizações de estado por um longo período. Os únicos custos incorridos são a abertura e o encerramento do canal de estado do contrato inteligente; cada mudança de estado entre a abertura e o encerramento do canal será mais barata do que a última, uma vez que o custo da liquidação é distribuído em conformidade. -Implementar canais de estado nas soluções de camada 2, como [rollups](/developers/docs/scaling/#rollups), poderia torná-las ainda mais atraentes para pagamentos. Embora os canais ofereçam pagamentos baratos, os custos de estabelecer o contrato on-chain na rede principal durante a fase de abertura podem ser caros, especialmente quando as taxas de gás aumentam. Os rollups baseados no Ethereum oferecem [taxas de transação mais baixas](https://l2fees.info/) e podem reduzir a sobrecarga para os participantes do canal reduzindo as taxas de configuração. +Implementar canais estado em soluções de Layer 2, como [rollups](/developers/docs/scaling/#rollups), pode torná-las ainda mais atraentes para pagamentos. Embora os canais ofereçam pagamentos baratos, os custos de estabelecer o contrato on-chain na rede principal durante a fase de abertura podem ser caros, especialmente quando as taxas de gás aumentam. Os rollups baseados em Ethereum oferecem [taxas de transação mais baixas](https://l2fees.info/) e podem reduzir as despesas gerais para os participantes do canal ao diminuir as taxas de configuração. ### Microtransações {#microtransactions} @@ -177,25 +177,25 @@ Os canais de pagamento resolvem este problema reduzindo a sobrecarga associada c Além do custo de abrir e fechar o canal, os participantes não incorrem em custos adicionais nas microtransações (sem taxas de gás). Esta é uma situação vantajosa para todos, uma vez que os clientes têm mais flexibilidade na forma como pagam os serviços, e as empresas não perdem em microtransações rentáveis. -### Aplicativos descentralizados {#decentralized-applications} +### Aplicações descentralizadas {#decentralized-applications} -Tal como os canais de pagamento, os canais de estado podem fazer pagamentos condicionais, de acordo com os estados finais da máquina de estado. Canais de estado também podem suportar lógica arbitrária de transição de estado, tornando-os úteis para executar aplicativos genéricos off-chain. +Tal como os canais de pagamento, os canais de estado podem fazer pagamentos condicionais, de acordo com os estados finais da máquina de estado. Os canais de estado também podem suportar lógica de transição de estado arbitrária, tornando-os úteis para executar aplicativos genéricos offchain. -Os canais de estado são muitas vezes limitados a simples aplicativos baseados em turnos, já que isso facilita a gestão dos fundos comprometidos com o contrato on-chain. Além disso, com um número limitado de partes atualizando o estado do aplicativo off-chain em intervalos, punir comportamentos desonestos é relativamente simples. +Os canais de estado são geralmente limitados a aplicativos simples baseados em turnos, pois isso facilita o gerenciamento de fundos dedicados ao contrato on-chain. Além disso, com um número limitado de partes atualizando o estado do aplicativo off-chain em intervalos, punir comportamentos desonestos é relativamente simples. -A eficiência de um aplicativo do canal de estado depende também do seu desenho. Por exemplo, um desenvolvedor pode implantar o contrato de canal do aplicativo on-chain uma vez e permitir que outras partes reutilizem o app sem ter que estar on-chain. Neste caso, o canal inicial do aplicativo serve como um canal do ledger que oferece suporte a vários canais virtuais, cada um executando uma nova instância do contrato inteligente off-chain. +A eficiência de um aplicativo do canal de estado depende também do seu desenho. Por exemplo, um desenvolvedor pode implantar o contrato de canal do aplicativo on-chain uma vez e permitir que outras partes reutilizem o aplicativo sem ter que estar on-chain. Nesse caso, o canal do aplicativo inicial serve como um canal de registro que dá suporte a vários canais virtuais, cada um executando uma nova instância do contrato inteligente do aplicativo off-chain. -Um caso de uso potencial para aplicativos de canal de estado sao os jogos de dois jogadores, em que os fundos são distribuídos com base no resultado do jogo. O benefício aqui é que os jogadores não têm que confiar uns nos outros (trustlessness), e o contrato on-chain, não os jogadores, controla a alocação de fundos e a resolução de litígios (descentralização). +Um caso de uso potencial para aplicativos de canal de estado sao os jogos de dois jogadores, em que os fundos são distribuídos com base no resultado do jogo. O benefício aqui é que os jogadores não precisam confiar uns nos outros (trustlessness) e o contrato on-chain, não os jogadores, controla a alocação de fundos e a resolução de disputas (descentralização). Outros possíveis casos de uso para aplicativos de canais de estado incluem propriedade de nome ENS, registros NFT e muito mais. ### Transferências atômicas {#atomic-transfers} -Os canais de pagamento iniciais eram restritos a transferências entre duas partes, limitando a sua usabilidade. No entanto, a introdução de canais virtuais permitiu que indivíduos encaminhassem transferências através de intermediários (ou seja, vários canais p2p) sem ter que abrir um novo canal on-chain. +Os canais de pagamento iniciais eram restritos a transferências entre duas partes, limitando a sua usabilidade. No entanto, a introdução de canais virtuais permitiu que indivíduos encaminhassem transferências por meio de intermediários (ou seja, vários canais p2p) sem precisar abrir um novo canal on-chain. -Comumente descrito como transferências "multi-hop", os pagamentos roteados são atômicos (ou seja, ou todas as partes da transação são realizadas de forma bem-sucedida ou ela falha completamente). As transferências atômicas usam [Hashed Timelock Contracts (HTLCs)](https://en.bitcoin.it/wiki/Hash_Time_Locked_Contracts) para garantir que o pagamento seja liberado apenas se certas condições forem atendidas, reduzindo assim o risco de contraparte. +Comumente descrito como transferências "multi-hop", os pagamentos roteados são atômicos (ou seja, ou todas as partes da transação são realizadas de forma bem-sucedida ou ela falha completamente). Transferências atômicas usam [Contratos de Bloqueio de Tempo com Hash (HTLCs)](https://en.bitcoin.it/wiki/Hash_Time_Locked_Contracts) para garantir que o pagamento seja liberado somente se certas condições forem atendidas, reduzindo assim o risco da contraparte. -## Desvantagens de se usar canais de estado {#drawbacks-of-state-channels} +## Desvantagens do uso de canais estado {#drawbacks-of-state-channels} ### Suposições de vivacidade {#liveness-assumptions} @@ -203,7 +203,7 @@ Para garantir a eficiência, os canais de estado colocam limites de tempo na cap Na realidade, os usuários podem ficar offline por razões fora do seu controle (por exemplo, má conexão de internet, falha mecânica, etc.). Se um usuário honesto fica offline, um par malicioso pode explorar a situação apresentando os antigos estados intermediários ao contrato do adjudicador e roubar os fundos comprometidos. -Alguns canais usam "watchtowers" – entidades responsáveis por acompanhar eventos de disputas on-chain em nome de outros e tomar as ações necessárias, como alertar as partes interessadas. No entanto, isso pode aumentar os custos de utilização de um canal de estado. +Alguns canais usam "torres de vigilância", entidades responsáveis ​​por monitorar eventos de disputas on-chain em nome de terceiros e tomar as medidas necessárias, como alertar as partes interessadas. No entanto, isso pode aumentar os custos de utilização de um canal de estado. ### Indisponibilidade de dados {#data-unavailability} @@ -215,29 +215,29 @@ Os usuários do Ethereum não precisam lidar com esse problema, uma vez que a re ### Problemas de liquidez {#liquidity-issues} -Para estabelecer um canal blockchain, os participantes precisam bloquear fundos em um contrato inteligente on-chain para o ciclo de vida do canal. Isto reduz a liquidez dos usuários do canal e também limita os canais para aqueles que podem arcar com os fundos bloqueados na rede principal. +Para estabelecer um canal blockchain, os participantes precisam bloquear fundos em um contrato inteligente onchain durante o ciclo de vida do canal. Isto reduz a liquidez dos usuários do canal e também limita os canais para aqueles que podem arcar com os fundos bloqueados na rede principal. -No entanto, canais do ledger, operados por um provedor de serviços off-chain (OSP), podem reduzir problemas de liquidez para os usuários. Dois pares conectados a um canal de ledger podem criar um canal virtual, que eles podem abrir e finalizar completamente off-chain, quando quiserem. +No entanto, os canais de registro, operados por um provedor de serviços off-chain (OSP), podem reduzir os problemas de liquidez para os usuários. Dois pares conectados a um canal de registro podem criar um canal virtual, que eles podem abrir e finalizar completamente off-chain, quando quiserem. -Provedores de serviço off-chain também podem abrir canais com vários pares, tornando-os úteis para encaminhar pagamentos. É claro que os utilizadores têm de pagar taxas aos OSPs pelos seus serviços, o que pode ser indesejável para alguns. +Os provedores de serviços offchain também podem abrir canais com vários pares, tornando-os úteis para rotear pagamentos. É claro que os utilizadores têm de pagar taxas aos OSPs pelos seus serviços, o que pode ser indesejável para alguns. ### Ataques de griefing {#griefing-attacks} Os ataques de griefing são uma característica comum dos sistemas baseados em provas de fraude. Um ataque de griefing não beneficia diretamente o atacante, mas causa dor (ou seja, dano) à vítima, daí o nome. -A prova de fraude é suscetível a ataques de griefing porque a parte honesta deve responder a todas as disputas, até mesmo as inválidas, ou corre o risco de perder os seus fundos. Um participante malicioso pode decidir repetidamente publicar o estado de transições on-chain, forçando a parte honesta a responder com o estado válido. O custo dessas transações on-chain pode aumentar rapidamente, fazendo com que partes honestas se percam no processo. +A prova de fraude é suscetível a ataques de griefing porque a parte honesta deve responder a todas as disputas, até mesmo as inválidas, ou corre o risco de perder os seus fundos. Um participante malicioso pode decidir postar repetidamente transições de estado onchain, forçando a parte honesta a responder com o estado válido. O custo dessas transações onchain pode aumentar rapidamente, fazendo com que as partes honestas percam no processo. ### Conjuntos de participantes predefinidos {#predefined-participant-sets} -Por desenho, o número de participantes que compõem um canal do estado permanece fixo ao longo de sua vida. Isso porque atualizar o conjunto dos participantes iria complicar a operação do canal, especialmente ao financiar o canal ou resolver conflitos. Adicionar ou remover os participantes também exigiria atividade adicional on-chain, o que aumenta a sobrecarga para os usuários. +Por desenho, o número de participantes que compõem um canal do estado permanece fixo ao longo de sua vida. Isso porque atualizar o conjunto dos participantes iria complicar a operação do canal, especialmente ao financiar o canal ou resolver conflitos. Adicionar ou remover participantes também exigiria atividade adicional na onchain, o que aumentaria a sobrecarga para os usuários. Embora isso torne os canais de estado mais fáceis de justificar, ele limita a utilidade dos desenhos de canais aos desenvolvedores de aplicativos. Isso explica parcialmente porque os canais de estado foram preteridos a favor de outras soluções de dimensionamento, como rollups. -### Processamento paralelo de transações {#parallel-transaction-processing} +### Processamento de transações paralelas {#parallel-transaction-processing} -Os participantes do canal de estado enviam atualizações de estado em turnos, e é por isso que eles funcionam melhor para aplicativos baseados em turnos (por exemplo, um jogo de xadrez com dois jogadores). Isso elimina a necessidade de lidar com atualizações de estado simultâneas e reduz o trabalho que o contrato on-chain deve fazer para punir quem publica atualizações de estado obsoletas. No entanto, um efeito colateral desse desenho é que as transações são dependentes uma das outras, aumentando a latência e diminuindo a experiência geral do usuário. +Os participantes do canal de estado enviam atualizações de estado em turnos, e é por isso que eles funcionam melhor para aplicativos baseados em turnos (por exemplo, um jogo de xadrez com dois jogadores). Isso elimina a necessidade de lidar com atualizações de estado simultâneas e reduz o trabalho que o contrato on-chain deve fazer para punir quem publica atualizações desatualizadas. No entanto, um efeito colateral desse desenho é que as transações são dependentes uma das outras, aumentando a latência e diminuindo a experiência geral do usuário. -Alguns canais de estado resolvem esse problema usando um design "full-duplex" que separa o estado off-chain em dois estados unidirecionais de estados "simplex", permitindo atualizações de estado simultâneas. Tais desenhos melhoram a taxa de transferência off-chain e diminuem os atrasos nas transações. +Alguns canais de estado resolvem esse problema usando um design "full-duplex" que separa o estado offchain em dois estados "simplex" unidirecionais, permitindo atualizações de estado simultâneas. Esses projetos melhoram o rendimento offchain e diminuem os atrasos nas transações. ## Usar canais de estado {#use-state-channels} @@ -253,9 +253,9 @@ Vários projetos fornecem implementações da cadeia Plasma que você pode integ **Canais de Estado** -- [Entendendo a camada 2](https://medium.com/l4-media/making-sense-of-ethereums-layer-2-scaling-solutions-state-channels-plasma-and-truebit-22cb40dcc2f4) _12 de fev., 2018 - Josh Stark_ -- [Canais de estado: uma explicação](https://www.jeffcoleman.ca/state-channels/) _6 de nov., 2015 - Jeff Coleman_ -- [Fundamentos dos canais de estado](https://unlock-protocol.github.io/ethhub/ethereum-roadmap/layer-2-scaling/state-channels/) _District0x_ -- [Canais de estado da blockchain: um componente de última geração](https://ieeexplore.ieee.org/document/9627997) +- [Compreendendo as soluções de escalabilidade da camada 2 do Ethereum: canais de estado, plasma e Truebit](https://medium.com/l4-media/making-sense-of-ethereums-layer-2-scaling-solutions-state-channels-plasma-and-truebit-22cb40dcc2f4) _– Josh Stark, Feb 12 2018_ +- [Estados de Canais - uma explicação](https://www.jeffcoleman.ca/state-channels/) _Nov 6, 2015 - Jeff Coleman_ +- [Noções básicas sobre Estados de Canais](https://education.district0x.io/general-topics/understanding-ethereum/basics-state-channels/) - _District0x_ +- [Estados de Canais Blockchain: Um Estado da Arte](https://ieeexplore.ieee.org/document/9627997) -_Conhece um recurso da comunidade que ajudou você? Edite essa página e adicione-o!_ \ No newline at end of file +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ diff --git a/public/content/translations/pt-br/developers/docs/scaling/validium/index.md b/public/content/translations/pt-br/developers/docs/scaling/validium/index.md index 4d27137442b..b2aa8a4da66 100644 --- a/public/content/translations/pt-br/developers/docs/scaling/validium/index.md +++ b/public/content/translations/pt-br/developers/docs/scaling/validium/index.md @@ -1,41 +1,41 @@ --- title: Validium -description: Uma introdução ao Validium como uma solução de dimensionamento atualmente utilizada pela comunidade Ethereum. +description: "Uma introdução ao Validium como uma solução de dimensionamento atualmente utilizada pela comunidade Ethereum." lang: pt-br sidebarDepth: 3 --- -Validium é uma [solução de dimensionamento](/developers/docs/scaling/) que reforça a integridade de transações usando provas de validade como [ZK-rollups](/developers/docs/scaling/zk-rollups/), mas não armazena dados de transação na rede principal do Ethereum. Embora a disponibilidade de dados off-chain introduz compromissos, ela pode levar a enormes melhorias de dimensionamento (validiums podem processar [cerca de 9.000 transações ou mais, por segundo](https://blog.matter-labs.io/zkrollup-vs-validium-starkex-5614e38bc263)). +O Validium é uma [solução de escalabilidade](/developers/docs/scaling/) que impõe a integridade das transações usando provas de validade como os [ZK-rollups](/developers/docs/scaling/zk-rollups/), mas não armazena os dados das transações na Mainnet do Ethereum. Embora a disponibilidade de dados fora da cadeia introduza alguns compromissos, ela pode levar a melhorias massivas na escalabilidade (os validiums podem processar [\~9.000 transações, ou mais, por segundo](https://blog.matter-labs.io/zkrollup-vs-validium-starkex-5614e38bc263)). ## Pré-requisitos {#prerequisites} -Você deve ler e entender mais sobre em nossa página [Dimensionamento Ethereum](/developers/docs/scaling/) e [camada 2](/layer-2). +Você deve ter lido e entendido nossa página sobre [escalabilidade do Ethereum](/developers/docs/scaling/) e [camada 2](/layer-2/). ## O que é validium? {#what-is-validium} -Validiums são soluções de dimensionamento que usam a disponibilidade de dados off-chain e computação projetadas para melhorar a taxa de transferência processando transações fora da rede principal do Ethereum. Como rollups de conhecimento zero (ZK-rollups), os validiums publicam [provas de conhecimento zero](/glossary/#zk-proof) para verificar transações off-chain no Ethereum. Isso impede transições de estado inválidas e melhora as garantias de segurança de uma cadeia validium. +Validiums são soluções de escala que usam a disponibilidade de dados off-chain e computação projetadas para melhorar a taxa de transferência processando transações fora da rede principal do Ethereum. Assim como os rollups de conhecimento zero (ZK-rollups), os validiums publicam [provas de conhecimento zero](/glossary/#zk-proof) para verificar transações fora da cadeia no Ethereum. Isso impede transições de estado inválidas e melhora as garantias de segurança de uma cadeia validium. Essas "provas de validade" podem vir na forma de ZK-SNARKs (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge) ou ZK-STARKs (Zero-Knowledge Scalable Transparent ARgument of Knowledge). Mais sobre [provas de conhecimento zero](https://consensys.net/blog/blockchain-explained/zero-knowledge-proofs-starks-vs-snarks/). -Fundos pertencentes a usuários validium são controlados por um contrato inteligente no Ethereum. Os validiums oferecem saques quase instantâneos, muito parecidos com ZK-rollups; uma vez que a prova de validade para uma solicitação de retirada tenha sido verificada na rede principal, os usuários podem retirar fundos fornecendo [provas Merkle](/developers/tutorials/merkle-proofs-for-offline-data-integrity/). A prova Merkle valida a inclusão da transação de retirada do usuário em um lote de transação verificado, permitindo o contrato on-chain processar a retirada. +Fundos pertencentes a usuários validium são controlados por um contrato inteligente no Ethereum. Os validiums oferecem saques quase instantâneos, assim como os ZK-rollups; uma vez que a prova de validade de uma solicitação de saque tenha sido verificada na Mainnet, os usuários podem sacar fundos fornecendo [provas Merkle](/developers/tutorials/merkle-proofs-for-offline-data-integrity/). A prova Merkle valida a inclusão da transação de retirada do usuário em um lote de transações verificadas, permitindo que o contrato onchain processe a retirada. -No entanto, usuários validium podem ter seus fundos congelados e retiradas restritas. Isso pode acontecer se os gerentes de disponibilidade de dados na cadeia validium retiverem dados de estado off-chain de usuários. Sem acesso a dados de transação, os usuários não podem calcular a prova de Merkle necessária para provar a propriedade de fundos e executar retiradas. +No entanto, usuários validium podem ter seus fundos congelados e retiradas restritas. Isso pode acontecer se os gerentes de disponibilidade de dados na rede validium retiverem dados de estado off-chain de usuários. Sem acesso a dados de transação, os usuários não podem calcular a prova de Merkle necessária para provar a propriedade de fundos e executar retiradas. Esta é a maior diferença entre validiums e ZK-rollups: suas posições sobre o espectro de disponibilidade de dados. Ambas as soluções abordam o armazenamento de dados de forma diferente, o que tem implicações para a segurança e a não necessidade de confiança. ## Como os validiums interagem com o Ethereum? {#how-do-validiums-interact-with-ethereum} -Validiums são protocolos de dimensionamento criados sobre a cadeia Ethereum existente. Embora execute transações off-chain, uma cadeia validium é administrada por uma coleção de contratos inteligentes implantados na rede principal, incluindo: +Validiums são protocolos de dimensionamento criados sobre a cadeia Ethereum existente. Embora execute transações off-chain, uma rede validium é administrada por uma coleção de contratos inteligentes implementados na rede principal, incluindo: -1. **Contrato verificador**: o contrato verificador verifica a validade das provas submetidas pelo operador validium ao fazer atualizações no estado. Isso inclui provas de validade que atestam a exatidão das transações off-chain e provas de disponibilidade de dados verificando a existência de dados de transações off-chain. +1. **Contrato verificador**: O contrato verificador verifica a validade das provas enviadas pelo operador do validium ao fazer atualizações de estado. Isso inclui provas de validade que atestam a exatidão das transações off-chain e provas de disponibilidade de dados verificando a existência de dados de transações off-chain. -2. **Contrato principal**: o contrato principal armazena os compromissos do estado (Merkle roots) enviados por produtores de blocos e atualiza o estado do validium, uma vez que uma prova do validium é verificada on-chain. Este contrato também processa tanto saques quanto depósitos para a cadeia validium. +2. **Contrato principal**: O contrato principal armazena compromissos de estado (raízes Merkle) enviados por produtores de bloco e atualiza o estado do validium assim que uma prova de validade for verificada na cadeia. Este contrato também processa tanto saques quanto depósitos para a cadeia validium. Validiums também dependem da principal cadeia de Ethereum para o seguinte: ### Liquidação {#settlement} -Transações executadas em um validium não podem ser totalmente confirmadas até que a cadeia pai verifique sua validade. Todos os negócios realizados em um validium devem eventualmente ser estabelecidos na rede principal. A blockchain Ethereum também fornece "garantias de liquidação" para usuários validium, o que significa que as transações off-chain não podem ser revertidas ou alteradas uma vez gravadas on-chain. +Transações executadas em um validium não podem ser totalmente confirmadas até que a cadeia pai verifique sua validade. Todos os negócios realizados em um validium devem eventualmente ser estabelecidos na rede principal. A blockchain Ethereum também fornece "garantias de liquidação" para usuários validium, o que significa que as transações off-chain não podem ser revertidas ou alteradas uma vez gravadas onchain. ### Segurança {#security} @@ -47,17 +47,17 @@ Se o contrato do verificador on-chain considerar a prova inválida, as transaç ### Transações {#transactions} -Os usuários enviam transações para o operador, um nó responsável por executar transações na cadeia de validium. Alguns validiums podem usar um único operador para executar a cadeia ou depender de um mecanismo de [prova de participação (PoS)](/developers/docs/consensus-mechanisms/pos/) para rotar os operadores. +Os usuários enviam transações para o operador, um nó responsável por executar transações na cadeia de validium. Alguns validiums podem usar um único operador para executar a cadeia ou depender de um mecanismo de [prova de participação (PoS)](/developers/docs/consensus-mechanisms/pos/) para rotacionar operadores. O operador agrega as transações em um lote e envia para um circuito de prova para testar. O circuito de prova aceita o lote de transação (e outros dados relevantes) como entradas e produz como saída uma prova de validade verificando que as operações foram executadas corretamente. -### Compromissos com o estado {#state-commitments} +### Compromissos de estado {#state-commitments} O estado do validium é em hash como uma árvore Merkle, com a raiz armazenada no contrato principal no Ethereum. A raiz de Merkle, também conhecida como a raiz do estado, atua como um compromisso criptográfico com o estado atual das contas e saldos no validium. Para executar uma atualização de estado, o operador deve calcular uma nova raiz de estado (depois de executar transações) e enviá-la ao contrato on-chain. Se a prova de validade confirmar, o estado proposto é aceito e o validium muda para a nova raiz do estado. -### Depósitos e retiradas {#deposits-and-withdrawals} +### Depósitos e saques {#deposits-and-withdrawals} Os usuários movem fundos do Ethereum para um validium depositando ETH (ou qualquer token compatível com ERC) no contrato on-chain. O contrato transmite o evento de depósito para o validium off-chain, em que o endereço do usuário é creditado com um valor igual ao seu depósito. O operador também inclui esta transação de depósito em um novo lote. @@ -69,13 +69,13 @@ Como um mecanismo anticensura, o protocolo de validium permite que os usuários Após executar um lote de transações, o operador submete a prova de validade associada ao contrato verificador e propõe uma nova raiz do estado para o contrato principal. Se a prova for válida, o contrato principal atualizará o estado do validium e finalizará os resultados das transações do lote. -Ao contrário de uma ZK-rollup, produtores de blocos em um validium não são obrigados a publicar dados de transações para transação em lotes (apenas cabeçalhos do bloco). Isso faz do validium um protocolo de dimensionamento puramenteoff-chain, ao contrário de protocolos de dimensionamento "híbridos" (ou seja, [camada 2](/layer-2/)) que publicam dados de estado na cadeia principal do Ethereum como `calldata`. +Ao contrário de uma ZK-rollup, produtores de blocos em um validium não são obrigados a publicar dados de transações para transação em lotes (apenas cabeçalhos do bloco). Isso torna o validium um protocolo de escalabilidade puramente fora da cadeia, em oposição aos protocolos de escalabilidade "híbridos" (ou seja, [camada 2](/layer-2/)) que publicam dados de estado na cadeia principal do Ethereum usando dados blob, `calldata` ou uma combinação de ambos. ### Disponibilidade de dados {#data-availability} -Como mencionado, os validiums atuais utilizam um modelo de disponibilidade de dados off-chain em que os operadores armazenam todos os dados de transação fora da rede principal do Ethereum. A baixa pegada de dados on-chain do validium melhora o dimensionamento (a transferência não é limitada pela capacidade de processamento de dados do Ethereum) e reduz as taxas de usuário (o custo de publicação de `calldata` é menor). +Como mencionado, os validiums utilizam um modelo de disponibilidade de dados off-chain em que os operadores armazenam todos os dados de transação fora da rede principal do Ethereum. A baixa pegada de dados onchain do validium melhora o dimensionamento (a transferência não é limitada pela capacidade de processamento de dados do Ethereum) e reduz as taxas de usuário (o custo de publicação de calldata é menor). -No entanto, a disponibilidade de dados off-chain apresenta um problema: os dados necessários para a criação ou verificação de provas Merkle podem estar indisponíveis. Isto significa que os utilizadores poderão não conseguir retirar fundos do contrato on-chain se os operadores agirem de forma maliciosa. +No entanto, a disponibilidade de dados off-chain apresenta um problema: os dados necessários para a criação ou verificação de provas Merkle podem estar indisponíveis. Isto significa que os usuários podem não conseguir retirar fundos do contrato on-chain se os operadores agirem de forma maliciosa. Várias soluções validium tentam resolver este problema descentralizando o armazenamento de dados do estado. Isso envolve forçar os produtores de blocos a enviar os dados subjacentes a "gerentes de disponibilidade de dados" responsáveis por armazenar dados off-chain e disponibilizá-los aos usuários a pedido. @@ -87,17 +87,17 @@ Validiums diferem em sua abordagem da gestão da disponibilidade de dados. Algun Para garantir a disponibilidade de dados off-chain, algumas soluções validium nomeiam um grupo de entidades confiáveis, coletivamente conhecido como um comitê de disponibilidade de dados (DAC), para armazenar cópias do estado e fornecer uma prova de disponibilidade de dados. Os DACs são mais fáceis de implementar e exigem menos coordenação, uma vez que a adesão é baixa. -No entanto, os usuários devem confiar no DAC para disponibilizar os dados quando necessário (por exemplo, para a geração de provas de Merkle). Existe a possibilidade de membros dos comitês de disponibilidade de dados [serem comprometidos por um ator malicioso](https://notes.ethereum.org/DD7GyItYQ02d0ax_X-UbWg?view) que pode então reter dados off-chain. +No entanto, os usuários devem confiar no DAC para disponibilizar os dados quando necessário (por exemplo, para a geração de provas de Merkle). Existe a possibilidade de membros dos comitês de disponibilidade de dados [serem comprometidos por um agente malicioso](https://notes.ethereum.org/DD7GyItYQ02d0ax_X-UbWg?view) que pode então reter os dados fora da cadeia. -[Mais sobre comissões de disponibilidade de dados em validiums](https://medium.com/starkware/data-availability-e5564c416424). +[Mais sobre comitês de disponibilidade de dados em validiums](https://medium.com/starkware/data-availability-e5564c416424). -#### Disponibilidade de dados vinculados {#bonded-data-availability} +#### Disponibilidade de dados por vínculo {#bonded-data-availability} Outros validiums exigem que os participantes sejam cobrados com o armazenamento de dados offline para fazer staking (ou seja, bloquear) tokens em um contrato inteligente antes de assumir suas funções. Este stake serve como uma "obrigação" para garantir um comportamento honesto entre os gerentes de disponibilidade de dados e reduzir as suposições de confiança. Se esses participantes não conseguirem provar a disponibilidade de dados, o vínculo será reduzido. -Em um esquema de disponibilidade de dados vinculado, qualquer um pode ser atribuído para armazenar dados off-chain assim que eles fornecem o stake necessário. Isto expande o pool de gestores de disponibilidade de dados elegíveis, reduzindo a centralização que afeta os comitês de disponibilidade de dados (DAC). Mais importante, essa abordagem depende de incentivos criptoeconômicos para evitar atividade maliciosa, que é consideravelmente mais seguro do que a nomeação de partes de confiança para proteger dados offline no validium. +Em um esquema de disponibilidade de dados vinculados, qualquer um pode ser atribuído para armazenar dados off-chain assim que eles fornecerem o stake necessário. Isto expande o pool de gestores de disponibilidade de dados elegíveis, reduzindo a centralização que afeta os comitês de disponibilidade de dados (DAC). Mais importante, essa abordagem depende de incentivos criptoeconômicos para evitar atividade maliciosa, que é consideravelmente mais seguro do que a nomeação de partes de confiança para proteger dados offline no validium. -[Mais sobre a disponibilidade de dados vinculados em validiums](https://blog.matter-labs.io/zkporter-a-breakthrough-in-l2-scaling-ed5e48842fbf). +[Mais sobre disponibilidade de dados por vínculo em validiums](https://blog.matter-labs.io/zkporter-a-breakthrough-in-l2-scaling-ed5e48842fbf). ## Volitions e validium {#volitions-and-validium} @@ -107,51 +107,51 @@ Volitions combinam um ZK-rollup e uma cadeia validium e permitem que os usuário Uma exchange descentralizada (DEX) pode preferir usar uma infraestrutura validium dimensionável e particular para negociações de alto valor. Também pode usar uma ZK-rollup para usuários que queiram maiores garantias de segurança e sem necessidade de confiança de um ZK-rollup. -## Validiums e compatibilidade com EVM {#validiums-and-evm-compatibility} +## Validiums e compatibilidade com a EVM {#validiums-and-evm-compatibility} -Como os ZK-rollups, os validiums são geralmente adequados a aplicativos simples, como swaps de tokens e pagamentos. É difícil oferecer suporte à computação geral e à execução do contrato inteligente entre validiums, dada a sobrecarga considerável de provar instruções [EVM](/developers/docs/evm/) em um circuito de prova de conhecimento zero. +Como os ZK-rollups, os validiums são geralmente adequados a aplicativos simples, como swaps de tokens e pagamentos. Suportar computação geral e execução de contratos inteligentes entre validiums é difícil de implementar, dada a sobrecarga considerável de provar instruções da [EVM](/developers/docs/evm/) em um circuito de prova de conhecimento zero. Alguns projetos de validium tentam contornar este problema compilando linguagens compatíveis com EVM (por exemplo, Solidity, Vyper) para criar bytecode personalizado otimizado para uma prova eficiente. Uma desvantagem desta abordagem é que novas VMs amigáveis a conhecimento zero podem não suportar importantes opcodes EVM, e os desenvolvedores devem escrever diretamente na linguagem geral para uma experiência ideal. Isso cria ainda mais problemas: força os desenvolvedores a desenvolver dapps com uma pilha de desenvolvimento inteiramente nova e quebra a compatibilidade com a atual infraestrutura do Ethereum. -Algumas equipes, no entanto, estão tentando otimizar opcodes de EVM existentes para os circuitos de prova ZK. Isto resultará no desenvolvimento de uma Máquina Virtual Ethereum de conhecimento zero (zkEVM), uma VM compatível com EVM que produz provas para verificar a exatidão da execução do programa. Com um zkEVM, as cadeias de validium podem executar contratos inteligentes off-chain e submeter provas de validade para verificar uma computação off-chain (sem ter que executá-lo novamente) no Ethereum. +Algumas equipes, no entanto, estão tentando otimizar opcodes de EVM existentes para os circuitos de prova ZK. Isto resultará no desenvolvimento de uma Máquina Virtual Ethereum de conhecimento zero (zkEVM), uma VM compatível com EVM que produz provas para verificar a exatidão da execução do programa. Com um zkEVM, as redes de validium podem executar contratos inteligentes off-chain e submeter provas de validade para verificar uma computação off-chain (sem ter que executá-lo novamente) no Ethereum. [Mais sobre zkEVMs](https://www.alchemy.com/overviews/zkevm). ## Como os validiums dimensionam o Ethereum? {#scaling-ethereum-with-validiums} -### 1. Armazenamento de dados off-chain {#off-chain-data-storage} +### 1. Armazenamento de dados fora da cadeia {#offchain-data-storage} -Projetos de dimensionamento de camada 2, como optimistic rollups e ZK-rollups, negociam o dimensionamento infinito de protocolos de dimensionamento off-chain puros (por exemplo, [Plasma](/developers/docs/scaling/plasma/)) para fins de segurança, publicando alguns dados de transação na L1. Mas isso significa que as propriedades de dimensionamento dos rollups são limitadas pela largura de banda na Mainnet (Rede principal) do Ethereum (a [fragmentação (sharding) de dados](/roadmap/danksharding/) propõe melhorar a capacidade de armazenamento de dados do Ethereum por este motivo). +Projetos de escalabilidade de camada 2, como optimistic rollups e ZK-rollups, trocam a escalabilidade infinita de protocolos de escalabilidade puramente fora da cadeia (por exemplo, [Plasma](/developers/docs/scaling/plasma/)) por segurança, publicando alguns dados de transação na L1. Mas isso significa que as propriedades de escalabilidade dos rollups são limitadas pela largura de banda de dados na Mainnet do Ethereum (a [fragmentação de dados](/roadmap/danksharding/) propõe melhorar a capacidade de armazenamento de dados do Ethereum por esse motivo). -Os validiums alcançam o dimensionamento mantendo todos os dados de transação off-chain e apenas publicando compromissos do estado (e provas de validade) ao transmitir atualizações de estado para a cadeia principal do Ethereum. A existência de provas de validade, no entanto, dá aos validiums garantias de segurança mais elevadas do que outras soluções de dimensionamento off-chain puras, incluindo Plasma e [sidechains](/developers/docs/scaling/sidechains/). Ao reduzir a quantidade de dados que o Ethereum precisa processar antes de validar transações off-chain, os desenhos de validiums estendem muito a taxa de transferência na rede principal. +Os validiums alcançam escalabilidade mantendo todos os dados de transação off-chain e apenas publicando compromissos do estado (e provas de validade) ao transmitir atualizações de estado para a rede principal do Ethereum. A existência de provas de validade, no entanto, dá aos validiums garantias de segurança mais altas do que outras soluções de escalabilidade puramente fora da cadeia, incluindo Plasma e [sidechains](/developers/docs/scaling/sidechains/). Ao reduzir a quantidade de dados que o Ethereum precisa processar antes de validar transações off-chain, os projetos de validium aumentam muito a taxa de transferência na Mainnet. ### 2. Provas recursivas {#recursive-proofs} Uma prova recursiva é uma prova de validade que verifica a validade de outras provas. Essas "prova de provas" são geradas recursivamente agregando várias provas até que uma última prova que verifica todas as provas anteriores seja criada. As provas recursivas aumentam a velocidade de processamento da blockchain aumentando o número de transações que podem ser verificadas por prova de validade. -Normalmente, cada prova de validade que o operador validium submete para o Ethereum para verificação valida a integridade de um único bloco. Uma única prova recursiva pode ser usada para confirmar a validade de vários blocos validium ao mesmo tempo, e isso é possível porque o circuito de prova pode recursivamente agregar várias provas de bloco em uma prova final. Se o contrato do verificador on-chain aceitar a prova recursiva, todos os blocos subjacentes serão finalizados imediatamente. +Normalmente, cada prova de validade que o operador validium submete para o Ethereum para verificação valida a integridade de um único bloco. Uma única prova recursiva pode ser usada para confirmar a validade de vários blocos validium ao mesmo tempo, e isso é possível porque o circuito de prova pode recursivamente agregar várias provas de bloco em uma prova final. Se o contrato verificador on-chain aceitar a prova recursiva, todos os blocos subjacentes serão finalizados imediatamente. ## Prós e contras do validium {#pros-and-cons-of-validium} -| Prós | Contras | -| ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Provas de validade reforçam a integridade das transações off-chain e impedem que os operadores finalizem atualizações de estado inválidas. | Produzir provas de validade requer hardware especial, o que representa um risco de centralização. | -| Aumenta a eficiência do capital para os usuários (sem atrasos na retirada dos fundos para o Ethereum) | Suporte limitado para computação geral/contratos inteligentes; linguagens especializadas necessárias para desenvolvimento. | -| Não vulnerável a certos ataques econômicos enfrentados por sistemas baseados em fraudes em aplicativos de elevado valor. | Alto poder computacional necessário para gerar provas ZK; a relação custo-benefício não é vantajosa para aplicativos de baixa taxa de transmissão. | +| Prós | Desvantagens | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Provas de validade reforçam a integridade das transações off-chain e impedem que os operadores finalizem atualizações de estado inválidas. | Produzir provas de validade requer hardware especial, o que representa um risco de centralização. | +| Aumenta a eficiência do capital para os usuários (sem atrasos na retirada dos fundos para o Ethereum) | Suporte limitado para computação geral/contratos inteligentes; linguagens especializadas necessárias para desenvolvimento. | +| Não vulnerável a certos ataques econômicos enfrentados por sistemas baseados em fraudes em aplicativos de elevado valor. | Alto poder computacional necessário para gerar provas ZK; a relação custo-benefício não é vantajosa para aplicativos de baixa taxa de transmissão. | | Reduz as taxas de gás para os usuários ao não publicar calldata para a rede principal do Ethereum. | Tempo de finalidade subjetiva mais lento (de 10 a 30 minutos para gerar uma prova de ZK), porém mais rápido para a finalidade completa porque não há nenhum atraso no tempo de disputas. | -| Adequado para casos de uso específicos, como trading ou jogos de blockchain que priorizam a privacidade de transações e o dimensionamento. | Os usuários podem ser impedidos de sacar fundos já que a geração de provas de propriedade Merkle requer que dados off-chain estejam disponíveis em todos os momentos. | -| A disponibilidade de dados off-chain fornece níveis mais elevados de transferência e aumenta o dimensionamento. | O modelo de segurança se baseia em suposições de confiança e incentivos criptoeconômicos, ao contrário dos ZK-rollups, que dependem apenas de mecanismos de segurança criptográficos. | +| Adequado para casos de uso específicos, como trading ou jogos de blockchain que priorizam a privacidade de transações e o dimensionamento. | Usuários podem ser impedidos de sacar fundos já que a geração de provas de propriedade Merkle requer que dados off-chain estejam disponíveis em todos os momentos. | +| A disponibilidade de dados off-chain fornece níveis mais elevados de transferência e aumenta a escalabilidade. | O modelo de segurança se baseia em suposições de confiança e incentivos criptoeconômicos, ao contrário dos ZK-rollups, que dependem apenas de mecanismos de segurança criptográficos. | -### Uso de validium/volitions {#use-validium-and-volitions} +### Use Validium/Volitions {#use-validium-and-volitions} Vários projetos fornecem implementações de validium e volitions que você pode integrar aos seus dapps: -**StarkWare StarkEx**: _StarkEx é uma solução de dimensionamento de camada 2 (L2) do Ethereum que é baseada em provas de validade. Pode operar em modos de disponibilidade de dados ZK-Rollup ou Validium._ +**StarkWare StarkEx** - _StarkEx é uma solução de escalabilidade de camada 2 (L2) do Ethereum que se baseia em provas de validade. Pode operar em modos de disponibilidade de dados ZK-Rollup ou Validium._ - [Documentação](https://docs.starkware.co/starkex-v4/starkex-deep-dive/data-availability-modes#validium) - [Website](https://starkware.co/starkex/) -**Matter Labs zkPorter**: _zkPorter é um protocolo de dimensionamento de camada 2 que aborda a disponibilidade de dados com uma abordagem híbrida que combina os conceitos de zkRollup e sharding. Pode suportar arbitrariamente muitos shards, cada um com sua própria política de disponibilidade de dados._ +**Matter Labs zkPorter**- _O zkPorter é um protocolo de escalabilidade de camada 2 que lida com a disponibilidade de dados com uma abordagem híbrida que combina as ideias de zkRollup e fragmentação. Pode suportar arbitrariamente muitos shards, cada um com sua própria política de disponibilidade de dados._ - [Blog](https://blog.matter-labs.io/zkporter-a-breakthrough-in-l2-scaling-ed5e48842fbf) - [Documentação](https://docs.zksync.io/zksync-protocol/rollup/data-availability) @@ -159,7 +159,8 @@ Vários projetos fornecem implementações de validium e volitions que você pod ## Leitura adicional {#further-reading} -- [Validium e a camada 2 juntos – Edição nº 99](https://www.buildblockchain.tech/newsletter/issues/no-99-validium-and-the-layer-2-two-by-two) -- [ZK-rollups vs Validium](https://blog.matter-labs.io/zkrollup-vs-validium-starkex-5614e38bc263) +- [Validium e a Camada 2 Dois por Dois — Edição nº 99](https://www.buildblockchain.tech/newsletter/issues/no-99-validium-and-the-layer-2-two-by-two) +- [ZK-rollups vs. Validium](https://blog.matter-labs.io/zkrollup-vs-validium-starkex-5614e38bc263) - [Volition e o espectro emergente de disponibilidade de dados](https://medium.com/starkware/volition-and-the-emerging-data-availability-spectrum-87e8bfa09bb) -- [Rollups, Validiums, e Volitions: aprenda sobre as soluções de dimensionamento mais recentes do Ethereum](https://medium.com/coinmonks/rollups-vs-validiums-vs-volitions-d76300170f4a) +- [Rollups, Validiums e Volitions: aprenda sobre as soluções de escalabilidade mais populares do Ethereum](https://www.defipulse.com/blog/rollups-validiums-and-volitions-learn-about-the-hottest-ethereum-scaling-solutions) +- [O Guia Prático para Rollups da Ethereum](https://web.archive.org/web/20241108192208/https://research.2077.xyz/the-practical-guide-to-ethereum-rollups) diff --git a/public/content/translations/pt-br/developers/docs/scaling/zk-rollups/index.md b/public/content/translations/pt-br/developers/docs/scaling/zk-rollups/index.md index d63c9e7b62d..1d06c87e684 100644 --- a/public/content/translations/pt-br/developers/docs/scaling/zk-rollups/index.md +++ b/public/content/translations/pt-br/developers/docs/scaling/zk-rollups/index.md @@ -1,46 +1,46 @@ --- title: Rollups de conhecimento zero -description: 'Uma introdução aos rollups de zero conhecimento: uma solução de dimensionamento usada pela comunidade Ethereum.' +description: "Uma introdução aos rollups de zero conhecimento: uma solução de dimensionamento usada pela comunidade Ethereum." lang: pt-br --- -Rollups de conhecimento zero (ZK-rollups) são [soluções de dimensionamento](/developers/docs/scaling/) de camada 2 que aumentam a vazão na rede principal do Ethereum movendo off-chain a computação e o armazenamento do estado. ZK-rollups podem processar milhares de transações em um lote e logo publicar apenas alguns dados mínimos resumidos para a rede principal. Este resumo de dados define as alterações que devem ser feitas ao estado do Ethereum e algumas provas criptográficas de que essas alterações estão corretas. +Rollups de conhecimento zero (ZK-rollups) são [soluções de escalabilidade](/developers/docs/scaling/) de camada 2 que aumentam a taxa de transferência na Rede Principal do Ethereum ao mover a computação e o armazenamento de estado para fora da cadeia. ZK-rollups podem processar milhares de transações em um lote e logo publicar apenas alguns dados mínimos resumidos para a rede principal. Este resumo de dados define as alterações que devem ser feitas ao estado do Ethereum e algumas provas criptográficas de que essas alterações estão corretas. -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -Você deve ler e entender mais sobre em nossa página [Ethereum scaling](/developers/docs/scaling/) e [camada 2](/layer-2). +Você deve ter lido e entendido nossa página sobre [escalabilidade do Ethereum](/developers/docs/scaling/) e [camada 2](/layer-2). ## O que são rollups de conhecimento zero? {#what-are-zk-rollups} -**Rollups de conhecimento zero (ZK-rollups)** agrupam (ou acumulam) transações em lotes que são executados off-chain. A computação off-chain reduz a quantidade de dados que devem ser publicados na blockchain. Operadores de ZK-rollups submetem um resumo das mudanças necessárias para representar todas as transações em um lote, ao invés de enviar cada transação individualmente. Eles também produzem [provas de validade](/glossary/#validity-proof) para provar a exatidão de suas mudanças. +**Rollups de conhecimento zero (ZK-rollups)** agrupam (ou 'enrolam') transações em lotes que são executados fora da cadeia. A computação offchain reduz a quantidade de dados que precisam ser postados na blockchain. Operadores de ZK-rollups submetem um resumo das mudanças necessárias para representar todas as transações em um lote, ao invés de enviar cada transação individualmente. Eles também produzem [provas de validade](/glossary/#validity-proof) para provar a correção de suas alterações. -O estado dos ZK-rollups é mantido por um contrato inteligente implantado na rede Ethereum. Para atualizar este estado, os nós ZK-rollup devem enviar uma prova de validade para verificação. Como mencionado, a prova de validade é uma garantia criptográfica de que a mudança de estado proposta pelo rollup é realmente o resultado da execução de um determinado lote de transações. Isso significa que os ZK-rollups só precisam fornecer provas de validade para finalizar as transações no Ethereum, em vez de publicar todos os dados da transação on-chain, como [optimistic rollups](/developers/docs/scaling/optimistic-rollups/). +O estado dos ZK-rollups é mantido por um contrato inteligente implantado na rede Ethereum. Para atualizar este estado, os nós ZK-rollup devem enviar uma prova de validade para verificação. Como mencionado, a prova de validade é uma garantia criptográfica de que a mudança de estado proposta pelo rollup é realmente o resultado da execução de um determinado lote de transações. Isso significa que os ZK-rollups só precisam fornecer provas de validade para finalizar as transações no Ethereum, em vez de publicar todos os dados da transação na cadeia, como os [optimistic rollups](/developers/docs/scaling/optimistic-rollups/). -Não há atrasos ao mover fundos de um ZK-rollup para o Ethereum porque as transações de saída são executadas assim que o contrato de ZK-rollup verifica a prova de validade. Inversamente, sacar fundos dos optimistic rollups está sujeito a um atraso para permitir que qualquer pessoa desafie a transação de saída com uma [prova de fraude](/glossary/#fraud-proof). +Não há atrasos ao mover fundos de um ZK-rollup para o Ethereum porque as transações de saída são executadas assim que o contrato de ZK-rollup verifica a prova de validade. Por outro lado, a retirada de fundos de optimistic rollups está sujeita a um atraso para permitir que qualquer pessoa conteste a transação de saída com uma [prova de fraude](/glossary/#fraud-proof). -ZK-rollups escrevem transações para o Ethereum como `calldata`. `calldata` é onde os dados incluídos em chamadas externas para funções de contrato inteligente ficam armazenados. As informações em `calldata` são publicadas na blockchain, permitindo que qualquer pessoa reconstrua o estado do rollup de forma independente. ZK-rollups utilizam técnicas de compactação para reduzir os dados de transação – por exemplo, as contas são representadas por um índice ao invés de um endereço, o que economiza 28 bytes de dados. A publicação de dados on-chain é um custo significativo para os rollups, de modo que a compressão de dados pode reduzir as tarifas para os usuários. +Os ZK-rollups gravam as transações no Ethereum como `calldata`. `calldata` é onde os dados incluídos em chamadas externas para as funções de contratos inteligentes são armazenados. As informações em `calldata` são publicadas na blockchain, permitindo que qualquer pessoa reconstrua o estado do rollup de forma independente. ZK-rollups utilizam técnicas de compactação para reduzir os dados de transação – por exemplo, as contas são representadas por um índice ao invés de um endereço, o que economiza 28 bytes de dados. A publicação de dados onchain é um custo significativo para rollups, portanto a compactação de dados pode reduzir as taxas para os usuários. ## Como os ZK-rollups interagem com o Ethereum? {#zk-rollups-and-ethereum} -Uma cadeia ZK-rollup é um protocolo off-chain que opera no topo da blockchain Ethereum e é gerenciado por contratos inteligentes on-chain no Ethereum. ZK-rollups executam transações fora da rede principal, mas periodicamente comprometem lotes de transações off-chain para um contrato de rollup on-chain. Este registro de transação é imutável, muito parecido com a blockchain Ethereum e forma a cadeia ZK-rollup. +Uma cadeia ZK-rollup é um protocolo offchain que opera sobre a blockchain Ethereum e é gerenciado por contratos inteligentes onchain Ethereum. Os ZK-rollups executam transações fora da Mainnet, mas periodicamente comprometem lotes de transações offchain com um contrato de rollup onchain. Este registro de transação é imutável, muito parecido com a blockchain Ethereum e forma a cadeia ZK-rollup. A arquitetura principal do ZK-rollup é composta dos seguintes componentes: -1. **Contratos on-chain**: conforme mencionado, o protocolo ZK-rollup é controlado por contratos inteligentes em execução no Ethereum. Isto inclui o contrato principal que armazena os blocos de rollup, rastreia os depósitos e monitora as atualizações de estado. Outro contrato on-chain (o contrato verificador) verifica as provas de conhecimento zero submetidas pelos produtores de blocos. Assim, o Ethereum serve como camada base ou "camada 1" para o ZK-rollup. +1. **Contratos na cadeia**: como mencionado, o protocolo ZK-rollup é controlado por contratos inteligentes executados no Ethereum. Isto inclui o contrato principal que armazena os blocos de rollup, rastreia os depósitos e monitora as atualizações de estado. Outro contrato onchain (o contrato verificador) verifica provas de conhecimento zero enviadas pelos produtores de blocos. Assim, o Ethereum serve como camada base ou "camada 1" para o ZK-rollup. -2. **Máquina virtual (VM) off-chain**: embora o protocolo ZK-rollup resida no Ethereum, a execução da transação e o armazenamento de estado ocorrem em uma máquina virtual separada, independente da [EVM](/developers/docs/evm/). Essa VM off-chain é o ambiente de execução para transações no ZK-rollup e serve como camada secundária ou "camada 2" para o protocolo ZK-rollup. As provas de validade verificadas na rede principal do Ethereum garantem a exatidão das transições de estado na VM off-chain. +2. **Máquina virtual fora da cadeia (VM)**: embora o protocolo ZK-rollup resida no Ethereum, a execução da transação e o armazenamento de estado acontecem em uma máquina virtual separada, independente da [EVM](/developers/docs/evm/). Esta VM offchain é o ambiente de execução para transações no ZK-rollup e serve como camada secundária ou "layer 2" para o protocolo ZK-rollup. Provas de validade verificadas na Mainnet Ethereum garantem a correção das transições de estado na VM offchain. -ZK-rollups são "soluções de dimensionemento híbrido", protocolos off-chain que operam de forma independente, mas obtêm segurança do Ethereum. Especificamente, a rede Ethereum impõe a validade das atualizações de estado no rollup ZK e garante a disponibilidade de dados por trás de cada atualização do estado do rollup. Como resultado, os ZK-rollups são consideravelmente mais seguros do que as soluções de dimensionamento fora da cadeia puras, tais como [sidechains](/developers/docs/scaling/sidechains/), que são responsáveis por suas propriedades de segurança, ou [validiums](/developers/docs/scaling/validium/), que também verificam transações no Ethereum com provas de validade, mas armazenam dados de transações em outro lugar. +ZK-rollups são "soluções de escalonamento híbrido" — protocolos offchain que operam de forma independente, mas obtêm segurança do Ethereum. Especificamente, a rede Ethereum impõe a validade das atualizações de estado no rollup ZK e garante a disponibilidade de dados por trás de cada atualização do estado do rollup. Como resultado, os ZK-rollups são consideravelmente mais seguros do que as soluções de escalabilidade puramente fora da cadeia, como as [sidechains](/developers/docs/scaling/sidechains/), que são responsáveis por suas próprias propriedades de segurança, ou os [validiums](/developers/docs/scaling/validium/), que também verificam transações no Ethereum com provas de validade, mas armazenam os dados das transações em outro lugar. ZK-rollups dependem do protocolo Ethereum principal para o seguinte: ### Disponibilidade de dados {#data-availability} -Os ZK-rollups publicam dados de estado para cada transação processada off-chain para o Ethereum. Com esses dados, é possível que indivíduos ou empresas reproduzam o estado do rollup e validem a cadeia por conta própria. O Ethereum disponibiliza esses dados para todos os participantes da rede como `calldata`. +Os ZK-rollups publicam dados de estado para cada transação processada offchain no Ethereum. Com esses dados, é possível que indivíduos ou empresas reproduzam o estado do rollup e validem a cadeia por conta própria. O Ethereum disponibiliza esses dados para todos os participantes da rede como `calldata`. -Os ZK-rollups não precisam publicar muitos dados de transação on-chain porque as provas de validade já verificam a autenticidade das transições de estado. No entanto, o armazenamento de dados on-chain ainda é importante porque permite a verificação independente e sem permissão do estado da cadeia L2 que, por sua vez, permite que qualquer pessoa envie lotes de transações, evitando que operadores maliciosos censurem ou congelem a cadeia. +Os ZK-rollups não precisam publicar muitos dados de transações na onchain porque as provas de validade já verificam a autenticidade das transições de estado. No entanto, armazenar dados na cadeia ainda é importante porque permite a verificação independente e sem permissão do estado da cadeia L2, o que, por sua vez, permite que qualquer pessoa envie lotes de transações, impedindo que operadores mal-intencionados censurem ou congelem a cadeia. -A cadeia on-chain é necessária para que os usuários interajam com o rollup. Sem acesso aos dados do estado, os usuários não podem consultar o saldo de sua conta ou iniciar transações (por exemplo, retiradas) que dependem de informações do estado. +O Onchain é necessário para que os usuários interajam com o rollup. Sem acesso aos dados do estado, os usuários não podem consultar o saldo de sua conta ou iniciar transações (por exemplo, retiradas) que dependem de informações do estado. ### Finalidade da transação {#transaction-finality} @@ -58,37 +58,37 @@ Como medida de segurança, os ZK-rollups permitem que os usuários enviem transa Os usuários do ZK-rollup assinam as transações e submetem aos operadores L2 para processamento e inclusão no próximo lote. Em alguns casos, o operador é uma entidade centralizada, chamada de sequenciador, que executa as transações, as agrega em lotes e envia ao L1. O sequenciador neste sistema é a única entidade autorizada a produzir blocos L2 e adicionar transações rollup ao contrato ZK-rollup. -Outros ZK-rollups podem alternar a função do operador usando um conjunto de validadores de [prova de participação](/developers/docs/consensus-mechanisms/pos/). Os operadores potenciais depositam fundos no contrato de rollup, com o tamanho de cada participação influenciando as chances do participante ser selecionado para produzir o próximo lote de rollup. A participação do operador pode ser reduzida se ele agir maliciosamente, o que o incentiva a publicar blocos válidos. +Outros ZK-rollups podem alternar a função de operador usando um conjunto de validadores de [prova de participação](/developers/docs/consensus-mechanisms/pos/). Os operadores potenciais depositam fundos no contrato de rollup, com o tamanho de cada participação influenciando as chances do participante ser selecionado para produzir o próximo lote de rollup. A participação do operador pode ser reduzida se ele agir maliciosamente, o que o incentiva a publicar blocos válidos. -#### Como os ZK-rollups publica dados de transações no Ethereum {#how-zk-rollups-publish-transaction-data-on-ethereum} +#### Como os ZK-rollups publicam dados de transação no Ethereum {#how-zk-rollups-publish-transaction-data-on-ethereum} -Como explicado, os dados de transações são publicados no Ethereum como `calldata`. `calldata` é uma área de dados em um contrato inteligente usado para passar argumentos para uma função e se comporta de forma semelhante à [memória](/developers/docs/smart-contracts/anatomy/#memory). Embora `calldata` não seja armazenado como parte do estado do Ethereum, ele persiste on-chain como parte do [histórico de logs](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html?highlight=memory#logs) da cadeia Ethereum. `calldata` não afeta o estado do Ethereum, o que a torna uma maneira barata de armazenar dados on-chain. +Conforme explicado, os dados da transação são publicados no Ethereum como `calldata`. `calldata` é uma área de dados em um contrato inteligente usada para passar argumentos para uma função e se comporta de forma semelhante à [memória](/developers/docs/smart-contracts/anatomy/#memory). Embora o `calldata` não seja armazenado como parte do estado do Ethereum, ele persiste na cadeia como parte dos [registros de histórico](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html?highlight=memory#logs) da cadeia Ethereum. O `calldata` não afeta o estado do Ethereum, tornando-o uma forma barata de armazenar dados na cadeia. -A palavra-chave `calldata` muitas vezes identifica o método do contrato inteligente sendo chamado por uma transação e contém entradas para o método na forma de uma sequência arbitrária de bytes. ZK-rollups usam `calldata` para publicar dados de transação compactados on-chain; o operador de rollup simplesmente adiciona um novo lote chamando a função requerida no contrato de rollup e passa os dados compactados como argumentos de função. Isto ajuda a reduzir os custos para os usuários, uma vez que uma grande parte das taxas de rollup vai para o armazenamento de dados de transações on-chain. +A palavra-chave `calldata` geralmente identifica o método do contrato inteligente que está sendo chamado por uma transação e contém as entradas para o método na forma de uma sequência arbitrária de bytes. Os ZK-rollups usam `calldata` para publicar dados de transação compactados na cadeia; o operador do rollup simplesmente adiciona um novo lote chamando a função necessária no contrato do rollup e passa os dados compactados como argumentos de função. Isso ajuda a reduzir custos para os usuários, já que uma grande parte das taxas de rollup é destinada ao armazenamento de dados de transações onchain. -### Compromissos com o estado {#state-commitments} +### Compromissos de estado {#state-commitments} -O estado do ZK-rollup, que inclui contas e saldos L2, é representado como uma [árvore Merkle](/whitepaper/#merkle-trees). Um hash criptográfico da raiz da árvore Merkle (raiz Merkle) é armazenado no contrato on-chain, permitindo que o protocolo de rollup rastreie alterações no estado do ZK-rollup. +O estado do ZK-rollup, que inclui contas e saldos da L2, é representado como uma [árvore de Merkle](/whitepaper/#merkle-trees). Um hash criptográfico da raiz da árvore Merkle (raiz Merkle) é armazenado no contrato onchain, permitindo que o protocolo rollup rastreie mudanças no estado do ZK-rollup. -O rollup passa para um novo estado após a execução de um novo conjunto de transações. O operador que iniciou a transição de estado é obrigado a calcular uma nova raiz de estado e se submeter ao contrato on-chain. Se a prova de validade associada ao lote for autenticada pelo contrato do verificador, a nova raiz Merkle se tornará a raiz do estado canônico do ZK-rollup. +O rollup passa para um novo estado após a execução de um novo conjunto de transações. O operador que iniciou a transição de estado deve calcular uma nova raiz de estado e enviá-la ao contrato onchain. Se a prova de validade associada ao lote for autenticada pelo contrato do verificador, a nova raiz Merkle se tornará a raiz do estado canônico do ZK-rollup. -Além de calcular as raízes de estado, o operador ZK-rollup também cria uma raiz de lote, a raiz de uma árvore Merkle que compreende todas as transações em um lote. Quando um novo lote é enviado, o contrato de rollup armazena a raiz do lote, permitindo que os usuários comprovem que uma transação (por exemplo, uma solicitação de saque) foi incluída no lote. Os usuários terão que fornecer detalhes da transação, a raiz do lote e uma [prova de Merkle](/developers/tutorials/merkle-proofs-for-offline-data-integrity/) mostrando o caminho de inclusão. +Além de calcular as raízes de estado, o operador ZK-rollup também cria uma raiz de lote, a raiz de uma árvore Merkle que compreende todas as transações em um lote. Quando um novo lote é enviado, o contrato de rollup armazena a raiz do lote, permitindo que os usuários comprovem que uma transação (por exemplo, uma solicitação de saque) foi incluída no lote. Os usuários terão que fornecer detalhes da transação, a raiz do lote e uma [prova de Merkle](/developers/tutorials/merkle-proofs-for-offline-data-integrity/) mostrando o caminho da inclusão. -### Prova de validação {#validity-proofs} +### Provas de validade {#validity-proofs} -A nova raiz de estado que o operador ZK-rollup submete ao contrato L1 é o resultado de atualizações no estado do rollup. Digamos que Alice envie 10 tokens para Bob, o operador simplesmente diminui o saldo de Alice em 10 e incrementa o saldo de Bob em 10. O operador então calcula o hash dos dados atualizados da conta, reconstrói a árvore Merkle do rollup e envia a nova raiz Merkle para o contrato on-chain. +A nova raiz de estado que o operador ZK-rollup submete ao contrato L1 é o resultado de atualizações no estado do rollup. Digamos que Alice envie 10 tokens para Bob, o operador simplesmente diminui o saldo de Alice em 10 e incrementa o saldo de Bob em 10. O operador então faz o hash dos dados atualizados da conta, reconstrói a árvore Merkle do rollup e envia a nova raiz Merkle para o contrato onchain. Mas o contrato de rollup não aceitará automaticamente o compromisso de estado proposto até que o operador prove que a nova raiz Merkle resultou de atualizações corretas no estado do rollup. O operador ZK-rollup faz isso produzindo uma prova de validade, um compromisso criptográfico sucinto que verifica a exatidão das transações em lote. -As provas de validade permitem que as partes provem a exatidão de uma declaração sem revelar a declaração em si – portanto, também são chamadas de provas de conhecimento zero. ZK-rollups usam provas de validade para confirmar a exatidão das transições de estado off-chain sem ter que executar novamente transações no Ethereum. Essas provas podem vir na forma de um [ZK-SNARK](https://arxiv.org/abs/2202.06877) (Argumento de Conhecimento Suncinto e Não Interativo de Conhecimento Zero) ou [ZK-STARK](https://eprint.iacr.org/2018/046) (Argumento de Conhecimento Transparente e Dimensionável de Conhecimento Zero). +As provas de validade permitem que as partes provem a exatidão de uma declaração sem revelar a declaração em si – portanto, também são chamadas de provas de conhecimento zero. Os ZK-rollups usam provas de validade para confirmar a correção das transições de estado offchain sem precisar reexecutar transações no Ethereum. Essas provas podem vir na forma de um [ZK-SNARK](https://arxiv.org/abs/2202.06877) (Argumento de Conhecimento Sucinto e Não Interativo de Conhecimento Zero) ou [ZK-STARK](https://eprint.iacr.org/2018/046) (Argumento de Conhecimento Transparente e Escalável de Conhecimento Zero). -Ambos SNARKs e STARKs ajudam a atestar a integridade da computação off-chain em ZK-rollups, embora cada tipo de prova tenha características distintas. +Tanto SNARKs quanto STARKs ajudam a atestar a integridade da computação offchain em ZK-rollups, embora cada tipo de prova tenha características distintas. **ZK-SNARKs** Para que o protocolo ZK-SNARK funcione, é necessário criar um Texto de Referência Comum (CRS, pela sigla em inglês): o CRS fornece parâmetros públicos para provar e verificar as provas de validade. A segurança do sistema de provas depende da configuração do CRS; se as informações usadas para criar parâmetros públicos caírem na posse de atores mal-intencionados, eles poderão gerar falsas provas de validade. -Alguns ZK-rollups tentam resolver esse problema usando uma [cerimônia de computação multipartidária (MPC)](https://zkproof.org/2021/06/30/setup-ceremonies/amp/), envolvendo pessoas de confiança, para gerar parâmetros públicos para o circuito ZK-SNARK. Cada parte contribui com alguma aleatoriedade (chamada de "lixo tóxico") para a construção do CRS, que deve ser destruída imediatamente. +Alguns ZK-rollups tentam resolver esse problema usando uma [cerimônia de computação multipartidária (MPC)](https://zkproof.org/2021/06/30/setup-ceremonies/amp/), envolvendo indivíduos de confiança, para gerar parâmetros públicos para o circuito ZK-SNARK. Cada parte contribui com alguma aleatoriedade (chamada de "lixo tóxico") para a construção do CRS, que deve ser destruída imediatamente. As configurações confiáveis são usadas porque aumentam a segurança da configuração do CRS. Desde que um participante honesto destrua sua entrada, a segurança do sistema ZK-SNARK é garantida. Ainda assim, esta abordagem requer a confiança dos envolvidos para eliminar suas amostras aleatórias e não prejudicar as garantias de segurança do sistema. @@ -96,11 +96,11 @@ Suposições de confiança à parte, ZK-SNARKs são populares por seus tamanhos **ZK-STARKs** -Como os ZK-SNARKs, os ZK-STARKs provam a validade da computação off-chain sem revelar as entradas. No entanto, os ZK-STARKs são considerados uma melhoria nos ZK-SNARKs devido a seu dimensionamento e transparência. +Assim como os ZK-SNARKs, os ZK-STARKs comprovam a validade da computação offchain sem revelar as entradas. No entanto, os ZK-STARKs são considerados uma melhoria nos ZK-SNARKs devido a seu dimensionamento e transparência. Os ZK-STARKs são "transparentes", pois podem funcionar sem a configuração confiável de um CRS. Em vez disso, os ZK-STARKs dependem da aleatoriedade verificável publicamente para estabelecer parâmetros de geração e verificação de provas. -Os ZK-STARKs também fornecem mais dimensionamento porque o tempo necessário para provar e verificar as provas de validade aumenta _quase linearmente_ em relação à complexidade da computação subjacente. Com ZK-SNARKs, os tempos de prova e verificação dimensionam _linearmente_ em relação ao tamanho da computação subjacente. Isso significa que os ZK-STARKs requerem menos tempo do que os ZK-SNARKs para provar e verificar quando grandes conjuntos de dados estão envolvidos, tornando-os úteis para aplicativos de alto volume. +Os ZK-STARKs também fornecem mais escalabilidade porque o tempo necessário para provar e verificar as provas de validade aumenta _quasilinearmente_ em relação à complexidade da computação subjacente. Com ZK-SNARKs, os tempos de prova e verificação escalam _linearmente_ em relação ao tamanho da computação subjacente. Isso significa que os ZK-STARKs requerem menos tempo do que os ZK-SNARKs para provar e verificar quando grandes conjuntos de dados estão envolvidos, tornando-os úteis para aplicativos de alto volume. Os ZK-STARKs também são seguros contra computadores quânticos, enquanto a Criptografia de Curva Elíptica (ECC, pela sigla em inglês) usada em ZK-SNARKs é amplamente considerada suscetível a ataques de computação quântica. A desvantagem dos ZK-STARKs é que eles produzem tamanhos de prova maiores, que são mais caros de verificar no Ethereum. @@ -136,13 +136,13 @@ O circuito de comprovação do ZK itera sobre todo o lote de transações, verif Após o circuito de prova verificar a correção das atualizações do estado, o operador L2 apresenta a prova de validade computada ao contrato do verificador em L1. O circuito de verificação do contrato verifica a validade das provas e também confere as entradas públicas que fazem parte da prova: -- **Raiz pré-estado**: o antigo estado raiz do ZK-rollup (ou seja, antes das transações em lote serem executadas), refletindo o último estado válido conhecido da cadeia L2. +- **Raiz do pré-estado**: a raiz de estado antiga do ZK-rollup (ou seja, antes que as transações em lote fossem executadas), refletindo o último estado válido conhecido da cadeia L2. -- **Raiz pós-estado**: o novo estado raiz do ZK-rollup (ou seja, após a execução de transações em lote), refletindo o estado mais recente da cadeia L2. A raiz pós-estado é a raiz final derivada após a aplicação de atualizações de estado no circuito de prova. +- **Raiz do pós-estado**: a nova raiz de estado do ZK-rollup (ou seja, após a execução de transações em lote), refletindo o estado mais recente da cadeia L2. A raiz pós-estado é a raiz final derivada após a aplicação de atualizações de estado no circuito de prova. -- **Raiz do lote**: a raiz Merkle do lote, derivada pela _aplicação da raiz de Merkle_ em transações no lote e pelo hash da raiz da árvore. +- **Raiz do lote**: a raiz de Merkle do lote, derivada da _merklização_ das transações no lote e da aplicação de hash na raiz da árvore. -- **Entradas de transação**: dados associados com as transações executadas como parte do lote enviado. +- **Entradas de transação**: dados associados às transações executadas como parte do lote enviado. Se a prova satisfaz o circuito (ou seja, é válida), significa que existe uma sequência de transações válidas que fazem a transição do rollup do estado anterior (impressões digitais criptográficas na raiz do pré-estado) para um novo estado (impressões digitais criptográficas na raiz do pós-estado). Se a raiz pré-estado corresponder à raiz armazenada no contrato de rollup e a prova for válida, o contrato de rollup obterá a raiz pós-estado da prova e atualizará sua árvore de estado para refletir o estado alterado do rollup. @@ -152,7 +152,7 @@ Os usuários entram no ZK-rollup depositando tokens no contrato de rollup implan Se a fila de depósitos pendentes começar a encher, o operador do ZK-rollup receberá as transações de depósito e as enviará ao contrato de rollup. Uma vez que os fundos do usuário estejam no rollup, eles podem começar a fazer transações enviando-as para o operador para processamento. Os usuários podem verificar saldos no rollup fazendo o hash de seus dados de conta, enviando o hash para o contrato de rollup e fornecendo uma prova Merkle para verificar a raiz do estado atual. -A retirada de um ZK-rollup para L1 é simples. O usuário inicia a transação de saída enviando seus ativos no rollup para uma conta específica para gravação. Se o operador incluir a transação no próximo lote, o usuário poderá enviar uma solicitação de retirada para o contrato on-chain. Este pedido de retirada incluirá o seguinte: +A retirada de um ZK-rollup para L1 é simples. O usuário inicia a transação de saída enviando seus ativos no rollup para uma conta específica para gravação. Se o operador incluir a transação no próximo lote, o usuário poderá enviar uma solicitação de retirada para o contrato onchain. Este pedido de retirada incluirá o seguinte: - Prova de Merkle provando a inclusão da transação do usuário na conta burn em um lote de transação @@ -164,11 +164,11 @@ A retirada de um ZK-rollup para L1 é simples. O usuário inicia a transação d O contrato de rollup faz o hash dos dados da transação, verifica se a raiz do lote existe e usa a prova de Merkle para verificar se o hash da transação faz parte da raiz do lote. Em seguida, o contrato executa a transação de saída e envia os fundos para o endereço escolhido pelo usuário na L1. -## Compatibilidade de ZK-rollups e EVM {#zk-rollups-and-evm-compatibility} +## ZK-rollups e compatibilidade com a EVM {#zk-rollups-and-evm-compatibility} -Ao contrário dos optimistic rollups, os ZK-rollups não são prontamente compatíveis com a [Máquina Virtual Ethereum (EVM)](/developers/docs/evm/). Provar o cálculo EVM de propósito geral em circuitos é mais difícil e intensivo em recursos do que provar cálculos simples (como a transferência simbólica descrita anteriormente). +Diferentemente dos optimistic rollups, os ZK-rollups não são diretamente compatíveis com a [Máquina Virtual Ethereum (EVM)](/developers/docs/evm/). Provar o cálculo EVM de propósito geral em circuitos é mais difícil e intensivo em recursos do que provar cálculos simples (como a transferência simbólica descrita anteriormente). -No entanto, [avanços na tecnologia de conhecimento zero](https://hackmd.io/@yezhang/S1_KMMbGt#Why-possible-now) estão despertando um interesse renovado em envolver a computação EVM em provas de conhecimento zero. Esses esforços são voltados para a criação de uma implementação EVM de conhecimento zero (zkEVM) que pode verificar com eficiência a exatidão da execução do programa. Um zkEVM recria opcodes EVM existentes para prova/verificação em circuitos, permitindo a execução de contratos inteligentes. +No entanto, os [avanços na tecnologia de conhecimento zero](https://hackmd.io/@yezhang/S1_KMMbGt#Why-possible-now) estão despertando um interesse renovado em encapsular a computação da EVM em provas de conhecimento zero. Esses esforços são voltados para a criação de uma implementação EVM de conhecimento zero (zkEVM) que pode verificar com eficiência a exatidão da execução do programa. Um zkEVM recria opcodes EVM existentes para prova/verificação em circuitos, permitindo a execução de contratos inteligentes. Como a EVM, um zkEVM transita entre os estados depois que a computação é executada em algumas entradas. A diferença é que o zkEVM também cria provas de conhecimento zero para verificar a exatidão de cada etapa da execução do programa. As provas de validade podem verificar a exatidão das operações que afetam o estado da VM (memória, pilha, armazenamento) e a própria computação (ou seja, a operação chamou os opcodes corretos e os executou corretamente?). @@ -178,21 +178,21 @@ A introdução de ZK-rollups compatíveis é esperado para ajudar os desenvolved O valor que os usuários pagam pelas transações em ZK-rollups depende da taxa de gás, assim como na rede principal do Ethereum. No entanto, as taxas de gás funcionam de maneira diferente na L2 e são influenciadas pelos seguintes custos: -1. **Gravação de estado**: há um custo fixo para gravar no estado do Ethereum (ou seja, enviar uma transação na blockchain Ethereum). Os ZK-rollups reduzem esse custo agrupando as transações e distribuindo os custos fixos entre vários usuários. +1. **Gravação de estado**: há um custo fixo para gravar no estado do Ethereum (ou seja, enviar uma transação na blockchain do Ethereum). Os ZK-rollups reduzem esse custo agrupando as transações e distribuindo os custos fixos entre vários usuários. -2. **Publicação de dados**: os ZK-rollups publicam dados de estado para cada transação no Ethereum como `calldata`. Os custos de `calldata` são atualmente regidos por [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), que estipula um custo de 16 gás para bytes diferentes de zero e 4 gás para zero bytes de `calldata`, respectivamente. O custo pago em cada transação é influenciado pela quantidade de `calldata` que precisa ser publicada na cadeia para isso. +2. **Publicação de dados**: os ZK-rollups publicam dados de estado de cada transação no Ethereum como `calldata`. Os custos de `calldata` são atualmente regidos pelo [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), que estipula um custo de 16 de gás para bytes diferentes de zero e 4 de gás para bytes zero de `calldata`, respectivamente. O custo pago em cada transação é influenciado pela quantidade de `calldata` que precisa ser postada na cadeia para ela. -3. **Taxas do operador L2**: este é o valor pago ao operador de rollup como compensação pelos custos computacionais incorridos no processamento de transações, muito parecido com ["taxas de prioridade (gorjetas)" de transação](/developers/docs/gas/#how-are-gas-fees-calculated) na rede principal do Ethereum. +3. **Taxas do operador L2**: este é o valor pago ao operador do rollup como compensação pelos custos computacionais incorridos no processamento de transações, muito semelhante às ["taxas de prioridade (gorjetas)" de transação](/developers/docs/gas/#how-are-gas-fees-calculated) na Rede Principal do Ethereum. -4. **Geração e verificação de provas**: os operadores de ZK-rollup devem produzir provas de validade para lotes de transações, que consomem muitos recursos. A verificação de provas de conhecimento zero na rede principal também custa gás (cerca de 500.000 gás). +4. **Geração e verificação de provas**: os operadores de ZK-rollup devem produzir provas de validade para lotes de transações, o que consome muitos recursos. A verificação de provas de conhecimento zero na rede principal também custa gás (cerca de 500.000 gás). -Além de transações em lote, os ZK-rollups reduzem as taxas para os usuários compactando os dados da transação. Veja um [panorama geral e em tempo real](https://l2fees.info/) de quanto custa usar ZK-rollups Ethereum. +Além de transações em lote, os ZK-rollups reduzem as taxas para os usuários compactando os dados da transação. Você pode [ver uma visão geral em tempo real](https://l2fees.info/) de quanto custa usar os ZK-rollups da Ethereum. ## De que maneira os ZK-rollups ajudam no dimensionamento do Ethereum? {#scaling-ethereum-with-zk-rollups} -### Compactação de dados da transação {#transaction-data-compression} +### Compressão de dados de transação {#transaction-data-compression} -Os ZK-rollups estendem a taxa de transferência na camada base do Ethereum, movendo a computação off-chain, mas o verdadeiro impulso para o dimensionamento vem da compactação dos dados da transação. O [tamanho do bloco](/developers/docs/blocks/#block-size) do Ethereum limita os dados que cada bloco pode conter e, por extensão, o número de transações processadas por bloco. Ao compactar os dados relacionados às transações, os ZK-rollups aumentam significativamente o número de transações processadas por bloco. +Os ZK-rollups estendem a taxa de transferência na camada base do Ethereum ao levar a computação para offchain, mas o verdadeiro impulso para o dimensionamento vem da compactação dos dados de transação. O [tamanho do bloco](/developers/docs/blocks/#block-size) do Ethereum limita a quantidade de dados que cada bloco pode conter e, por extensão, o número de transações processadas por bloco. Ao compactar os dados relacionados às transações, os ZK-rollups aumentam significativamente o número de transações processadas por bloco. Os ZK-rollups podem compactar melhor os dados das transações do que osoptimistic rollups, uma vez que não têm que publicar todos os dados necessários para validar cada transação. Eles só têm que publicar os dados mínimos necessários para reconstruir o estado mais recente das contas e saldos no rollup. @@ -204,19 +204,19 @@ Atualmente, as provas de validade são geradas bloco a bloco e submetidas ao con As provas recursivas, no entanto, permitem finalizar vários blocos com uma prova de validade. Isto porque o circuito de prova agrega recursivamente várias provas de blocos até que uma prova final seja criada. O operador L2 envia esta prova recursiva, e se o contrato aceitar, todos os blocos relevantes serão finalizados instantaneamente. Com provas recursivas, aumenta o número de transações de ZK-rollup que podem ser finalizadas no Ethereum em intervalos. -### Prós e contras de ZK-rollups {#zk-rollups-pros-and-cons} +### Prós e contras dos ZK-rollups {#zk-rollups-pros-and-cons} -| Prós | Contras | -| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| As provas de validade garantem a exatidão das transações off-chain e impedem que os operadores executem transições de estado inválido. | O custo associado à computação e verificação de provas de validade é substancial e pode aumentar as taxas para usuários de rollup. | -| Oferece uma conclusão mais rápida da transação, como as atualizações de estado são aprovadas assim que as provas de validade são verificadas em L1. | Construir ZK-rollups compatíveis com EVM é difícil devido à complexidade da tecnologia de conhecimento zero. | -| Baseia-se em mecanismos criptográficos não confiáveis para segurança, não na honestidade de atores incentivados como acontece com os [optimistic rollups](/developers/docs/scaling/optimistic-rollups/#optimistic-pros-and-cons). | Produzir provas de validade requer hardware especializado, o que pode encorajar o controle centralizado da cadeia por algumas partes. | -| Armazena os dados necessários para recuperar o estado off-chain na L1, o que garante segurança, resistência à censura e descentralização. | Operadores centralizados (sequenciadores) podem influenciar a ordem das transações. | -| Os usuários se beneficiam de uma maior eficiência de capital e podem retirar fundos da L2 sem atrasos. | Os requisitos de hardware podem reduzir o número de participantes que podem forçar a cadeia a progredir, aumentando o risco de operadores maliciosos congelarem o estado do rollup e censurarem os usuários. | -| Não depende de suposições de vivacidade, e os usuários não têm que validar a cadeia para proteger seus fundos. | Alguns sistemas de prova (por exemplo, ZK-SNARK) requerem uma configuração confiável, o que, se mal conduzida, pode comprometer o modelo de segurança de um ZK-rollup. | -| Uma melhor compactação de dados pode ajudar a reduzir os custos de publicação de `calldata` no Ethereum e minimizar as taxas de rollup para os usuários. | | +| Prós | Contras | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Provas de validade garantem a correção de transações off-chain e impedem que operadores executem transições de estado inválidas. | O custo associado à computação e verificação de provas de validade é substancial e pode aumentar as taxas para usuários de rollup. | +| Oferece uma conclusão mais rápida da transação, como as atualizações de estado são aprovadas assim que as provas de validade são verificadas em L1. | Construir ZK-rollups compatíveis com EVM é difícil devido à complexidade da tecnologia de conhecimento zero. | +| Baseia-se em mecanismos criptográficos que não exigem confiança para segurança, não na honestidade de atores incentivados como nos [optimistic rollups](/developers/docs/scaling/optimistic-rollups/#optimistic-pros-and-cons). | Produzir provas de validade requer hardware especializado, o que pode encorajar o controle centralizado da cadeia por algumas partes. | +| Armazena dados necessários para recuperar o estado off-chain em L1, o que garante segurança, resistência à censura e descentralização. | Operadores centralizados (sequenciadores) podem influenciar a ordem das transações. | +| Os usuários se beneficiam de uma maior eficiência de capital e podem retirar fundos da L2 sem atrasos. | Os requisitos de hardware podem reduzir o número de participantes que podem forçar a cadeia a progredir, aumentando o risco de operadores maliciosos congelarem o estado do rollup e censurarem os usuários. | +| Não depende de suposições de vivacidade, e os usuários não têm que validar a cadeia para proteger seus fundos. | Alguns sistemas de prova (por exemplo, ZK-SNARK) requerem uma configuração confiável, o que, se mal conduzida, pode comprometer o modelo de segurança de um ZK-rollup. | +| Uma melhor compressão de dados pode ajudar a reduzir os custos de publicação de `calldata` no Ethereum e minimizar as taxas de rollup para os usuários. | | -### Uma explicação visual de ZK-rollups {#zk-video} +### Uma explicação visual dos ZK-rollups {#zk-video} Assista ao Finematics explicando ZK-rollups: @@ -226,28 +226,32 @@ Assista ao Finematics explicando ZK-rollups: Os projetos que trabalham em zkEVMs incluem: -- **[zkEVM](https://github.com/privacy-scaling-explorations/zkevm-specs)** - _zkEVM é um projeto financiado pela Ethereum Foundation para desenvolver um ZK-rollup compatível com EVM e um mecanismo para gerar provas de validação para blocos Ethereum._ +- **[zkEVM](https://github.com/privacy-scaling-explorations/zkevm-specs)** - _O zkEVM é um projeto financiado pela Ethereum Foundation para desenvolver um ZK-rollup compatível com a EVM e um mecanismo para gerar provas de validade para os blocos do Ethereum._ -- **[Polygon zkEVM](https://polygon.technology/solutions/polygon-zkevm)** — _é um ZK-Rollup descentralizado na rede principal do Ethereum que trabalha em uma Máquina Virtual Ethereum de conhecimento zero (zkEVM) e executa transações do Ethereum de maneira transparente, incluindo contratos inteligentes com validações de prova de conhecimento._ +- **[Polygon zkEVM](https://polygon.technology/solutions/polygon-zkevm)** - _é um ZK-Rollup descentralizado na rede principal do Ethereum que funciona em uma Máquina Virtual Ethereum de conhecimento zero (zkEVM) que executa transações do Ethereum de forma transparente, incluindo contratos inteligentes com validações de prova de conhecimento zero._ -- **[Scroll](https://scroll.io/blog/zkEVM)** - _Scroll é uma empresa impulsionada pela tecnologia que trabalha no desenvolvimento de uma solução nativa zkEVM de camada 2 para Ethereum._ +- **[Scroll](https://scroll.io/blog/zkEVM)** - _A Scroll é uma empresa de tecnologia que trabalha na construção de uma solução nativa zkEVM de Camada 2 para o Ethereum._ -- **[Taiko](https://taiko.xyz)** - _Taiko é um ZK-rollup descentralizado, equivalente ao Ethereum (um [ZK-EVM do Tipo 1](https://vitalik.eth.limo/general/2022/08/04/zkevm.html))._ +- **[Taiko](https://taiko.xyz)** - _Taiko é um ZK-rollup descentralizado e equivalente ao Ethereum (um [ZK-EVM Tipo 1](https://vitalik.eth.limo/general/2022/08/04/zkevm.html))._ -- **[ZKsync](https://docs.zksync.io/)** - _ZKsync Era é um ZK Rollup compatível com EVM criado pela Matter Labs, com tecnologia do zkEVM da própria empresa._ +- **[ZKsync](https://docs.zksync.io/)** - _O ZKsync Era é um ZK-Rollup compatível com EVM construído pela Matter Labs, alimentado por seu próprio zkEVM._ -- **[Starknet](https://starkware.co/starknet/)** - _StarkNet é uma solução de dimensionamento de camada 2 compatível com EVM desenvolvida pela StarkWare._ +- **[Starknet](https://starkware.co/starknet/)** - _StarkNet é uma solução de escalabilidade de camada 2 compatível com EVM, construída pela StarkWare._ -- **[Morph](https://www.morphl2.io/)** - _Morph é uma solução de dimensionamento de rollup híbrida que utiliza zk-proof para resolver o problema do desafio de estado da Camada 2._ +- **[Morph](https://www.morphl2.io/)** - _Morph é uma solução de escalabilidade de rollup híbrido que utiliza prova de conhecimento zero para resolver o problema de desafio de estado da Camada 2._ -## Leitura adicional sobre leitura de ZK-rollups {#further-reading-on-zk-rollups} +- **[Linea](https://linea.build)** - _O Linea é uma Camada 2 zkEVM equivalente ao Ethereum, desenvolvida pela Consensys e totalmente alinhada com o ecossistema Ethereum._ -- [O que são os rollups de conhecimento zero?](https://coinmarketcap.com/alexandria/glossary/zero-knowledge-rollups) +## Leitura adicional sobre ZK-rollups {#further-reading-on-zk-rollups} + +- [O que são Rollups de Conhecimento Zero?](https://coinmarketcap.com/alexandria/glossary/zero-knowledge-rollups) - [O que são rollups de conhecimento zero?](https://alchemy.com/blog/zero-knowledge-rollups) -- [STARKs vs SNARKs](https://consensys.net/blog/blockchain-explained/zero-knowledge-proofs-starks-vs-snarks/) +- [O guia prático para os rollups do Ethereum](https://web.archive.org/web/20241108192208/https://research.2077.xyz/the-practical-guide-to-ethereum-rollups) +- [STARKs vs. SNARKs](https://consensys.net/blog/blockchain-explained/zero-knowledge-proofs-starks-vs-snarks/) - [O que é um zkEVM?](https://www.alchemy.com/overviews/zkevm) -- [Tipos de ZK-EVM: equivalente a Ethereum, equivalente a EVM, Tipo 1, Tipo 4 e outros termos do momento](https://taiko.mirror.xyz/j6KgY8zbGTlTnHRFGW6ZLVPuT0IV0_KmgowgStpA0K4) -- [Introdução a zkEVMs](https://hackmd.io/@yezhang/S1_KMMbGt) -- [Recursos incríveis para zkEVM](https://github.com/LuozhuZhang/awesome-zkevm) -- [ZK-SNARKS nos bastidores](https://vitalik.eth.limo/general/2017/02/01/zk_snarks.html) -- [SNARKs: como são possíveis?](https://vitalik.eth.limo/general/2021/01/26/snarks.html) +- [Tipos de ZK-EVM: equivalente ao Ethereum, equivalente à EVM, Tipo 1, Tipo 4 e outros jargões enigmáticos](https://taiko.mirror.xyz/j6KgY8zbGTlTnHRFGW6ZLVPuT0IV0_KmgowgStpA0K4) +- [Introdução ao zkEVM](https://hackmd.io/@yezhang/S1_KMMbGt) +- [O que são ZK-EVM L2s?](https://linea.mirror.xyz/qD18IaQ4BROn_Y40EBMTUTdJHYghUtdECscSWyMvm8M) +- [Recursos incríveis sobre zkEVM](https://github.com/LuozhuZhang/awesome-zkevm) +- [ZK-SNARKS por baixo dos panos](https://vitalik.eth.limo/general/2017/02/01/zk_snarks.html) +- [Como os SNARKs são possíveis?](https://vitalik.eth.limo/general/2021/01/26/snarks.html) diff --git a/public/content/translations/pt-br/developers/docs/smart-contracts/anatomy/index.md b/public/content/translations/pt-br/developers/docs/smart-contracts/anatomy/index.md index d62a36f7c01..17c03c8ea37 100644 --- a/public/content/translations/pt-br/developers/docs/smart-contracts/anatomy/index.md +++ b/public/content/translations/pt-br/developers/docs/smart-contracts/anatomy/index.md @@ -1,6 +1,6 @@ --- title: Anatomia dos contratos inteligentes -description: Uma análise aprofundada na anatomia de um contrato inteligente - funções, dados e variáveis. +description: "Uma análise aprofundada na anatomia de um contrato inteligente - funções, dados e variáveis." lang: pt-br --- @@ -8,20 +8,20 @@ Um contrato inteligente (smart contract) é um programa executado em um endereç ## Pré-requisitos {#prerequisites} -Não deixe de ler sobre [contratos inteligentes](/developers/docs/smart-contracts/). Este documento presume que você já está familiarizado com linguagens de programação como JavaScript ou Python. +Certifique-se de que leu sobre [contratos inteligentes](/developers/docs/smart-contracts/) primeiro. Este documento presume que você já está familiarizado com linguagens de programação como JavaScript ou Python. ## Dados {#data} -Quaisquer dados de contrato devem ser atribuídos a um local: seja para `armazenamento` ou `memória`. É caro modificar o armazenamento em um contrato inteligente, então você precisa considerar onde seus dados devem estar no ar. +Quaisquer dados de contrato devem ser atribuídos a um local: `storage` ou `memory`. É caro modificar o armazenamento em um contrato inteligente, então você precisa considerar onde seus dados devem estar no ar. ### Armazenamento {#storage} Dados persistentes são referidos como armazenamento e são representados por variáveis de estado. Esses valores são armazenados permanentemente na blockchain. É necessário declarar o tipo para que o contrato possa manter um registro de quanto espaço na blockchain será necessário quando ele compilar. ```solidity -// Exemplo Solidity +// Exemplo de Solidity contract SimpleStorage { - uint storedData; // State variable + uint storedData; // Variável de estado // ... } ``` @@ -31,7 +31,7 @@ contract SimpleStorage { storedData: int128 ``` -Se você já programou linguagens orientadas a objetos, provavelmente você estará familiarizado com a maioria dos tipos. Entretanto, `address` (endereço) deve ser novo para você se você for novo no desenvolvimento com Ethereum. +Se você já programou linguagens orientadas a objetos, provavelmente você estará familiarizado com a maioria dos tipos. No entanto, `address` (endereço) deve ser novidade para você se você é novo no desenvolvimento para Ethereum. Um tipo `address` pode conter um endereço Ethereum que equivale a 20 bytes ou 160 bits. Ele retorna em hexadecimal com um 0 à frente. @@ -42,31 +42,32 @@ Outros tipos incluem: - números de ponto fixo - arrays de bytes de tamanho fixo - arrays de bytes de tamanho dinâmico -- Literais racionais e inteiros -- Literais de strings -- Literais hexadecimais -- Enumeradores +- literais racionais e inteiros +- literais de string +- literais hexadecimais +- enums Para mais explicação, dê uma olhada na documentação: -- [Veja tipos de Vyper](https://vyper.readthedocs.io/en/v0.1.0-beta.6/types.html#value-types) -- [Veja tipos de Solidity](https://solidity.readthedocs.io/en/latest/types.html#value-types) +- [Veja os tipos Vyper](https://docs.vyperlang.org/en/v0.1.0-beta.6/types.html#value-types) +- [Veja os tipos Solidity](https://docs.soliditylang.org/en/latest/types.html#value-types) ### Memória {#memory} Valores que são armazenados apenas para a duração da execução da função de contratos são chamadas de variáveis de memória. Como estes não são armazenados permanentemente na blockchain, são muito mais baratos de usar. -Saiba mais sobre como a EVM armazena dados (Storage, Memória e Stack) em [Solidity docs](https://solidity.readthedocs.io/en/latest/introduction-to-smart-contracts.html?highlight=memory#storage-memory-and-the-stack). +Saiba mais sobre como a EVM armazena dados (Storage, Memory e a Pilha) nos [documentos do Solidity](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html#storage-memory-and-the-stack). ### Variáveis de ambiente {#environment-variables} -Além das variáveis definidas no seu contrato, existem algumas variáveis globais especiais. Elas são usadas principalmente para fornecer informações sobre a blockchain (cadeia de blocos) ou transação atual. +Além das variáveis definidas no seu contrato, existem algumas variáveis globais especiais. Elas são usadas principalmente para fornecer informações sobre a blockchain +(cadeia de blocos) ou transação atual. Exemplos: -| **Prop** | **Variável de estado** | **Descrição** | -| ----------------- | ---------------------- | ------------------------------------- | -| `block.timestamp` | uint256 | Data/hora de início do bloco atual | +| **Propriedade** | **Variável de estado** | **Descrição** | +| ----------------- | ---------------------- | -------------------------------------------------------- | +| `block.timestamp` | uint256 | Data/hora de início do bloco atual | | `msg.sender` | endereço | Remetente da mensagem (chamada atual) | ## Funções {#functions} @@ -75,15 +76,15 @@ Da forma mais simplista, funções podem obter informação ou um conjunto de in Existem dois tipos de chamadas de função: -- `internal` - estas não criam uma chamada EVM - - Funções internas e variáveis de estado só podem ser acessadas internamente (ou seja, de dentro do contrato atual ou de contratos derivados do mesmo) -- `external` - estas criam uma chamada EVM +- `internal` – estas não criam uma chamada de EVM + - As funções e variáveis de estado internas só podem ser acessadas internamente (ou seja, de dentro do contrato atual ou dos contratos que derivam dele) +- `external` – estas criam uma chamada de EVM - Funções externas fazem parte da interface do contrato, o que significa que elas podem ser chamadas a partir de outros contratos e através de transações. Uma função externa `f` não pode ser chamada internamente (ou seja, `f()` não funciona, mas `this.f()` funciona). -Também podem ser `públicas` ou `privadas` +Elas também podem ser `public` ou `private` -- `funções públicas` podem ser chamadas internamente a partir de dentro do contrato ou externamente por meio de mensagens -- `funções privadas` são visíveis apenas para o contrato no qual elas estão definidas e não nos contratos derivados +- As funções `public` podem ser chamadas internamente de dentro do contrato ou externamente por meio de mensagens +- As funções `private` são visíveis apenas para o contrato em que são definidas e não em contratos derivados Tanto funções quanto variáveis de estado podem ser tornadas públicas ou privadas @@ -96,11 +97,11 @@ function update_name(string value) public { } ``` -- O parâmetro `valor` do tipo `string` é passado para a função: `update_name` -- É declarado `público`, o que significa que qualquer um pode acessá-lo -- Não é declarada a `visão`, então ela pode modificar o estado do contrato +- O parâmetro `value` do tipo `string` é passado para a função: `update_name` +- Ela é declarada como `public`, o que significa que qualquer pessoa pode acessá-la +- Ela não é declarada como `view`, portanto, pode modificar o estado do contrato -### Ver funções {#view-functions} +### Funções de visualização {#view-functions} Essas funções prometem não modificar o estado dos dados do contrato. Exemplos comuns são funções "obter" – você pode usar isso para receber o saldo de um usuário, por exemplo. @@ -123,26 +124,26 @@ def readName() -> string: O que é considerado como modificar estado: 1. Escrevendo variáveis de estado. -2. [Emitir eventos](https://solidity.readthedocs.io/en/v0.7.0/contracts.html#events). -3. [Criação de outros contratos](https://solidity.readthedocs.io/en/v0.7.0/control-structures.html#creating-contracts). -4. Usando `autodestruct`. +2. [Emitindo eventos](https://docs.soliditylang.org/en/v0.7.0/contracts.html#events). +3. [Criando outros contratos](https://docs.soliditylang.org/en/v0.7.0/control-structures.html#creating-contracts). +4. Usando `selfdestruct`. 5. Enviando ether por chamadas. -6. Chamar qualquer função não marcada como`view`ou`puro`. +6. Chamando qualquer função não marcada como `view` ou `pure`. 7. Usando chamadas de baixo nível. 8. Usando montagem em linha que contém certos códigos. -### Funções de "construtor" {#constructor-functions} +### Funções de construtor {#constructor-functions} -`construtor` funções são executadas apenas uma vez quando o contrato é implantado pela primeira vez. Como o `construtor` em muitas linguagens de programação baseadas em classe, essas funções geralmente inicializam variáveis de estado para seus valores especificados. +As funções `constructor` são executadas apenas uma vez quando o contrato é implantado pela primeira vez. Assim como o `constructor` em muitas linguagens de programação baseadas em classes, essas funções geralmente inicializam variáveis de estado para seus valores especificados. ```solidity -// Exemplo Solidity +// Exemplo de Solidity // Inicializa os dados do contrato, definindo o `owner` -// como endereço do criador do contrato. +// para o endereço do criador do contrato. constructor() public { // Todos os contratos inteligentes dependem de transações externas para acionar suas funções. // `msg` é uma variável global que inclui dados relevantes sobre a transação em questão, - // como o endereço do remetente e o valor ETH incluído na transação. + // como o endereço do remetente e o valor de ETH incluído na transação. // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties owner = msg.sender; } @@ -158,16 +159,16 @@ def __init__(_beneficiary: endereço, _bidding_time: uint256): self.auctionEnd = self.auctionStart + _bidding_time ``` -### Funções integradas {#built-in-functions} +### Funções incorporadas {#built-in-functions} Além das variáveis definidas no seu contrato, existem algumas variáveis globais especiais. O exemplo mais óbvio é: - `address.send()` – Solidity -- `Enviar(endereço)` – Vyper +- `send(address)` – Vyper Estes permitem contratos para enviar ETH para outras contas. -## Como escrever funções {#writing-functions} +## Escrevendo funções {#writing-functions} Sua função precisa: @@ -180,28 +181,28 @@ Sua função precisa: pragma solidity >=0.4.0 <=0.6.0; contract ExampleDapp { - string dapp_name; // state variable + string dapp_name; // variável de estado - // Called when the contract is deployed and initializes the value + // Chamado quando o contrato é implantado e inicializa o valor constructor() public { - dapp_name = "My Example dapp"; + dapp_name = "Meu dapp de Exemplo"; } - // Get Function + // Função Get function read_name() public view returns(string) { return dapp_name; } - // Set Function + // Função Set function update_name(string value) public { dapp_name = value; } } ``` -Um contrato completo pode parecer algo assim. Aqui a função `construtor` fornece um valor inicial para a variável `dapp_name`. +Um contrato completo pode parecer algo assim. Aqui, a função `constructor` fornece um valor inicial para a variável `dapp_name`. -## Eventos e registros {#events-and-logs} +## Eventos e logs {#events-and-logs} Os eventos permitem que seu contrato inteligente se comunique com seu front-end ou outros aplicativos que se inscrevem para recebê-los. Uma vez que uma transação é validada e adicionada a um bloco, os contratos inteligentes podem emitir eventos e registrar informações, que o front-end pode processar e utilizar. @@ -209,29 +210,29 @@ Os eventos permitem que seu contrato inteligente se comunique com seu front-end Estes são alguns exemplos escritos em Solidity. Se você quiser brincar com o código, pode interagir com eles no [Remix](http://remix.ethereum.org). -### Hello World {#hello-world} +### Olá, mundo {#hello-world} ```solidity -// Especifica a versão do Solidity usando a versão semântica. +// Especifica a versão do Solidity, usando versionamento semântico. // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma pragma solidity ^0.5.10; // Define um contrato chamado `HelloWorld`. -// Um contrato é uma coleção de funções e dados (seu estado). +// Um contrato é um conjunto de funções e dados (seu estado). // Uma vez implantado, um contrato reside em um endereço específico na blockchain Ethereum. // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html contract HelloWorld { - // Declita uma variável `message` de tipo `string`. - // Variáveis de estado são variáveis cujos valores são permanentemente armazenados no armazenamento do contrato. - // A palavra-chave 'público' torna variáveis acessíveis fora de um contrato + // Declara uma variável de estado `message` do tipo `string`. + // Variáveis de estado são variáveis cujos valores são armazenados permanentemente no armazenamento do contrato. + // A palavra-chave `public` torna as variáveis acessíveis de fora de um contrato // e cria uma função que outros contratos ou clientes podem chamar para acessar o valor. - mensagem pública de cadeia; + string public message; - // Semelhante a muitas linguagens de objeto, baseadas em classes, um construtor é - // uma função especial que é executada somente após a criação do contrato. - // Os construtores são usados para inicializar os dados do contrato. - // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts. tml#constructors + // Semelhante a muitas linguagens de programação orientadas a objetos baseadas em classes, um construtor é + // uma função especial que é executada apenas na criação do contrato. + // Construtores são usados para inicializar os dados do contrato. + // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors constructor(string memory initMessage) public { // Aceita um argumento de string `initMessage` e define o valor // na variável de armazenamento `message` do contrato). @@ -252,134 +253,136 @@ contract HelloWorld { pragma solidity ^0.5.10; contract Token { - // Um "endereço" é comparável a um endereço de e-mail - é usado para comparar uma conta no Ethereum. - // Endereços podem representar uma conta de contrato inteligente ou uma conta externa (usuário). + // Um `address` é comparável a um endereço de e-mail - ele é usado para identificar uma conta na Ethereum. + // Endereços podem representar um contrato inteligente ou contas externas (de usuário). // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/types.html#address address public owner; // Um `mapping` é essencialmente uma estrutura de dados de tabela de hash. - // Este `mapeamento` atribui um inteiro não assinado (o saldo do token) a um endereço (o titular do token). + // Este `mapping` atribui um inteiro sem sinal (o saldo do token) a um endereço (o detentor do token). // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/types.html#mapping-types mapping (address => uint) public balances; - // Eventos permitem registro de atividade no blockchain. - // Clientes Ethereum podem ouvir eventos para reagir às alterações do estado do contrato. - // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#events + // Eventos permitem o registro de atividades na blockchain. + // Clientes Ethereum podem ouvir eventos para reagir a mudanças de estado do contrato. + // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#events event Transfer(address from, address to, uint amount); - // Initializes the contract's data, setting the `owner` - // to the address of the contract creator. + // Inicializa os dados do contrato, definindo o `owner` + // para o endereço do criador do contrato. constructor() public { - // Todos os contratos inteligentes dependem de transações externas para acionar suas funções. + // Todos os contratos inteligentes dependem de transações externas para acionar suas funções. // `msg` é uma variável global que inclui dados relevantes sobre a transação em questão, - // como o endereço do remetente e o valor ETH incluído na transação. + // como o endereço do remetente e o valor de ETH incluído na transação. // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties owner = msg.sender; } // Cria uma quantidade de novos tokens e os envia para um endereço. function mint(address receiver, uint amount) public { - // `require` é uma estrutura de controle usada para aplicar certas condições. - // Se um comando `require` for avaliado como `false`, uma exceção é acionada, - // que reverte todas as alterações feitas ao estado durante a chamada atual. - // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/control-structures. tml#error-handling-assert-require-revert-and-exceptions + // `require` é uma estrutura de controle usada para impor certas condições. + // Se uma instrução `require` for avaliada como `false`, uma exceção é acionada, + // que reverte todas as alterações feitas no estado durante a chamada atual. + // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions // Somente o proprietário do contrato pode chamar esta função - require(msg. remetente == dono, "Você não é o dono. ); + require(msg.sender == owner, "Você não é o proprietário."); - // Reforça uma quantidade máxima de tokens + // Impõe uma quantidade máxima de tokens require(amount < 1e60, "Emissão máxima excedida"); // Aumenta o saldo de `receiver` em `amount` - saldos[receiver] += amount; + balances[receiver] += amount; } - // Envia uma quantidade de tokens existentes de qualquer chamada para um endereço. + // Envia uma quantidade de tokens existentes de qualquer chamador para um endereço. function transfer(address receiver, uint amount) public { // O remetente deve ter tokens suficientes para enviar - require(amount <= balances[msg.sender], "Insufficient balance."); + require(amount <= balances[msg.sender], "Saldo insuficiente."); - // Ajusta os saldos do token dos dois endereços - balances[msg.sender] -= quantidade; - balances[receiver] += quantidade; + // Ajusta os saldos de token dos dois endereços + balances[msg.sender] -= amount; + balances[receiver] += amount; - // Emite um evendo definido anteriormente - emite Transfer(msg.sender, receiver, amount); + // Emite o evento definido anteriormente + emit Transfer(msg.sender, receiver, amount); } } ``` -### Ativo digital único {#unique-digital-asset} +### Ativo digital exclusivo {#unique-digital-asset} ```solidity -pragma solidity ^0.5.10. -// Neste caso, uma série de contratos auxiliares de OpenZeppelin. +pragma solidity ^0.5.10; + +// Importa símbolos de outros arquivos para o contrato atual. +// Neste caso, uma série de contratos de ajuda da OpenZeppelin. // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#importing-other-source-files import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol"; -import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver. ol"; +import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import "../node_modules/@openzeppelin/contracts/introspection/ERC165.sol"; import "../node_modules/@openzeppelin/contracts/math/SafeMath.sol"; // A palavra-chave `is` é usada para herdar funções e palavras-chave de contratos externos. -// Neste caso, o `CryptoPizza` herda dos contratos `IERC721` e `ERC165`. +// Neste caso, `CryptoPizza` herda dos contratos `IERC721` e `ERC165`. // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#inheritance contract CryptoPizza is IERC721, ERC165 { - // Usa a biblioteca OpenZeppelin para executar operações aritméticas de forma segura. - // Saiba mais: https://docs.openzeppelin.com/contracts/2. /api/math#SafeMath - usando SafeMath para uint256; + // Usa a biblioteca SafeMath do OpenZeppelin para realizar operações aritméticas com segurança. + // Saiba mais: https://docs.openzeppelin.com/contracts/2.x/api/math#SafeMath + using SafeMath for uint256; - // Variáveis de estado constantes em Solidity são semelhantes a outros idiomas - // mas você deve atribuir a partir de uma expressão que é constante na hora de compilação. - // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constant-state-variables + // Variáveis de estado constantes em Solidity são semelhantes a outras linguagens + // mas você deve atribuir a partir de uma expressão que é constante em tempo de compilação. + // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constant-state-variables uint256 constant dnaDigits = 10; uint256 constant dnaModulus = 10 ** dnaDigits; bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; - // Struct types let you define your own type - // Learn more: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs + // Tipos de estrutura permitem que você defina seu próprio tipo + // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs struct Pizza { string name; uint256 dna; } - // Creates an empty array of Pizza structs + // Cria uma matriz vazia de estruturas Pizza Pizza[] public pizzas; - // Mapping from pizza ID to its owner's address + // Mapeamento do ID da pizza para o endereço do seu proprietário mapping(uint256 => address) public pizzaToOwner; - // Mapping from owner's address to number of owned token + // Mapeamento do endereço do proprietário para o número de tokens possuídos mapping(address => uint256) public ownerPizzaCount; - // Mapping from token ID to approved address + // Mapeamento do ID do token para o endereço aprovado mapping(uint256 => address) pizzaApprovals; - // You can nest mappings, this example maps owner to operator approvals + // Você pode aninhar mapeamentos, este exemplo mapeia o proprietário para as aprovações do operador mapping(address => mapping(address => bool)) private operatorApprovals; - // Internal function to create a random Pizza from string (name) and DNA + // Função interna para criar uma Pizza aleatória a partir de uma string (nome) e DNA function _createPizza(string memory _name, uint256 _dna) - // The `internal` keyword means this function is only visible - // within this contract and contracts that derive this contract - // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters + // A palavra-chave `internal` significa que esta função só é visível + // dentro deste contrato e dos contratos que derivam deste contrato + // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters internal - // `isUnique` is a function modifier that checks if the pizza already exists - // Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers + // `isUnique` é um modificador de função que verifica se a pizza já existe + // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers isUnique(_name, _dna) { - // Adds Pizza to array of Pizzas and get id + // Adiciona a Pizza à matriz de Pizzas e obtém o id uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1); - // Checks that Pizza owner is the same as current user - // Learn more: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions + // Verifica se o proprietário da Pizza é o mesmo que o usuário atual + // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions - // note that address(0) is the zero address, - // indicating that pizza[id] is not yet allocated to a particular user. + // note que address(0) é o endereço zero, + // indicando que pizza[id] ainda não foi alocada para um usuário em particular. assert(pizzaToOwner[id] == address(0)); - // Maps the Pizza to the owner + // Mapeia a Pizza para o proprietário pizzaToOwner[id] = msg.sender; ownerPizzaCount[msg.sender] = SafeMath.add( ownerPizzaCount[msg.sender], @@ -387,38 +390,38 @@ contract CryptoPizza is IERC721, ERC165 { ); } - // Creates a random Pizza from string (name) + // Cria uma Pizza aleatória a partir de uma string (nome) function createRandomPizza(string memory _name) public { uint256 randDna = generateRandomDna(_name, msg.sender); _createPizza(_name, randDna); } - // Generates random DNA from string (name) and address of the owner (creator) + // Gera DNA aleatório a partir de uma string (nome) e do endereço do proprietário (criador) function generateRandomDna(string memory _str, address _owner) public - // Functions marked as `pure` promise not to read from or modify the state - // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions + // As funções marcadas como `pure` prometem não ler ou modificar o estado + // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions pure returns (uint256) { - // Generates random uint from string (name) + address (owner) + // Gera um uint aleatório a partir de uma string (nome) + endereço (proprietário) uint256 rand = uint256(keccak256(abi.encodePacked(_str))) + uint256(_owner); rand = rand % dnaModulus; return rand; } - // Returns array of Pizzas found by owner + // Retorna uma matriz de Pizzas encontradas pelo proprietário function getPizzasByOwner(address _owner) public - // Functions marked as `view` promise not to modify state - // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions + // Funções marcadas como `view` prometem não modificar o estado + // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions view returns (uint256[] memory) { - // Uses the `memory` storage location to store values only for the - // lifecycle of this function call. - // Learn more: https://solidity.readthedocs.io/en/v0.5.10/introduction-to-smart-contracts.html#storage-memory-and-the-stack + // Usa o local de armazenamento `memory` para armazenar valores apenas para o + // ciclo de vida desta chamada de função. + // Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/introduction-to-smart-contracts.html#storage-memory-and-the-stack uint256[] memory result = new uint256[](ownerPizzaCount[_owner]); uint256 counter = 0; for (uint256 i = 0; i < pizzas.length; i++) { @@ -430,28 +433,28 @@ contract CryptoPizza is IERC721, ERC165 { return result; } - // Transfers Pizza and ownership to other address + // Transfere a Pizza e a propriedade para outro endereço function transferFrom(address _from, address _to, uint256 _pizzaId) public { - require(_from != address(0) && _to != address(0), "Invalid address."); - require(_exists(_pizzaId), "Pizza does not exist."); - require(_from != _to, "Cannot transfer to the same address."); - require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved."); + require(_from != address(0) && _to != address(0), "Endereço inválido."); + require(_exists(_pizzaId), "A pizza não existe."); + require(_from != _to, "Não é possível transferir para o mesmo endereço."); + require(_isApprovedOrOwner(msg.sender, _pizzaId), "O endereço não está aprovado."); ownerPizzaCount[_to] = SafeMath.add(ownerPizzaCount[_to], 1); ownerPizzaCount[_from] = SafeMath.sub(ownerPizzaCount[_from], 1); pizzaToOwner[_pizzaId] = _to; - // Emits event defined in the imported IERC721 contract + // Emite evento definido no contrato IERC721 importado emit Transfer(_from, _to, _pizzaId); _clearApproval(_to, _pizzaId); } /** - * Safely transfers the ownership of a given token ID to another address - * If the target address is a contract, it must implement `onERC721Received`, - * which is called upon a safe transfer, and return the magic value + * Transfere com segurança a propriedade de um determinado ID de token para outro endereço + * Se o endereço de destino for um contrato, ele deverá implementar `onERC721Received`, + * que é chamado após uma transferência segura e retorna o valor mágico * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; - * otherwise, the transfer is reverted. + * caso contrário, a transferência será revertida. */ function safeTransferFrom(address from, address to, uint256 pizzaId) public @@ -461,11 +464,11 @@ contract CryptoPizza is IERC721, ERC165 { } /** - * Safely transfers the ownership of a given token ID to another address - * If the target address is a contract, it must implement `onERC721Received`, - * which is called upon a safe transfer, and return the magic value + * Transfere com segurança a propriedade de um determinado ID de token para outro endereço + * Se o endereço de destino for um contrato, ele deverá implementar `onERC721Received`, + * que é chamado após uma transferência segura e retorna o valor mágico * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; - * otherwise, the transfer is reverted. + * caso contrário, a transferência será revertida. */ function safeTransferFrom( address from, @@ -474,12 +477,12 @@ contract CryptoPizza is IERC721, ERC165 { bytes memory _data ) public { this.transferFrom(from, to, pizzaId); - require(_checkOnERC721Received(from, to, pizzaId, _data), "Must implement onERC721Received."); + require(_checkOnERC721Received(from, to, pizzaId, _data), "Deve implementar onERC721Received."); } /** - * Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract + * Função interna para invocar `onERC721Received` em um endereço de destino + * A chamada não é executada se o endereço de destino não for um contrato */ function _checkOnERC721Received( address from, @@ -500,13 +503,13 @@ contract CryptoPizza is IERC721, ERC165 { return (retval == _ERC721_RECEIVED); } - // Burns a Pizza - destroys Token completely - // The `external` function modifier means this function is - // part of the contract interface and other contracts can call it + // Queima uma Pizza - destrói o Token completamente + // O modificador de função `external` significa que esta função é + // parte da interface do contrato e outros contratos podem chamá-la function burn(uint256 _pizzaId) external { - require(msg.sender != address(0), "Invalid address."); - require(_exists(_pizzaId), "Pizza does not exist."); - require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved."); + require(msg.sender != address(0), "Endereço inválido."); + require(_exists(_pizzaId), "A pizza não existe."); + require(_isApprovedOrOwner(msg.sender, _pizzaId), "O endereço não está aprovado."); ownerPizzaCount[msg.sender] = SafeMath.sub( ownerPizzaCount[msg.sender], @@ -515,58 +518,58 @@ contract CryptoPizza is IERC721, ERC165 { pizzaToOwner[_pizzaId] = address(0); } - // Returns count of Pizzas by address + // Retorna a contagem de Pizzas por endereço function balanceOf(address _owner) public view returns (uint256 _balance) { return ownerPizzaCount[_owner]; } - // Returns owner of the Pizza found by id + // Retorna o proprietário da Pizza encontrado por id function ownerOf(uint256 _pizzaId) public view returns (address _owner) { address owner = pizzaToOwner[_pizzaId]; - require(owner != address(0), "Invalid Pizza ID."); + require(owner != address(0), "ID de pizza inválido."); return owner; } - // Approves other address to transfer ownership of Pizza + // Aprova outro endereço para transferir a propriedade da Pizza function approve(address _to, uint256 _pizzaId) public { - require(msg.sender == pizzaToOwner[_pizzaId], "Must be the Pizza owner."); + require(msg.sender == pizzaToOwner[_pizzaId], "Deve ser o proprietário da Pizza."); pizzaApprovals[_pizzaId] = _to; emit Approval(msg.sender, _to, _pizzaId); } - // Returns approved address for specific Pizza + // Retorna o endereço aprovado para uma Pizza específica function getApproved(uint256 _pizzaId) public view returns (address operator) { - require(_exists(_pizzaId), "Pizza does not exist."); + require(_exists(_pizzaId), "A pizza não existe."); return pizzaApprovals[_pizzaId]; } /** - * Private function to clear current approval of a given token ID - * Reverts if the given address is not indeed the owner of the token + * Função privada para limpar a aprovação atual de um determinado ID de token + * Reverte se o endereço fornecido não for de fato o proprietário do token */ function _clearApproval(address owner, uint256 _pizzaId) private { - require(pizzaToOwner[_pizzaId] == owner, "Must be pizza owner."); - require(_exists(_pizzaId), "Pizza does not exist."); + require(pizzaToOwner[_pizzaId] == owner, "Deve ser o proprietário da pizza."); + require(_exists(_pizzaId), "A pizza não existe."); if (pizzaApprovals[_pizzaId] != address(0)) { pizzaApprovals[_pizzaId] = address(0); } } /* - * Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf + * Define ou cancela a aprovação de um determinado operador + * Um operador tem permissão para transferir todos os tokens do remetente em seu nome */ function setApprovalForAll(address to, bool approved) public { - require(to != msg.sender, "Cannot approve own address"); + require(to != msg.sender, "Não é possível aprovar o próprio endereço"); operatorApprovals[msg.sender][to] = approved; emit ApprovalForAll(msg.sender, to, approved); } - // Tells whether an operator is approved by a given owner + // Informa se um operador é aprovado por um determinado proprietário function isApprovedForAll(address owner, address operator) public view @@ -575,20 +578,20 @@ contract CryptoPizza is IERC721, ERC165 { return operatorApprovals[owner][operator]; } - // Takes ownership of Pizza - only for approved users + // Assume a propriedade da Pizza - apenas para usuários aprovados function takeOwnership(uint256 _pizzaId) public { - require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved."); + require(_isApprovedOrOwner(msg.sender, _pizzaId), "O endereço não está aprovado."); address owner = this.ownerOf(_pizzaId); this.transferFrom(owner, msg.sender, _pizzaId); } - // Checks if Pizza exists + // Verifica se a Pizza existe function _exists(uint256 pizzaId) internal view returns (bool) { address owner = pizzaToOwner[pizzaId]; return owner != address(0); } - // Checks if address is owner or is approved to transfer Pizza + // Verifica se o endereço é o proprietário ou se está aprovado para transferir a Pizza function _isApprovedOrOwner(address spender, uint256 pizzaId) internal view @@ -603,7 +606,7 @@ contract CryptoPizza is IERC721, ERC165 { this.isApprovedForAll(owner, spender)); } - // Check if Pizza is unique and doesn't exist yet + // Verifica se a Pizza é única e ainda não existe modifier isUnique(string memory _name, uint256 _dna) { bool result = true; for (uint256 i = 0; i < pizzas.length; i++) { @@ -615,19 +618,19 @@ contract CryptoPizza is IERC721, ERC165 { result = false; } } - require(result, "Pizza with such name already exists."); + require(result, "Uma pizza com esse nome já existe."); _; } - // Returns whether the target address is a contract + // Retorna se o endereço de destino é um contrato function isContract(address account) internal view returns (bool) { uint256 size; - // Currently there is no better way to check if there is a contract in an address - // than to check the size of the code at that address. - // See https://ethereum.stackexchange.com/a/14016/36603 - // for more details about how this works. - // TODO Check this again before the Serenity release, because all addresses will be - // contracts then. + // Atualmente não há uma maneira melhor de verificar se há um contrato em um endereço + // do que verificar o tamanho do código nesse endereço. + // Veja https://ethereum.stackexchange.com/a/14016/36603 + // para mais detalhes sobre como isso funciona. + // TODO Verificar isso novamente antes do lançamento do Serenity, porque todos os endereços serão + // contratos então. // solium-disable-next-line security/no-inline-assembly assembly { size := extcodesize(account) @@ -641,16 +644,16 @@ contract CryptoPizza is IERC721, ERC165 { Confira a documentação sobre Solidity e Vyper para ter uma visão geral mais completa dos contratos inteligentes: -- [Solidity](https://solidity.readthedocs.io/) -- [Vyper](https://vyper.readthedocs.io/) +- [Solidity](https://docs.soliditylang.org/) +- [Vyper](https://docs.vyperlang.org/en/stable/) ## Tópicos relacionados {#related-topics} -- [Smart Contracts](/developers/docs/smart-contracts/) +- [Contratos inteligentes](/developers/docs/smart-contracts/) - [Máquina Virtual Ethereum](/developers/docs/evm/) ## Tutoriais relacionados {#related-tutorials} -- [Diminuir contratos para enfrentar o limite de tamanho do contrato](/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/) _– Algumas dicas práticas para reduzir o tamanho de seu contrato inteligente._ +- [Reduzindo o tamanho dos contratos para combater o limite de tamanho do contrato](/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/) _– Algumas dicas práticas para reduzir o tamanho do seu contrato inteligente._ - [Registrando dados de contratos inteligentes com eventos](/developers/tutorials/logging-events-smart-contracts/) _– Uma introdução aos eventos de contratos inteligentes e como você pode usá-los para registrar dados._ -- [Interaja com outros contratos Solidity](/developers/tutorials/interact-with-other-contracts-from-solidity/) _– Como implantar um contrato inteligente a partir de um contrato existente e interagir com ele._ +- [Interaja com outros contratos a partir do Solidity](/developers/tutorials/interact-with-other-contracts-from-solidity/) _– Como implantar um contrato inteligente a partir de um contrato existente e interagir com ele._ diff --git a/public/content/translations/pt-br/developers/docs/smart-contracts/compiling/index.md b/public/content/translations/pt-br/developers/docs/smart-contracts/compiling/index.md index 1d9a3f0514e..6a57de7822d 100644 --- a/public/content/translations/pt-br/developers/docs/smart-contracts/compiling/index.md +++ b/public/content/translations/pt-br/developers/docs/smart-contracts/compiling/index.md @@ -1,26 +1,26 @@ --- -title: Compilação de contratos inteligentes -description: Uma explicação do motivo pelo qual você precisa compilar contratos inteligentes e o que a compilação realmente faz. +title: "Compilação de contratos inteligentes" +description: "Uma explicação do motivo pelo qual você precisa compilar contratos inteligentes e o que a compilação realmente faz." lang: pt-br incomplete: true --- Você precisa compilar seu contrato para que seu aplicativo web e a máquina virtual Ethereum (EVM) possam entendê-lo. -## Pré-requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -Você pode achar útil ler nossa introdução a [contratos inteligentes](/developers/docs/smart-contracts/) e a [máquina virtual Ethereum](/developers/docs/evm/) antes de ler sobre compilação. +Pode ser útil ler a nossa introdução aos [contratos inteligentes](/developers/docs/smart-contracts/) e à [máquina virtual ethereum](/developers/docs/evm/) antes de ler sobre a compilação. ## A EVM {#the-evm} -Para a [ EVM](/developers/docs/evm/) poder executar seu contrato, ele precisa estar em ** bytecode**. A compilação transforma isso: +Para que a [EVM](/developers/docs/evm/) possa executar seu contrato, ele precisa estar em **bytecode**. A compilação transforma isso: ```solidity pragma solidity 0.4.24; -contract Saudações { +contract Greeter { - function greet() public constant returns (string) { + function greet() public view returns (string memory) { return "Olá"; } @@ -33,17 +33,17 @@ contract Saudações { PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x41 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0xCFAE3217 EQ PUSH2 0x46 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x52 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x5B PUSH2 0xD6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x9B JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x80 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xC8 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x40 DUP1 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x48656C6C6F000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 POP SWAP1 JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 SLT 0xec 0xe 0xf5 0xf8 SLT 0xc7 0x2d STATICCALL ADDRESS SHR 0xdb COINBASE 0xb1 BALANCE 0xe8 0xf8 DUP14 0xda 0xad DUP13 LOG1 0x4c 0xb4 0x26 0xc2 DELEGATECALL PUSH7 0x8994D3E002900 ``` -Esses são chamados de **opcodes**. Os opcodes da EVM são instruções de baixo nível que a Máquina Virtual Ethereum (EVM) pode executar. Cada opcode representa uma operação específica, como operações aritméticas, operações lógicas, manipulação de dados, controle de fluxo, entre outras. +Eles são chamados de **códigos de operação**. Os opcodes da EVM são instruções de baixo nível que a Máquina Virtual Ethereum (EVM) pode executar. Cada opcode representa uma operação específica, como operações aritméticas, operações lógicas, manipulação de dados, controle de fluxo, entre outras. -[Mais sobre opcodes](/developers/docs/evm/opcodes/) +[Mais sobre códigos de operação](/developers/docs/evm/opcodes/) -## Aplicativos Web {#web-applications} +## Aplicações web {#web-applications} -O compilador também produzirá a ** Interface Binária de Aplicação (ABI)** de que necessita para que a sua aplicação compreenda o contrato e chame as funções do contrato. +O compilador também produzirá a **Interface Binária de Aplicação (ABI)**, que é necessária para que sua aplicação entenda o contrato e chame as funções do contrato. A ABI é um arquivo JSON que descreve o contrato implantado e suas funções de contrato inteligente. Ele faz a ponte entre a web2 e web3 -Uma [biblioteca cliente JavaScript](/developers/docs/apis/javascript/) vai ler a **ABI** para que você chame seu contrato inteligente na interface do seu aplicativo da web. +Uma [biblioteca de cliente JavaScript](/developers/docs/apis/javascript/) lerá a **ABI** para que você possa chamar seu contrato inteligente na interface da sua aplicação web. Abaixo está a ABI para o contrato de token ERC-20. Um ERC-20 é um token que você pode negociar no Ethereum. @@ -274,9 +274,9 @@ Abaixo está a ABI para o contrato de token ERC-20. Um ERC-20 é um token que vo ## Leitura adicional {#further-reading} -- [ Especificações ABI](https://solidity.readthedocs.io/en/v0.7.0/abi-spec.html)_– Solidity_ +- [Especificação da ABI](https://solidity.readthedocs.io/en/v0.7.0/abi-spec.html) _– Solidity_ ## Tópicos relacionados {#related-topics} -- [Bibliotecas cliente JavaScript](/developers/docs/apis/javascript/) -- [Máquina virtual Ethereum](/developers/docs/evm/) +- [Bibliotecas de cliente JavaScript](/developers/docs/apis/javascript/) +- [máquina virtual ethereum](/developers/docs/evm/) diff --git a/public/content/translations/pt-br/developers/docs/smart-contracts/composability/index.md b/public/content/translations/pt-br/developers/docs/smart-contracts/composability/index.md index 65bdef6b491..5a424715cda 100644 --- a/public/content/translations/pt-br/developers/docs/smart-contracts/composability/index.md +++ b/public/content/translations/pt-br/developers/docs/smart-contracts/composability/index.md @@ -1,13 +1,13 @@ --- -title: Composição de contrato inteligente -description: +title: "Composição de contrato inteligente" +description: Aprenda como os contratos inteligentes podem ser combinados como blocos de Lego para construir dapps complexos reutilizando componentes existentes. lang: pt-br incomplete: true --- ## Uma breve introdução {#a-brief-introduction} -Os contratos inteligentes são públicos na Ethereum e podem ser considerados como APIs abertas. Você não precisa escrever o seu próprio contrato inteligente para se tornar um desenvolvedor dapp, você só precisa saber como interagir com eles. Por exemplo, você pode usar os contratos inteligentes existentes do [Uniswap](https://uniswap.exchange/swap), uma troca descentralizada, para lidar com toda a lógica de troca de token em seu aplicativo - você não precisa começar do zero. Confira alguns de seus contratos [v2](https://github.com/Uniswap/uniswap-v2-core/tree/master/contracts) e [v3](https://github.com/Uniswap/uniswap-v3-core/tree/main/contracts). +Os contratos inteligentes são públicos na Ethereum e podem ser considerados como APIs abertas. Você não precisa escrever o seu próprio contrato inteligente para se tornar um desenvolvedor dapp, você só precisa saber como interagir com eles. Por exemplo, você pode usar os contratos inteligentes existentes da [Uniswap](https://uniswap.exchange/swap), uma corretora descentralizada, para lidar com toda a lógica de troca de token em seu aplicativo – você não precisa começar do zero. Confira alguns de seus contratos [v2](https://github.com/Uniswap/uniswap-v2-core/tree/master/contracts) e [v3](https://github.com/Uniswap/uniswap-v3-core/tree/main/contracts). ## O que é composabilidade? {#what-is-composability} @@ -19,17 +19,17 @@ Na Ethereum, todo contrato inteligente é uma espécie de Lego – você pode us Os contratos inteligentes Ethereum são como APIs públicas, para que qualquer pessoa possa interagir com o contrato ou integrá-los em dapps para funcionalidade adicional. A composição de contrato inteligente geralmente funciona com três princípios: modularidade, autonomia e descoberta: -**1. Modularidade**: Esta é a capacidade de componentes individuais para executar uma tarefa específica. Na Ethereum, cada contrato inteligente tem um caso de uso específico (como mostrado no exemplo Uniswap). +\*\*1. **Modularidade**: Esta é a capacidade de componentes individuais de realizar uma tarefa específica. Na Ethereum, cada contrato inteligente tem um caso de uso específico (como mostrado no exemplo Uniswap). -**2. Autonomia**: Componentes compostos devem ser capazes de operar independentemente. Cada contrato inteligente na Ethereum é autoexecutável e pode funcionar sem depender de outras partes do sistema. +\*\*2. **Autonomia**: Componentes componíveis devem ser capazes de operar de forma independente. Cada contrato inteligente na Ethereum é autoexecutável e pode funcionar sem depender de outras partes do sistema. -**3. Capacidade de descoberta**: Desenvolvedores não podem chamar contratos externos ou integrar bibliotecas de software em aplicativos, se o primeiro não estiver disponível publicamente. Por concepção, os contratos inteligentes são de código aberto; qualquer um pode chamar um contrato inteligente ou copiar uma base de código. +\*\*3. **Capacidade de descoberta**: Desenvolvedores não podem chamar contratos externos ou integrar bibliotecas de software em aplicativos se os primeiros não estiverem disponíveis publicamente. Por concepção, os contratos inteligentes são de código aberto; qualquer um pode chamar um contrato inteligente ou copiar uma base de código. -## Benefícios da composabilidade {#benefits-of-composability} +## Benefícios da componibilidade {#benefits-of-composability} -### Ciclo de desenvolvimento curto {#shorter-development-cycle} +### Ciclo de desenvolvimento mais curto {#shorter-development-cycle} -A composabilidade reduz o trabalho que os desenvolvedores têm de fazer ao criar [dapps](/apps/#what-are-dapps). [Como Naval Ravikant coloca:](https://twitter.com/naval/status/1444366754650656770) "O código aberto significa que todo problema deve ser resolvido uma vez." +A componibilidade reduz o trabalho que os desenvolvedores precisam fazer ao criar [dapps](/apps/#what-are-dapps). [Como diz Naval Ravikant:](https://twitter.com/naval/status/1444366754650656770) "Código aberto significa que cada problema precisa ser resolvido apenas uma vez." Se houver um contrato inteligente que resolva um problema, outros desenvolvedores podem reutilizá-lo, para que não precisem resolver o mesmo problema. Dessa forma, os desenvolvedores podem usar bibliotecas de software existentes e adicionar funcionalidades extras para criar novos dapps. @@ -43,13 +43,13 @@ A interoperabilidade entre os componentes do ecossistema Ethereum melhora a expe Usaremos um exemplo de negociação de arbitragem para ilustrar os benefícios da interoperabilidade: -Se um token estiver sendo negociado mais alto na `troca A` do que na `troca B`, você pode aproveitar a diferença de preço para obter lucro. No entanto, você só pode fazer isso se tiver capital suficiente para financiar a transação (ou seja, comprar o token da `troca B` e vendê-lo na `troca A`). +Se um token está sendo negociado a um preço mais alto na `corretora A` do que na `corretora B`, você pode aproveitar a diferença de preço para obter lucro. No entanto, você só pode fazer isso se tiver capital suficiente para financiar a transação (ou seja, comprar o token da `corretora B` e vendê-lo na `corretora A`). -Em um cenário em que você não tem fundos suficientes para cobrir a negociação, um empréstimo rápido pode ser o ideal. Os [empréstimos relâmpagos](/defi/#flash-loans) são altamente técnicos, mas a ideia básica é que você pode emprestar ativos (sem garantias) e devolvê-los dentro de *uma* transação. +Em um cenário em que você não tem fundos suficientes para cobrir a negociação, um empréstimo rápido pode ser o ideal. [Empréstimos-relâmpago](/defi/#flash-loans) são altamente técnicos, mas a ideia básica é que você pode tomar ativos emprestados (sem colateral) e devolvê-los dentro de _uma_ única transação. -Voltando ao nosso exemplo inicial, um trader de arbitragem pode fazer um grande empréstimo relâmpago, comprar tokens da `troca B`, vendê-los na `troca A`, pagar o capital + juros, e manter o lucro, dentro da mesma transação. Essa lógica complexa requer a combinação de chamadas para vários contratos, o que não seria possível se os contratos inteligentes não tivessem interoperabilidade. +Voltando ao nosso exemplo inicial, um trader de arbitragem pode fazer um grande empréstimo-relâmpago, comprar tokens da `corretora B`, vendê-los na `corretora A`, pagar o capital + juros e ficar com o lucro, tudo na mesma transação. Essa lógica complexa requer a combinação de chamadas para vários contratos, o que não seria possível se os contratos inteligentes não tivessem interoperabilidade. -## Exemplos de composabilidade na Ethereum {#composability-in-ethereum} +## Exemplos de componibilidade na Ethereum {#composability-in-ethereum} ### Trocas de tokens {#token-swaps} @@ -57,20 +57,20 @@ Se você criar um dapp que exige que as transações sejam pagas em ETH, você p ### Governança {#governance} -Construir sistemas de governança sob medida para um [DAO](/dao/) pode ser caro e demorado. Em vez disso, você pode usar um kit de ferramentas de governança de código aberto, como [Aragon Client](https://client.aragon.org/), para inicializar seu DAO e criar rapidamente um framework de governança. +Construir sistemas de governança personalizados para uma [DAO](/dao/) pode ser caro e demorado. Em vez disso, você pode usar um kit de ferramentas de governança de código aberto, como o [Aragon Client](https://client.aragon.org/), para inicializar sua DAO e criar rapidamente uma estrutura de governança. ### Gerenciamento de identidade {#identity-management} -Em vez de criar um sistema de autenticação personalizado ou depender de provedores centralizados, você pode integrar ferramentas de identidade descentralizada (DID) para gerenciar a autenticação de usuários. Um exemplo é o [SpruceID](https://www.spruceid.com/), um kit de ferramentas de código aberto que oferece uma funcionalidade "Entrar com Ethereum" que permite aos usuários autenticar identidades com uma carteira Ethereum. +Em vez de criar um sistema de autenticação personalizado ou depender de provedores centralizados, você pode integrar ferramentas de identidade descentralizada (DID) para gerenciar a autenticação de usuários. Um exemplo é o [SpruceID](https://www.spruceid.com/), um kit de ferramentas de código aberto que oferece a funcionalidade "Sign in with Ethereum", que permite que os usuários autentiquem identidades com uma carteira Ethereum. ## Tutoriais relacionados {#related-tutorials} -- [Comece seu desenvolvimento de front-end dapp com create-eth-app](/developers/tutorials/kickstart-your-dapp-frontend-development-with-create-eth-app/) _– Uma visão geral de como usar o create-eth-app para criar apps com contratos inteligentes populares prontos para uso._ +- [Dê um pontapé inicial no desenvolvimento de frontend do seu dapp com o create-eth-app](/developers/tutorials/kickstart-your-dapp-frontend-development-with-create-eth-app/) _– Uma visão geral de como usar o create-eth-app para criar aplicativos com contratos inteligentes populares prontos para uso._ ## Leitura adicional {#further-reading} -_Conhece algum recurso da comunidade que o ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ -- [Composição é Inovação](https://future.a16z.com/how-composability-unlocks-crypto-and-everything-else/) -- [Porque a Composabilidade é importante para a Web3](https://hackernoon.com/why-composability-matters-for-web3) -- [O que é Composabilidade?](https://blog.aragon.org/what-is-composability/#:~:text=Aragon,connect%20to%20every%20other%20piece.) +- [Componibilidade é Inovação](https://a16zcrypto.com/posts/article/how-composability-unlocks-crypto-and-everything-else/) +- [Por que a componibilidade é importante para a Web3](https://hackernoon.com/why-composability-matters-for-web3) +- [O que é componibilidade?](https://blog.aragon.org/what-is-composability/#:~:text=Aragon,connect%20to%20every%20other%20piece.) diff --git a/public/content/translations/pt-br/developers/docs/smart-contracts/deploying/index.md b/public/content/translations/pt-br/developers/docs/smart-contracts/deploying/index.md index 88aa1119212..94593d0d84f 100644 --- a/public/content/translations/pt-br/developers/docs/smart-contracts/deploying/index.md +++ b/public/content/translations/pt-br/developers/docs/smart-contracts/deploying/index.md @@ -1,6 +1,6 @@ --- -title: Implantação de contratos inteligentes -description: +title: "Implantação de contratos inteligentes" +description: "Aprender como implantar contratos inteligentes para redes Ethereum, incluindo pré-requisitos, ferramentas e etapas de implantação." lang: pt-br --- @@ -8,52 +8,52 @@ Você precisa implantar o seu contrato inteligente para que ele esteja disponív Para implantar um contrato inteligente, você apenas envia uma transação Ethereum que contém o código do contrato inteligente compilado sem especificar os destinatários. -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -Você deve entender as [redes Ethereum](/developers/docs/networks/), [transações](/developers/docs/transactions/) e a [anatomia de contratos inteligentes](/developers/docs/smart-contracts/anatomy/) antes de implantar contratos inteligentes. +Você deve entender sobre [redes Ethereum](/developers/docs/networks/), [transações](/developers/docs/transactions/) e a [anatomia de contratos inteligentes](/developers/docs/smart-contracts/anatomy/) antes de implantar contratos inteligentes. -Implantar um contrato também custa ether (ETH), pois eles são armazenados na blockchain, portanto, você deveria estar familiarizado com [gás e taxas](/developers/docs/gas/) na Ethereum. +Implantar um contrato também custa ether (ETH), uma vez que eles são armazenados na blockchain, então você deve estar familiarizado com [gás e taxas](/developers/docs/gas/) no Ethereum. -Finalmente, você precisará compilar seu contrato antes de implantá-lo, então certifique-se de ter lido sobre [compilação de contratos inteligentes](/developers/docs/smart-contracts/compiling/). +Finalmente, você precisará compilar seu contrato antes de implantá-lo, portanto, certifique-se de que leu sobre a [compilação de contratos inteligentes](/developers/docs/smart-contracts/compiling/). ## Como implantar um contrato inteligente {#how-to-deploy-a-smart-contract} -### O que você precisará {#what-youll-need} +### Do que você vai precisar {#what-youll-need} -- Bytecode do seu contrato - isto é gerado através da [compilação](/developers/docs/smart-contracts/compiling/). +- O bytecode do seu contrato – gerado através da [compilação](/developers/docs/smart-contracts/compiling/) - Ether para gás – você definirá o seu limite de gás como outras transações, então esteja ciente de que a implantação do contrato precisa de muito mais gás do que uma simples transferência de ETH - um script de implantação ou um plugin -- acesso a um [nó Ethereum](/developers/docs/nodes-and-clients/), executando o seu próprio, conectando a um nó público ou por meio de uma chave de API usando um [serviço de nó](/developers/docs/nodes-and-clients/nodes-as-a-service/) +- acesso a um [nó do Ethereum](/developers/docs/nodes-and-clients/), seja executando o seu próprio, conectando-se a um nó público ou por meio de uma chave de API usando um [serviço de nós](/developers/docs/nodes-and-clients/nodes-as-a-service/) -### Como implantar um contrato inteligente {#steps-to-deploy} +### Passos para implantar um contrato inteligente {#steps-to-deploy} -Os passos específicos envolvidos dependerão do framework de desenvolvimento em questão. Por exemplo, confira [a documentação do Hardhat sobre como implementar seu contrato](https://hardhat.org/docs/tutorial/deploying) ou [a documentação do Foundry sobre como implementar e verificar um contrato inteligente](https://book.getfoundry.sh/forge/deploying). Uma vez implementado, seu contrato terá um endereço Ethereum igual qualquer outra [conta](/developers/docs/accounts/) e poderá ser verificado usando [ferramentas de verificação de código-fonte](/developers/docs/smart-contracts/verifying/#source-code-verification-tools). +Os passos específicos envolvidos dependerão do framework de desenvolvimento em questão. Por exemplo, você pode conferir a [documentação do Hardhat sobre a implantação de seus contratos](https://hardhat.org/docs/tutorial/deploying) ou a [documentação do Foundry sobre a implantação e verificação de um contrato inteligente](https://book.getfoundry.sh/forge/deploying). Uma vez implantado, seu contrato terá um endereço Ethereum como outras [contas](/developers/docs/accounts/) e poderá ser verificado usando [ferramentas de verificação de código-fonte](/developers/docs/smart-contracts/verifying/#source-code-verification-tools). ## Ferramentas relacionadas {#related-tools} -**Remix - _Remix IDE permite desenvolver, implantar e administrar contratos inteligentes para Ethereum como as cadeias de blocos._** +**Remix - _O Remix IDE permite desenvolver, implantar e administrar contratos inteligentes para blockchains como o Ethereum_** - [Remix](https://remix.ethereum.org) -**Tenderly - _Plataforma de desenvolvimento web3 que fornece blocos de construção para debugar, observar, e para infraestrutura para desenvolvimento, testes, monitoramento e operação de contratos inteligentes_** +**Tenderly - _Plataforma de desenvolvimento Web3 que fornece depuração, observabilidade e blocos de construção de infraestrutura para desenvolver, testar, monitorar e operar contratos inteligentes_** -- [tenderly.com](https://tenderly.co/) +- [tenderly.co](https://tenderly.co/) - [Documentação](https://docs.tenderly.co/) - [GitHub](https://github.com/Tenderly) - [Discord](https://discord.gg/eCWjuvt) -**Hardhat - _Um ambiente de desenvolvimento para compilar, implantar, testar e depurar seu software de Ethereum_** +**Hardhat - _Um ambiente de desenvolvimento para compilar, implantar, testar e depurar seu software Ethereum_** - [hardhat.org](https://hardhat.org/getting-started/) -- [Documentos na implantação de seus contratos](https://hardhat.org/docs/tutorial/deploying) +- [Documentação sobre a implantação de seus contratos](https://hardhat.org/docs/tutorial/deploying) - [GitHub](https://github.com/nomiclabs/hardhat) - [Discord](https://discord.com/invite/TETZs2KK4k) -**thirdweb - _Implemente facilmente qualquer contrato em qualquer cadeia compatível com EVM, usando um único comando_** +**thirdweb - _Implante facilmente qualquer contrato em qualquer cadeia compatível com EVM, usando um único comando_** - [Documentação](https://portal.thirdweb.com/deploy/) -**Crossmint - _Plataforma de desenvolvimento web3 de nível empresarial para implantar contratos inteligentes, habilitar pagamentos com cartão de crédito e entre cadeias, e usar APIs para criar, distribuir, vender, armazenar e editar NFTs._** +**Crossmint - _Plataforma de desenvolvimento web3 de nível empresarial para implantar contratos inteligentes, habilitar pagamentos com cartão de crédito e cross-chain e usar APIs para criar, distribuir, vender, armazenar e editar NFTs._** - [crossmint.com](https://www.crossmint.com) - [Documentação](https://docs.crossmint.com) @@ -62,20 +62,20 @@ Os passos específicos envolvidos dependerão do framework de desenvolvimento em ## Tutoriais relacionados {#related-tutorials} -- [Implementando o seu primeiro contrato inteligente](/developers/tutorials/deploying-your-first-smart-contract/) _– Uma introdução à implementação do seu primeiro contrato inteligente em uma rede de teste da Ethereum._ -- [Hello World | tutorial para contrato inteligente](/developers/tutorials/hello-world-smart-contract/)_ - Um tutorial fácil de seguir para criar & implementar um contrato inteligente básico na Ethereum._ -- [Interaja com outros contratos Solidity](/developers/tutorials/interact-with-other-contracts-from-solidity/) _– Como implantar um contrato inteligente a partir de um contrato existente e interagir com ele._ -- [Como diminuir o tamanho de seu contrato](/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/) _- Como reduzir o tamanho do seu contrato para mantê-lo abaixo do limite e economizar Gas_ +- [Implantando seu primeiro contrato inteligente](/developers/tutorials/deploying-your-first-smart-contract/) _– Uma introdução à implantação de seu primeiro contrato inteligente em uma rede de teste da Ethereum._ +- [Hello World | tutorial de contrato inteligente](/developers/tutorials/hello-world-smart-contract/) _– Um tutorial fácil de seguir para criar e implantar um contrato inteligente básico no Ethereum._ +- [Interaja com outros contratos a partir do Solidity](/developers/tutorials/interact-with-other-contracts-from-solidity/) _– Como implantar um contrato inteligente a partir de um contrato existente e interagir com ele._ +- [Como reduzir o tamanho do seu contrato](/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/) _- Como reduzir o tamanho do seu contrato para mantê-lo abaixo do limite e economizar gás_ -## Leia mais {#further-reading} +## Leitura adicional {#further-reading} - [https://docs.openzeppelin.com/learn/deploying-and-interacting](https://docs.openzeppelin.com/learn/deploying-and-interacting) - _OpenZeppelin_ -- [Implementando seus contratos com Hardhat](https://hardhat.org/docs/tutorial/deploying) - _Nomic Labs_ +- [Implantando seus contratos com o Hardhat](https://hardhat.org/docs/tutorial/deploying) - _Nomic Labs_ -_Conhece um recurso da comunidade que te ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ ## Tópicos relacionados {#related-topics} -- [Estruturas de desenvolvimento](/developers/docs/frameworks/) -- [Executando um nó Ethereum](/developers/docs/nodes-and-clients/run-a-node/) -- [Nódulos como serviço](/developers/docs/nodes-and-clients/nodes-as-a-service) +- [Frameworks de desenvolvimento](/developers/docs/frameworks/) +- [Executar um nó Ethereum](/developers/docs/nodes-and-clients/run-a-node/) +- [Nós como serviço](/developers/docs/nodes-and-clients/nodes-as-a-service) diff --git a/public/content/translations/pt-br/developers/docs/smart-contracts/formal-verification/index.md b/public/content/translations/pt-br/developers/docs/smart-contracts/formal-verification/index.md index 9ff72b630c0..2be5b23281d 100644 --- a/public/content/translations/pt-br/developers/docs/smart-contracts/formal-verification/index.md +++ b/public/content/translations/pt-br/developers/docs/smart-contracts/formal-verification/index.md @@ -1,12 +1,12 @@ --- -title: Verificação formal de contratos inteligentes -description: Uma visão geral da verificação formal de contratos inteligentes na Ethereum +title: "Verificação formal de contratos inteligentes" +description: "Uma visão geral da verificação formal de contratos inteligentes na Ethereum" lang: pt-br --- -[Contratos inteligentes](/developers/docs/smart-contracts/) permitem criar aplicativos descentralizados, sem necessidade de confiança, e robustos, que introduzem novos casos de uso e desbloqueiam valor para os usuários. Como os contratos inteligentes manipulam grandes quantidades de valor, a segurança é uma consideração crítica para desenvolvedores. +[Contratos inteligentes](/developers/docs/smart-contracts/) permitem criar aplicativos descentralizados, sem necessidade de confiança e robustos, que introduzem novos casos de uso e desbloqueiam valor para os usuários. Como os contratos inteligentes manipulam grandes quantidades de valor, a segurança é uma consideração crítica para desenvolvedores. -A verificação formal é uma das técnicas recomendadas para melhorar [a segurança do contrato inteligente](/developers/docs/smart-contracts/security/). Verificação formal, que usa [métodos formais](https://www.brookings.edu/techstream/formal-methods-as-a-path-toward-better-cybersecurity/) para especificar, conceber e verificar programas, tem sido usada há anos para garantir a correção de sistemas críticos de hardware e software. +A verificação formal é uma das técnicas recomendadas para melhorar a [segurança de contratos inteligentes](/developers/docs/smart-contracts/security/). A verificação formal, que usa [métodos formais](https://www.brookings.edu/techstream/formal-methods-as-a-path-toward-better-cybersecurity/) para especificar, projetar e verificar programas, tem sido usada há anos para garantir a correção de sistemas de hardware e software críticos. Quando implementada em contratos inteligentes, a verificação formal pode comprovar que a lógica de negócio de um contrato cumpre uma especificação predefinida. Comparado com outros métodos para avaliar a exatidão do código do contrato, como testes, verificação formal dá mais garantias de que um contrato inteligente está funcionalmente correto. @@ -18,7 +18,7 @@ Comportamentos esperados do sistema (um contrato inteligente, neste caso) são d ### O que é um modelo formal? {#what-is-a-formal-model} -Na ciência da computação, um [modelo formal](https://en.wikipedia.org/wiki/Model_of_computation) é uma descrição matemática de um processo computacional. Programas são abstraídos em funções matemáticas (equações), com o modelo que descreve como as saídas para funções são computadas dada uma entrada. +Em ciência da computação, um [modelo formal](https://en.wikipedia.org/wiki/Model_of_computation) é uma descrição matemática de um processo computacional. Programas são abstraídos em funções matemáticas (equações), com o modelo que descreve como as saídas para funções são computadas dada uma entrada. Modelos formais fornecem um nível de abstração sobre o qual a análise do comportamento de um programa pode ser avaliada. A existência de modelos formais permite a criação de uma _especificação formal_, que descreve as propriedades desejadas do modelo em questão. @@ -26,15 +26,15 @@ Diferentes técnicas são utilizadas para modelagem de contratos inteligentes pa Os modelos mais gerais focam na relação entre contratos inteligentes e agentes externos, como contas de propriedade externa (EOA), contas de contrato e ambiente da blockchain. Esses modelos são úteis para definir propriedades que especificam como um contrato deve se comportar em resposta a determinadas interações do usuário. -Inversamente, outros modelos formais se concentram no comportamento de baixo nível de um contrato inteligente. Embora os modelos mais gerais possam ajudar no raciocínio sobre a funcionalidade de um contrato, eles podem não conseguir capturar detalhes sobre o funcionamento interno da implementação. Modelos de baixo nível aplicam uma visualização de caixa branca para programar a análise e dependem de representações de baixo nível de aplicações de contrato inteligentes, como traços de programas e [gráficos de controle de fluxo](https://en.wikipedia.org/wiki/Control-flow_graph), justificando sobre propriedades relevantes para a execução de um contrato. +Inversamente, outros modelos formais se concentram no comportamento de baixo nível de um contrato inteligente. Embora os modelos mais gerais possam ajudar no raciocínio sobre a funcionalidade de um contrato, eles podem não conseguir capturar detalhes sobre o funcionamento interno da implementação. Modelos de baixo nível aplicam uma visão de caixa-branca à análise de programas e dependem de representações de nível inferior de aplicativos de contratos inteligentes, como rastreamentos de programas e [gráficos de fluxo de controle](https://en.wikipedia.org/wiki/Control-flow_graph), para analisar propriedades relevantes para a execução de um contrato. -Modelos de baixo nível são considerados ideais uma vez que representam a execução real de um contrato inteligente no ambiente de execução da Ethereum (ou seja, a [EVM](/developers/docs/evm/)). Técnicas de modelagem de baixo nível são especialmente úteis para estabelecer propriedades de segurança críticas em contratos inteligentes e para detectar potenciais vulnerabilidades. +Modelos de baixo nível são considerados ideais, pois representam a execução real de um contrato inteligente no ambiente de execução do Ethereum (ou seja, a [EVM](/developers/docs/evm/)). Técnicas de modelagem de baixo nível são especialmente úteis para estabelecer propriedades de segurança críticas em contratos inteligentes e para detectar potenciais vulnerabilidades. ### O que é uma especificação formal? {#what-is-a-formal-specification} Uma especificação é simplesmente um requisito técnico que determinado sistema tem de cumprir. Em programação, as especificações representam ideias gerais sobre a execução de um programa (ou seja, o que o programa deve fazer). -No contexto dos contratos inteligentes, especificações formais se referem a _propriedades_—descrições formais dos requisitos que um contrato deve cumprir. Essas propriedades são descritas como "invariáveis" e representam afirmações lógicas sobre a execução de um contrato que devem permanecer verdadeiras em todas as circunstâncias possíveis, sem quaisquer exceções. +No contexto de contratos inteligentes, as especificações formais se referem a _propriedades_ — descrições formais dos requisitos que um contrato deve satisfazer. Essas propriedades são descritas como "invariáveis" e representam afirmações lógicas sobre a execução de um contrato que devem permanecer verdadeiras em todas as circunstâncias possíveis, sem quaisquer exceções. Assim, podemos pensar em uma especificação formal como uma coleção de instruções escritas em uma linguagem formal que descreve a execução pretendida de um contrato inteligente. As especificações cobrem as propriedades de um contrato e definem como o contrato deve se comportar em diferentes circunstâncias. O objetivo da verificação formal é determinar se um contrato inteligente possui essas propriedades (conhecidas como invariáveis ou invariantes) e que essas propriedades não são violadas durante a execução. @@ -44,55 +44,55 @@ As especificações formais são fundamentais no desenvolvimento de implementaç Especificações formais permitem o raciocínio matemático sobre a exatidão da execução do programa. Como nos modelos formais, as especificações formais podem capturar propriedades de alto nível ou o comportamento de baixo nível de uma implementação de contrato. -Especificações formais são derivadas usando elementos de [lógica de programa](https://en.wikipedia.org/wiki/Logic_programming), que permitem raciocínio formal sobre as propriedades de um programa. Uma lógica do programa tem regras formais que expressam (na linguagem matemática) o comportamento esperado de um programa. Várias lógicas de programa são usadas na criação de especificações formais, incluindo a [lógica de acessibilidade](https://en.wikipedia.org/wiki/Reachability_problem), [lógica temporal](https://en.wikipedia.org/wiki/Temporal_logic), e [lógica Hoare](https://en.wikipedia.org/wiki/Hoare_logic). +As especificações formais são derivadas usando elementos da [lógica de programação](https://en.wikipedia.org/wiki/Logic_programming), que permitem o raciocínio formal sobre as propriedades de um programa. Uma lógica do programa tem regras formais que expressam (na linguagem matemática) o comportamento esperado de um programa. Várias lógicas de programação são usadas na criação de especificações formais, incluindo [lógica de alcançabilidade](https://en.wikipedia.org/wiki/Reachability_problem), [lógica temporal](https://en.wikipedia.org/wiki/Temporal_logic) e [lógica de Hoare](https://en.wikipedia.org/wiki/Hoare_logic). -Especificações formais para contratos inteligentes podem ser classificadas geralmente como especificações de **alto nível** ou de **baixo nível**. Independentemente da categoria a que pertence uma especificação, ela deve descrever de forma adequada e inequívoca a propriedade do sistema em análise. +As especificações formais para contratos inteligentes podem ser classificadas de forma ampla como especificações **de alto nível** ou **de baixo nível**. Independentemente da categoria a que pertence uma especificação, ela deve descrever de forma adequada e inequívoca a propriedade do sistema em análise. ### Especificações de alto nível {#high-level-specifications} -Como o nome sugere, uma especificação de alto nível (também chamada de "especificação orientada ao modelo") descreve o comportamento de alto nível de um programa. Especificações de alto nível modelam um contrato inteligente como uma [máquina de estado finito](https://en.wikipedia.org/wiki/Finite-state_machine) (FSM), que pode fazer a transição entre os estados realizando operações, com lógica temporal usada para definir propriedades formais para o modelo FSM. +Como o nome sugere, uma especificação de alto nível (também chamada de "especificação orientada ao modelo") descreve o comportamento de alto nível de um programa. As especificações de alto nível modelam um contrato inteligente como uma [máquina de estados finitos](https://en.wikipedia.org/wiki/Finite-state_machine) (FSM), que pode transitar entre estados realizando operações, com a lógica temporal sendo usada para definir propriedades formais para o modelo FSM. -[Lógicas temporais](https://en.wikipedia.org/wiki/Temporal_logic) são "regras para raciocínio de proposições qualificadas em termos de tempo (por exemplo, "Eu tenho _sempre_ fome" ou "Eu vou _em algum momento_ estar com fome")." Quando aplicadas à verificação formal, as lógicas temporais são usadas para declarar asserções sobre o comportamento correto de sistemas modelados como máquinas de estado. Especificamente, uma lógica temporal descreve os estados futuros em que um contrato inteligente pode estar e como ele transita entre estados. +[Lógicas temporais](https://en.wikipedia.org/wiki/Temporal_logic) são "regras para raciocinar sobre proposições qualificadas em termos de tempo (por exemplo, "Estou _sempre_ com fome" ou "Eu _eventualmente_ ficarei com fome")." Quando aplicadas à verificação formal, as lógicas temporais são usadas para declarar asserções sobre o comportamento correto de sistemas modelados como máquinas de estado. Especificamente, uma lógica temporal descreve os estados futuros em que um contrato inteligente pode estar e como ele transita entre estados. -Especificações de alto nível geralmente capturam duas propriedades temporais críticas para contratos inteligentes: **segurança** e **vivacidade** (liveness). As propriedades de segurança representam a ideia de que “nada de mal jamais acontece” e geralmente expressam invariância. Uma propriedade de segurança pode definir requisitos gerais de software, como liberdade de [impasse](https://www.techtarget.com/whatis/definition/deadlock) ou expressar propriedades específicas de domínio para contratos (por exemplo, invariáveis no controle de acesso para funções, valores admissíveis de variáveis de estado ou condições para transferências de token). +As especificações de alto nível geralmente capturam duas propriedades temporais críticas para contratos inteligentes: **segurança** e **vivacidade (liveness)**. As propriedades de segurança representam a ideia de que “nada de mal jamais acontece” e geralmente expressam invariância. Uma propriedade de segurança pode definir requisitos gerais de software, como a ausência de [deadlock](https://www.techtarget.com/whatis/definition/deadlock), ou expressar propriedades específicas de domínio para contratos (p. ex., invariantes no controle de acesso para funções, valores admissíveis de variáveis de estado ou condições para transferências de tokens). -Veja, por exemplo, este requisito de segurança que cobre condições para usar `transfer()` ou `transferFrom()` em contratos de token ERC-20: _ “O saldo de um remetente nunca é inferior à quantidade solicitada de tokens a serem enviados.”_. Essa descrição em linguagem natural de uma invariável de contrato pode ser traduzida em uma especificação formal (matemática), que pode então ser rigorosamente verificada para validade. +Considere, por exemplo, este requisito de segurança que abrange as condições para usar `transfer()` ou `transferFrom()` em contratos de token ERC-20: _“O saldo de um remetente nunca é inferior à quantidade solicitada de tokens a serem enviados.”_. Essa descrição em linguagem natural de uma invariável de contrato pode ser traduzida em uma especificação formal (matemática), que pode então ser rigorosamente verificada para validade. -Propriedades de vivacidade afirmam que “algo eventualmente bom acontece” e se refere à capacidade do contrato progredir por diferentes estados. Um exemplo de uma propriedade de vivacidade é a “liquidez”, que se refere à capacidade do contrato transferir seus saldos aos usuários por solicitação. Se essa propriedade for violada, os usuários não poderiam retirar os ativos armazenados no contrato, como aconteceu com o [incidente de carteira do Parity](https://www.cnbc.com/2017/11/08/accidental-bug-may-have-frozen-280-worth-of-ether-on-parity-wallet.html). +Propriedades de vivacidade afirmam que “algo eventualmente bom acontece” e se refere à capacidade do contrato progredir por diferentes estados. Um exemplo de uma propriedade de vivacidade é a “liquidez”, que se refere à capacidade do contrato transferir seus saldos aos usuários por solicitação. Se essa propriedade for violada, os usuários não poderão sacar os ativos armazenados no contrato, como o que aconteceu com o [incidente da carteira Parity](https://www.cnbc.com/2017/11/08/accidental-bug-may-have-frozen-280-worth-of-ether-on-parity-wallet.html). ### Especificações de baixo nível {#low-level-specifications} As especificações de alto nível tomam como ponto de partida um modelo de estado finito de um contrato e definem as propriedades desejadas deste modelo. Em contraste, as especificações de baixo nível (também chamadas de "especificações orientadas à propriedade") muitas vezes modelam programas (contratos inteligentes) como sistemas que compreendem uma coleção de funções matemáticas e descrevem o comportamento correto desses sistemas. -Em termos simples, as especificações de baixo nível analisam _traços de programa_ e tentam definir propriedades de um contrato inteligente sobre esses traços. Traços se referem a sequências de execuções de funções que alteram o estado de um contrato inteligente; por isso, as especificações de baixo nível ajudam a especificar requisitos para uma execução interna de contrato. +Em termos mais simples, as especificações de baixo nível analisam _rastreamentos de programa_ e tentam definir propriedades de um contrato inteligente sobre esses rastreamentos. Traços se referem a sequências de execuções de funções que alteram o estado de um contrato inteligente; por isso, as especificações de baixo nível ajudam a especificar requisitos para uma execução interna de contrato. Especificações formais de baixo nível podem ser fornecidas como propriedades do estilo Hoare ou invariáveis em caminhos de execução. -### Propriedades do estilo Hoare {#hoare-style-properties} +### Propriedades no estilo Hoare {#hoare-style-properties} -[Hore Logic](https://en.wikipedia.org/wiki/Hoare_logic) fornece um conjunto de regras formais para raciocinar sobre a correção de programas, incluindo contratos inteligentes. Uma propriedade de estilo Hoare é representada por um triplo Hoare `{P}c{Q}`, onde `c` é um programa e `P` e `Q` são predicados no estado do `c` (ou seja, o programa), formalmente descritos como _precondições_ e _pós-condições_, respectivamente. +A [Lógica de Hoare](https://en.wikipedia.org/wiki/Hoare_logic) fornece um conjunto de regras formais para raciocinar sobre a correção de programas, incluindo contratos inteligentes. Uma propriedade de estilo Hoare é representada por uma tripla de Hoare `{P}c{Q}`, onde `c` é um programa e `P` e `Q` são predicados sobre o estado de `c` (ou seja, o programa), formalmente descritos como _pré-condições_ e _pós-condições_, respectivamente. -Uma precondição é um predicado que descreve as condições necessárias para a execução correta de uma função; os usuários que chamam um contrato devem satisfazer este requisito. Uma pós-condição é um predicado que descreve a condição que uma função estabelece se executada corretamente; os usuários podem esperar que essa condição seja verdadeira após chamar a função. Uma _invariável_ na lógica Hoare é um predicado que é preservado pela execução de uma função (ou seja, não muda). +Uma precondição é um predicado que descreve as condições necessárias para a execução correta de uma função; os usuários que chamam um contrato devem satisfazer este requisito. Uma pós-condição é um predicado que descreve a condição que uma função estabelece se executada corretamente; os usuários podem esperar que essa condição seja verdadeira após chamar a função. Uma _invariante_ na lógica de Hoare é um predicado que é preservado pela execução de uma função (ou seja, não muda). -As especificações do estilo Hoare podem garantir _correção parcial_ ou _correção total_. A implementação de uma função de contrato é "parcialmente correta" se a precondição se confirmar verdadeira antes da função ser executada e, se a execução terminar, a pós-condição também é verdadeira. A prova de correção total é obtida se uma precondição for verdadeira antes da execução da função, a execução é garantida para terminar e, quando isso acontecer, a pós-condição é verdadeira. +As especificações de estilo Hoare podem garantir _correção parcial_ ou _correção total_. A implementação de uma função de contrato é "parcialmente correta" se a precondição se confirmar verdadeira antes da função ser executada e, se a execução terminar, a pós-condição também é verdadeira. A prova de correção total é obtida se uma precondição for verdadeira antes da execução da função, a execução é garantida para terminar e, quando isso acontecer, a pós-condição é verdadeira. Obter a comprovação de correção total é difícil, pois algumas execuções podem atrasar antes de terminar ou nunca terminar nada. Dito isso, a questão de se a execução termina é sem dúvida um ponto discutível, já que o mecanismo de gás da Ethereum evita loops infinitos de programa (a execução termina, ou com sucesso, ou termina devido a um erro de 'falta de gás'). As especificações de contrato inteligente criadas usando a lógica de Hoare terão precondições, pós-condições e invariáveis definidas para a execução de funções e loops em um contrato. Precondições geralmente incluem a possibilidade de entradas erradas para uma função, com pós-condições descrevendo a resposta esperada para essas entradas (por exemplo, lançando uma exceção específica). Dessa maneira, as propriedades do estilo Hoare são eficazes para garantir a correção das implementações de contratos. -Muitas estruturas formais de verificação usam especificações no estilo Hoare para comprovar a correção semântica das funções. Também é possível adicionar propriedades do estilo Hoare (como asserções) diretamente ao código do contrato usando as instruções `require` e `assert` no Solidity. +Muitas estruturas formais de verificação usam especificações no estilo Hoare para comprovar a correção semântica das funções. Também é possível adicionar propriedades no estilo Hoare (como asserções) diretamente ao código do contrato usando as instruções `require` e `assert` no Solidity. -As instruções `require` expressam uma precondição ou invariável e são frequentemente usadas para validar as entradas do usuário, enquanto `assert` captura uma pós-condição necessária para segurança. Por exemplo, o controle de acesso adequado para funções (um exemplo de uma propriedade de segurança) pode ser alcançado usando `require` como uma verificação de precondição na identidade da conta de chamada. Da mesma forma, uma invariável em valores permitidos de variáveis de estado em um contrato (por exemplo, número total de tokens em circulação) pode ser protegida contra violação usando `assert` para confirmar o estado do contrato após a execução da função. +As instruções `require` expressam uma pré-condição ou invariante e são frequentemente usadas para validar as entradas do usuário, enquanto `assert` captura uma pós-condição necessária para a segurança. Por exemplo, o controle de acesso adequado para funções (um exemplo de uma propriedade de segurança) pode ser alcançado usando `require` como uma verificação de pré-condição na identidade da conta chamadora. Da mesma forma, uma invariante sobre os valores admissíveis das variáveis de estado em um contrato (por exemplo, o número total de tokens em circulação) pode ser protegida de violação usando `assert` para confirmar o estado do contrato após a execução da função. -### Propriedades de nível de traços {#trace-level-properties} +### Propriedades em nível de rastreamento {#trace-level-properties} Especificações baseadas em traços descrevem operações que transitam um contrato entre diferentes estados e as relações entre essas operações. Como foi explicado anteriormente, os traços são sequências de operações que alteram o estado de um contrato de uma forma específica. -Essa abordagem depende do modelo de contratos inteligentes como sistemas de transição de estado com alguns estados predefinidos (descritos por variáveis de estado) junto com um conjunto de transições predefinidas (descritas pelas funções de contrato). Além disso, um [gráfico de controle de fluxo ](https://www.geeksforgeeks.org/software-engineering-control-flow-graph-cfg/) (CFG), que é uma representação gráfica do fluxo de execução de um programa, é frequentemente utilizado para descrever a semântica operacional de um contrato. Aqui, cada traço representado como um caminho no gráfico do fluxo de controle. +Essa abordagem depende do modelo de contratos inteligentes como sistemas de transição de estado com alguns estados predefinidos (descritos por variáveis de estado) junto com um conjunto de transições predefinidas (descritas pelas funções de contrato). Além disso, um [gráfico de fluxo de controle](https://www.geeksforgeeks.org/software-engineering-control-flow-graph-cfg/) (CFG), que é uma representação gráfica do fluxo de execução de um programa, é frequentemente usado para descrever a semântica operacional de um contrato. Aqui, cada traço representado como um caminho no gráfico do fluxo de controle. Em primeiro lugar, as especificações de nível de traços são usadas para raciocinar sobre padrões de execução interna em contratos inteligentes. Ao criar especificações de nível de traços, afirmamos os caminhos de execução admissíveis (ou seja, transições de estado) para um contrato inteligente. Utilizando técnicas, como a execução simbólica, podemos verificar formalmente que a execução nunca segue um caminho não definido no modelo formal. -Vamos usar um exemplo de um contrato com [DAO](/dao/) que tem algumas funções publicamente acessíveis para descrever propriedades de nível de traços. Aqui, assumimos que o contrato DAO permite aos usuários executar as seguintes operações: +Vamos usar um exemplo de um contrato de [DAO](/dao/) que tem algumas funções publicamente acessíveis para descrever propriedades de nível de rastreamento. Aqui, assumimos que o contrato DAO permite aos usuários executar as seguintes operações: - Depositar fundos @@ -100,7 +100,7 @@ Vamos usar um exemplo de um contrato com [DAO](/dao/) que tem algumas funções - Reivindicar um reembolso se eles não votarem em uma proposta -Exemplo de propriedades de nível de traços poderia ser _"usuários que não depositam fundos não podem votar em uma proposta"_ ou _"usuários que não votarem em uma proposta devem estar sempre aptos a reivindicar um reembolso"_. Ambas as propriedades afirmam sequências preferidas de execução (votação não pode acontecer _antes_ de depositar fundos, e reivindicar um reembolso não pode acontecer _após_ a votação de uma proposta). +Exemplos de propriedades em nível de rastreamento poderiam ser _“usuários que não depositam fundos não podem votar em uma proposta”_ ou _“usuários que não votam em uma proposta devem sempre poder solicitar um reembolso”_. Ambas as propriedades afirmam sequências de execução preferidas (a votação não pode acontecer _antes_ de depositar fundos e a solicitação de reembolsos não pode acontecer _depois_ de votar em uma proposta). ## Técnicas para verificação formal de contratos inteligentes {#formal-verification-techniques} @@ -108,19 +108,19 @@ Exemplo de propriedades de nível de traços poderia ser _"usuários que não de A verificação de modelo é uma técnica de verificação formal na qual um algoritmo verifica um modelo formal de um contrato inteligente em relação à sua especificação. No modelo de verificação, os contratos inteligentes são frequentemente representados como sistemas de transição de estado, enquanto as propriedades nos estados de contrato permitidos são definidas usando lógica temporal. -A verificação de modelo requer a criação de uma representação matemática abstrata de um sistema (ou seja, um contrato) e a expressão das propriedades desse sistema usando fórmulas enraizadas na [lógica proposicional](https://www.baeldung.com/cs/propositional-logic). Isto simplifica a tarefa do algoritmo de verificação de modelo, ou seja, comprovar que um modelo matemático cumpre uma dada fórmula lógica. +A verificação de modelo requer a criação de uma representação matemática abstrata de um sistema (ou seja, um contrato) e a expressão de propriedades desse sistema usando fórmulas baseadas na [lógica proposicional](https://www.baeldung.com/cs/propositional-logic). Isto simplifica a tarefa do algoritmo de verificação de modelo, ou seja, comprovar que um modelo matemático cumpre uma dada fórmula lógica. -A verificação de modelo na verificação formal é usada principalmente para avaliar propriedades temporais que descrevem o comportamento de um contrato ao longo do tempo. As propriedades temporais para contratos inteligentes incluem _segurança_ e _vivacidade_, a qual explicamos anteriormente. +A verificação de modelo na verificação formal é usada principalmente para avaliar propriedades temporais que descrevem o comportamento de um contrato ao longo do tempo. As propriedades temporais para contratos inteligentes incluem _segurança_ e _vivacidade_, que explicamos anteriormente. -Por exemplo, uma propriedade de segurança relacionada ao controle de acesso (exemplo: _Somente o proprietário do contrato pode chamar `selfdestruct`_) pode ser escrita na lógica formal. Depois disso, o algoritmo de verificação de modelos pode verificar se o contrato satisfaz esta especificação formal. +Por exemplo, uma propriedade de segurança relacionada ao controle de acesso (p. ex., _Apenas o proprietário do contrato pode chamar `selfdestruct`_) pode ser escrita em lógica formal. Depois disso, o algoritmo de verificação de modelos pode verificar se o contrato satisfaz esta especificação formal. A verificação de modelo usa a exploração do espaço do estado, que envolve construir todos os estados possíveis de um contrato inteligente e tentar encontrar estados acessíveis que resultem em violações de propriedades. No entanto, isso pode levar a um número infinito de estados (conhecido como o "problema da explosão de estado"), por isso, os verificadores de modelos dependem de técnicas de abstração para possibilitar uma análise eficiente de contratos inteligentes. -### Comprovação de teorema {#theorem-proving} +### Prova de teoremas {#theorem-proving} Comprovação de teorema é um método de raciocínio matemático sobre a exatidão de programas, incluindo contratos inteligentes. Ela envolve transformar o modelo do sistema de um contrato e as suas especificações em fórmulas matemáticas (declarações lógicas). -O objetivo da comprovação de teorema é verificar a equivalência lógica entre essas declarações. “Equivalência lógica” (também chamada de “bi-implicação lógica”) é um tipo de relação entre duas declarações, de modo que a primeira declaração é verdadeira, _se e somente se_, a segunda declaração for verdadeira. +O objetivo da comprovação de teorema é verificar a equivalência lógica entre essas declarações. A “equivalência lógica” (também chamada de “bi-implicação lógica”) é um tipo de relação entre duas instruções, de modo que a primeira instrução é verdadeira _se, e somente se_, a segunda instrução for verdadeira. A relação necessária (equivalência lógica) entre as declarações sobre o modelo de um contrato e sua propriedade é formulada como uma declaração provável (chamada teorema). Usando um sistema formal de inferência, o comprovador do teorema automatizado pode verificar a validade do teorema. Em outras palavras, um comprovador de teorema pode comprovar de forma conclusiva se o modelo de um contrato inteligente corresponde precisamente às suas especificações. @@ -130,13 +130,13 @@ Como resultado, muitas vezes a assistência humana é necessária para guiar o c ### Execução simbólica {#symbolic-execution} -Execução simbólica é um método de análise de um contrato inteligente que executa funções usando _valores simbólicos_ (por exemplo, `x > 5`) em vez de _valores concretos_ (por exemplo, `x == 5`). Como técnica formal de verificação, a execução simbólica é usada para argumentar formalmente sobre propriedades de traços no código de um contrato. +A execução simbólica é um método de analisar um contrato inteligente executando funções usando _valores simbólicos_ (p. ex., `x > 5`) em vez de _valores concretos_ (p. ex., `x == 5`). Como técnica formal de verificação, a execução simbólica é usada para argumentar formalmente sobre propriedades de traços no código de um contrato. -A execução simbólica representa um traço de execução como uma fórmula matemática sobre valores simbólicos de entrada, também chamados de _predicado de caminho_. Um [SMT solver](https://en.wikipedia.org/wiki/Satisfiability_modulo_theories) é usado para verificar se um predicado de caminho é "satisfatório" (ou seja, existe um valor que pode cumprir a fórmula). Se um caminho vulnerável for cumprido, o solucionador SMT gerará um valor concreto que acionará a execução de guias em direção àquele caminho. +A execução simbólica representa um rastreamento de execução como uma fórmula matemática sobre valores de entrada simbólicos, também chamado de _predicado de caminho_. Um [solucionador SMT](https://en.wikipedia.org/wiki/Satisfiability_modulo_theories) é usado para verificar se um predicado de caminho é "satisfatível" (ou seja, existe um valor que pode satisfazer a fórmula). Se um caminho vulnerável for cumprido, o solucionador SMT gerará um valor concreto que acionará a execução de guias em direção àquele caminho. -Suponha que a função de um contrato inteligente tome como entrada, um valor `uint` (`x`) e reverta quando `x` for maior que `5` e também menor que `10`. Encontrar um valor para `x` que dispara o erro usando um procedimento de teste normal exigiria ser executado por dezenas de casos de teste (ou mais) sem a garantia de realmente encontrar uma entrada de disparo de erro. +Suponha que a função de um contrato inteligente receba como entrada um valor `uint` (`x`) e reverta quando `x` for maior que `5` e também menor que `10`. Encontrar um valor para `x` que acione o erro usando um procedimento de teste normal exigiria a execução de dezenas de casos de teste (ou mais) sem a garantia de encontrar de fato uma entrada que acione o erro. -Inversamente, uma ferramenta de execução simbólica executaria a função com o valor simbólico: `X > 5 ∧ X < 10` (ou seja, `x` é maior que 5 E `x` é menor que 10). O predicado do caminho associado `x = X > 5 ∧ X < 10` seria dada a um solucionador de SMT para resolver. Se determinado valor satisfaz a fórmula `x = X > 5 ∧ X < 10`, o solucionador SMT irá calculá-lo—por exemplo, o solucionador pode produzir `7` como um valor para `x`. +Por outro lado, uma ferramenta de execução simbólica executaria a função com o valor simbólico: `X > 5 ∧ X < 10` (ou seja, `x` é maior que 5 E `x` é menor que 10). O predicado de caminho associado `x = X > 5 ∧ X < 10` seria então fornecido a um solucionador SMT para ser resolvido. Se um valor específico satisfizer a fórmula `x = X > 5 ∧ X < 10`, o solucionador SMT o calculará — por exemplo, o solucionador pode produzir `7` como um valor para `x`. Como a execução simbólica depende de entradas para um programa, e o conjunto de entradas para explorar todos os estados acessíveis é potencialmente infinito, ela ainda é uma forma de teste. Contudo, como mostrado no exemplo, a execução simbólica é mais eficiente do que os testes regulares para encontrar entradas que desencadeiem violações de propriedade. @@ -152,25 +152,26 @@ function safe_add(uint x, uint y) returns(uint z){ require(z>=y); return z; +} ``` -Um traço de execução que resulta em um overflow de número inteiro precisaria satisfazer a fórmula: `z = x + y E (z >= x) E (z=>y) E (z < x OU z < y)` É improvável que uma fórmula como essa seja resolvida, portanto ela serve uma comprovação matemática de que a função `safe_add` nunca sofre overflow. +Um rastreamento de execução que resulta em um overflow de inteiro precisaria satisfazer a fórmula: `z = x + y AND (z >= x) AND (z >= y) AND (z < x OR z < y)` É improvável que tal fórmula seja resolvida, portanto, serve como prova matemática de que a função `safe_add` nunca sofre overflow. -### Por que usar a verificação formal para contratos inteligentes? {#benefits-of-formal-verification} +### Por que usar a verificação formal para contratos inteligentes? Benefícios da verificação formal {#benefits-of-formal-verification} #### Necessidade de confiabilidade {#need-for-reliability} -A verificação formal é utilizada para avaliar a exatidão de sistemas críticos em matéria de segurança, cuja falha pode ter consequências devastadoras, como a morte, ferimentos ou a ruína financeira. Contratos inteligentes são aplicações de alto valor que controlam enormes quantidades de valor, e erros simples na concepção podem levar a [perdas irrecuperáveis para usuários](https://www.freecodecamp.org/news/a-hacker-stole-31m-of-ether-how-it-happened-and-what-it-means-for-ethereum-9e5dc29e33ce/amp/). Verificar formalmente um contrato antes da implantação pode, no entanto, aumentar as garantias de que ele executará como esperado, uma vez funcionando na blockchain. +A verificação formal é utilizada para avaliar a exatidão de sistemas críticos em matéria de segurança, cuja falha pode ter consequências devastadoras, como a morte, ferimentos ou a ruína financeira. Os contratos inteligentes são aplicativos de alto valor que controlam enormes quantidades de valor, e erros simples no projeto podem levar a [perdas irrecuperáveis para os usuários](https://www.freecodecamp.org/news/a-hacker-stole-31m-of-ether-how-it-happened-and-what-it-means-for-ethereum-9e5dc29e33ce/amp/). Verificar formalmente um contrato antes da implantação pode, no entanto, aumentar as garantias de que ele executará como esperado, uma vez funcionando na blockchain. A confiabilidade é uma qualidade altamente desejada em qualquer contrato inteligente, especialmente porque o código implantado na Ethereum Virtual Machine (EVM) é tipicamente imutável. Com melhorias pós-lançamento não prontamente acessíveis, a necessidade de garantir a confiabilidade dos contratos torna necessária a verificação formal. A verificação formal é capaz de detectar problemas complicados, como underflows e overflows de inteiros, reentrância, e otimizações de gás fracas, que podem passar por auditores e testadores. -#### Comprovar correção funcional {#prove-functional-correctness} +#### Comprovação da correção funcional {#prove-functional-correctness} O teste do programa é o método mais comum de comprovar que um contrato inteligente cumpre alguns requisitos. Isso envolve a execução de um contrato com uma amostra dos dados que se espera que eles lidem e analisar seu comportamento. Se o contrato retorna os resultados esperados para os dados da amostra, então os desenvolvedores têm uma prova objetiva de sua exatidão. -No entanto, esta abordagem não pode comprovar a execução correta para valores de entrada que não fazem parte da amostra. Portanto, testar um contrato pode ajudar a detectar erros (ou seja, se alguns caminhos de código falham em retornar os resultados desejados durante a execução), mas **ele não pode comprovar de forma conclusiva a ausência de bugs**. +No entanto, esta abordagem não pode comprovar a execução correta para valores de entrada que não fazem parte da amostra. Portanto, testar um contrato pode ajudar a detectar bugs (ou seja, se alguns caminhos de código não retornarem os resultados desejados durante a execução), mas **não pode provar conclusivamente a ausência de bugs**. -Inversamente, verificação formal pode comprovar formalmente que um contrato inteligente cumpre as exigências de uma infinita gama de execuções _sem_ executar nada do contrato. Isso requer a criação de uma especificação formal que descreva precisamente comportamentos de contratos corretos e desenvolva um modelo formal (matemático) do sistema do contrato. Em seguida, podemos seguir um procedimento formal de prova para verificar a consistência entre o modelo do contrato e a sua especificação. +Por outro lado, a verificação formal pode provar formalmente que um contrato inteligente satisfaz os requisitos para uma gama infinita de execuções _sem_ executar o contrato. Isso requer a criação de uma especificação formal que descreva precisamente comportamentos de contratos corretos e desenvolva um modelo formal (matemático) do sistema do contrato. Em seguida, podemos seguir um procedimento formal de prova para verificar a consistência entre o modelo do contrato e a sua especificação. Com a verificação formal, a questão de verificar se a lógica de negócios de um contrato satisfaz os requisitos é uma proposta matemática que pode ser comprovada ou reprovada. Ao comprovar formalmente uma proposição, podemos verificar um número infinito de casos de teste com um número finito de etapas. Desta forma, a verificação formal tem melhores perspectivas de comprovar que um contrato é funcionalmente correto no que se refere a uma especificação. @@ -182,7 +183,7 @@ Contratos inteligentes, pelo menos em certa medida, preenchem ambos os requisito ### Ciclo de desenvolvimento mais rápido {#faster-development-cycle} -Técnicas de verificação formais, como verificação de modelo e execução simbólica, geralmente são mais eficientes do que a análise regular do código do contrato inteligente (executado durante testes ou auditorias). Isso é porque a verificação formal depende de valores simbólicos para testar declarações ("e se um usuário tentar retirar _n_ ether?") Ao contrário de testes que usam valores concretos ("e se um usuário tentar retirar 5 ethers?"). +Técnicas de verificação formais, como verificação de modelo e execução simbólica, geralmente são mais eficientes do que a análise regular do código do contrato inteligente (executado durante testes ou auditorias). Isso ocorre porque a verificação formal se baseia em valores simbólicos para testar asserções ("e se um usuário tentar sacar _n_ ether?") Ao contrário de testes que usam valores concretos ("e se um usuário tentar retirar 5 ethers?"). Variáveis de entrada simbólica podem cobrir várias classes de valores concretos, assim as abordagens de verificação formal prometem mais cobertura de código em um período de tempo mais curto. Quando usado de forma eficaz, a verificação formal pode acelerar o ciclo de desenvolvimento para desenvolvedores. @@ -206,78 +207,78 @@ Se as especificações forem mal escritas, as violações de propriedades - que Verificação formal acarreta uma série de problemas de desempenho. Por exemplo, os problemas de explosão de estado e caminho encontrados durante a verificação do modelo e a verificação simbólica, respectivamente, podem afetar os procedimentos de verificação. Além disso, as ferramentas formais de verificação muitas vezes usam solucionadores SMT e outros solucionadores de restrições em sua camada subjacente, e esses solucionadores dependem de procedimentos computacionais intensos. -Além disso, nem sempre é possível que os verificadores de programa determinem se uma propriedade (descrita como uma fórmula lógica) pode ser satisfeita ou não (o "[decidability problem](https://en.wikipedia.org/wiki/Decision_problem)") porque um programa pode nunca terminar. Como tal, pode ser impossível comprovar algumas propriedades de um contrato, mesmo se estiver bem especificado. +Além disso, nem sempre é possível para os verificadores de programas determinar se uma propriedade (descrita como uma fórmula lógica) pode ser satisfeita ou não (o "[problema da decidibilidade](https://en.wikipedia.org/wiki/Decision_problem)"), porque um programa pode nunca terminar. Como tal, pode ser impossível comprovar algumas propriedades de um contrato, mesmo se estiver bem especificado. -## Ferramentas de verificação formal para contratos inteligentes Ethereum {#formal-verification-tools} +## Ferramentas de verificação formal para contratos inteligentes do Ethereum {#formal-verification-tools} -### Linguagens de especificação para criação de especificações formais {#specification-languages} +### Linguagens de especificação para criar especificações formais {#specification-languages} -**Act**: _*O Act permite a especificação de atualizações de armazenamento, condições de pré/pós e invariáveis do contrato. Seu conjunto de ferramentas também tem backends capazes de comprovar muitas propriedades via Coq, solucionadores SMT, ou hevm.** +**Act**: __O Act permite a especificação de atualizações de armazenamento, pré/pós-condições e invariantes de contrato. Seu conjunto de ferramentas também tem backends capazes de comprovar muitas propriedades via Coq, solucionadores SMT, ou hevm.__ - [GitHub](https://github.com/ethereum/act) -- [Documentação](https://ethereum.github.io/act/) +- [Documentação](https://github.com/argotorg/act) -**Scribble** - _*Scribble transforma anotações de código na linguagem de especificação Scribble em afirmações concretas que verificam a especificação.** +**Scribble** - __O Scribble transforma anotações de código na linguagem de especificação Scribble em asserções concretas que verificam a especificação.__ - [Documentação](https://docs.scribble.codes/) -**Dafny** - _*Dafny é uma linguagem de programação pronta para verificação que depende de anotações de alto nível para argumentar e comprovar a exatidão do código.** +**Dafny** - __Dafny é uma linguagem de programação pronta para verificação que se baseia em anotações de alto nível para raciocinar e provar a correção do código.__ - [GitHub](https://github.com/dafny-lang/dafny) -### Verificadores de programa para checagem de exatidão {#program-verifiers} +### Verificadores de programa para checagem de correção {#program-verifiers} -**Certora Prover** - _Certora Prover é uma ferramenta de verificação formal automática para verificar a exatidão do código em contratos inteligentes. As especificações são escritas em CVL (Certora Verification Language), com violações de propriedade detectadas usando uma combinação de análise estática e resolução de restrições._ +**Certora Prover** - _O Certora Prover é uma ferramenta automática de verificação formal para checar a correção do código em contratos inteligentes. As especificações são escritas em CVL (Certora Verification Language), com as violações de propriedade detectadas usando uma combinação de análise estática e resolução de restrições._ - [Site](https://www.certora.com/) - [Documentação](https://docs.certora.com/en/latest/index.html) -**Solidity SMTChecker** - _*Solidity’s SMTChecker é um verificador de modelos integrado com base no SMT (Teorias do Módulo de Satisfiabilidade) e na resolução de Horn. Ele confirma se o código-fonte de um contrato corresponde às especificações durante a compilação e procura estaticamente por violações de propriedades de segurança.** +**Solidity SMTChecker** - __O SMTChecker do Solidity é um verificador de modelo integrado baseado em SMT (Satisfiability Modulo Theories) e na solução de Horn. Ele confirma se o código-fonte de um contrato corresponde às especificações durante a compilação e procura estaticamente por violações de propriedades de segurança.__ - [GitHub](https://github.com/ethereum/solidity) -**solc-verify** - _*solc-verify é uma versão estendida do compilador Solidity que pode executar a verificação formal automatizada no código Solidity usando anotações e verificação de programa modular.** +**solc-verify** - __O solc-verify é uma versão estendida do compilador Solidity que pode realizar verificação formal automatizada no código Solidity usando anotações e verificação de programa modular.__ - [GitHub](https://github.com/SRI-CSL/solidity) -**KEVM** - _*KEVM é uma semântica formal da Máquina Virtual Ethereum (EVM) escrita no framework K. KEVM é executável e pode comprovar determinadas declarações relacionadas à propriedade usando a lógica de alcançabilidade.** +**KEVM** - __KEVM é uma semântica formal da Máquina Virtual Ethereum (EVM) escrita no framework K. KEVM é executável e pode comprovar determinadas declarações relacionadas à propriedade usando a lógica de alcançabilidade.__ - [GitHub](https://github.com/runtimeverification/evm-semantics) - [Documentação](https://jellopaper.org/) -### Frameworks lógicos para comprovação de teorema {#theorem-provers} +### Frameworks lógicos para prova de teoremas {#theorem-provers} -**Isabelle** - _Isabelle/HOL é um assistente de comprovação que permite que fórmulas matemáticas sejam expressas em uma linguagem formal e fornece ferramentas para comprovar essas fórmulas. A aplicação principal é a formalização de provas matemáticas e, em particular, a verificação formal, que inclui comprovar a exatidão do hardware ou software de computador e comprovar propriedades de linguagens e protocolos de computador._ +**Isabelle** - _O Isabelle/HOL é um assistente de prova que permite que fórmulas matemáticas sejam expressas em uma linguagem formal e fornece ferramentas para provar essas fórmulas. A aplicação principal é a formalização de provas matemáticas e, em particular, a verificação formal, que inclui comprovar a exatidão do hardware ou software de computador e comprovar propriedades de linguagens e protocolos de computador._ - [GitHub](https://github.com/isabelle-prover) - [Documentação](https://isabelle.in.tum.de/documentation.html) -**Coq** - _Coq é um comprovador de teorema interativo que permite definir programas usando teoremas e interativamente gerar comprovações de correção verificadas por máquina._ +**Rocq** - _O Rocq é um provador de teoremas interativo que permite definir programas usando teoremas e gerar interativamente provas de correção verificadas por máquina._ -- [GitHub](https://github.com/coq/coq) -- [Documentação](https://coq.github.io/doc/v8.13/refman/index.html) +- [GitHub](https://github.com/rocq-prover/rocq) +- [Documentação](https://rocq-prover.org/docs) -### Ferramentas de execução simbólica para detectar padrões vulneráveis em contratos inteligentes {#symbolic-execution-tools} +### Ferramentas baseadas em execução simbólica para detectar padrões vulneráveis em contratos inteligentes {#symbolic-execution-tools} -**Manticore** - _*Uma ferramenta para analisar a ferramenta de análise de bytecode EVM com base em execução simbólica*.* +**Manticore** - __Uma ferramenta para analisar bytecode da EVM baseada em execução simbólica.__ - [GitHub](https://github.com/trailofbits/manticore) - [Documentação](https://github.com/trailofbits/manticore/wiki) -**hevm** - _*hevm é um mecanismo de execução simbólico e um verificador de equivalência para bytecode EVM.** +**hevm** - __hevm é um mecanismo de execução simbólica e um verificador de equivalência para o bytecode da EVM.__ - [GitHub](https://github.com/dapphub/dapptools/tree/master/src/hevm) -**Mythril** - _Uma ferramenta de execução simbólica para detectar vulnerabilidades nos contratos inteligentes da Ethereum_ +**Mythril** - _Uma ferramenta de execução simbólica para detectar vulnerabilidades em contratos inteligentes do Ethereum_ - [GitHub](https://github.com/ConsenSys/mythril-classic) - [Documentação](https://mythril-classic.readthedocs.io/en/develop/) ## Leitura adicional {#further-reading} -- [Como funciona a verificação formal dos contratos inteligentes](https://runtimeverification.com/blog/how-formal-verification-of-smart-contracts-works/) -- [Como a verificação formal pode garantir contratos inteligentes infalíveis](https://media.consensys.net/how-formal-verification-can-ensure-flawless-smart-contracts-cbda8ad99bd1) -- [Uma visão geral dos Projetos de Verificação Formal no Ecossistema Ethereum](https://github.com/leonardoalt/ethereum_formal_verification_overview) -- [Verificação formal de ponta a ponta do contrato inteligente de depósito Ethereum 2.0](https://runtimeverification.com/blog/end-to-end-formal-verification-of-ethereum-2-0-deposit-smart-contract/) -- [Verificando formalmente o Contrato Inteligente Mais Popular do Mundo](https://www.zellic.io/blog/formal-verification-weth) -- [SMTChecker e Verificação Formal](https://docs.soliditylang.org/en/v0.8.15/smtchecker.html) +- [Como funciona a verificação formal de contratos inteligentes](https://runtimeverification.com/blog/how-formal-verification-of-smart-contracts-works/) +- [Como a verificação formal pode garantir contratos inteligentes sem falhas](https://media.consensys.net/how-formal-verification-can-ensure-flawless-smart-contracts-cbda8ad99bd1) +- [Uma visão geral dos projetos de verificação formal no ecossistema Ethereum](https://github.com/leonardoalt/ethereum_formal_verification_overview) +- [Verificação formal de ponta a ponta do contrato inteligente de depósito do Ethereum 2.0](https://runtimeverification.com/blog/end-to-end-formal-verification-of-ethereum-2-0-deposit-smart-contract/) +- [Verificando formalmente o contrato inteligente mais popular do mundo](https://www.zellic.io/blog/formal-verification-weth) +- [SMTChecker e verificação formal](https://docs.soliditylang.org/en/v0.8.15/smtchecker.html) diff --git a/public/content/translations/pt-br/developers/docs/smart-contracts/index.md b/public/content/translations/pt-br/developers/docs/smart-contracts/index.md index 4c1715fd383..3180c72c704 100644 --- a/public/content/translations/pt-br/developers/docs/smart-contracts/index.md +++ b/public/content/translations/pt-br/developers/docs/smart-contracts/index.md @@ -1,6 +1,6 @@ --- -title: Introdução aos contratos inteligentes -description: Uma visão geral dos contratos inteligentes, centrada em suas características e limitações únicas. +title: "Introdução aos contratos inteligentes" +description: "Uma visão geral dos contratos inteligentes, centrada em suas características e limitações únicas." lang: pt-br --- @@ -8,17 +8,17 @@ lang: pt-br Um "contrato inteligente" é simplesmente um programa executado na blockchain Ethereum. É uma coleção de código (suas funções) e dados (seu estado) que reside em um endereço específico na blockchain Ethereum. -Os contratos inteligentes são um tipo de [conta Ethereum](/developers/docs/accounts/). Isso significa que eles têm saldo e podem ser alvo de transações. No entanto, eles não são controlados por um usuário, em vez disso, eles são implantados na rede e são executados como programados. Contas de usuários podem então interagir com um contrato inteligente enviando transações que executam uma função definida no contrato inteligente. Os contratos inteligentes podem definir regras, como um contrato regular, e aplicá-los automaticamente através do código. Os contratos inteligentes não podem ser excluídos por padrão, e as interações com eles são irreversíveis. +Contratos inteligentes são um tipo de [conta Ethereum](/developers/docs/accounts/). Isso significa que eles têm saldo e podem ser alvo de transações. No entanto, eles não são controlados por um usuário, em vez disso, eles são implantados na rede e são executados como programados. Contas de usuários podem então interagir com um contrato inteligente enviando transações que executam uma função definida no contrato inteligente. Os contratos inteligentes podem definir regras, como um contrato regular, e aplicá-los automaticamente através do código. Os contratos inteligentes não podem ser excluídos por padrão, e as interações com eles são irreversíveis. ## Pré-requisitos {#prerequisites} Se você está apenas começando ou procurando uma introdução menos técnica, recomendamos nossa [introdução aos contratos inteligentes](/smart-contracts/). -Não deixe de ler [contas](/developers/docs/accounts/), [transações](/developers/docs/transactions/) e [máquina virtual Ethereum](/developers/docs/evm/) antes de entrar no mundo dos contratos inteligentes. +Certifique-se de que leu sobre [contas](/developers/docs/accounts/), [transações](/developers/docs/transactions/) e a [máquina virtual Ethereum](/developers/docs/evm/) antes de mergulhar no mundo dos contratos inteligentes. -## Uma máquina de vendas digitais {#a-digital-vending-machine} +## Uma máquina de venda automática digital {#a-digital-vending-machine} -Talvez a melhor metáfora para um contrato inteligente seja uma máquina de venda automática, descrita por [Nick Szabo](https://unenumerated.blogspot.com/). Com as entradas certas, uma saída segura é garantida. +Talvez a melhor metáfora para um contrato inteligente seja uma máquina de venda automática, conforme descrito por [Nick Szabo](https://unenumerated.blogspot.com/). Com as entradas certas, uma saída segura é garantida. Para obter um snack de uma máquina de venda automática: @@ -35,27 +35,28 @@ pragma solidity 0.8.7; contract VendingMachine { - // Declarar variáveis de estado do endereço público do proprietário do contrato; + // Declarar variáveis de estado do contrato + address public owner; mapping (address => uint) public cupcakeBalances; - // Quando o contrato 'VendingMachine' é implantado: - // 1. defina o endereço de implantação como proprietário do contrato - // 2. defina o saldo de cupcake do contrato inteligente para 100 - constructor() public { + // Quando o contrato 'VendingMachine' for implantado: + // 1. defina o endereço de implantação como o proprietário do contrato + // 2. defina o saldo de cupcakes do contrato inteligente implantado como 100 + constructor() { owner = msg.sender; cupcakeBalances[address(this)] = 100; } - // Permite que o proprietário aumente o saldo de cupcake no contrato inteligente + // Permitir que o proprietário aumente o saldo de cupcakes do contrato inteligente function refill(uint amount) public { - require(msg.sender == owner, "Only the owner can refill."); + require(msg.sender == owner, "Apenas o proprietário pode reabastecer."); cupcakeBalances[address(this)] += amount; } - // Permite que qualquer pessoa adquira cupcakes + // Permitir que qualquer pessoa compre cupcakes function purchase(uint amount) public payable { - require(msg.value >= amount * 1 ether, "You must pay at least 1 ETH per cupcake"); - require(cupcakeBalances[address(this)] >= amount, "Not enough cupcakes in stock to complete this purchase"); + require(msg.value >= amount * 1 ether, "Você deve pagar pelo menos 1 ETH por cupcake"); + require(cupcakeBalances[address(this)] >= amount, "Não há cupcakes suficientes em estoque para concluir esta compra"); cupcakeBalances[address(this)] -= amount; cupcakeBalances[msg.sender] += amount; } @@ -64,9 +65,9 @@ contract VendingMachine { De maneira similar a como uma máquina de venda automática elimina a necessidade de um funcionário fornecedor, os contratos inteligentes podem substituir intermediários em muitos setores. -## Sem necessidade de permissão {#permissionless} +## Sem permissão {#permissionless} -Qualquer um pode escrever um contrato inteligente e implantá-lo na rede. Você só precisa aprender a codificar em uma [linguagem de contrato inteligente](/developers/docs/smart-contracts/languages/) e ter ETH suficiente para implantar seu contrato. A implantação de um contrato inteligente é tecnicamente uma transação, portanto, você precisa pagar o [gás](/developers/docs/gas/) da mesma forma que precisa pagar o Gas por uma simples transferência de ETH. No entanto, os custos de gás para implantação de contrato são muito mais altos. +Qualquer um pode escrever um contrato inteligente e implantá-lo na rede. Você só precisa aprender a codificar em uma [linguagem de contrato inteligente](/developers/docs/smart-contracts/languages/) e ter ETH suficiente para implantar seu contrato. Implantar um contrato inteligente é tecnicamente uma transação, então você precisa pagar [gás](/developers/docs/gas/) da mesma forma que precisa pagar gás por uma simples transferência de ETH. No entanto, os custos de gás para implantação de contrato são muito mais altos. A Ethereum tem linguagens que o desenvolvedor terá facilidade de usar para escrever contratos inteligentes: @@ -81,23 +82,23 @@ Contudo, elas devem ser compiladas antes de poderem ser implantadas para que a m Os contratos inteligentes são públicos na Ethereum e podem ser considerados como APIs abertas. Isso significa que você pode chamar outros contratos inteligentes em seu próprio contrato inteligente para estender muito o que é possível. Os contratos podem mesmo implantar outros contratos. -Saiba mais sobre a [composição do contrato inteligente](/developers/docs/smart-contracts/composability/). +Saiba mais sobre a [componibilidade de contratos inteligentes](/developers/docs/smart-contracts/composability/). ## Limitações {#limitations} Os contratos inteligentes sozinhos não podem obter informações sobre eventos do "mundo real", porque não podem recuperar dados de fontes off-chain. Isso significa que eles não podem responder a eventos no mundo real. Isto é, por concepção. A sua concepção é a de que as informações externas podem pôr em causa o consenso, que é importante para a segurança e a descentralização. -No entanto, é importante que aplicações blockchain possam usar dados off-chain. A solução são os [oráculos](/developers/docs/oracles/), instrumentos que ingerem dados off-chain e os disponibilizam para contratos inteligentes. +No entanto, é importante que aplicações blockchain possam usar dados off-chain. A solução são [oráculos](/developers/docs/oracles/), que são ferramentas que ingerem dados fora da cadeia e os disponibilizam para contratos inteligentes. -Outra limitação de contratos inteligentes é o tamanho máximo do contrato. Um contrato inteligente pode ser um máximo de 24KB ou ficará sem gás. Isso pode ser contornado usando [O Padrão de Diamante](https://eips.ethereum.org/EIPS/eip-2535). +Outra limitação de contratos inteligentes é o tamanho máximo do contrato. Um contrato inteligente pode ser um máximo de 24KB ou ficará sem gás. Isso pode ser contornado usando o [Padrão Diamante (The Diamond Pattern)](https://eips.ethereum.org/EIPS/eip-2535). ## Contratos Multisig {#multisig} -Os contratos multisig (com múltiplas assinaturas) são contas de contrato inteligente que exigem várias assinaturas válidas para executar uma transação. Isso é muito útil para evitar pontos únicos de falha para contratos com quantidades substanciais de ether ou outros tokens. Os Multisigs também dividem a responsabilidade pela execução do contrato e gerenciamento das chaves entre vários participantes e evitam que a perda de uma única chave privada leve à perda irreversível de fundos. Por esses motivos, os contratos multisig podem ser usados para governança DAO simples. Multisigs requerem N assinaturas de M possíveis assinaturas aceitáveis (onde N ≤ M e M > 1) para serem executados. `N = 3, M = 5` e `N = 4, M = 7` são utilizados com frequência. Um multisig 4/7 requer quatro das sete assinaturas válidas possíveis. Isso significa que os fundos ainda podem ser recuperados, mesmo que três assinaturas sejam perdidas. Nesse caso, também significa que a maioria dos detentores de chaves deve concordar e assinar para que o contrato seja executado. +Os contratos multisig (com múltiplas assinaturas) são contas de contrato inteligente que exigem várias assinaturas válidas para executar uma transação. Isso é muito útil para evitar pontos únicos de falha para contratos com quantidades substanciais de ether ou outros tokens. Os Multisigs também dividem a responsabilidade pela execução do contrato e gerenciamento das chaves entre vários participantes e evitam que a perda de uma única chave privada leve à perda irreversível de fundos. Por esses motivos, os contratos multisig podem ser usados para governança DAO simples. Multisigs exigem N de M assinaturas possíveis (onde N ≤ M e M > 1) para serem executados. `N = 3, M = 5` e `N = 4, M = 7` são comumente usados. Um multisig 4/7 requer quatro das sete assinaturas válidas possíveis. Isso significa que os fundos ainda podem ser recuperados, mesmo que três assinaturas sejam perdidas. Nesse caso, também significa que a maioria dos detentores de chaves deve concordar e assinar para que o contrato seja executado. -## Recursos para contratos inteligentes {#smart-contract-resources} +## Recursos de contratos inteligentes {#smart-contract-resources} -**OpenZeppelin Contracts -** **_Biblioteca para o desenvolvimento de contratos inteligentes seguros._** +**OpenZeppelin Contracts -** **_Biblioteca para desenvolvimento seguro de contratos inteligentes._** - [openzeppelin.com/contracts/](https://openzeppelin.com/contracts/) - [GitHub](https://github.com/OpenZeppelin/openzeppelin-contracts) @@ -107,5 +108,5 @@ Os contratos multisig (com múltiplas assinaturas) são contas de contrato intel - [Coinbase: O que é um contrato inteligente?](https://www.coinbase.com/learn/crypto-basics/what-is-a-smart-contract) - [Chainlink: O que é um contrato inteligente?](https://chain.link/education/smart-contracts) -- [Vídeo: Simplesmente Explicado - Contratos Inteligentes](https://youtu.be/ZE2HxTmxfrI) -- [Cyfrin Updraft: Plataforma de aprendizado e auditoria Web3](https://updraft.cyfrin.io) +- [Vídeo: Explicando de forma simples - Contratos Inteligentes](https://youtu.be/ZE2HxTmxfrI) +- [Cyfrin Updraft: plataforma de aprendizado e auditoria da Web3](https://updraft.cyfrin.io) diff --git a/public/content/translations/pt-br/developers/docs/smart-contracts/languages/index.md b/public/content/translations/pt-br/developers/docs/smart-contracts/languages/index.md index 4e03783385c..dd739390f20 100644 --- a/public/content/translations/pt-br/developers/docs/smart-contracts/languages/index.md +++ b/public/content/translations/pt-br/developers/docs/smart-contracts/languages/index.md @@ -1,10 +1,10 @@ --- title: Linguagens de contratos inteligentes -description: Uma visão geral e comparação de duas línguagens de contratos inteligentes – Solidity e Vyper. +description: "Uma visão geral e comparação de duas línguagens de contratos inteligentes – Solidity e Vyper." lang: pt-br --- -Um grande aspecto sobre a Ethereum é que os contratos inteligentes podem ser programados usando linguagens relativamente amigáveis para o desenvolvedor. Se você tem experiência com Python ou qualquer [linguagem de marcação](https://wikipedia.org/wiki/List_of_programming_languages_by_type#Curly-bracket_languages), você pode encontrar uma linguagem com sintaxe familiar. +Um grande aspecto sobre a Ethereum é que os contratos inteligentes podem ser programados usando linguagens relativamente amigáveis para o desenvolvedor. Se você tem experiência com Python ou qualquer [linguagem de chaves](https://wikipedia.org/wiki/List_of_programming_languages_by_type#Curly-bracket_languages), pode encontrar uma linguagem com sintaxe familiar. As duas linguagens mais ativas e mantidas são: @@ -34,15 +34,15 @@ Conhecimento anterior de linguagens de programação, especialmente de JavaScrip ### Links importantes {#important-links} - [Documentação](https://docs.soliditylang.org/en/latest/) -- [Portal da linguagem Solidity](https://soliditylang.org/) -- [Solidity como exemplo](https://docs.soliditylang.org/en/latest/solidity-by-example.html) +- [Portal da Linguagem Solidity](https://soliditylang.org/) +- [Solidity por Exemplo](https://docs.soliditylang.org/en/latest/solidity-by-example.html) - [GitHub](https://github.com/ethereum/solidity/) -- [Solidity Matrix Chatroom](https://gitter.im/ethereum/solidity) ponte para [Solidity Matrix Chatroom](https://matrix.to/#/#ethereum_solidity:gitter.im) -- [Dicas](https://reference.auditless.com/cheatsheet) -- [Blog da Solidity](https://blog.soliditylang.org/) -- [Solidity Twitter](https://twitter.com/solidity_lang) +- [Chat do Solidity no Gitter](https://gitter.im/ethereum/solidity) com ponte para o [Chat do Solidity no Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im) +- [Folha de consulta](https://reference.auditless.com/cheatsheet) +- [Blog do Solidity](https://blog.soliditylang.org/) +- [Twitter do Solidity](https://twitter.com/solidity_lang) -### Exemplo de contrato {#example-contract} +### Contrato de exemplo {#example-contract} ```solidity // SPDX-License-Identifier: GPL-3.0 @@ -58,14 +58,14 @@ contract Coin { // alterações de contrato que você declara event Sent(address from, address to, uint amount); - // O código constructor só é executado quando o contrato + // O código do construtor só é executado quando o contrato // é criado constructor() { minter = msg.sender; } - // Envia uma quantidade de moedas recém criadas para um endereço - // Só pode ser chamada pelo criador do contrato + // Envia uma quantidade de moedas recém-criadas para um endereço + // Só pode ser chamado pelo criador do contrato function mint(address receiver, uint amount) public { require(msg.sender == minter); require(amount < 1e60); @@ -73,7 +73,7 @@ contract Coin { } // Envia uma quantidade de moedas existentes - // de qualquer solicitador para um endereço + // de qualquer chamador para um endereço function send(address receiver, uint amount) public { require(amount <= balances[msg.sender], "Saldo insuficiente."); balances[msg.sender] -= amount; @@ -101,21 +101,21 @@ Esse exemplo deve dar a você, uma ideia de como é a sintaxe de um contrato na - Repetições com comprimento infinito - Pontos fixos binários -Para obter mais informações, [leia a lógica do Vyper](https://vyper.readthedocs.io/en/latest/index.html). +Para mais informações, [leia a justificativa do Vyper](https://vyper.readthedocs.io/en/latest/index.html). ### Links importantes {#important-links-1} - [Documentação](https://vyper.readthedocs.io) -- [Vyper como exemplo](https://vyper.readthedocs.io/en/latest/vyper-by-example.html) +- [Vyper por Exemplo](https://vyper.readthedocs.io/en/latest/vyper-by-example.html) - [Mais Vyper por Exemplo](https://vyper-by-example.org/) - [GitHub](https://github.com/vyperlang/vyper) -- [Chat Discord da comunidade Vyper](https://discord.gg/SdvKC79cJk) -- [Dicas](https://reference.auditless.com/cheatsheet) -- [Ferramentas e frameworks de desenvolvimento de contratos inteligentes para Vyper](/developers/docs/programming-languages/python/) -- [VyperPunk - Aprenda a proteger e hackear contratos inteligentes Vyper](https://github.com/SupremacyTeam/VyperPunk) -- [Vyper Hub para desenvolvimento](https://github.com/zcor/vyper-dev) -- [Exemplos de contratos inteligentes de maiores sucessos Vyper](https://github.com/pynchmeister/vyper-greatest-hits/tree/main/contracts) -- [Recursos incríveis com curadoria do Vyper](https://github.com/spadebuilders/awesome-vyper) +- [Chat da comunidade Vyper no Discord](https://discord.gg/SdvKC79cJk) +- [Folha de consulta](https://reference.auditless.com/cheatsheet) +- [Estruturas e ferramentas de desenvolvimento de contratos inteligentes para Vyper](/developers/docs/programming-languages/python/) +- [VyperPunk - aprenda a proteger e hackear contratos inteligentes Vyper](https://github.com/SupremacyTeam/VyperPunk) +- [Hub Vyper para desenvolvimento](https://github.com/zcor/vyper-dev) +- [Exemplos de contratos inteligentes Vyper greatest hits](https://github.com/pynchmeister/vyper-greatest-hits/tree/main/contracts) +- [Awesome Vyper: recursos selecionados](https://github.com/spadebuilders/awesome-vyper) ### Exemplo {#example} @@ -123,72 +123,90 @@ Para obter mais informações, [leia a lógica do Vyper](https://vyper.readthedo # Leilão aberto # Parâmetros do leilão -# Beneficiário recebe dinheiro do licitante com lance mais alto + +# O beneficiário recebe o dinheiro do maior lance + beneficiary: public(address) auctionStart: public(uint256) auctionEnd: public(uint256) # Estado atual do leilão + highestBidder: public(address) highestBid: public(uint256) -# Definido como verdadeiro no final, não permite qualquer alteração +# Definido como verdadeiro no final, não permite nenhuma alteração + ended: public(bool) -# Acompanha os lances reembolsados para que possamos seguir o padrão de saque +# Acompanhe os lances reembolsados para que possamos seguir o padrão de saque + pendingReturns: public(HashMap[address, uint256]) -# Cria um leilão simples com `_bidding_time` -# segundos de tempo de licitação em nome do +# Crie um leilão simples com tempo de lance de `_bidding_time` + +# segundos em nome do + # endereço do beneficiário `_beneficiary`. + @external def __init__(_beneficiary: address, _bidding_time: uint256): self.beneficiary = _beneficiary self.auctionStart = block.timestamp self.auctionEnd = self.auctionStart + _bidding_time -# Licita no leilão com o valor enviado +# Dê um lance no leilão com o valor enviado + # junto com esta transação. -# O valor só será devolvido se o -# leilão não foi ganho. + +# O valor só será reembolsado se o + +# leilão não for ganho. + @external @payable def bid(): - # Verifica se o período de licitação acabou. + # Verifique se o período de lances terminou. assert block.timestamp < self.auctionEnd - # Verifica se o lance é alto o suficiente + # Verifique se o lance é alto o suficiente assert msg.value > self.highestBid - # Rastreia o reembolso do licitante anterior + # Acompanhe o reembolso do licitante anterior com o lance mais alto self.pendingReturns[self.highestBidder] += self.highestBid - # Rastreia o mais recente lance mais alto + # Acompanhe o novo lance mais alto self.highestBidder = msg.sender self.highestBid = msg.value -# Retira um lance previamente reembolsado. O padrão de retirada é +# Saque um lance reembolsado anteriormente. O padrão de saque é + # usado aqui para evitar um problema de segurança. Se os reembolsos fossem diretamente -# enviados como parte do lance (bid()), um contrato de licitação malicioso poderia bloquear -# esses reembolsos e, assim, bloquear a entrada de novos lances mais altos. + +# enviados como parte do bid(), um contrato de lance malicioso poderia bloquear + +# esses reembolsos e, assim, impedir a entrada de novos lances mais altos. + @external def withdraw(): pending_amount: uint256 = self.pendingReturns[msg.sender] self.pendingReturns[msg.sender] = 0 send(msg.sender, pending_amount) -# Termina o leilão e envia o lance mais alto +# Encerre o leilão e envie o lance mais alto + # para o beneficiário. + @external def endAuction(): - # É uma boa diretriz para estruturar funções que interagem - # com outros contratos (ou seja, eles chamam funções ou enviam Ether) + # É uma boa diretriz estruturar funções que interagem + # com outros contratos (ou seja, eles chamam funções ou enviam ether) # em três fases: - # 1. verificando as condições - # 2. realizando ações (condições potencialmente mutáveis) - # 3. interagindo com outros contratos - # Se essas fases forem misturadas, o outro contrato poderia retornar ao - # contrato atual e modificar o estado ou causar - # efeitos (pagamento em ether) para serem realizados várias vezes. - # Se as funções chamadas internamente incluem interações - # com contratos externos, também devem ser consideradas interações com + # 1. verificação de condições + # 2. execução de ações (potencialmente alterando condições) + # 3. interação com outros contratos + # Se essas fases forem misturadas, o outro contrato poderá chamar + # de volta para o contrato atual e modificar o estado ou causar + # efeitos (pagamento de ether) a serem realizados várias vezes. + # Se as funções chamadas internamente incluírem interação com + # contratos externos, elas também deverão ser consideradas como interação com # contratos externos. # 1. Condições @@ -213,24 +231,25 @@ Se você é novo na Ethereum e ainda não fez qualquer codificação com linguag **Yul** - Linguagem intermediária para Ethereum. -- Suporta a [EVM](/developers/docs/evm) e [eWASM](https://github.com/ewasm), um WebAssembly com sabor de Ethereum e concebido para ser um denominador comum utilizável de ambas as plataformas. +- Suporta a [EVM](/developers/docs/evm) e o [Ewasm](https://github.com/ewasm), um WebAssembly com sabor de Ethereum, e foi projetado para ser um denominador comum utilizável de ambas as plataformas. - Alvo para fases de otimização de alto nível que podem beneficiar tanto as plataformas EVM como Ewasm de forma igual. **Yul+** - Uma extensão de baixo nível altamente eficiente para Yul. -- Inicialmente concebido para um [optimistic rollup](/developers/docs/scaling/optimistic-rollups/). +- Inicialmente projetado para um contrato de [optimistic rollup](/developers/docs/scaling/optimistic-rollups/). - Yul+ pode ser visto como uma proposta de atualização experimental para Yul, adicionando novos recursos. -### Links Importantes {#important-links-2} +### Links importantes {#important-links-2} -- [Documentação](https://docs.soliditylang.org/en/latest/yul.html) -- [Documentação Yul+](https://github.com/fuellabs/yulp) -- [Yul+ Post de Introdução](https://medium.com/@fuellabs/introducing-yul-a-new-low-level-language-for-ethereum-aa64ce89512f) +- [Documentação do Yul](https://docs.soliditylang.org/en/latest/yul.html) +- [Documentação do Yul+](https://github.com/fuellabs/yulp) +- [Post de introdução ao Yul+](https://medium.com/@fuellabs/introducing-yul-a-new-low-level-language-for-ethereum-aa64ce89512f) -### Exemplo de contrato {#example-contract-2} +### Contrato de exemplo {#example-contract-2} -O exemplo a seguir simples implementa uma função de energia. Ele pode ser compilado usando `solc --strict-assembly --bin input.yul`. O exemplo deve ser armazenado no arquivo input.yul. +O exemplo a seguir simples implementa uma função de energia. Pode ser compilado usando `solc --strict-assembly --bin input.yul`. O exemplo deve ser +armazenado no arquivo input.yul. ``` { @@ -251,7 +270,7 @@ O exemplo a seguir simples implementa uma função de energia. Ele pode ser comp } ``` -Se você já é bem experiente com contratos inteligentes, uma implementação do ERC20 em Yul pode ser encontrada [aqui](https://solidity.readthedocs.io/en/latest/yul.html#complete-erc20-example). +Se você já tem bastante experiência com contratos inteligentes, uma implementação completa do ERC20 em Yul pode ser encontrada [aqui](https://solidity.readthedocs.io/en/latest/yul.html#complete-erc20-example). ## Fe {#fe} @@ -263,31 +282,31 @@ Se você já é bem experiente com contratos inteligentes, uma implementação d ### Links importantes {#important-links-3} - [GitHub](https://github.com/ethereum/fe) -- [Anúncio da Fe](https://snakecharmers.ethereum.org/fe-a-new-language-for-the-ethereum-ecosystem/) -- [Fe 2021 Roadmap](https://notes.ethereum.org/LVhaTF30SJOpkbG1iVw1jg) -- [Chat de Discord Fe](https://discord.com/invite/ywpkAXFjZH) -- [Fe Twitter](https://twitter.com/official_fe) +- [Anúncio do Fe](https://snakecharmers.ethereum.org/fe-a-new-language-for-the-ethereum-ecosystem/) +- [Planejamento do Fe para 2021](https://notes.ethereum.org/LVhaTF30SJOpkbG1iVw1jg) +- [Chat do Fe no Discord](https://discord.com/invite/ywpkAXFjZH) +- [Twitter do Fe](https://twitter.com/official_fe) -### Exemplo de contrato {#example-contract-3} +### Contrato de exemplo {#example-contract-3} O seguinte é um contrato simples implementado em Fe. ``` type BookMsg = bytes[100] -contrate GuestBook: +contract GuestBook: pub guest_book: map event Signed: book_msg: BookMsg pub def sign(book_msg: BookMsg): - eu mesmo. uest_book[msg.sender] = book_msg + self.guest_book[msg.sender] = book_msg - emite Signed(book_msg=book_msg) + emit Signed(book_msg=book_msg) pub def get_msg(addr: address) -> BookMsg: - remeter. uest_book[addr].to_mem() + return self.guest_book[addr].to_mem() ``` @@ -299,7 +318,7 @@ Aqui estão algumas coisas a considerar se você ainda não tentou nenhuma das l ### O que é que há de melhor em Solidity? {#solidity-advantages} -- Se você for um iniciante, há muitos tutoriais e ferramentas de aprendizagem disponíveis. Veja mais sobre isso na seção [Aprenda programando](/developers/learning-tools/). +- Se você for um iniciante, há muitos tutoriais e ferramentas de aprendizagem disponíveis. Veja mais sobre isso na seção [Aprenda Programando](/developers/learning-tools/). - Ótima ferramenta de desenvolvedor disponível. - Solidity tem uma grande comunidade de desenvolvedores, o que significa que você provavelmente encontrará respostas para as suas perguntas muito rapidamente. @@ -316,9 +335,9 @@ Aqui estão algumas coisas a considerar se você ainda não tentou nenhuma das l ## Comparações de linguagens {#language-comparisons} -Para comparações de sintaxe básica, o ciclo de vida do contrato, interfaces, operadores, estruturas de dados, funções, fluxo de controle e mais confira esta [folha de crédito por auditoria](https://reference.auditless.com/cheatsheet/) +Para comparações de sintaxe básica, ciclo de vida do contrato, interfaces, operadores, estruturas de dados, funções, fluxo de controle e muito mais, confira esta [folha de consulta da Auditless](https://reference.auditless.com/cheatsheet/) ## Leitura adicional {#further-reading} -- [Biblioteca de Contratos da Solidity por OpenZeppelin](https://docs.openzeppelin.com/contracts/5.x/) -- [Solidity como exemplo](https://solidity-by-example.org) +- [Biblioteca de Contratos Solidity da OpenZeppelin](https://docs.openzeppelin.com/contracts/5.x/) +- [Solidity por Exemplo](https://solidity-by-example.org) diff --git a/public/content/translations/pt-br/developers/docs/smart-contracts/libraries/index.md b/public/content/translations/pt-br/developers/docs/smart-contracts/libraries/index.md index b392fff6b0c..7c3f5cca2b3 100644 --- a/public/content/translations/pt-br/developers/docs/smart-contracts/libraries/index.md +++ b/public/content/translations/pt-br/developers/docs/smart-contracts/libraries/index.md @@ -1,14 +1,14 @@ --- title: Biblioteca de contratos inteligentes -description: +description: "Acesse bibliotecas de contratos inteligentes pré-construídos e reutilize-os para desenvolver projetos em Ethereum mais rapidamente." lang: pt-br --- Você não precisa escrever todos os contratos inteligentes em seu projeto a partir do zero. Há muitas bibliotecas de contratos inteligentes de código aberto disponíveis que fornecem blocos de construção reutilizáveis para o seu projeto que podem evitar que você tenha que reinventar a roda. -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -Antes de entrar em bibliotecas de contratos inteligentes, é uma boa ideia ter uma boa compreensão da estrutura de um contrato inteligente. Vá até a [anatomia do contrato inteligente](/developers/docs/smart-contracts/anatomy/) se você ainda não fez isso. +Antes de entrar em bibliotecas de contratos inteligentes, é uma boa ideia ter uma boa compreensão da estrutura de um contrato inteligente. Acesse a [anatomia de contratos inteligentes](/developers/docs/smart-contracts/anatomy/) se você ainda não o fez. ## O que há em uma biblioteca {#whats-in-a-library} @@ -16,11 +16,11 @@ Geralmente, você pode encontrar dois tipos de blocos de construção em bibliot ### Comportamentos {#behaviors} -Ao escrever contratos inteligentes, há uma boa chance de você escrever padrões semelhantes repetidamente, como atribuir um endereço de administrador __ para realizar operações protegidas em um contrato, ou adicionando um botão de emergência _pause_ em caso de um problema inesperado. +Ao escrever contratos inteligentes, há uma boa chance de que você se pegue escrevendo padrões semelhantes repetidamente, como atribuir um endereço de _admin_ para realizar operações protegidas em um contrato, ou adicionar um botão de _pausa_ de emergência no caso de um problema inesperado. -As bibliotecas inteligentes de contratos geralmente fornecem implementações reutilizáveis destes comportamentos como [bibliotecas](https://solidity.readthedocs.io/en/v0.7.2/contracts.html#libraries) ou via [herança](https://solidity.readthedocs.io/en/v0.7.2/contracts.html#inheritance) em Solidity. +As bibliotecas de contratos inteligentes geralmente fornecem implementações reutilizáveis desses comportamentos como [bibliotecas](https://solidity.readthedocs.io/en/v0.7.2/contracts.html#libraries) ou via [herança](https://solidity.readthedocs.io/en/v0.7.2/contracts.html#inheritance) em Solidity. -Como exemplo, a seguir é uma versão simplificada do [`contrato` próprio](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.2.0/contracts/access/Ownable.sol) da [biblioteca de contratos OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts), que concebe um endereço como proprietário de um contrato e fornece um modificador para restringir o acesso a um método apenas para esse proprietário. +Como exemplo, a seguir está uma versão simplificada do [contrato `Ownable`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.2.0/contracts/access/Ownable.sol) da [biblioteca OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts), que designa um endereço como o proprietário de um contrato, e fornece um modificador para restringir o acesso a um método apenas a esse proprietário. ```solidity contract Ownable { @@ -50,19 +50,19 @@ contract MyContract is Ownable { } ``` -Outro exemplo popular é o [SafeMath](https://docs.openzeppelin.com/contracts/3.x/utilities#math) ou [DsMath](https://dappsys.readthedocs.io/en/latest/ds_math.html). Estas são bibliotecas (em oposição aos contratos base) que fornecem as funções aritméticas com verificações de excesso de fluxo, que não são fornecidas pela linguagem. É uma boa prática usar uma dessas bibliotecas em vez de operações aritméticas para proteger seu contrato contra transbordos, que pode ter consequências desastrosas! +Outro exemplo popular é [SafeMath](https://docs.openzeppelin.com/contracts/3.x/utilities#math) ou [DsMath](https://dappsys.readthedocs.io/en/latest/ds_math.html). Estas são bibliotecas (em oposição aos contratos base) que fornecem as funções aritméticas com verificações de excesso de fluxo, que não são fornecidas pela linguagem. É uma boa prática usar uma dessas bibliotecas em vez de operações aritméticas para proteger seu contrato contra transbordos, que pode ter consequências desastrosas! ### Padrões {#standards} -Para facilitar a [composição e a interoperabilidade](/developers/docs/smart-contracts/composability/), a comunidade Ethereum definiu vários padrões na forma de **ERCs**. Você pode ler mais sobre eles na seção [de padrões](/developers/docs/standards/). +Para facilitar a [componibilidade e interoperabilidade](/developers/docs/smart-contracts/composability/), a comunidade Ethereum definiu vários padrões na forma de **ERCs**. Você pode ler mais sobre eles na seção de [padrões](/developers/docs/standards/). -Ao incluir um ERC como parte de seus contratos, É uma boa ideia procurar implementações padrão ao invés de tentar implantar a sua própria. Muitas bibliotecas de contratos inteligentes incluem implementações para os ERC mais populares. Por exemplo, o onipresente [padrão de token fungível lERC20 universal](/developers/tutorials/understand-the-erc-20-token-smart-contract/) pode ser encontrado em [HQ20](https://github.com/HQ20/contracts/blob/master/contracts/token/README.md), [DappSys](https://github.com/dapphub/ds-token/) e [OpenZeppelin](https://docs.openzeppelin.com/contracts/3.x/erc20). Além disso, alguns ERCs também fornecem implementações canônicas como parte do próprio ERC. +Ao incluir um ERC como parte de seus contratos, É uma boa ideia procurar implementações padrão ao invés de tentar implantar a sua própria. Muitas bibliotecas de contratos inteligentes incluem implementações para os ERC mais populares. Por exemplo, o onipresente [padrão de token fungível ERC20](/developers/tutorials/understand-the-erc-20-token-smart-contract/) pode ser encontrado em [HQ20](https://github.com/HQ20/contracts/blob/master/contracts/token/README.md), [DappSys](https://github.com/dapphub/ds-token/) e [OpenZeppelin](https://docs.openzeppelin.com/contracts/3.x/erc20). Além disso, alguns ERCs também fornecem implementações canônicas como parte do próprio ERC. -Vale a pena mencionar que alguns ERCs não são sozinhos, mas são adições a outros ERCs. Por exemplo, [ERC2612](https://eips.ethereum.org/EIPS/eip-2612) adiciona uma extensão ao ERC20 para melhorar sua usabilidade. +Vale a pena mencionar que alguns ERCs não são sozinhos, mas são adições a outros ERCs. Por exemplo, o [ERC2612](https://eips.ethereum.org/EIPS/eip-2612) adiciona uma extensão ao ERC20 para melhorar sua usabilidade. ## Como adicionar uma biblioteca {#how-to} -Sempre consulte a documentação da biblioteca que você está incluindo para instruções específicas sobre como incluí-la no seu projeto. Várias bibliotecas de contratos Solidity são empacotadas usando o `npm`, então você pode apenas `npm instale-as`. A maioria das ferramentas para [compilar](/developers/docs/smart-contracts/compiling/) contratos irá analisar os seus `node_modules` para bibliotecas de contratos inteligentes, assim você poderá fazer o seguinte: +Sempre consulte a documentação da biblioteca que você está incluindo para instruções específicas sobre como incluí-la no seu projeto. Várias bibliotecas de contratos Solidity são empacotadas usando `npm`, então você pode simplesmente `npm install` nelas. A maioria das ferramentas para [compilar](/developers/docs/smart-contracts/compiling/) contratos procurará em seus `node_modules` por bibliotecas de contratos inteligentes, para que você possa fazer o seguinte: ```solidity // Isto irá carregar a biblioteca @openzeppelin/contracts de seus node_modules @@ -73,13 +73,13 @@ contrato MyNFT é ERC721 { } ``` -Independente do método que você usa, ao incluir uma biblioteca, sempre fique de olho na versão de [linguagem](/developers/docs/smart-contracts/languages/). Por exemplo, não é possível usar uma biblioteca para Solidity 0.6 se você estiver escrevendo seus contratos em Solidity 0.5. +Independentemente do método que você usa, ao incluir uma biblioteca, sempre fique de olho na versão da [linguagem](/developers/docs/smart-contracts/languages/). Por exemplo, não é possível usar uma biblioteca para Solidity 0.6 se você estiver escrevendo seus contratos em Solidity 0.5. ## Quando usar {#when-to-use} Usar uma biblioteca de contratos inteligente para o seu projeto traz vários benefícios. Em primeiro lugar e acima de tudo, economiza seu tempo fornecendo blocos de construção prontos para usar que você pode incluir no seu sistema, ao invés de ter que programar você mesmo. -A segurança é também um importante ganho. Bibliotecas de contratos inteligentes de código aberto também são frequentemente cuidadosamente controladas. Dado que muitos projectos dependem deles, existe um forte incentivo por parte da comunidade para os manter sob constante revisão. É muito mais comum encontrar erros no código do aplicativo do que em bibliotecas de contratos reutilizáveis. Algumas bibliotecas também são submetidas a [auditorias externas](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/audits) para segurança adicional. +A segurança é também um importante ganho. Bibliotecas de contratos inteligentes de código aberto também são frequentemente cuidadosamente controladas. Dado que muitos projectos dependem deles, existe um forte incentivo por parte da comunidade para os manter sob constante revisão. É muito mais comum encontrar erros no código do aplicativo do que em bibliotecas de contratos reutilizáveis. Algumas bibliotecas também passam por [auditorias externas](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/audits) para segurança adicional. No entanto, o uso de bibliotecas de contratos inteligentes acarreta o risco de incluir código com que você não está familiarizado no seu projeto. É tentador importar um contrato e incluí-lo diretamente no seu projeto, mas sem um bom entendimento do que esse contrato faz, você pode estar inadvertidamente a introduzir um problema no seu sistema devido a um comportamento inesperado. Certifique-se de ler a documentação do código que você está importando, e, em seguida, revise o próprio código antes de torná-lo parte do seu projeto! @@ -87,31 +87,31 @@ Por último, ao decidir se deve incluir uma biblioteca, considere a sua utiliza ## Ferramentas relacionadas {#related-tools} -**OpenZeppelin Contracts -** **_Biblioteca para o desenvolvimento de contratos inteligentes seguros._** +**OpenZeppelin Contracts -** **_A biblioteca mais popular para o desenvolvimento seguro de contratos inteligentes._** - [Documentação](https://docs.openzeppelin.com/contracts/) - [GitHub](https://github.com/OpenZeppelin/openzeppelin-contracts) - [Fórum da Comunidade](https://forum.openzeppelin.com/c/general/16) -**DappSys -** **_Blocos de código seguros, simples e flexíveis para contratos inteligentes._** +**DappSys -** **_Blocos de construção seguros, simples e flexíveis para contratos inteligentes._** - [Documentação](https://dappsys.readthedocs.io/) - [GitHub](https://github.com/dapphub/dappsys) -**HQ20 -** **_Um projeto Solidity com contratos, bibliotecas e exemplos para ajudá-lo a construir aplicações distribuídas completas para o mundo real._** +**HQ20 -** **_Um projeto Solidity com contratos, bibliotecas e exemplos para ajudá-lo a construir aplicativos distribuídos completos para o mundo real._** - [GitHub](https://github.com/HQ20/contracts) -**thirdweb Solidity SDK -** **_Fornece as ferramentas necessárias para criar contratos inteligentes e personalizados com eficiência_** +**thirdweb Solidity SDK -** **_Fornece as ferramentas necessárias para construir contratos inteligentes personalizados de forma eficiente_** - [Documentação](https://portal.thirdweb.com/contracts/build/overview) - [GitHub](https://github.com/thirdweb-dev/contracts) ## Tutoriais relacionados {#related-tutorials} -- [Considerações de segurança para os desenvolvedores da Ethereum](/developers/docs/smart-contracts/security/) _– Um tutorial sobre considerações de segurança ao criar contratos inteligentes, incluindo o uso da biblioteca._ -- [Entenda o contrato inteligente de token ERC-20](/developers/tutorials/understand-the-erc-20-token-smart-contract/) _-Tutorial no padrão ERC20, fornecido por várias bibliotecas._ +- [Considerações de segurança para desenvolvedores Ethereum](/developers/docs/smart-contracts/security/) _– Um tutorial sobre considerações de segurança ao construir contratos inteligentes, incluindo o uso de bibliotecas._ +- [Entenda o contrato inteligente do token ERC-20](/developers/tutorials/understand-the-erc-20-token-smart-contract/) _- Tutorial sobre o padrão ERC20, fornecido por várias bibliotecas._ ## Leitura adicional {#further-reading} -_Conhece um recurso da comunidade que te ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ diff --git a/public/content/translations/pt-br/developers/docs/smart-contracts/naming/index.md b/public/content/translations/pt-br/developers/docs/smart-contracts/naming/index.md new file mode 100644 index 00000000000..41183a694e4 --- /dev/null +++ b/public/content/translations/pt-br/developers/docs/smart-contracts/naming/index.md @@ -0,0 +1,101 @@ +--- +title: Nomeando contratos inteligentes +description: "Melhores práticas para nomear contratos inteligentes do Ethereum com ENS" +lang: pt-br +--- + +Os contratos inteligentes são uma pedra angular da infraestrutura descentralizada do Ethereum, permitindo aplicações e protocolos autônomos. Mas, mesmo com a evolução das capacidades dos contratos, usuários e desenvolvedores ainda dependem de endereços hexadecimais brutos para identificar e referenciar esses contratos. + +Nomear contratos inteligentes com o [Ethereum Name Service (ENS)](https://ens.domains/) melhora a experiência do usuário, eliminando os endereços de contrato hexadecimais e reduz o risco de ataques como envenenamento de endereços e ataques de spoofing. Este guia explica por que a nomeação de contratos inteligentes é importante, como ela pode ser implementada e as ferramentas disponíveis, como o [Enscribe](https://www.enscribe.xyz), para simplificar o processo e ajudar os desenvolvedores a adotar essa prática. + +## Por que nomear contratos inteligentes? {#why-name-contracts} + +### Identificadores legíveis por humanos {#human-readable-identifiers} + +Em vez de interagir com endereços de contrato opacos como `0x8f8e...f9e3`, os desenvolvedores e usuários podem usar nomes legíveis por humanos como `v2.myapp.eth`. Isso simplifica as interações de contratos inteligentes. + +Isso é possível graças ao [Ethereum Name Service](https://ens.domains/), que fornece um serviço de nomeação descentralizado para endereços Ethereum. Isso é análogo a como o Serviço de Nomes de Domínio (DNS) permite que os usuários da internet acessem endereços de rede usando um nome como ethereum.org em vez de um endereço IP como `104.18.176.152`. + +### Segurança e confiança aprimoradas {#improved-security-and-trust} + +Contratos nomeados ajudam a reduzir transações acidentais para o endereço errado. Eles também ajudam os usuários a identificar contratos vinculados a aplicativos ou marcas específicas. Isso adiciona uma camada de confiança reputacional, especialmente quando os nomes estão vinculados a domínios pais bem conhecidos como `uniswap.eth`. + +Devido ao comprimento de 42 caracteres de um endereço Ethereum, é muito difícil para os usuários identificarem pequenas alterações nos endereços, onde alguns caracteres foram modificados. Por exemplo, um endereço como `0x58068646C148E313CB414E85d2Fe89dDc3426870` normalmente seria truncado para `0x580...870` por aplicativos voltados para o usuário, como carteiras. É improvável que um usuário perceba um endereço malicioso onde alguns caracteres foram alterados. + +Esse tipo de técnica é empregado em ataques de falsificação e envenenamento de endereço, nos quais os usuários são levados a acreditar que estão interagindo ou enviando fundos para o endereço correto, quando, na verdade, o endereço apenas se assemelha ao endereço correto, mas não é o mesmo. + +Nomes ENS para carteiras e contratos protegem contra esses tipos de ataques. Assim como os ataques de spoofing de DNS, os ataques de spoofing de ENS também podem ocorrer, no entanto, um usuário tem maior probabilidade de notar um erro de digitação em um nome ENS do que uma pequena modificação em um endereço hexadecimal. + +### Melhor UX para carteiras e exploradores {#better-ux} + +Quando um contrato inteligente foi configurado com um nome ENS, é possível para aplicativos como carteiras e exploradores de blockchain exibir nomes ENS para contratos inteligentes, em vez de endereços hexadecimais. Isso proporciona uma melhoria significativa na experiência do usuário (UX) para os usuários. + +Por exemplo, ao interagir com um aplicativo como o Uniswap, os usuários normalmente verão que o aplicativo com o qual estão interagindo está hospedado no site `uniswap.org`, mas um endereço de contrato hexadecimal seria apresentado se o Uniswap não nomeasse seus contratos inteligentes com ENS. Se o contrato for nomeado, em vez disso, eles poderiam ver `v4.contracts.uniswap.eth`, o que é muito mais útil. + +## Nomeação na implantação vs. pós-implantação {#when-to-name} + +Há dois momentos em que os contratos inteligentes podem ser nomeados: + +- **No momento da implantação**: atribuir um nome ENS ao contrato no momento em que ele é implantado. +- **Após a implantação**: mapear um endereço de contrato existente para um novo nome ENS. + +Ambas as abordagens dependem de ter acesso de proprietário ou gerente a um domínio ENS para que possam criar e definir registros ENS. + +## Como funciona a nomeação de contratos com ENS {#how-ens-naming-works} + +Os nomes ENS são armazenados na cadeia e resolvidos para endereços Ethereum através de resolvedores ENS. Para nomear um contrato inteligente: + +1. Registre ou controle um domínio pai ENS (p. ex., `myapp.eth`) +2. Crie um subdomínio (p. ex., `v1.myapp.eth`) +3. Defina o registro de `endereço` do subdomínio para o endereço do contrato +4. Defina o registro reverso do contrato para o ENS para permitir que o nome seja encontrado por meio de seu endereço + +Os nomes ENS são hierárquicos e suportam um número ilimitado de subnomes. A definição desses registros normalmente envolve a interação com o registro ENS e os contratos do resolvedor público. + +## Ferramentas para nomear contratos {#tools} + +Existem duas abordagens para nomear contratos inteligentes. Seja usando o [App ENS](https://app.ens.domains) com alguns passos manuais, ou usando o [Enscribe](https://www.enscribe.xyz). Eles são descritos abaixo. + +### Configuração manual do ENS {#manual-ens-setup} + +Usando o [App ENS](https://app.ens.domains/), os desenvolvedores podem criar subnomes manualmente e definir registros de endereço de encaminhamento. No entanto, eles não podem definir um nome primário para um contrato inteligente, definindo o registro reverso para o nome através do aplicativo ENS. Devem ser tomadas medidas manuais, que são abordadas nos [documentos do ENS](https://docs.ens.domains/web/naming-contracts/). + +### Enscribe {#enscribe} + +[Enscribe](https://www.enscribe.xyz) simplifica a nomeação de contratos inteligentes com o ENS e aumenta a confiança do usuário em contratos inteligentes. Ele fornece: + +- **Implantação e nomeação atômicas**: atribua um nome ENS ao implantar um novo contrato +- **Nomeação pós-implantação**: anexe nomes a contratos já implantados +- **Suporte multichain**: funciona em redes Ethereum e L2 onde o ENS é suportado +- **Dados de verificação de contrato**: inclui dados de verificação de contrato obtidos de várias fontes para aumentar a confiança dos usuários + +O Enscribe suporta nomes ENS fornecidos pelos usuários ou seus próprios domínios se o usuário não tiver um nome ENS. + +Você pode acessar o [Enscribe App](https://app.enscribe.xyz) para começar a nomear e visualizar contratos inteligentes. + +## Boas práticas {#best-practices} + +- **Use nomes claros e com versão**, como `v1.myapp.eth`, para tornar as atualizações do contrato transparentes +- **Defina registros reversos** para vincular contratos a nomes ENS para visibilidade em aplicativos como carteiras e exploradores da blockchain. +- **Monitore os vencimentos de perto** se quiser evitar alterações acidentais de propriedade +- **Verifique a fonte do contrato** para que os usuários possam confiar que o contrato nomeado se comporta como esperado + +## Riscos {#risks} + +A nomeação de contratos inteligentes oferece benefícios significativos para os usuários do Ethereum, no entanto, os proprietários de domínios ENS devem ser vigilantes em relação à sua gestão. Riscos notáveis incluem: + +- **Vencimento**: assim como os nomes de DNS, os registros de nomes de ENS têm duração finita. Portanto, é vital que os proprietários monitorem as datas de validade de seus domínios e os renovem com bastante antecedência do vencimento. Tanto o App ENS quanto o Enscribe fornecem indicadores visuais para os proprietários de domínio quando o vencimento está se aproximando. +- **Mudança de propriedade**: os registros ENS são representados como NFTs na Ethereum, onde o proprietário de um domínio `.eth` específico tem o NFT associado em sua posse. Portanto, se uma conta diferente assumir a propriedade deste NFT, o novo proprietário poderá modificar quaisquer registros ENS como achar melhor. + +Para mitigar esses riscos, a conta do proprietário dos domínios de segundo nível (2LD) `.eth` deve ser protegida por meio de uma carteira de assinaturas múltiplas, com subdomínios sendo criados para gerenciar a nomenclatura de contratos. Dessa forma, no caso de quaisquer alterações acidentais ou maliciosas na propriedade no nível do subdomínio, elas podem ser substituídas pelo proprietário do 2LD. + +## O futuro da nomeação de contratos {#future} + +A nomeação de contratos está se tornando uma melhor prática para o desenvolvimento de dapps, semelhante a como os nomes de domínio substituíram os endereços IP na web. À medida que mais infraestrutura, como carteiras, exploradores e painéis, integram a resolução ENS para contratos, os contratos nomeados melhorarão a segurança e reduzirão os erros em todo o ecossistema. + +Ao tornar os contratos inteligentes mais fáceis de reconhecer e de se raciocinar sobre, a nomeação ajuda a preencher a lacuna entre os usuários e os aplicativos na Ethereum, melhorando a segurança e a experiência do usuário (UX). + +## Leitura adicional {#further-reading} + +- [Nomeando Contratos Inteligentes com ENS](https://docs.ens.domains/web/naming-contracts/) +- [Nomeando Contratos Inteligentes com Enscribe](https://www.enscribe.xyz/docs). diff --git a/public/content/translations/pt-br/developers/docs/smart-contracts/security/index.md b/public/content/translations/pt-br/developers/docs/smart-contracts/security/index.md index 2f250c0fed8..9ede9cb3b3f 100644 --- a/public/content/translations/pt-br/developers/docs/smart-contracts/security/index.md +++ b/public/content/translations/pt-br/developers/docs/smart-contracts/security/index.md @@ -1,14 +1,14 @@ --- -title: Segurança de um Contrato Inteligente -description: Uma visão geral das diretrizes para a construção segura de contratos inteligentes na Ethereum +title: "Segurança de um Contrato Inteligente" +description: "Uma visão geral das diretrizes para a construção segura de contratos inteligentes na Ethereum" lang: pt-br --- Os contratos inteligentes são extremamente flexíveis e capazes de controlar grandes quantidades de valor e dados, enquanto executam lógica imutável com base no código implantado na blockchain. Isto criou um vibrante ecossistema de aplicações descentralizadas e sem confiança que oferecem muitas vantagens sobre os sistemas legados. Eles também representam oportunidades para os invasores que procuram lucrar explorando vulnerabilidades em contratos inteligentes. -Blockchains públicas, como a Ethereum, complicam ainda mais a questão de proteger contratos inteligentes. O código de contrato implantado _geralmente_ não pode ser alterado para corrigir falhas de segurança, enquanto os ativos roubados de contratos inteligentes são extremamente difíceis de rastrear e, em sua maioria, irrecuperáveis devido à imutabilidade. +Blockchains públicas, como a Ethereum, complicam ainda mais a questão de proteger contratos inteligentes. O código do contrato implantado _geralmente_ não pode ser alterado para corrigir falhas de segurança, enquanto os ativos roubados de contratos inteligentes são extremamente difíceis de rastrear e, em sua maioria, irrecuperáveis devido à imutabilidade. -Embora os números variem, estima-se que o valor total roubado ou perdido devido a defeitos de segurança em contratos inteligentes é facilmente superior a 1 bilhão de dólares. Isso inclui incidentes de alto perfil, como o [DAO hack](https://hackingdistributed.com/2016/06/18/analysis-of-the-dao-exploit/) (com 3,6 milhões de ETH roubados, no valor de mais de US$ 1 bilhão de dólares nos preços de hoje), [Hack da carteira múltiplas assinaturas da Parity](https://www.coindesk.com/markets/2017/07/19/30-million-ether-reported-stolen-due-to-parity-wallet-breach) (US$ 30 milhões perdidos para hackers) e o [Caso da carteira congelada da Parity](https://www.theguardian.com/technology/2017/nov/08/cryptocurrency-300m-dollars-stolen-bug-ether) (mais de US$ 300 milhões em ETH bloqueados para sempre). +Embora os números variem, estima-se que o valor total roubado ou perdido devido a defeitos de segurança em contratos inteligentes é facilmente superior a 1 bilhão de dólares. Isso inclui incidentes de grande repercussão, como o [hack da DAO](https://hackingdistributed.com/2016/06/18/analysis-of-the-dao-exploit/) (3,6M de ETH roubados, valendo mais de US$ 1 bilhão nos preços de hoje), o [hack da carteira multi-assinatura da Parity](https://www.coindesk.com/markets/2017/07/19/30-million-ether-reported-stolen-due-to-parity-wallet-breach) (US$ 30 milhões perdidos para hackers) e o [problema da carteira congelada da Parity](https://www.theguardian.com/technology/2017/nov/08/cryptocurrency-300m-dollars-stolen-bug-ether) (mais de US$ 300 milhões em ETH bloqueados para sempre). As questões mencionadas tornam imperativo para os desenvolvedores investirem esforços na construção de contratos inteligentes seguros, sólidos e resistentes. Segurança dos contratos inteligentes é um assunto sério, e todo desenvolvedor deve aprender. Este guia abrangerá considerações de segurança para desenvolvedores de Ethereum e explorará recursos para melhorar a segurança dos contratos inteligentes. @@ -16,73 +16,73 @@ As questões mencionadas tornam imperativo para os desenvolvedores investirem es Certifique-se de estar familiarizado com os [fundamentos do desenvolvimento de contratos inteligentes](/developers/docs/smart-contracts/) antes de abordar a segurança. -## Diretrizes para construir contratos inteligentes Ethereum seguros {#smart-contract-security-guidelines} +## Diretrizes para a criação de contratos inteligentes Ethereum seguros {#smart-contract-security-guidelines} -### 1. Crie controles de acesso adequados {#design-proper-access-controls} +### 1. Projete controles de acesso adequados {#design-proper-access-controls} -Em contratos inteligentes, funções marcadas `públicas` ou `externas` podem ser chamadas por quaisquer contas externas (EOAs) ou contas de contrato. Especificar a visibilidade pública para funções é necessária se você quiser que outras pessoas interajam com seu contrato. As funções marcadas como `privadas`, no entanto, só podem ser chamadas por funções dentro do contrato inteligente e não por contas externas. Dar a cada participantes da rede o acesso às funções do contrato pode causar problemas, especialmente se isso significar que qualquer pessoa pode realizar operações confidenciais (por exemplo, cunhar novos tokens). +Em contratos inteligentes, as funções marcadas como `public` ou `external` podem ser chamadas por quaisquer contas de propriedade externa (EOAs) ou contas de contrato. Especificar a visibilidade pública para funções é necessária se você quiser que outras pessoas interajam com seu contrato. No entanto, as funções marcadas como `private` só podem ser chamadas por funções dentro do contrato inteligente, e não por contas externas. Dar a cada participantes da rede o acesso às funções do contrato pode causar problemas, especialmente se isso significar que qualquer pessoa pode realizar operações confidenciais (por exemplo, cunhar novos tokens). -Para evitar o uso não autorizado de funções do contrato inteligente, é necessário implementar controles de acesso seguros. Os mecanismos de controle de acesso restringem a capacidade de usar determinadas funções em um contrato inteligente para entidades aprovadas, como contas responsáveis pelo gerenciamento do contrato. O **padrão de propriedade** e o **controle baseado em funções** são dois padrões úteis para implementar o controle de acesso em contratos inteligentes: +Para evitar o uso não autorizado de funções do contrato inteligente, é necessário implementar controles de acesso seguros. Os mecanismos de controle de acesso restringem a capacidade de usar determinadas funções em um contrato inteligente para entidades aprovadas, como contas responsáveis pelo gerenciamento do contrato. O **padrão Ownable** e o **controle baseado em papéis** são dois padrões úteis para a implementação do controle de acesso em contratos inteligentes: -#### Padrão proprietário {#ownable-pattern} +#### Padrão Ownable {#ownable-pattern} -No padrão Proprietário, um endereço é definido como o “dono” do contrato durante o processo de criação do contrato. As funções protegidas são atribuídas a um modificador `OnlyOwner`, que garante que o contrato autentique a identidade do endereço de chamada antes de executar a função. Chamadas para funções protegidas de outros endereços além do proprietário do contrato sempre revertem, impedindo o acesso indesejado. +No padrão Proprietário, um endereço é definido como o “dono” do contrato durante o processo de criação do contrato. As funções protegidas recebem um modificador `OnlyOwner`, que garante que o contrato autentique a identidade do endereço de chamada antes de executar a função. Chamadas para funções protegidas de outros endereços além do proprietário do contrato sempre revertem, impedindo o acesso indesejado. -#### Controle de acesso baseado em funções {#role-based-access-control} +#### Controle de acesso baseado em papéis {#role-based-access-control} -Registrar um único endereço como `Proprietário` em um contrato inteligente apresenta o risco de centralização e representa um único ponto de falha. Se as chaves da conta do proprietário forem comprometidas, os invasores podem invadir o contrato de propriedade. É por isso que usar um padrão de controle de acesso baseado em funções com várias contas administrativas pode ser uma opção melhor. +Registrar um único endereço como `Owner` em um contrato inteligente introduz o risco de centralização e representa um único ponto de falha. Se as chaves da conta do proprietário forem comprometidas, os invasores podem invadir o contrato de propriedade. É por isso que usar um padrão de controle de acesso baseado em funções com várias contas administrativas pode ser uma opção melhor. No controle de acesso baseado em funções, o acesso a funções confidenciais é distribuído entre um conjunto de participantes confiáveis. Por exemplo, uma conta pode ser responsável por cunhar tokens (transformar um ativo digital na blockchain), enquanto outra conta realiza atualizações ou pausa o contrato. Descentralizar o controle de acesso dessa forma elimina pontos únicos de falha e reduz as suposições de confiança para os usuários. ##### Usando carteiras multi-assinatura -Outra abordagem para implementar controle seguro de acesso é usar uma [conta de múltiplas assinaturas](/developers/docs/smart-contracts/#multisig) para gerenciar um contrato. Ao contrário de um EOA (conta de propriedade externa) regular, as contas com várias assinaturas são de propriedade de várias entidades e exigem assinaturas de um número mínimo de contas - digamos 3 de 5 - para executar transações. +Outra abordagem para implementar um controle de acesso seguro é usar uma [conta de múltiplas assinaturas](/developers/docs/smart-contracts/#multisig) para gerenciar um contrato. Ao contrário de um EOA (conta de propriedade externa) regular, as contas com várias assinaturas são de propriedade de várias entidades e exigem assinaturas de um número mínimo de contas - digamos 3 de 5 - para executar transações. O uso de multisig (múltiplas assinaturas) para controle de acesso introduz uma camada extra de segurança, pois as ações no contrato de destino exigem o consentimento de várias partes. Isso é particularmente útil se usar o padrão Proprietário, pois torna mais difícil para um invasor ou malfeitor interno de manipular funções de contrato confidenciais para fins maliciosos. -### 2. Use as instruções require(), assert() e revert() para proteger as operações do contrato {#use-require-assert-revert} +### 2. Use as instruções `require()`, `assert()` e `revert()` para proteger as operações do contrato {#use-require-assert-revert} -Como mencionado, qualquer pessoa pode chamar funções públicas em seu contrato inteligente uma vez que ele é implantado na blockchain. Como você não pode saber com antecedência como as contas externas (EOA) vão interagir com um contrato, é ideal implementar proteções internas contra operações problemáticas antes da implantação. Você pode aplicar o comportamento correto nos contratos inteligentes usando as instruções `require()`, `assert()` e `revert()` para acionar exceções e reverter mudanças de estado se a execução não satisfazer determinados requisitos. +Como mencionado, qualquer pessoa pode chamar funções públicas em seu contrato inteligente uma vez que ele é implantado na blockchain. Como você não pode saber com antecedência como as contas externas (EOA) vão interagir com um contrato, é ideal implementar proteções internas contra operações problemáticas antes da implantação. Você pode impor o comportamento correto em contratos inteligentes usando as instruções `require()`, `assert()` e `revert()` para acionar exceções e reverter alterações de estado se a execução falhar em satisfazer certos requisitos. -**`require()`**: `require` são definidas no início das funções e garantem condições predefinidas antes que a função chamada seja executada. Uma instrução `require` pode ser usada para validar entradas do usuário, verificar variáveis de estado ou autenticar a identidade da conta de chamada antes de prosseguir com uma função. +**`require()`**: As instruções `require` são definidas no início das funções e garantem que as condições predefinidas sejam atendidas antes que a função chamada seja executada. Uma instrução `require` pode ser usada para validar entradas do usuário, verificar variáveis de estado ou autenticar a identidade da conta chamadora antes de prosseguir com uma função. -**`assert()`**: `assert()` é usado para detectar erros internos e verificar por violações de "invariáveis" em seu código. Uma invariável é uma asserção lógica sobre o estado de um contrato que deve ser verdadeira para todas as execuções de função. Um exemplo invariável é a oferta total máxima ou saldo de um contrato de token. O uso do `assert()` garante que seu contrato nunca atinja um estado vulnerável e, se isso acontecer, todas as mudanças nas variáveis de estado serão revertidas. +**`assert()`**: `assert()` é usado para detectar erros internos e verificar violações de “invariantes” em seu código. Uma invariável é uma asserção lógica sobre o estado de um contrato que deve ser verdadeira para todas as execuções de função. Um exemplo invariável é a oferta total máxima ou saldo de um contrato de token. O uso de `assert()` garante que seu contrato nunca atinja um estado vulnerável e, se isso acontecer, todas as alterações nas variáveis de estado serão revertidas. -**`revert()`**: `revert()` pode ser usado em uma instrução if-else (se-senão) que aciona uma exceção se a condição exigida não for satisfeita. O modelo de contrato abaixo usa o `revert()` para proteger a execução de funções: +**`revert()`**: `revert()` pode ser usado em uma instrução if-else que aciona uma exceção se a condição necessária não for satisfeita. O contrato de exemplo abaixo usa `revert()` para proteger a execução das funções: ``` pragma solidity ^0.8.4; contract VendingMachine { address owner; - error Unauthorized(); + error NaoAutorizado(); function buy(uint amount) public payable { if (amount > msg.value / 2 ether) - revert("Not enough Ether provided."); - // Perform the purchase. + revert("Ether insuficiente fornecido."); + // Realizar a compra. } function withdraw() public { if (msg.sender != owner) - revert Unauthorized(); + revert NaoAutorizado(); payable(msg.sender).transfer(address(this).balance); } } ``` -### 3. Teste contratos inteligentes e verifique a corretude do código {#test-smart-contracts-and-verify-code-correctness} +### 3. Teste contratos inteligentes e verifique a exatidão do código {#test-smart-contracts-and-verify-code-correctness} -A imutabilidade do código em execução na [Máquina Virtual Ethereum](/developers/docs/evm/) significa que os contratos inteligentes demandam um nível mais alto de avaliação de qualidade durante a fase de desenvolvimento. Testar seu contrato extensivamente e observá-lo para quaisquer resultados inesperados irão melhorar muito a segurança e proteger os seus usuários a longo prazo. +A imutabilidade do código em execução na [Máquina Virtual Ethereum](/developers/docs/evm/) significa que os contratos inteligentes exigem um nível mais alto de avaliação de qualidade durante a fase de desenvolvimento. Testar seu contrato extensivamente e observá-lo para quaisquer resultados inesperados irão melhorar muito a segurança e proteger os seus usuários a longo prazo. -O método habitual é escrever pequenos testes unitários utilizando dados simulados que o contrato deverá receber dos usuários. O [teste unitário](/developers/docs/smart-contracts/testing/#unit-testing) é bom para testar a funcionalidade de determinadas funções e garantir que um contrato inteligente funcione como esperado. +O método habitual é escrever pequenos testes unitários utilizando dados simulados que o contrato deverá receber dos usuários. [Teste de unidade](/developers/docs/smart-contracts/testing/#unit-testing) é bom para testar a funcionalidade de certas funções e garantir que um contrato inteligente funcione como esperado. Infelizmente, o teste unitário é minimamente eficaz para melhorar a segurança do contrato inteligente quando usado isoladamente. Um teste unitário pode provar que uma função é executada corretamente para dados simulados (mock), mas os testes unitários são tão eficazes quanto os testes que são escritos. Isso torna difícil detectar casos perdidos de falha e vulnerabilidades que poderiam quebrar a segurança de seu contrato inteligente. -Uma abordagem melhor é combinar testes unitários com testes baseados em propriedades realizados usando [análise estática e dinâmica](/developers/docs/smart-contracts/testing/#static-dynamic-analysis) (do código). A análise estática depende de representações de baixo nível, como [controlar fluxo de controle](https://en.wikipedia.org/wiki/Control-flow_graph) e [árvores de sintaxe abstrata](https:// deepsource.io/glossary/ast/) para analisar estados de programas alcançáveis e caminhos de execução. Enquanto isso, as técnicas de análise dinâmica, como [fuzzing de contrato inteligente](https://www.cyfrin.io/blog/smart-contract-fuzzing-and-invariants-testing-foundry), executam o código do contrato com valores de entrada aleatórios para detectar operações que violam as propriedades de segurança. +Uma abordagem melhor é combinar testes de unidade com testes baseados em propriedades, realizados usando [análise estática e dinâmica](/developers/docs/smart-contracts/testing/#static-dynamic-analysis). A análise estática se baseia em representações de baixo nível, como [gráficos de fluxo de controle](https://en.wikipedia.org/wiki/Control-flow_graph) e [árvores de sintaxe abstrata](https://deepsource.io/glossary/ast/), para analisar os estados do programa e os caminhos de execução alcançáveis. Enquanto isso, as técnicas de análise dinâmica, como o [fuzzing de contratos inteligentes](https://www.cyfrin.io/blog/smart-contract-fuzzing-and-invariants-testing-foundry), executam o código do contrato com valores de entrada aleatórios para detectar operações que violam as propriedades de segurança. -A [Verificação Formal](/developers/docs/smart-contracts/formal-verification) é outra técnica para verificar propriedades de segurança em contratos inteligentes. Ao contrário dos testes regulares, a verificação formal pode comprovar conclusivamente a ausência de erros em um contrato inteligente. Isso é alcançado criando uma especificação formal que captura as propriedades de segurança desejadas e provando que um modelo formal dos contratos adere a esta especificação. +[A verificação formal](/developers/docs/smart-contracts/formal-verification) é outra técnica para verificar as propriedades de segurança em contratos inteligentes. Ao contrário dos testes regulares, a verificação formal pode comprovar conclusivamente a ausência de erros em um contrato inteligente. Isso é alcançado criando uma especificação formal que captura as propriedades de segurança desejadas e provando que um modelo formal dos contratos adere a esta especificação. -### 4. Peça uma revisão independente do seu código {#get-independent-code-reviews} +### 4. Solicite uma revisão independente do seu código {#get-independent-code-reviews} Depois de testar seu contrato, é bom pedir aos outros que verifiquem o código-fonte para quaisquer problemas de segurança. O teste não revelará todas as falhas de um contrato inteligente, mas realizar uma revisão independente aumenta a possibilidade de detectar vulnerabilidades. @@ -92,16 +92,16 @@ A comissão de uma auditoria de contrato inteligente é uma forma de realizar um Com isto em mente, há que evitar tratar as auditorias como uma bala de prata. Auditorias de contratos inteligentes não irão detectar todos os bugs e são concebidas principalmente para fornecer uma rodada adicional de revisões, o qual pode ajudar a detectar problemas perdidos pelos desenvolvedores durante o desenvolvimento e testes iniciais. Você também deve seguir as práticas recomendadas para trabalhar com auditores, como documentar o código apropriadamente e adicionar comentários em linha, para maximizar o benefício de uma auditoria de contrato inteligente. -- [Dicas e sugestões para a auditoria de contratos inteligentes](https://twitter.com/tinchoabbate/status/1400170232904400897) - _@tinchoabbate_ -- [Aproveite ao máximo sua auditoria](https://inference.ag/blog/2023-08-14-tips/) - _Inferência_ +- [Dicas e truques de auditoria de contratos inteligentes](https://twitter.com/tinchoabbate/status/1400170232904400897) - _@tinchoabbate_ +- [Aproveite ao máximo sua auditoria](https://inference.ag/blog/2023-08-14-tips/) - _Inference_ -#### Recompensa por bugs {#bug-bounties} +#### Recompensas por bugs {#bug-bounties} A criação de um programa de recompensas por bugs é outra abordagem para implementar revisões de código externas. Uma recompensa por bugs é uma recompensa financeira dada a indivíduos (geralmente hackers de chapéu branco) que descobrem vulnerabilidades em um aplicativo. -Quando usadas corretamente, as recompensas por bugs dão aos membros da comunidade hacker incentivo para inspecionar seu código em busca de falhas críticas. Um exemplo real é o “bug do dinheiro infinito” que teria deixado um invasor criar uma quantidade ilimitada de Ether no [Optimism](https://www.optimism.io/), um protocolo da [Camada 2](/layer-2/) em execução na Ethereum. Felizmente, um hacker de chapéu branco [descobriu a falha](https://www.saurik.com/optimism.html) e notificou a equipe, [ganhando um grande pagamento no processo](https://cryptoslate.com/critical-bug-in-ethereum-l2-optimism-2m-bounty-paid/). +Quando usadas corretamente, as recompensas por bugs dão aos membros da comunidade hacker incentivo para inspecionar seu código em busca de falhas críticas. Um exemplo da vida real é o “bug do dinheiro infinito” que teria permitido a um invasor criar uma quantidade ilimitada de ether no [Optimism](https://www.optimism.io/), um protocolo de [Camada 2](/layer-2/) em execução no Ethereum. Felizmente, um hacker white hat [descobriu a falha](https://www.saurik.com/optimism.html) e notificou a equipe, [ganhando um grande pagamento no processo](https://cryptoslate.com/critical-bug-in-ethereum-l2-optimism-2m-bounty-paid/). -Uma estratégia útil é definir o pagamento de um programa de recompensas por bugs proporcionalmente à quantidade de fundos em jogo. Descrita como a “[recompensa por bugs que escala](https://medium.com/immunefi/a-defi-security-standard-the-scaling-bug-bounty-9b83dfdc1ba7)”, essa abordagem fornece incentivos financeiros para que os indivíduos revelem vulnerabilidades de forma responsável em vez de explorá-las. +Uma estratégia útil é definir o pagamento de um programa de recompensas por bugs proporcionalmente à quantidade de fundos em jogo. Descrita como a “[recompensa por bug de escalabilidade](https://medium.com/immunefi/a-defi-security-standard-the-scaling-bug-bounty-9b83dfdc1ba7)”, essa abordagem fornece incentivos financeiros para que indivíduos divulguem vulnerabilidades de forma responsável, em vez de explorá-las. ### 5. Siga as melhores práticas durante o desenvolvimento de contratos inteligentes {#follow-smart-contract-development-best-practices} @@ -115,11 +115,11 @@ A existência de auditorias e recompensas por bugs não dispensa sua responsabil - Use um [ambiente de desenvolvimento](/developers/docs/frameworks/) para testar, compilar e implantar contratos inteligentes -- Execute seu código por meio de ferramentas básicas de análise de código, como [Cyfrin Aderyn](https://github.com/Cyfrin/aderyn), Mythril e Slither. Idealmente, você deve fazer isso antes de cada solicitação de pull ser mesclado (merge) e comparar as diferenças na saída +- Execute seu código através de ferramentas básicas de análise de código, como [Cyfrin Aderyn](https://github.com/Cyfrin/aderyn), Mythril e Slither. Idealmente, você deve fazer isso antes de cada solicitação de pull ser mesclado (merge) e comparar as diferenças na saída - Garanta que seu código seja compilado sem erros e que o compilador Solidity não emita alertas -- Documente seu código adequadamente (usando [NatSpec](https://solidity.readthedocs.io/en/develop/natspec-format.html)) e descreva detalhes sobre a arquitetura do contrato em linguagem fácil de entender. Isso facilitará para outras pessoas auditarem e revisarem seu código. +- Documente seu código adequadamente (usando [NatSpec](https://solidity.readthedocs.io/en/develop/natspec-format.html)) e descreva detalhes sobre a arquitetura do contrato em uma linguagem de fácil compreensão. Isso facilitará para outras pessoas auditarem e revisarem seu código. ### 6. Implemente planos robustos de recuperação de desastres {#implement-disaster-recovery-plans} @@ -129,30 +129,30 @@ Conceber controles de acesso seguros, implementar modificadores de função e ou Embora os contratos inteligentes Ethereum sejam imutáveis por padrão, é possível alcançar algum grau de mutabilidade usando padrões de atualização. A atualização de contratos é necessária nos casos em que uma falha crítica torna seu contrato antigo inutilizável e a implantação de uma nova lógica é a opção mais viável. -Os mecanismos de atualização de contrato funcionam de forma diferente, mas o “padrão de proxy” é uma das abordagens mais populares para atualizar contratos inteligentes. [Os padrões de proxy](https://www.cyfrin.io/blog/upgradeable-proxy-smart-contract-pattern) dividem o estado e a lógica de um aplicativo entre _dois_ contratos. O primeiro contrato (chamado de 'contrato de proxy') armazena variáveis de estado (por exemplo, saldos de usuários), enquanto o segundo contrato (chamado de 'contrato lógico') contém o código para executar funções de contrato. +Os mecanismos de atualização de contrato funcionam de forma diferente, mas o “padrão de proxy” é uma das abordagens mais populares para atualizar contratos inteligentes. [Padrões de proxy](https://www.cyfrin.io/blog/upgradeable-proxy-smart-contract-pattern) dividem o estado e a lógica de um aplicativo entre _dois_ contratos. O primeiro contrato (chamado de 'contrato de proxy') armazena variáveis de estado (por exemplo, saldos de usuários), enquanto o segundo contrato (chamado de 'contrato lógico') contém o código para executar funções de contrato. -As contas interagem com o contrato de proxy, que despacha todas as chamadas de função para o contrato lógico usando o [`delegatecall()`](https://docs.soliditylang.org/en/v0.8.16/introduction-to-smart-contracts.html?highlight=delegatecall#delegatecall-callcode-and-libraries) em chamada de baixo nível. Ao contrário de uma chamada de mensagem normal, o `delegatecall()` garante que o código executado no endereço do contrato lógico seja executado no contexto do contrato de chamada. Isso significa que o contrato lógico sempre escreverá no armazenamento do proxy (em vez de em seu próprio armazenamento) e os valores originais de `msg.sender` e `msg.value` são preservados. +As contas interagem com o contrato de proxy, que encaminha todas as chamadas de função para o contrato de lógica usando a chamada de baixo nível [`delegatecall()`](https://docs.soliditylang.org/en/v0.8.16/introduction-to-smart-contracts.html?highlight=delegatecall#delegatecall-callcode-and-libraries). Diferente de uma chamada de mensagem regular, `delegatecall()` garante que o código em execução no endereço do contrato de lógica seja executado no contexto do contrato chamador. Isso significa que o contrato de lógica sempre gravará no armazenamento do proxy (em vez de em seu próprio armazenamento) e os valores originais de `msg.sender` e `msg.value` serão preservados. Delegar chamadas para o contrato lógico requer armazenar seu endereço no armazenamento do contrato de proxy. Portanto, atualizar a lógica do contrato é apenas uma questão de implantar outro contrato lógico e armazenar o novo endereço no contrato de proxy. Como as chamadas subsequentes para o contrato de proxy são roteadas automaticamente para o novo contrato lógico, você teria “atualizado” o contrato sem realmente modificar o código. -[Mais sobre atualização de contratos](/developers/docs/smart-contracts/upgrading/). +[Mais sobre a atualização de contratos](/developers/docs/smart-contracts/upgrading/). -#### Interrupções de emergência {#emergency-stops} +#### Paradas de emergência {#emergency-stops} Como mencionado, auditorias e testes extensivos não podem descobrir todos os bugs em um contrato inteligente. Se uma vulnerabilidade aparecer em seu código após a implantação, corrigi-la é impossível, pois você não pode alterar o código em execução no endereço do contrato. Além disso, mecanismos de atualização (por exemplo, padrões de proxy) podem levar tempo para serem implementados (eles geralmente exigem aprovação de diferentes partes), o que só dá aos invasores mais tempo para causar mais danos. A opção nuclear é implementar uma função de “interrupção de emergência” que bloqueia chamadas para funções vulneráveis em um contrato. As interrupções ou paradas de emergência normalmente compreendem os seguintes componentes: -1. Uma variável global booleana indicando se o contrato inteligente está em um estado interrompido ou não. Esta variável é definida como `false` ao criar o contrato, mas reverterá para `true` assim que o contrato for interrompido. +1. Uma variável global booleana indicando se o contrato inteligente está em um estado interrompido ou não. Esta variável é definida como `false` ao configurar o contrato, mas reverterá para `true` assim que o contrato for interrompido. 2. Funções que referenciam a variável booleana em sua execução. Essas funções são acessíveis quando o contrato inteligente não é interrompido e tornam-se inacessíveis quando o recurso da interrupção de emergência é acionado. -3. Uma entidade que tem acesso à função da interrupção de emergência, que define a variável booleana como `true`. Para evitar ações maliciosas, as chamadas para essa função podem ser restritas a um endereço confiável (por exemplo, o proprietário do contrato). +3. Uma entidade que tenha acesso à função de parada de emergência, que define a variável booleana como `true`. Para evitar ações maliciosas, as chamadas para essa função podem ser restritas a um endereço confiável (por exemplo, o proprietário do contrato). -Uma vez que o contrato ative a parada ou interrupção de emergência, determinadas funções não poderão ser chamadas. Isso é alcançado envolvendo funções de seleção em um modificador que faz referência à variável global. Veja abaixo [um exemplo](https://github.com/fravoll/solidity-patterns/blob/master/EmergencyStop/EmergencyStop.sol) que descreve uma implementação desse padrão em contratos: +Uma vez que o contrato ative a parada ou interrupção de emergência, determinadas funções não poderão ser chamadas. Isso é alcançado envolvendo funções de seleção em um modificador que faz referência à variável global. Abaixo está [um exemplo](https://github.com/fravoll/solidity-patterns/blob/master/EmergencyStop/EmergencyStop.sol) que descreve uma implementação desse padrão em contratos: ```solidity -// Este código não foi auditado profissionalmente e não faz promessas sobre sua segurança ou correção. Use por sua conta e risco. +// Este código não foi auditado profissionalmente e não faz promessas sobre segurança ou exatidão. Use por sua conta e risco. contract EmergencyStop { @@ -169,7 +169,7 @@ contract EmergencyStop { } modifier onlyAuthorized { - // Check for authorization of msg.sender here + // Verifique a autorização do msg.sender aqui _; } @@ -182,20 +182,20 @@ contract EmergencyStop { } function deposit() public payable stoppedInEmergency { - // Deposit logic happening here + // Lógica de depósito aqui } function emergencyWithdraw() public onlyWhenStopped { - // Emergency withdraw happening here + // Saque de emergência aqui } } ``` Este exemplo mostra as características básicas das interrupções de emergência: -- `isStopped` é um booleano avaliado como `false` no início e `true` quando o contrato entra no modo de emergência. +- `isStopped` é uma variável booleana que avalia para `false` no início e `true` quando o contrato entra no modo de emergência. -- Os modificadores de função `onlyWhenStopped` e `stoppedInEmergency` verificam a variável `isStopped`. `stoppedInEmergency` é usado para controlar funções que devem ser inacessíveis quando o contrato é vulnerável (por exemplo, `deposit()`). As chamadas para essas funções simplesmente serão revertidas. +- Os modificadores de função `onlyWhenStopped` e `stoppedInEmergency` verificam a variável `isStopped`. `stoppedInEmergency` é usado para controlar funções que devem estar inacessíveis quando o contrato está vulnerável (por exemplo, `deposit()`). As chamadas para essas funções simplesmente serão revertidas. `onlyWhenStopped` é usado para funções que devem ser chamadas durante uma emergência (por exemplo, `emergencyWithdraw()`). Essas funções podem ajudar a resolver a situação, daí a sua exclusão da lista de “funções restritas”. @@ -203,7 +203,7 @@ Usar uma funcionalidade de interrupção de emergência fornece um paliativo efi #### Monitoramento de eventos {#event-monitoring} -[Eventos](https://docs.soliditylang.org/en/v0.8.15/contracts.html#events) permitem rastrear chamadas para funções de contrato inteligente e monitorar mudanças em variáveis de estado. É ideal programar seu contrato inteligente para emitir um evento sempre que alguma parte tomar uma ação crítica de segurança (por exemplo, retirar fundos). +[Eventos](https://docs.soliditylang.org/en/v0.8.15/contracts.html#events) permitem que você rastreie chamadas para funções de contrato inteligente e monitore alterações nas variáveis de estado. É ideal programar seu contrato inteligente para emitir um evento sempre que alguma parte tomar uma ação crítica de segurança (por exemplo, retirar fundos). Registrar eventos e monitorá-los off-chain fornece informações sobre as operações do contrato e auxilia na descoberta mais rápida de ações maliciosas. Isso significa que sua equipe pode responder mais rapidamente a hacks e tomar medidas para mitigar o impacto sobre os usuários, como pausar funções ou realizar uma atualização. @@ -213,17 +213,17 @@ Você também pode optar por uma ferramenta de monitoramento pronta para uso, qu Você pode querer descentralizar sua aplicação, transferindo o controle dos principais contratos inteligentes para os membros da comunidade. Neste caso, o sistema de contrato inteligente incluirá um módulo de governança — um mecanismo que permite que os membros da comunidade aprovem ações administrativas, por meio de um sistema de governança on-chain. Por exemplo, uma proposta para atualizar um contrato de proxy para uma nova implementação, que pode ser votada pelos detentores do token. -A governança descentralizada pode ser benéfica, especialmente porque alinha os interesses dos desenvolvedores e usuários finais. No entanto, os mecanismos de governança de contratos inteligentes podem apresentar novos riscos se implementados incorretamente. Um cenário plausível é se um invasor adquirir um enorme poder de voto (medido em número de tokens mantidos) ao fazer um [empréstimo imediato](/defi/#flash-loans) e enviar uma proposta maliciosa. +A governança descentralizada pode ser benéfica, especialmente porque alinha os interesses dos desenvolvedores e usuários finais. No entanto, os mecanismos de governança de contratos inteligentes podem apresentar novos riscos se implementados incorretamente. Um cenário plausível é se um invasor adquirir um enorme poder de voto (medido pelo número de tokens detidos) ao fazer um [empréstimo relâmpago](/defi/#flash-loans) e aprovar uma proposta maliciosa. -Uma maneira de evitar problemas relacionados à governança on-chain é [usar um timelock](https://blog.openzeppelin.com/protect-your-users-with-smart-contract-timelocks/). Um timelock impede que um contrato inteligente execute certas ações até que um período específico passe. Outras estratégias incluem atribuir um “peso de voto” a cada token com base em quanto tempo ele foi bloqueado ou medir o poder de voto de um endereço em um período histórico (por exemplo, 2-3 blocos no passado) em vez do bloco atual. Ambos os métodos reduzem a possibilidade de acumular rapidamente o poder de voto para influenciar os votos on-chain. +Uma forma de evitar problemas relacionados à governança on-chain é [usar um timelock](https://blog.openzeppelin.com/protect-your-users-with-smart-contract-timelocks/). Um timelock impede que um contrato inteligente execute certas ações até que um período específico passe. Outras estratégias incluem atribuir um “peso de voto” a cada token com base em quanto tempo ele foi bloqueado ou medir o poder de voto de um endereço em um período histórico (por exemplo, 2-3 blocos no passado) em vez do bloco atual. Ambos os métodos reduzem a possibilidade de acumular rapidamente o poder de voto para influenciar os votos on-chain. -Mais sobre [como projetar sistemas de governança seguros](https://blog.openzeppelin.com/smart-contract-security-guidelines-4-strategies-for-safer-governance-systems/), [diferentes mecanismos de votação em DAOs](https://hackernoon.com/governance-is-the-holy-grail-for-daos) e [os vetores comuns de ataque de DAO que usam DeFi](https://dacian.me/dao-governance-defi-attacks) nos links compartilhados. +Mais sobre [como projetar sistemas de governança seguros](https://blog.openzeppelin.com/smart-contract-security-guidelines-4-strategies-for-safer-governance-systems/), [diferentes mecanismos de votação em DAOs](https://hackernoon.com/governance-is-the-holy-grail-for-daos) e [os vetores comuns de ataque a DAOs que se aproveitam do DeFi](https://dacian.me/dao-governance-defi-attacks) nos links compartilhados. ### 8. Reduza a complexidade do código ao mínimo {#reduce-code-complexity} Os desenvolvedores de software tradicionais estão familiarizados com o princípio KISS (“Não complique, estúpido!”), o qual aconselha a não introdução complexidade desnecessária na concepção de software. Isso segue o pensamento de longa data, de que “sistemas complexos falham de maneiras complexas” e são mais suscetíveis a erros dispendiosos. -Não complicar é de particular importância ao escrever contratos inteligentes, visto que os contratos inteligentes estão potencialmente controlando grandes quantidades de valor. Uma dica para descomplicar ao escrever contratos inteligentes é reutilizar bibliotecas existentes, como [Contratos OpenZeppelin](https://docs.openzeppelin.com/contracts/5.x/), sempre que possível. Como essas bibliotecas foram extensivamente auditadas e testadas pelos desenvolvedores, usá-las reduz as chances de introduzir bugs ao escrever novas funcionalidades do zero. +Não complicar é de particular importância ao escrever contratos inteligentes, visto que os contratos inteligentes estão potencialmente controlando grandes quantidades de valor. Uma dica para alcançar a simplicidade ao escrever contratos inteligentes é reutilizar bibliotecas existentes, como os [Contratos OpenZeppelin](https://docs.openzeppelin.com/contracts/5.x/), sempre que possível. Como essas bibliotecas foram extensivamente auditadas e testadas pelos desenvolvedores, usá-las reduz as chances de introduzir bugs ao escrever novas funcionalidades do zero. Outro conselho comum é escrever funções pequenas e manter contratos modulares, dividindo a lógica do negócio por vários contratos. Não só escrever um código simples reduz a superfície de ataque em um contrato inteligente, também facilita argumentar sobre a exatidão do sistema por inteiro e detectar possíveis erros de concepção mais cedo. @@ -231,14 +231,14 @@ Outro conselho comum é escrever funções pequenas e manter contratos modulares #### Reentrância {#reentrancy} -A EVM (Ethereum Virtual Machine) não permite concorrência (paralelismo), o que significa que dois contratos envolvidos em uma chamada de mensagem não podem ser executados simultaneamente. Uma chamada externa pausa a execução e a memória do contrato de chamada até que a chamada retorne, momento em que a execução prossegue normalmente. Esse processo pode ser formalmente descrito como a transferência do [fluxo de controle](https://www.computerhope.com/jargon/c/contflow.htm) para outro contrato. +A EVM (Ethereum Virtual Machine) não permite concorrência (paralelismo), o que significa que dois contratos envolvidos em uma chamada de mensagem não podem ser executados simultaneamente. Uma chamada externa pausa a execução e a memória do contrato de chamada até que a chamada retorne, momento em que a execução prossegue normalmente. Este processo pode ser formalmente descrito como a transferência do [fluxo de controle](https://www.computerhope.com/jargon/c/contflow.htm) para outro contrato. Embora a maioria seja inofensiva, a transferência de fluxo de controle para contratos não confiáveis pode causar problemas, tais como a reentrância. Um ataque de reentrância ocorre quando um contrato malicioso volta a chamar um contrato vulnerável antes que a invocação da função original ser completa. Este tipo de ataque é melhor explicado com um exemplo. Considere um contrato inteligente ("vítima") que permite que qualquer pessoa deposite e saque Ether: ```solidity -// This contract is vulnerable. Do not use in production +// Este contrato é vulnerável. Não use em produção contract Victim { mapping (address => uint256) public balances; @@ -256,15 +256,15 @@ contract Victim { } ``` -Este contrato expõe uma função `withdraw()` para permitir que os usuários retirem ETH previamente depositados no contrato. Ao processar uma retirada, o contrato realiza as seguintes operações: +Este contrato expõe uma função `withdraw()` para permitir que os usuários saquem ETH previamente depositado no contrato. Ao processar uma retirada, o contrato realiza as seguintes operações: 1. Verifica o saldo de ETH do usuário 2. Envia fundos para o endereço de chamada 3. Redefine seu saldo para 0, evitando saques adicionais do usuário -A função `withdraw()` no contrato `Victim` segue um padrão "verificações-efeitos-interações". Ela _verifica_ se as condições necessárias para a execução são atendidas (ou seja, o usuário tem um saldo ETH positivo) e realiza a _interação_ enviando ETH para o endereço do chamador, antes de aplicar os _efeitos_ da transação (ou seja, reduzir o saldo do usuário). +A função `withdraw()` no contrato `Victim` segue um padrão de “verificações-interações-efeitos”. Ele _verifica_ se as condições necessárias para a execução são satisfeitas (ou seja, o usuário tem um saldo de ETH positivo) e realiza a _interação_ enviando ETH para o endereço do chamador, antes de aplicar os _efeitos_ da transação (ou seja, reduzindo o saldo do usuário). -Se `withdraw()` for chamado de uma conta de propriedade externa (EOA), a função será executada conforme o esperado: `msg.sender.call.value()` envia ETH para o chamador. Contudo, se `msg.sender` é uma conta de contrato inteligente que chama `withdraw()`, o envio de fundos usando `msg.sender.call.value()` também acionará o código armazenado naquele endereço para ser executado. +Se `withdraw()` for chamada a partir de uma conta de propriedade externa (EOA), a função será executada como esperado: `msg.sender.call.value()` envia ETH para o chamador. No entanto, se `msg.sender` for uma conta de contrato inteligente que chama `withdraw()`, o envio de fundos usando `msg.sender.call.value()` também acionará a execução do código armazenado nesse endereço. Imagine que este é o código implantado no endereço do contrato: @@ -289,7 +289,7 @@ Este contrato foi concebido para fazer três coisas: 2. Deposite 1 ETH no contrato Victim 3. Retire o 1 ETH armazenado no contrato inteligente -Não há nada de errado aqui, exceto que o `Attacker` tem outra função que chama `withdraw()` em `Victim` novamente se, o gás restante de entrada do `msg.sender.call.value` for superior a 40.000. Isso dá ao `Invasor` a capacidade de reentrar em `Victim` e retirar mais fundos _antes_ da primeira invocação de `withdraw` concluir. O ciclo fica assim: +Não há nada de errado aqui, exceto que `Attacker` tem outra função que chama `withdraw()` em `Victim` novamente se o gás restante do `msg.sender.call.value` recebido for maior que 40.000. Isso dá a `Attacker` a capacidade de reentrar em `Victim` e sacar mais fundos _antes_ que a primeira invocação de `withdraw` seja concluída. O ciclo fica assim: ```solidity - EOA do invasor chama `Attacker.beginAttack()` com 1 ETH @@ -304,13 +304,13 @@ Não há nada de errado aqui, exceto que o `Attacker` tem outra função que cha - `Victim` finalmente aplica os resultados da primeira transação (e as subsequentes) ao seu estado, então o saldo do `Attacker` é definido para 0 (zero) ``` -O resumo é que, como o saldo do chamador não é definido como 0 até que a execução da função termine, as invocações subsequentes serão bem-sucedidas e permitirão que o chamador retire seu saldo várias vezes. Esse tipo de ataque pode ser usado para drenar um contrato inteligente de seus fundos, como aconteceu no [DAO hack em 2016](https://www.coindesk.com/learn/understanding-the-dao-attack). Os ataques de reentrância ainda são um problema crítico para contratos inteligentes hoje, como mostram as[listagens públicas de exploits de reentrância](https://github.com/pcaversaccio/reentrancy-attacks). +O resumo é que, como o saldo do chamador não é definido como 0 até que a execução da função termine, as invocações subsequentes serão bem-sucedidas e permitirão que o chamador retire seu saldo várias vezes. Esse tipo de ataque pode ser usado para drenar os fundos de um contrato inteligente, como o que aconteceu no [hack da DAO em 2016](https://www.coindesk.com/learn/understanding-the-dao-attack). Os ataques de reentrância ainda são um problema crítico para os contratos inteligentes hoje, como mostram as [listas públicas de explorações de reentrância](https://github.com/pcaversaccio/reentrancy-attacks). ##### Como prevenir ataques de reentrância Uma abordagem para lidar com a reentrância é seguir o [padrão de verificações-efeitos-interações](https://docs.soliditylang.org/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern). Este padrão ordena a execução de funções de forma que o código que realiza as verificações necessárias antes de prosseguir com a execução chegar primeiro, seguido pelo código que manipula o estado do contrato, com o código que interage com outros contratos ou EOAs chegando por último. -O padrão verificação-efeito-interação é usado em uma versão revisada do contrato `Victim` mostrado abaixo: +O padrão de interação de verificação-efeito é usado em uma versão revisada do contrato `Victim` mostrado abaixo: ```solidity contract NoLongerAVictim { @@ -323,9 +323,9 @@ contract NoLongerAVictim { } ``` -Este contrato realiza uma _verificação_ do saldo do usuário, aplica os _efeitos_ da função `withdraw()` (redefinindo o saldo do usuário para 0, zero), e passa a realizar a _interação_ (enviando ETH para o endereço do usuário). Isso garante que o contrato atualize seu armazenamento antes da chamada externa, eliminando a condição de reentrância que permitiu o primeiro ataque. O contrato `Attacker` ainda poderia chamar de volta para `NoLongerAVictim`, mas como `balances[msg.sender]` foi definido como 0 (zero), retiradas adicionais gerarão um erro. +Este contrato realiza uma _verificação_ no saldo do usuário, aplica os _efeitos_ da função `withdraw()` (redefinindo o saldo do usuário para 0) e prossegue para realizar a _interação_ (enviando ETH para o endereço do usuário). Isso garante que o contrato atualize seu armazenamento antes da chamada externa, eliminando a condição de reentrância que permitiu o primeiro ataque. O contrato `Attacker` ainda poderia chamar de volta `NoLongerAVictim`, mas como `balances[msg.sender]` foi definido como 0, saques adicionais gerarão um erro. -Outra opção é usar um bloqueio de exclusão mútua (comumente descrito como "mutex") que bloqueia uma porção do estado de um contrato até que a invocação de uma função seja concluída. Isso é implementado usando uma variável booleana que é definida como `true` antes da execução da função e revertida para `false` após a chamada ser finalizada. Como visto no exemplo abaixo, usar um mutex protege uma função contra chamadas recursivas enquanto a invocação original ainda está sendo processada, efetivamente interrompendo a reentrada. +Outra opção é usar um bloqueio de exclusão mútua (comumente descrito como "mutex") que bloqueia uma porção do estado de um contrato até que a invocação de uma função seja concluída. Isso é implementado usando uma variável booleana que é definida como `true` antes que a função seja executada e reverte para `false` após a conclusão da invocação. Como visto no exemplo abaixo, usar um mutex protege uma função contra chamadas recursivas enquanto a invocação original ainda está sendo processada, efetivamente interrompendo a reentrada. ```solidity pragma solidity ^0.7.0; @@ -335,15 +335,15 @@ contract MutexPattern { mapping(address => uint256) public balances; modifier noReentrancy() { - require(!locked, "Blocked from reentrancy."); + require(!locked, "Bloqueado contra reentrância."); locked = true; _; locked = false; } - // This function is protected by a mutex, so reentrant calls from within `msg.sender.call` cannot call `withdraw` again. - // The `return` statement evaluates to `true` but still evaluates the `locked = false` statement in the modifier + // Esta função está protegida por um mutex, portanto, chamadas reentrantes de dentro de `msg.sender.call` não podem chamar `withdraw` novamente. + // A instrução `return` é avaliada como `true`, mas ainda avalia a instrução `locked = false` no modificador function withdraw(uint _amount) public payable noReentrancy returns(bool) { - require(balances[msg.sender] >= _amount, "No balance to withdraw."); + require(balances[msg.sender] >= _amount, "Nenhum saldo para sacar."); balances[msg.sender] -= _amount; (bool success, ) = msg.sender.call{value: _amount}(""); @@ -354,31 +354,31 @@ contract MutexPattern { } ``` -Você também pode usar um sistema de [receber pagamentos](https://docs.openzeppelin.com/contracts/5.x/api/utils#security#PullPayment), que exige que os usuários retirem fundos dos contratos inteligentes, em vez de um sistema de "envio de pagamentos" que envia fundos para contas. Isso elimina a possibilidade de acionar código inadvertidamente em endereços desconhecidos (e também pode impedir determinados ataques de negação de serviço). +Você também pode usar um sistema de [pagamentos pull](https://docs.openzeppelin.com/contracts/5.x/api/security#PullPayment) que exige que os usuários retirem fundos dos contratos inteligentes, em vez de um sistema de "pagamentos push" que envia fundos para as contas. Isso elimina a possibilidade de acionar código inadvertidamente em endereços desconhecidos (e também pode impedir determinados ataques de negação de serviço). -#### Overflows e underflows em inteiro {#integer-underflows-and-overflows} +#### Underflows e overflows de números inteiros {#integer-underflows-and-overflows} -Um extravasamento (overflow) de números inteiros ocorre quando os resultados de uma operação aritmética ficam fora do intervalo aceitável de valores, fazendo com que ela "role" para o menor valor representável. Por exemplo, um `uint8` só pode armazenar valores até 2^8-1 = 255. Operações aritméticas que resultam em valores superiores a `255` irão extravasar e redefinir `uint` para `0`, semelhante a como o odômetro em um carro é redefinido para 0 uma vez que atinge a quilometragem máxima (999999). +Um extravasamento (overflow) de números inteiros ocorre quando os resultados de uma operação aritmética ficam fora do intervalo aceitável de valores, fazendo com que ela "role" para o menor valor representável. Por exemplo, um `uint8` só pode armazenar valores até 2^8-1=255. As operações aritméticas que resultam em valores superiores a `255` sofrerão overflow e redefinirão `uint` para `0`, semelhante a como o hodômetro de um carro é redefinido para 0 quando atinge a quilometragem máxima (999999). -Os extravasamentos negativos (underflows) de números inteiros acontecem por motivos semelhantes: os resultados de uma operação aritmética ficam abaixo do intervalo aceitável. Digamos que você tentou decrementar `0` em um `uint8`, o resultado simplesmente passaria para o valor máximo representável (`255`). +Underflows de inteiros acontecem por razões semelhantes: os resultados de uma operação aritmética ficam abaixo do intervalo aceitável. Digamos que você tentou decrementar `0` em um `uint8`, o resultado simplesmente passaria para o valor máximo representável (`255`). Tanto overflows quanto underflows de inteiros podem levar a mudanças inesperadas nas variáveis de estado de um contrato e resultar em execução não planejada. Veja abaixo um exemplo mostrando como um invasor pode explorar o extravasamento aritmético em um contrato inteligente para executar uma operação inválida: ``` pragma solidity ^0.7.6; -// Este contrato foi projetado para atuar como um cofre no tempo. -// O usuário pode depositar neste contrato, mas não pode retirar por pelo menos uma semana. -// O usuário também pode estender o tempo de espera além do período estipulado de 1 semana. +// Este contrato foi projetado para atuar como um cofre de tempo. +// O usuário pode depositar neste contrato, mas não pode sacar por pelo menos uma semana. +// O usuário também pode estender o tempo de espera para além do período de espera de 1 semana. /* -1. Implantar TimeLock -2. Ataque de Implantação com endereço do TimeLock -3. Chame Attack.attack enviando 1 ether. Você imediatamente será capaz de - retirar seu ether. +1. Implante o TimeLock +2. Implante o Attack com o endereço do TimeLock +3. Chame Attack.attack enviando 1 ether. Você poderá imediatamente + sacar seu ether. O que aconteceu? -O ataque causou o extravasamento do TimeLock.lockTime e foi capaz de retirar +O ataque causou o overflow de TimeLock.lockTime e foi capaz de sacar antes do período de espera de 1 semana. */ @@ -396,14 +396,14 @@ contract TimeLock { } function withdraw() public { - require(balances[msg.sender] > 0, "Insufficient funds"); - require(block.timestamp > lockTime[msg.sender], "Lock time not expired"); + require(balances[msg.sender] > 0, "Fundos insuficientes"); + require(block.timestamp > lockTime[msg.sender], "O tempo de bloqueio não expirou"); uint amount = balances[msg.sender]; balances[msg.sender] = 0; (bool sent, ) = msg.sender.call{value: amount}(""); - require(sent, "Failed to send Ether"); + require(sent, "Falha ao enviar Ether"); } } @@ -419,11 +419,11 @@ contract Attack { function attack() public payable { timeLock.deposit{value: msg.value}(); /* - if t = current lock time then we need to find x such that + se t = tempo de bloqueio atual, então precisamos encontrar x tal que x + t = 2**256 = 0 - so x = -t + então x = -t 2**256 = type(uint).max + 1 - so x = type(uint).max + 1 - t + então x = type(uint).max + 1 - t */ timeLock.increaseLockTime( type(uint).max + 1 - timeLock.lockTime(address(this)) @@ -435,15 +435,15 @@ contract Attack { ##### Como evitar overflows e underflows de números inteiros -A partir da versão 0.8.0, o compilador Solidity rejeita código que resulta em underflows e overflows de números inteiros. No entanto, contratos compilados com uma versão inferior do compilador devem ou realizar verificações sobre funções que envolvem operações aritméticas ou usar uma biblioteca (e.., [SafeMath](https://docs.openzeppelin.com/contracts/2.x/api/math)) que verifica se há underflow/overflow (extravasamentos negativos/extravasamentos). +A partir da versão 0.8.0, o compilador Solidity rejeita código que resulta em underflows e overflows de números inteiros. No entanto, os contratos compilados com uma versão inferior do compilador devem realizar verificações em funções que envolvam operações aritméticas ou usar uma biblioteca (por exemplo, [SafeMath](https://docs.openzeppelin.com/contracts/2.x/api/math)) que verifica a ocorrência de underflow/overflow. #### Manipulação de oráculos {#oracle-manipulation} -Os [oráculos](/developers/docs/oracles/) fornecem informações off-chain e as enviam on-chain para que os contratos inteligentes possam usá-las. Com oráculos, você pode criar contratos inteligentes que interagem com sistemas off-chain, como mercados capitais, expandindo muito sua aplicação. +[Oráculos](/developers/docs/oracles/) obtêm informações off-chain e as enviam on-chain para uso em contratos inteligentes. Com oráculos, você pode criar contratos inteligentes que interagem com sistemas off-chain, como mercados capitais, expandindo muito sua aplicação. Mas se o oráculo estiver corrompido e enviar informações incorretas on-chain, os contratos inteligentes serão executados com base em entradas erradas, o que pode causar problemas. Essa é a base do “problema do oráculo” (paradoxo), que diz respeito à tarefa de garantir que as informações de um oráculo da blockchain sejam precisas, atualizadas e pontuais. -Uma preocupação de segurança relacionada está usando um oráculo on-chain, como uma troca descentralizada, para obter o preço de ponto por um ativo. Plataformas de empréstimos no setor de [finanças descentralizadas (DeFi)](/defi/) frequentemente fazem isso para determinar o valor da garantia de um usuário para determinar quanto eles podem emprestar. +Uma preocupação de segurança relacionada está usando um oráculo on-chain, como uma troca descentralizada, para obter o preço de ponto por um ativo. As plataformas de empréstimo no setor de [finanças descentralizadas (DeFi)](/defi/) costumam fazer isso para determinar o valor da garantia de um usuário e, assim, definir o quanto ele pode tomar emprestado. Os preços dos DEX são muitas vezes exatos, em grande parte devido aos árbitros que restauram a paridade nos mercados. Porém, eles estão abertos à manipulação, especialmente se o oráculo on-chain calcular os preços dos ativos com base em padrões históricos de negociação (como geralmente é o caso). @@ -451,125 +451,125 @@ Por exemplo, um invasor pode explodir artificialmente o preço de um ativo fazen ##### Como evitar manipulação de oráculos -O requisito mínimo para [evitar a manipulação de oráculos](https://www.cyfrin.io/blog/price-oracle-manipultion-attacks-with-examples) é usar uma rede de oráculos descentralizada que consulte informações de várias fontes para evitar pontos únicos de falha. Na maioria dos casos, oráculos descentralizados tem incentivos criptoeconômicos incorporados para incentivar nós oráculos a relatar informações corretas, tornando-os mais seguros do que os oráculos centralizados. +O requisito mínimo para [evitar a manipulação de oráculos](https://www.cyfrin.io/blog/price-oracle-manipultion-attacks-with-examples) é usar uma rede de oráculos descentralizada que consulta informações de várias fontes para evitar pontos únicos de falha. Na maioria dos casos, oráculos descentralizados tem incentivos criptoeconômicos incorporados para incentivar nós oráculos a relatar informações corretas, tornando-os mais seguros do que os oráculos centralizados. -Se você planeja consultar um oráculo on-chain sobre preços de ativos, considere usar um que implemente um mecanismo de preço médio ponderado por tempo (TWAP). Um [TWAP oracle](https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles) consulta o preço de um ativo em dois pontos diferentes em tempo (que você pode modificar) e calcula o preço de ponto com base na média obtida. Escolher períodos mais longos protege seu protocolo contra a manipulação de preços uma vez que grandes ordens executadas recentemente não podem afetar os preços dos ativos. +Se você planeja consultar um oráculo on-chain sobre preços de ativos, considere usar um que implemente um mecanismo de preço médio ponderado por tempo (TWAP). Um [oráculo TWAP](https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles) consulta o preço de um ativo em dois momentos diferentes (que você pode modificar) e calcula o preço à vista com base na média obtida. Escolher períodos mais longos protege seu protocolo contra a manipulação de preços uma vez que grandes ordens executadas recentemente não podem afetar os preços dos ativos. -## Recursos de segurança de contrato inteligente para desenvolvedores {#smart-contract-security-resources-for-developers} +## Recursos de segurança de contratos inteligentes para desenvolvedores {#smart-contract-security-resources-for-developers} -### Ferramentas para analisar contratos inteligentes e verificar a exatidão do código {#code-analysis-tools} +### Ferramentas para analisar contratos inteligentes e verificar a correção do código {#code-analysis-tools} -- **[Ferramentas de teste e bibliotecas](/developers/docs/smart-contracts/testing/#testing-tools-and-libraries)** - _Coleção de ferramentas e bibliotecas padrão do setor para realizar testes unitários, análise estática e análise dinâmica em contratos inteligentes._ +- **[Ferramentas e bibliotecas de teste](/developers/docs/smart-contracts/testing/#testing-tools-and-libraries)** - _Coleção de ferramentas e bibliotecas padrão da indústria para realizar testes de unidade, análise estática e análise dinâmica em contratos inteligentes._ -- **[Ferramentas de verificação formal](/developers/docs/smart-contracts/formal-verification/#formal-verification-tools)** - _Ferramentas para verificar a correção funcional em contratos inteligentes e verificar inconsistências._ +- **[Ferramentas de verificação formal](/developers/docs/smart-contracts/formal-verification/#formal-verification-tools)** - _Ferramentas para verificar a correção funcional em contratos inteligentes e checar invariantes._ -- **[Serviços de auditoria de contrato inteligente](/developers/docs/smart-contracts/testing/#smart-contract-auditing-services)** - _Lista de organizações que fornecem serviços de auditoria de contrato inteligente para projetos de desenvolvimento Ethereum._ +- **[Serviços de auditoria de contratos inteligentes](/developers/docs/smart-contracts/testing/#smart-contract-auditing-services)** - _Listagem de organizações que fornecem serviços de auditoria de contratos inteligentes para projetos de desenvolvimento Ethereum._ -- **[Plataformas de recompensa por bugs](/developers/docs/smart-contracts/testing/#bug-bounty-platforms) ** - _Plataformas para coordenar recompensas por bugs e recompensar a divulgação responsável de vulnerabilidades críticas em contratos inteligentes._ +- **[Plataformas de recompensa por bugs](/developers/docs/smart-contracts/testing/#bug-bounty-platforms)** - _Plataformas para coordenar recompensas por bugs e premiar a divulgação responsável de vulnerabilidades críticas em contratos inteligentes._ -- **[Fork Checker](https://forkchecker.hashex.org/)** – _Uma ferramenta online gratuita para verificar todas as informações disponíveis sobre um contrato bifurcado._ +- **[Fork Checker](https://forkchecker.hashex.org/)** - _Uma ferramenta on-line gratuita para verificar todas as informações disponíveis sobre um contrato bifurcado._ -- **[ABI Encoder](https://abi.hashex.org/)** – _Um serviço online para codificar suas funções de contrato e argumentos de construtor do Solidity._ +- **[ABI Encoder](https://abi.hashex.org/)** - _Um serviço online gratuito para codificar as funções e os argumentos do construtor do seu contrato Solidity._ -- **[Aderyn](https://github.com/Cyfrin/aderyn)** - _Analisador estático da Solidity, que percorre as árvores de sintaxe abstrata (AST) para identificar vulnerabilidades suspeitas e imprimir os problemas em um formato markdown fácil de usar._ +- **[Aderyn](https://github.com/Cyfrin/aderyn)** - _Analisador estático do Solidity, percorrendo as Árvores de Sintaxe Abstrata (AST) para identificar vulnerabilidades suspeitas e imprimir problemas em um formato markdown de fácil consumo._ ### Ferramentas para monitorar contratos inteligentes {#smart-contract-monitoring-tools} -- **[Alerta leve e em tempo real](https://tenderly.co/alerting/)** - _Uma ferramenta para receber notificações em tempo real quando eventos incomuns ou inesperados acontecem em seus contratos inteligentes ou carteiras._ +- **[Tenderly Real-Time Alerting](https://tenderly.co/monitoring)** - _Uma ferramenta para receber notificações em tempo real quando eventos incomuns ou inesperados acontecem em seus contratos inteligentes ou carteiras._ ### Ferramentas para administração segura de contratos inteligentes {#smart-contract-administration-tools} -- **[Safe](https://safe.global/)** - _Carteira de contrato inteligente em execução na Ethereum, que requer um número mínimo de pessoas para aprovar uma transação antes que ela possa ocorrer (M-de-N)._ +- **[Safe](https://safe.global/)** - _Carteira de contrato inteligente executada na Ethereum que requer um número mínimo de pessoas para aprovar uma transação antes que ela possa ocorrer (M-de-N)._ -- **[Contratos OpenZeppelin](https://docs.openzeppelin.com/contracts/5.x/)** - _Bibliotecas de contrato para implementação de funcionalidades administrativas, incluindo propriedade de contratos, atualizações, controles de acesso, governança, pausabilidade e muito mais._ +- **[OpenZeppelin Contracts](https://docs.openzeppelin.com/contracts/5.x/)** - _Bibliotecas de contratos para implementar recursos administrativos, incluindo propriedade de contrato, atualizações, controles de acesso, governança, pausabilidade e muito mais._ -### Serviços de auditoria de contrato inteligente {#smart-contract-auditing-services} +### Serviços de auditoria de contratos inteligentes {#smart-contract-auditing-services} -- **[ConsenSys Diligence](https://consensys.net/diligence/)** - _Serviço de auditoria para contrato inteligente que ajuda projetos em todo o ecossistema blockchain a garantir que seus protocolos estejam prontos para lançamento e criados para proteger os usuários._ +- **[ConsenSys Diligence](https://diligence.consensys.io/)** - _Serviço de auditoria de contratos inteligentes que ajuda projetos em todo o ecossistema de blockchain a garantir que seus protocolos estejam prontos para o lançamento e construídos para proteger os usuários._ -- **[CertiK](https://www.certik.com/)** - _Empresa de segurança Blockchain pioneira no uso de tecnologia de verificação formal de ponta em contratos inteligentes e redes blockchain._ +- **[CertiK](https://www.certik.com/)** - _Empresa de segurança de blockchain pioneira no uso de tecnologia de verificação formal de ponta em contratos inteligentes e redes de blockchain._ -- **[Trilha de Bits](https://www.trailofbits.com/)** - _Empresa de cibersegurança que combina pesquisa de segurança com uma mentalidade de um invasor para reduzir riscos e fortalecer o código._ +- **[Trail of Bits](https://www.trailofbits.com/)** - _Empresa de segurança cibernética que combina pesquisa de segurança com uma mentalidade de invasor para reduzir riscos e fortalecer códigos._ -- **[PeckShield](https://peckshield.com/)** - _Empresa de segurança Blockchain que oferece produtos e serviços para segurança, privacidade e usabilidade de todo o ecossistema blockchain._ +- **[PeckShield](https://peckshield.com/)** - _Empresa de segurança de blockchain que oferece produtos e serviços para a segurança, privacidade e usabilidade de todo o ecossistema de blockchain._ -- **[QuantStamp](https://quantstamp.com/)** - _Serviço de auditoria que facilita o mainstream de adoção da tecnologia blockchain por meio de serviços de avaliação de segurança e risco._ +- **[QuantStamp](https://quantstamp.com/)** - _Serviço de auditoria que facilita a adoção em massa da tecnologia blockchain por meio de serviços de segurança e avaliação de riscos._ -- **[OpenZeppelin](https://www.openzeppelin.com/security-audits)** - _ Empresa de segurança de contrato inteligente que fornece auditorias de segurança para sistemas distribuídos._ +- **[OpenZeppelin](https://www.openzeppelin.com/security-audits)** - _Empresa de segurança de contratos inteligentes que fornece auditorias de segurança para sistemas distribuídos._ -- **[Runtime Verification](https://runtimeverification.com/)** - _Empresa de segurança especializada em modelagem formal e verificação de contratos inteligentes._ +- **[Runtime Verification](https://runtimeverification.com/)** - _Empresa de segurança especializada em modelagem e verificação formal de contratos inteligentes._ -- **[Hacken](https://hacken.io)** - _Auditor de cibersegurança da Web3 que traz a abordagem de 360 graus à segurança da blockchain._ +- **[Hacken](https://hacken.io)** - _Auditor de segurança cibernética da Web3 que traz a abordagem de 360 graus para a segurança da blockchain._ -- **[Nethermind](https://www.nethermind.io/smart-contract-audits)** - _Serviços de auditoria Solidity e Cairo que garantem a integridade dos contratos inteligentes e a segurança dos usuários em toda a Ethereum e Starknet._ +- **[Nethermind](https://www.nethermind.io/smart-contract-audits)** - _Serviços de auditoria em Solidity e Cairo que garantem a integridade dos contratos inteligentes e a segurança dos usuários em toda a Ethereum e Starknet._ -- **[HashEx](https://hashex.org/)** – _O HashEx se dedica a blockchain e auditoria de contrato inteligente para garantir a segurança de criptomoedas, fornecendo serviços como desenvolvimento de contrato inteligente, teste de penetração e consultoria em blockchain._ +- **[HashEx](https://hashex.org/)** - _A HashEx se concentra na auditoria de blockchain e contratos inteligentes para garantir a segurança de criptomoedas, fornecendo serviços como desenvolvimento de contratos inteligentes, testes de penetração e consultoria em blockchain._ - **[Code4rena](https://code4rena.com/)** - _Plataforma de auditoria competitiva que incentiva especialistas em segurança de contratos inteligentes a encontrar vulnerabilidades e ajudar a tornar a web3 mais segura._ - **[CodeHawks](https://codehawks.com/)** - _Plataforma de auditorias competitivas que hospeda competições de auditoria de contratos inteligentes para pesquisadores de segurança._ -- **[Cyfrin](https://cyfrin.io)** - _Poderosa empresa de segurança da Web3, desenvolvendo a segurança de criptografia por meio de produtos e serviços de auditoria de contratos inteligentes._ +- **[Cyfrin](https://cyfrin.io)** - _Potência em segurança Web3, incubando a segurança de criptoativos através de produtos e serviços de auditoria de contratos inteligentes._ -- **[ImmuneBytes](https://immunebytes.com/smart-contract-audit/)** - _Empresa de segurança Web3 que oferece auditorias de segurança para sistemas de blockchain por meio de uma equipe de auditores experientes e das melhores ferramentas da categoria._ +- **[ImmuneBytes](https://immunebytes.com/smart-contract-audit/)** - _Empresa de segurança Web3 que oferece auditorias de segurança para sistemas de blockchain por meio de uma equipe de auditores experientes e as melhores ferramentas da categoria._ -- **[Oxorio](https://oxor.io/)** - _Auditorias de contratos inteligentes e serviços de segurança de blockchain com experiência em EVM, Solidity, ZK, tecnologia cross-chain para empresas de criptografia e projetos DeFi._ +- **[Oxorio](https://oxor.io/)** - _Auditorias de contratos inteligentes e serviços de segurança de blockchain com experiência em EVM, Solidity, ZK e tecnologia cross-chain para empresas de criptoativos e projetos de DeFi._ -- **[Inferência](https://inference.ag/)** - _Empresa de auditoria de segurança, especializada em auditoria de contratos inteligentes para blockchains baseados em EVM. É graças a seus auditores especializados que eles identificam possíveis problemas e sugerem soluções úteis para corrigi-los antes da implementação._ +- **[Inference](https://inference.ag/)** - _Empresa de auditoria de segurança especializada em auditoria de contratos inteligentes para blockchains baseadas em EVM. É graças a seus auditores especializados que eles identificam possíveis problemas e sugerem soluções úteis para corrigi-los antes da implementação._ ### Plataformas de recompensa por bugs {#bug-bounty-platforms} -- **[Immunefi](https://immunefi.com/)** - _Plataforma de recompensa por bugs para contratos inteligentes e projetos DeFi, onde os pesquisadores de segurança revisam o código, divulgam vulnerabilidades, recebem pagamentos e tornam a criptografia mais segura._ +- **[Immunefi](https://immunefi.com/)** - _Plataforma de recompensa por bugs para contratos inteligentes e projetos de DeFi, onde pesquisadores de segurança revisam códigos, divulgam vulnerabilidades, são pagos e tornam as criptomoedas mais seguras._ -- **[HackerOne](https://www.hackerone.com/)** - _Coordenação de vulnerabilidades e plataforma de recompensa por bugs que conecta empresas com testadores de penetração e pesquisadores de segurança cibernética._ +- **[HackerOne](https://www.hackerone.com/)** - _Plataforma de coordenação de vulnerabilidades e recompensa por bugs que conecta empresas com testadores de penetração e pesquisadores de segurança cibernética._ -- **[HackenProof](https://hackenproof.com/)** - _Plataforma especializada de recompensa por bug para projetos cripto (DeFi, Contratos Inteligentes, Wallets, CEX e muito mais), onde os profissionais de segurança fornecem serviços de triagem e os pesquisadores são pagos por relatórios de bug relevantes, verificados._ +- **[HackenProof](https://hackenproof.com/)** - _Plataforma de recompensa por bugs especializada para projetos de cripto (DeFi, contratos inteligentes, carteiras, CEX e mais), onde profissionais de segurança fornecem serviços de triagem e pesquisadores são pagos por relatórios de bugs relevantes e verificados._ -- **[Sherlock](https://www.sherlock.xyz/)** - _Subscritor em Web3 para segurança de contratos inteligentes, com pagamentos para auditores gerenciados por meio de contratos inteligentes para garantir que bugs relevantes sejam pagos de forma justa._ +- **[Sherlock](https://www.sherlock.xyz/)** - _Subscritor na Web3 para segurança de contratos inteligentes, com pagamentos para auditores gerenciados por meio de contratos inteligentes para garantir que os bugs relevantes sejam pagos de forma justa._ -- **[CodeHawks](https://www.codehawks.com/)** - _Plataforma competitiva de recompensa por bugs em que os auditores participam de concursos e desafios de segurança e, em breve, de suas próprias auditorias privadas._ +- **[CodeHawks](https://www.codehawks.com/)** - _Plataforma de recompensa por bugs competitiva, onde os auditores participam de concursos e desafios de segurança e (em breve) em suas próprias auditorias privadas._ -### Publicações de vulnerabilidades e exploits conhecidos em contratos inteligentes {#common-smart-contract-vulnerabilities-and-exploits} +### Publicações de vulnerabilidades e ataques (exploits) conhecidos de contratos inteligentes {#common-smart-contract-vulnerabilities-and-exploits} -- **[ConsenSys: Ataques Conhecidos em Contrato Inteligente](https://consensysdiligence.github.io/smart-contract-best-practices/attacks/)** - _Explicação fácil das vulnerabilidades de contrato mais significativas, com código de exemplo para a maioria dos casos._ +- **[ConsenSys: ataques conhecidos em contratos inteligentes](https://consensysdiligence.github.io/smart-contract-best-practices/attacks/)** - _Explicação amigável para iniciantes sobre as vulnerabilidades de contrato mais significativas, com código de exemplo para a maioria dos casos._ -- **[Registro SWC](https://swcregistry.io/)** - _Lista selecionada de Enumerações de Vulnerabilidades Comuns (Common Weakness Enumeration, CWE) que se aplicam a contratos inteligentes da Ethereum._ +- **[Registro SWC](https://swcregistry.io/)** - _Lista com curadoria de itens da Enumeração de Fraquezas Comuns (CWE) que se aplicam a contratos inteligentes Ethereum._ -- **[Rekt](https://rekt.news/)** - _Publicação regularmente atualizada de cripto hacks (roubos) e exploits (ataques) de alto-perfil, juntamente com relatórios post-mortem (após incidente) detalhados._ +- **[Rekt](https://rekt.news/)** - _Publicação atualizada regularmente sobre hacks e explorações de criptoativos de grande repercussão, juntamente com relatórios post-mortem detalhados._ -### Desafios para aprender a segurança de contratos inteligentes {#challenges-for-learning-smart-contract-security} +### Desafios para aprender sobre segurança de contratos inteligentes {#challenges-for-learning-smart-contract-security} -- **[A Incrível BlockSec CTF](https://github.com/blockthreat/blocksec-ctfs)** - _Lista selecionada de jogos de guerra de segurança na blockchain, desafios e a [Capture The Flag](https://www.webopedia.com/definitions/ctf-event/amp/) com competições e descrições de soluções._ +- **[Awesome BlockSec CTF](https://github.com/blockthreat/blocksec-ctfs)** - _Lista com curadoria de wargames de segurança de blockchain, desafios e competições de [Capture The Flag](https://www.webopedia.com/definitions/ctf-event/amp/) e artigos de soluções._ -- **[Maldito DeFi Vulnerável](https://www.damnvulnerabledefi.xyz/)** - _Jogo de guerra para aprender a segurança ofensiva de contratos inteligentes DeFi e desenvolver habilidades em caça a bugs e auditoria de segurança._ +- **[Damn Vulnerable DeFi](https://www.damnvulnerabledefi.xyz/)** - _Wargame para aprender segurança ofensiva de contratos inteligentes de DeFi e desenvolver habilidades em caça a bugs e auditoria de segurança._ -- **[Ethernaut](https://ethernaut.openzeppelin.com/)** - _Jogo de guerra baseado em Web3/Solidity onde cada nível é um contrato inteligente que precisa ser 'hackeado'._ +- **[Ethernaut](https://ethernaut.openzeppelin.com/)** - _Wargame baseado em Web3/Solidity onde cada nível é um contrato inteligente que precisa ser 'hackeado'._ - **[HackenProof x HackTheBox](https://app.hackthebox.com/tracks/HackenProof-Track)** - _Desafio de hacking de contrato inteligente, ambientado em uma aventura de fantasia. A conclusão bem-sucedida do desafio também dá acesso a um programa privado de recompensa por bugs._ ### Melhores práticas para proteger contratos inteligentes {#smart-contract-security-best-practices} -- **[ConsenSys: Melhores Práticas de Segurança em Contratos Inteligentes Ethereum](https://consensys.github.io/smart-contract-best-practices/)** - _Lista abrangente de diretrizes para proteger contratos inteligentes Ethereum._ +- **[ConsenSys: melhores práticas de segurança de contratos inteligentes Ethereum](https://consensys.github.io/smart-contract-best-practices/)** - _Lista abrangente de diretrizes para proteger contratos inteligentes Ethereum._ -- **[Nascent: Kit de Ferramentas de Segurança Simples](https://github.com/nascentxyz/simple-security-toolkit)** - _Coleção de guias práticos com foco em segurança e listas de verificação para o desenvolvimento de contratos inteligentes._ +- **[Nascent: Simple Security Toolkit](https://github.com/nascentxyz/simple-security-toolkit)** - _Coleção de guias práticos focados em segurança e listas de verificação para o desenvolvimento de contratos inteligentes._ -- **[Padrões Solidity](https://fravoll.github.io/solidity-patterns/)** - *Compilação útil de padrões segurança e melhores práticas para contratos inteligentes da linguagem de programação Solidity.* +- **[Padrões do Solidity](https://fravoll.github.io/solidity-patterns/)** - _Compilação útil de padrões seguros e melhores práticas para a linguagem de programação de contratos inteligentes Solidity._ -- **[Documentação Solidity: Considerações de Segurança](https://docs.soliditylang.org/en/v0.8.16/security-considerations.html)** - _Diretrizes para programar contratos inteligentes seguros com Solidity._ +- **[Documentação do Solidity: Considerações de segurança](https://docs.soliditylang.org/en/v0.8.16/security-considerations.html)** - _Diretrizes para escrever contratos inteligentes seguros com Solidity._ -- **[Padrão de Verificação de Segurança de Contrato Inteligente](https://github.com/securing/SCSVS)** - _Lista de verificação de quatorze partes criadas para padronizar a segurança de contratos inteligentes para desenvolvedores, arquitetos, revisores de segurança e fornecedores._ +- **[Padrão de Verificação de Segurança de Contratos Inteligentes](https://github.com/securing/SCSVS)** - _Lista de verificação de quatorze partes criada para padronizar a segurança de contratos inteligentes para desenvolvedores, arquitetos, revisores de segurança e fornecedores._ -- **[Aprenda sobre segurança e auditoria de contratos inteligentes](https://updraft.cyfrin.io/courses/security)** — _Curso definitivo de segurança e auditoria de contratos inteligentes, criado para desenvolvedores de contratos inteligentes que desejam melhorar suas práticas recomendadas de segurança e se tornar pesquisadores de segurança._ +- **[Aprenda sobre segurança e auditoria de contratos inteligentes](https://updraft.cyfrin.io/courses/security)** - _Curso definitivo de segurança e auditoria de contratos inteligentes, criado para desenvolvedores de contratos inteligentes que desejam aprimorar suas melhores práticas de segurança e se tornar pesquisadores de segurança._ ### Tutoriais sobre segurança de contratos inteligentes {#tutorials-on-smart-contract-security} -- [Como programar contratos inteligentes seguros](/developers/tutorials/secure-development-workflow/) +- [Como escrever contratos inteligentes seguros](/developers/tutorials/secure-development-workflow/) -- [Como utilizar o Slither para encontrar bugs nos contratos inteligentes](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/) +- [Como usar o Slither para encontrar bugs em contratos inteligentes](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/) - [Como usar o Manticore para encontrar bugs em contratos inteligentes](/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/) -- [Diretrizes de segurança do contrato inteligente](/developers/tutorials/smart-contract-security-guidelines/) +- [Diretrizes de segurança para contratos inteligentes](/developers/tutorials/smart-contract-security-guidelines/) - [Como integrar com segurança seu contrato de token com tokens arbitrários](/developers/tutorials/token-integration-checklist/) diff --git a/public/content/translations/pt-br/developers/docs/smart-contracts/testing/index.md b/public/content/translations/pt-br/developers/docs/smart-contracts/testing/index.md index fa409657f8b..5256b287f01 100644 --- a/public/content/translations/pt-br/developers/docs/smart-contracts/testing/index.md +++ b/public/content/translations/pt-br/developers/docs/smart-contracts/testing/index.md @@ -1,38 +1,38 @@ --- title: Testes de contratos inteligentes -description: Uma visão geral das técnicas e considerações para testar contratos inteligentes Ethereum. +description: "Uma visão geral das técnicas e considerações para testar contratos inteligentes Ethereum." lang: pt-br --- -Blockchains públicas como Ethereum são imutáveis, dificultando alterações de código de contratos inteligentes após sua implementação. Existem [padrões de atualização de contrato](/developers/docs/smart-contracts/upgrading/) para realizar "atualizações virtuais", mas são difíceis de implementar e requer um consenso social. Além disso, uma atualização só pode corrigir um erro _após_ que é descoberto se um invasor descobrir a vulnerabilidade primeiro, seu contrato inteligente corre o risco sofrer um exploit. +Blockchains públicas como Ethereum são imutáveis, dificultando alterações de código de contratos inteligentes após sua implementação. Existem [padrões de atualização de contrato](/developers/docs/smart-contracts/upgrading/) para realizar "atualizações virtuais", mas são difíceis de implementar e exigem consenso social. Além disso, uma atualização só pode corrigir um erro _após_ sua descoberta — se um invasor descobrir a vulnerabilidade primeiro, seu contrato inteligente corre o risco de um exploit. -Por estas razões, testar contratos inteligentes antes de [implementar](/developers/docs/smart-contracts/deploying/) à rede principal é o requisito mínimo para [segurança](/developers/docs/smart-contracts/security/). Existem muitas técnicas para testar contratos e avaliar a corretude de código; qual escolher depende de suas necessidades. No entanto, um conjunto de testes feito a partir de diferentes ferramentas e abordagens é ideal para pegar pequenas e grandes falhas de segurança no código do contrato. +Por esses motivos, testar contratos inteligentes antes de [implantá-los](/developers/docs/smart-contracts/deploying/) na Mainnet é um requisito mínimo para a [segurança](/developers/docs/smart-contracts/security/). Existem muitas técnicas para testar contratos e avaliar a corretude de código; qual escolher depende de suas necessidades. No entanto, um conjunto de testes feito a partir de diferentes ferramentas e abordagens é ideal para pegar pequenas e grandes falhas de segurança no código do contrato. ## Pré-requisitos {#prerequisites} Esta página explica como testar contratos inteligentes antes de implantar na rede Ethereum. Pressupõe-se que você esteja familiarizado com [contratos inteligentes](/developers/docs/smart-contracts/). -## O que é teste de contrato inteligente? {#what-is-smart-contract-testing} +## O que é teste de contrato inteligente? O que é o teste de contrato inteligente? {#what-is-smart-contract-testing} O teste de contrato inteligente é o processo de verificação de que o código de um contrato inteligente funciona conforme o esperado. Testar é útil para verificar se um contrato inteligente específico atende aos requisitos de confiabilidade, usabilidade e segurança. Embora as abordagens variem, a maioria dos métodos de teste exige a execução de um contrato inteligente com uma pequena amostra dos dados que se espera manipular. Se o contrato produzir resultados corretos para dados da amostra, presume-se que esteja funcionando corretamente. A maioria das ferramentas de teste fornece recursos para escrever e executar [casos de teste](https://en.m.wikipedia.org/wiki/Test_case) para verificar se a execução de um contrato corresponde aos resultados esperados. -### Por que é importante testar contratos inteligentes? {#importance-of-testing-smart-contracts} +### Por que é importante testar contratos inteligentes? Importância de testar contratos inteligentes {#importance-of-testing-smart-contracts} -Como os contratos inteligentes geralmente gerenciam ativos financeiros de alto valor, pequenos erros de programação podem e geralmente levam a [perdas massivas para os usuários](https://rekt.news/leaderboard/). Testes rigorosos podem, no entanto, ajudar a descobrir de maneira antecipada erros e problemas no código de um contrato inteligente e corrigi-los antes do lançamento na rede principal. +Como os contratos inteligentes geralmente gerenciam ativos financeiros de alto valor, pequenos erros de programação podem levar, e frequentemente levam, a [perdas massivas para os usuários](https://rekt.news/leaderboard/). Testes rigorosos podem, no entanto, ajudar a descobrir de maneira antecipada erros e problemas no código de um contrato inteligente e corrigi-los antes do lançamento na rede principal. -Embora seja possível atualizar um contrato se um bug for descoberto, as atualizações são complexas e podem [ resultar em erros](https://blog.trailofbits.com/2018/09/05/contract-upgrade-anti-patterns/) se tratadas de forma inadequada. A atualização de um contrato vai contra o princípio da imutabilidade e sobrecarrega os usuários com suposições de confiança adicionais. Por outro lado, um plano abrangente para testar seu contrato reduz os riscos de segurança do contrato inteligente e reduz a necessidade de realizar atualizações lógicas complexas após a implantação. +Embora seja possível atualizar um contrato se um bug for descoberto, as atualizações são complexas e podem [resultar em erros](https://blog.trailofbits.com/2018/09/05/contract-upgrade-anti-patterns/) se tratadas de forma inadequada. A atualização de um contrato vai contra o princípio da imutabilidade e sobrecarrega os usuários com suposições de confiança adicionais. Por outro lado, um plano abrangente para testar seu contrato reduz os riscos de segurança do contrato inteligente e reduz a necessidade de realizar atualizações lógicas complexas após a implantação. ## Métodos para testar contratos inteligentes {#methods-for-testing-smart-contracts} -Os métodos para testar contratos inteligentes no Ethereum se dividem em duas categorias amplas: **teste automatizado** e **teste manual**. Testes automatizados e testes manuais tem seus prós e contras, mas você pode combinar ambos para criar um plano robusto para analisar seus contratos. +Os métodos para testar contratos inteligentes do Ethereum se dividem em duas grandes categorias: **testes automatizados** e **testes manuais**. Testes automatizados e testes manuais tem seus prós e contras, mas você pode combinar ambos para criar um plano robusto para analisar seus contratos. ### Teste automatizado {#automated-testing} O teste automatizado usa ferramentas que verificam automaticamente um código de contratos inteligentes em busca de erros na execução. O benefício do teste automatizado vem do uso de [scripts](https://www.techtarget.com/whatis/definition/script?amp=1) para orientar a avaliação das funcionalidades do contrato. Os scripts de testes podem ser programados para serem executados repetidamente com o mínimo de intervenção humana, tornando o teste automatizado mais eficiente do que as abordagens manuais de teste. -O teste automatizado é particularmente útil quando os testes são repetitivos e demorados; difícil de realizar manualmente; suscetíveis a erro humano; ou envolvem a avaliação de funções contratuais críticas. Mas as ferramentas de teste automatizadas podem ter desvantagens - elas podem perder certos bugs e produzir muitos [falsos positivos](https://www.contrastsecurity.com/glossary/false-positive). Portanto, combinar testes automatizados com testes manuais para contratos inteligentes é ideal. +O teste automatizado é particularmente útil quando os testes são repetitivos e demorados; difícil de realizar manualmente; suscetíveis a erro humano; ou envolvem a avaliação de funções contratuais críticas. Mas as ferramentas de teste automatizadas podem ter desvantagens: elas podem não detectar certos bugs e produzir muitos [falsos positivos](https://www.contrastsecurity.com/glossary/false-positive). Portanto, combinar testes automatizados com testes manuais para contratos inteligentes é ideal. ### Teste manual {#manual-testing} @@ -44,19 +44,19 @@ Um teste manual eficaz requer recursos consideráveis ​​(habilidade, tempo, ## Teste automatizado para contratos inteligentes {#automated-testing-for-smart-contracts} -### Teste unitário {#unit-testing-for-smart-contracts} +### Teste de unidade {#unit-testing-for-smart-contracts} O teste unitário avalia as funções do contrato separadamente e verifica se cada componente funciona corretamente. Testes unitários bons devem ser simples, rápidos de executar e fornecer uma ideia clara do que deu errado se os testes falharem. Os testes unitários são úteis para verificar se as funções retornam os valores esperados e se o armazenamento do contrato é atualizado corretamente após a execução da função. Além disso, a execução de testes unitários após fazer alterações em uma base de código de contratos garante que a adição de nova lógica não introduza erros. Abaixo estão algumas diretrizes para executar testes unitários eficazes: -#### Diretrizes para testes unitários de contratos inteligentes {#unit-testing-guidelines} +#### Diretrizes para testes de unidade de contratos inteligentes {#unit-testing-guidelines} ##### 1. Entenda a lógica de negócios e o fluxo de trabalho de seus contratos -Antes de escrever testes unitários, é bom saber quais funcionalidades um contrato inteligente oferece e como os usuários acessarão e usarão essas funções. Isso é particularmente útil para executar [testes de caminho feliz](https://en.m.wikipedia.org/wiki/Happy_path) que determinam se as funções em um contrato retornam a saída correta para entradas válidas do usuário. Explicaremos esse conceito usando este exemplo (resumido) de [um contrato de leilão](https://docs.soliditylang.org/en/v0.8.17/solidity-by-example.html?highlight=Auction%20contract#simple-open-auction) +Antes de escrever testes unitários, é bom saber quais funcionalidades um contrato inteligente oferece e como os usuários acessarão e usarão essas funções. Isso é particularmente útil para executar [testes de caminho feliz](https://en.m.wikipedia.org/wiki/Happy_path) que determinam se as funções em um contrato retornam o resultado correto para entradas de usuário válidas. Explicaremos esse conceito usando este exemplo (resumido) de [um contrato de leilão](https://docs.soliditylang.org/en/v0.8.17/solidity-by-example.html?highlight=Auction%20contract#simple-open-auction) -``` +```solidity constructor( uint biddingTime, address payable beneficiaryAddress @@ -108,11 +108,11 @@ function auctionEnd() external { } ``` -Este é um contrato de leilão simples projetado para receber lances durante o período de submissão de ofertas. Se a variável `highestBid` aumentar, o licitante anterior mais alto receberá seu dinheiro; uma vez terminado o período de licitação, o objeto `beneficiary` aciona o contrato para obter seu dinheiro. +Este é um contrato de leilão simples projetado para receber lances durante o período de submissão de ofertas. Se o `highestBid` aumentar, o licitante com o lance mais alto anterior recebe seu dinheiro de volta; quando o período de lances terminar, o `beneficiary` chama o contrato para receber seu dinheiro. -Testes unitários para um contrato como este cobriria diferentes funções que um usuário poderia chamar quando interagindo com o contrato. Um exemplo seria um teste unitário que verifica se um usuário pode fazer uma oferta enquanto o leilão está em andamento (ou seja, que as chamadas para `bid()` são bem-sucedidas) ou um que verifica se um usuário pode fazer uma oferta maior do que a atual `highestBid`. +Testes unitários para um contrato como este cobriria diferentes funções que um usuário poderia chamar quando interagindo com o contrato. Um exemplo seria um teste de unidade que verifica se um usuário pode fazer um lance enquanto o leilão está em andamento (ou seja, as chamadas para `bid()` são bem-sucedidas) ou um que verifica se um usuário pode fazer um lance maior que o `highestBid` atual. -Entendendo o fluxo operacional do contrato também ajuda a escrever testes unitários que checam se a execução atende os requisitos. Por exemplo, o contrato de leilão especifica que os usuários não podem colocar ordens quando o leilão terminou (ou seja, quando `auctionEndTime` é menor que `block.timestamp`). Portanto, o desenvolvedor deve rodar um teste unitário que checa se chamadas para a função `bid()` tiveram sucesso ou falharam quando o leilão terminou (ou seja, quando `auctionEndTime` > `block.timestamp`). +Entendendo o fluxo operacional do contrato também ajuda a escrever testes unitários que checam se a execução atende os requisitos. Por exemplo, o contrato de leilão especifica que os usuários não podem fazer lances quando o leilão termina (ou seja, quando `auctionEndTime` é menor que `block.timestamp`). Assim, um desenvolvedor pode executar um teste de unidade que verifica se as chamadas para a função `bid()` são bem-sucedidas ou falham quando o leilão termina (ou seja, quando `auctionEndTime` > `block.timestamp`). ##### 2. Avalie todas as suposições relacionadas à execução do contrato @@ -126,11 +126,11 @@ Muitos frameworks de teste unitário permitem você criar afirmações - simples - Usuários que falham em vencer o leilão são creditados com seus fundos -**Nota**: Uma outra maneira de testar suposições é escrever testes que disparam [modificadores de função](https://docs.soliditylang.org/en/v0.8.16/contracts.html#function-modifiers) em um contrato, especialmente declarações`require`, `assert`, e `if…else`. +**Observação**: outra maneira de testar suposições é escrever testes que acionem [modificadores de função](https://docs.soliditylang.org/en/v0.8.16/contracts.html#function-modifiers) em um contrato, especialmente as instruções `require`, `assert` e `if…else`. ##### 3. Medida de cobertura do código -[Cobertura de código](https://en.m.wikipedia.org/wiki/Code_coverage) é uma métrica de teste que rastreia o número de ramificações, linhas e comandos no seu código executados durante os testes. Os testes devem contar com uma boa cobertura de código para minimizar o risco de vulnerabilidades não testadas. Sem cobertura suficiente, você pode presumir erroneamente que seu contrato é seguro porque todos os testes foram aprovados, embora ainda existam vulnerabilidades em caminhos de código não testados. Obtendo alta cobertura de código, entretanto, dá a segurança que todos os comandos/funções em um contrato inteligente foram suficientemente testados por exatidão. +A [cobertura de código](https://en.m.wikipedia.org/wiki/Code_coverage) é uma métrica de teste que rastreia o número de ramificações, linhas e instruções em seu código executadas durante os testes. Os testes devem contar com uma boa cobertura de código para minimizar o risco de vulnerabilidades não testadas. Sem cobertura suficiente, você pode presumir erroneamente que seu contrato é seguro porque todos os testes foram aprovados, embora ainda existam vulnerabilidades em caminhos de código não testados. Obtendo alta cobertura de código, entretanto, dá a segurança que todos os comandos/funções em um contrato inteligente foram suficientemente testados por exatidão. ##### 4. Use frameworks de teste bem desenvolvidos @@ -138,19 +138,19 @@ A qualidade das ferramentas usada para rodar testes unitários para o seu contra Frameworks de teste unitário para contratos inteligentes em Solidity vêm em diferentes linguagens (geralmente JavaScript, Python e Rust). Veja alguns dos guias abaixo para informações sobre como começar a rodar testes unitários com diferentes frameworks de teste: -- **[Rodando testes unitários com Brownie](https://eth-brownie.readthedocs.io/en/v1.0.0_a/tests.html)** -- **[Rodando testes unitários com Foundry](https://book.getfoundry.sh/forge/writing-tests)** -- **[Rodando testes unitários com Waffle](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)** -- **[Rodando testes unitários com Remix](https://remix-ide.readthedocs.io/en/latest/unittesting.html#write-tests)** -- **[Rodando testes unitários com Ape](https://docs.apeworx.io/ape/stable/userguides/testing.html)** -- **[Rodando testes unitários com Hardhat](https://hardhat.org/hardhat-runner/docs/guides/test-contracts)** -- **[Como executar testes unitários com Wake](https://ackeeblockchain.com/wake/docs/latest/testing-framework/overview/)** +- **[Executando testes de unidade com o Brownie](https://eth-brownie.readthedocs.io/en/v1.0.0_a/tests.html)** +- **[Executando testes de unidade com o Foundry](https://book.getfoundry.sh/forge/writing-tests)** +- **[Executando testes de unidade com o Waffle](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)** +- **[Executando testes de unidade com o Remix](https://remix-ide.readthedocs.io/en/latest/unittesting.html#write-tests)** +- **[Executando testes de unidade com Ape](https://docs.apeworx.io/ape/stable/userguides/testing.html)** +- **[Executando testes de unidade com o Hardhat](https://hardhat.org/hardhat-runner/docs/guides/test-contracts)** +- **[Executando testes de unidade com Wake](https://ackeeblockchain.com/wake/docs/latest/testing-framework/overview/)** -### Teste de Integração {#integration-testing-for-smart-contracts} +### Teste de integração {#integration-testing-for-smart-contracts} -Enquanto o teste unitário depura funções de contrato isoladamente, testes integrados avaliam os componentes de um contrato inteligente como um todo. Teste de integração pode detectar defeitos vindos de chamadas entre contratos ou interações entre diferentes funções no mesmo contrato inteligente. Por exemplo, testes de integração podem ajudar a checar se coisas como [herança](https://docs.soliditylang.org/en/v0.8.12/contracts.html#inheritance) e injeção de dependência funcionam devidamente. +Enquanto o teste unitário depura funções de contrato isoladamente, testes integrados avaliam os componentes de um contrato inteligente como um todo. Teste de integração pode detectar defeitos vindos de chamadas entre contratos ou interações entre diferentes funções no mesmo contrato inteligente. Por exemplo, os testes de integração podem ajudar a verificar se itens como [herança](https://docs.soliditylang.org/en/v0.8.12/contracts.html#inheritance) e injeção de dependência funcionam corretamente. -Os testes de integração são úteis se o seu contrato adota uma arquitetura modular ou interfaces com outros contratos on-chain durante a execução. Uma maneira de executar testes de integração é [fazer um fork da blockchain](/glossary/#fork) a uma altura específica (usando uma ferramenta como [Forge](https://book.getfoundry.sh/forge/fork-testing) ou [Hardhat](https://hardhat.org/hardhat-network/docs/guides/forking-other-networks) e simular interações entre seu contrato e contratos implantados. +Os testes de integração são úteis se o seu contrato adota uma arquitetura modular ou interfaces com outros contratos on-chain durante a execução. Uma maneira de executar testes de integração é [bifurcar a cadeia de blocos](/glossary/#fork) em uma altura específica (usando uma ferramenta como [Forge](https://book.getfoundry.sh/forge/fork-testing) ou [Hardhat](https://hardhat.org/hardhat-network/docs/guides/forking-other-networks)) e simular interações entre seu contrato e contratos implantados. O blockchain que sofreu fork irá se comportar similarmente à Mainnet e ter contas com estados e saldos associados. Mas ele age somente como um ambiente de área local de desenvolvimento restrita, significando que você não precisará de ETH real para transações, por exemplo, nem suas modificações irão afetar o protocolo Ethereum real. @@ -158,151 +158,153 @@ O blockchain que sofreu fork irá se comportar similarmente à Mainnet e ter con Teste baseado em propriedade é o processo de checar que um contrato inteligente satisfaz algumas propriedades definidas. Propriedades afirmam fatos sobre o comportamento de um contrato esperado continuar verdadeiro em diferentes cenários - um exemplo de propriedade de contrato inteligente poderia ser "Operações aritméticas no contrato nunca sofrem overflow ou underflow." -**Análise estática** e **análise dinâmica** são duas técnicas comuns de execução de teste baseado em propriedade, e ambas podem verificar que o código para um programa (um contrato inteligente no caso) satisfaz algumas propriedades pré-definidas. Algumas ferramentas de teste baseadas em propriedade vem com regras pré-definidas sobre propriedades esperadas de contratos e checam o código contra estas regras, enquanto outras permitem você criar propriedades customizadas para um contrato inteligente. +**Análise estática** e **análise dinâmica** são duas técnicas comuns para executar testes baseados em propriedades, e ambas podem verificar que o código de um programa (um contrato inteligente, neste caso) satisfaz alguma propriedade predefinida. Algumas ferramentas de teste baseadas em propriedade vem com regras pré-definidas sobre propriedades esperadas de contratos e checam o código contra estas regras, enquanto outras permitem você criar propriedades customizadas para um contrato inteligente. #### Análise estática {#static-analysis} Um analisador estático pega como entrada o código-fonte de um contrato inteligente e retorna resultados declarando se o contrato satisfaz a propriedade ou não. Diferente da análise dinâmica, análise estática não envolve executar um contrato para analisá-lo por exatidão. Análise estática gera razões alternativas sobre todos os caminhos possíveis que um contrato inteligente poderia tomar durante a execução (ou seja, examinando a estrutura do código-fonte para determinar o que significaria para a operação do contrato em tempo de execução). -Testes [Linting](https://www.perforce.com/blog/qac/what-lint-code-and-why-linting-important) e [estático](https://www.techtarget.com/whatis/definition/static-analysis-static-code-analysis) são métodos comuns de rodar análise estática em contratos. Ambos requerem analisar representações de baixo nível da execução de um contrato, como [árvores de sintaxe abstrata](https://en.m.wikipedia.org/wiki/Abstract_syntax_tree) e [gráficos de controle de fluxo](https://www.geeksforgeeks.org/software-engineering-control-flow-graph-cfg/amp/) retornados pelo compilador. +[Linting](https://www.perforce.com/blog/qac/what-is-linting) e [testes estáticos](https://www.techtarget.com/whatis/definition/static-analysis-static-code-analysis) são métodos comuns para executar análises estáticas em contratos. Ambos exigem a análise de representações de baixo nível da execução de um contrato, como [árvores de sintaxe abstrata](https://en.m.wikipedia.org/wiki/Abstract_syntax_tree) e [gráficos de fluxo de controle](https://www.geeksforgeeks.org/software-engineering-control-flow-graph-cfg/amp/) gerados pelo compilador. Na maioria dos casos, análise estática é útil para detectar problemas de segurança como uso de construtores inseguros, erros de sintaxe, ou violações de padrões de código no código de contratos. Entretanto, analisadores estáticos são conhecidos por geralmente serem instáveis em detectar vulnerabilidades mais profundas, e podem produzir excessivos falsos positivos. #### Análise dinâmica {#dynamic-analysis} -Análise dinâmica gera entradas simbólicas (por exemplo, em [execução simbólica](https://en.m.wikipedia.org/wiki/Symbolic_execution)) ou entradas concretas (por exemplo, em [fuzzing](https://owasp.org/www-community/Fuzzing)) para funções de contratos inteligentes para ver se qualquer trace de execução violou propriedades específicas. Esta forma de teste baseado em propriedades difere dos testes unitários no tocante a casos de teste cobrem múltiplos cenários e um programa manipula a geração de casos de teste. +A análise dinâmica gera entradas simbólicas (por exemplo, em [execução simbólica](https://en.m.wikipedia.org/wiki/Symbolic_execution)) ou entradas concretas (por exemplo, em [fuzzing](https://owasp.org/www-community/Fuzzing)) para as funções de um contrato inteligente para ver se algum traço de execução viola propriedades específicas. Esta forma de teste baseado em propriedades difere dos testes unitários no tocante a casos de teste cobrem múltiplos cenários e um programa manipula a geração de casos de teste. -[Fuzzing](https://halborn.com/what-is-fuzz-testing-fuzzing/) é um exemplo de análise técnica dinâmica para verificar propriedades arbitrárias em contratos inteligentes. Um fuzzer invoca funções em um contrato alvo com variações randômicas ou mal formadas de um valor de entrada definido. Se um contrato inteligente entra em estado de erro (por exemplo, uma afirmação 'where' falha), o problema é indicado e as entradas que geraram esta execução para o caminho da vulnerabilidade são produzidas em um relatório. +[Fuzzing](https://www.halborn.com/blog/post/what-is-fuzz-testing-fuzzing) é um exemplo de uma técnica de análise dinâmica para verificar propriedades arbitrárias em contratos inteligentes. Um fuzzer invoca funções em um contrato alvo com variações randômicas ou mal formadas de um valor de entrada definido. Se um contrato inteligente entra em estado de erro (por exemplo, uma afirmação 'where' falha), o problema é indicado e as entradas que geraram esta execução para o caminho da vulnerabilidade são produzidas em um relatório. Fuzzing é útil para avaliação de um mecanismo de validação de entrada de contratos inteligentes, já que manipulação imprópria de entradas inesperadas pode resultar em execução não pretendida e produzir efeitos perigosos. Esta forma de teste baseado em propriedade pode ser ideal por muitas razões: -1. **Escrever casos de teste para cobrir muitos cenários é difícil.** Um teste de propriedade somente requer que você defina o comportamento e faixa de dados com a qual testar o comportamento - o programa automaticamente gera casos de teste baseados na propriedade definida. +1. **Escrever casos de teste para cobrir muitos cenários é difícil.** Um teste de propriedade exige apenas que você defina um comportamento e um intervalo de dados para testar o comportamento — o programa gera automaticamente casos de teste com base na propriedade definida. -2. **Sua suíte de testes pode não cobrir suficientemente todos os caminhos possíveis dentro do programa. ** Até com 100% de cobertura, é possível perder alguns casos limítrofes. +2. **Seu conjunto de testes pode não cobrir suficientemente todos os caminhos possíveis dentro do programa.** Mesmo com 100% de cobertura, é possível deixar passar casos extremos. -3. **Testes unitários provam que um contrato executa corretamente para dados de amostra, mas se o contrato executa corretamente para entradas fora das amostras, permanece desconhecido.** Testes de propriedade executam um contrato alvo com múltiplas variações de uma dado valor de entrada para encontrar traços de execução que causaram falhas de afirmação. Por isso, um teste proprietário fornece mais garantias que um contrato execute corretamente para uma larga classe de dados de entrada. +3. **Testes de unidade provam que um contrato é executado corretamente para dados de amostra, mas se o contrato é executado corretamente para entradas fora da amostra permanece desconhecido.** Os testes de propriedade executam um contrato de destino com várias variações de um determinado valor de entrada para encontrar traços de execução que causam falhas de asserção. Por isso, um teste proprietário fornece mais garantias que um contrato execute corretamente para uma larga classe de dados de entrada. -### Orientações para rodar teste baseado em propriedade para contratos inteligentes {#running-property-based-tests} +### Diretrizes para executar testes baseados em propriedade para contratos inteligentes {#running-property-based-tests} -Executar testes baseados em propriedade geralmente começa com a definição da propriedade (por exemplo, ausência de [overflows de inteiro](https://github.com/ConsenSys/mythril/wiki/Integer-Overflow)) ou com coleções de propriedades que você quer verificar em um contrato inteligente. Você pode também precisar definir uma faixa de valores dentro da qual o programa pode gerar dados para entradas de transação quando escrevendo os testes de propriedade. +A execução de testes baseados em propriedade geralmente começa com a definição de uma propriedade (por exemplo, ausência de [estouros de inteiros](https://github.com/ConsenSys/mythril/wiki/Integer-Overflow)) ou uma coleção de propriedades que você deseja verificar em um contrato inteligente. Você pode também precisar definir uma faixa de valores dentro da qual o programa pode gerar dados para entradas de transação quando escrevendo os testes de propriedade. Uma vez configurado propriamente, a ferramenta de teste de propriedade irá executar as suas funções do contrato inteligente com entradas aleatoriamente geradas. Se houver quaisquer violações de afirmações, você deve receber um relatório com os dados de entrada concretos que violaram a propriedade sendo avaliada. Veja alguns dos guias abaixo para começar com testes baseados em propriedade com diferentes ferramentas: -- **[Análise estática de contratos inteligentes com Slither](https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/slither#slither)** -- **[Análise estática de contratos inteligentes com Wake](https://ackeeblockchain.com/wake/docs/latest/static-analysis/using-detectors/)** -- **[Teste baseado em propriedade com Brownie](https://eth-brownie.readthedocs.io/en/stable/tests-hypothesis-property.html)** -- **[Testando contratos com fuzzing com o Foundry](https://book.getfoundry.sh/forge/fuzz-testing)** -- **[Testando contratos com fuzzing com o Echidna](https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/echidna#echidna-tutorial)** -- **[Testando contratos com fuzzing usando Wake](https://ackeeblockchain.com/wake/docs/latest/testing-framework/fuzzing/)** +- **[Análise estática de contratos inteligentes com Slither](https://github.com/crytic/slither)** +- **[Análise estática de contratos inteligentes com o Wake](https://ackeeblockchain.com/wake/docs/latest/static-analysis/using-detectors/)** +- **[Teste baseado em propriedade com o Brownie](https://eth-brownie.readthedocs.io/en/stable/tests-hypothesis-property.html)** +- **[Fuzzing de contratos com Foundry](https://book.getfoundry.sh/forge/fuzz-testing)** +- **[Fuzzing de contratos com Echidna](https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/echidna#echidna-tutorial)** +- **[Fuzzing de contratos com Wake](https://ackeeblockchain.com/wake/docs/latest/testing-framework/fuzzing/)** - **[Execução simbólica de contratos inteligentes com Manticore](https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/manticore#manticore-tutorial)** - **[Execução simbólica de contratos inteligentes com Mythril](https://mythril-classic.readthedocs.io/en/master/tutorial.html)** -## Testes manuais para contratos inteligentes {#manual-testing-for-smart-contracts} +## Teste manual para contratos inteligentes {#manual-testing-for-smart-contracts} Teste manual de contratos inteligentes frequentemente vêm mais tarde no ciclo de desenvolvimento, após rodar testes automatizados. Essa forma de teste avalia o contrato inteligente como um produto totalmente integrado para ver se ele executa conforme especificado nos requisitos técnicos. -### Testando contratos no blockchain local {#testing-on-local-blockchain} +### Testando contratos em uma cadeia de blocos local {#testing-on-local-blockchain} Enquanto testes automatizados realizados em um ambiente local de desenvolvimento podem fornecer informações úteis de depuração, você irá querer saber como seus contrato inteligente se comporta em um ambiente de produção. Entretanto, implantar na cadeia principal do Ethereum incorre em taxas de gas - sem mencionar que você ou seus usuários podem perder dinheiro real se o seu contrato inteligente ainda tem falhas. -Testar seu contrato em um blockchain local (também conhecido como uma [rede de desenvolvimento](/developers/docs/development-networks/)) é uma alternativa recomendada em relação a testar na Mainnet. Um blockchain local é uma cópia do blockchain Ethereum rodando localmente no seu computador que simula o comportamento da camada de execução do Ethereum. Como tal, você pode programar transações para interagir com um contrato sem incorrer em custo significante. +Testar seu contrato em uma cadeia de blocos local (também conhecida como uma [rede de desenvolvimento](/developers/docs/development-networks/)) é uma alternativa recomendada para testar na Mainnet. Um blockchain local é uma cópia do blockchain Ethereum rodando localmente no seu computador que simula o comportamento da camada de execução do Ethereum. Como tal, você pode programar transações para interagir com um contrato sem incorrer em custo significante. -Rodar contratos em blockchain local pode ser útil como forma de teste de integração manual. [Os contratos inteligentes são altamente combináveis](/developers/docs/smart-contracts/composability/), o que permite integrá-los com protocolos existentes — mas você ainda precisará garantir que interações on-chain complexas como essas produzam os resultados corretos. +Rodar contratos em blockchain local pode ser útil como forma de teste de integração manual. [Os contratos inteligentes são altamente combináveis](/developers/docs/smart-contracts/composability/), permitindo a integração com protocolos existentes — mas você ainda precisará garantir que interações on-chain tão complexas produzam os resultados corretos. [Mais sobre redes de desenvolvimento.](/developers/docs/development-networks/) -### Testando contratos nas redes de teste {#testing-contracts-on-testnets} +### Testando contratos em redes de teste {#testing-contracts-on-testnets} -Uma rede de teste ou testnet funciona exatamente como o Ethereum Mainnet, exceto pelo fato de usar Ether (ETH) sem valor no mundo real. Implantar seu contrato em uma [testnet](/developers/docs/networks/#ethereum-testnets) significa que qualquer um pode interagir com ele (por exemplo, via o front-end do dapp) sem colocar fundos em risco. +Uma rede de teste ou testnet funciona exatamente como o Ethereum Mainnet, exceto pelo fato de usar Ether (ETH) sem valor no mundo real. Implantar seu contrato em uma [rede de teste](/developers/docs/networks/#ethereum-testnets) significa que qualquer pessoa pode interagir com ele (por exemplo, por meio do frontend do dapp) sem colocar fundos em risco. Esta forma de teste manual é útil para avaliação do fluxo fim-a-fim da sua aplicação do ponto de vista do usuário. Aqui, testadores beta podem também realizar execuções experimentais e reportar qualquer problema com a lógica de negócios do contrato e funcionalidade geral. Implantar na testnet depois de testar no blockchain local é ideal desde que o primeiro é mais perto do comportamento da Máquina Virtual Ethereum. Portanto, é comum para muitos projetos nativos do Ethereum implantar dapps nas testnets para avaliar a operação dos contratos inteligentes em condições de vida real. -[Mais sobre redes de teste do Ethereum.](/developers/docs/development-networks/#public-beacon-testchains) +[Mais sobre as redes de teste do Ethereum.](/developers/docs/development-networks/#public-beacon-testchains) -## Testes vs. Verificação formal {#testing-vs-formal-verification} +## Teste vs. verificação formal {#testing-vs-formal-verification} -Ao passo que testar ajuda a confirmar se um contrato retorna os resultados esperados para algumas entradas de dados, isso não pode comprovar de forma conclusiva o mesmo para entradas não utilizadas durante os testes. Testar um contrato inteligente, portanto, não pode garantir "correção funcional" (o que significa que não pode mostrar que um programa se comporta conforme necessário para _todos os_ conjuntos de valores de entrada). +Ao passo que testar ajuda a confirmar se um contrato retorna os resultados esperados para algumas entradas de dados, isso não pode comprovar de forma conclusiva o mesmo para entradas não utilizadas durante os testes. Testar um contrato inteligente, portanto, não pode garantir a "exatidão funcional" (ou seja, não pode mostrar que um programa se comporta conforme o necessário para _todos_ os conjuntos de valores de entrada). Verificação formal é uma abordagem para avaliação da correção do software checando se um modelo formal do programa bate com a especificação formal. Um modelo formal é uma representação matemática abstrata de um programa, enquanto uma especificação formal define as propriedades de um programa (por exemplo, afirmações lógicas sobre a execução do programa). Pelo fato de propriedades serem escritas em termos matemáticos, é possível verificar que um modelo formal (matemático) do sistema satisfaz uma especificação usando regras lógicas de inferência. Por isso, ferramentas de verificação formal são ditas produzir 'provas matemáticas' da correção de um sistema. -Diferente de testar, verificações formais podem ser usadas para verificar se a execução de um contrato inteligente satisfaz uma especificação formal para _todas_ as execuções (por exemplo, não ter falhas) sem necessitar executá-lo com dados de amostra. Não apenas isto reduz tempo gasto em rodar dezenas de testes unitários, mas é também mais efetivo na caça por vulnerabilidades escondidas. Dito isto, técnicas de verificação formal se baseiam em um espectro dependendo da sua dificuldade de implementação e utilidade. +Diferentemente dos testes, a verificação formal pode ser usada para verificar se a execução de um contrato inteligente satisfaz uma especificação formal para _todas_ as execuções (ou seja, não tem bugs) sem a necessidade de executá-lo com dados de amostra. Não apenas isto reduz tempo gasto em rodar dezenas de testes unitários, mas é também mais efetivo na caça por vulnerabilidades escondidas. Dito isto, técnicas de verificação formal se baseiam em um espectro dependendo da sua dificuldade de implementação e utilidade. -[Saiba mais sobre verificação formal de contratos inteligentes.](/developers/docs/smart-contracts/formal-verification) +[Mais sobre verificação formal para contratos inteligentes.](/developers/docs/smart-contracts/formal-verification) -## Testes vs auditorias e recompensas por bugs {#testing-vs-audits-bug-bounties} +## Teste vs. auditorias e recompensas por bugs {#testing-vs-audits-bug-bounties} Como mencionado, testes rigorosos raramente podem garantir a ausência de bugs em um contrato; abordagens de verificação formal podem fornecer garantias mais fortes da correção, mas atualmente são difíceis de usar e incorrem em custos consideráveis. -Ainda assim, você pode aumentar a possibilidade de encontrar vulnerabilidades de contrato pegando uma revisão independente de código. [Auditorias de contratos inteligentes](https://www.immunebytes.com/blog/what-is-a-smart-contract-audit/) e [recompensas por bugs](https://medium.com/immunefi/a-defi-security-standard-the-scaling-bug-bounty-9b83dfdc1ba7) são duas maneiras de ter outros analisando os seus contratos. +Ainda assim, você pode aumentar a possibilidade de encontrar vulnerabilidades de contrato pegando uma revisão independente de código. [Auditorias de contratos inteligentes](https://www.immunebytes.com/blog/what-is-a-smart-contract-audit/) e [programas de recompensa por bugs](https://medium.com/immunefi/a-defi-security-standard-the-scaling-bug-bounty-9b83dfdc1ba7) são duas maneiras de fazer com que outras pessoas analisem seus contratos. Auditorias são realizadas por auditores experientes em encontrar casos de falhas de segurança e práticas pobres de desenvolvimento em contratos inteligentes. Uma auditoria irá geralmente incluir testes (e possivelmente verificação formal) assim como revisão manual de todo o código. -Por outro lado, um programa de recompensas por bug geralmente envolve oferta de recompensa financeira para um indivíduo (geralmente descrito como um [whitehat hackers](https://en.wikipedia.org/wiki/White_hat_(computer_security))) que descobre uma vulnerabilidade em um contrato inteligente e divulga-a para os desenvolvedores. As recompensas por bugs são semelhantes às auditorias, uma vez que envolve pedir que outras pessoas ajudem a encontrar defeitos em contratos inteligentes. +Por outro lado, um programa de recompensa por bugs geralmente envolve a oferta de uma recompensa financeira a um indivíduo (comumente descrito como [hackers whitehat](https://en.wikipedia.org/wiki/White_hat_\(computer_security\))) que descobre uma vulnerabilidade em um contrato inteligente e a divulga aos desenvolvedores. As recompensas por bugs são semelhantes às auditorias, uma vez que envolve pedir que outras pessoas ajudem a encontrar defeitos em contratos inteligentes. A maior diferença é que programas de recompensa por bug são abertos a uma maior comunidade de desenvolvedores/hackers e atraem uma vasta classe de hackers éticos e profissionais de segurança independentes com habilidades únicas e experiência. Isso pode ser uma vantagem em relação às auditorias de contratos inteligentes, que dependem principalmente de equipes que podem possuir conhecimentos especializados limitados ou estreitos. -## Testando ferramentas e bibliotecas {#testing-tools-and-libraries} +## Ferramentas e bibliotecas de teste {#testing-tools-and-libraries} -### Ferramentas de testes unitários {#unit-testing-tools} +### Ferramentas de teste de unidade {#unit-testing-tools} - **[solidity-coverage](https://github.com/sc-forks/solidity-coverage)** - _Ferramenta de cobertura de código para contratos inteligentes escritos em Solidity._ -- **[Waffle](https://ethereum-waffle.readthedocs.io/en/latest/)** - _Framework para desenvolvimento avançado de contratos inteligentes e teste (baseado no ethers.js)_. +- **[Waffle](https://ethereum-waffle.readthedocs.io/en/latest/)** - _Framework para desenvolvimento e teste avançados de contratos inteligentes (baseado em ethers.js)_. -- **[Remix Tests](https://github.com/ethereum/remix-project/tree/master/libs/remix-tests)** - _Ferramenta para testar contratos inteligentes em Solidity. Funciona abaixo do plugin Remix IDE "Solidity Unit Testing" usado para escrever e executar casos de teste para um contrato._ +- **[Testes Remix](https://github.com/ethereum/remix-project/tree/master/libs/remix-tests)** - _Ferramenta para testar contratos inteligentes em Solidity. Funciona abaixo do plugin Remix IDE "Solidity Unit Testing" usado para escrever e executar casos de teste para um contrato._ -- **[Auxiliar para Teste do OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-test-helpers)** - _Biblioteca de asserções para teste de contrato inteligente Ethereum. Certifique-se de que seus contratos se comportam como esperado!_ +- **[OpenZeppelin Test Helpers](https://github.com/OpenZeppelin/openzeppelin-test-helpers)** - _Biblioteca de asserção para testes de contratos inteligentes do Ethereum. Certifique-se de que seus contratos se comportam como esperado!_ -- **[Framework de teste de unidade do Brownie](https://eth-brownie.readthedocs.io/en/v1.0.0_a/tests.html)** - _Brownie utiliza Pytest, uma estrutura de teste rica em recursos que permite que você escreva pequenos testes com o mínimo de código, escala bem para grandes projetos e é altamente extensível._ +- **[Framework de teste de unidade do Brownie](https://eth-brownie.readthedocs.io/en/v1.0.0_a/tests.html)** - _O Brownie utiliza o Pytest, um framework de teste rico em recursos que permite escrever testes pequenos com código mínimo, é adequado para grandes projetos e é altamente extensível._ -- **[Testes Foundry](https://github.com/foundry-rs/foundry/tree/master/crates/forge)** — _Foundry oferece o Forge, uma estrutura de testes no Ethereum rápida e flexível, capaz de executar testes de unidade simples, verificações de otimização de gás e mutações (fuzzing) em contratos._ +- **[Testes Foundry](https://github.com/foundry-rs/foundry/tree/master/crates/forge)** - _Foundry oferece Forge, um framework de teste do Ethereum rápido e flexível, capaz de executar testes de unidade simples, verificações de otimização de gás e fuzzing de contratos._ -- **[Hardhat Testes](https://hardhat.org/hardhat-runner/docs/guides/test-contracts)** - _Framework para testar contratos inteligentes com base no ethers.js, Mocha e Chai._ +- **[Testes do Hardhat](https://hardhat.org/hardhat-runner/docs/guides/test-contracts)** - _Framework para testar contratos inteligentes com base em ethers.js, Mocha e Chai._ -- **[ApeWorx](https://docs.apeworx.io/ape/stable/userguides/testing.html)** - _Desenvolvimento baseado em Python e framework de teste para contratos inteligentes voltados para a Máquina Virtual Ethereum._ +- **[ApeWorx](https://docs.apeworx.io/ape/stable/userguides/testing.html)** - _Framework de desenvolvimento e teste baseado em Python para contratos inteligentes direcionados à Máquina Virtual Ethereum._ -- **[Wake](https://ackeeblockchain.com/wake/docs/latest/testing-framework/overview/)** - _Framework baseado em Python para teste unitário e fuzzing com fortes capacidades de depuração e suporte a testes cross-chain, utilizando pytest e Anvil para a melhor experiência e desempenho do usuário._ +- **[Wake](https://ackeeblockchain.com/wake/docs/latest/testing-framework/overview/)** - _Framework baseado em Python para testes de unidade e fuzzing com fortes recursos de depuração e suporte a testes entre cadeias, utilizando pytest e Anvil para a melhor experiência do usuário e desempenho._ ### Ferramentas de teste baseadas em propriedades {#property-based-testing-tools} #### Ferramentas de análise estática {#static-analysis-tools} -- **[Slither](https://github.com/crytic/slither)** - _Framework com base no Python de análise estática estabelecida no Solidity para encontrar vulnerabilidades, aprimorar a compreensão do código e escrever análises personalizadas para contratos inteligentes._ +- **[Slither](https://github.com/crytic/slither)** - _Framework de análise estática de Solidity baseado em Python para encontrar vulnerabilidades, melhorar a compreensão do código e escrever análises personalizadas para contratos inteligentes._ + +- **[Ethlint](https://ethlint.readthedocs.io/en/latest/)** - _Linter para aplicar as melhores práticas de estilo e segurança para a linguagem de programação de contrato inteligente Solidity._ -- **[Ethlint](https://ethlint.readthedocs.io/en/latest/)** - _Analisador (linter) para garantir as práticas recomendadas de estilo e segurança para a linguagem de programação de contrato inteligente Solidity._ +- **[Cyfrin Aderyn](https://cyfrin.io/tools/aderyn)** - _Analisador estático baseado em Rust, projetado especificamente para a segurança e o desenvolvimento de contratos inteligentes da Web3._ -- **[Cyfrin Aderyn](https://cyfrin.io/tools/aderyn)** - _Analisador estático baseado em Rust especificamente projetado para a segurança e o desenvolvimento de contratos inteligentes Web3._ +- **[Wake](https://ackeeblockchain.com/wake/docs/latest/static-analysis/using-detectors/)** - _Framework de análise estática baseado em Python com detectores de vulnerabilidade e qualidade de código, impressores para extrair informações úteis do código e suporte para escrever submódulos personalizados._ -- **[Wake](https://ackeeblockchain.com/wake/docs/latest/static-analysis/using-detectors/)** - _Framework de análise estática baseado em Python com detectores de vulnerabilidades e qualidade de código, impressoras para extrair informações úteis do código e suporte para a criação de submódulos personalizados._ +- **[Slippy](https://github.com/fvictorio/slippy)** - _Um linter simples e poderoso para Solidity._ #### Ferramentas de análise dinâmica {#dynamic-analysis-tools} -- **[Echidna](https://github.com/crytic/echidna/)** - _Fuzzer (analisador) de contrato para detectar vulnerabilidades em contratos inteligentes por meio de testes baseados em propriedade._ +- **[Echidna](https://github.com/crytic/echidna/)** - _Fuzzer de contrato rápido para detectar vulnerabilidades em contratos inteligentes por meio de testes baseados em propriedades._ -- **[Diligence Fuzzing](https://consensys.net/diligence/fuzzing/)** - _ Ferramenta de análise automatizada útil para detectar violações de propriedade no código de contrato inteligente._ +- **[Diligence Fuzzing](https://consensys.net/diligence/fuzzing/)** - _Ferramenta de fuzzing automatizada útil para detectar violações de propriedade no código de contrato inteligente._ -- **[Manticore](https://manticore.readthedocs.io/en/latest/index.html)** - _Framework de execução simbólica dinâmica para análise de bytecode na EVM._ +- **[Manticore](https://manticore.readthedocs.io/en/latest/index.html)** - _Framework de execução simbólica dinâmica para analisar bytecode da EVM._ -- **[Mithril](https://github.com/ConsenSys/mythril-classic)** - _ Ferramenta para diagnóstico de bytecode na EVM para detectar vulnerabilidades de contrato usando análise de contaminação, análise simbólica e verificação de fluxo de controle._ +- **[Mythril](https://github.com/ConsenSys/mythril-classic)** - _Ferramenta de avaliação de bytecode da EVM para detectar vulnerabilidades de contratos usando análise de propagação de dados (taint analysis), análise concolica e verificação de fluxo de controle._ -- **[Diligence Scribble](https://consensys.net/diligence/scribble/)** - _ Scribble é uma linguagem de especificação e ferramenta de verificação do tempo de execução, que possibilita anotar contratos inteligentes com propriedades, o que permite testar automaticamente os contratos com ferramentas como Diligence Fuzzing ou MythX._ +- **[Diligence Scribble](https://consensys.net/diligence/scribble/)** - _Scribble é uma linguagem de especificação e uma ferramenta de verificação em tempo de execução que permite anotar contratos inteligentes com propriedades que permitem testar automaticamente os contratos com ferramentas como Diligence Fuzzing ou MythX._ ## Tutoriais relacionados {#related-tutorials} - [Uma visão geral e comparação de diferentes produtos de teste](/developers/tutorials/guide-to-smart-contract-security-tools/) \_ - [Como usar o Echidna para testar contratos inteligentes](/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/) - [Como usar o Manticore para encontrar bugs em contratos inteligentes](/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/) -- [Como utilizar o Slither para encontrar bugs nos contratos inteligentes](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/) +- [Como usar o Slither para encontrar bugs em contratos inteligentes](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/) - [Como simular contratos Solidity para teste](/developers/tutorials/how-to-mock-solidity-contracts-for-testing/) -- [Como executar testes unitários em Solidity usando Foundry](https://www.rareskills.io/post/foundry-testing-solidity) +- [Como executar testes de unidade em Solidity usando Foundry](https://www.rareskills.io/post/foundry-testing-solidity) ## Leitura adicional {#further-reading} - [Um guia detalhado para testar contratos inteligentes do Ethereum](https://iamdefinitelyahuman.medium.com/an-in-depth-guide-to-testing-ethereum-smart-contracts-2e41b2770297) - [Como testar contratos inteligentes do Ethereum](https://betterprogramming.pub/how-to-test-ethereum-smart-contracts-35abc8fa199d) - [Guia de teste de unidade do MolochDAO para desenvolvedores](https://github.com/MolochVentures/moloch/tree/4e786db8a4aa3158287e0935dcbc7b1e43416e38/test#moloch-testing-guide) -- [Como testar contratos inteligentes como um astro do rock](https://forum.openzeppelin.com/t/test-smart-contracts-like-a-rockstar/1001) +- [Como testar contratos inteligentes como um rockstar](https://forum.openzeppelin.com/t/test-smart-contracts-like-a-rockstar/1001) diff --git a/public/content/translations/pt-br/developers/docs/smart-contracts/upgrading/index.md b/public/content/translations/pt-br/developers/docs/smart-contracts/upgrading/index.md index 0ea6b7aca97..db42daeb81e 100644 --- a/public/content/translations/pt-br/developers/docs/smart-contracts/upgrading/index.md +++ b/public/content/translations/pt-br/developers/docs/smart-contracts/upgrading/index.md @@ -1,6 +1,6 @@ --- title: Atualizando contratos inteligentes -description: Uma visão geral dos padrões de atualização de contratos inteligentes no Ethereum +description: "Uma visão geral dos padrões de atualização de contratos inteligentes no Ethereum" lang: pt-br --- @@ -12,7 +12,7 @@ Entretanto, mais pesquisas sobre melhoria de contratos inteligentes tem levado ## Pré-requisitos {#prerequisites} -Você deve ter um bom entendimento de [contratos inteligentes](/developers/docs/smart-contracts/), [anatomia de contratos inteligentes](/developers/docs/smart-contracts/anatomy/), e a [Máquina Virtual Ethereum (EVM)](/developers/docs/evm/). Este guia também presume que os leitores entendam de programação de contratos inteligentes. +Você deve ter um bom entendimento de [contratos inteligentes](/developers/docs/smart-contracts/), [anatomia de contratos inteligentes](/developers/docs/smart-contracts/anatomy/) e da [Máquina Virtual Ethereum (EVM)](/developers/docs/evm/). Este guia também presume que os leitores entendam de programação de contratos inteligentes. ## O que é uma atualização de contrato inteligente? {#what-is-a-smart-contract-upgrade} @@ -42,7 +42,7 @@ O último passo na migração do contrato é convencer usuários a mudar para o Migração de contrato é uma medida relativamente direta e segura para atualização de contratos inteligentes sem quebrar interações de usuários. Entretanto, migrar manualmente o storage do usuário e saldos para o novo contrato é demorado e pode incorrer em altos gastos com gas. -[Mais sobre migração de contrato.](https://blog.trailofbits.com/2018/10/29/how-contract-migration-works/) +[Mais sobre a migração de contratos.](https://blog.trailofbits.com/2018/10/29/how-contract-migration-works/) ### Mecanismo de atualização 2: Separação de dados {#data-separation} @@ -66,17 +66,17 @@ Isto é o que acontece em um padrão proxy: 1. Usuários interagem com o contrato de proxy, que armazena dados, mas não mantém a lógica de negócio. -2. O contrato proxy armazena os endereços do contrato lógico e delega todas as chamadas de função para o contrato lógico (que mantém a lógica de negócio) usando a função `delegatecall`. +2. O contrato proxy armazena o endereço do contrato de lógica e delega todas as chamadas de função para o contrato de lógica (que contém a lógica de negócios) usando a função `delegatecall`. 3. Depois de a chamada ser direcionada para o contrato lógico, os dados retornados do contrato lógico é recuperado e retornado ao usuário. -Usar padrões de proxy requer um entendimento da função **delegatecall**. Basicamente, `delegatecall` é um opcode que permite um contrato chamar outro contrato, enquanto a execução real do código acontece no contexto do contrato chamado. Uma implicação de usar `delegatecall` em padrões proxy é que o contrato proxy lê e escreve no seu storage e executa lógica armazenada no contrato lógico como se chamando uma função interna. +Usar os padrões de proxy requer um entendimento da função **delegatecall**. Basicamente, `delegatecall` é um opcode que permite que um contrato chame outro contrato, enquanto a execução real do código acontece no contexto do contrato chamador. Uma implicação de usar `delegatecall` em padrões de proxy é que o contrato de proxy lê e escreve em seu armazenamento e executa a lógica armazenada no contrato de lógica como se estivesse chamando uma função interna. -Da [Documentação Solidity](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html#delegatecall-callcode-and-libraries): +Da [documentação do Solidity](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html#delegatecall-callcode-and-libraries): -> _Existe uma variante especial de chamada de mensagem, chamada **delegatecall** que é idêntica à chamada de mensagem, exceto pelo fato de que o código no endereço alvo é executado no contexto (ou seja, no endereço) do contrato chamador e `msg.sender` e `msg.value` não mudam seus valores._ _Isto significa que um contrato pode dinamicamente carregar código de um endereço diferente em tempo de execução. Storage, endereço atual e saldo ainda se referem ao contrado chamador, somente o código é pego do endereço chamado._ +> _Existe uma variante especial de uma chamada de mensagem, chamada **delegatecall**, que é idêntica a uma chamada de mensagem, exceto pelo fato de que o código no endereço de destino é executado no contexto (ou seja, no endereço) do contrato chamador e os valores de `msg.sender` e `msg.value` não se alteram._ _Isso significa que um contrato pode carregar código dinamicamente de um endereço diferente em tempo de execução._ Storage, endereço atual e saldo ainda se referem ao contrado chamador, somente o código é pego do endereço chamado._ -O contrato proxy sabe invocar `delegatecall` sempre quando um usuário chama a função, porque ele tem uma funçaõ `fallback` construída dentro dele. Em programação Solidity a [função fallback](https://docs.soliditylang.org/en/latest/contracts.html#fallback-function) é executada quando uma chamada de função não encontra funções especificadas em um contrato. +O contrato proxy sabe que deve invocar o `delegatecall` sempre que um usuário chamar uma função, pois ele tem uma função `fallback` incorporada. Na programação em Solidity, a [função de fallback](https://docs.soliditylang.org/en/latest/contracts.html#fallback-function) é executada quando uma chamada de função não corresponde às funções especificadas em um contrato. Fazer o padrão proxy trabalhar requer escrever uma função fallback customizada que especifique como o contrato proxy deve manipular chamadas de função que ele não suporta. Neste caso, a função de fallback do proxy é programada para iniciar um delegatecall and re-rotear a requisição do usuário para a implementação atual do contrato lógico. @@ -84,29 +84,29 @@ O contrato proxy é imutável por padrão, mas novos contratos lógicos com lóg Ao apontar o contrato proxy para um novo contrato lógico, o código executado quando os usuários chamam a função do contrato proxy é alterado. Isso nos permite atualizar a lógica do contrato sem pedir para os usuários interagirem com o novo contrato. -Padrões proxy são um método popular para atualização de contratos inteligentes porque eles eliminam as dificuldades associadas com migração de contrato. No entanto, os padrões de proxy são mais complicados de usar e podem introduzir falhas críticas, como [conflitos do seletor de funções](https://medium.com/nomic-foundation-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357), se usado indevidamente. +Padrões proxy são um método popular para atualização de contratos inteligentes porque eles eliminam as dificuldades associadas com migração de contrato. No entanto, os padrões de proxy são mais complicados de usar e podem introduzir falhas críticas, como [conflitos de seletor de função](https://medium.com/nomic-foundation-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357), se usados incorretamente. [Mais sobre padrões de proxy](https://blog.openzeppelin.com/proxy-patterns/). ### Mecanismo de atualização 4: Padrão de estratégia {#strategy-pattern} -Esta técnica é influenciada pelo [padrão de estratégia](https://en.wikipedia.org/wiki/Strategy_pattern), que encoraja criar programas de software que fazem interface com outros programas para implementar recursos específicos. Aplicar padrão de estratégia para desenvolvimento Ethereum significaria construir um contrato inteligente que chama funções de outros contratos. +Essa técnica é influenciada pelo [padrão de estratégia](https://en.wikipedia.org/wiki/Strategy_pattern), que incentiva a criação de programas de software que fazem interface com outros programas para implementar recursos específicos. Aplicar padrão de estratégia para desenvolvimento Ethereum significaria construir um contrato inteligente que chama funções de outros contratos. O contrato principal neste caso contém o núcleo da lógica de negócio, mas faz interface com outros contratos inteligentes ("contratos satélites") para executar certas funções. Este contrato principal também armazena o endereço para cada contrato satélite e pode alternar entre diferentes implementações de contrato satélite. -Você pode construir um novo contrato satélite e configurar o contrato principal com o novo endereço. Isto permite você mudar _estratégias_ (ou seja, implementar nova lógica) para um contrato inteligente. +Você pode construir um novo contrato satélite e configurar o contrato principal com o novo endereço. Isso permite que você altere _estratégias_ (ou seja, implementar nova lógica) para um contrato inteligente. Apesar de similar ao padrão de proxy discutido anteriormente, o padrão de estratégia é diferente porque o contrato principal, com o qual usuários interagem, mantém a lógica de negócios. Usar este padrão te dá a oportunidade de introduzir mudanças limitadas a um contrato inteligente sem afetar a infraestrutura principal. A principal desvantagem é que este padrão é mais útil para implantar atualizações menores. Além disso, se o contrato for comprometido (por exemplo, via um hack), você não pode usar este método de atualização. -### Mecanismo de atualização 5: Padrão Diamante {#diamond-pattern} +### Mecanismo de atualização 5: Padrão diamante {#diamond-pattern} O padrão diamante pode ser considerado uma melhoria do padrão proxy. Padrões diamante diferem dos padrões proxy porque o contrato proxy diamante pode delegar chamadas de função para mais de um contrato lógico. -Os contratos lógicos no padrão diamante são conhecidos como _facets_. Para fazer o padrão diamante funcionar, você precisa criar um mapeamento no contrato proxy que mapeie [funções seletoras](https://docs.soliditylang.org/en/latest/abi-spec.html#function-selector) para endereços facet diferentes. +Os contratos de lógica no padrão diamante são conhecidos como _facets_. Para que o padrão diamante funcione, você precisa criar um mapeamento no contrato proxy que mapeia [seletores de função](https://docs.soliditylang.org/en/latest/abi-spec.html#function-selector) para diferentes endereços de facet. -Quando um usuário faz uma chamada de função, o contrato proxy checa o mapeamento para encontrar o facet responsável por executar aquela função. Então ele invoca `delegatecall` (usando a função fallback) e redireciona a chamada para o devido contrato lógico. +Quando um usuário faz uma chamada de função, o contrato proxy checa o mapeamento para encontrar o facet responsável por executar aquela função. Em seguida, ele invoca o `delegatecall` (usando a função de fallback) e redireciona a chamada para o contrato de lógica apropriado. O padrão de atualização diamante tem algumas desvantagens sobre os padrões tradicionais de atualização proxy: @@ -114,27 +114,27 @@ O padrão de atualização diamante tem algumas desvantagens sobre os padrões t 2. Todos os contratos inteligentes (incluindo contratos lógicos usados nos padrões proxy) tem 24KB de limite de tamanho, o que pode ser uma limitação - especialmente para contratos complexos que requerem mais funções. O padrão diamante facilita resolver este problema dividindo funções por múltiplos contratos lógicos. -3. Padrões proxy adotam uma abordagem de pegar todos para controle de acesso. Uma entidade com acesso a funções de atualização pode mudar o contrato _inteiro_. Mas o padrão diamante habilita uma abordagem de permissões modulares, onde você pode restringir entidades para atualizar certas funções dentro de um contrato inteligente. +3. Padrões proxy adotam uma abordagem de pegar todos para controle de acesso. Uma entidade com acesso às funções de atualização pode alterar o contrato _inteiro_. Mas o padrão diamante habilita uma abordagem de permissões modulares, onde você pode restringir entidades para atualizar certas funções dentro de um contrato inteligente. -[Mais sobre padrão diamante](https://eip2535diamonds.substack.com/p/introduction-to-the-diamond-standard?s=w). +[Mais sobre o padrão diamante](https://eip2535diamonds.substack.com/p/introduction-to-the-diamond-standard?s=w). ## Prós e contras da atualização de contratos inteligentes {#pros-and-cons-of-upgrading-smart-contracts} -| Prós | Contras | -| ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Prós | Contras | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Uma atualização de contrato inteligente pode tornar mais fácil corrigir vulnerabilidades descobertas na fase pós-implantação. | A atualização de contratos inteligentes nega a ideia de imutabilidade do código, o qual tem implicações sobre descentralização e segurança. | | Os desenvolvedores podem usar atualizações lógicas para adicionar novas funcionalidades para aplicações descentralizadas. | Os usuários devem confiar nos desenvolvedores para não modificar contratos inteligentes de forma arbitrária. | | As atualizações de contratos inteligentes podem melhorar a segurança para os usuários finais, pois os bugs podem ser corrigidos rapidamente. | A funcionalidade de atualização de programação em contratos inteligentes adiciona outra camada de complexidade e aumenta a possibilidade de falhas críticas. | | As atualizações de contrato dá aos desenvolvedores mais liberdade para experimentar diferentes recursos e melhorar os dapps ao longo do tempo. | A oportunidade para atualizar contratos inteligentes pode encorajar os desenvolvedores a lançar projetos mais rapidamente sem fazer a devida diligência durante a fase de desenvolvimento. | -| | O controle de acesso inseguro ou a centralização em contratos inteligentes podem tornar mais fácil por atores maliciosos a execução de atualizações não autorizadas. | +| | O controle de acesso inseguro ou a centralização em contratos inteligentes podem tornar mais fácil por atores maliciosos a execução de atualizações não autorizadas. | -## Considerações para atualizar contratos inteligentes {#considerations-for-upgrading-smart-contracts} +## Considerações sobre a atualização de contratos inteligentes {#considerations-for-upgrading-smart-contracts} 1. Use mecanismos seguros de controle/autorização de acesso para evitar atualizações não autorizadas de contratos inteligentes, especialmente ao usar padrões de proxy, padrões de estratégia ou separação de dados. Um exemplo é restringir o acesso à função de atualização, de modo que apenas o proprietário do contrato possa chamá-lo. 2. A atualização de contratos inteligentes é uma atividade complexa e requer um alto nível de diligência para impedir a introdução de vulnerabilidades. -3. Reduza as suposições de confiança ao descentralizar o processo de implementação de atualizações. As estratégias possíveis incluem usar um [contrato de carteira multi-sig](/developers/docs/smart-contracts/#multisig), para controlar atualizações ou exigir [membros de um DAO](/dao/) para votar na aprovação da atualização. +3. Reduza as suposições de confiança ao descentralizar o processo de implementação de atualizações. As estratégias possíveis incluem o uso de um [contrato de carteira multi-sig](/developers/docs/smart-contracts/#multisig) para controlar as atualizações, ou exigir que [membros de uma DAO](/dao/) votem na aprovação da atualização. 4. Esteja ciente dos custos envolvidos na atualização de contratos. Por uma razão que, ao copiar o estado (por exemplo, saldos do usuário) de um contrato antigo para um novo contrato durante a migração do contrato pode exigir mais do que uma transação, o que significa mais taxas de gás. @@ -142,24 +142,24 @@ O padrão de atualização diamante tem algumas desvantagens sobre os padrões t Os bloqueios de tempo dão aos usuários algum tempo para sair do sistema, se eles discordarem de uma mudança proposta (por exemplo, atualização lógica ou novos esquemas de taxas). Sem bloqueios de tempo, os usuários precisam confiar nos desenvolvedores para não implementar alterações arbitrárias em um contrato inteligente sem aviso prévio. A desvantagem aqui é que os bloqueios de tempo restringem a capacidade de corrigir vulnerabilidades rapidamente. -## Recursos {#resources} +## Documentos {#resources} -**Plugins de atualização do OpenZeppelin - _Um conjunto de ferramentas para implantar e proteger contratos inteligentes atualizáveis._** +**Plugins de atualização da OpenZeppelin - _Um conjunto de ferramentas para implantar e proteger contratos inteligentes atualizáveis._** - [GitHub](https://github.com/OpenZeppelin/openzeppelin-upgrades) - [Documentação](https://docs.openzeppelin.com/upgrades) ## Tutoriais {#tutorials} -- [Atualizando seus contratos inteligentes | Tutorial do YouTube](https://www.youtube.com/watch?v=bdXJmWajZRY) por Patrick Collins -- [Tutorial de migração de contrtos inteligentes Ethereum](https://medium.com/coinmonks/ethereum-smart-contract-migration-13f6f12539bd) por Austin Griffith +- [Atualizando seus Contratos Inteligentes | Tutorial do YouTube](https://www.youtube.com/watch?v=bdXJmWajZRY) por Patrick Collins +- [Tutorial de Migração de Contrato Inteligente do Ethereum](https://medium.com/coinmonks/ethereum-smart-contract-migration-13f6f12539bd) por Austin Griffith - [Usando o padrão de proxy UUPS para atualizar contratos inteligentes](https://blog.logrocket.com/author/praneshas/) por Pranesh A.S -- [Tutorial Web3: Escreva o contrato inteligente atualizável (proxy) usando OpenZeppelin](https://dev.to/yakult/tutorial-write-upgradeable-smart-contract-proxy-contract-with-openzeppelin-1916) por fangjun.eth +- [Tutorial Web3: Escreva um contrato inteligente atualizável (proxy) usando OpenZeppelin](https://dev.to/yakult/tutorial-write-upgradeable-smart-contract-proxy-contract-with-openzeppelin-1916) por fangjun.eth ## Leitura adicional {#further-reading} -- [O estado das atualizações de contratos inteligentes](https://blog.openzeppelin.com/the-state-of-smart-contract-upgrades/) por Santiago Palladino -- [Várias maneiras de atualizar um contrato inteligente Solidity](https://cryptomarketpool.com/multiple-ways-to-upgrade-a-solidity-smart-contract/) - Blog do Crypto Market Pool -- [Aprenda: Atualizando contratos inteligentes](https://docs.openzeppelin.com/learn/upgrading-smart-contracts) - Documentos do OpenZeppelin -- [Padrões de proxy para capacidade de atualização de contratos Solidity: Proxies Transparentes vs UUPS](https://mirror.xyz/0xB38709B8198d147cc9Ff9C133838a044d78B064B/M7oTptQkBGXxox-tk9VJjL66E1V8BUF0GF79MMK4YG0) por Naveen Sahu -- [Como funcionam as atualizações por diamantes](https://dev.to/mudgen/how-diamond-upgrades-work-417j) de Nick Mudge +- [O Estado das Atualizações de Contratos Inteligentes](https://blog.openzeppelin.com/the-state-of-smart-contract-upgrades/) por Santiago Palladino +- [Várias maneiras de atualizar um contrato inteligente Solidity](https://cryptomarketpool.com/multiple-ways-to-upgrade-a-solidity-smart-contract/) - blog da Crypto Market Pool +- [Aprenda: Atualizando Contratos Inteligentes](https://docs.openzeppelin.com/learn/upgrading-smart-contracts) - Documentação da OpenZeppelin +- [Padrões de Proxy para Atualização de Contratos Solidity: Proxies Transparentes vs. UUPS](https://mirror.xyz/0xB38709B8198d147cc9Ff9C133838a044d78B064B/M7oTptQkBGXxox-tk9VJjL66E1V8BUF0GF79MMK4YG0) por Naveen Sahu +- [Como Funcionam as Atualizações Diamante](https://dev.to/mudgen/how-diamond-upgrades-work-417j) por Nick Mudge diff --git a/public/content/translations/pt-br/developers/docs/smart-contracts/verifying/index.md b/public/content/translations/pt-br/developers/docs/smart-contracts/verifying/index.md index e2de46ba098..bbcd9588eed 100644 --- a/public/content/translations/pt-br/developers/docs/smart-contracts/verifying/index.md +++ b/public/content/translations/pt-br/developers/docs/smart-contracts/verifying/index.md @@ -1,16 +1,16 @@ --- title: Verificando contratos inteligentes -description: Uma visão geral da verificação do código-fonte de contratos inteligentes no Ethereum +description: "Uma visão geral da verificação do código-fonte de contratos inteligentes no Ethereum" lang: pt-br --- -[Contratos inteligentes](/developers/docs/smart-contracts/) são projetados para serem "sem confiança", ou seja, usuários não precisam ter que confiar em terceiros (ex. desenvolvedores e empresas) antes de interagir com um contrato. Como um requisito para a não necessidade de confiança, usuários e outros desenvolvedores precisam ser capazes de verificar o código-fonte de um contrato inteligente. A verificação do código-fonte assegura aos usuários e desenvolvedores que o código do contrato publicado é o mesmo código em execução no endereço do contrato na blockchain Ethereum. +[Contratos inteligentes](/developers/docs/smart-contracts/) são projetados para serem “sem confiança”, o que significa que os usuários não precisam confiar em terceiros (por exemplo, desenvolvedores e empresas) antes de interagir com um contrato. Como um requisito para a não necessidade de confiança, usuários e outros desenvolvedores precisam ser capazes de verificar o código-fonte de um contrato inteligente. A verificação do código-fonte assegura aos usuários e desenvolvedores que o código do contrato publicado é o mesmo código em execução no endereço do contrato na blockchain Ethereum. -É importante fazer a distinção entre "verificação de código-fonte" e "[verificação formal](/developers/docs/smart-contracts/formal-verification/)". Verificação do código-fonte, que será explicada em detalhes abaixo, refere-se à verificação de que um determinado código-fonte de um contrato inteligente em uma linguagem de alto nível (ex. Solidity) compila com o mesmo bytecode a ser executado no endereço do contrato. Por outro lado, verificação formal descreve a verificação da corretude de um contrato inteligente, assegurando que o contrato se comporta como o esperado. Embora dependa do contexto, a verificação do contrato geralmente se refere à verificação do código-fonte. +É importante fazer a distinção entre "verificação de código-fonte" e "[verificação formal](/developers/docs/smart-contracts/formal-verification/)". A verificação do código-fonte, que será explicada em detalhes abaixo, refere-se à verificação de que um determinado código-fonte de um contrato inteligente em uma linguagem de alto nível (por exemplo, Solidity) compila para o mesmo bytecode a ser executado no endereço do contrato. Por outro lado, verificação formal descreve a verificação da corretude de um contrato inteligente, assegurando que o contrato se comporta como o esperado. Embora dependa do contexto, a verificação do contrato geralmente se refere à verificação do código-fonte. ## O que é verificação do código-fonte? {#what-is-source-code-verification} -Antes de fazer o deploy de um contrato inteligente na [Máquina Virtual do Ethereum (EVM)](/developers/docs/evm/), desenvolvedores [compilam](/developers/docs/smart-contracts/compiling/) o código-fonte do contrato —instruções [escritas em Solidity](/developers/docs/smart-contracts/languages/) ou outra linguagem de programação de alto nível— para bytecode. Como a EVM não pode interpretar instruções de alto nível, compilar o código-fonte para bytecode (ou seja, de baixo nível, instruções de máquina) é necessário para executar a lógica do contrato na EVM. +Antes de implantar um contrato inteligente na [Máquina Virtual do Ethereum (EVM)](/developers/docs/evm/), os desenvolvedores [compilam](/developers/docs/smart-contracts/compiling/) o código-fonte do contrato — instruções [escritas em Solidity](/developers/docs/smart-contracts/languages/) ou outra linguagem de programação de alto nível — para bytecode. Como a EVM não pode interpretar instruções de alto nível, compilar o código-fonte para bytecode (ou seja, de baixo nível, instruções de máquina) é necessário para executar a lógica do contrato na EVM. A verificação do código-fonte é a comparação entre o código-fonte do contrato inteligente e o bytecode compilado usado durante a criação do contrato para detectar quaisquer diferenças. A verificação de contratos inteligentes é importante visto que o código do contrato anunciado pode diferir do que é executado na blockchain. @@ -20,17 +20,17 @@ A verificação do contrato inteligente permite investigar o que um contrato faz Há algumas partes do código-fonte que não afetam o bytecode compilado, como comentários ou nomes de variáveis. Isso significa que dois códigos-fonte com diferentes nomes de variáveis e comentários conseguiriam verificar o mesmo contrato. Com isso, um ator malicioso consegue adicionar comentários enganosos ou dar nomes de variáveis enganosas dentro do código-fonte e obter o contrato verificado com um código-fonte diferente do código-fonte original. -É possível evitar isso anexando dados extras ao bytecode para servir como uma _garantia criptográfica_ da exatidão do código-fonte e como uma _impressão digital_ das informações de compilação. A informação necessária está disponível em [Metadados de contrato Solidity](https://docs.soliditylang.org/en/v0.8.15/metadata.html), e o hash desse arquivo é adicionado ao bytecode do contrato. Você pode conferi-lo em ação no [playground de metadados](https://playground.sourcify.dev). +É possível evitar isso anexando dados extras ao bytecode para servir como uma _garantia criptográfica_ para a exatidão do código-fonte, e como uma _impressão digital_ das informações de compilação. As informações necessárias são encontradas nos [metadados do contrato do Solidity](https://docs.soliditylang.org/en/v0.8.15/metadata.html), e o hash desse arquivo é anexado ao bytecode de um contrato. Você pode ver isso em ação no [playground de metadados](https://playground.sourcify.dev) O arquivo de metadados contém informações sobre a compilação do contrato incluindo o código-fonte e seus hashes. Significa que, se alguma das configurações de compilação ou até mesmo um byte em um dos arquivos de origem mudar, o arquivo de metadados muda. Consequentemente, o hash do arquivo de metadados, o qual é anexado ao bytecode, também muda. Isso significa que se o bytecode de um contrato + seu hash de metadados correspondem ao determinado código-fonte e as configurações de compilação, nós podemos ter certeza de que é o mesmo código-fonte usando na compilação original, nem mesmo um único byte de diferença. -Esse é tipo de verificação que se aproveita do hash é referenciado como **[verificação total](https://docs.sourcify.dev/docs/full-vs-partial-match/)** (também "verificação perfeita"). Se os hashes de metadados não coincidirem ou não forem considerados na verificação, essa seria uma "correspondência parcial", que atualmente é a maneira mais comum de se verificar contratos. É possível [inserir código malicioso](https://samczsun.com/hiding-in-plain-sight/) que não apareceria no código-fonte verificado sem a verificação total. A maioria dos desenvolvedores não está ciente da verificação completa e não mantém o arquivo de metadados de sua compilação, portanto, a verificação parcial tem sido o método de fato para verificar os contratos até agora. +Este tipo de verificação que utiliza o hash de metadados é referido como **"[verificação completa](https://docs.sourcify.dev/docs/full-vs-partial-match/)"** (também "verificação perfeita"). Se os hashes de metadados não coincidirem ou não forem considerados na verificação, essa seria uma "correspondência parcial", que atualmente é a maneira mais comum de se verificar contratos. É possível [inserir código malicioso](https://samczsun.com/hiding-in-plain-sight/) que não seria refletido no código-fonte verificado sem a verificação completa. A maioria dos desenvolvedores não está ciente da verificação completa e não mantém o arquivo de metadados de sua compilação, portanto, a verificação parcial tem sido o método de fato para verificar os contratos até agora. ## Por que a verificação do código-fonte é importante? {#importance-of-source-code-verification} ### Ausência de confiança {#trustlessness} -A ausência da necessidade de confiança é provavelmente a maior premissa para contratos inteligentes e [aplicações descentralizadas (dapps)](/developers/docs/dapps/). Os contratos inteligentes são "imutáveis" e não podem ser alterados; um contrato executará apenas a lógica de negócio definida no código no momento do deploy. Isto significa que os desenvolvedores e empresas não podem manipular o código de um contrato após o deploy no Ethereum. +A ausência de confiança é, sem dúvida, a maior premissa para contratos inteligentes e [aplicativos descentralizados (dapps)](/developers/docs/dapps/). Os contratos inteligentes são "imutáveis" e não podem ser alterados; um contrato executará apenas a lógica de negócio definida no código no momento do deploy. Isto significa que os desenvolvedores e empresas não podem manipular o código de um contrato após o deploy no Ethereum. Para que um contrato inteligente seja ausente de confiança, o código do contrato deve estar disponível para verificação independente. Embora o bytecode compilado de cada contrato inteligente esteja disponível publicamente na blockchain, uma linguagem de baixo nível é difícil de entender — tanto para desenvolvedores quanto para usuários. @@ -40,13 +40,13 @@ As ferramentas de verificação do código-fonte fornecem garantias de que os ar ### Segurança do usuário {#user-safety} -Em contratos inteligentes, geralmente há muito dinheiro envolvido. Isso pede por altas garantias de segurança e verificação da lógica de um contrato inteligente antes de usá-lo. O problema é que desenvolvedores inescrupulosos podem enganar usuários inserindo código malicioso em um contrato inteligente. Sem a verificação, contratos inteligentes maliciosos podem ter [backdoors](https://www.trustnodes.com/2018/11/10/concerns-rise-over-backdoored-smart-contracts), controversos mecanismos de controle de acesso, vulnerabilidades exploráveis, e outras coisas que comprometem a segurança dos usuários e que passariam despercebidas. +Em contratos inteligentes, geralmente há muito dinheiro envolvido. Isso pede por altas garantias de segurança e verificação da lógica de um contrato inteligente antes de usá-lo. O problema é que desenvolvedores inescrupulosos podem enganar usuários inserindo código malicioso em um contrato inteligente. Sem verificação, contratos inteligentes maliciosos podem ter [backdoors](https://www.trustnodes.com/2018/11/10/concerns-rise-over-backdoored-smart-contracts), mecanismos de controle de acesso controversos, vulnerabilidades exploráveis e outras coisas que comprometem a segurança do usuário e que passariam despercebidas. Publicar os arquivos de código-fonte de um contrato inteligente torna mais fácil para interessados, como auditores, avaliar o contrato quanto a possíveis vetores de ataque. Com várias partes verificando independentemente o contrato inteligente, os usuários têm maiores garantias quanto à sua segurança. -## Como verificar o código-fonte para contratos inteligentes Ethereum {#source-code-verification-for-ethereum-smart-contracts} +## Como verificar o código-fonte de contratos inteligentes da Ethereum {#source-code-verification-for-ethereum-smart-contracts} -[Implantar um contrato inteligente no Ethereum](/developers/docs/smart-contracts/deploying/) requer o envio de uma transação com o payload de dados (bytecode compilado) para um endereço especial. O payload de dados é gerado compilando o código-fonte, além dos [argumentos do construtor](https://docs.soliditylang.org/en/v0.8.14/contracts.html#constructor) da instância do contrato anexado aos dados do payload na transação. A compilação é determinística, o que significa que sempre produz a mesma saída (ou seja, bytecode de contrato), se os mesmos arquivos de origem e configurações de compilação (por exemplo, versão do compilador, otimizador) forem usados. +[Implantar um contrato inteligente na Ethereum](/developers/docs/smart-contracts/deploying/) exige o envio de uma transação com um payload de dados (bytecode compilado) para um endereço especial. O payload de dados é gerado pela compilação do código-fonte, mais os [argumentos do construtor](https://docs.soliditylang.org/en/v0.8.14/contracts.html#constructor) da instância do contrato anexados ao payload de dados na transação. A compilação é determinística, o que significa que sempre produz a mesma saída (isto é, o bytecode do contrato) se os mesmos arquivos de origem e configurações de compilação (por exemplo, versão do compilador, otimizador) forem usados. ![Um diagrama mostrando a verificação do código-fonte do contrato inteligente](./source-code-verification.png) @@ -62,41 +62,47 @@ A verificação de um contrato inteligente basicamente envolve os seguintes pass 5. Além disso, se os hashes de metadados no final do bytecode corresponderem, será uma correspondência completa. -Note que esta é uma descrição simplista de verificação e há muitas exceções que não funcionariam com isso, como ter [variáveis imutáveis](https://docs.sourcify.dev/docs/immutables/). +Observe que esta é uma descrição simplista de verificação e há muitas exceções que não funcionariam com isso, como ter [variáveis imutáveis](https://docs.sourcify.dev/docs/immutables/). -## Ferramentas de verificação de código-fonte {#source-code-verification-tools} +## Ferramentas de verificação do código-fonte {#source-code-verification-tools} O processo tradicional de verificação de contratos pode ser complexo. Isto é porque nós temos ferramentas para verificar o código-fonte para contratos inteligentes implantados no Ethereum. Estas ferramentas automatizam grandes partes da verificação de código-fonte e também selecionam contratos verificados para os benefícios dos usuários. ### Etherscan {#etherscan} -Embora mais conhecido como um [observador da blockchain do Ethereum](/developers/docs/data-and-analytics/block-explorers/), o Etherscan também oferece um [serviço de verificação de código-fonte](https://etherscan.io/verifyContract) para desenvolvedores e usuários de contratos inteligentes. +Embora seja mais conhecido como um [explorador de blockchain da Ethereum](/developers/docs/data-and-analytics/block-explorers/), o Etherscan também oferece um [serviço de verificação de código-fonte](https://etherscan.io/verifyContract) para desenvolvedores e usuários de contratos inteligentes. -O Etherscan permite que você recompile o bytecode do contrato a partir do payload de dados original (código-fonte, endereço da biblioteca, configurações do compilador, endereço do contrato, etc.) Se o bytecode recompilado está associado ao bytecode (e aos parâmetros do construtor) do contrato on-chain, então [o contrato é verificado](https://info.etherscan.com/types-of-contract-verification/). +O Etherscan permite que você recompile o bytecode do contrato a partir do payload de dados original (código-fonte, endereço da biblioteca, configurações do compilador, endereço do contrato, etc.) Se o bytecode recompilado está associado ao bytecode (e aos parâmetros do construtor) do contrato em cadeia, então [o contrato é verificado](https://info.etherscan.com/types-of-contract-verification/). -Uma vez verificado, o código-fonte do seu contrato recebe um rótulo "Verificado" e é publicado no Etherscan, para que outros auditem. Ele também é adicionado à seção [Contratos Verificados](https://etherscan.io/contractsVerified/) - um repositório de contratos inteligentes com códigos-fonte verificados. +Uma vez verificado, o código-fonte do seu contrato recebe um rótulo "Verificado" e é publicado no Etherscan, para que outros auditem. Ele também é adicionado à seção [Contratos Verificados](https://etherscan.io/contractsVerified/) — um repositório de contratos inteligentes com códigos-fonte verificados. -Etherscan é a ferramenta mais usada para verificação de contratos. No entanto, a verificação de contrato do Etherscan tem uma desvantagem: ele falha ao comparar o **hash de metadados** do bytecode on-chain e do bytecode recompilado. Portanto, as correspondências no Etherscan são correspondências parciais. +Etherscan é a ferramenta mais usada para verificação de contratos. No entanto, a verificação de contrato do Etherscan tem uma desvantagem: ela falha ao comparar o **hash de metadados** do bytecode em cadeia e do bytecode recompilado. Portanto, as correspondências no Etherscan são correspondências parciais. -[Mais sobre a verificação de contratos no Etherscan](https://medium.com/etherscan-blog/verifying-contracts-on-etherscan-f995ab772327). +[Saiba mais sobre como verificar contratos no Etherscan](https://medium.com/etherscan-blog/verifying-contracts-on-etherscan-f995ab772327). + +### Blockscout {#blockscout} + +O [Blockscout](https://blockscout.com/) é um explorador de blockchain de código aberto que também fornece um [serviço de verificação de contratos](https://eth.blockscout.com/contract-verification) para desenvolvedores e usuários de contratos inteligentes. Como uma alternativa de código aberto, o Blockscout oferece transparência sobre como a verificação é realizada e permite contribuições da comunidade para melhorar o processo de verificação. + +Como outros serviços de verificação, o Blockscout permite que você verifique o código-fonte do seu contrato recompilando o bytecode e comparando-o com o contrato implantado. Após a verificação, seu contrato recebe o status de verificação e o código-fonte fica disponível publicamente para auditoria e interação. Os contratos verificados também são listados no [repositório de contratos verificados](https://eth.blockscout.com/verified-contracts) do Blockscout para facilitar a navegação e a descoberta. ### Sourcify {#sourcify} -[Sourcify](https://sourcify.dev/#/verifier) é outra ferramenta para verificação de contratos que é de código aberto e descentralizada. Não é um observador de blocos e apenas verifica contratos em [diferentes redes baseadas em EVM](https://docs.sourcify.dev/docs/chains). Ele atua como uma infraestrutura pública para que outras ferramentas construam sobre ele, e tem como objetivo permitir interações de contrato mais amigáveis a humanos usando o [ABI](/developers/docs/smart-contracts/compiling/#web-applications) e [NatSpec](https://docs.soliditylang.org/en/v0.8.15/natspec-format.html) encontrados no arquivo de metadados. +O [Sourcify](https://sourcify.dev/#/verifier) é outra ferramenta de verificação de contratos que é de código aberto e descentralizada. Não é um explorador de blockchain e apenas verifica contratos em [diferentes redes baseadas na EVM](https://docs.sourcify.dev/docs/chains). Ele atua como uma infraestrutura pública para que outras ferramentas possam ser desenvolvidas sobre ele, e visa permitir interações de contrato mais amigáveis ao ser humano usando os comentários do [ABI](/developers/docs/smart-contracts/compiling/#web-applications) e do [NatSpec](https://docs.soliditylang.org/en/v0.8.15/natspec-format.html) encontrados no arquivo de metadados. -Ao contrário do Etherscan, o Sourcify suporta correspondências completas com o hash de metadados. Os contratos verificados são servidos em seu [repositório público](https://docs.sourcify.dev/docs/repository/) HTTP e [IPFS](https://docs.ipfs.io/concepts/what-is-ipfs/#what-is-ipfs), que é um [armazenamento descentralizado](https://web3.storage/docs/concepts/content-addressing/) endereçado ao conteúdo. Isso permite buscar o arquivo de metadados de um contrato sobre IPFS, pois o hash de metadados incluído é um hash IPFS. +Ao contrário do Etherscan, o Sourcify suporta correspondências completas com o hash de metadados. Os contratos verificados são servidos em seu [repositório público](https://docs.sourcify.dev/docs/repository/) em HTTP e [IPFS](https://docs.ipfs.io/concepts/what-is-ipfs/#what-is-ipfs), que é um armazenamento descentralizado e [endereçado por conteúdo](https://docs.storacha.network/concepts/content-addressing/). Isso permite buscar o arquivo de metadados de um contrato sobre IPFS, pois o hash de metadados incluído é um hash IPFS. -Adicionalmente, também é possível recuperar os arquivos de código-fonte por IPFS, pois os hashes IPFS desses arquivos também são encontrados nos metadados. Um contrato pode ser verificado fornecendo o arquivo de metadados e os arquivos da origem por meio de sua API ou [UI](https://sourcify.dev/#/verifier) ou usando os plugins. A ferramenta de monitoramento Sourcify também escuta as criações de contratos em novos blocos e tenta verificar os contratos se os seus metadados e arquivos de origem são publicados no IPFS. +Adicionalmente, também é possível recuperar os arquivos de código-fonte por IPFS, pois os hashes IPFS desses arquivos também são encontrados nos metadados. Um contrato pode ser verificado fornecendo o arquivo de metadados e os arquivos-fonte através da sua API ou da [IU](https://sourcify.dev/#/verifier), ou usando os plugins. A ferramenta de monitoramento Sourcify também escuta as criações de contratos em novos blocos e tenta verificar os contratos se os seus metadados e arquivos de origem são publicados no IPFS. -[Mais sobre a verificação de contratos no Sourcify](https://blog.soliditylang.org/2020/06/25/sourcify-faq/). +[Saiba mais sobre a verificação de contratos no Sourcify](https://soliditylang.org/blog/2020/06/25/sourcify-faq/). ### Tenderly {#tenderly} -A [plataforma Tenderly](https://tenderly.co/) permite desenvolvedores Web3 criem, testem, monitorem e operem contratos inteligentes. Ao combinar ferramentas de depuração com observabilidade e blocos de construção de infraestrutura, o Tenderly ajuda os desenvolvedores a acelerar o desenvolvimento de contratos inteligentes. Para habilitar totalmente os recursos do Tenderly, os desenvolvedores precisam [realizar a verificação do código-fonte](https://docs.tenderly.co/monitoring/contract-verification) usando vários métodos. +A [plataforma Tenderly](https://tenderly.co/) permite que os desenvolvedores da Web3 construam, testem, monitorem e operem contratos inteligentes. Ao combinar ferramentas de depuração com observabilidade e blocos de construção de infraestrutura, o Tenderly ajuda os desenvolvedores a acelerar o desenvolvimento de contratos inteligentes. Para habilitar totalmente os recursos do Tenderly, os desenvolvedores precisam [realizar a verificação do código-fonte](https://docs.tenderly.co/monitoring/contract-verification) usando vários métodos. É possível verificar um contrato de forma privada ou pública. Se verificado privadamente, o contrato inteligente ficará visível apenas para você (e outros membros do seu projeto). A verificação de um contrato publicamente o torna visível para todos que usam a plataforma Tenderly. -Você pode verificar seus contratos usando o [Painel](https://docs.tenderly.co/monitoring/smart-contract-verification/verifying-a-smart-contract), [Plugin Tenderly da Hardhat](https://docs.tenderly.co/monitoring/smart-contract-verification/verifying-contracts-using-the-tenderly-hardhat-plugin) ou [CLI](https://docs.tenderly.co/monitoring/smart-contract-verification/verifying-contracts-using-cli). +Você pode verificar seus contratos usando o [Painel](https://docs.tenderly.co/contract-verification), o [plugin Hardhat da Tenderly](https://docs.tenderly.co/contract-verification/hardhat), ou a [CLI (interface de linha de comando)](https://docs.tenderly.co/monitoring/smart-contract-verification/verifying-contracts-using-cli). Ao verificar contratos através do Painel, você precisa importar o arquivo de origem ou o arquivo de metadados gerado pelo compilador Solidity, o endereço/rede e as configurações do compilador. diff --git a/public/content/translations/pt-br/developers/docs/standards/index.md b/public/content/translations/pt-br/developers/docs/standards/index.md index ef2d2757224..ee48efac94b 100644 --- a/public/content/translations/pt-br/developers/docs/standards/index.md +++ b/public/content/translations/pt-br/developers/docs/standards/index.md @@ -1,58 +1,59 @@ --- -title: Padrões de desenvolvimento Ethereum -description: Standards +title: "Padrões de desenvolvimento Ethereum" +description: "Aprenda sobre padrões de Ethereum, incluindo EIPs, padrões de token como ERC-20 e ERC-721 e convenções de desenvolvimento." lang: pt-br incomplete: true --- ## Visão geral dos padrões {#standards-overview} -A comunidade Ethereum adotou vários padrões que ajudam a manter projetos (tais como [Ethereum clients](/developers/docs/nodes-and-clients/) e carteiras) interoperáveis entre implementações, e asseguram que os contratos inteligentes e os dapps permaneçam compostos. +A comunidade Ethereum adotou muitos padrões que ajudam a manter os projetos (como [clientes Ethereum](/developers/docs/nodes-and-clients/) e carteiras) interoperáveis entre implementações e garantem que os contratos inteligentes e dapps permaneçam componíveis. -Normalmente, os padrões são apresentados como [Propostas de melhorias do Ethereum](/eips/) (EIPs), que são discutidas pela comunidade por meio de um [processo padronizado](https://eips.ethereum.org/EIPS/eip-1). +Normalmente, os padrões são introduzidos como [Propostas de Melhoria do Ethereum](/eips/) (EIPs), que são discutidas pelos membros da comunidade por meio de um [processo padrão](https://eips.ethereum.org/EIPS/eip-1). - [Introdução às EIPs](/eips/) - [Lista de EIPs](https://eips.ethereum.org/) -- [Repositório de GitHub sobre EIP](https://github.com/ethereum/EIPs) -- [Tabela de discussão de EIP](https://ethereum-magicians.org/c/eips) -- [Introdução à governança do Ethereum](/governance/) -- [Visão geral da governança Ethereum](https://web.archive.org/web/20201107234050/https://blog.bmannconsulting.com/ethereum-governance/) _31 de Março de 2019 - Boris Mann_ -- [Coordenação de desenvolvimento do protocolo de governança do Ethereum e atualização da rede](https://hudsonjameson.com/posts/2020-03-23-ethereum-protocol-development-governance-and-network-upgrade-coordination/) _23 de Março 23 - Hudson Jameson_ -- [Lista de reprodução de todas as reuniões de Ethereum Core Dev](https://www.youtube.com/@EthereumProtocol) _(YouTube Playlist)_ +- [Repositório GitHub de EIPs](https://github.com/ethereum/EIPs) +- [Fórum de discussão sobre EIPs](https://ethereum-magicians.org/c/eips) +- [Introdução à Governança do Ethereum](/governance/) +- [Visão geral da Governança do Ethereum](https://web.archive.org/web/20201107234050/https://blog.bmannconsulting.com/ethereum-governance/) _31 de março de 2019 - Boris Mann_ +- [Governança de Desenvolvimento do Protocolo Ethereum e Coordenação de Upgrade da Rede](https://hudsonjameson.com/posts/2020-03-23-ethereum-protocol-development-governance-and-network-upgrade-coordination/) _23 de março de 2020 - Hudson Jameson_ +- [Playlist de todas as reuniões de desenvolvedores do núcleo do Ethereum](https://www.youtube.com/@EthereumProtocol) _(Playlist do YouTube)_ ## Tipos de padrões {#types-of-standards} Existem 3 tipos de EIP: - Acompanhemento padrão: descreve qualquer mudança que afeta a maioria ou todas as implementações do Ethereum -- [Acompanhamento Meta](https://eips.ethereum.org/meta): descreve um processo em torno do Ethereum ou propõe uma alteração para um processo -- [Acompanhamento informativo](https://eips.ethereum.org/informational): descreve um problema de design do Ethereum e fornece orientações ou informações gerais para a comunidade Ethereum +- [Trilha Meta](https://eips.ethereum.org/meta): descreve um processo em torno do Ethereum ou propõe uma mudança a um processo +- [Trilha Informativa](https://eips.ethereum.org/informational): descreve um problema de design do Ethereum ou fornece diretrizes gerais ou informações para a comunidade Ethereum Além disso, o acompanhamento padrão é subdividido em 4 categorias: -- [Core](https://eips.ethereum.org/core): melhorias que requerem um fork de consenso -- [Networking](https://eips.ethereum.org/networking): melhorias em torno do devp2p e do Light Ethereum Subprotocol, bem como propostas de melhorias nas especificações de protocolo de rede do whisper e do swarm. -- [Interface](https://eips.ethereum.org/interface): melhorias em torno das especificações e padrões de API/RPC, e certos padrões no nível de linguagem, como nomes de método e contratos ABIs. -- [ERC](https://eips.ethereum.org/erc): normas e convenções dno nível do aplicativo +- [Núcleo (Core)](https://eips.ethereum.org/core): melhorias que exigem uma bifurcação de consenso +- [Rede (Networking)](https://eips.ethereum.org/networking): melhorias em torno do devp2p e do Subprotocolo Leve do Ethereum (Light Ethereum Subprotocol), bem como melhorias propostas para especificações de protocolo de rede do whisper e do swarm. +- [Interface](https://eips.ethereum.org/interface): melhorias em torno de especificações e padrões de API/RPC do cliente, e certos padrões de nível de linguagem como nomes de métodos e ABIs de contrato. +- [ERC](https://eips.ethereum.org/erc): padrões e convenções de nível de aplicativo -Encontre informações mais detalhadas sobre esses tipos e categorias diferentes em [EIP-1](https://eips.ethereum.org/EIPS/eip-1#eip-types) +Informações mais detalhadas sobre esses diferentes tipos e categorias podem ser encontradas na [EIP-1](https://eips.ethereum.org/EIPS/eip-1#eip-types) ### Padrões de token {#token-standards} -- [ERC-20](/developers/docs/standards/tokens/erc-20/) - Uma interface padrão para tokens fungíveis (intermutáveis), como tokens de votação, tokens de staking ou moedas virtuais. - - [ERC-1363:](/developers/docs/standards/tokens/erc-1363/)define uma interface de token para tokens ERC-20 que suportam a execução do código destinatário após a transferência (ou transferFrom), ou o código do gastador após a aprovação -- [ERC-721](/developers/docs/standards/tokens/erc-721/) - Uma interface padrão para tokens não fungíveis, como uma ação para obra de arte ou uma música. - - [ERC-2309](https://eips.ethereum.org/EIPS/eip-2309): um evento padronizado emitido ao criar/transferir um ou muitos tokens não-fungíveis usando identificadores de token consecutivos. - - [ERC-4400:](https://eips.ethereum.org/EIPS/eip-4400)extensão da interface para o papel do consumidor EIP-721 - - [ERC-4907:](https://eips.ethereum.org/EIPS/eip-4907) adicione um papel com limitação de tempo com permissões restritas aos tokens ERC-721. -- [ERC-777](/developers/docs/standards/tokens/erc-777/) **(NÃO RECOMENDADO): ** um padrão de token que aprimora o ERC-20. -- [ERC-1155](/developers/docs/standards/tokens/erc-1155/): um padrão de token que pode conter ativos fungíveis e não-fungíveis. -- [ERC-4626](/developers/docs/standards/tokens/erc-4626/): um padrão de cofre tokenizado projetado para otimizar e unificar os parâmetros técnicos dos cofres de rendimento. +- [ERC-20](/developers/docs/standards/tokens/erc-20/) - Uma interface padrão para tokens fungíveis (intercambiáveis), como tokens de votação, tokens de staking ou moedas virtuais. + - [ERC-223](/developers/docs/standards/tokens/erc-223/) - Um padrão de tokens fungíveis que faz com que os tokens se comportem de forma idêntica ao ether e oferece suporte ao tratamento de transferências de tokens no lado do destinatário. + - [ERC-1363](/developers/docs/standards/tokens/erc-1363/) - Uma interface de extensão para tokens ERC-20 que suporta a execução de um callback em contratos de destinatário em uma única transação. +- [ERC-721](/developers/docs/standards/tokens/erc-721/) - Uma interface padrão para tokens não fungíveis, como um título de propriedade para uma obra de arte ou uma música. + - [ERC-2309](https://eips.ethereum.org/EIPS/eip-2309) - Um evento padronizado emitido ao criar/transferir um ou muitos tokens não fungíveis usando identificadores de token consecutivos. + - [ERC-4400](https://eips.ethereum.org/EIPS/eip-4400) - Extensão de interface para a função de consumidor da EIP-721. + - [ERC-4907](https://eips.ethereum.org/EIPS/eip-4907) - Adiciona uma função com tempo limitado e com permissões restritas aos tokens ERC-721. +- [ERC-777](/developers/docs/standards/tokens/erc-777/) - **(NÃO RECOMENDADO)** Um padrão de token que melhora o ERC-20. +- [ERC-1155](/developers/docs/standards/tokens/erc-1155/) - Um padrão de token que pode conter ativos fungíveis e não fungíveis. +- [ERC-4626](/developers/docs/standards/tokens/erc-4626/) - Um padrão de cofre tokenizado projetado para otimizar e unificar os parâmetros técnicos de cofres de rendimento. -Aprenda mais sobre [padrões de token](/developers/docs/standards/tokens/). +Saiba mais sobre [padrões de token](/developers/docs/standards/tokens/). ## Leitura adicional {#further-reading} -- [Propostas de Melhorias do Ethereum (EIPs)](/eips/) +- [Propostas de Melhoria do Ethereum (EIPs)](/eips/) -_Conhece algum recurso da comunidade que o ajudou? Edite essa página e adicione!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ diff --git a/public/content/translations/pt-br/developers/docs/standards/tokens/erc-1155/index.md b/public/content/translations/pt-br/developers/docs/standards/tokens/erc-1155/index.md index 0198cc8f268..2a756ce1bc5 100644 --- a/public/content/translations/pt-br/developers/docs/standards/tokens/erc-1155/index.md +++ b/public/content/translations/pt-br/developers/docs/standards/tokens/erc-1155/index.md @@ -1,35 +1,35 @@ --- -title: Padrão Multi-Token ERC-1155 -description: Token +title: "Padrão Multi-Token ERC-1155" +description: "Saiba mais sobre o ERC-1155, um padrão de múltiplos tokens que combina tokens fungíveis e não fungíveis em um único contrato." lang: pt-br --- ## Introdução {#introduction} -Uma interface padrão para contratos que gerenciam vários tipos de tokens. Um único contrato implementado pode incluir qualquer combinação de tokens fungíveis, tokens não fungíveis ou outras configurações, por exemplo, tokens semifungíveis. +Uma interface padrão para contratos que gerenciam vários tipos de tokens. Um único contrato implementado pode incluir qualquer combinação de tokens fungíveis, tokens não fungíveis ou outras configurações (por exemplo, tokens semifungíveis). **O que se entende por padrão Multi-Token?** -A ideia é simples e trata-se de criar uma interface de contratos inteligentes que possa representar e controlar qualquer número de tipos de token, fungíveis ou não fungíveis. Dessa forma, o token ERC-1155 pode fazer as mesmas funções que um token [ERC-20](/developers/docs/standards/tokens/erc-20/) ou um token [ERC-721](/developers/docs/standards/tokens/erc-721/), ou ainda as duas funções simultaneamente. Ele melhora a funcionalidade de ambos os padrões ERC-20 e ERC-721, tornando-os mais eficientes e corrigindo erros óbvios de implementação. +A ideia é simples e trata-se de criar uma interface de contratos inteligentes que possa representar e controlar qualquer número de tipos de token, fungíveis ou não fungíveis. Dessa forma, o token ERC-1155 pode executar as mesmas funções de um token [ERC-20](/developers/docs/standards/tokens/erc-20/) e [ERC-721](/developers/docs/standards/tokens/erc-721/), e até mesmo de ambos ao mesmo tempo. Ele melhora a funcionalidade de ambos os padrões ERC-20 e ERC-721, tornando-os mais eficientes e corrigindo erros óbvios de implementação. -O token ERC-1155 é descrito com profundidade em [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155). +O token ERC-1155 é descrito em detalhes na [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155). ## Pré-requisitos {#prerequisites} -Para entender melhor esta página, recomendamos ler primeiro sobre [padrões de token](/developers/docs/standards/tokens/), [ERC-20](/developers/docs/standards/tokens/erc-20/) e [ERC-721](/developers/docs/standards/tokens/erc-721/). +Para entender melhor esta página, recomendamos que você leia primeiro sobre os [padrões de token](/developers/docs/standards/tokens/), o [ERC-20](/developers/docs/standards/tokens/erc-20/) e o [ERC-721](/developers/docs/standards/tokens/erc-721/). ## Funções e características do ERC-1155: {#body} -- [Transferências em lote](#batch_transfers): transfira vários ativos em uma única chamada. +- [Transferência em lote](#batch_transfers): transfira vários ativos em uma única chamada. - [Saldo em lote](#batch_balance): obtenha os saldos de vários ativos em uma única chamada. -- [Aprovação em lote](#batch_approval): aprove todos os tokens de um endereço. -- [Hooks](#receive_hook): receba hook de tokens. -- [Suporte para NFT](#nft_support): se a cunhagem for de apenas 1, tratar como NFT. -- [Regras de transferência segura](#safe_transfer_rule): conjunto de regras para transferências seguras. +- [Aprovação em lote](#batch_approval): aprove todos os tokens para um endereço. +- [Hooks](#receive_hook): hook para recebimento de tokens. +- [Suporte a NFT](#nft_support): se o fornecimento for de apenas 1, trate-o como um NFT. +- [Regras de transferência segura](#safe_transfer_rule): conjunto de regras para transferência segura. ### Transferências em lote {#batch-transfers} -As transferências em lote funcionam de forma muito semelhante às transferências regulares do ERC-20. Vejamos a função `transferFrom` da ERC-20 habitual: +As transferências em lote funcionam de forma muito semelhante às transferências regulares do ERC-20. Vejamos a função `transferFrom` regular do ERC-20: ```solidity // ERC-20 @@ -45,17 +45,17 @@ function safeBatchTransferFrom( ) external; ``` -A única diferença no ERC-1155 é que passamos os valores como um array e também passamos um array de ‘ids’. Por exemplo, dadas as matrizes `ids=[3, 6, 13]` e `values=[100, 200, 5]`, as transferências resultantes serão +A única diferença no ERC-1155 é que passamos os valores como um array e também passamos um array de ‘ids’. Por exemplo, dados `ids=[3, 6, 13]` e `values=[100, 200, 5]`, as transferências resultantes serão -1. Transferir 100 tokens da ID 3 de `_from` para `_to`. -2. Transferir 200 tokens da ID 6 de `_from` para `_to`. -3. Transferir 5 tokens da ID 13 de `_from` to `_to`. +1. Transferir 100 tokens com o id 3 de `_from` para `_to`. +2. Transferir 200 tokens com o id 6 de `_from` para `_to`. +3. Transferir 5 tokens com o id 13 de `_from` para `_to`. -No ERC-1155, só temos `transferFrom`, ou seja, não há `transfer`. Para usá-lo como uma transferência regular, ou `transfer`, defina o endereço de origem como o endereço que está chamando a função. +No ERC-1155, só temos `transferFrom`, não `transfer`. Para usá-lo como um `transfer` regular, basta definir o endereço de origem como o endereço que está chamando a função. ### Saldo em lote {#batch-balance} -A respectiva chamada `balanceOf` do ERC-20 também tem sua função parceira com suporte para lotes. Como lembrete, esta é a versão do ERC-20: +A respectiva chamada `balanceOf` do ERC-20 também tem sua função parceira com suporte a lote. Como lembrete, esta é a versão do ERC-20: ```solidity // ERC-20 @@ -70,7 +70,7 @@ function balanceOfBatch( Ainda mais simples para a chamada de saldo, podemos recuperar saldos múltiplos em uma única chamada. Passamos a matriz de proprietários, seguida pela matriz dos IDs dos tokens. -Por exemplo, dado `_ids=[3, 6, 13]` e `_owners=[0xbeef..., 0x1337..., 0x11...]`, o valor de retorno será +Por exemplo, dados `_ids=[3, 6, 13]` e `_owners=[0xbeef..., 0x1337..., 0x1111...]`, o valor de retorno será ```solidity [ @@ -95,13 +95,13 @@ function isApprovedForAll( ) external view returns (bool); ``` -As aprovações são um pouco diferentes do ERC-20. Em vez de aprovar valores específicos, você define um operador para aprovados ou não aprovados via `setApprovalForAll`. +As aprovações são um pouco diferentes do ERC-20. Em vez de aprovar valores específicos, você define um operador como aprovado ou não aprovado através do `setApprovalForAll`. -Ler o status atual pode ser feito via `isApprovedForAll`. Como você pode ver, é uma operação de tudo ou nada. Você não pode definir quantos tokens aprovar ou mesmo quais classes de token. +A leitura do status atual pode ser feita através do `isApprovedForAll`. Como você pode ver, é uma operação de tudo ou nada. Você não pode definir quantos tokens aprovar ou mesmo quais classes de token. Isto é intencionalmente concebido pensando na simplicidade. Você só pode aprovar tudo para um endereço. -### Receber hooks {#receive-hook} +### Hook de recebimento {#receive-hook} ```solidity function onERC1155BatchReceived( @@ -113,7 +113,7 @@ function onERC1155BatchReceived( ) external returns(bytes4); ``` -Dado o suporte da [EIP-165](https://eips.ethereum.org/EIPS/eip-165), o ERC-1155 pode receber hooks apenas por contratos inteligentes. A função de hook deve retornar um valor mágico predefinido de 4 bytes que é dado como: +Com o suporte da [EIP-165](https://eips.ethereum.org/EIPS/eip-165), o ERC-1155 suporta hooks de recebimento apenas para contratos inteligentes. A função de hook deve retornar um valor mágico predefinido de 4 bytes que é dado como: ```solidity bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)")) @@ -121,26 +121,26 @@ bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],byt Quando o contrato de recebimento devolve este valor, assume-se que o contrato aceita a transferência e sabe como lidar com os tokens ERC-1155. Ótimo, nenhum token bloqueados em um contrato! -### Suporte para NFTs {#nft-support} +### Suporte a NFT {#nft-support} -Quando a oferta é apenas uma, o token é essencialmente um token não-fungível (NFT, pela sigla em inglês) E como é padrão para o ERC-721, você pode definir um URL de metadados. Esse URL pode ser lido e modificado pelos clientes; veja [aqui](https://eips.ethereum.org/EIPS/eip-1155#metadata). +Quando a oferta é apenas uma, o token é essencialmente um token não-fungível (NFT, pela sigla em inglês) E como é padrão para o ERC-721, você pode definir um URL de metadados. A URL pode ser lida e modificada pelos clientes, veja [aqui](https://eips.ethereum.org/EIPS/eip-1155#metadata). ### Regra de transferência segura {#safe-transfer-rule} Já abordamos algumas regras de transferência segura nas explicações anteriores. Mas vamos analisar as regras mais importantes: -1. O chamador deve ser aprovado para gastar os tokens para o endereço `_from` ou o chamador deve ser igual ao endereço `_from`. +1. O chamador deve ser aprovado para gastar os tokens do endereço `_from` ou o chamador deve ser igual a `_from`. 2. A chamada de transferência deve ser revertida caso - 1. o enderaço `_to` seja 0. - 2. o comprimento dos `_ids` não seja o mesmo que o comprimento dos `_values`. - 3. qualquer um do saldos dos titulares dos tokens em `_ids` seja menor que as respectivas quantidades em `_values` enviados para o destinatário. + 1. O endereço `_to` é 0. + 2. O comprimento de `_ids` não é o mesmo que o comprimento de `_values`. + 3. qualquer um dos saldos dos detentores de tokens em `_ids` for menor que as respectivas quantias em `_values` enviadas ao destinatário. 4. ocorra qualquer outro erro. -_Nota_: Todas as funções por lotes, incluindo o hook, também existem como versões sem lotes. Isto é feito para fins de eficiência do gás, já que é provável que a transferência de apenas um ativo continue sendo a maneira habitualmente mais utilizada. Por simplificar as explicações, as deixamos de lado, incluindo as regras de transferência segura. Os nomes são idênticos, basta eliminar a palavra "lote". +_Nota_: Todas as funções em lote, incluindo o hook, também existem como versões sem lote. Isto é feito para fins de eficiência do gás, já que é provável que a transferência de apenas um ativo continue sendo a maneira habitualmente mais utilizada. Por simplificar as explicações, as deixamos de lado, incluindo as regras de transferência segura. Os nomes são idênticos, basta eliminar a palavra "lote". ## Leitura adicional {#further-reading} -- [EIP-1155: Padrão Multi-Token](https://eips.ethereum.org/EIPS/eip-1155) -- [ERC-1155: Documentos da Openzeppelin](https://docs.openzeppelin.com/contracts/3.x/erc1155) -- [ERC-1155: Repositório no GitHub](https://github.com/enjin/erc-1155) -- [NFT API do Alchemy](https://docs.alchemy.com/alchemy/enhanced-apis/nft-api) +- [EIP-1155: Padrão de múltiplos tokens](https://eips.ethereum.org/EIPS/eip-1155) +- [ERC-1155: Documentos da OpenZeppelin](https://docs.openzeppelin.com/contracts/5.x/erc1155) +- [ERC-1155: Repositório do GitHub](https://github.com/enjin/erc-1155) +- [API de NFT da Alchemy](https://www.alchemy.com/docs/reference/nft-api-quickstart) diff --git a/public/content/translations/pt-br/developers/docs/standards/tokens/erc-1363/index.md b/public/content/translations/pt-br/developers/docs/standards/tokens/erc-1363/index.md new file mode 100644 index 00000000000..e99a0189080 --- /dev/null +++ b/public/content/translations/pt-br/developers/docs/standards/tokens/erc-1363/index.md @@ -0,0 +1,213 @@ +--- +title: "Padrão de Token Pagável ERC-1363" +description: "O ERC-1363 é uma interface de extensão para tokens ERC-20 que suporta a execução de lógica personalizada em um contrato receptor após transferências, ou em um contrato gastador após aprovações, tudo em uma única transação." +lang: pt-br +--- + +## Introdução {#introduction} + +### O que é ERC-1363? {#what-is-erc1363} + +O ERC-1363 é uma interface de extensão para tokens ERC-20 que suporta a execução de lógica personalizada em um contrato receptor após transferências, ou em um contrato gastador após aprovações, tudo em uma única transação. + +### Diferenças do ERC-20 {#erc20-differences} + +As operações padrão do ERC-20, como `transfer`, `transferFrom` e `approve`, não permitem a execução de código no contrato receptor ou gastador sem uma transação separada. +Isso introduz complexidade no desenvolvimento de UI e atrito na adoção, porque os usuários devem esperar a primeira transação ser executada para então enviar a segunda. +Eles também devem pagar GÁS duas vezes. + +O ERC-1363 torna os tokens fungíveis capazes de realizar ações com mais facilidade e funcionar sem o uso de qualquer ouvinte off-chain. +Ele permite fazer um callback em um contrato receptor ou gastador, após uma transferência ou aprovação, em uma única transação. + +## Pré-requisitos {#prerequisites} + +Para entender melhor esta página, recomendamos que primeiro leia sobre: + +- [Padrões de token](/developers/docs/standards/tokens/) +- [ERC-20](/developers/docs/standards/tokens/erc-20/) + +## Body {#body} + +O ERC-1363 introduz uma API padrão para que os tokens ERC-20 interajam com contratos inteligentes após `transfer`, `transferFrom` ou `approve`. + +Este padrão fornece a funcionalidade básica para transferir tokens, bem como permite que os tokens sejam aprovados para que possam ser gastos por um terceiro on-chain, e em seguida, fazer um callback no contrato receptor ou gastador. + +Existem muitos usos propostos para contratos inteligentes que podem aceitar callbacks de ERC-20. + +Alguns exemplos são: + +- **Vendas coletivas**: os tokens enviados acionam a alocação instantânea de recompensas. +- **Serviços**: o pagamento ativa o acesso ao serviço em uma única etapa. +- **Faturas**: os tokens liquidam faturas automaticamente. +- **Assinaturas**: a aprovação da taxa anual ativa a assinatura com o pagamento do primeiro mês. + +Por essas razões, ele foi originalmente nomeado **"Payable Token"**. + +O comportamento de callback expande ainda mais sua utilidade, permitindo interações perfeitas como: + +- **Staking**: os tokens transferidos acionam o bloqueio automático em um contrato de staking. +- **Votação**: os tokens recebidos registram votos em um sistema de governança. +- **Troca**: aprovações de token ativam a lógica de troca em uma única etapa. + +Os tokens ERC-1363 podem ser usados para utilidades específicas em todos os casos que exigem a execução de um callback após o recebimento de uma transferência ou aprovação. +O ERC-1363 também é útil para evitar a perda ou o bloqueio de tokens em contratos inteligentes, verificando a capacidade do destinatário de lidar com os tokens. + +Diferentemente de outras propostas de extensão do ERC-20, o ERC-1363 não substitui os métodos `transfer` e `transferFrom` do ERC-20 e define os IDs das interfaces a serem implementadas, mantendo a retrocompatibilidade com o ERC-20. + +De [EIP-1363](https://eips.ethereum.org/EIPS/eip-1363): + +### Métodos {#methods} + +Os contratos inteligentes que implementam o padrão ERC-1363 **DEVEM** implementar todas as funções na interface `ERC1363`, bem como as interfaces `ERC20` e `ERC165`. + +```solidity +pragma solidity ^0.8.0; + +/** + * @title ERC1363 + * @dev Uma interface de extensão para tokens ERC-20 que suporta a execução de código em um contrato receptor + * após `transfer` ou `transferFrom`, ou código em um contrato gastador após `approve`, em uma única transação. + */ +interface ERC1363 is ERC20, ERC165 { + /* + * NOTA: o identificador ERC-165 para esta interface é 0xb0202a11. + * 0xb0202a11 === + * bytes4(keccak256('transferAndCall(address,uint256)')) ^ + * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ + * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ + * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ + * bytes4(keccak256('approveAndCall(address,uint256)')) ^ + * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) + */ + + /** + * @dev Move uma quantidade de tokens de `value` da conta do chamador para `to` + * e então chama `ERC1363Receiver::onTransferReceived` em `to`. + * @param to O endereço para o qual os tokens estão sendo transferidos. + * @param value A quantidade de tokens a serem transferidos. + * @return Um valor booleano que indica que a operação foi bem-sucedida, a menos que uma exceção seja lançada. + */ + function transferAndCall(address to, uint256 value) external returns (bool); + + /** + * @dev Move uma quantidade de tokens de `value` da conta do chamador para `to` + * e então chama `ERC1363Receiver::onTransferReceived` em `to`. + * @param to O endereço para o qual os tokens estão sendo transferidos. + * @param value A quantidade de tokens a serem transferidos. + * @param data Dados adicionais sem formato especificado, enviados na chamada para `to`. + * @return Um valor booleano que indica que a operação foi bem-sucedida, a menos que uma exceção seja lançada. + */ + function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); + + /** + * @dev Move uma quantidade de tokens de `value` de `from` para `to` usando o mecanismo de permissão (allowance) + * e então chama `ERC1363Receiver::onTransferReceived` em `to`. + * @param from O endereço do qual os tokens são enviados. + * @param to O endereço para o qual os tokens estão sendo transferidos. + * @param value A quantidade de tokens a serem transferidos. + * @return Um valor booleano que indica que a operação foi bem-sucedida, a menos que uma exceção seja lançada. + */ + function transferFromAndCall(address from, address to, uint256 value) external returns (bool); + + /** + * @dev Move uma quantidade de tokens de `value` de `from` para `to` usando o mecanismo de permissão (allowance) + * e então chama `ERC1363Receiver::onTransferReceived` em `to`. + * @param from O endereço do qual os tokens são enviados. + * @param to O endereço para o qual os tokens estão sendo transferidos. + * @param value A quantidade de tokens a serem transferidos. + * @param data Dados adicionais sem formato especificado, enviados na chamada para `to`. + * @return Um valor booleano que indica que a operação foi bem-sucedida, a menos que uma exceção seja lançada. + */ + function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); + + /** + * @dev Define uma quantidade de tokens de `value` como a permissão (allowance) de `spender` sobre os tokens do chamador + * e então chama `ERC1363Spender::onApprovalReceived` em `spender`. + * @param spender O endereço que gastará os fundos. + * @param value A quantidade de tokens a serem gastos. + * @return Um valor booleano que indica que a operação foi bem-sucedida, a menos que uma exceção seja lançada. + */ + function approveAndCall(address spender, uint256 value) external returns (bool); + + /** + * @dev Define uma quantidade de tokens de `value` como a permissão (allowance) de `spender` sobre os tokens do chamador + * e então chama `ERC1363Spender::onApprovalReceived` em `spender`. + * @param spender O endereço que gastará os fundos. + * @param value A quantidade de tokens a serem gastos. + * @param data Dados adicionais sem formato especificado, enviados na chamada para `spender`. + * @return Um valor booleano que indica que a operação foi bem-sucedida, a menos que uma exceção seja lançada. + */ + function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); +} + +interface ERC20 { + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); + function transfer(address to, uint256 value) external returns (bool); + function transferFrom(address from, address to, uint256 value) external returns (bool); + function approve(address spender, uint256 value) external returns (bool); + function totalSupply() external view returns (uint256); + function balanceOf(address account) external view returns (uint256); + function allowance(address owner, address spender) external view returns (uint256); +} + +interface ERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} +``` + +Um contrato inteligente que queira aceitar tokens ERC-1363 via `transferAndCall` ou `transferFromAndCall` **DEVE** implementar a interface `ERC1363Receiver`: + +```solidity +/** + * @title ERC1363Receiver + * @dev Interface para qualquer contrato que queira suportar `transferAndCall` ou `transferFromAndCall` de contratos de token ERC-1363. + */ +interface ERC1363Receiver { + /** + * @dev Sempre que tokens ERC-1363 são transferidos para este contrato via `ERC1363::transferAndCall` ou `ERC1363::transferFromAndCall` + * por `operator` de `from`, esta função é chamada. + * + * NOTA: Para aceitar a transferência, esta função deve retornar + * `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))` + * (ou seja, 0x88a7ca5c, ou seu próprio seletor de função). + * + * @param operator O endereço que chamou a função `transferAndCall` ou `transferFromAndCall`. + * @param from O endereço do qual os tokens são transferidos. + * @param value A quantidade de tokens transferidos. + * @param data Dados adicionais sem formato especificado. + * @return `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))` se a transferência for permitida, a menos que uma exceção seja lançada. + */ + function onTransferReceived(address operator, address from, uint256 value, bytes calldata data) external returns (bytes4); +} +``` + +Um contrato inteligente que queira aceitar tokens ERC-1363 via `approveAndCall` **DEVE** implementar a interface `ERC1363Spender`: + +```solidity +/** + * @title ERC1363Spender + * @dev Interface para qualquer contrato que queira dar suporte a `approveAndCall` de contratos de token ERC-1363. + */ +interface ERC1363Spender { + /** + * @dev Sempre que o `owner` (dono) de um token ERC-1363 aprova este contrato via `ERC1363::approveAndCall` + * para gastar seus tokens, esta função é chamada. + * + * NOTA: Para aceitar a aprovação, esta função deve retornar + * `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))` + * (ou seja, 0x7b04a2d0, ou seu próprio seletor de função). + * + * @param owner O endereço que chamou a função `approveAndCall` e que anteriormente possuía os tokens. + * @param value A quantidade de tokens a ser gasta. + * @param data Dados adicionais sem formato especificado. + * @return `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))` se a aprovação for permitida, a menos que uma exceção seja lançada. + */ + function onApprovalReceived(address owner, uint256 value, bytes calldata data) external returns (bytes4); +} +``` + +## Leitura adicional {#further-reading} + +- [ERC-1363: Padrão de Token Pagável](https://eips.ethereum.org/EIPS/eip-1363) +- [ERC-1363: Repositório no GitHub](https://github.com/vittominacori/erc1363-payable-token) diff --git a/public/content/translations/pt-br/developers/docs/standards/tokens/erc-20/index.md b/public/content/translations/pt-br/developers/docs/standards/tokens/erc-20/index.md index a48379944e5..3ebb162e486 100644 --- a/public/content/translations/pt-br/developers/docs/standards/tokens/erc-20/index.md +++ b/public/content/translations/pt-br/developers/docs/standards/tokens/erc-20/index.md @@ -1,6 +1,6 @@ --- -title: Padrão de token ERC-20 -description: Token +title: "Padrão de token ERC-20" +description: "Aprenda sobre ERC-20, o padrão para tokens fungiveis em Ethereum que permite aplicações de token interoperáveis." lang: pt-br --- @@ -12,27 +12,28 @@ Um token podem representar praticamente qualquer coisa em Ethereum: - pontos de reputação em uma plataforma online - habilidades de um personagem em um jogo -- bilhetes de loteria - ativos financeiros, como a ação em uma empresa - uma moeda fiduciária, como USD - 28,3 gr de ouro - e mais... -Uma característica tão poderosa do Ethereum deve ser tratada por um padrão robusto, certo? É aí que o ERC-20 entra! Este padrão permite que desenvolvedores criem aplicativos de token que são interoperáveis com outros produtos e serviços. +Uma característica tão poderosa do Ethereum deve ser tratada por um padrão robusto, certo? É aí que o ERC-20 entra! Este padrão permite que desenvolvedores criem aplicativos de token que são interoperáveis com outros produtos e serviços. O padrão ERC-20 também é usado para fornecer funcionalidade adicional ao [ether](/glossary/#ether). **O que é ERC-20?** -O ERC-20 introduz um padrão para os tokens fungíveis, ou seja, eles têm uma propriedade que faz com que cada token tenha exatamente o mesmo de outro token (em termos de tipo e valor). Por exemplo, um token ERC-20 age como o ETH, significando que 1 token é e será sempre igual a todos os outros tokens. +O ERC-20 introduz um padrão para os tokens fungíveis, ou seja, eles têm uma propriedade que faz com que cada token tenha exatamente o mesmo de outro token (em termos de tipo e valor). Por exemplo, um token ERC-20 age como o ETH, significando que 1 token +é e será sempre igual a todos os outros tokens. ## Pré-requisitos {#prerequisites} - [Contas](/developers/docs/accounts) -- [Contratos Inteligentes](/developers/docs/smart-contracts/) +- [Contratos inteligentes](/developers/docs/smart-contracts/) - [Padrões de token](/developers/docs/standards/tokens/) -## Apresentação {#body} +## Body {#body} -O ERC-20 (Ethereum Request for Comments 20), proposto por Fabian Vogelsteller em novembro de 2015, é um padrão de token que implementa uma API para tokens em contratos inteligentes. +O ERC-20 (Ethereum Request for Comments 20), proposto por Fabian Vogelsteller em novembro de 2015, é um padrão de token que +implementa uma API para tokens em contratos inteligentes. Exemplo de funcionalidades que o ERC-20 fornece: @@ -68,11 +69,13 @@ event Approval(address indexed _owner, address indexed _spender, uint256 _value) ### Exemplos {#web3py-example} -Vejamos por que um padrão é importante e como ele simplifica o controle de qualquer contrato de token ERC-20 no Ethereum. Só precisamos da Interface Binária de Aplicativos (ABI, pela sigla em inglês) do contrato para criar uma interface com qualquer token ERC-20. Como você pode ver abaixo, usaremos uma ABI simplificada, para torná-la um exemplo de fácil compreensão. +Vejamos por que um padrão é importante e como ele simplifica o controle de qualquer contrato de token ERC-20 no Ethereum. +Só precisamos da Interface Binária de Aplicativos (ABI, pela sigla em inglês) do contrato para criar uma interface com qualquer token ERC-20. Como você pode +ver abaixo, usaremos uma ABI simplificada, para torná-la um exemplo de fácil compreensão. -#### Exemplo para a Web3.py {#web3py-example} +#### Exemplo de Web3.py {#web3py-example} -Primeiro, certifique-se de que você instalou a biblioteca [Web3.py](https://web3py.readthedocs.io/en/stable/quickstart.html#installation) do Python: +Primeiro, certifique-se de que você instalou a biblioteca Python [Web3.py](https://web3py.readthedocs.io/en/stable/quickstart.html#installation): ``` pip install web3 @@ -85,12 +88,12 @@ from web3 import Web3 w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com")) dai_token_addr = "0x6B175474E89094C44Da98b954EedeAC495271d0F" # DAI -weth_token_addr = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" # Wrapped ether (WETH) +weth_token_addr = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" # Ether encapsulado (WETH) acc_address = "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11" # Uniswap V2: DAI 2 -# This is a simplified Contract Application Binary Interface (ABI) of an ERC-20 Token Contract. -# It will expose only the methods: balanceOf(address), decimals(), symbol() and totalSupply() +# Esta é uma Interface Binária de Aplicação (ABI) de Contrato simplificada de um Contrato de Token ERC-20. +# Ela irá expor apenas os métodos: balanceOf(address), decimals(), symbol() e totalSupply() simplified_abi = [ { 'inputs': [{'internalType': 'address', 'name': 'account', 'type': 'address'}], @@ -126,8 +129,8 @@ addr_balance = dai_contract.functions.balanceOf(acc_address).call() / 10**decima # DAI print("===== %s =====" % symbol) -print("Total Supply:", totalSupply) -print("Addr Balance:", addr_balance) +print("Fornecimento Total:", totalSupply) +print("Saldo do Endereço:", addr_balance) weth_contract = w3.eth.contract(address=w3.to_checksum_address(weth_token_addr), abi=simplified_abi) symbol = weth_contract.functions.symbol().call() @@ -137,13 +140,50 @@ addr_balance = weth_contract.functions.balanceOf(acc_address).call() / 10**decim # WETH print("===== %s =====" % symbol) -print("Total Supply:", totalSupply) -print("Addr Balance:", addr_balance) +print("Fornecimento Total:", totalSupply) +print("Saldo do Endereço:", addr_balance) ``` +## Problemas conhecidos {#erc20-issues} + +### Problema de recebimento de token ERC-20 {#reception-issue} + +**Em 20/06/2024, pelo menos US$ 83.656.418 em tokens ERC-20 foram perdidos devido a esse problema. Observe que uma implementação ERC-20 pura está propensa a esse problema, a menos que você implemente um conjunto de restrições adicionais além do padrão, conforme listado abaixo.** + +Quando tokens ERC-20 são enviados para um contrato inteligente que não foi projetado para lidar com tokens ERC-20, esses tokens podem ser permanentemente perdidos. Isso acontece porque o contrato receptor não possui a funcionalidade para reconhecer ou responder aos tokens recebidos, e não há um mecanismo no padrão ERC-20 para notificar o contrato receptor sobre os tokens recebidos. As principais formas pelas quais esse problema se manifesta são: + +1. Mecanismo de transferência de tokens + +- Os tokens ERC-20 são transferidos usando as funções transfer ou transferFrom + - Quando um usuário envia tokens para um endereço de contrato usando essas funções, os tokens são transferidos independentemente de o contrato receptor estar ou não projetado para manipulá-los + +2. Falta de notificação + - O contrato receptor não recebe uma notificação ou retorno de chamada de que os tokens foram enviados a ele + - Se o contrato de recebimento não tiver um mecanismo para lidar com tokens (por exemplo, uma função de fallback ou uma função dedicada para gerenciar a recepção de tokens), os tokens ficarão efetivamente presos no endereço do contrato +3. Sem manuseio integrado + - O padrão ERC-20 não inclui uma função obrigatória para receber contratos a serem implementados, levando a uma situação em que muitos contratos não conseguem gerenciar os tokens recebidos adequadamente + +**Possíveis Soluções** + +Embora não seja possível evitar completamente esse problema com o ERC-20, existem métodos que permitiriam reduzir significativamente a possibilidade de perda de tokens para o usuário final: + +- O problema mais comum é quando um usuário envia tokens para o próprio endereço do contrato do token (por exemplo, USDT depositado no endereço do contrato do token USDT). É recomendável restringir a função `transfer(..)` para reverter tais tentativas de transferência. Considere adicionar a verificação `require(_to != address(this));` na implementação da função `transfer(..)`. +- A função `transfer(..)` em geral não foi projetada para depositar tokens em contratos. O padrão `approve(..) & transferFrom(..)` é usado, em vez disso, para depositar tokens ERC-20 em contratos. É possível restringir a função de transferência para não permitir o depósito de tokens em quaisquer contratos com ela, no entanto, isso pode quebrar a compatibilidade com contratos que assumem que os tokens podem ser depositados em contratos com a função `trasnfer(..)` (por exemplo, pools de liquidez Uniswap). +- Sempre presuma que tokens ERC-20 podem acabar no seu contrato, mesmo que seu contrato nunca deva recebê-los. Não há como evitar ou rejeitar depósitos acidentais por parte dos destinatários. É recomendável implementar uma função que permita extrair tokens ERC-20 depositados acidentalmente. +- Considere usar padrões de token alternativos. + +Alguns padrões alternativos surgiram desse problema, como o [ERC-223](/developers/docs/standards/tokens/erc-223) ou o [ERC-1363](/developers/docs/standards/tokens/erc-1363). + ## Leitura adicional {#further-reading} -- [EIP-20: Padrão de token ERC-20](https://eips.ethereum.org/EIPS/eip-20) -- [OpenZeppelin: Tokens](https://docs.openzeppelin.com/contracts/3.x/tokens#ERC20) -- [OpenZeppelin: Implementação ERC-20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol) -- [Alchemy — Guia para os Tokens ERC20 do Solidity](https://www.alchemy.com/overviews/erc20-solidity) +- [EIP-20: Padrão de Token ERC-20](https://eips.ethereum.org/EIPS/eip-20) +- [OpenZeppelin - Tokens](https://docs.openzeppelin.com/contracts/3.x/tokens#ERC20) +- [OpenZeppelin - Implementação do ERC-20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol) +- [Alchemy - Guia para Tokens ERC20 em Solidity](https://www.alchemy.com/overviews/erc20-solidity) + +## Outros padrões de tokens fungíveis {#fungible-token-standards} + +- [ERC-223](/developers/docs/standards/tokens/erc-223) +- [ERC-1363](/developers/docs/standards/tokens/erc-1363) +- [ERC-777](/developers/docs/standards/tokens/erc-777) +- [ERC-4626 - Vaults tokenizados](/developers/docs/standards/tokens/erc-4626) diff --git a/public/content/translations/pt-br/developers/docs/standards/tokens/erc-223/index.md b/public/content/translations/pt-br/developers/docs/standards/tokens/erc-223/index.md new file mode 100644 index 00000000000..1c453a4d1a6 --- /dev/null +++ b/public/content/translations/pt-br/developers/docs/standards/tokens/erc-223/index.md @@ -0,0 +1,198 @@ +--- +title: "Padrão de token ERC-223" +description: "Uma visão geral do padrão de token fungível ERC-223, como ele funciona e uma comparação com o ERC-20." +lang: pt-br +--- + +## Introdução {#introduction} + +### O que é ERC-223? {#what-is-erc223} + +O ERC-223 é um padrão para tokens fungíveis, semelhante ao padrão ERC-20. A principal diferença é que o ERC-223 define não apenas a API do token, mas também a lógica para transferir tokens do remetente para o destinatário. Ele introduz um modelo de comunicação que permite que transferências de tokens sejam manipuladas pelo lado do destinatário. + +### Diferenças do ERC-20 {#erc20-differences} + +O ERC-223 aborda algumas limitações do ERC-20 e introduz um novo método de interação entre o contrato de token e um contrato que pode receber os tokens. Há poucas coisas que são possíveis com ERC-223, mas não com ERC-20: + +- Tratamento de transferência de tokens no lado do destinatário: os destinatários podem detectar que um token ERC-223 está sendo depositado. +- Rejeição de tokens enviados incorretamente: se um usuário enviar tokens ERC-223 para um contrato que não deveria receber tokens, o contrato poderá rejeitar a transação, evitando a perda de tokens. +- Metadados em transferências: tokens ERC-223 podem incluir metadados, permitindo que informações arbitrárias sejam anexadas às transações de tokens. + +## Pré-requisitos {#prerequisites} + +- [Contas](/developers/docs/accounts) +- [Contratos inteligentes](/developers/docs/smart-contracts/) +- [Padrões de token](/developers/docs/standards/tokens/) +- [ERC-20](/developers/docs/standards/tokens/erc-20/) + +## Body {#body} + +ERC-223 é um padrão de token que implementa uma API para tokens dentro de contratos inteligentes. Ele também declara uma API para contratos que devem receber tokens ERC-223. Contratos que não suportam a API do Receptor ERC-223 não podem receber tokens ERC-223, evitando erros do usuário. + +Se um contrato inteligente implementar os seguintes métodos e eventos, ele poderá ser chamado de contrato de token compatível com ERC-223. Uma vez implantado, ele +será responsável por manter o controle dos tokens criados no Ethereum. + +O contrato não é obrigado a ter apenas essas funções e um desenvolvedor pode adicionar qualquer outro recurso de diferentes padrões de token a este contrato. Por exemplo, as funções `approve` e `transferFrom` não fazem parte do padrão ERC-223, mas essas funções podem ser implementadas caso seja necessário. + +De [EIP-223](https://eips.ethereum.org/EIPS/eip-223): + +### Métodos {#methods} + +O token ERC-223 deve implementar os seguintes métodos: + +```solidity +function name() public view returns (string) +function symbol() public view returns (string) +function decimals() public view returns (uint8) +function totalSupply() public view returns (uint256) +function balanceOf(address _owner) public view returns (uint256 balance) +function transfer(address _to, uint256 _value) public returns (bool success) +function transfer(address _to, uint256 _value, bytes calldata _data) public returns (bool success) +``` + +Um contrato que deve receber tokens ERC-223 deve implementar o seguinte método: + +```solidity +function tokenReceived(address _from, uint _value, bytes calldata _data) +``` + +Se os tokens ERC-223 forem enviados para um contrato que não implementa a função `tokenReceived(..)`, a transferência deverá falhar e os tokens não deverão ser movidos do saldo do remetente. + +### Eventos {#events} + +```solidity +event Transfer(address indexed _from, address indexed _to, uint256 _value, bytes calldata _data) +``` + +### Exemplos {#examples} + +A API do token ERC-223 é semelhante à do ERC-20, portanto, do ponto de vista do desenvolvimento da interface do usuário, não há diferença. A única exceção aqui é que os tokens ERC-223 não podem ter as funções `approve` + `transferFrom`, pois elas são opcionais para este padrão. + +#### Exemplos de Solidity {#solidity-example} + +O exemplo a seguir ilustra como um contrato básico de token ERC-223 opera: + +```solidity +pragma solidity ^0.8.19; +abstract contract IERC223Recipient { + function tokenReceived(address _from, uint _value, bytes memory _data) public virtual; +} +contract VeryBasicERC223Token { + event Transfer(address indexed from, address indexed to, uint value, bytes data); + string private _name; + string private _symbol; + uint8 private _decimals; + uint256 private _totalSupply; + mapping(address => uint256) private balances; + function name() public view returns (string memory) { return _name; } + function symbol() public view returns (string memory) {return _symbol; } + function decimals() public view returns (uint8) { return _decimals; } + function totalSupply() public view returns (uint256) { return _totalSupply; } + function balanceOf(address _owner) public view returns (uint256) { return balances[_owner]; } + function isContract(address account) internal view returns (bool) { + uint256 size; + assembly { size := extcodesize(account) } + return size > 0; + } + function transfer(address _to, uint _value, bytes calldata _data) public returns (bool success){ + balances[msg.sender] = balances[msg.sender] - _value; + balances[_to] = balances[_to] + _value; + if(isContract(_to)) { + IERC223Recipient(_to).tokenReceived(msg.sender, _value, _data); + } + emit Transfer(msg.sender, _to, _value, _data); + return true; + } + function transfer(address _to, uint _value) public returns (bool success){ + bytes memory _empty = hex"00000000"; + balances[msg.sender] = balances[msg.sender] - _value; + balances[_to] = balances[_to] + _value; + if(isContract(_to)) { + IERC223Recipient(_to).tokenReceived(msg.sender, _value, _empty); + } + emit Transfer(msg.sender, _to, _value, _empty); + return true; + } +} +``` + +Agora queremos que outro contrato aceite depósitos de `tokenA`, assumindo que o tokenA é um token ERC-223. O contrato deve aceitar apenas o tokenA e rejeitar quaisquer outros tokens. Quando o contrato recebe o tokenA, ele deve emitir um evento `Deposit()` e aumentar o valor da variável interna `deposits`. + +Aqui está o código: + +```solidity +contract RecipientContract is IERC223Recipient { + event Deposit(address whoSentTheTokens); + uint256 deposits = 0; + address tokenA; // The only token that we want to accept. + function tokenReceived(address _from, uint _value, bytes memory _data) public override + { + // It is important to understand that within this function + // msg.sender is the address of a token that is being received, + // msg.value is always 0 as the token contract does not own or send ether in most cases, + // _from is the sender of the token transfer, + // _value is the amount of tokens that was deposited. + require(msg.sender == tokenA); + deposits += _value; + emit Deposit(_from); + } +} +``` + +## Perguntas mais frequentes {#faq} + +### O que acontecerá se enviarmos algum tokenB para o contrato? {#sending-tokens} + +A transação falhará e a transferência de tokens não acontecerá. Os tokens serão devolvidos ao endereço do remetente. + +### Como podemos fazer um depósito neste contrato? {#contract-deposits} + +Chame a função `transfer(address,uint256)` ou `transfer(address,uint256,bytes)` do token ERC-223, especificando o endereço do `RecipientContract`. + +### O que acontecerá se transferirmos um token ERC-20 para este contrato? {#erc-20-transfers} + +Se um token ERC-20 for enviado para o `RecipientContract`, os tokens serão transferidos, mas a transferência não será reconhecida (nenhum evento `Deposit()` será disparado e o valor dos depósitos não será alterado). Depósitos indesejados de ERC-20 não podem ser filtrados ou evitados. + +### E se quisermos executar alguma função após a conclusão do depósito do token? {#function-execution} + +Há várias maneiras de fazer isso. Neste exemplo, seguiremos o método que torna as transferências ERC-223 idênticas às transferências de ether: + +```solidity +contract RecipientContract is IERC223Recipient { + event Foo(); + event Bar(uint256 someNumber); + address tokenA; // O único token que queremos aceitar. + function tokenReceived(address _from, uint _value, bytes memory _data) public override + { + require(msg.sender == tokenA); + address(this).call(_data); // Manipular a transação recebida e executar uma chamada de função subsequente. + } + function foo() public + { + emit Foo(); + } + function bar(uint256 _someNumber) public + { + emit Bar(_someNumber); + } +} +``` + +Quando o `RecipientContract` receber token de acordo à ERC-223 o contrato executará uma função codificada como parâmetro `_data` da transação do token, idêntico a como transações ether codificam chamadas de função como `data` da transação. Leia [o campo de dados](/developers/docs/transactions/#the-data-field) para obter mais informações. + +No exemplo acima, um token ERC-223 deve ser transferido para o endereço do `RecipientContract` com a função `transfer(address,uin256,bytes calldata _data)`. Se o parâmetro de dados for `0xc2985578` (a assinatura de uma função `foo()`), então a função foo() será invocada após o depósito do token ser recebido e o evento Foo() será disparado. + +Os parâmetros também podem ser codificados nos `data` da transferência do token, por exemplo, podemos chamar a função bar() com o valor 12345 para `_someNumber`. Neste caso, o `data` deve ser `0x0423a13200000000000000000000000000000000000000000000000000000000000000000000004d2` onde `0x0423a132` é a assinatura da função `bar(uint256)` e `000000000000000000000000000000000000000000000000000000000000000000000004d2` é 12345 como uint256. + +## Limitações {#limitations} + +Embora o ERC-223 aborde vários problemas encontrados no padrão ERC-20, ele não está isento de limitações: + +- Adoção e compatibilidade: o ERC-223 ainda não foi amplamente adotado, o que pode limitar sua compatibilidade com ferramentas e plataformas existentes. +- Compatibilidade com versões anteriores: O ERC-223 não é compatível com versões anteriores do ERC-20, o que significa que os contratos e ferramentas ERC-20 existentes não funcionarão com tokens ERC-223 sem modificações. +- Custos de gás: as verificações e funcionalidades adicionais nas transferências ERC-223 podem resultar em custos de gás mais altos em comparação às transações ERC-20. + +## Leitura adicional {#further-reading} + +- [EIP-223: Padrão de Token ERC-223](https://eips.ethereum.org/EIPS/eip-223) +- [Proposta inicial ERC-223](https://github.com/ethereum/eips/issues/223) diff --git a/public/content/translations/pt-br/developers/docs/standards/tokens/erc-4626/index.md b/public/content/translations/pt-br/developers/docs/standards/tokens/erc-4626/index.md index 371ffca8180..bf2786d15bb 100644 --- a/public/content/translations/pt-br/developers/docs/standards/tokens/erc-4626/index.md +++ b/public/content/translations/pt-br/developers/docs/standards/tokens/erc-4626/index.md @@ -1,6 +1,6 @@ --- -title: Padrão de cofre tokenizado ERC-4626 -description: Um padrão para os cofres de rendimento. +title: "Padrão de cofre tokenizado ERC-4626" +description: "Um padrão para os cofres de rendimento." lang: pt-br --- @@ -14,20 +14,36 @@ Mercados de empréstimo, agregadores e tokens intrinsecamente de rendimento ajud O ERC-4626 nos cofres de rendimento reduzirá o esforço de integração e desbloqueará o acesso a rendimentos em várias aplicações, com pouco esforço especializado dos desenvolvedores, criando padrões de implementação mais consistentes e robustos. -O token ERC-4626 é descrito em mais detalhes em [EIP-4626](https://eips.ethereum.org/EIPS/eip-4626). +O token ERC-4626 é descrito por completo em [EIP-4626](https://eips.ethereum.org/EIPS/eip-4626). + +**Extensão assíncrona de cofre (ERC-7540)** + +O ERC-4626 é otimizado para depósitos e resgates atômicos até um limite. Se o limite for atingido, nenhum novo depósito ou resgate poderá ser enviado. Essa limitação não funciona bem para qualquer sistema de contrato inteligente com ações assíncronas ou atrasos como pré-requisito para interagir com o Cofre (por exemplo, protocolos de ativos do mundo real, protocolos de empréstimos subcolateralizados, protocolos de empréstimos cross-chain, tokens de staking líquido ou módulos de segurança de seguro). + +O ERC-7540 amplia a utilidade dos cofres ERC-4626 para casos de uso assíncronos. A interface de Cofre existente (`deposit`/`withdraw`/`mint`/`redeem`) é totalmente utilizada para reivindicar Solicitações assíncronas. + +A extensão ERC-7540 é descrita por completo em [ERC-7540](https://eips.ethereum.org/EIPS/eip-7540). + +**Extensão de cofre multiativo (ERC-7575)** + +Um caso de uso ausente que não é suportado pelo ERC-4626 são cofres que possuem múltiplos ativos ou pontos de entrada, como tokens de provedor de liquidez (LP tokens). Esses casos geralmente são difíceis de manejar ou não compatíveis devido ao requisito de que o ERC-4626 seja, por si só, um ERC-20. + +O ERC-7575 adiciona suporte a cofres com múltiplos ativos ao externalizar a implementação do token ERC-20 da implementação do ERC-4626. + +A extensão ERC-7575 é descrita por completo em [ERC-7575](https://eips.ethereum.org/EIPS/eip-7575). ## Pré-requisitos {#prerequisites} -Para entender melhor esta página, recomendamos que você leia primeiro sobre [padrões de tokens](/developers/docs/standards/tokens/) e [ERC-20](/developers/docs/standards/tokens/erc-20/). +Para entender melhor esta página, recomendamos que você leia primeiro sobre [padrões de token](/developers/docs/standards/tokens/) e [ERC-20](/developers/docs/standards/tokens/erc-20/). -## Funções e características do ERC-4626: {#body} +## Funções e recursos do ERC-4626: {#body} ### Métodos {#methods} #### asset {#asset} ```solidity -function asset() public view returns (address) +function asset() public view returns (address assetTokenAddress) ``` Esta função retorna o endereço do token subjacente usado para o cofre para contabilidade, depósito, retirada. @@ -46,7 +62,7 @@ Esta função retorna a quantidade total de ativos subjacentes mantidos pelo cof function convertToShares(uint256 assets) public view returns (uint256 shares) ``` -Esta função retorna a quantidade de `shares` que seriam intercambiadas pelo cofre pela quantidade de `assets` fornecidos. +Esta função retorna a quantidade de `shares` que seriam trocadas pelo cofre pela quantidade de `assets` fornecida. #### convertToAssets {#convertoassets} @@ -54,92 +70,92 @@ Esta função retorna a quantidade de `shares` que seriam intercambiadas pelo co function convertToAssets(uint256 shares) public view returns (uint256 assets) ``` -Esta função retorna a quantidade de `assets` que seriam intercambiadas pelo cofre pela quantidade de `shares` fornecidos. +Esta função retorna a quantidade de `assets` que seriam trocados pelo cofre pela quantidade de `shares` fornecida. #### maxDeposit {#maxdeposit} ```solidity -function maxDeposit(address receiver) public view returns (uint256) +function maxDeposit(address receiver) public view returns (uint256 maxAssets) ``` -Esta função retorna a quantidade máxima de ativos subjacentes que podem ser depositados em um único [`deposit`](#deposit) chamado pelo `receiver`. +Esta função retorna a quantidade máxima de ativos subjacentes que podem ser depositados em uma única chamada de [`deposit`](#deposit), com as shares mintadas para o `receiver`. #### previewDeposit {#previewdeposit} ```solidity -function previewDeposit(uint256 assets) public view returns (uint256) +function previewDeposit(uint256 assets) public view returns (uint256 shares) ``` Esta função permite aos usuários simular os efeitos de seu depósito no bloco atual. -#### depositar {#deposit} +#### deposit {#deposit} ```solidity function deposit(uint256 assets, address receiver) public returns (uint256 shares) ``` -Esta função deposita `assets` de tokens subjacentes no cofre e concede a propriedade de `shares` para o `receiver`. +Esta função deposita `assets` de tokens subjacentes no cofre e concede a propriedade de `shares` ao `receiver`. #### maxMint {#maxmint} ```solidity -function maxMint(address receiver) public view returns (uint256) +function maxMint(address receiver) public view returns (uint256 maxShares) ``` -Esta função retorna a quantidade máxima de ativos subjacentes que podem ser mintados em um único [`mint`](#mint) chamado pelo `receiver`. +Esta função retorna a quantidade máxima de shares que podem ser mintadas em uma única chamada de [`mint`](#mint), com as shares mintadas para o `receiver`. #### previewMint {#previewmint} ```solidity -function previewMint(uint256 shares) public view returns (uint256) +function previewMint(uint256 shares) public view returns (uint256 assets) ``` Esta função permite aos usuários simular os efeitos de seu mint no bloco atual. -#### cunhar {#mint} +#### mint {#mint} ```solidity function mint(uint256 shares, address receiver) public returns (uint256 assets) ``` -Esta função minta exatamente `shares` no cofre para o `receiver` depositando `assets` dos tokens subjacentes. +Esta função minta exatamente `shares` de cofre para o `receiver`, depositando `assets` de tokens subjacentes. #### maxWithdraw {#maxwithdraw} ```solidity -function maxWithdraw(address owner) public view returns (uint256) +function maxWithdraw(address owner) public view returns (uint256 maxAssets) ``` -Esta função retorna a quantidade máxima de ativos subjacentes que podem ser retirados do saldo do `owner` com uma única chamada [`withdraw`](#withdraw). +Esta função retorna a quantidade máxima de ativos subjacentes que podem ser sacados do saldo do `owner` com uma única chamada de [`withdraw`](#withdraw). #### previewWithdraw {#previewwithdraw} ```solidity -function previewWithdraw(uint256 assets) public view returns (uint256) +function previewWithdraw(uint256 assets) public view returns (uint256 shares) ``` Esta função permite aos usuários simular os efeitos da sua retirada no bloco atual. -#### sacar {#withdraw} +#### withdraw {#withdraw} ```solidity function withdraw(uint256 assets, address receiver, address owner) public returns (uint256 shares) ``` -Esta função queima `shares` do `owner` e envia exatamente tokens `assets` do cofre para o `receiver`. +Esta função queima `shares` do `owner` e envia exatamente `assets` de token do cofre para o `receiver`. #### maxRedeem {#maxredeem} ```solidity -function maxRedeem(address owner) public view returns (uint256) +function maxRedeem(address owner) public view returns (uint256 maxShares) ``` -Essa função retorna a quantidade máxima de ações que podem ser resgatadas do saldo do `owner` com uma chamada de [`redeem`](#redeem). +Esta função retorna a quantidade máxima de shares que podem ser resgatadas do saldo do `owner` por meio de uma chamada de [`redeem`](#redeem). #### previewRedeem {#previewredeem} ```solidity -function previewRedeem(uint256 shares) public view returns (uint256) +function previewRedeem(uint256 shares) public view returns (uint256 assets) ``` Essa função permite aos usuários simular os efeitos de seu resgate no bloco atual. @@ -150,7 +166,7 @@ Essa função permite aos usuários simular os efeitos de seu resgate no bloco a function redeem(uint256 shares, address receiver, address owner) public returns (uint256 assets) ``` -Essa função resgata um número específico de `shares` do `owner` e envia `assets` do token subjacente do cofre para o `receiver`. +Esta função resgata um número específico de `shares` do `owner` e envia `assets` do token subjacente do cofre para o `receiver`. #### totalSupply {#totalsupply} @@ -166,13 +182,17 @@ Retorna o número total de shares não resgatadas do cofre em circulação. function balanceOf(address owner) public view returns (uint256) ``` -Retorna a quantidade total de shares do cofre que o `owner` tem atualmente. +Retorna a quantidade total de shares do cofre que o `owner` possui atualmente. + +### Mapa da interface {#mapOfTheInterface} + +![Mapa da interface ERC-4626](./map-of-erc-4626.png) ### Eventos {#events} #### Evento de depósito -**PRECISA** ser emitido quando os tokens são depositados no cofre por meio dos métodos [`mint`](#mint) e [`deposit`](#deposit) +**DEVE** ser emitido quando tokens são depositados no cofre através dos métodos [`mint`](#mint) e [`deposit`](#deposit). ```solidity event Deposit( @@ -183,11 +203,11 @@ event Deposit( ) ``` -Em que `sender` é o usuário que trocou `assets` por `shares` e transferiu aquelas `shares` para o `owner`. +Onde `sender` é o usuário que trocou `assets` por `shares` e transferiu essas `shares` para o `owner`. #### Evento de retirada -**PRECISA** ser emitido quando as shares são retiradas do cofre por um depositante nos métodos de [`redeem`](#redeem) ou [`withdraw`](#withdraw). +**DEVE** ser emitido quando shares são sacadas do cofre por um depositante nos métodos [`redeem`](#redeem) ou [`withdraw`](#withdraw). ```solidity event Withdraw( @@ -195,13 +215,13 @@ event Withdraw( address indexed receiver, address indexed owner, uint256 assets, - uint256 share + uint256 shares ) ``` -Em que `sender` é o usuário que acionou a retirada e trocou `shares`, de propriedade do `owner`, por `assets`. `receiver` é o usuário que recebeu os `assets ` retirados. +Onde `sender` é o usuário que acionou o saque e trocou `shares`, de propriedade do `owner`, por `assets`. `receiver` é o usuário que recebeu os `assets` sacados. ## Leitura adicional {#further-reading} -- [EIP-4626: Padrão do cofre tokenizado](https://eips.ethereum.org/EIPS/eip-4626) -- [ERC-4626: GitHub Repo](https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC4626.sol) +- [EIP-4626: Padrão de Cofre Tokenizado](https://eips.ethereum.org/EIPS/eip-4626) +- [ERC-4626: Repositório no GitHub](https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC4626.sol) diff --git a/public/content/translations/pt-br/developers/docs/standards/tokens/erc-721/index.md b/public/content/translations/pt-br/developers/docs/standards/tokens/erc-721/index.md index 57648ada626..13b5e56f174 100644 --- a/public/content/translations/pt-br/developers/docs/standards/tokens/erc-721/index.md +++ b/public/content/translations/pt-br/developers/docs/standards/tokens/erc-721/index.md @@ -1,32 +1,42 @@ --- -title: ERC-721 Padrão de token não-fungível -description: Token +title: "ERC-721 Padrão de token não-fungível" +description: "Conheça sobre ERC-721, o padrão para tokens não substituíveis (NFTs) que representam um único Ethereum digital." lang: pt-br --- ## Introdução {#introduction} -**O que é um token não fungível (NFT)?** +**O que é um Token Não Fungível?** -Um token não fungível (NFT) é utilizado para identificar algo ou alguém de uma forma única. Este tipo de token é perfeito para ser usado em plataformas que oferecem itens colecionáveis, acessar chaves, bilhetes de loteria, assentos numerados para concertos, jogos esportivos etc. Este tipo especial de token tem possibilidades incríveis, então merece um padrão adequado, o ERC-721! +Um token não fungível (NFT) é utilizado para identificar algo ou alguém de uma forma única. Este tipo de token é perfeito para ser +usado em plataformas que oferecem itens colecionáveis, acessar chaves, bilhetes de loteria, assentos numerados para concertos, +jogos esportivos etc. Este tipo especial de token tem possibilidades incríveis, então merece um padrão adequado, o ERC-721! **O que é ERC-721?** -O ERC-721 apresenta um padrão para NFT. Em outras palavras, este tipo de token é único e pode ter um valor diferente do que outro token do mesmo contrato inteligente, talvez devido a sua validade, raridade ou mesmo sua aparência. Um momento, aparência? +O ERC-721 apresenta um padrão para NFT. Em outras palavras, este tipo de token é único e pode ter um valor diferente +do que outro token do mesmo contrato inteligente, talvez devido a sua validade, raridade ou mesmo sua aparência. +Um momento, aparência? -Sim! Todos os NFTs têm uma variável `uint256` chamada `tokenId`, então para qualquer contrato ERC-721, o par `contract address, uint256 tokenId` deve ser globalmente único. Dito isso, um dApp pode ter um "conversor" que usa o `tokenId` como entrada e retorna uma imagem de algo legal, como zumbis, armas, habilidades ou gatinhos incríveis! +Sim! Todos os NFTs têm uma variável `uint256` chamada `tokenId`, então, para qualquer Contrato ERC-721, o par +`contract address, uint256 tokenId` deve ser globalmente único. Dito isso, um dapp pode ter um "conversor" que +usa o `tokenId` como entrada e produz uma imagem de algo legal, como zumbis, armas, habilidades ou gatinhos incríveis! ## Pré-requisitos {#prerequisites} - [Contas](/developers/docs/accounts/) -- [Contratos Inteligentes](/developers/docs/smart-contracts/) +- [Contratos inteligentes](/developers/docs/smart-contracts/) - [Padrões de token](/developers/docs/standards/tokens/) -## Apresentação {#body} +## Body {#body} -O ERC-721(Ethereum Request for Comments 721), proposto por William Entriken, Dieter Shirley, Jacob Evans e Nastassia Sachs em janeiro de 2018, é um padrão de token não-fungível que implementa uma API para tokens em contratos inteligentes. +O ERC-721(Ethereum Request for Comments 721), proposto por William Entriken, Dieter Shirley, Jacob Evans e +Nastassia Sachs em janeiro de 2018, é um padrão de token não-fungível que implementa uma API para tokens em contratos inteligentes. -Oferece funcionalidades, como transferir tokens de uma conta para outra, para obter o saldo atual do token de uma conta e também a oferta total do token disponível na rede. Além disso, ele também tem algumas outras funcionalidades como aprovar que uma quantidade de token de uma conta pode ser gasta por uma conta de terceiros. +Oferece funcionalidades, como transferir tokens de uma conta para outra, para obter o saldo atual do token de uma conta +e também a oferta total do token disponível na rede. +Além disso, ele também tem algumas outras funcionalidades +como aprovar que uma quantidade de token de uma conta pode ser gasta por uma conta de terceiros. Se um contrato inteligente implementa os métodos e eventos a seguir, ele pode ser chamado de Contrato de token ERC-721 e, uma vez implantado, é responsável por fazer um acompanhamento dos tokens criados no Ethereum. @@ -56,11 +66,13 @@ De [EIP-721](https://eips.ethereum.org/EIPS/eip-721): ### Exemplos {#web3py-example} -Vejamos por que um padrão é importante e como ele simplifica o controle de qualquer contrato de token ERC-721 no Ethereum. Só precisamos da Interface Binária de Aplicativos (ABI, pela sigla em inglês) do contrato para criar uma interface com qualquer token ERC-721. Como você pode ver abaixo, usaremos uma ABI simplificada, para torná-la um exemplo de fácil compreensão. +Vejamos por que um padrão é importante e como ele simplifica o controle de qualquer contrato de token ERC-721 no Ethereum. +Só precisamos da Interface Binária de Aplicativos (ABI, pela sigla em inglês) do contrato para criar uma interface com qualquer token ERC-721. Como você pode +ver abaixo, usaremos uma ABI simplificada, para torná-la um exemplo de fácil compreensão. -#### Exemplo Web3.py {#web3py-example} +#### Exemplo de Web3.py {#web3py-example} -Primeiro, certifique-se de que você instalou a [biblioteca Web3.py](https://web3py.readthedocs.io/en/stable/quickstart.html#installation) do Python: +Primeiro, certifique-se de que você instalou a biblioteca Python [Web3.py](https://web3py.readthedocs.io/en/stable/quickstart.html#installation): ``` pip install web3 @@ -73,12 +85,12 @@ from web3._utils.events import get_event_data w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com")) -ck_token_addr = "0x06012c8cf97BEaD5deAe237070F9587f8E7A266d" # CryptoKitties Contract +ck_token_addr = "0x06012c8cf97BEaD5deAe237070F9587f8E7A266d" # Contrato CryptoKitties -acc_address = "0xb1690C08E213a35Ed9bAb7B318DE14420FB57d8C" # CryptoKitties Sales Auction +acc_address = "0xb1690C08E213a35Ed9bAb7B318DE14420FB57d8C" # Leilão de Vendas CryptoKitties -# This is a simplified Contract Application Binary Interface (ABI) of an ERC-721 NFT Contract. -# Serão expostos apenas os métodos: balanceOf(address), name(), ownerOf(tokenId), symbol(), totalSupply() +# Esta é uma Interface Binária de Aplicação de Contrato (ABI) simplificada de um Contrato de NFT ERC-721. +# Ela exporá apenas os métodos: balanceOf(address), name(), ownerOf(tokenId), symbol(), totalSupply() simplified_abi = [ { 'inputs': [{'internalType': 'address', 'name': 'owner', 'type': 'address'}], @@ -127,16 +139,16 @@ ck_extra_abi = [ } ] -ck_contract = w3.eth.contract(address=w3.toChecksumAddress(ck_token_addr), abi=simplified_abi+ck_extra_abi) +ck_contract = w3.eth.contract(address=w3.to_checksum_address(ck_token_addr), abi=simplified_abi+ck_extra_abi) name = ck_contract.functions.name().call() symbol = ck_contract.functions.symbol().call() kitties_auctions = ck_contract.functions.balanceOf(acc_address).call() -print(f"{name} [{symbol}] NFTs in Auctions: {kitties_auctions}") +print(f"{name} [{symbol}] NFTs em leilões: {kitties_auctions}") pregnant_kitties = ck_contract.functions.pregnantKitties().call() -print(f"{name} [{symbol}] NFTs Pregnants: {pregnant_kitties}") +print(f"{name} [{symbol}] NFTs grávidos: {pregnant_kitties}") -# Usando o Evento de Transferência ABI para obter informações sobre os Kitties transferidos. +# Usando o ABI do Evento de Transferência para obter informações sobre os Kitties transferidos. tx_event_abi = { 'anonymous': False, 'inputs': [ @@ -147,34 +159,34 @@ tx_event_abi = { 'type': 'event' } -# We need the event's signature to filter the logs -event_signature = w3.sha3(text="Transfer(address,address,uint256)").hex() +# Precisamos da assinatura do evento para filtrar os logs +event_signature = w3.keccak(text="Transfer(address,address,uint256)").hex() -logs = w3.eth.getLogs({ - "fromBlock": w3.eth.blockNumber - 120, - "address": w3.toChecksumAddress(ck_token_addr), +logs = w3.eth.get_logs({ + "fromBlock": w3.eth.block_number - 120, + "address": w3.to_checksum_address(ck_token_addr), "topics": [event_signature] }) -# Notes: -# - 120 blocks is the max range for CloudFlare Provider -# - If you didn't find any Transfer event you can also try to get a tokenId at: +# Observações: +# - Aumente o número de blocos acima de 120 se nenhum evento de Transferência for retornado. +# - Se você não encontrou nenhum evento de Transferência, também pode tentar obter um tokenId em: # https://etherscan.io/address/0x06012c8cf97BEaD5deAe237070F9587f8E7A266d#events -# Click to expand the event's logs and copy its "tokenId" argument - +# Clique para expandir os logs do evento e copie seu argumento "tokenId" recent_tx = [get_event_data(w3.codec, tx_event_abi, log)["args"] for log in logs] -kitty_id = recent_tx[0]['tokenId'] # Paste the "tokenId" here from the link above -is_pregnant = ck_contract.functions.isPregnant(kitty_id).call() -print(f"{name} [{symbol}] NFTs {kitty_id} is pregnant: {is_pregnant}") +if recent_tx: + kitty_id = recent_tx[0]['tokenId'] # Cole o "tokenId" aqui do link acima + is_pregnant = ck_contract.functions.isPregnant(kitty_id).call() + print(f"{name} [{symbol}] NFT {kitty_id} está grávido: {is_pregnant}") ``` Contrato de CriptoKitties tem alguns eventos interessantes além dos padrões. -Vamos ver dois deles, `Pregnant` e `Birth`. +Vamos verificar dois deles, `Pregnant` e `Birth`. ```python -# Usando o Evento ABI "Gravidez e Nascimento" para obter informações sobre os novos Kitties. +# Usando o ABI dos eventos Pregnant e Birth para obter informações sobre novos Kitties. ck_extra_events_abi = [ { 'anonymous': False, @@ -198,27 +210,27 @@ ck_extra_events_abi = [ 'type': 'event' }] -# We need the event's signature to filter the logs +# Precisamos da assinatura do evento para filtrar os logs ck_event_signatures = [ - w3.sha3(text="Pregnant(address,uint256,uint256,uint256)").hex(), - w3.sha3(text="Birth(address,uint256,uint256,uint256,uint256)").hex(), + w3.keccak(text="Pregnant(address,uint256,uint256,uint256)").hex(), + w3.keccak(text="Birth(address,uint256,uint256,uint256,uint256)").hex(), ] -# Here is a Pregnant Event: +# Aqui está um evento Pregnant: # - https://etherscan.io/tx/0xc97eb514a41004acc447ac9d0d6a27ea6da305ac8b877dff37e49db42e1f8cef#eventlog -pregnant_logs = w3.eth.getLogs({ - "fromBlock": w3.eth.blockNumber - 120, - "address": w3.toChecksumAddress(ck_token_addr), +pregnant_logs = w3.eth.get_logs({ + "fromBlock": w3.eth.block_number - 120, + "address": w3.to_checksum_address(ck_token_addr), "topics": [ck_event_signatures[0]] }) recent_pregnants = [get_event_data(w3.codec, ck_extra_events_abi[0], log)["args"] for log in pregnant_logs] -# Here is a Birth Event: +# Aqui está um evento Birth: # - https://etherscan.io/tx/0x3978028e08a25bb4c44f7877eb3573b9644309c044bf087e335397f16356340a -birth_logs = w3.eth.getLogs({ - "fromBlock": w3.eth.blockNumber - 120, - "address": w3.toChecksumAddress(ck_token_addr), +birth_logs = w3.eth.get_logs({ + "fromBlock": w3.eth.block_number - 120, + "address": w3.to_checksum_address(ck_token_addr), "topics": [ck_event_signatures[1]] }) @@ -227,18 +239,24 @@ recent_births = [get_event_data(w3.codec, ck_extra_events_abi[1], log)["args"] f ## NFTs populares {#popular-nfts} -- [Etherscan NFT Tracker](https://etherscan.io/tokens-nft) lista o maior NFT no Ethereum por volume de transferências. -- [CryptoKitties](https://www.cryptokitties.co/) é um jogo centrado em criaturas de coleção adoráveis que chamamos de CryptoKitties. -- [Sorare](https://sorare.com/) é um jogo global de fantasia em que você pode coletar edições limitadas, gerenciar suas equipes e concorrer para ganhar prêmios. -- [Ethereum Name Service (ENS)](https://ens.domains/) oferece uma forma segura e descentralizada de endereçar os recursos dentro e fora da blockchain usando nomes legíveis simples. -- [POAP](https://poap.xyz) oferece NFTs grátis para pessoas que participam de eventos ou realizam ações específicas. Os POAPs são livres para criar e distribuir. -- [Unstoppable Domains](https://unstoppabledomains.com/) é uma empresa com sede em São Francisco que cria domínios em blockchains. Os domínios de blockchain substituem endereços de criptomoeda por nomes legíveis e podem ser usados para habilitar sites resistentes à censura. -- [Gods Unchained Cards](https://godsunchained.com/) é uma TCG na blockchain Ethereum que usa NFT para representar a propriedade real nos ativos do jogo. -- [Bored Ape Yacht Club](https://boredapeyachtclub.com) é uma coleção de 10.000 NFT exclusivos que, além de ser uma peça de arte comprovadamente eclética, atua como um token de adesão ao clube, oferecendo vantagens e benefícios aos membros, que aumentam ao longo do tempo como resultado dos esforços da comunidade. - -## Leia mais {#further-reading} - -- [EIP-721: ERC-721 Padrão de token não-fungível](https://eips.ethereum.org/EIPS/eip-721) -- [OpenZeppelin: Documentação ERC-721](https://docs.openzeppelin.com/contracts/3.x/erc721) -- [OpenZeppelin: Implementação ERC-721](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol) -- [API do NFT da Alchemy](https://docs.alchemy.com/alchemy/enhanced-apis/nft-api) +- [Etherscan NFT Tracker](https://etherscan.io/nft-top-contracts) lista os principais NFTs no Ethereum por volume de transferências. +- [CryptoKitties](https://www.cryptokitties.co/) é um jogo centrado em criaturas criáveis, colecionáveis e superadoráveis + que chamamos de CryptoKitties. +- [Sorare](https://sorare.com/) é um jogo de futebol fantasia global onde você pode colecionar itens colecionáveis de edição limitada, + gerenciar suas equipes e competir para ganhar prêmios. +- [O Ethereum Name Service (ENS)](https://ens.domains/) oferece uma maneira segura e descentralizada de endereçar recursos tanto + dentro quanto fora da blockchain usando nomes simples e legíveis por humanos. +- [POAP](https://poap.xyz) entrega NFTs gratuitos para pessoas que participam de eventos ou concluem ações específicas. Os POAPs são livres para criar e distribuir. +- [Unstoppable Domains](https://unstoppabledomains.com/) é uma empresa com sede em São Francisco que constrói domínios em + blockchains. Domínios de blockchain substituem endereços de criptomoedas por nomes legíveis por humanos e podem ser usados para habilitar + sites resistentes à censura. +- [Gods Unchained Cards](https://godsunchained.com/) é um TCG na blockchain Ethereum que usa NFTs para trazer propriedade real + para os ativos do jogo. +- [Bored Ape Yacht Club](https://boredapeyachtclub.com) é uma coleção de 10.000 NFTs únicos que, além de ser uma obra de arte comprovadamente rara, funciona como um token de associação ao clube, oferecendo vantagens e benefícios aos membros que aumentam com o tempo como resultado dos esforços da comunidade. + +## Leitura adicional {#further-reading} + +- [EIP-721: Padrão de Token Não Fungível ERC-721](https://eips.ethereum.org/EIPS/eip-721) +- [OpenZeppelin - Documentação do ERC-721](https://docs.openzeppelin.com/contracts/3.x/erc721) +- [OpenZeppelin - Implementação do ERC-721](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol) +- [API de NFT da Alchemy](https://www.alchemy.com/docs/reference/nft-api-quickstart) diff --git a/public/content/translations/pt-br/developers/docs/standards/tokens/erc-777/index.md b/public/content/translations/pt-br/developers/docs/standards/tokens/erc-777/index.md index da86904e165..de23574d146 100644 --- a/public/content/translations/pt-br/developers/docs/standards/tokens/erc-777/index.md +++ b/public/content/translations/pt-br/developers/docs/standards/tokens/erc-777/index.md @@ -1,45 +1,45 @@ --- -title: Padrão de token ERC-777 -description: Token +title: "Padrão de token ERC-777" +description: "Saiba mais sobre o ERC-777, um padrão de token fungível aprimorado com ganchos, embora o ERC-20 seja recomendado por questões de segurança." lang: pt-br --- -## Atenção {#warning} +## Aviso {#warning} -**ERC-777 é difícil de implementar adequadamente, devido à sua [suscetibilidade a diferentes formas de ataque](https://github.com/OpenZeppelin/openzeppelin-contracts/issues/2620). Recomenda-se usar [ERC-20](/developers/docs/standards/tokens/erc-20/) em vez disso.** Esta página permanece como um arquivo histórico. +**ERC-777 é difícil de implementar propriamente, devido à sua [suscetibilidade a diferentes formas de ataque](https://github.com/OpenZeppelin/openzeppelin-contracts/issues/2620). É recomendável usar [ERC-20](/developers/docs/standards/tokens/erc-20/) ao invés. ** Essa página mantém um histórico de arquivos. -## Introdução {#introduction} +## Introdução? {#introduction} -ERC-777 é um padrão de token fungível com o objetivo de aprimorar o padrão [ERC-20](/developers/docs/standards/tokens/erc-20/) existente. +ERC-777 é um padrão de token fungível superior aos anteriores [ERC-20](/developers/docs/standards/tokens/erc-20/). -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -Para entender melhor essa página, recomendamos primeiramente uma leitura sobre [ERC-20](/developers/docs/standards/tokens/erc-20/). +Para entender melhor essa página, recomendamos que leia sobre[ERC-20](/developers/docs/standards/tokens/erc-20/). ## Quais as melhorias do ERC-777 em relação ao ERC-20? {#-erc-777-vs-erc-20} O ERC-777 proporciona as seguintes melhorias em relação ao ERC-20. -### Hooks {#hooks} +### Ganchos {#hooks} -Os hooks são funções descritas no código de um contrato inteligente. Eles são invocados quando os tokens são enviados ou recebidos pelo contrato. Isso possibilita que o contrato inteligente reaja aos tokens recebidos ou enviados. +Os hooks são funções descritas no código de um smart contract. Eles são invocados quando os tokens são enviados ou recebidos pelo contrato. Isso possibilita que o smart contract reaja aos tokens recebidos ou enviados. -Os hooks são registrados e descobertos utilizando o padrão [ERC-1820](https://eips.ethereum.org/EIPS/eip-1820). +Os hooks são registrados e descobertos por meio do padrão [ERC-1820](https://eips.ethereum.org/EIPS/eip-1820). #### Porque os hooks são uma vantagem? {#why-are-hooks-great} -1. Os hooks possibilitam o envio de tokens para um contrato e a notificação do contrato em apenas uma transação. O [ERC-20](https://eips.ethereum.org/EIPS/eip-20), porém, necessita de duas chamadas (`approve`/`transferFrom`) para fazer isso. -2. Contratos que não possuem hooks registrados são incompatíveis com o ERC-777. O contrato enviado irá abortar a transação quando o receptor não estiver com um hook registrado. Isso previne transferências acidentais para contratos inteligentes fora do padrão ERC-777. -3. Hooks podem rejeitas transações. +1. Eles possibilitam o envio de tokens para um contrato e a notificação do contrato em apenas uma transação. O [ERC-20](https://eips.ethereum.org/EIPS/eip-20), porém, necessita de duas chamadas (`approve`/`transferFrom`) para fazer isso. +2. Contratos que não possuem hooks registrados são incompatíveis com o ERC-777. O contrato enviado irá abortar a transação quando o receptor não estiver com um hook registrado. Isso previne transferências acidentais para smart contracts fora do padrão ERC-777. +3. Hooks podem rejeitar transações. ### Decimais {#decimals} O padrão ERC-777 também soluciona a confusão referente a `decimals` causada pelo ERC-20. Esta clareza melhora a experiência do desenvolvedor. -### Retrocompatibilidade com o ERC-20 {#backwards-compatibility-with-erc-20} +### Retrocompatibilidade com ERC-20 {#backwards-compatibility-with-erc-20} -Contratos ERC-777 permitem interação como se fossem contratos ERC-20. +Contratos ERC-777 podem ter interações como se fossem contratos ERC-20. -## Leitura Adicional {#further-reading} +## Leitura adicional {#further-reading} -[EIP-777: Padrão de token](https://eips.ethereum.org/EIPS/eip-777) +[EIP-777: Padrão de Token](https://eips.ethereum.org/EIPS/eip-777) diff --git a/public/content/translations/pt-br/developers/docs/standards/tokens/index.md b/public/content/translations/pt-br/developers/docs/standards/tokens/index.md index 6f20013c39e..615f556b783 100644 --- a/public/content/translations/pt-br/developers/docs/standards/tokens/index.md +++ b/public/content/translations/pt-br/developers/docs/standards/tokens/index.md @@ -1,36 +1,41 @@ --- -title: Padrões de token -description: Token +title: "Padrões de token" +description: "Explorar os padrões de tokens Ethereum, incluindo ERC-20, ERC-721, e ERC-1155 para tokens substituível e não substituível." lang: pt-br incomplete: true --- ## Introdução {#introduction} -Muitos padrões de desenvolvimento do Ethereum focam em interfaces de tokens. Esses padrõess ajudam a garantir que os contratos inteligentes permaneçam compostos. Por exemplo, quando um novo projeto emite um token, que ele permaneça compatível com exchanges descentralizadas existentes. +Muitos padrões de desenvolvimento do Ethereum focam em interfaces de tokens. Esses padrões ajudam a garantir que os contratos inteligentes permaneçam componíveis, para que, quando um novo projeto emitir um token, ele permaneça compatível com as corretoras e aplicativos descentralizados existentes. + +Os padrões de token definem como os tokens se comportam e interagem em todo o ecossistema Ethereum. Eles facilitam a criação para os desenvolvedores sem reinventar a roda, garantindo que os tokens funcionem perfeitamente com carteiras, corretoras e plataformas DeFi. Seja em jogos, governança ou outros casos de uso, esses padrões fornecem consistência e tornam o Ethereum mais interconectado. ## Pré-requisitos {#prerequisites} -- [Critérios de desenvolvimento do Ethereum](/developers/docs/standards/) -- [Smart Contracts](/developers/docs/smart-contracts/) +- [Padrões de desenvolvimento do Ethereum](/developers/docs/standards/) +- [Contratos inteligentes](/developers/docs/smart-contracts/) ## Padrões de token {#token-standards} Aqui estão alguns dos padrões mais populares de token no Ethereum: -- [ERC-20](/developers/docs/standards/tokens/erc-20/): uma interface padrão para tokens fungíveis (intercambiáveis), como tokens de votação, tokens de staking ou moedas virtuais. -- [ERC-721](/developers/docs/standards/tokens/erc-721/): uma interface padrão para tokens não-fungíveis, como uma ação para obra de arte ou uma música. -- [ERC-777](/developers/docs/standards/tokens/erc-777/): o ERC-777 permite que as pessoas criem funcionalidades extras com base nos tokens, como um contrato mixto para melhorar a privacidade das transações ou uma função de recuperação de emergência para ajudá-lo a recuperar suas chaves privadas caso você as perca. -- [ERC-1155](/developers/docs/standards/tokens/erc-1155/): o ERC-1155 permite operações mais eficientes e pode enviar pacotes de transações, o que economiza custos. Este padrão de token permite a criação tanto de tokens utilitários, como $BNB ou $BAT, quanto de tokens não-fungíveis, por exemplo, os CryptoPunks. -- [ERC-4626](/developers/docs/standards/tokens/erc-4626/): um padrão de cofre tokenizado projetado para otimizar e unificar os parâmetros técnicos dos cofres de rendimento. +- [ERC-20](/developers/docs/standards/tokens/erc-20/) - Uma interface padrão para tokens fungíveis (intercambiáveis), como tokens de votação, tokens de staking ou moedas virtuais. + +### Padrões de NFT {#nft-standards} + +- [ERC-721](/developers/docs/standards/tokens/erc-721/) - Uma interface padrão para tokens não fungíveis, como um título de propriedade para uma obra de arte ou uma música. +- [ERC-1155](/developers/docs/standards/tokens/erc-1155/) - O ERC-1155 permite negociações mais eficientes e o agrupamento de transações, economizando custos. Este padrão de token permite a criação tanto de tokens utilitários, como $BNB ou $BAT, quanto de tokens não-fungíveis, por exemplo, os CryptoPunks. + +A lista completa de propostas [ERC](https://eips.ethereum.org/erc). ## Leitura adicional {#further-reading} -_Conhece um recurso da comunidade que ajudou você? Edite essa página e adicione-o!_ +_Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ ## Tutoriais relacionados {#related-tutorials} -- [Lista de verificação para integração de tokens:](/developers/tutorials/token-integration-checklist/) _uma lista de verificação para considerar quando estiver interagindo com tokens._ -- [Entenda o contrato inteligente de token do ERC20:](/developers/tutorials/understand-the-erc-20-token-smart-contract/) _uma introdução para a implementação do seu primeiro contrato inteligente na rede de teste do Ethereum_ -- [Transferências e aprovação de tokens do ERC20 de um contrato inteligente Solidity:](/developers/tutorials/transfers-and-approval-of-erc-20-tokens-from-a-solidity-smart-contract/) _como usar um contrato inteligente para interagir com um token usando a linguagem Solidity._ -- [Implementação de um mercado ERC721 [um guia prático]:](/developers/tutorials/how-to-implement-an-erc721-market/) _ como colocar itens tokenizados à venda em um painel de classificações descentralizadas._ +- [Lista de verificação da integração de tokens](/developers/tutorials/token-integration-checklist/) _– Uma lista de verificação de itens a serem considerados ao interagir com tokens._ +- [Entenda o contrato inteligente do token ERC20](/developers/tutorials/understand-the-erc-20-token-smart-contract/) _– Uma introdução à implantação do seu primeiro contrato inteligente em uma rede de teste Ethereum._ +- [Transferências e aprovação de tokens ERC20 a partir de um contrato inteligente em Solidity](/developers/tutorials/transfers-and-approval-of-erc-20-tokens-from-a-solidity-smart-contract/) _– Como usar um contrato inteligente para interagir com um token usando a linguagem Solidity._ +- [Implementando um mercado ERC721 [um guia prático]](/developers/tutorials/how-to-implement-an-erc721-market/) _– Como colocar itens tokenizados à venda em um quadro de classificados descentralizado._ diff --git a/public/content/translations/pt-br/developers/docs/storage/index.md b/public/content/translations/pt-br/developers/docs/storage/index.md index ca22c62ad58..daaa3451119 100644 --- a/public/content/translations/pt-br/developers/docs/storage/index.md +++ b/public/content/translations/pt-br/developers/docs/storage/index.md @@ -1,12 +1,12 @@ --- title: Armazenamento Descentralizado -description: Visão geral do que é o armazenamento descentralizado e as ferramentas disponíveis para integrar a um dapp. +description: "Visão geral do que é o armazenamento descentralizado e as ferramentas disponíveis para integrar a um dapp." lang: pt-br --- Ao contrário de um servidor localizado centralmente operado por uma única empresa ou organização, os sistemas de armazenamento descentralizado consistem em uma rede ponto a ponto de usuários operadores que mantêm uma parte dos dados gerais, criando um sistema resiliente de armazenamento e compartilhamento de arquivos. Elas podem estar em um aplicativo baseado em blockchain ou qualquer rede baseada em peer-to-peer. -A Ethereum em si pode ser usada como um sistema de armazenamento descentralizado, e é quando se trata de codificar o armazenamento em todos os contratos inteligentes. No entanto, quando se trata de grandes quantidades de dados, para as quais a Ethereum não foi concebida. A corrente está crescendo constantemente, mas no momento da escrita, a cadeia Ethereum é de cerca de 500GB - 1TB ([dependendo do cliente](https://etherscan.io/chartsync/chaindefault)), e cada nó da rede precisa ser capaz de armazenar todos os dados. Se a cadeia fosse expandir para grandes quantidades de dados (diga 5TBs) não seria viável que todos os nós continuassem a rodar. Além disso, o custo de implantar essa quantidade de dados para a rede principal seria proibitivamente caro devido às taxas de [gás](/developers/docs/gas). +A Ethereum em si pode ser usada como um sistema de armazenamento descentralizado, e é quando se trata de codificar o armazenamento em todos os contratos inteligentes. No entanto, quando se trata de grandes quantidades de dados, para as quais a Ethereum não foi concebida. A cadeia está crescendo de forma constante, mas, no momento da redação, a cadeia Ethereum tem cerca de 500 GB a 1 TB ([dependendo do cliente](https://etherscan.io/chartsync/chaindefault)), e cada nó na rede precisa ser capaz de armazenar todos os dados. Se a cadeia fosse expandir para grandes quantidades de dados (diga 5TBs) não seria viável que todos os nós continuassem a rodar. Além disso, o custo de implantar tantos dados na Mainnet seria proibitivamente caro devido às taxas de [gás](/developers/docs/gas). Devido a essas restrições, precisamos de uma cadeia ou metodologia diferente para armazenar grandes quantidades de dados de forma descentralizada. @@ -14,7 +14,7 @@ Ao analisar as opções de armazenamento descentralizado (dStorage), existem alg - Mecanismo de persistência/estrutura de incentivo - Execução de retenção de dados -- Descentralizada +- Descentralização - Consenso ## Mecanismo de persistência / estrutura de incentivo {#persistence-mechanism} @@ -23,9 +23,9 @@ Ao analisar as opções de armazenamento descentralizado (dStorage), existem alg Para que uma peça de dados se mantenha para sempre, precisamos utilizar um mecanismo de persistência. Por exemplo, na Ethereum, o mecanismo de persistência é que toda a cadeia precisa ser contabilizada ao executar um nó. Novos dados são empilhados no final da cadeia, continuando a crescer - exigindo que cada nó replique todos os dados embutidos. -Conhecemos isto como persistência **baseada em blockchain**. +Isso é conhecido como persistência **baseada em blockchain**. -O problema com persistência baseada em blockchain é que a cadeia pode ficar muito grande para manter e armazenar todos os dados viáveis (por exemplo, [muitas fontes](https://healthit.com.au/how-big-is-the-internet-and-how-do-we-measure-it/) estimam que a Internet precisa de mais de 40 Zetabytes de capacidade de armazenamento). +O problema com a persistência baseada em blockchain é que a cadeia pode se tornar grande demais para manter e armazenar todos os dados de forma viável (por exemplo, [muitas fontes](https://healthit.com.au/how-big-is-the-internet-and-how-do-we-measure-it/) estimam que a Internet exige mais de 40 Zetabytes de capacidade de armazenamento). A blockchain (cadeia de blocos) também deve ter algum tipo de estrutura de incentivo. Para persistência baseada em blockchain, há um pagamento feito ao validador. Quando os dados são adicionados à cadeia, os validadores são pagos para adicionar os dados. @@ -34,23 +34,23 @@ Plataformas com persistência baseada em blockchain (cadeia de blocos): - Ethereum - [Arweave](https://www.arweave.org/) -### Baseado em contratos {#contract-based} +### Baseado em contrato {#contract-based} -A persistência **baseada em contrato** tem a intuição de que os dados não podem ser replicados por todos os nós e mantidos para sempre, senão que, ao invés disso, devem ser mantidos com acordos de contrato. Trata-se de acordos celebrados com vários nós que prometeram a conservação de dados por um período de tempo. Devem ser reembolsados ou renovados sempre que se esgotem para manter os dados persistentes. +A persistência **baseada em contrato** parte do princípio de que os dados não podem ser replicados por todos os nós e armazenados para sempre e, em vez disso, devem ser mantidos com acordos de contrato. Trata-se de acordos celebrados com vários nós que prometeram a conservação de dados por um período de tempo. Devem ser reembolsados ou renovados sempre que se esgotem para manter os dados persistentes. -Na maioria dos casos, em vez de armazenar todos os dados on-chain, o hash de onde os dados estão localizados em uma cadeia é armazenado. Dessa forma, a cadeia inteira não precisará escalar para guardar todos os dados. +Na maioria dos casos, em vez de armazenar todos os dados onchain, o hash de onde os dados estão localizados onchain é armazenado. Dessa forma, a cadeia inteira não precisará escalar para guardar todos os dados. Plataformas com persistência baseada em blockchain (cadeia de blocos): -- [Filecoin](https://docs.filecoin.io/about-filecoin/what-is-filecoin/) -- [Skynet](https://siasky.net/) +- [Filecoin](https://docs.filecoin.io/basics/what-is-filecoin) +- [Skynet](https://sia.tech/) - [Storj](https://storj.io/) - [Züs](https://zus.network/) -- [Rede Crust](https://crust.network) +- [Crust Network](https://crust.network) - [Swarm](https://www.ethswarm.org/) - [4EVERLAND](https://www.4everland.org/) -### Considerações finais {#additional-consideration} +### Considerações adicionais {#additional-consideration} IPFS é um sistema distribuído para armazenamento e acesso a arquivos, sites, aplicações e dados. Ele não tem um esquema baseado em incentivos, mas pode ser usado com qualquer uma das soluções acima baseadas em contratos de incentivos para persistências de longo prazo. Outra maneira de persistir dados no IPFS é trabalhar com um serviço fixo, que permita "fixar" seus dados para você. Você pode até mesmo rodar seu próprio nó IPFS e contribuir para a rede para persistir seus dados ou os de outra pessoa de forma gratuita! @@ -58,12 +58,12 @@ IPFS é um sistema distribuído para armazenamento e acesso a arquivos, sites, a - [Pinata](https://www.pinata.cloud/) _(serviço de fixação IPFS)_ - [web3.storage](https://web3.storage/) _(serviço de fixação IPFS/Filecoin)_ - [Infura](https://infura.io/product/ipfs) _(serviço de fixação IPFS)_ -- [Verificação IPFS](https://ipfs-scan.io) _(explorador de fixação de IPFS)_ -- [4EVERLAND](https://www.4everland.org/)_ (Serviço de fixação IPFS) _ -- [Filebase](https://filebase.com) _(Serviço de Fixação IPFS)_ -- [Spheron Network](https://spheron.network/) _(serviço de pinning IPFS/Filecoin)_ +- [IPFS Scan](https://ipfs-scan.io) _(explorador de fixação IPFS)_ +- [4EVERLAND](https://www.4everland.org/) _(serviço de fixação IPFS)_ +- [Filebase](https://filebase.com) _(Serviço de fixação IPFS)_ +- [Spheron Network](https://spheron.network/) _(serviço de fixação IPFS/Filecoin)_ -SWARM é uma tecnologia descentralizada de armazenamento e distribuição de dados com um sistema de incentivo ao armazenamento e um oráculo de preços de aluguel de armazenamento. +O SWARM é uma tecnologia de armazenamento e distribuição de dados descentralizada com um sistema de incentivo de armazenamento e um oráculo de preços de aluguel de armazenamento. ## Retenção de dados {#data-retention} @@ -98,7 +98,7 @@ Ferramentas descentralizadas sem KYC: ### Consenso {#consensus} -A maioria dessas ferramentas tem sua própria versão de um [mecanismo de consenso](/developers/docs/consensus-mechanisms/) mas, geralmente, elas são baseadas em [**proof-of-work (prova de trabalho)**](/developers/docs/consensus-mechanisms/pow/) ou [**proof-of-stake (prova de participação, PoS)**](/developers/docs/consensus-mechanisms/pos/). +A maioria dessas ferramentas tem sua própria versão de um [mecanismo de consenso](/developers/docs/consensus-mechanisms/), mas geralmente elas são baseadas em [**prova de trabalho (PoW)**](/developers/docs/consensus-mechanisms/pow/) ou [**prova de participação (PoS)**](/developers/docs/consensus-mechanisms/pos/). Baseado em prova de trabalho (proof-of-work): @@ -114,23 +114,23 @@ Baseado em prova de participação (proof-of-stake): ## Ferramentas relacionadas {#related-tools} -**IPFS - _InterPlanetary File System é um sistema descentralizado de armazenamento e referenciamento de arquivos para a Ethereum._** +**IPFS - _O InterPlanetary File System é um sistema descentralizado de armazenamento e referenciamento de arquivos para o Ethereum._** - [Ipfs.io](https://ipfs.io/) - [Documentação](https://docs.ipfs.io/) - [GitHub](https://github.com/ipfs/ipfs) -**Storj DCS - _Armazenamento descentralizado e compatível com a S3-Cloud para desenvolvedores._** +**Storj DCS - _Armazenamento de objetos em nuvem descentralizado, seguro, privado e compatível com S3 para desenvolvedores._** - [Storj.io](https://storj.io/) - [Documentação](https://docs.storj.io/) - [GitHub](https://github.com/storj/storj) -**Skynet - _O Skynet é uma cadeia descentralizada de PoW dedicada a uma web descentralizada._** +**Sia - _Utiliza criptografia para criar um mercado de armazenamento em nuvem sem necessidade de confiança, permitindo que compradores e vendedores transacionem diretamente._** -- [Skynet.net](https://siasky.net/) -- [Documentação](https://siasky.net/docs/) -- [GitHub](https://github.com/SkynetLabs/) +- [Skynet.net](https://sia.tech/) +- [Documentação](https://docs.sia.tech/) +- [GitHub](https://github.com/SiaFoundation/) **Filecoin - _Filecoin foi criado pela mesma equipe por trás do IPFS. É uma camada de incentivo no topo dos ideais IPFS._** @@ -144,49 +144,49 @@ Baseado em prova de participação (proof-of-stake): - [Documentação](https://docs.arweave.org/info/) - [Arweave](https://github.com/ArweaveTeam/arweave/) -**Züs - _Züs é uma plataforma de dStorage baseada em prova de participação, com suporte a fragmentação e blobbers._** +**Züs - _Züs é uma plataforma de dStorage de prova de participação com fragmentação e blobbers._** - [zus.network](https://zus.network/) -- [Documentação](https://0chaindocs.gitbook.io/zus-docs) +- [Documentação](https://docs.zus.network/zus-docs/) - [GitHub](https://github.com/0chain/) -**Rede Croust - _Crust é uma plataforma de dStorage no topo do IPFS._** +**Crust Network - _Crust é uma plataforma de dStorage sobre o IPFS._** - [Crust.network](https://crust.network) - [Documentação](https://wiki.crust.network) - [GitHub](https://github.com/crustio) -**Swarm - _Uma plataforma de armazenamento distribuída e serviço de distribuição de conteúdo para a pilha Ethereum web3._** +**Swarm - _Uma plataforma de armazenamento distribuída e um serviço de distribuição de conteúdo para a pilha web3 do Ethereum._** - [EthSwarm.org](https://www.ethswarm.org/) -- [Documentação](https://docs.ethswarm.org/docs/) +- [Documentação](https://docs.ethswarm.org/) - [GitHub](https://github.com/ethersphere/) -**OrbitDB - _Um banco de dados descentralizado peer-to-peer no topo do IPFS._** +**OrbitDB - _Um banco de dados peer-to-peer descentralizado sobre o IPFS._** - [OrbitDB.org](https://orbitdb.org/) - [Documentação](https://github.com/orbitdb/field-manual/) - [GitHub](https://github.com/orbitdb/orbit-db/) -**Aleph.im - _Projeto na nuvem descentralizado (banco de dados, armazenamento de arquivos, computação e DID). Uma combinação única de tecnologia off-chain e peer-to-peer. IPFS e compatibilidade multicadeia._** +**Aleph.im - _Projeto de nuvem descentralizada (banco de dados, armazenamento de arquivos, computação e DID). Uma combinação única de tecnologia off-chain e peer-to-peer. IPFS e compatibilidade multicadeia._** -- [Aleph.im](https://aleph.im/) -- [Documentação](https://aleph.im/#/developers/) +- [Aleph.im](https://aleph.cloud/) +- [Documentação](https://docs.aleph.cloud/) - [GitHub](https://github.com/aleph-im/) **Ceramic - _Armazenamento de banco de dados IPFS controlado pelo usuário para aplicativos ricos em dados e envolventes._** - [Ceramic.network](https://ceramic.network/) -- [Documentação](https://developers.ceramic.network/learn/welcome/) +- [Documentação](https://developers.ceramic.network/) - [GitHub](https://github.com/ceramicnetwork/js-ceramic/) -**Filebase - _Armazenamento descentralizado compatível com S3 e serviço de fixação IPFS com redundância geográfica. Todos os arquivos carregados para o IPFS através do Filebase são automaticamente fixados na infraestrutura do Filebase com replicação 3x em todo o mundo._** +**Filebase - _Armazenamento descentralizado compatível com S3 e serviço de fixação IPFS com redundância geográfica. Todos os arquivos enviados para o IPFS através do Filebase são automaticamente fixados na infraestrutura do Filebase com replicação 3x em todo o mundo._** - [Filebase.com](https://filebase.com/) - [Documentação](https://docs.filebase.com/) - [GitHub](https://github.com/filebase) -**4EVERLAND - _Plataforma web 3.0 de computação em nuvem que integra armazenamento, computação e capacidades de núcleo em rede, é compatível com o S3 e fornece armazenamento de dados síncrono em redes de armazenamento descentralizadas, como IPFS e Arweave. s_** +**4EVERLAND - _Uma plataforma de computação em nuvem Web 3.0 que integra recursos essenciais de armazenamento, computação e rede, é compatível com S3 e fornece armazenamento de dados síncrono em redes de armazenamento descentralizadas, como IPFS e Arweave._** - [4everland.org](https://www.4everland.org/) - [Documentação](https://docs.4everland.org/) @@ -198,7 +198,7 @@ Baseado em prova de participação (proof-of-stake): - [Documentação](https://docs.kaleido.io/kaleido-services/ipfs/) - [GitHub](https://github.com/kaleido-io) -**Spheron Network - _Spheron é uma plataforma como serviço (PaaS) projetada para dApps que busca lançar seus aplicativos em infraestrutura descentralizada com o melhor desempenho. Oferece computação, armazenamento descentralizado, CDN e hospedagem web prontos para uso._** +**Spheron Network - _A Spheron é uma plataforma como serviço (PaaS) projetada para dApps que procuram lançar seus aplicativos em infraestrutura descentralizada com o melhor desempenho. Oferece computação, armazenamento descentralizado, CDN e hospedagem web prontos para uso._** - [spheron.network](https://spheron.network/) - [Documentação](https://docs.spheron.network/) @@ -206,11 +206,11 @@ Baseado em prova de participação (proof-of-stake): ## Leitura adicional {#further-reading} -- [O que é armazenamento descentralizado?](https://coinmarketcap.com/alexandria/article/what-is-decentralized-storage-a-deep-dive-by-filecoin) - _CoinMarketCap_ -- [Cinco Mitos Comuns sobre o Armazenamento Descentralizado](https://www.storj.io/blog/busting-five-common-myths-about-decentralized-storage) - _Storj_ +- [O que é armazenamento descentralizado?](https://coinmarketcap.com/academy/article/what-is-decentralized-storage-a-deep-dive-by-filecoin) - _CoinMarketCap_ +- [Desvendando cinco mitos comuns sobre o armazenamento descentralizado](https://www.storj.io/blog/busting-five-common-myths-about-decentralized-storage) - _Storj_ _Conhece um recurso da comunidade que ajudou você? Edite essa página e adicione-o!_ ## Tópicos relacionados {#related-topics} -- [Estruturas de desenvolvimento](/developers/docs/frameworks/) +- [Frameworks de desenvolvimento](/developers/docs/frameworks/) diff --git a/public/content/translations/pt-br/developers/docs/transactions/index.md b/public/content/translations/pt-br/developers/docs/transactions/index.md index 8b9f9f85a0c..a9a66b541fc 100644 --- a/public/content/translations/pt-br/developers/docs/transactions/index.md +++ b/public/content/translations/pt-br/developers/docs/transactions/index.md @@ -1,20 +1,21 @@ --- -title: Transações -description: 'Uma visão geral das transações no Ethereum: como elas funcionam, sua estrutura de dados e como enviá-las através de um aplicativo.' +title: "Transações" +description: "Uma visão geral das transações no Ethereum: como elas funcionam, sua estrutura de dados e como enviá-las através de um aplicativo." lang: pt-br --- Transações são instruções assinadas criptograficamente de contas. Uma conta iniciará uma transação para atualizar o estado da rede Ethereum. A transação mais simples é transferir ETH de uma conta para outra. -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -Mas para ajudá-lo a entender melhor esta página, recomendamos que você primeiro leia [Contas](/developers/docs/accounts/), [Transações](/developers/docs/transactions/)e nossa [introdução ao Ethereum](/developers/docs/intro-to-ethereum/). +Para ajudar você a entender melhor esta página, recomendamos que você leia primeiro [Contas](/developers/docs/accounts/) e nossa [introdução ao Ethereum](/developers/docs/intro-to-ethereum/). ## O que é uma transação? {#whats-a-transaction} Uma transação Ethereum refere-se a uma ação iniciada por uma conta de propriedade externa, ou seja, uma conta gerenciada por um ser humano, não um contrato. Por exemplo, se Bob enviar a Alice 1 ETH, a conta de Bob deverá ser debitada e a de Alice deverá ser creditada. Esta ação de mudança de estado ocorre no âmbito de uma transação. -![Diagrama mostrando uma transação que causa mudança de estado](./tx.png) _Diagrama adaptado de [Ethereum EVM ilustrado](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ +![Diagrama mostrando uma transação causando mudança de estado](./tx.png) +_Diagrama adaptado de [Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ Transações que alteram o estado da EVM precisam ser transmitidas para toda a rede. Qualquer nó pode transmitir uma solicitação para que uma transação seja executada na EVM; depois que isso acontecer, um validador executará a transação e propagará a mudança de estado resultante para o restante da rede. @@ -22,15 +23,15 @@ As transações exigem uma taxa e devem ser incluídas em um bloco validado. Par Uma transação enviada inclui as seguintes informações: -- `from`: o endereço do remetente que assinará a transação. Ela será uma conta de propriedade externa, pois as contas de contrato não podem enviar transações. -- `para`: o endereço de recebimento (se for uma conta de propriedade externa, a transação transferirá o valor. Se for uma conta de contrato, a transação executará o código do contrato) -- `signature`: o identificador do remetente. Ele é gerado quando a chave privada do remetente assina a transação e confirma que o remetente autorizou essa transação. -- `nonce`: um contador de incremento sequencial que indica o número da transação a partir da conta. -- `value`: a quantidade de ETH a transferir do remetente para o destinatário (denominado em WEI, onde 1ETH equivale a 1e+18wei). -- `input data` – campo opcional para incluir um dado arbitrário -- `gasLimit`: a quantidade máxima de gás que pode ser consumida pela transação. A [EVM](/developers/docs/evm/opcodes) especifica as unidades de gás necessárias para cada etapa computacional -- `maxPriorityFeePerGas`: o preço máximo do gás consumido a ser incluído como gorjeta para o validador. -- `maxFeePerGas`: a taxa máxima por unidade de gás disposta a ser paga pela transação (inclusive de `baseFeePerGas` e `maxPriorityFeePerGas`) +- `from` – o endereço do remetente, que assinará a transação. Ela será uma conta de propriedade externa, pois as contas de contrato não podem enviar transações +- `to` – o endereço de recebimento (se for uma conta de propriedade externa, a transação transferirá valor. Se for uma conta de contrato, a transação executará o código do contrato) +- `signature` – o identificador do remetente. Ele é gerado quando a chave privada do remetente assina a transação e confirma que o remetente autorizou essa transação. +- `nonce` - um contador de incremento sequencial que indica o número da transação da conta +- `value` – quantia de ETH a ser transferida do remetente para o destinatário (denominada em WEI, em que 1 ETH é igual a 1e+18 wei) +- `input data` – campo opcional para incluir dados arbitrários +- `gasLimit` – a quantidade máxima de unidades de gás que pode ser consumida pela transação. A [EVM](/developers/docs/evm/opcodes) especifica as unidades de gás necessárias para cada etapa computacional +- `maxPriorityFeePerGas` - o preço máximo do gás consumido a ser incluído como uma gorjeta para o validador +- `maxFeePerGas` - a taxa máxima por unidade de gás que se está disposto a pagar pela transação (incluindo `baseFeePerGas` e `maxPriorityFeePerGas`) Gás é uma referência ao cálculo necessário para processar a transação por um validador. Os usuários têm que pagar uma taxa por este cálculo. O `gasLimit` e o `maxPriorityFeePerGas` determinam a taxa máxima de transação paga ao validador. [Mais sobre gás](/developers/docs/gas/). @@ -99,22 +100,26 @@ Exemplo de resposta: } ``` -- o `raw` é a transação assinada no [Prefixo de Tamanho Recursivo (RLP)](/developers/docs/data-structures-and-encoding/rlp) na forma codificada -- `tx` é a transação assinada no formato JSON +- o `raw` é a transação assinada em formato codificado com [Prefixo de Comprimento Recursivo (RLP)](/developers/docs/data-structures-and-encoding/rlp) +- o `tx` é a transação assinada em formato JSON Com o hash da assinatura, a transação pode ser provada criptograficamente de que veio do remetente e enviada para a rede. ### O campo de dados {#the-data-field} -A grande maioria das transações acessa um contrato de uma conta de propriedade externa. A maioria dos contratos é escrita em Solidity e interpreta seus campos de dados de acordo com a [interface binária do aplicativo (ABI)](/glossary/#abi). +A grande maioria das transações acessa um contrato de uma conta de propriedade externa. +A maioria dos contratos é escrita em Solidity e interpreta seu campo de dados de acordo com a [interface binária de aplicação (ABI)](/glossary/#abi). -Os primeiros quatro bytes especificam qual função chamar, usando o hash do nome e dos argumentos da função. Às vezes, você pode identificar a função do seletor usando [este banco de dados](https://www.4byte.directory/signatures/). +Os primeiros quatro bytes especificam qual função chamar, usando o hash do nome e dos argumentos da função. +Às vezes, você pode identificar a função do seletor usando [este banco de dados](https://www.4byte.directory/signatures/). -O restante dos dados da chamada são os argumentos, [codificado conforme especificado nas especificações ABI](https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding). +O resto do calldata são os argumentos, [codificados conforme especificado nas especificações da ABI](https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding). -Por exemplo, vejamos [esta transação](https://etherscan.io/tx/0xd0dcbe007569fcfa1902dae0ab8b4e078efe42e231786312289b1eee5590f6a1). Use **Clique para ver mais** para conferir os dados de chamada. +Por exemplo, vamos dar uma olhada [nesta transação](https://etherscan.io/tx/0xd0dcbe007569fcfa1902dae0ab8b4e078efe42e231786312289b1eee5590f6a1). +Use **Clique para ver mais** para ver o calldata. -O seletor de função é `0xa9059cbb`. Existem várias [funções conhecidas com esta assinatura](https://www.4byte.directory/signatures/?bytes4_signature=0xa9059cbb). Nesse caso, [o código-fonte do contrato](https://etherscan.io/address/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48#code) foi carregado para o Etherscan, então sabemos que a função é `transfer(address, uint256)`. +O seletor de função é `0xa9059cbb`. Existem várias [funções conhecidas com esta assinatura](https://www.4byte.directory/signatures/?bytes4_signature=0xa9059cbb). +Neste caso, [o código-fonte do contrato](https://etherscan.io/address/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48#code) foi carregado no Etherscan, então sabemos que a função é `transfer(address,uint256)`. O resto dos dados é: @@ -123,21 +128,23 @@ O resto dos dados é: 000000000000000000000000000000000000000000000000000000003b0559f4 ``` -De acordo com as especificações da ABI, valores inteiros (como endereços, que são inteiros de 20 bytes) aparecem na ABI como palavras de 32 bytes, preenchidos com zeros na frente. Portanto, sabemos que o endereço `para` é [`4f6742badb049791cd9a37ea913f2bac38d01279`](https://etherscan.io/address/0x4f6742badb049791cd9a37ea913f2bac38d01279). O `valor` é 0x3b0559f4 = 990206452. +De acordo com as especificações da ABI, valores inteiros (como endereços, que são inteiros de 20 bytes) aparecem na ABI como palavras de 32 bytes, preenchidos com zeros na frente. +Então, sabemos que o endereço `to` é [`4f6742badb049791cd9a37ea913f2bac38d01279`](https://etherscan.io/address/0x4f6742badb049791cd9a37ea913f2bac38d01279). +O `value` é 0x3b0559f4 = 990206452. ## Tipos de transações {#types-of-transactions} -No Ethereum existem alguns tipos diferentes de transações: +Existem alguns tipos diferentes de transações no Ethereum: - Transações regulares: uma transação de uma conta para outra. - Transações de implantação do contrato: uma transação sem um endereço 'para', onde o campo de dados é usado para o código do contrato. - Execução de um contrato: uma transação que interage com um contrato inteligente implantado. Nesse caso, o endereço "para" é o endereço do contrato inteligente. -### Sobre gás {#on-gas} +### Sobre o gás {#on-gas} Como mencionado, as transações custam [gás](/developers/docs/gas/) para serem executadas. Transações de transferência simples requerem 21.000 unidades de gás. -Então para Bob enviar a Alice 1 ETH para `baseFeePerGas` de 190 gwei e `maxPriorityFeePerGas` de 10 gwei, Bob precisará pagar a seguinte taxa: +Então, para Bob enviar 1 ETH para Alice com um `baseFeePerGas` de 190 gwei e `maxPriorityFeePerGas` de 10 gwei, Bob precisará pagar a seguinte taxa: ``` (190 + 10) * 21000 = 4.200.000 gwei @@ -145,16 +152,16 @@ Então para Bob enviar a Alice 1 ETH para `baseFeePerGas` de 190 gwei e `maxPrio 0,0042 ETH ``` -A conta de Bob será debitada **-1,0042 ETH** (1 ETH para Alice + 0,0042 ETH em taxas de gás) +A conta de Bob será debitada em **-1,0042 ETH** (1 ETH para Alice + 0,0042 ETH em taxas de gás) -A conta de Alice será creditada **+1,0 ETH** +A conta de Alice será creditada em **+1,0 ETH** -A taxa base queimará **-0,00399 ETH** +A taxa base será queimada **-0,00399 ETH** -O validador mantém a gorjeta de **+0,000210 ETH** +O validador fica com a gorjeta **+0,000210 ETH** - -![Diagrama que mostra como o gás não utilizado é reembolsado](./gas-tx.png) _Diagrama adaptado do [Ethereum EVM ilustrado](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ +![Diagrama mostrando como o gás não utilizado é reembolsado](./gas-tx.png) +_Diagrama adaptado de [Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)_ Qualquer gás não usado em uma transação é reembolsado para a conta do usuário. @@ -162,18 +169,21 @@ Qualquer gás não usado em uma transação é reembolsado para a conta do usuá Gás é necessário para qualquer transação que envolva um contrato inteligente. -Contratos inteligentes também podem conter funções conhecidas como [`visões`](https://docs.soliditylang.org/en/latest/contracts.html#view-functions) ou [`puras`](https://docs.soliditylang.org/en/latest/contracts.html#pure-functions), as quais não alteram o estado do contrato. Dessa maneira, nenhum gás é necessário ao chamar essas funções de um EOA. A chamada RPC subjacente para esse cenário é [`eth_call`](/developers/docs/apis/json-rpc#eth_call) +Contratos inteligentes também podem conter funções conhecidas como funções [`view`](https://docs.soliditylang.org/en/latest/contracts.html#view-functions) ou [`pure`](https://docs.soliditylang.org/en/latest/contracts.html#pure-functions), que não alteram o estado do contrato. Dessa maneira, nenhum gás é necessário ao chamar essas funções de um EOA. A chamada RPC subjacente para este cenário é [`eth_call`](/developers/docs/apis/json-rpc#eth_call). -Diferentemente de quando acessadas usando `eth_call`, essas funções ` de visualização` ou `puras "` também são comumente chamadas internamente (ou seja, a partir do próprio contrato ou de outro contrato), o que custa gás. +Diferentemente de quando são acessadas usando `eth_call`, essas funções `view` ou `pure` também são comumente chamadas internamente (ou seja, do próprio contrato ou de outro contrato), o que custa gás. -## Ciclo de vida de transação {#transaction-lifecycle} +## Ciclo de vida da transação {#transaction-lifecycle} Quando uma transação é enviada, acontece o seguinte: -1. Um hash de transação é gerado criptograficamente: `0x97d99bc7729211111a21b12c933c949d4f31684f1d6954ff477d0477538ff017` +1. Um hash de transação é gerado criptograficamente: + `0x97d99bc7729211111a21b12c933c949d4f31684f1d6954ff477d0477538ff017` 2. A transação é então transmitida para a rede e adicionada a um pool de transações que compreende todas as outras transações de rede pendentes. 3. Um validador deve escolher sua transação e incluí-la em um bloco para verificar a transação e considerá-la "bem-sucedida". -4. Com o passar do tempo, o bloco que contém sua transação será atualizado para "justificado" e depois "finalizado". Essas atualizações tornam muito mais certo de que sua transação foi bem-sucedida e nunca será alterada. Uma vez que um bloco é “finalizado”, ele só poderá ser alterado por um ataque na rede que custe muitos bilhões de dólares. +4. Com o passar do tempo, o bloco que contém sua transação será atualizado para "justificado" e depois "finalizado". Essas atualizações tornam muito + mais certo que sua transação foi bem-sucedida e nunca será alterada. Uma vez que um bloco é "finalizado", ele só poderia ser alterado + por um ataque em nível de rede que custaria muitos bilhões de dólares. ## Uma demonstração visual {#a-visual-demo} @@ -181,41 +191,43 @@ Assista Austin mostrar as transações, gás e mineração. -## Envelope de transação digitado {#typed-transaction-envelope} +## Envelope de Transação Tipada {#typed-transaction-envelope} -O Ethereum originalmente tinha um formato para transações. Cada transação possuía um emissor, custo de "queima", parâmetro de "queima", endereçamentos, valores, dados, v, r, e s. Esses campos são [codificados por RLP](/developers/docs/data-structures-and-encoding/rlp/), podendo se parecer com isto: +O Ethereum originalmente tinha um formato para transações. Cada transação possuía um emissor, custo de "queima", parâmetro de "queima", endereçamentos, valores, dados, v, r, e s. Esses campos são [codificados com RLP](/developers/docs/data-structures-and-encoding/rlp/), para se parecer com algo assim: -`RLP ([emissor, taxa de "queima", parâmetros de "queima", destino, valor, dados, v, r, s])` +`RLP([nonce, gasPrice, gasLimit, to, value, data, v, r, s])` -O Ethereum evoluiu para apoiar vários tipos de transações, permitindo que novos recursos, como listas de acesso e [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) sejam implementados sem que isso afete os formatos de transação herdados. +O Ethereum evoluiu para suportar múltiplos tipos de transações para permitir que novos recursos, como listas de acesso e o [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), sejam implementados sem afetar os formatos de transação legados. -[EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) é o que permite esse comportamento. Transações são interpretadas como: +O [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) é o que permite este comportamento. Transações são interpretadas como: `TransactionType || TransactionPayload` Onde os campos são definidos como: -- `TransactionType`: um número entre 0 e 0x7f, para um total de 128 tipos de transações possíveis. -- `TransactionPayload`: um array de bytes arbitrário definido pelo tipo de transação. +- `TransactionType` - um número entre 0 e 0x7f, para um total de 128 tipos de transação possíveis. +- `TransactionPayload` - uma matriz de bytes arbitrária definida pelo tipo de transação. -Baseado no valor do `TransactionType` , a transação pode ser classificada como +Com base no valor de `TransactionType`, uma transação pode ser classificada como: -1. **Transações do tipo 0 (legado):** O formato de transação original usado desde o lançamento do Ethereum. Eles não incluem recursos do [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), como cálculos dinâmicos de taxas de gás ou listas de acesso para contratos inteligentes. As transações legadas não têm um prefixo específico que indique seu tipo em sua forma serializada, começando com o byte `0xf8` ao usar a codificação [Prefixo de comprimento recursivo (RLP, na sigla em inglês)](/developers/docs/data-structures-and-encoding/rlp). O valor TransactionType para essas transações é `0x0`. +1. **Transações do Tipo 0 (Legado):** O formato de transação original usado desde o lançamento do Ethereum. Elas não incluem recursos do [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), como cálculos dinâmicos de taxas de gás ou listas de acesso para contratos inteligentes. As transações legadas não possuem um prefixo específico que indique seu tipo em sua forma serializada, começando com o byte `0xf8` ao usar a codificação [Prefixo de Comprimento Recursivo (RLP)](/developers/docs/data-structures-and-encoding/rlp). O valor de TransactionType para essas transações é `0x0`. -2. **Transações do tipo 1:** Introduzidas na [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930) como parte da [Melhoria de Berlim](/ethereum-forks/#berlin) do Ethereum, essas transações incluem um parâmetro `accessList`. Essa lista especifica endereços e chaves de armazenamento que a transação espera acessar, ajudando a reduzir potencialmente os custos de [gás](/developers/docs/gas/) para transações complexas que envolvem contratos inteligentes. As alterações de mercado da taxa EIP-1559 não estão incluídas nas transações do Tipo 1. As transações do tipo 1 também incluem um parâmetro `yParity`, que pode ser `0x0` ou `0x1`, indicando a paridade do valor y da assinatura secp256k1. Elas começam com o byte `0x01`, e seu valor TransactionType é `0x1`. +2. **Transações do Tipo 1:** Introduzidas no [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930) como parte da [Atualização Berlim](/ethereum-forks/#berlin) do Ethereum, essas transações incluem um parâmetro `accessList`. Esta lista especifica os endereços e as chaves de armazenamento que a transação espera acessar, ajudando a reduzir potencialmente os custos de [gás](/developers/docs/gas/) para transações complexas que envolvem contratos inteligentes. As alterações de mercado da taxa EIP-1559 não estão incluídas nas transações do Tipo 1. As transações do tipo 1 também incluem um parâmetro `yParity`, que pode ser `0x0` ou `0x1`, indicando a paridade do valor-y da assinatura secp256k1. Elas são identificadas começando com o byte `0x01`, e seu valor de TransactionType é `0x1`. -3. **Transações do Tipo 2**, comumente conhecidas como transações EIP-1559, são transações introduzidas no [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), na [Melhoria Londres](/ethereum-forks/#london) do Ethereum. Elas se tornaram o tipo de transação padrão na rede Ethereum. Essas transações introduzem um novo mecanismo de mercado de taxas que melhora a previsibilidade ao separar a taxa de transação em uma taxa base e uma taxa de prioridade. Elas começam com o byte `0x02` e incluem campos como `maxPriorityFeePerGas` e `maxFeePerGas`. As transações do Tipo 2 agora são o padrão devido à sua flexibilidade e eficiência, especialmente preferidas durante períodos de alta congestão na rede por sua capacidade de ajudar os usuários a gerenciar as taxas de transação de forma mais previsível. O valor TransactionType para essas transações é `0x2`. +3. **Transações do tipo 2**, comumente chamadas de transações EIP-1559, são transações introduzidas no [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), na [Atualização Londres](/ethereum-forks/#london) do Ethereum. Elas se tornaram o tipo de transação padrão na rede Ethereum. Essas transações introduzem um novo mecanismo de mercado de taxas que melhora a previsibilidade ao separar a taxa de transação em uma taxa base e uma taxa de prioridade. Elas começam com o byte `0x02` e incluem campos como `maxPriorityFeePerGas` e `maxFeePerGas`. As transações do Tipo 2 agora são o padrão devido à sua flexibilidade e eficiência, especialmente preferidas durante períodos de alta congestão na rede por sua capacidade de ajudar os usuários a gerenciar as taxas de transação de forma mais previsível. O valor de TransactionType para essas transações é `0x2`. +4. **Transações do Tipo 3 (Blob)** foram introduzidas no [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) como parte da [Atualização Dencun](/ethereum-forks/#dencun) do Ethereum. Essas transações são projetadas para manipular dados "blob" (Binary Large Objects) de forma mais eficiente, beneficiando particularmente os rollups da Layer 2, pois fornecem uma maneira de postar dados na rede Ethereum a um custo menor. As transações blob incluem campos adicionais, como `blobVersionedHashes`, `maxFeePerBlobGas` e `blobGasPrice`. Elas começam com o byte `0x03`, e seu valor de TransactionType é `0x3`. As transações de blobs representam uma melhoria significativa na disponibilidade de dados e nos recursos de dimensionamento do Ethereum. +5. **Transações do Tipo 4** foram introduzidas no [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) como parte da [Atualização Pectra](/roadmap/pectra/) do Ethereum. Essas transações são projetadas para serem compatíveis com a abstração de conta. Elas permitem que as EOAs se comportem temporariamente como contas de contrato inteligente sem comprometer sua funcionalidade original. Elas incluem um parâmetro `authorization_list`, que especifica o contrato inteligente para o qual a EOA delega sua autoridade. Após a transação, o campo de código da EOA terá o endereço do contrato inteligente delegado. ## Leitura adicional {#further-reading} -- [EIP-2718: Typed Transaction Envelope](https://eips.ethereum.org/EIPS/eip-2718) +- [EIP-2718: Envelope de transação tipada](https://eips.ethereum.org/EIPS/eip-2718) _Conhece um recurso da comunidade que o ajudou? Edite esta página e adicione-a!_ ## Tópicos relacionados {#related-topics} - [Contas](/developers/docs/accounts/) -- [Máquina virtual de Ethereum (EVM)](/developers/docs/evm/) +- [Máquina Virtual Ethereum (EVM)](/developers/docs/evm/) - [Gás](/developers/docs/gas/) diff --git a/public/content/translations/pt-br/developers/docs/web2-vs-web3/index.md b/public/content/translations/pt-br/developers/docs/web2-vs-web3/index.md index 15e5e20e0d5..3f1a00ddd89 100644 --- a/public/content/translations/pt-br/developers/docs/web2-vs-web3/index.md +++ b/public/content/translations/pt-br/developers/docs/web2-vs-web3/index.md @@ -1,12 +1,12 @@ --- title: Web2 vs Web3 -description: +description: "Comparar os serviços centralizados do Web2 com as aplicações descentralizadas da Web3 baseadas na tecnologia Ethereum blockchain." lang: pt-br --- Web2 refere-se à versão da internet que a maioria de nós conhecemos hoje. Uma internet dominada por empresas que prestam serviços em troca de seus dados pessoais. Web3, no contexto da Ethereum, refere-se a aplicativos descentralizados que são executados na cadeia de blocos. Estes são aplicativos que permitem a qualquer pessoa participar sem monetizar seus dados pessoais. -Procurando por uma explicação mais adaptada para iniciantes? Veja nossa [introdução ao Web3](/web3/). +Procurando por uma explicação mais adaptada para iniciantes? Veja nossa [introdução à web3](/web3/). ## Benefícios da Web3 {#web3-benefits} @@ -36,27 +36,27 @@ O Web3 tem alguns limites neste momento: - Acessibilidade – A falta de integração em navegadores de internet modernos torna a web3 menos acessível à maioria dos usuários. - Custo – os dapps mais bem sucedidos colocam pequenas partes do seu código na blockchain, pois é caro. -## Centralização vs descentralização {#centralization-vs-decentralization} +## Centralização vs. descentralização {#centralization-vs-decentralization} Na tabela abaixo, listamos algumas das vantagens e desvantagens das redes digitais centralizadas e descentralizadas. -| Sistemas centralizados | Sistemas Descentralizados | -| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Diâmetro da rede baixo (todos os participantes estão conectados a uma autoridade central); a informação propaga-se rapidamente, já que a propagação é tratada por uma autoridade central com muitos recursos computacionais. | Os demais participantes da rede podem estar muito distantes uns dos outros. A transmissão de informações de um lado da rede pode levar muito tempo para chegar à outra parte. | -| Geralmente maior desempenho (maior taxa de transferência, menos recursos computacionais totais gastos) e mais fácil de implementar. | Geralmente maior desempenho (maior taxa de transferência, menos recursos computacionais totais gastos) e mais fácil de implementar. | -| Em caso de conflito de dados, a resolução é clara e fácil: a fonte final da verdade é a autoridade central. | Para a resolução de litígios, é necessário um protocolo (frequentemente complexo) se os pares fizerem afirmações conflitantes sobre o estado dos dados em que os participantes devem ser sincronizados. | -| Um ponto único do fracasso: os agentes maliciosos poderão conseguir derrubar a rede dirigindo-se à autoridade central. | Nenhum ponto de falha: a rede pode ainda funcionar mesmo que uma grande percentagem de participantes seja atacada/eliminada. | +| Sistemas centralizados | Sistemas Descentralizados | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Diâmetro da rede baixo (todos os participantes estão conectados a uma autoridade central); a informação propaga-se rapidamente, já que a propagação é tratada por uma autoridade central com muitos recursos computacionais. | Os demais participantes da rede podem estar muito distantes uns dos outros. A transmissão de informações de um lado da rede pode levar muito tempo para chegar à outra parte. | +| Geralmente maior desempenho (maior taxa de transferência, menos recursos computacionais totais gastos) e mais fácil de implementar. | Geralmente maior desempenho (maior taxa de transferência, menos recursos computacionais totais gastos) e mais fácil de implementar. | +| Em caso de conflito de dados, a resolução é clara e fácil: a fonte final da verdade é a autoridade central. | Para a resolução de litígios, é necessário um protocolo (frequentemente complexo) se os pares fizerem afirmações conflitantes sobre o estado dos dados em que os participantes devem ser sincronizados. | +| Um ponto único do fracasso: os agentes maliciosos poderão conseguir derrubar a rede dirigindo-se à autoridade central. | Nenhum ponto de falha: a rede pode ainda funcionar mesmo que uma grande percentagem de participantes seja atacada/eliminada. | | A coordenação entre os participantes na rede é muito mais fácil e é gerida por uma autoridade central. A autoridade central pode obrigar os participantes da rede a adotarem melhorias, melhorias de protocolo, etc., com muito pouca fricção. | A coordenação é muitas vezes difícil, já que nenhum agente tem a última palavra sobre decisões a nível de rede, melhorias de protocolo, etc. No pior dos casos, a rede está propensa a fracturar quando há desacordos sobre alterações de protocolo. | -| A autoridade central pode censurar dados, impedindo potencialmente partes da rede de interagir com o resto da rede. | A censura é muito mais difícil, pois a informação tem muitas maneiras de se propagar através da rede. | -| A participação na rede é controlada pela autoridade central. | Qualquer um pode participar da rede; não há “guardiões”. O ideal é que o custo da participação seja muito baixo. | +| A autoridade central pode censurar dados, impedindo potencialmente partes da rede de interagir com o resto da rede. | A censura é muito mais difícil, pois a informação tem muitas maneiras de se propagar através da rede. | +| A participação na rede é controlada pela autoridade central. | Qualquer um pode participar da rede; não há “guardiões”. O ideal é que o custo da participação seja muito baixo. | Observe que estes são padrões gerais que podem não se aplicar em todas as redes. Além disso, na realidade, o grau em que uma rede é centralizada/descentralizada reside em um espectro; nenhuma rede é inteiramente centralizada ou inteiramente descentralizada. -## Leia mais {#further-reading} +## Leitura adicional {#further-reading} -- [O que é Web3?](/web3/) - _ethereum.org_ +- [O que é a Web3?](/web3/) - _ethereum.org_ - [A Arquitetura de um aplicativo Web 3.0](https://www.preethikasireddy.com/post/the-architecture-of-a-web-3-0-application) - _Preethi Kasireddy_ -- [O Significado da Descentralização](https://medium.com/@VitalikButerin/the-meaning-of-decentralization-a0c92b76a274) _6 de fevereiro de 2017 – Vitalik Buterin_ -- [Por que a descentralização é importante](https://medium.com/s/story/why-decentralization-matters-5e3f79f7638e) _18 de fevereiro de 2018 – Chris Dixon_ -- [O que é o Web 3.0 e por que ele é importante](https://medium.com/fabric-ventures/what-is-web-3-0-why-it-matters-934eb07f3d2b) _31 de dezembro de 2019 – Max Mersch e Richard Muirhead_ -- [Por que precisamos do Web 3.0](https://medium.com/@gavofyork/why-we-need-web-3-0-5da4f2bf95ab) _12 de setembro de 2018 - Gavin Wood_ +- [O Significado da Descentralização](https://medium.com/@VitalikButerin/the-meaning-of-decentralization-a0c92b76a274) _6 de fev. de 2017 - Vitalik Buterin_ +- [Por que a descentralização é importante](https://onezero.medium.com/why-decentralization-matters-5e3f79f7638e) _18 de fev. de 2018 - Chris Dixon_ +- [O que é a Web 3.0 e por que ela é importante](https://medium.com/fabric-ventures/what-is-web-3-0-why-it-matters-934eb07f3d2b) _31 de dez. de 2019 - Max Mersch e Richard Muirhead_ +- [Por que precisamos da Web 3.0](https://gavofyork.medium.com/why-we-need-web-3-0-5da4f2bf95ab) _12 de set. de 2018 - Gavin Wood_ diff --git a/public/content/translations/pt-br/developers/docs/wrapped-eth/index.md b/public/content/translations/pt-br/developers/docs/wrapped-eth/index.md index a8b7225af4b..97f66878dd5 100644 --- a/public/content/translations/pt-br/developers/docs/wrapped-eth/index.md +++ b/public/content/translations/pt-br/developers/docs/wrapped-eth/index.md @@ -1,6 +1,6 @@ --- -title: O que é Wrapped Ether (WETH) -description: Uma introdução ao Wrapped ether (WETH), um wrapper compatível com ERC20 para ether (ETH). +title: "O que é Wrapped Ether (WETH)" +description: "Uma introdução ao Wrapped ether (WETH), um wrapper compatível com ERC20 para ether (ETH)." lang: pt-br --- @@ -35,19 +35,16 @@ O [ERC-20](/developers/docs/standards/tokens/erc-20/) define uma interface padr Você paga taxas de gás para empacotar ou desempacotar ETH usando o contrato WETH. - O WETH é geralmente considerado seguro porque é baseado em um contrato inteligente simples e de eficiência comprovada. O contrato WETH também foi formalmente verificado, que é o mais alto padrão de segurança para contratos inteligentes no Ethereum. - -Além da [implementação canônica do WETH] (https://etherscan.io/token/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2) descrita nesta página, há outras variantes disponíveis. Eles podem ser tokens personalizados criados por desenvolvedores de aplicativos ou versões emitidas em outras blockchains e podem se comportar de forma diferente ou ter propriedades de segurança diferentes. \*\*Sempre verifique novamente as informações do token para saber com qual implementação do WETH você está interagindo - +Além da [implementação canônica do WETH](https://etherscan.io/token/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2) descrita nesta página, há outras variantes disponíveis. Eles podem ser tokens personalizados criados por desenvolvedores de aplicativos ou versões emitidas em outras blockchains e podem se comportar de forma diferente ou ter propriedades de segurança diferentes. \*\*Sempre verifique novamente as informações do token para saber com qual implementação do WETH você está interagindo @@ -55,7 +52,6 @@ Além da [implementação canônica do WETH] (https://etherscan.io/token/0xc02aa - [Rede principal do Ethereum](https://etherscan.io/token/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2) - [Arbitrum](https://arbiscan.io/token/0x82af49447d8a07e3bd95bd0d56f35241523fbab1) - [Optimism](https://optimistic.etherscan.io/token/0x4200000000000000000000000000000000000006) - ## Leitura adicional {#further-reading} diff --git a/public/content/translations/pt-br/developers/tutorials/a-developers-guide-to-ethereum-part-one/index.md b/public/content/translations/pt-br/developers/tutorials/a-developers-guide-to-ethereum-part-one/index.md index 7e4e56b22c1..2cd0404a826 100644 --- a/public/content/translations/pt-br/developers/tutorials/a-developers-guide-to-ethereum-part-one/index.md +++ b/public/content/translations/pt-br/developers/tutorials/a-developers-guide-to-ethereum-part-one/index.md @@ -1,33 +1,32 @@ --- -title: Uma introdução do desenvolvedor Python ao Ethereum, parte 1 -description: Uma introdução ao desenvolvimento do Ethereum, especialmente útil para aqueles com conhecimento sobre a linguagem de programação Python +title: "Uma introdução ao Ethereum para desenvolvedores Python, parte 1" +description: "Uma introdução ao desenvolvimento em Ethereum, especialmente útil para aqueles com conhecimento da linguagem de programação Python" author: Marc Garreau lang: pt-br -tags: - - "python" - - "web3.py" +tags: [ "Python", "web3.py" ] skill: beginner published: 2020-09-08 -source: O encantador de cobras +source: Snake charmers sourceUrl: https://snakecharmers.ethereum.org/a-developers-guide-to-ethereum-pt-1/ --- -Então, você ouviu falar sobre esta coisa do Ethereum e está pronto para se aventurar no buraco do coelho? Este post cobrirá rapidamente alguns conceitos básicos de blockchain e, em seguida, fará com que você interaja com um nó simulado do Ethereum – lendo dados do bloco, verificando saldos da conta e enviando transações. Em todo o caminho, vamos destacar as diferenças entre as maneiras tradicionais de desenvolver aplicativos e este novo paradigma descentralizado. +Então, você já ouviu falar de Ethereum e está pronto para entrar na toca do coelho? Este artigo abordará rapidamente alguns conceitos básicos de blockchain e, em seguida, fará com que você interaja com um nó Ethereum simulado – lendo dados de blocos, verificando saldos de contas e enviando transações. Ao longo do caminho, destacaremos as diferenças entre as formas tradicionais de criar aplicativos e este novo paradigma descentralizado. -## Pré-requisitos de software {#soft-prerequisites} +## (Pré-requisitos flexíveis) {#soft-prerequisites} -Este post espera ser acessível a muitos desenvolvedores. Usaremos [ferramentas Python](/developers/docs/programming-languages/python/), mas elas são apenas um meio para as ideias — não há problema se você não é um desenvolvedor Python. No entanto, vou fazer apenas algumas suposições sobre o que você já sabe, para que possamos passar rapidamente aos temas específicos do Ethereum. +Este artigo pretende ser acessível a uma vasta gama de desenvolvedores. [Ferramentas Python](/developers/docs/programming-languages/python/) serão usadas, mas elas são apenas um veículo para as ideias – não há problema se você não for um desenvolvedor Python. No entanto, farei apenas algumas suposições sobre o que você já sabe, para que possamos avançar rapidamente para os pontos específicos do Ethereum. Suposições: -- Você pode utilizar um terminal, +- Você sabe usar um terminal, - Você já escreveu algumas linhas de código Python, -- A versão 3.6 ou superior do Python está instalada no seu computador (uso de um [ambiente virtual](https://realpython.com/effective-python-environment/#virtual-environments) é fortemente recomendado) e -- você já usou o `pip`, instalador de pacotes do Python. Novamente, se algum destes pré-requisitos não for verdadeiro, ou se você não planeja reproduzir o código apresentado neste artigo, é provável que você ainda possa acompanhar sem maiores problemas. +- A versão 3.6 ou superior do Python está instalada em sua máquina (o uso de um [ambiente virtual](https://realpython.com/effective-python-environment/#virtual-environments) é fortemente incentivado), e +- você já usou o `pip`, o instalador de pacotes do Python. + Novamente, se algum desses pontos não for verdadeiro, ou se você não planeja reproduzir o código neste artigo, provavelmente ainda conseguirá acompanhar sem problemas. -## Blockchains, em poucas palavras {#blockchains-briefly} +## Blockchains, resumidamente {#blockchains-briefly} -Há muitas maneiras de descrever o Ethereum, mas no fundo é uma blockchain. As blockchains são compostas de uma série de blocos, então vamos começar por aí. Em termos mais simples, cada bloco na blockchain do Ethereum é somente um conjunto de metadados e uma lista de transações. No formato JSON, que se parece com algo assim: +Existem muitas maneiras de descrever o Ethereum, mas em sua essência, ele é uma blockchain. As blockchains são compostas por uma série de blocos, então vamos começar por aí. Em termos mais simples, cada bloco na blockchain Ethereum é apenas um conjunto de metadados e uma lista de transações. No formato JSON, se parece com algo assim: ```json { @@ -41,98 +40,98 @@ Há muitas maneiras de descrever o Ethereum, mas no fundo é uma blockchain. As Cada [bloco](/developers/docs/blocks/) tem uma referência ao bloco que veio antes dele; o `parentHash` é simplesmente o hash do bloco anterior. -Observação: o Ethereum faz uso regular de funções hash para produzir valores de tamanho fixo ("hashes"). Os hashes desempenham um papel importante no Ethereum, mas você pode pensar neles como IDs exclusivos por enquanto. +Observação: o Ethereum faz uso regular de funções hash para produzir valores de tamanho fixo (“hashes”). Os hashes desempenham um papel importante no Ethereum, mas você pode pensar neles como IDs exclusivos por enquanto. -![Um diagrama que retrata uma blockchain incluindo os dados dentro de cada bloco](./blockchain-diagram.png) +![Um diagrama que retrata uma blockchain, incluindo os dados dentro de cada bloco](./blockchain-diagram.png) -_Uma blockchain é essencialmente uma lista encadeada; onde cada bloco tem uma referência ao bloco anterior._ +_Uma blockchain é essencialmente uma lista encadeada; cada bloco tem uma referência ao bloco anterior._ -Esta estrutura de dados não é nada nova, mas as regras (por exemplo, os protocolos peer-to-peer) que regem a rede são. Não há autoridade central; a rede de pares deve colaborar para sustentar a rede e competir para decidir quais transações incluir no próximo bloco. Então, quando você quiser enviar algum dinheiro para um amigo, você precisará transmitir essa transação para a rede, depois espere que ela seja incluída em um próximo bloco. +Essa estrutura de dados não é nova, mas as regras (ou seja, protocolos ponto a ponto) que governam a rede, sim. Não há autoridade central; a rede de pares deve colaborar para sustentar a rede e competir para decidir quais transações incluir no próximo bloco. Então, quando você quiser enviar dinheiro para um amigo, precisará transmitir essa transação para a rede e esperar que ela seja incluída em um bloco futuro. -A única maneira de a blockchain verificar se o dinheiro foi realmente enviado de um usuário para outro é usar uma moeda nativa de (isto é, criada e governada por) aquela blockchain. No Ethereum, esta moeda é chamada ether, e a blockchain Ethereum contém o único registro oficial dos saldos das contas. +A única maneira de a blockchain verificar se o dinheiro foi realmente enviado de um usuário para outro é usar uma moeda nativa daquela blockchain (ou seja, criada e governada por ela). No Ethereum, essa moeda é chamada ether, e a blockchain Ethereum contém o único registro oficial de saldos de contas. ## Um novo paradigma {#a-new-paradigm} -Esta nova pilha de tecnologia descentralizada gerou novas ferramentas de desenvolvedor. Tais ferramentas existem em muitas linguagens de programação, mas vamos analisar através das lentes do Python. Para reiterar: mesmo que o Python não seja sua linguagem escolhida, você não terá muitos problemas para acompanhar. +Essa nova pilha de tecnologia descentralizada gerou novas ferramentas para desenvolvedores. Essas ferramentas existem em muitas linguagens de programação, mas nós as veremos pela ótica do Python. Reiterando: mesmo que Python não seja sua linguagem de escolha, não deve ser muito difícil acompanhar. -Os desenvolvedores do Python que querem interagir com o Ethereum provavelmente usem a [Web3.py](https://web3py.readthedocs.io/). Web3.py é uma biblioteca que simplifica muito a forma como você se conecta a um nó Ethereum, e depois envia e recebe dados dele. +Desenvolvedores Python que desejam interagir com o Ethereum provavelmente usarão o [Web3.py](https://web3py.readthedocs.io/). Web3.py é uma biblioteca que simplifica muito a maneira como você se conecta a um nó Ethereum e, em seguida, envia e recebe dados dele. -Nota: "Nó Ethereum" e "Cliente Ethereum" são usados de forma intercambiável. Em ambos os casos, refere-se ao software que um participante da rede Ethereum executa. Este software pode ler dados de blocos, receber atualizações quando novos blocos são adicionados à cadeia, transmitir novas transações e mais. Tecnicamente, o cliente é o software, o nódulo é o computador que executa o software. +Observação: “nó Ethereum” e “cliente Ethereum” são usados de forma intercambiável. Em ambos os casos, refere-se ao software que um participante da rede Ethereum executa. Este software pode ler dados de blocos, receber atualizações quando novos blocos são adicionados à cadeia, transmitir novas transações e muito mais. Tecnicamente, o cliente é o software, e o nó é o computador que executa o software. -[Clientes Ethereum](/developers/docs/nodes-and-clients/) podem ser configurados para serem acessíveis por [IPC](https://wikipedia.org/wiki/Inter-process_communication), HTTPS ou Websockets, então Web3.py precisará espelhar esta configuração. Web3.py refere-se a estas opções de conexão como **provedores**. Você vai querer escolher um dos três provedores para vincular a instância da Web3.py ao seu nó. +[Clientes Ethereum](/developers/docs/nodes-and-clients/) podem ser configurados para serem acessíveis por [IPC](https://wikipedia.org/wiki/Inter-process_communication), HTTP ou Websockets, então o Web3.py precisará espelhar essa configuração. O Web3.py se refere a essas opções de conexão como **provedores**. Você precisará escolher um dos três provedores para vincular a instância do Web3.py com seu nó. -![Um diagrama mostrando como web3.py usa IPC para conectar seu aplicativo a um nódulo Ethereum](./web3py-and-nodes.png) +![Um diagrama mostrando como o web3.py usa IPC para conectar seu aplicativo a um nó Ethereum](./web3py-and-nodes.png) -_Configure o nó Ethereum e o Web3.py para se comunicarem através do mesmo protocolo, por exemplo, o IPC neste diagrama._ +_Configure o nó Ethereum e o Web3.py para se comunicarem através do mesmo protocolo, por exemplo, IPC neste diagrama._ -Uma vez que o Web3.py estiver configurado corretamente, você pode começar a interagir com a blockchain. Aqui estão alguns exemplos de uso da Web3.py como uma prévia do que está por vir: +Uma vez que o Web3.py esteja configurado corretamente, você pode começar a interagir com a blockchain. Aqui estão alguns exemplos de uso do Web3.py como uma prévia do que está por vir: ```python -# read block data: +# ler dados de bloco: w3.eth.get_block('latest') -# send a transaction: +# enviar uma transação: w3.eth.send_transaction({'from': ..., 'to': ..., 'value': ...}) ``` ## Instalação {#installation} -Neste guia, vamos trabalhar apenas com um interpretador de Python. Não criaremos nenhum diretório, arquivos, classes ou funções. +Neste passo a passo, trabalharemos apenas dentro de um interpretador Python. Não criaremos nenhum diretório, arquivo, classe ou função. Observação: nos exemplos abaixo, os comandos que começam com `$` devem ser executados no terminal. (Não digite o `$`, ele apenas significa o início da linha.) -Primeiro, instale [IPython](https://ipython.org/) para explorar em um ambiente amigável. IPython propõe, entre outros, um recurso de autopreenchimento com tab, o que facilita a navegação no Web3.py. +Primeiro, instale o [IPython](https://ipython.org/) para ter um ambiente amigável para explorar. O IPython oferece preenchimento com a tecla Tab, entre outros recursos, tornando muito mais fácil ver o que é possível dentro do Web3.py. ```bash pip install ipython ``` -Web3.py é publicado sob o nome `web3`. Instale-o assim: +O Web3.py é publicado com o nome `web3`. Instale-o da seguinte forma: ```bash pip install web3 ``` -Mais uma coisa: vamos simular uma blockchain mais tarde, o que requer mais algumas dependências. Você pode instalar por meio de: +Mais uma coisa – vamos simular uma blockchain mais tarde, o que requer mais algumas dependências. Você pode instalá-las via: ```bash pip install 'web3[tester]' ``` -Você está pronto para começar! +Está tudo pronto para começar! -Nota: o pacote `web3[tester]` funciona até Python 3.10.xx +Observação: o pacote `web3[tester]` funciona até o Python 3.10.xx -## Crie uma sandbox {#spin-up-a-sandbox} +## Iniciando um sandbox {#spin-up-a-sandbox} -Abra um novo ambiente Python executando o `ipython` no seu terminal. Isso é como executar `python`, mas vem com mais "efeitos especiais". +Abra um novo ambiente Python executando `ipython` em seu terminal. Isso é comparável a executar `python`, mas vem com mais recursos extras. ```bash ipython ``` -Isso mostrará algumas informações sobre as versões do Python e do IPython que você está executando, então você deve ver um prompt esperando por uma entrada: +Isso imprimirá algumas informações sobre as versões do Python e do IPython que você está executando, e então você verá um prompt aguardando a entrada: ```python In [1]: ``` -Você está olhando para um shell interativo do Python agora. Essencialmente, é um ambiente de testes para brincar. Se você chegou até aqui, é hora de importar Web3.py: +Você está vendo um shell interativo do Python agora. Essencialmente, é um sandbox para experimentar. Se você chegou até aqui, é hora de importar o Web3.py: ```python In [1]: from web3 import Web3 ``` -## Introduzindo o módulo Web3 {#introducing-the-web3-module} +## Apresentando o módulo Web3 {#introducing-the-web3-module} -Além de ser um gateway para Ethereum, o módulo [Web3](https://web3py.readthedocs.io/en/stable/overview.html#base-api) oferece algumas funções práticas. Vamos ver algumas. +Além de ser um portal para o Ethereum, o módulo [Web3](https://web3py.readthedocs.io/en/stable/overview.html#base-api) oferece algumas funções de conveniência. Vamos explorar algumas delas. -Em um aplicativo Ethereum, você normalmente precisará converter denominações de moeda. O módulo web3 fornece alguns métodos auxiliares apenas para isso: [from_wei](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.from_wei) e [to_wei](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_wei). +Em um aplicativo Ethereum, você comumente precisará converter denominações de moeda. O módulo Web3 fornece alguns métodos auxiliares apenas para isso: [from_wei](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.from_wei) e [to_wei](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_wei). -Observação: os computadores são notoriamente pouco eficazes para lidar com números decimais. Para contornar isso, os desenvolvedores costumam armazenar valores em dólares em centavos. Por exemplo, um item com preço de $5,99 pode ser armazenado no banco de dados como 599. +Observação: computadores são conhecidos por não lidarem bem com matemática decimal. Para contornar isso, os desenvolvedores geralmente armazenam valores em dólares como centavos. Por exemplo, um item com o preço de US$ 5,99 pode ser armazenado no banco de dados como 599. -Um padrão similar é usado ao lidar com transações em ether. No entanto, em vez de dois pontos decimais, ether tem 18! A menor denominação de ether é chamada de wei, portanto, esse é o valor especificado ao enviar transações. +Um padrão semelhante é usado ao lidar com transações em ether. No entanto, em vez de duas casas decimais, o ether tem 18! A menor denominação do ether é chamada de wei, então esse é o valor especificado ao enviar transações. 1 ether = 1000000000000000000 wei @@ -140,7 +139,7 @@ Um padrão similar é usado ao lidar com transações em ether. No entant -Tente converter alguns valores de e para wei. Note que [existem nomes para muitas das denominações](https://web3py.readthedocs.io/en/stable/troubleshooting.html#how-do-i-convert-currency-denominations) entre ether e wei. Um dos mais conhecidos entre eles é o **gwei**, já que é frequentemente como as taxas de transação são representadas. +Tente converter alguns valores de e para wei. Observe que [existem nomes para muitas das denominações](https://web3py.readthedocs.io/en/stable/troubleshooting.html#how-do-i-convert-currency-denominations) entre ether e wei. Um dos mais conhecidos entre eles é o **gwei**, pois é frequentemente como as taxas de transação são representadas. ```python In [2]: Web3.to_wei(1, 'ether') @@ -150,32 +149,33 @@ In [3]: Web3.from_wei(500000000, 'gwei') Out[3]: Decimal('0.5') ``` -Outros métodos utilitários no módulo Web3 incluem conversores de formato de dados (por exemplo, [`toHex`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.toHex)), os métodos para gerar endereços (por exemplo, [`isAddress`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.isAddress)) e funções hash (por exemplo, [`keccak`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.keccak)). Muitos deles serão cobertos mais tarde pela série. Para ver todos os métodos e propriedades disponíveis, utilize o autopreenchimento do IPython, digitando `Web3` e pressionando a tecla tab duas vezes após o ponto. +Outros métodos utilitários no módulo Web3 incluem conversores de formato de dados (por exemplo, [`toHex`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.toHex)), auxiliares de endereço (por exemplo, [`isAddress`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.isAddress)) e funções de hash (por exemplo, [`keccak`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.keccak)). Muitos deles serão abordados mais adiante na série. Para ver todos os métodos e propriedades disponíveis, utilize o preenchimento automático do IPython digitando `Web3`. e pressionando a tecla Tab duas vezes após o ponto. -## Se comunicar com a cadeia {#talk-to-the-chain} +## Conversando com a cadeia {#talk-to-the-chain} -Os métodos práticos são convenientes, mas vamos passar à blockchain. O próximo passo é configurar o Web3.py para se comunicar com um nó Ethereum. Aqui temos a opção de usar os provedores IPC, HTTPS ou Websocket. +Os métodos de conveniência são ótimos, mas vamos passar para a blockchain. O próximo passo é configurar o Web3.py para se comunicar com um nó Ethereum. Aqui, temos a opção de usar os provedores IPC, HTTP ou Websocket. -Não vamos nos adentrar nesse tema, mas um exemplo de um fluxo de trabalho completo usando o provedor HTTP pode parecer algo assim: +Não seguiremos por este caminho, mas um exemplo de um fluxo de trabalho completo usando o Provedor HTTP pode ser algo assim: -- Baixe um nó Ethereum, por exemplo, [Geth](https://geth.ethereum.org/). -- Inicie o Geth em uma janela de terminal e aguarde a sincronização da rede. A porta HTTP padrão é `8545`, mas é configurável. -- Peça ao Web3.py para se conectar ao nó via HTTP, no `localhost:8545`. `w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))` +- Baixe um nó Ethereum, por exemplo, o [Geth](https://geth.ethereum.org/). +- Inicie o Geth em uma janela de terminal e espere que ele sincronize com a rede. A porta HTTP padrão é `8545`, mas é configurável. +- Diga ao Web3.py para se conectar ao nó via HTTP, em `localhost:8545`. + `w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))` - Use a instância `w3` para interagir com o nó. -Embora esta seja uma maneira "real" de fazer isso, o processo de sincronização leva horas e é desnecessário se você só quer um ambiente de desenvolvimento. A Web3.py expõe um quarto provedor para esse propósito, o **EthereumTesterProvider**. Este provedor de teste se vincula a um nó Ethereum simulado com autorizações abrangentes e moeda falsa para utilizar. +Embora esta seja uma maneira “real” de fazer isso, o processo de sincronização leva horas e é desnecessário se você só quer um ambiente de desenvolvimento. O Web3.py expõe um quarto provedor para este fim, o **EthereumTesterProvider**. Este provedor de teste se vincula a um nó Ethereum simulado com permissões flexíveis e moeda falsa para experimentar. -![Um diagrama mostrando o EthereumTesterProvider que vincula o seu aplicativo web3.py a um nó simulado de Ethereum](./ethereumtesterprovider.png) +![Um diagrama mostrando o EthereumTesterProvider que vincula o seu aplicativo web3.py a um nó Ethereum simulado](./ethereumtesterprovider.png) -_O EthereumTesterProvider conecta-se a um nó simulado e é útil para ambientes de desenvolvimento rápido._ +_O EthereumTesterProvider se conecta a um nó simulado e é útil para ambientes de desenvolvimento rápidos._ -O nó simulado é chamado [eth-tester](https://github.com/ethereum/eth-tester) e o instalamos como parte do `pip install web3[tester]`. Configurar o Web3.py para usar este provedor de teste é tão simples como: +Esse nó simulado é chamado [eth-tester](https://github.com/ethereum/eth-tester) e nós o instalamos como parte do comando `pip install web3[tester]`. Configurar o Web3.py para usar este provedor de teste é tão simples quanto: ```python In [4]: w3 = Web3(Web3.EthereumTesterProvider()) ``` -Agora você está pronto para navegar pela cadeia! Disso as pessoas não falam. É algo que eu acabei de inventar. Façamos um tour rápido. +Agora você está pronto para surfar na cadeia! Isso não é algo que as pessoas dizem. Eu acabei de inventar isso. Vamos fazer um tour rápido. ## O tour rápido {#the-quick-tour} @@ -186,11 +186,11 @@ In [5]: w3.is_connected() Out[5]: True ``` -Já que estamos utilizando o provedor de teste, esse não é um teste muito importante, mas se ele falhar, você provavelmente digitou algo errado ao instanciar a variável `w3`. Verifique se você incluiu os parênteses internos, ou seja, `Web3.EthereumTesterProvider()`. +Como estamos usando o provedor de teste, este não é um teste muito valioso, mas se ele falhar, é provável que você tenha digitado algo errado ao instanciar a variável `w3`. Verifique se você incluiu os parênteses internos, ou seja, `Web3.EthereumTesterProvider()`. -## Parada n.º 1 do tour: [contas](/developers/docs/accounts/) {#tour-stop-1-accounts} +## Parada do tour nº 1: [contas](/developers/docs/accounts/) {#tour-stop-1-accounts} -Por conveniência, o provedor de teste criou algumas contas e as pré-carregou com o ether. +Por conveniência, o provedor de teste criou algumas contas e as pré-carregou com ether de teste. Primeiro, vamos ver uma lista dessas contas: @@ -201,16 +201,16 @@ Out[6]: ['0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf', '0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69', ...] ``` -Se você executar esse comando, você deverá ver uma lista de dez variáveis que começam com `0x`. Cada um é um **endereço público** e é, em alguns aspectos, análogo ao número da conta em uma conta corrente. Você forneceria este endereço a alguém que quisesse mandar ether para você. +Se você executar este comando, verá uma lista de dez strings que começam com `0x`. Cada um é um **endereço público** e é, de certa forma, análogo ao número de uma conta corrente. Você forneceria este endereço a alguém que quisesse lhe enviar ether. -Como mencionado, o provedor de teste pré-carregou cada uma dessas contas com algum ether. Vamos descobrir quanto há na primeira conta: +Como mencionado, o provedor de teste pré-carregou cada uma dessas contas com um pouco de ether de teste. Vamos descobrir quanto há na primeira conta: ```python In [7]: w3.eth.get_balance(w3.eth.accounts[0]) Out[7]: 1000000000000000000000000 ``` -São muitos zeros! Antes de você ir rindo até o banco falso, lembre-se daquela lição anterior sobre denominações de moeda. Os valores de ether são representados na menor denominação, wei. Converta para ether: +São muitos zeros! Antes de sair rindo até o banco falso, lembre-se da lição sobre denominações de moeda de antes. Os valores de Ether são representados na menor denominação, wei. Converta isso para ether: ```python In [8]: w3.from_wei(1000000000000000000000000, 'ether') @@ -219,7 +219,7 @@ Out[8]: Decimal('1000000') Um milhão de ether de teste — nada mal. -## Parada n.º 2 do tour: dados do bloco {#tour-stop-2-block-data} +## Parada do tour nº 2: dados do bloco {#tour-stop-2-block-data} Vamos dar uma olhada no estado desta blockchain simulada: @@ -234,15 +234,15 @@ Out[9]: AttributeDict({ }) ``` -São fornecidas muitas informações sobre um bloco, mas há apenas alguns pontos para salientar aqui: +Muitas informações são retornadas sobre um bloco, mas há apenas algumas coisas a serem destacadas aqui: -- O número de bloco é zero — não importa quanto tempo você configurou o provedor de teste. Ao contrário da rede Ethereum real, que minera um novo bloco aproximadamente a cada 12 segundos, essa simulação esperará até que você a instrua a fazer alguma coisa. +- O número do bloco é zero — não importa há quanto tempo você configurou o provedor de teste. Ao contrário da rede Ethereum real, que adiciona um novo bloco a cada 12 segundos, esta simulação esperará até que você lhe dê algum trabalho a fazer. - `transactions` é uma lista vazia, pelo mesmo motivo: ainda não fizemos nada. Este primeiro bloco é um **bloco vazio**, apenas para iniciar a cadeia. -- Observe que o `parentHash` é apenas um monte de bytes vazios. Isso significa que ele é o primeiro bloco da cadeia, também conhecido como **bloco de início**. +- Observe que o `parentHash` é apenas um monte de bytes vazios. Isso significa que é o primeiro bloco da cadeia, também conhecido como **bloco gênese**. -## Parada n.º 2 do tour: [transações](/developers/docs/transactions/) {#tour-stop-3-transactions} +## Parada do tour nº 3: [transações](/developers/docs/transactions/) {#tour-stop-3-transactions} -Estamos parados no bloco zero até que haja uma transação para minerar, então vamos começar. Envie um teste com ether de uma conta para outra: +Estamos presos no bloco zero até que haja uma transação pendente, então vamos criar uma. Envie alguns ether de teste de uma conta para outra: ```python In [10]: tx_hash = w3.eth.send_transaction({ @@ -253,13 +253,16 @@ In [10]: tx_hash = w3.eth.send_transaction({ }) ``` -Esse é normalmente o ponto em que você espera (vários segundos) até que sua transação seja minerada em um novo bloco. O processo completo envolve algo como isto: +Este é geralmente o ponto em que você esperaria vários segundos para que sua transação fosse incluída em um novo bloco. O processo completo é mais ou menos assim: -1. Envie uma transação e espere pelo hash da transação. Até que o bloco que contém a transação seja criado e transmitido, a transação fica "pendente" `tx_hash = w3.eth.send_transaction({ … })` -2. Aguarde a mineração da transação: `w3.eth.wait_for_transaction_receipt(tx_hash)` -3. Continue a lógica do aplicativo. Para visualizar a transação bem-sucedida: `w3.eth.get_transaction(tx_hash)` +1. Envie uma transação e guarde o hash da transação. Até que o bloco contendo a transação seja criado e transmitido, a transação fica “pendente”. + `tx_hash = w3.eth.send_transaction({ … })` +2. Aguarde a transação ser incluída em um bloco: + `w3.eth.wait_for_transaction_receipt(tx_hash)` +3. Continue a lógica do aplicativo. Para ver a transação bem-sucedida: + `w3.eth.get_transaction(tx_hash)` -Nosso ambiente simulado adicionará a transação a um novo bloco instantaneamente para que possamos ver a transação imediatamente: +Nosso ambiente simulado adicionará a transação a um novo bloco instantaneamente, para que possamos ver a transação imediatamente: ```python In [11]: w3.eth.get_transaction(tx_hash) @@ -274,9 +277,9 @@ Out[11]: AttributeDict({ }) ``` -Você verá alguns detalhes familiares aqui: os campos `de`, `para` e `valor` devem corresponder às entradas da chamada `sendTransaction`. A outra parte tranquilizadora é que esta transação foi incluída como a primeira transação (`'transactionIndex': 0`) dentro do bloco número 1. +Você verá alguns detalhes familiares aqui: os campos `from`, `to` e `value` devem corresponder às entradas de nossa chamada `send_transaction`. O outro detalhe reconfortante é que esta transação foi incluída como a primeira transação (`'transactionIndex': 0`) no bloco número 1. -Também podemos ver facilmente o sucesso dessa transação, verificando o saldo das duas contas envolvidas. Três ether deveriam ter sido enviados de uma conta para outra. +Também podemos verificar facilmente o sucesso desta transação, verificando os saldos das duas contas envolvidas. Três ether deveriam ter sido movidos de uma para outra. ```python In [12]: w3.eth.get_balance(w3.eth.accounts[0]) @@ -286,12 +289,12 @@ In [13]: w3.eth.get_balance(w3.eth.accounts[1]) Out[13]: 1000003000000000000000000 ``` -O último parece bem! O saldo foi de 1.000.000 a 1.000.003 ether. Mas o que aconteceu com a primeira conta? Parece ter perdido um pouco mais que três ether. Infelizmente, nada na vida é gratuito, e o uso da rede pública Ethereum requer que você compense os seus pares pelo papel de apoio deles. Uma pequena taxa de transação foi deduzida da conta que submeteu a transação - esta taxa é a quantidade de gás queimado (21000 unidades de gás para uma transferência ETH) multiplicado por uma taxa base, que varia de acordo com a atividade da rede, mais a gorjeta que vai para o validador que inclui a transação em um bloco. +O último parece bom! O saldo passou de 1.000.000 para 1.000.003 ether. Mas o que aconteceu com a primeira conta? Parece ter perdido um pouco mais de três ether. Infelizmente, nada na vida é de graça, e usar a rede pública Ethereum exige que você compense seus pares por seu papel de apoio. Uma pequena taxa de transação foi deduzida da conta que enviou a transação - essa taxa é a quantidade de gás queimado (21.000 unidades de gás para uma transferência de ETH) multiplicada por uma taxa base que varia de acordo com a atividade da rede, mais uma gorjeta que vai para o validador que inclui a transação em um bloco. Mais sobre [gás](/developers/docs/gas/#post-london) -Observação: na rede pública, as taxas de transação são variáveis baseadas na demanda da rede e na rapidez com que você gostaria que uma transação fosse processada. Se você estiver interessado em ver como as taxas são calculadas, veja minha publicação anterior sobre como transações são incluídas em um bloco. +Observação: na rede pública, as taxas de transação são variáveis com base na demanda da rede e na rapidez com que você gostaria que uma transação fosse processada. Se você estiver interessado em uma análise de como as taxas são calculadas, veja minha postagem anterior sobre como as transações são incluídas em um bloco. -## Agora uma pausa {#and-breathe} +## E respire {#and-breathe} -Já estamos nisso por um tempo, então este parece um lugar tão bom quanto qualquer um para fazer uma pausa. A descoberta continua, e vamos continuar com a parte dois desta série. Alguns conceitos que surgem: conectar a um nó real, contratos inteligentes e tokens. Tem perguntas adicionais? Queremos saber! Seu feedback influenciará o caminho a seguir. Suas perguntas são bem-vindas no [Twitter](https://twitter.com/wolovim). +Já estamos nisso há um tempo, então este parece ser um bom lugar para fazer uma pausa. A descoberta continua, e vamos continuar explorando na parte dois desta série. Alguns conceitos futuros: conectar a um nó real, contratos inteligentes e tokens. Tem mais alguma pergunta? Queremos saber! Seu feedback influenciará para onde vamos a partir daqui. Pedidos são bem-vindos via [Twitter](https://twitter.com/wolovim). diff --git a/public/content/translations/pt-br/developers/tutorials/ai-trading-agent/index.md b/public/content/translations/pt-br/developers/tutorials/ai-trading-agent/index.md new file mode 100644 index 00000000000..9305476d7c3 --- /dev/null +++ b/public/content/translations/pt-br/developers/tutorials/ai-trading-agent/index.md @@ -0,0 +1,981 @@ +--- +title: "Crie seu próprio agente de negociação de IA no Ethereum" +description: "Neste tutorial, você aprenderá a criar um agente simples de negociação de IA. Este agente lê informações da cadeia de blocos, solicita uma recomendação a um LLM com base nessas informações, executa a negociação que o LLM recomenda e, em seguida, aguarda e repete." +author: Ori Pomerantz + Ori Pomerantz +tags: [ "IA", "negociação", "agente", "python" ] +skill: intermediate +published: 2026-02-13 +lang: pt-br +sidebarDepth: 3 +--- + +Neste tutorial, você aprenderá a criar um agente simples de negociação de IA. Este agente funciona seguindo estas etapas: + +1. Ler os preços atuais e passados de um token, bem como outras informações potencialmente relevantes +2. Criar uma consulta com essas informações, juntamente com informações de fundo para explicar como elas podem ser relevantes +3. Enviar a consulta e receber de volta um preço projetado +4. Negociar com base na recomendação +5. Aguardar e repetir + +Este agente demonstra como ler informações, traduzi-las em uma consulta que produz uma resposta utilizável e usar essa resposta. Todas essas são etapas necessárias para um agente de IA. Este agente é implementado em Python porque é a linguagem mais comum usada em IA. + +## Por que fazer isso? {#why-do-this} + +Agentes de negociação automatizados permitem que os desenvolvedores selecionem e executem uma estratégia de negociação. [agentes de IA](/ai-agents) permitem estratégias de negociação mais complexas e dinâmicas, usando potencialmente informações e algoritmos que o desenvolvedor nem considerou usar. + +## As ferramentas {#tools} + +Este tutorial usa [Python](https://www.python.org/), a [biblioteca Web3](https://web3py.readthedocs.io/en/stable/) e o [Uniswap v3](https://github.com/Uniswap/v3-periphery) para cotações e negociações. + +### Por que Python? {#python} + +A linguagem mais utilizada para IA é o [Python](https://www.python.org/), por isso a usamos aqui. Não se preocupe se você não conhece Python. A linguagem é muito clara e explicarei exatamente o que ela faz. + +A [biblioteca Web3](https://web3py.readthedocs.io/en/stable/) é a API Python Ethereum mais comum. É bem fácil de usar. + +### Negociando na cadeia de blocos {#trading-on-blockchain} + +Existem [muitas corretoras distribuídas (DEX)](/apps/categories/defi/) que permitem negociar tokens no Ethereum. No entanto, elas tendem a ter taxas de câmbio semelhantes devido à [arbitragem](/developers/docs/smart-contracts/composability/#better-user-experience). + +O [Uniswap](https://app.uniswap.org/) é uma DEX amplamente utilizada que podemos usar tanto para cotações (para ver os valores relativos dos tokens) quanto para negociações. + +### OpenAI {#openai} + +Para um modelo de linguagem grande, escolhi começar com o [OpenAI](https://openai.com/). Para executar a aplicação neste tutorial, você precisará pagar pelo acesso à API. O pagamento mínimo de US$ 5 é mais do que suficiente. + +## Desenvolvimento, passo a passo {#step-by-step} + +Para simplificar o desenvolvimento, prosseguimos em etapas. Cada etapa é um branch no GitHub. + +### Primeiros passos {#getting-started} + +Existem etapas para começar no UNIX ou Linux (incluindo o [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)) + +1. Se ainda não tiver, baixe e instale o [Python](https://www.python.org/downloads/). + +2. Clone o repositório do GitHub. + + ```sh + git clone https://github.com/qbzzt/260215-ai-agent.git -b 01-getting-started + cd 260215-ai-agent + ``` + +3. Instale o [`uv`](https://docs.astral.sh/uv/getting-started/installation/). O comando em seu sistema pode ser diferente. + + ```sh + pipx install uv + ``` + +4. Baixe as bibliotecas. + + ```sh + uv sync + ``` + +5. Ative o ambiente virtual. + + ```sh + source .venv/bin/activate + ``` + +6. Para verificar se o Python e o Web3 estão funcionando corretamente, execute o `python3` e forneça a ele este programa. Você pode inseri-lo no prompt `>>>`; não é necessário criar um arquivo. + + ```python + from web3 import Web3 + MAINNET_URL = "https://eth.drpc.org" + w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) + w3.eth.block_number + quit() + ``` + +### Lendo da cadeia de blocos {#read-blockchain} + +O próximo passo é ler da cadeia de blocos. Para fazer isso, você precisa mudar para o branch `02-read-quote` e usar o `uv` para executar o programa. + +```sh +git checkout 02-read-quote +uv run agent.py +``` + +Você deve receber uma lista de objetos `Quote`, cada um com um timestamp, um preço e o ativo (atualmente sempre `WETH/USDC`). + +Aqui está uma explicação linha por linha. + +```python +from web3 import Web3 +from web3.contract import Contract +from decimal import Decimal, ROUND_HALF_UP +from dataclasses import dataclass +from datetime import datetime, timezone +from pprint import pprint +import time +import functools +import sys +``` + +Importe as bibliotecas que precisamos. Eles são explicados abaixo quando usados. + +```python +print = functools.partial(print, flush=True) +``` + +Substitui o `print` do Python por uma versão que sempre descarrega a saída imediatamente. Isso é útil em um script de longa duração, porque não queremos esperar por atualizações de status ou saídas de depuração. + +```python +MAINNET_URL = "https://eth.drpc.org" +``` + +Uma URL para chegar à rede principal. Você pode obter uma de um [Nó como serviço](/developers/docs/nodes-and-clients/nodes-as-a-service/) ou usar uma das anunciadas na [Chainlist](https://chainlist.org/chain/1). + +```python +BLOCK_TIME_SECONDS = 12 +MINUTE_BLOCKS = int(60 / BLOCK_TIME_SECONDS) +HOUR_BLOCKS = MINUTE_BLOCKS * 60 +DAY_BLOCKS = HOUR_BLOCKS * 24 +``` + +Um bloco da rede principal do Ethereum geralmente acontece a cada doze segundos, então este é o número de blocos que esperamos que aconteçam em um período de tempo. Observe que este não é um número exato. Quando o [propositor de bloco](/developers/docs/consensus-mechanisms/pos/block-proposal/) está inativo, esse bloco é pulado e o tempo para o próximo bloco é de 24 segundos. Se quiséssemos obter o bloco exato para um timestamp, usaríamos a [busca binária](https://en.wikipedia.org/wiki/Binary_search). No entanto, isso é próximo o suficiente para nossos propósitos. Prever o futuro não é uma ciência exata. + +```python +CYCLE_BLOCKS = DAY_BLOCKS +``` + +O tamanho do ciclo. Revisamos as cotações uma vez por ciclo e tentamos estimar o valor no final do próximo ciclo. + +```python +# O endereço do pool que estamos lendo +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +``` + +Os valores da cotação são retirados do pool USDC/WETH do Uniswap 3 no endereço [`0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`](https://eth.blockscout.com/address/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640?tab=read_write_contract). Este endereço já está no formato checksum, mas é melhor usar [`Web3.to_checksum_address`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_checksum_address) para tornar o código reutilizável. + +```python +POOL_ABI = [ + { "name": "slot0", ... }, + { "name": "token0", ... }, + { "name": "token1", ... }, +] + +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... } +] +``` + +Estas são as [IABs](https://docs.soliditylang.org/en/latest/abi-spec.html) para os dois contratos que precisamos contatar. Para manter o código conciso, incluímos apenas as funções que precisamos chamar. + +```python +w3 = Web3(Web3.HTTPProvider(MAINNET_URL)) +``` + +Inicie a biblioteca [`Web3`](https://web3py.readthedocs.io/en/stable/quickstart.html#remote-providers) e conecte-se a um nó Ethereum. + +```python +@dataclass(frozen=True) +class ERC20Token: + address: str + symbol: str + decimals: int + contract: Contract +``` + +Esta é uma maneira de criar uma classe de dados em Python. O tipo de dados [`Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) é usado para se conectar ao contrato. Observe o `(frozen=True)`. Em Python, os [booleanos](https://en.wikipedia.org/wiki/Boolean_data_type) são definidos como `True` ou `False`, com letra maiúscula. Esta classe de dados é `frozen` (congelada), o que significa que os campos não podem ser modificados. + +Observe a indentação. Em contraste com as [linguagens derivadas de C](https://en.wikipedia.org/wiki/List_of_C-family_programming_languages), o Python usa indentação para denotar blocos. O interpretador Python sabe que a definição a seguir não faz parte desta classe de dados porque não começa na mesma indentação que os campos da classe de dados. + +```python +@dataclass(frozen=True) +class PoolInfo: + address: str + token0: ERC20Token + token1: ERC20Token + contract: Contract + asset: str + decimal_factor: Decimal = 1 +``` + +O tipo [`Decimal`](https://docs.python.org/3/library/decimal.html) é usado para lidar com precisão com frações decimais. + +```python + def get_price(self, block: int) -> Decimal: +``` + +Esta é a maneira de definir uma função em Python. A definição é indentada para mostrar que ainda faz parte de `PoolInfo`. + +Em uma função que faz parte de uma classe de dados, o primeiro parâmetro é sempre `self`, a instância da classe de dados que a chamou. Aqui há outro parâmetro, o número do bloco. + +```python + assert block <= w3.eth.block_number, "O bloco está no futuro" +``` + +Se pudéssemos ler o futuro, não precisaríamos de IA para negociação. + +```python + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) +``` + +A sintaxe para chamar uma função na EVM a partir do Web3 é esta: `.functions.().call()`. Os parâmetros podem ser os parâmetros da função da EVM (se houver; aqui não há) ou [parâmetros nomeados](https://en.wikipedia.org/wiki/Named_parameter) para modificar o comportamento da cadeia de blocos. Aqui usamos um, `block_identifier`, para especificar [o número do bloco](/developers/docs/apis/json-rpc/#default-block) no qual desejamos executar. + +O resultado é [esta struct, em formato de array](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol#L56-L72). O primeiro valor é uma função da taxa de câmbio entre os dois tokens. + +```python + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 +``` + +Para reduzir os cálculos na cadeia, o Uniswap v3 não armazena o fator de câmbio real, mas sim sua raiz quadrada. Como a EVM não suporta matemática de ponto flutuante ou frações, em vez do valor real, a resposta é price296 + +```python + # (token1 por token0) + return 1/(raw_price * self.decimal_factor) +``` + +O preço bruto que obtemos é o número de `token0` que obtemos para cada `token1`. Em nosso pool, o `token0` é USDC (moeda estável com o mesmo valor de um dólar americano) e o `token1` é [WETH](https://opensea.io/learn/blockchain/what-is-weth). O valor que realmente queremos é o número de dólares por WETH, não o inverso. + +O fator decimal é a proporção entre os [fatores decimais](https://docs.openzeppelin.com/contracts/4.x/erc20#a-note-on-decimals) para os dois tokens. + +```python +@dataclass(frozen=True) +class Quote: + timestamp: str + price: Decimal + asset: str +``` + +Essa classe de dados representa uma cotação: o preço de um ativo específico em um determinado momento. Neste ponto, o campo `asset` é irrelevante, porque usamos um único pool e, portanto, temos um único ativo. No entanto, adicionaremos mais ativos posteriormente. + +```python +def read_token(address: str) -> ERC20Token: + token = w3.eth.contract(address=address, abi=ERC20_ABI) + symbol = token.functions.symbol().call() + decimals = token.functions.decimals().call() + + return ERC20Token( + address=address, + symbol=symbol, + decimals=decimals, + contract=token + ) +``` + +Esta função recebe um endereço e retorna informações sobre o contrato do token nesse endereço. Para criar um novo [`Contrato` Web3](https://web3py.readthedocs.io/en/stable/web3.contract.html), fornecemos o endereço e a IAB para `w3.eth.contract`. + +```python +def read_pool(address: str) -> PoolInfo: + pool_contract = w3.eth.contract(address=address, abi=POOL_ABI) + token0Address = pool_contract.functions.token0().call() + token1Address = pool_contract.functions.token1().call() + token0 = read_token(token0Address) + token1 = read_token(token1Address) + + return PoolInfo( + address=address, + asset=f"{token1.symbol}/{token0.symbol}", + token0=token0, + token1=token1, + contract=pool_contract, + decimal_factor=Decimal(10) ** Decimal(token0.decimals - token1.decimals) + ) +``` + +Esta função retorna tudo o que precisamos sobre [um pool específico](https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol). A sintaxe `f""` é uma [string formatada](https://docs.python.org/3/reference/lexical_analysis.html#f-strings). + +```python +def get_quote(pool: PoolInfo, block_number: int = None) -> Quote: +``` + +Obtenha um objeto `Quote`. O valor padrão para `block_number` é `None` (sem valor). + +```python + if block_number is None: + block_number = w3.eth.block_number +``` + +Se um número de bloco não foi especificado, use `w3.eth.block_number`, que é o número do bloco mais recente. Essa é a sintaxe para [uma instrução `if`](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement). + +Pode parecer que seria melhor apenas definir o padrão como `w3.eth.block_number`, mas isso não funciona bem porque seria o número do bloco no momento em que a função é definida. Em um agente de longa duração, isso seria um problema. + +```python + block = w3.eth.get_block(block_number) + price = pool.get_price(block_number) + return Quote( + timestamp=datetime.fromtimestamp(block.timestamp, timezone.utc).isoformat(), + price=price.quantize(Decimal("0.01")), + asset=pool.asset + ) +``` + +Use [a biblioteca `datetime`](https://docs.python.org/3/library/datetime.html) para formatá-lo em um formato legível para humanos e modelos de linguagem grandes (LLMs). Use [`Decimal.quantize`](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) para arredondar o valor para duas casas decimais. + +```python +def get_quotes(pool: PoolInfo, start_block: int, end_block: int, step: int) -> list[Quote]: +``` + +Em Python, você define uma [lista](https://docs.python.org/3/library/stdtypes.html#typesseq-list) que só pode conter um tipo específico usando `list[]`. + +```python + quotes = [] + for block in range(start_block, end_block + 1, step): +``` + +Em Python, um [loop `for`](https://docs.python.org/3/tutorial/controlflow.html#for-statements) normalmente itera sobre uma lista. A lista de números de bloco para encontrar cotações vem de [`range`](https://docs.python.org/3/library/stdtypes.html#range). + +```python + quote = get_quote(pool, block) + quotes.append(quote) + return quotes +``` + +Para cada número de bloco, obtenha um objeto `Quote` e anexe-o à lista `quotes`. Em seguida, retorne essa lista. + +```python +pool = read_pool(WETHUSDC_ADDRESS) +quotes = get_quotes( + pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) + +pprint(quotes) +``` + +Este é o código principal do script. Leia as informações do pool, obtenha doze cotações e use [`pprint`](https://docs.python.org/3/library/pprint.html#pprint.pprint) para exibi-las. + +### Criando um prompt {#prompt} + +Em seguida, precisamos converter essa lista de cotações em um prompt para um LLM e obter um valor futuro esperado. + +```sh +git checkout 03-create-prompt +uv run agent.py +``` + +A saída agora será um prompt para um LLM, semelhante a: + +``` +Dadas estas cotações: +Ativo: WETH/USDC + 2026-01-20T16:34 3016.21 + . + . + . + 2026-02-01T17:49 2299.10 + +Ativo: WBTC/WETH + 2026-01-20T16:34 29.84 + . + . + . + 2026-02-01T17:50 33.46 + + +Qual você esperaria que fosse o valor para WETH/USDC no momento 2026-02-02T17:56? + +Forneça sua resposta como um único número arredondado para duas casas decimais, +sem nenhum outro texto. +``` + +Observe que há cotações para dois ativos aqui, `WETH/USDC` e `WBTC/WETH`. Adicionar cotações de outro ativo pode melhorar a precisão da previsão. + +#### Como é um prompt {#prompt-explanation} + +Este prompt contém três seções, que são bastante comuns em prompts de LLM. + +1. Informação. Os LLMs têm muitas informações de seu treinamento, mas geralmente não têm as mais recentes. É por isso que precisamos recuperar as cotações mais recentes aqui. Adicionar informações a um prompt é chamado de [geração aumentada por recuperação (RAG)](https://en.wikipedia.org/wiki/Retrieval-augmented_generation). + +2. A pergunta real. É isso que queremos saber. + +3. Instruções de formatação de saída. Normalmente, um LLM nos dará uma estimativa com uma explicação de como chegou a ela. Isso é melhor para humanos, mas um programa de computador só precisa do resultado final. + +#### Explicação do código {#prompt-code} + +Aqui está o novo código. + +```python +from datetime import datetime, timezone, timedelta +``` + +Precisamos fornecer ao LLM o tempo para o qual queremos uma estimativa. Para obter um tempo "n minutos/horas/dias" no futuro, usamos [a classe `timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta). + +```python +# Os endereços dos pools que estamos lendo +WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") +WETHWBTC_ADDRESS = Web3.to_checksum_address("0xCBCdF9626bC03E24f779434178A73a0B4bad62eD") +``` + +Temos dois pools que precisamos ler. + +```python +@dataclass(frozen=True) +class PoolInfo: + . + . + . + reverse: bool = False + + def get_price(self, block: int) -> Decimal: + assert block <= w3.eth.block_number, "Block is in the future" + sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0]) + raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 # (token1 per token0) + if self.reverse: + return 1/(raw_price * self.decimal_factor) + else: + return raw_price * self.decimal_factor +``` + +No pool WETH/USDC, queremos saber quantos `token0` (USDC) precisamos para comprar um `token1` (WETH). No pool WETH/WBTC, queremos saber quantos `token1` (WETH) precisamos para comprar um `token0` (WBTC, que é Bitcoin embrulhado). Precisamos rastrear se a proporção do pool precisa ser invertida. + +```python +def read_pool(address: str, reverse: bool = False) -> PoolInfo: + . + . + . + + return PoolInfo( + . + . + . + + asset= f"{token1.symbol}/{token0.symbol}" if reverse else f"{token0.symbol}/{token1.symbol}", + reverse=reverse + ) +``` + +Para saber se um pool precisa ser revertido, precisamos obter isso como entrada para `read_pool`. Além disso, o símbolo do ativo precisa ser configurado corretamente. + +A sintaxe ` if else ` é o equivalente em Python do [operador condicional ternário](https://en.wikipedia.org/wiki/Ternary_conditional_operator), que em uma linguagem derivada de C seria ` ? : `. + +```python +def format_quotes(quotes: list[Quote]) -> str: + result = f"Asset: {quotes[0].asset}\n" + for quote in quotes: + result += f"\t{quote.timestamp[0:16]} {quote.price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)}\n" + return result +``` + +Esta função cria uma string que formata uma lista de objetos `Quote`, supondo que todos se apliquem ao mesmo ativo. + +```python +def make_prompt(quotes: list[list[Quote]], expected_time: str, asset: str) -> str: + return f""" +``` + +Em Python, os [literais de string de várias linhas](https://www.w3schools.com/python/gloss_python_multi_line_strings.asp) são escritos como `"""` .... `"""`. + +```python +Dadas estas cotações: +{ + functools.reduce(lambda acc, q: acc + '\n' + q, + map(lambda q: format_quotes(q), quotes)) +} +``` + +Aqui, usamos o padrão [MapReduce](https://en.wikipedia.org/wiki/MapReduce) para gerar uma string para cada lista de cotações com `format_quotes` e, em seguida, reduzi-las a uma única string para uso no prompt. + +```python +Qual você esperaria que fosse o valor para {asset} no momento {expected_time}? + +Forneça sua resposta como um único número arredondado para duas casas decimais, +sem nenhum outro texto. + """ +``` + +O resto do prompt é como esperado. + +```python +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - 12*CYCLE_BLOCKS, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +Revise os dois pools e obtenha cotações de ambos. + +```python +future_time = (datetime.now(timezone.utc) + timedelta(days=1)).isoformat()[0:16] + +print(make_prompt(wethusdc_quotes + wethwbtc_quotes, future_time, wethusdc_pool.asset)) +``` + +Determine o ponto de tempo futuro para o qual queremos a estimativa e crie o prompt. + +### Interface com um LLM {#interface-llm} + +Em seguida, solicitamos um LLM real e recebemos um valor futuro esperado. Eu escrevi este programa usando OpenAI, então se você quiser usar um provedor diferente, precisará ajustá-lo. + +1. Obtenha uma [conta OpenAI](https://auth.openai.com/create-account) + +2. [Financie a conta](https://platform.openai.com/settings/organization/billing/overview) — o valor mínimo no momento da escrita é de US$ 5 + +3. [Crie uma chave de API](https://platform.openai.com/settings/organization/api-keys) + +4. Na linha de comando, exporte a chave de API para que seu programa possa usá-la + + ```sh + export OPENAI_API_KEY=sk- + ``` + +5. Faça o checkout e execute o agente + + ```sh + git checkout 04-interface-llm + uv run agent.py + ``` + +Aqui está o novo código. + +```python +from openai import OpenAI + +open_ai = OpenAI() # O cliente lê a variável de ambiente OPENAI_API_KEY +``` + +Importe e instancie a API OpenAI. + +```python +response = open_ai.chat.completions.create( + model="gpt-4-turbo", + messages=[ + {"role": "user", "content": prompt} + ], + temperature=0.0, + max_tokens=16, +) +``` + +Chame a API OpenAI (`open_ai.chat.completions.create`) para criar a resposta. + +```python +expected_price = Decimal(response.choices[0].message.content.strip()) +current_price = wethusdc_quotes[-1].price + +print ("Current price:", wethusdc_quotes[-1].price) +print(f"In {future_time}, expected price: {expected_price} USD") + +if (expected_price > current_price): + print(f"Buy, I expect the price to go up by {expected_price - current_price} USD") +else: + print(f"Sell, I expect the price to go down by {current_price - expected_price} USD") +``` + +Mostre o preço e forneça uma recomendação de compra ou venda. + +#### Testando as previsões {#testing-the-predictions} + +Agora que podemos gerar previsões, também podemos usar dados históricos para avaliar se produzimos previsões úteis. + +```sh +uv run test-predictor.py +``` + +O resultado esperado é semelhante a: + +``` +Previsão para 2026-01-05T19:50: previsto 3138.93 USD, real 3218.92 USD, erro 79.99 USD +Previsão para 2026-01-06T19:56: previsto 3243.39 USD, real 3221.08 USD, erro 22.31 USD +Previsão para 2026-01-07T20:02: previsto 3223.24 USD, real 3146.89 USD, erro 76.35 USD +Previsão para 2026-01-08T20:11: previsto 3150.47 USD, real 3092.04 USD, erro 58.43 USD +. +. +. +Previsão para 2026-01-31T22:33: previsto 2637.73 USD, real 2417.77 USD, erro 219.96 USD +Previsão para 2026-02-01T22:41: previsto 2381.70 USD, real 2318.84 USD, erro 62.86 USD +Previsão para 2026-02-02T22:49: previsto 2234.91 USD, real 2349.28 USD, erro 114.37 USD +Erro médio de previsão em 29 previsões: 83.87103448275862068965517241 USD +Mudança média por recomendação: 4.787931034482758620689655172 USD +Variância padrão das mudanças: 104.42 USD +Dias lucrativos: 51.72% +Dias com perdas: 48.28% +``` + +A maior parte do testador é idêntica ao agente, mas aqui estão as partes que são novas ou modificadas. + +```python +CYCLES_FOR_TEST = 40 # Para o backtest, quantos ciclos testamos + +# Obtenha muitas cotações +wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True) +wethusdc_quotes = get_quotes( + wethusdc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS, +) + +wethwbtc_pool = read_pool(WETHWBTC_ADDRESS) +wethwbtc_quotes = get_quotes( + wethwbtc_pool, + w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST, + w3.eth.block_number, + CYCLE_BLOCKS +) +``` + +Analisamos `CYCLES_FOR_TEST` (especificado como 40 aqui) dias para trás. + +```python +# Crie previsões e verifique-as em relação ao histórico real + +total_error = Decimal(0) +changes = [] +``` + +Existem dois tipos de erros nos quais estamos interessados. O primeiro, `total_error`, é simplesmente a soma dos erros que o previsor cometeu. + +Para entender o segundo, `changes`, precisamos nos lembrar do propósito do agente. Não é prever a proporção WETH/USDC (preço do ETH). É para emitir recomendações de venda e compra. Se o preço atual for US$ 2.000 e ele prever US$ 2.010 para amanhã, não nos importamos se o resultado real for US$ 2.020 e ganharmos dinheiro extra. Mas nós nos importamos se ele previu US$ 2.010 e comprou ETH com base nessa recomendação, e o preço cair para US$ 1.990. + +```python +for index in range(0,len(wethusdc_quotes)-CYCLES_BACK): +``` + +Só podemos analisar os casos em que o histórico completo (os valores usados para a previsão e o valor do mundo real para compará-lo) está disponível. Isso significa que o caso mais recente deve ser aquele que começou há `CYCLES_BACK`. + +```python + wethusdc_slice = wethusdc_quotes[index:index+CYCLES_BACK] + wethwbtc_slice = wethwbtc_quotes[index:index+CYCLES_BACK] +``` + +Use [fatias (slices)](https://www.w3schools.com/python/ref_func_slice.asp) para obter o mesmo número de amostras que o número que o agente usa. O código entre aqui e o próximo segmento é o mesmo código para obter uma previsão que temos no agente. + +```python + predicted_price = Decimal(response.choices[0].message.content.strip()) + real_price = wethusdc_quotes[index+CYCLES_BACK].price + prediction_time_price = wethusdc_quotes[index+CYCLES_BACK-1].price +``` + +Obtenha o preço previsto, o preço real e o preço no momento da previsão. Precisamos do preço no momento da previsão para determinar se a recomendação foi de compra ou de venda. + +```python + error = abs(predicted_price - real_price) + total_error += error + print (f"Prediction for {prediction_time}: predicted {predicted_price} USD, real {real_price} USD, error {error} USD") +``` + +Calcule o erro e adicione-o ao total. + +```python + recomended_action = 'buy' if predicted_price > prediction_time_price else 'sell' + price_increase = real_price - prediction_time_price + changes.append(price_increase if recomended_action == 'buy' else -price_increase) +``` + +Para `changes`, queremos o impacto monetário da compra ou venda de um ETH. Então, primeiro, precisamos determinar a recomendação, depois avaliar como o preço real mudou e se a recomendação gerou lucro (mudança positiva) ou prejuízo (mudança negativa). + +```python +print (f"Mean prediction error over {len(wethusdc_quotes)-CYCLES_BACK} predictions: {total_error / Decimal(len(wethusdc_quotes)-CYCLES_BACK)} USD") + +length_changes = Decimal(len(changes)) +mean_change = sum(changes, Decimal(0)) / length_changes +print (f"Mean change per recommendation: {mean_change} USD") +var = sum((x - mean_change) ** 2 for x in changes) / length_changes +print (f"Standard variance of changes: {var.sqrt().quantize(Decimal("0.01"))} USD") +``` + +Relate os resultados. + +```python +print (f"Profitable days: {len(list(filter(lambda x: x > 0, changes)))/length_changes:.2%}") +print (f"Losing days: {len(list(filter(lambda x: x < 0, changes)))/length_changes:.2%}") +``` + +Use o [`filter`](https://www.w3schools.com/python/ref_func_filter.asp) para contar o número de dias lucrativos e o número de dias com prejuízo. O resultado é um objeto de filtro, que precisamos converter em uma lista para obter o comprimento. + +### Envio de transações {#submit-txn} + +Agora precisamos realmente enviar as transações. No entanto, não quero gastar dinheiro de verdade neste momento, antes que o sistema seja comprovado. Em vez disso, criaremos uma bifurcação local da rede principal e "negociaremos" nessa rede. + +Aqui estão as etapas para criar uma bifurcação local e habilitar a negociação. + +1. Instale o [Foundry](https://getfoundry.sh/introduction/installation) + +2. Inicie o [`anvil`](https://getfoundry.sh/anvil/overview) + + ```sh + anvil --fork-url https://eth.drpc.org --block-time 12 + ``` + + `anvil` está escutando na URL padrão para o Foundry, http://localhost:8545, então não precisamos especificar a URL para o [comando `cast`](https://getfoundry.sh/cast/overview) que usamos para manipular a cadeia de blocos. + +3. Ao executar no `anvil`, há dez contas de teste que têm ETH — defina as variáveis de ambiente para a primeira + + ```sh + PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ADDRESS=`cast wallet address $PRIVATE_KEY` + ``` + +4. Estes são os contratos que precisamos usar. O [`SwapRouter`](https://github.com/Uniswap/v3-periphery/blob/main/contracts/SwapRouter.sol) é o contrato Uniswap v3 que usamos para negociar de fato. Poderíamos negociar diretamente através do pool, mas isso é muito mais fácil. + + As duas variáveis inferiores são os caminhos do Uniswap v3 necessários para trocar entre WETH e USDC. + + ```sh + WETH_ADDRESS=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + USDC_ADDRESS=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + POOL_ADDRESS=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 + SWAP_ROUTER=0xE592427A0AEce92De3Edee1F18E0157C05861564 + WETH_TO_USDC=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 + USDC_TO_WETH=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + ``` + +5. Cada uma das contas de teste tem 10.000 ETH. Use o contrato WETH para embrulhar 1000 ETH e obter 1000 WETH para negociação. + + ```sh + cast send $WETH_ADDRESS "deposit()" --value 1000ether --private-key $PRIVATE_KEY + ``` + +6. Use o `SwapRouter` para negociar 500 WETH por USDC. + + ```sh + cast send $WETH_ADDRESS "approve(address,uint256)" $SWAP_ROUTER 500ether --private-key $PRIVATE_KEY + MAXINT=`cast max-int uint256` + cast send $SWAP_ROUTER \ + "exactInput((bytes,address,uint256,uint256,uint256))" \ + "($WETH_TO_USDC,$ADDRESS,$MAXINT,500ether,1000000)" \ + --private-key $PRIVATE_KEY + ``` + + A chamada `approve` cria uma permissão que permite que o `SwapRouter` gaste alguns dos nossos tokens. Contratos não podem monitorar eventos, portanto, se transferirmos tokens diretamente para o contrato `SwapRouter`, ele não saberia que foi pago. Em vez disso, permitimos que o contrato `SwapRouter` gaste uma certa quantia, e então o `SwapRouter` o faz. Isso é feito através de uma função chamada pelo `SwapRouter`, para que ele saiba se foi bem-sucedido. + +7. Verifique se você tem o suficiente de ambos os tokens. + + ```sh + cast call $WETH_ADDRESS "balanceOf(address)" $ADDRESS | cast from-wei + echo `cast call $USDC_ADDRESS "balanceOf(address)" $ADDRESS | cast to-dec`/10^6 | bc + ``` + +Agora que temos WETH e USDC, podemos realmente executar o agente. + +```sh +git checkout 05-trade +uv run agent.py +``` + +A saída será semelhante a: + +``` +(ai-trading-agent) qbzzt@Ori-Cloudnomics:~/260215-ai-agent$ uv run agent.py +Preço atual: 1843.16 +Em 2026-02-06T23:07, preço esperado: 1724.41 USD +Saldos da conta antes da negociação: +Saldo de USDC: 927301.578272 +Saldo de WETH: 500 +Vender, espero que o preço caia 118,75 USD +Transação de aprovação enviada: 74e367ddbb407c1aaf567d87aa5863049991b1d2aa092b6b85195d925e2bd41f +Transação de aprovação minerada. +Transação de venda enviada: fad1bcf938585c9e90364b26ac7a80eea9efd34c37e5db81e58d7655bcae28bf +Transação de venda minerada. +Saldos da conta após a negociação: +Saldo de USDC: 929143.797116 +Saldo de WETH: 499 +``` + +Para realmente usá-lo, você precisa de algumas pequenas alterações. + +- Na linha 14, altere `MAINNET_URL` para um ponto de acesso real, como `https://eth.drpc.org` +- Na linha 28, altere `PRIVATE_KEY` para sua própria chave privada +- A menos que você seja muito rico e possa comprar ou vender 1 ETH por dia para um agente não comprovado, você pode querer alterar a linha 29 para diminuir o `WETH_TRADE_AMOUNT` + +#### Explicação do código {#trading-code} + +Aqui está o novo código. + +```python +SWAP_ROUTER_ADDRESS=Web3.to_checksum_address("0xE592427A0AEce92De3Edee1F18E0157C05861564") +WETH_TO_USDC=bytes.fromhex("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") +USDC_TO_WETH=bytes.fromhex("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +``` + +As mesmas variáveis que usamos na etapa 4. + +```python +WETH_TRADE_AMOUNT=1 +``` + +A quantia a ser negociada. + +```python +ERC20_ABI = [ + { "name": "symbol", ... }, + { "name": "decimals", ... }, + { "name": "balanceOf", ...}, + { "name": "approve", ...} +] +``` + +Para realmente negociar, precisamos da função `approve`. Também queremos mostrar os saldos antes e depois, então também precisamos de `balanceOf`. + +```python +SWAP_ROUTER_ABI = [ + { "name": "exactInput", ...}, +] +``` + +Na IAB do `SwapRouter`, só precisamos de `exactInput`. Existe uma função relacionada, `exactOutput`, que poderíamos usar para comprar exatamente um WETH, mas para simplificar, usamos apenas `exactInput` em ambos os casos. + +```python +account = w3.eth.account.from_key(PRIVATE_KEY) +swap_router = w3.eth.contract( + address=SWAP_ROUTER_ADDRESS, + abi=SWAP_ROUTER_ABI +) +``` + +As definições do Web3 para a [`conta`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html) e o contrato `SwapRouter`. + +```python +def txn_params() -> dict: + return { + "from": account.address, + "value": 0, + "gas": 300000, + "nonce": w3.eth.get_transaction_count(account.address), + } +``` + +Os parâmetros da transação. Precisamos de uma função aqui porque [o nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) deve mudar a cada vez. + +```python +def approve_token(contract: Contract, amount: int): +``` + +Aprove uma permissão de token para o `SwapRouter`. + +```python + txn = contract.functions.approve(SWAP_ROUTER_ADDRESS, amount).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) +``` + +É assim que enviamos uma transação no Web3. Primeiro, usamos [o objeto `Contract`](https://web3py.readthedocs.io/en/stable/web3.contract.html) para construir a transação. Em seguida, usamos [`web3.eth.account.sign_transaction`](https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-contract-transaction) para assinar a transação, usando `PRIVATE_KEY`. Finalmente, usamos [`w3.eth.send_raw_transaction`](https://web3py.readthedocs.io/en/stable/transactions.html#chapter-2-w3-eth-send-raw-transaction) para enviar a transação. + +```python + print(f"Approve transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Approve transaction mined.") +``` + +[`w3.eth.wait_for_transaction_receipt`](https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.wait_for_transaction_receipt) espera até que a transação seja minerada. Ele retorna o recibo, se necessário. + +```python +SELL_PARAMS = { + "path": WETH_TO_USDC, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": WETH_TRADE_AMOUNT * 10 ** wethusdc_pool.token1.decimals, + "amountOutMinimum": 0, +} +``` + +Estes são os parâmetros ao vender WETH. + +```python +def make_buy_params(quote: Quote) -> dict: + return { + "path": USDC_TO_WETH, + "recipient": account.address, + "deadline": 2**256 - 1, + "amountIn": int(quote.price*WETH_TRADE_AMOUNT) * 10**wethusdc_pool.token0.decimals, + "amountOutMinimum": 0, + } +``` + +Em contraste com `SELL_PARAMS`, os parâmetros de compra podem mudar. O valor de entrada é o custo de 1 WETH, conforme disponível em `quote`. + +```python +def buy(quote: Quote): + buy_params = make_buy_params(quote) + approve_token(wethusdc_pool.token0.contract, buy_params["amountIn"]) + txn = swap_router.functions.exactInput(buy_params).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Buy transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Buy transaction mined.") + + +def sell(): + approve_token(wethusdc_pool.token1.contract, + WETH_TRADE_AMOUNT * 10**wethusdc_pool.token1.decimals) + txn = swap_router.functions.exactInput(SELL_PARAMS).build_transaction(txn_params()) + signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY) + tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) + print(f"Sell transaction sent: {tx_hash.hex()}") + w3.eth.wait_for_transaction_receipt(tx_hash) + print("Sell transaction mined.") +``` + +As funções `buy()` e `sell()` são quase idênticas. Primeiro, aprovamos uma permissão suficiente para o `SwapRouter` e, em seguida, o chamamos com o caminho e a quantia corretos. + +```python +def balances(): + token0_balance = wethusdc_pool.token0.contract.functions.balanceOf(account.address).call() + token1_balance = wethusdc_pool.token1.contract.functions.balanceOf(account.address).call() + + print(f"{wethusdc_pool.token0.symbol} Balance: {Decimal(token0_balance) / Decimal(10 ** wethusdc_pool.token0.decimals)}") + print(f"{wethusdc_pool.token1.symbol} Balance: {Decimal(token1_balance) / Decimal(10 ** wethusdc_pool.token1.decimals)}") +``` + +Relate os saldos do usuário em ambas as moedas. + +```python +print("Saldos da conta antes da negociação:") +balances() + +if (expected_price > current_price): + print(f"Comprar, espero que o preço suba em {expected_price - current_price} USD") + buy(wethusdc_quotes[-1]) +else: + print(f"Vender, espero que o preço caia em {current_price - expected_price} USD") + sell() + +print("Saldos da conta após a negociação:") +balances() +``` + +Este agente atualmente só funciona uma vez. No entanto, você pode alterá-lo para funcionar continuamente, executando-o a partir do [`crontab`](https://man7.org/linux/man-pages/man1/crontab.1.html) ou envolvendo as linhas 368-400 em um loop e usando [`time.sleep`](https://docs.python.org/3/library/time.html#time.sleep) para esperar até a hora do próximo ciclo. + +## Possíveis melhorias {#improvements} + +Esta não é uma versão de produção completa; é apenas um exemplo para ensinar o básico. Aqui estão algumas ideias de melhorias. + +### Negociação mais inteligente {#smart-trading} + +Há dois fatos importantes que o agente ignora ao decidir o que fazer. + +- _A magnitude da mudança antecipada_. O agente vende uma quantia fixa de `WETH` se o preço for esperado para diminuir, independentemente da magnitude do declínio. + Pode-se argumentar que seria melhor ignorar pequenas alterações e vender com base no quanto esperamos que o preço caia. +- _O portfólio atual_. Se 10% do seu portfólio estiver em WETH e você achar que o preço vai subir, provavelmente faz sentido comprar mais. Mas se 90% do seu portfólio estiver em WETH, você pode estar suficientemente exposto e não há necessidade de comprar mais. O inverso é verdadeiro se você espera que o preço caia. + +### E se você quiser manter sua estratégia de negociação em segredo? {#secret} + +Os fornecedores de IA podem ver as consultas que você envia para seus LLMs, o que poderia expor o sistema de negociação genial que você desenvolveu com seu agente. Um sistema de negociação que muitas pessoas usam não tem valor, porque muitas pessoas tentam comprar quando você quer comprar (e o preço sobe) e tentam vender quando você quer vender (e o preço cai). + +Você pode executar um LLM localmente, por exemplo, usando o [LM-Studio](https://lmstudio.ai/), para evitar este problema. + +### De bot de IA para agente de IA {#bot-to-agent} + +Você pode argumentar que este é [um bot de IA, não um agente de IA](/ai-agents/#ai-agents-vs-ai-bots). Ele implementa uma estratégia relativamente simples que depende de informações predefinidas. Podemos habilitar a auto-melhoria, por exemplo, fornecendo uma lista de pools do Uniswap v3 e seus valores mais recentes e perguntando qual combinação tem o melhor valor preditivo. + +### Proteção contra slippage {#slippage-protection} + +Atualmente não há [proteção contra slippage](https://uniswapv3book.com/milestone_3/slippage-protection.html). Se a cotação atual for de US$ 2.000 e o preço esperado for de US$ 2.100, o agente comprará. No entanto, se antes de o agente comprar o custo subir para US$ 2.200, não faz mais sentido comprar. + +Para implementar a proteção contra slippage, especifique um valor de `amountOutMinimum` nas linhas 325 e 334 de [`agent.py`](https://github.com/qbzzt/260215-ai-agent/blob/05-trade/agent.py#L325). + +## Conclusão {#conclusion} + +Esperamos que agora você saiba o suficiente para começar a usar agentes de IA. Esta não é uma visão geral abrangente do assunto; existem livros inteiros dedicados a isso, mas isso é suficiente para você começar. Boa sorte! + +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). diff --git a/public/content/translations/pt-br/developers/tutorials/all-you-can-cache/index.md b/public/content/translations/pt-br/developers/tutorials/all-you-can-cache/index.md index 7a99bcf4de1..9a0c6fce339 100644 --- a/public/content/translations/pt-br/developers/tutorials/all-you-can-cache/index.md +++ b/public/content/translations/pt-br/developers/tutorials/all-you-can-cache/index.md @@ -1,42 +1,39 @@ --- -title: "Tudo que você puder armazenar em cache" -description: Aprenda como criar e usar um contrato de cache para transações de roll-up mais baratas +title: "Tudo que você pode colocar em cache" +description: "Aprenda a criar e usar um contrato de cache para transações de rollup mais baratas" author: Ori Pomerantz -tags: - - "camada 2" - - "armazenamento em cache" - - "armazenamento" +tags: [ "camada 2", "cache", "armazenamento" ] skill: intermediate published: 2022-09-15 lang: pt-br --- -Ao usar roll-ups, o custo de um byte na transação é muito mais caro que o custo de um slot de armazenamento. Portanto, faz sentido armazenar em cache o máximo de informações possível na cadeia. +Ao usar rollups, o custo de um byte na transação é muito mais caro do que o custo de um slot de armazenamento. Portanto, faz sentido armazenar em cache o máximo de informações on-chain possível. -Neste artigo, você aprenderá como criar e usar um contrato de armazenamento em cache de forma que qualquer valor de parâmetro, provável de ser usado diversas vezes, será armazenado em cache e ficará disponível para uso (depois da primeira vez) com um número muito menor de bytes, e como escrever código off-chain para usar esse cache. +Neste artigo, você aprenderá a criar e usar um contrato de cache de forma que qualquer valor de parâmetro que provavelmente será usado várias vezes será armazenado em cache e estará disponível para uso (após a primeira vez) com um número muito menor de bytes, e como escrever código off-chain que usa esse cache. -Se você quiser pular o artigo e somente ver o código-fonte, [consulte-o aqui](https://github.com/qbzzt/20220915-all-you-can-cache). A pilha de desenvolvimento é [Foundry](https://book.getfoundry.sh/getting-started/installation). +Se quiser pular o artigo e ver apenas o código-fonte, [ele está aqui](https://github.com/qbzzt/20220915-all-you-can-cache). A pilha de desenvolvimento é a [Foundry](https://getfoundry.sh/introduction/installation/). -## Design Geral {#overall-design} +## Projeto geral {#overall-design} -Para fins de simplicidade, vamos supor que todos os parâmetros de transação são `uint256`, com 32 bytes de tamanho. Quando recebemos uma transação, fazemos o parse em cada parâmetro deste modo: +Para simplificar, vamos supor que todos os parâmetros da transação são `uint256`, com 32 bytes de comprimento. Ao receber uma transação, analisaremos cada parâmetro desta forma: -1. Se o primeiro byte for `0xFF`, pegue os 32 bytes seguintes como um valor de parâmetro e escreva-o no cache. +1. Se o primeiro byte for `0xFF`, pegue os próximos 32 bytes como um valor de parâmetro e escreva-o no cache. 2. Se o primeiro byte for `0xFE`, pegue os próximos 32 bytes como um valor de parâmetro, mas _não_ o escreva no cache. -3. Para qualquer outro valor, pegue os primeiros quatro bits como o número de bytes adicionais, e os últimos quatro bits como os bits mais significantes da chave do cache. Veja aqui alguns exemplos: +3. Para qualquer outro valor, pegue os quatro bits superiores como o número de bytes adicionais e os quatro bits inferiores como os bits mais significativos da chave do cache. Veja aqui alguns exemplos: - | Bytes em calldata | Chave da cache | - |:----------------- | --------------:| + | Bytes em calldata | Chave de cache | + | :---------------- | -------------: | | 0x0F | 0x0F | | 0x10,0x10 | 0x10 | | 0x12,0xAC | 0x02AC | | 0x2D,0xEA, 0xD6 | 0x0DEAD6 | -## Manipulação do cache {#cache-manipulation} +## Manipulação de cache {#cache-manipulation} -A cache é implementada em [`Cache.sol`](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/src/Cache.sol). Vamos passar por ele linha a linha. +O cache é implementado em [`Cache.sol`](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/src/Cache.sol). Vamos analisá-lo linha por linha. ```solidity // SPDX-License-Identifier: UNLICENSED @@ -49,22 +46,22 @@ contract Cache { bytes1 public constant DONT_CACHE = 0xFE; ``` -Essas constantes são usadas para interpretar os casos especiais nos quais fornecemos todas as informações, independentemente de as querermos escritas no cache ou não. Escrever no cache requer duas operações [`SSTORE`](https://www.evm.codes/#55) nos slots de armazenamento previamente não utilizados, ao custo de 22.100 gás cada. Portanto, deixamos isso opcional. +Essas constantes são usadas para interpretar os casos especiais em que fornecemos todas as informações e queremos ou não que elas sejam gravadas no cache. Escrever no cache requer duas operações [`SSTORE`](https://www.evm.codes/#55) em slots de armazenamento não utilizados anteriormente, a um custo de 22.100 de gás cada, por isso tornamos isso opcional. ```solidity mapping(uint => uint) public val2key; ``` -Um [mapeamento](https://www.geeksforgeeks.org/solidity-mappings/) entre os valores e suas chaves. Esta informação é necessária para codificar valores antes de você enviar a transação. +Um [mapeamento](https://www.geeksforgeeks.org/solidity/solidity-mappings/) entre os valores e suas chaves. Esta informação é necessária para codificar valores antes de enviar a transação. ```solidity - // Location n has the value for key n+1, because we need to preserve - // zero as "not in the cache". + // A localização n tem o valor da chave n+1, porque precisamos preservar + // o zero como "não está no cache". uint[] public key2val; ``` -Podemos usar uma matriz para mapear das chaves aos valores, pois atribuímos as chaves e, para simplificar, fazemos isso de modo sequencial. +Podemos usar um array para o mapeamento de chaves para valores, pois atribuímos as chaves e, para simplificar, fazemos isso sequencialmente. ```solidity function cacheRead(uint _key) public view returns (uint) { @@ -73,69 +70,69 @@ Podemos usar uma matriz para mapear das chaves aos valores, pois atribuímos as } // cacheRead ``` -Ler um valor da cache. +Lê um valor do cache. ```solidity - // Write a value to the cache if it's not there already - // Only public to enable the test to work + // Escreve um valor no cache se ele ainda não estiver lá + // Público apenas para permitir que o teste funcione function cacheWrite(uint _value) public returns (uint) { - // If the value is already in the cache, return the current key + // Se o valor já estiver no cache, retorne a chave atual if (val2key[_value] != 0) { return val2key[_value]; } ``` -Não faz sentido colocar o mesmo valor no cache mais de uma vez. Se o valor já está lá, apenas retorne a chave existente. +Não faz sentido colocar o mesmo valor no cache mais de uma vez. Se o valor já estiver lá, basta retornar a chave existente. ```solidity - // Since 0xFE is a special case, the largest key the cache can - // hold is 0x0D followed by 15 0xFF's. If the cache length is already that - // large, fail. + // Como 0xFE é um caso especial, a maior chave que o cache pode + // conter é 0x0D seguido por 15 0xFF's. Se o tamanho do cache já for tão + // grande, falhe. // 1 2 3 4 5 6 7 8 9 A B C D E F require(key2val.length+1 < 0x0DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, "cache overflow"); ``` -Não acho que iremos algum dia ter um cache tão grande (cerca de 1,8\*1037 entradas, o que exigiria cerca de 1027 TB de armazenamento). No entanto, eu sou velho o suficiente para lembrar que ["640kB sempre será o suficiente"](https://quoteinvestigator.com/2011/09/08/640k-enough/). Este teste é muito barato. +Acho que nunca teremos um cache tão grande (aproximadamente 1,8\*1037 entradas, o que exigiria cerca de 1027 TB para armazenar). No entanto, tenho idade suficiente para me lembrar de ["640kB sempre seriam suficientes"](https://quoteinvestigator.com/2011/09/08/640k-enough/). Este teste é muito barato. ```solidity - // Write the value using the next key + // Escreve o valor usando a próxima chave val2key[_value] = key2val.length+1; ``` -Adicione a busca reversa (do valor para a chave). +Adicione a pesquisa reversa (do valor para a chave). ```solidity key2val.push(_value); ``` -Adicione a busca para frente (da chave para o valor). Como atribuímos valores de modo sequencial, podemos apenas adicioná-los depois do último valor da matriz. +Adicione a pesquisa direta (da chave para o valor). Como atribuímos valores sequencialmente, podemos simplesmente adicioná-lo após o último valor do array. ```solidity return key2val.length; } // cacheWrite ``` -Retorne o novo tamanho de `key2val`, que é a célula onde o novo valor está armazenado. +Retorna o novo comprimento de `key2val`, que é a célula onde o novo valor está armazenado. ```solidity function _calldataVal(uint startByte, uint length) private pure returns (uint) ``` -Essa função lê um valor de calldata de tamanho arbitrário (até 32 bytes, o tamanho da palavra). +Esta função lê um valor do calldata de comprimento arbitrário (até 32 bytes, o tamanho da palavra). ```solidity { uint _retVal; require(length < 0x21, - "_calldataVal length limit is 32 bytes"); + "O limite de comprimento de _calldataVal é de 32 bytes"); require(length + startByte <= msg.data.length, - "_calldataVal trying to read beyond calldatasize"); + "_calldataVal tentando ler além do tamanho do calldata"); ``` -A função é interna, por isso, se o resto do código for escrito corretamente, esses testes não serão obrigatórios. Porém, como eles não custam muito, podemos tê-los de qualquer forma. +Esta função é interna, então se o resto do código for escrito corretamente, esses testes não são necessários. No entanto, eles não custam muito, então podemos mantê-los. ```solidity assembly { @@ -143,7 +140,7 @@ A função é interna, por isso, se o resto do código for escrito corretamente, } ``` -Este código está em [Yul](https://docs.soliditylang.org/en/v0.8.16/yul.html). Ele lê um valor de 32 bytes do calldata. Isso funciona até mesmo se o calldata parar antes `startByte+32`, pois o espaço não inicializado na EVM é considerado como zero. +Este código está em [Yul](https://docs.soliditylang.org/en/v0.8.16/yul.html). Ele lê um valor de 32 bytes do calldata. Isso funciona mesmo que o calldata pare antes de `startByte+32`, porque o espaço não inicializado na EVM é considerado como zero. ```solidity _retVal = _retVal >> (256-length*8); @@ -156,39 +153,39 @@ Não queremos necessariamente um valor de 32 bytes. Isso elimina os bytes em exc } // _calldataVal - // Read a single parameter from the calldata, starting at _fromByte + // Lê um único parâmetro do calldata, começando em _fromByte function _readParam(uint _fromByte) internal returns (uint _nextByte, uint _parameterValue) { ``` -Leia um único parâmetro do calldata. Observe que precisamos retornar não somente o valor que lemos, mas também a localização do próximo byte, pois os parâmetros podem estar na faixa de comprimento de 1 byte a 33 bytes. +Lê um único parâmetro do calldata. Observe que precisamos retornar não apenas o valor que lemos, mas também a localização do próximo byte, porque os parâmetros podem variar de 1 a 33 bytes de comprimento. ```solidity - // The first byte tells us how to interpret the rest + // O primeiro byte nos diz como interpretar o resto uint8 _firstByte; _firstByte = uint8(_calldataVal(_fromByte, 1)); ``` -O Solidity tenta reduzir o número de bugs proibindo [conversões de tipo implícitas](https://docs.soliditylang.org/en/v0.8.16/types.html#implicit-conversions) potencialmente perigosas. Um rebaixamento, por exemplo, de 256 bits para 8 bits, precisa ser explícito. +O Solidity tenta reduzir o número de bugs, proibindo [conversões de tipo implícitas](https://docs.soliditylang.org/en/v0.8.16/types.html#implicit-conversions) potencialmente perigosas. Um rebaixamento, por exemplo, de 256 bits para 8 bits, precisa ser explícito. ```solidity - // Read the value, but do not write it to the cache + // Lê o valor, mas não o escreve no cache if (_firstByte == uint8(DONT_CACHE)) return(_fromByte+33, _calldataVal(_fromByte+1, 32)); - // Read the value, and write it to the cache + // Lê o valor e o escreve no cache if (_firstByte == uint8(INTO_CACHE)) { uint _param = _calldataVal(_fromByte+1, 32); cacheWrite(_param); return(_fromByte+33, _param); } - // If we got here it means that we need to read from the cache + // Se chegamos aqui, significa que precisamos ler do cache - // Number of extra bytes to read + // Número de bytes extras para ler uint8 _extraBytes = _firstByte / 16; ``` @@ -207,13 +204,13 @@ Pegue o [nibble](https://en.wikipedia.org/wiki/Nibble) inferior e combine-o com function _readParams(uint _paramNum) internal returns (uint[] memory) { ``` -Poderíamos pegar o número de parâmetros que temos do calldata propriamente dito, mas as funções que nos chamam sabem quantos parâmetros elas esperam. É mais fácil que elas nos contem. +Poderíamos obter o número de parâmetros que temos do próprio calldata, mas as funções que nos chamam sabem quantos parâmetros esperam. É mais fácil que elas nos contem. ```solidity - // The parameters we read + // Os parâmetros que lemos uint[] memory params = new uint[](_paramNum); - // Parameters start at byte 4, before that it's the function signature + // Os parâmetros começam no byte 4, antes disso é a assinatura da função uint _atByte = 4; for(uint i=0; i<_paramNum; i++) { @@ -221,14 +218,14 @@ Poderíamos pegar o número de parâmetros que temos do calldata propriamente di } ``` -Leia os parâmetros até que você tenha o número de que precisa. Se ultrapassarmos o fim do calldata, `_readParams` reverterá a chamada. +Leia os parâmetros até ter o número que você precisa. Se passarmos do final do calldata, `_readParams` reverterá a chamada. ```solidity return(params); } // readParams - // For testing _readParams, test reading four parameters + // Para testar _readParams, teste a leitura de quatro parâmetros function fourParam() public returns (uint256,uint256,uint256,uint256) { @@ -238,45 +235,45 @@ Leia os parâmetros até que você tenha o número de que precisa. Se ultrapassa } // fourParam ``` -Uma grande vantagem do Foundry é que ele permite que os testes sejam escritos no Solidity ([veja o teste de cache abaixo](#testing-the-cache)). Isto faz testes unitários muito mais fáceis. Essa é uma função que lê quatro parâmetros e retorna-os para que o teste possa verificar que eles estão corretos. +Uma grande vantagem da Foundry é que ela permite que os testes sejam escritos em Solidity ([veja Testando o cache abaixo](#testing-the-cache)). Isso torna os testes de unidade muito mais fáceis. Esta é uma função que lê quatro parâmetros e os retorna para que o teste possa verificar se eles estavam corretos. ```solidity - // Get a value, return bytes that will encode it (using the cache if possible) + // Obtém um valor, retorna os bytes que o codificarão (usando o cache, se possível) function encodeVal(uint _val) public view returns(bytes memory) { ``` -`encodeVal` é uma função que o código off-chain chama para ajudar a criar o calldata que usa o cache. Ela recebe um único valor e retorna os bytes que o codificam. Essa função é uma `view`, portanto, ela não requer uma transação e, quando chamada externamente, não custa nenhum gás. +`encodeVal` é uma função que o código off-chain chama para ajudar a criar calldata que usa o cache. Ela recebe um único valor e retorna os bytes que o codificam. Esta função é uma `view`, portanto não requer uma transação e, quando chamada externamente, não custa gás. ```solidity uint _key = val2key[_val]; - // The value isn't in the cache yet, add it + // O valor ainda não está no cache, adicione-o if (_key == 0) return bytes.concat(INTO_CACHE, bytes32(_val)); ``` -Na [EVM](/developers/docs/evm/) todo o armazenamento não inicializado é considerado como zero. Então, se buscarmos a chave de um valor que não está lá, obteremos zero. Nesse caso, os bytes que o codificaram são `INTO_CACHE` (portanto, ele será armazenado em cache da próxima vez), seguido do valor real. +Na [EVM](/developers/docs/evm/), todo o armazenamento não inicializado é considerado como zero. Então, se procurarmos a chave de um valor que não está lá, obtemos um zero. Nesse caso, os bytes que o codificam são `INTO_CACHE` (para que seja armazenado em cache da próxima vez), seguido do valor real. ```solidity - // If the key is <0x10, return it as a single byte + // Se a chave for <0x10, retorne-a como um único byte if (_key < 0x10) return bytes.concat(bytes1(uint8(_key))); ``` -Bytes únicos são os mais fáceis. Somente usamos [`bytes.concat`](https://docs.soliditylang.org/en/v0.8.16/types.html#the-functions-bytes-concat-and-string-concat) para transformar um tipo de `bytes` em uma matriz de bytes que pode ser de qualquer tamanho. Apesar do nome, isso funciona bem quando fornecemos somente um argumento. +Bytes únicos são os mais fáceis. Nós apenas usamos [`bytes.concat`](https://docs.soliditylang.org/en/v0.8.16/types.html#the-functions-bytes-concat-and-string-concat) para transformar um tipo `bytes` em um array de bytes que pode ter qualquer comprimento. Apesar do nome, funciona bem quando fornecido com apenas um argumento. ```solidity - // Two byte value, encoded as 0x1vvv + // Valor de dois bytes, codificado como 0x1vvv if (_key < 0x1000) return bytes.concat(bytes2(uint16(_key) | 0x1000)); ``` -Quando temos uma chave que é inferior a 163, podemos expressá-la em dois bytes. Primeiro, convertemos `_key`, que é um valor de 256 bits, para um valor de 16 bits e usamos um cálculo lógico para adicionar o número de bytes extras ao primeiro byte. Então, convertemos o byte em um valor `bytes2`, que pode ser convertido para `bytes`. +Quando temos uma chave menor que 163, podemos expressá-la em dois bytes. Primeiro, convertemos `_key`, que é um valor de 256 bits, para um valor de 16 bits e usamos o OU lógico para adicionar o número de bytes extras ao primeiro byte. Então, o transformamos em um valor `bytes2`, que pode ser convertido em `bytes`. ```solidity - // There is probably a clever way to do the following lines as a loop, - // but it's a view function so I'm optimizing for programmer time and - // simplicity. + // Provavelmente existe uma maneira inteligente de fazer as seguintes linhas como um loop, + // mas é uma função de visualização, então estou otimizando para o tempo do programador e + // simplicidade. if (_key < 16*256**2) return bytes.concat(bytes3(uint24(_key) | (0x2 * 16 * 256**2))); @@ -291,14 +288,14 @@ Quando temos uma chave que é inferior a 163, podemos expressá-la em return bytes.concat(bytes16(uint128(_key) | (0xF * 16 * 256**15))); ``` -Os outros valores (3 bytes, 4 bytes, etc.) são manipulados da mesma maneira, apenas com diferentes tamanhos de campo. +Os outros valores (3 bytes, 4 bytes, etc.) são tratados da mesma forma, apenas com tamanhos de campo diferentes. ```solidity - // If we get here, something is wrong. - revert("Error in encodeVal, should not happen"); + // Se chegarmos aqui, algo está errado. + revert("Erro em encodeVal, não deveria acontecer"); ``` -Se chegarmos até aí, significa que temos a chave que não é inferior a 16\*25615. Porém, `cacheWrite` limita as chaves, portanto, não conseguimos nem mesmo chegar a 14\*25616 (o que teria o primeiro byte de 0xFE, que se pareceria com `DONT_CACHE`). Mas ele não nos custa tanto para adicionar um teste caso um futuro programador introduza um bug. +Se chegarmos aqui, significa que obtivemos uma chave que não é menor que 16\*25615. Mas `cacheWrite` limita as chaves para que não possamos chegar a 14\*25616 (o que teria um primeiro byte de 0xFE, então se pareceria com `DONT_CACHE`). Mas não custa muito adicionar um teste caso um futuro programador introduza um bug. ```solidity } // encodeVal @@ -308,7 +305,7 @@ Se chegarmos até aí, significa que temos a chave que não é inferior a 16\*25 ### Testando o cache {#testing-the-cache} -Uma das vantagens do Foundry é que [ele deixa você escrever testes em Solidity](https://book.getfoundry.sh/forge/tests), o que facilita escrever testes de unidade. Os testes para a classe `Cache` estão [aqui](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/test/Cache.t.sol). Como o código de teste pode ser repetitivo, assim como os testes tendem a ser, este artigo explica apenas as partes interessantes. +Uma das vantagens da Foundry é que [ela permite que você escreva testes em Solidity](https://getfoundry.sh/forge/tests/overview/), o que facilita a escrita de testes de unidade. Os testes para a classe `Cache` estão [aqui](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/test/Cache.t.sol). Como o código de teste é repetitivo, como os testes tendem a ser, este artigo explica apenas as partes interessantes. ```solidity // SPDX-License-Identifier: UNLICENSED @@ -317,11 +314,11 @@ pragma solidity ^0.8.13; import "forge-std/Test.sol"; -// Need to run `forge test -vv` for the console. +// É necessário executar `forge test -vv` para o console. import "forge-std/console.sol"; ``` -Isso é apenas um modelo necessário para usar o pacote de teste e `console.log`. +Isso é apenas um código padrão necessário para usar o pacote de teste e o `console.log`. ```solidity import "src/Cache.sol"; @@ -338,13 +335,13 @@ contract CacheTest is Test { } ``` -A função `setUp` é chamada antes de cada teste. Nesse caso, acabamos de criar um novo cache, de modo que nossos testes não sejam afetados um pelo outro. +A função `setUp` é chamada antes de cada teste. Neste caso, apenas criamos um novo cache, para que nossos testes não afetem uns aos outros. ```solidity function testCaching() public { ``` -Testes são funções cujos nomes começam com `test`. Essa função verifica a funcionalidade básica do cache, escrevendo valores e lendo-os novamente. +Testes são funções cujos nomes começam com `test`. Esta função verifica a funcionalidade básica do cache, escrevendo valores e lendo-os novamente. ```solidity for(uint i=1; i<5000; i++) { @@ -355,15 +352,15 @@ Testes são funções cujos nomes começam com `test`. Essa função verifica a assertEq(cache.cacheRead(i), i*i); ``` -Isto é como você faz teste realmente, usando as funções [`assert...`](https://book.getfoundry.sh/reference/forge-std/std-assertions). Nesse caso, nós verificamos que o valor que escrevemos é o mesmo que lemos. Podemos descartar o resultado de `cache.cacheWrite`, pois sabemos que as chaves do cache são atribuídos linearmente. +É assim que você faz o teste real, usando as [funções `assert...`](https://getfoundry.sh/reference/forge-std/std-assertions/). Neste caso, verificamos que o valor que escrevemos é o que lemos. Podemos descartar o resultado de `cache.cacheWrite` porque sabemos que as chaves de cache são atribuídas linearmente. ```solidity } } // testCaching - // Cache the same value multiple times, ensure that the key stays - // the same + // Armazena o mesmo valor em cache várias vezes, garante que a chave permaneça + // a mesma function testRepeatCaching() public { for(uint i=1; i<100; i++) { uint _key1 = cache.cacheWrite(i); @@ -372,7 +369,7 @@ Isto é como você faz teste realmente, usando as funções [`assert...`](https: } ``` -Primeiro, escrevemos cada valor duas vezes para o cache e nos certificamos de que as chaves são as mesmas (ou seja, a segunda escrita não aconteceu realmente). +Primeiro, escrevemos cada valor duas vezes no cache e garantimos que as chaves sejam as mesmas (o que significa que a segunda escrita não aconteceu de fato). ```solidity for(uint i=1; i<100; i+=3) { @@ -382,20 +379,20 @@ Primeiro, escrevemos cada valor duas vezes para o cache e nos certificamos de qu } // testRepeatCaching ``` -Na teoria poderia haver um bug que não afetasse escritas em cache consecutivas. Então, fazemos aqui algumas escritas que não sejam consecutivas e observamos que os valores ainda não foram reescritos. +Em teoria, poderia haver um bug que não afeta as escritas consecutivas no cache. Então, aqui fazemos algumas escritas que não são consecutivas e vemos que os valores ainda não são reescritos. ```solidity - // Read a uint from a memory buffer (to make sure we get back the parameters - // we sent out) + // Lê um uint de um buffer de memória (para garantir que recebamos de volta os parâmetros + // que enviamos) function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) ``` -Leia uma palavra de 256 bits de um buffer de `bytes memory`. Essa função utilitária nos deixa verificar que recebemos os resultados corretos quando executamos uma chamada de função que usa o cache. +Lê uma palavra de 256 bits de um buffer `bytes memory`. Esta função utilitária nos permite verificar se recebemos os resultados corretos quando executamos uma chamada de função que usa o cache. ```solidity { - require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); + require(_bytes.length >= _start + 32, "toUint256_fora_dos_limites"); uint256 tempUint; assembly { @@ -403,31 +400,31 @@ Leia uma palavra de 256 bits de um buffer de `bytes memory`. Essa função utili } ``` -O Yul não suporta estruturas de dados além de `uint256`, então quando você se refere a uma estrutura de dados mais sofisticada, como um buffer de memória `_bytes`, você obtém o endereço dessa estrutura. O Solidity armazena valores `bytes memory` como uma palavra de 32 bytes que contém o tamanho, seguida dos bytes reais, então, para obter o número de bytes `_start`, precisamos calcular `_bytes+32+_start`. +O Yul não suporta estruturas de dados além de `uint256`, então, quando você se refere a uma estrutura de dados mais sofisticada, como o buffer de memória `_bytes`, você obtém o endereço dessa estrutura. O Solidity armazena valores `bytes memory` como uma palavra de 32 bytes que contém o comprimento, seguida pelos bytes reais, então para obter o byte de número `_start` precisamos calcular `_bytes+32+_start`. ```solidity return tempUint; } // toUint256 - // Function signature for fourParams(), courtesy of + // Assinatura da função para fourParams(), cortesia de // https://www.4byte.directory/signatures/?bytes4_signature=0x3edc1e6d bytes4 constant FOUR_PARAMS = 0x3edc1e6d; - // Just some constant values to see we're getting the correct values back + // Apenas alguns valores constantes para ver se estamos recebendo os valores corretos de volta uint256 constant VAL_A = 0xDEAD60A7; uint256 constant VAL_B = 0xBEEF; uint256 constant VAL_C = 0x600D; uint256 constant VAL_D = 0x600D60A7; ``` -Algumas constantes de que precisamos para os testes. +Algumas constantes que precisamos para testar. ```solidity function testReadParam() public { ``` -Chame `fourParams()`, uma função que usa `readParams`, para testar nós podemos ler parâmetros corretamente. +Chame `fourParams()`, uma função que usa `readParams`, para testar se conseguimos ler os parâmetros corretamente. ```solidity address _cacheAddr = address(cache); @@ -436,7 +433,7 @@ Chame `fourParams()`, uma função que usa `readParams`, para testar nós podemo bytes memory _callOutput; ``` -Não podemos usar o mecanismo de ABI normal para chamar uma função usando o cache, por isso, precisamos usar o mecanismo de baixo nível [`
.call()`](https://docs.soliditylang.org/en/v0.8.16/types.html#members-of-addresses). Esse mecanismo pega um `bytes memory` como entrada e retorna aquele (assim como o valor booleano) como saída. +Não podemos usar o mecanismo ABI normal para chamar uma função usando o cache, então precisamos usar o mecanismo de baixo nível [`
.call()`](https://docs.soliditylang.org/en/v0.8.16/types.html#members-of-addresses). Esse mecanismo usa um `bytes memory` como entrada e o retorna (assim como um valor booleano) como saída. ```solidity // First call, the cache is empty @@ -444,15 +441,15 @@ Não podemos usar o mecanismo de ABI normal para chamar uma função usando o ca FOUR_PARAMS, ``` -É útil para o mesmo contrato suportar ambas funções em cache (para chamadas diretamente de transações) e funções não em cache (para chamadas de outros contratos inteligentes). Para fazer isso nós precisamos continuar a confiar no mecanismo Solidity para chamar a função correta, ao invés de pôr tudo em [uma função `fallback`](https://docs.soliditylang.org/en/v0.8.16/contracts.html#fallback-function). Fazer isso torna a componibilidade muito mais fácil. Um único byte seria suficiente para identificar a função na maioria dos casos, por isso, estamos desperdiçando três bytes (16\*3=48 gás). No entanto, no momento em que escrevo este artigo, 48 gás custam 0,07 centavos de dólar, o que é um custo razoável para um código mais simples e menos sujeito a bugs. +É útil que o mesmo contrato suporte tanto funções em cache (para chamadas diretamente de transações) quanto funções não armazenadas em cache (para chamadas de outros contratos inteligentes). Para fazer isso, precisamos continuar a confiar no mecanismo do Solidity para chamar a função correta, em vez de colocar tudo em uma [função `fallback`](https://docs.soliditylang.org/en/v0.8.16/contracts.html#fallback-function). Fazer isso torna a componentização muito mais fácil. Um único byte seria suficiente para identificar a função na maioria dos casos, então estamos desperdiçando três bytes (16\*3=48 de gás). No entanto, no momento em que escrevo, esses 48 de gás custam 0,07 centavos de dólar, o que é um custo razoável para um código mais simples e menos propenso a bugs. ```solidity - // First value, add it to the cache + // Primeiro valor, adicione-o ao cache cache.INTO_CACHE(), bytes32(VAL_A), ``` -O primeiro valor: Um sinalizador dizendo que é um valor que precisa ser escrito na cache, seguido pelos 32 bytes do valor. Os outros três valores são similares, exceto que `VAL_B` não é escrito no cache e `VAL_C` é ambos o terceiro e quarto parâmetros. +O primeiro valor: um sinalizador dizendo que é um valor completo que precisa ser escrito no cache, seguido pelos 32 bytes do valor. Os outros três valores são semelhantes, exceto que `VAL_B` não é escrito no cache e `VAL_C` é tanto o terceiro quanto o quarto parâmetro. ```solidity . @@ -468,14 +465,14 @@ O primeiro valor: Um sinalizador dizendo que é um valor que precisa ser escrito assertEq(_success, true); ``` -Nós esperamos que a chamada tenha sucesso. +Esperamos que a chamada seja bem-sucedida. ```solidity assertEq(cache.cacheRead(1), VAL_A); assertEq(cache.cacheRead(2), VAL_C); ``` -Nós começamos com uma cache vazia e então adicionamos `VAL_A` seguida de `VAL_C`. Nós esperaríamos a primeira ter a chave 1, e a segunda ter a 2. +Começamos com um cache vazio e depois adicionamos `VAL_A` seguido de `VAL_C`. Esperaríamos que o primeiro tivesse a chave 1 e o segundo a chave 2. ``` assertEq(toUint256(_callOutput,0), VAL_A); @@ -484,25 +481,25 @@ Nós começamos com uma cache vazia e então adicionamos `VAL_A` seguida de `VAL assertEq(toUint256(_callOutput,96), VAL_C); ``` -A saída é composta pelos quatro parâmetros. Aqui, verificamos que está correto. +A saída são os quatro parâmetros. Aqui verificamos que está correto. ```solidity - // Second call, we can use the cache + // Segunda chamada, podemos usar o cache _callInput = bytes.concat( FOUR_PARAMS, - // First value in the Cache + // Primeiro valor no Cache bytes1(0x01), ``` -As chaves de cache abaixo de 16 correspondem a apenas um byte. +Chaves de cache abaixo de 16 têm apenas um byte. ```solidity - // Second value, don't add it to the cache + // Segundo valor, não o adicione ao cache cache.DONT_CACHE(), bytes32(VAL_B), - // Third and fourth values, same value + // Terceiro e quarto valores, mesmo valor bytes1(0x02), bytes1(0x02) ); @@ -512,13 +509,13 @@ As chaves de cache abaixo de 16 correspondem a apenas um byte. } // testReadParam ``` -Os testes depois da chamada são idênticos a aqueles depois da primeira chamada. +Os testes após a chamada são idênticos aos da primeira chamada. ```solidity function testEncodeVal() public { ``` -Esta função é similar a `testReadParam`, exceto que ao invés de escrever os parâmetros explicitamente, nós usamos `encodeVal()`. +Esta função é semelhante a `testReadParam`, exceto que, em vez de escrever os parâmetros explicitamente, usamos `encodeVal()`. ```solidity . @@ -538,23 +535,23 @@ Esta função é similar a `testReadParam`, exceto que ao invés de escrever os } // testEncodeVal ``` -O único teste adicional em `testEncodeVal()` é verificar que o comprimento de `_callInput` está correto. Para a primeira chamada, ele é 4+33\*4. Para a segunda, na qual cada valor já está no cache, ele é 4+1\*4. +O único teste adicional em `testEncodeVal()` é verificar se o comprimento de `_callInput` está correto. Para a primeira chamada, é 4+33\*4. Para a segunda, onde cada valor já está no cache, é 4+1\*4. ```solidity - // Test encodeVal when the key is more than a single byte - // Maximum three bytes because filling the cache to four bytes takes - // too long. + // Testa encodeVal quando a chave tem mais de um byte + // Máximo de três bytes porque preencher o cache até quatro bytes leva + // muito tempo. function testEncodeValBig() public { - // Put a number of values in the cache. - // To keep things simple, use key n for value n. + // Coloca uma série de valores no cache. + // Para simplificar, use a chave n para o valor n. for(uint i=1; i<0x1FFF; i++) { cache.cacheWrite(i); } ``` -A função `testEncodeVal` acima somente escreve quatro valores na cache, então [a parte da função que lida com valores multi-byte](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/src/Cache.sol#L144-L171) não é checada. Porém, esse código é complicado e sujeito a erros. +A função `testEncodeVal` acima apenas escreve quatro valores no cache, então [a parte da função que lida com valores de vários bytes](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/src/Cache.sol#L144-L171) não é verificada. Mas esse código é complicado e propenso a erros. -A primeira parte dessa função é um loop que escreve todos os valores de 1 até 0x1FFF para o cache em ordem, a fim de podermos codificar esses valores e saber para onde eles estão indo. +A primeira parte desta função é um loop que escreve todos os valores de 1 a 0x1FFF no cache em ordem, para que possamos codificar esses valores e saber para onde eles estão indo. ```solidity . @@ -563,14 +560,14 @@ A primeira parte dessa função é um loop que escreve todos os valores de 1 at _callInput = bytes.concat( FOUR_PARAMS, - cache.encodeVal(0x000F), // One byte 0x0F - cache.encodeVal(0x0010), // Two bytes 0x1010 - cache.encodeVal(0x0100), // Two bytes 0x1100 - cache.encodeVal(0x1000) // Three bytes 0x201000 + cache.encodeVal(0x000F), // Um byte 0x0F + cache.encodeVal(0x0010), // Dois bytes 0x1010 + cache.encodeVal(0x0100), // Dois bytes 0x1100 + cache.encodeVal(0x1000) // Três bytes 0x201000 ); ``` -Teste valores de um byte, dois bytes e três bytes. Não testamos além disso, pois levaria tempo demais para escrever entradas de pilha suficientes (pelo menos 0x10000000, cerca de um quarto de bilhão). +Testa valores de um, dois e três bytes. Não testamos além disso porque levaria muito tempo para escrever entradas de pilha suficientes (pelo menos 0x10000000, aproximadamente um quarto de bilhão). ```solidity . @@ -580,11 +577,11 @@ Teste valores de um byte, dois bytes e três bytes. Não testamos além disso, p } // testEncodeValBig - // Test what with an excessively small buffer we get a revert + // Testa o que acontece com um buffer excessivamente pequeno para obter uma reversão function testShortCalldata() public { ``` -Teste o que acontece no caso anormal em que não há parâmetros suficientes. +Testa o que acontece no caso anormal em que não há parâmetros suficientes. ```solidity . @@ -595,10 +592,10 @@ Teste o que acontece no caso anormal em que não há parâmetros suficientes. } // testShortCalldata ``` -Como ele é revertido, o resultado deve ser `false`. +Como ele reverte, o resultado que devemos obter é `false`. ``` - // Call with cache keys that aren't there + // Chama com chaves de cache que não existem function testNoCacheKey() public { . . @@ -606,52 +603,52 @@ Como ele é revertido, o resultado deve ser `false`. _callInput = bytes.concat( FOUR_PARAMS, - // First value, add it to the cache + // Primeiro valor, adicione-o ao cache cache.INTO_CACHE(), bytes32(VAL_A), - // Second value + // Segundo valor bytes1(0x0F), bytes2(0x1234), bytes11(0xA10102030405060708090A) ); ``` -Esta função pega quatro parâmetros perfeitamente legítimos, exceto que a cache está vazia, então não há valores lá para ler. +Esta função obtém quatro parâmetros perfeitamente legítimos, exceto que o cache está vazio, então não há valores para ler. ```solidity . . . - // Test what with an excessively long buffer everything works file + // Testa o que acontece com um buffer excessivamente longo para ver se tudo funciona bem function testLongCalldata() public { address _cacheAddr = address(cache); bool _success; bytes memory _callInput; bytes memory _callOutput; - // First call, the cache is empty + // Primeira chamada, o cache está vazio _callInput = bytes.concat( FOUR_PARAMS, - // First value, add it to the cache + // Primeiro valor, adicione-o ao cache cache.INTO_CACHE(), bytes32(VAL_A), - // Second value, add it to the cache + // Segundo valor, adicione-o ao cache cache.INTO_CACHE(), bytes32(VAL_B), - // Third value, add it to the cache + // Terceiro valor, adicione-o ao cache cache.INTO_CACHE(), bytes32(VAL_C), - // Fourth value, add it to the cache + // Quarto valor, adicione-o ao cache cache.INTO_CACHE(), bytes32(VAL_D), - // And another value for "good luck" + // E outro valor para "dar sorte" bytes4(0x31112233) ); ``` -Esta função envia cinco valores. Sabemos que o quinto valor é ignorado porque não é uma entrada de cache válida, o que causaria uma reversão se não tivesse sido incluída. +Esta função envia cinco valores. Sabemos que o quinto valor é ignorado porque não é uma entrada de cache válida, o que teria causado uma reversão se não tivesse sido incluído. ```solidity (_success, _callOutput) = _cacheAddr.call(_callInput); @@ -665,13 +662,13 @@ Esta função envia cinco valores. Sabemos que o quinto valor é ignorado porque ``` -## Uma amostra do aplicativo {#a-sample-app} +## Um aplicativo de exemplo {#a-sample-app} -Escrever testes em Solidity é tudo muito bem, mas no final do dia, um dapp precisa ser capaz de processar requisições de fora da cadeia para ser útil. Este artigo demonstra como usar o cache em um dapp com `WORM`, que significa “escrever uma vez, ler várias” (em inglês, "Write Once, Read Many"). Se uma chave ainda não estiver escrita, você pode escrever um valor para ela. Se a chave já estiver escrita, você terá uma reversão. +Escrever testes em Solidity é muito bom, mas no final das contas um dapp precisa ser capaz de processar solicitações de fora da cadeia para ser útil. Este artigo demonstra como usar o cache em um dapp com `WORM`, que significa "Write Once, Read Many" (Escreva uma vez, leia muitas). Se uma chave ainda não foi escrita, você pode escrever um valor para ela. Se a chave já estiver escrita, você recebe uma reversão. ### O contrato {#the-contract} -[Este é o contrato](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/src/WORM.sol). Ele repete, em grande parte, o que já fizemos com `Cache` e `CacheTest`, então abrangeremos somente as partes que são interessantes. +[Este é o contrato](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/src/WORM.sol). Ele repete principalmente o que já fizemos com `Cache` e `CacheTest`, então abordaremos apenas as partes interessantes. ```solidity import "./Cache.sol"; @@ -679,7 +676,7 @@ import "./Cache.sol"; contract WORM is Cache { ``` -A maneira mais fácil de usar `Cache` é herdá-lo no seu próprio contrato. +A maneira mais fácil de usar o `Cache` é herdá-lo em nosso próprio contrato. ```solidity function writeEntryCached() external { @@ -688,59 +685,59 @@ A maneira mais fácil de usar `Cache` é herdá-lo no seu próprio contrato. } // writeEntryCached ``` -Essa função é similar a `fourParam` no `CacheTest` acima. Como nós não seguimos as especificações da ABI, é melhor não declarar nenhum parâmetro dentro da função. +Esta função é semelhante a `fourParam` em `CacheTest` acima. Como não seguimos as especificações da ABI, é melhor não declarar nenhum parâmetro na função. ```solidity - // Make it easier to call us - // Function signature for writeEntryCached(), courtesy of + // Facilita a chamada + // Assinatura da função para writeEntryCached(), cortesia de // https://www.4byte.directory/signatures/?bytes4_signature=0xe4e4f2d3 bytes4 constant public WRITE_ENTRY_CACHED = 0xe4e4f2d3; ``` -O código externo que chama `writeEntryCached` precisará construir manualmente o calldata, ao invés de usar `worm.writeEntryCached`, porque nós não seguimos as especificações da ABI. Tendo o valor desta constante só facilita escrevê-la. +O código externo que chama `writeEntryCached` precisará construir manualmente o calldata, em vez de usar `worm.writeEntryCached`, porque não seguimos as especificações da ABI. Ter esse valor constante apenas facilita a escrita. -Observe que, apesar de definirmos `WRITE_ENTRY_CACHED` como uma variável de estado, para lê-la externamente é necessário usar a função getter, `worm.WRITE_ENTRY_CACHED()`. +Observe que, embora definamos `WRITE_ENTRY_CACHED` como uma variável de estado, para lê-la externamente é necessário usar sua função getter, `worm.WRITE_ENTRY_CACHED()`. ```solidity function readEntry(uint key) public view returns (uint _value, address _writtenBy, uint _writtenAtBlock) ``` -A função de leitura é uma `view`, então ela não requer uma transação e não custa gas. Como resultado, não há benefício de usar cache para o parâmetro. Com funções view é melhor usar o mecanismo padrão, que é mais simples. +A função de leitura é uma `view`, portanto não requer uma transação e não custa gás. Como resultado, não há benefício em usar o cache para o parâmetro. Com funções de visualização, é melhor usar o mecanismo padrão que é mais simples. ### O código de teste {#the-testing-code} -[Este é o código de teste para o contrato](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/test/WORM.t.sol). Novamente, vamos ver somente o que é interessante. +[Este é o código de teste para o contrato](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/test/WORM.t.sol). Novamente, vamos olhar apenas para o que é interessante. ```solidity function testWReadWrite() public { worm.writeEntry(0xDEAD, 0x60A7); - vm.expectRevert(bytes("entry already written")); + vm.expectRevert(bytes("entrada já escrita")); worm.writeEntry(0xDEAD, 0xBEEF); ``` -[Este (`vm.expectRevert`)](https://book.getfoundry.sh/cheatcodes/expect-revert#expectrevert) é como especificamos em um teste Foundry que a próxima chamada deve falhar, assim como a razão dessa falha. Isto se aplica quando nós usamos a sintaxe `.()` ao invés de construir o calldata e chamar o contrato usando interface de baixo nível (`.call()`, etc.). +[Isso (`vm.expectRevert`)](https://book.getfoundry.sh/cheatcodes/expect-revert#expectrevert) é como especificamos em um teste da Foundry que a próxima chamada deve falhar e o motivo relatado para a falha. Isso se aplica quando usamos a sintaxe `.`() em vez de construir o calldata e chamar o contrato usando a interface de baixo nível (`.call()`, etc.). ```solidity function testReadWriteCached() public { uint cacheGoat = worm.cacheWrite(0x60A7); ``` -Aqui nós usamos o fato de `cacheWrite` retornar a chave da cache. Isto não é algo que nós esperaríamos usar em produção, porque `cacheWrite` altera o estado, e por isso pode ser chamado apenas durante a transação. Transações não têm valores de retorno. Se elas têm resultados, esses resultados devem ser supostamente emitidos como eventos. Assim, o valor de retorno de `cacheWrite` é somente acessível do código on-chain, e o código on-chain não precisa armazenar parâmetros em cache. +Aqui usamos o fato de que `cacheWrite` retorna a chave do cache. Isso não é algo que esperaríamos usar em produção, porque `cacheWrite` altera o estado e, portanto, só pode ser chamado durante uma transação. As transações não têm valores de retorno; se tiverem resultados, esses resultados devem ser emitidos como eventos. Portanto, o valor de retorno `cacheWrite` só é acessível a partir do código na cadeia (on-chain), e o código na cadeia não precisa de cache de parâmetros. ```solidity (_success,) = address(worm).call(_callInput); ``` -É assim que contamos ao Solidity que, enquanto `.call()` tem dois valores de retorno, só nos importamos com o primeiro. +É assim que dizemos ao Solidity que, embora `.call()` tenha dois valores de retorno, só nos importamos com o primeiro. ```solidity (_success,) = address(worm).call(_callInput); assertEq(_success, false); ``` -Como usamos a função de baixo nível `
.call()`, não podemos usar `vm.expectRevert()` e temos de olhar para o valor de êxito booleano que obtivemos da chamada. +Como usamos a função de baixo nível `
.call()`, não podemos usar `vm.expectRevert()` e temos que observar o valor de sucesso booleano que obtemos da chamada. ```solidity event EntryWritten(uint indexed key, uint indexed value); @@ -756,13 +753,13 @@ Como usamos a função de baixo nível `
.call()`, não podemos usar `vm (_success,) = address(worm).call(_callInput); ``` -Essa é a maneira que verificamos que o código [emite um evento corretamente](https://book.getfoundry.sh/cheatcodes/expect-emit) no Foundry. +É assim que verificamos se o código [emite um evento corretamente](https://getfoundry.sh/reference/cheatcodes/expect-emit/) na Foundry. ### O cliente {#the-client} -Uma coisa que você não obtém com testes no Solidity é código JavaScript, que você pode cortar e colar no seu próprio aplicativo. Para escrever este código, implantei WORM na [Optimism Goerli](https://community.optimism.io/docs/useful-tools/networks/#optimism-goerli), a nova rede de teste da [Optimism](https://www.optimism.io/). Ela está no endereço [`0xd34335b1d818cee54e3323d3246bd31d94e6a78a`](https://goerli-optimism.etherscan.io/address/0xd34335b1d818cee54e3323d3246bd31d94e6a78a). +Uma coisa que você não obtém com os testes do Solidity é o código JavaScript que você pode cortar e colar em seu próprio aplicativo. Para escrever esse código, implantei o WORM na [Optimism Goerli](https://community.optimism.io/docs/useful-tools/networks/#optimism-goerli), a nova [rede de teste](https://www.optimism.io/) da [Optimism](https://www.optimism.io/). Ele está no endereço [`0xd34335b1d818cee54e3323d3246bd31d94e6a78a`](https://goerli-optimism.etherscan.io/address/0xd34335b1d818cee54e3323d3246bd31d94e6a78a). -[Você pode ver o código JavaScript para o cliente aqui](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/javascript/index.js). Para usá-lo: +[Você pode ver o código JavaScript do cliente aqui](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/javascript/index.js). Para usá-lo: 1. Clone o repositório git: @@ -783,22 +780,22 @@ Uma coisa que você não obtém com testes no Solidity é código JavaScript, qu cp .env.example .env ``` -4. Edite `.env` para a sua configuração: +4. Edite o `.env` para sua configuração: - | Parâmetro | Valor | - | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | MNEMÔNICO | O mnemônico para uma conta que tem ETH suficiente para pagar por uma transação. [Você consegue ETH grátis para a rede Optimism Goerli aqui](https://optimismfaucet.xyz/). | - | OPTIMISM_GOERLI_URL | URL da Optimism Goerli. O endpoint público, `https://goerli.optimism.io`, tem taxa limitada mas suficiente para o que precisamos aqui | + | Parâmetro | Valor | + | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | MNEMÔNICO | O mnemônico de uma conta que tem ETH suficiente para pagar por uma transação. [Você pode obter ETH grátis para a rede Optimism Goerli aqui](https://optimismfaucet.xyz/). | + | OPTIMISM_GOERLI_URL | URL para a Optimism Goerli. O endpoint público, `https://goerli.optimism.io`, tem taxa limitada, mas é suficiente para o que precisamos aqui | -5. Rode `index.js`. +5. Execute o `index.js`. ```sh node index.js ``` - Primeiro, esse exemplo de aplicativo escreve uma entrada para WORM, exibindo o calldata e um link para a transação no Etherscan. Em seguida, ele lê novamente essa entrada e exibe a chave que usou e os valores na entrada (valor, bloco, número e autor). + Este aplicativo de exemplo primeiro escreve uma entrada no WORM, exibindo o calldata e um link para a transação no Etherscan. Em seguida, ele lê essa entrada e exibe a chave que usa e os valores na entrada (valor, número do bloco e autor). -A maioria dos clientes é Javascript Dapp normal. Então, novamente, passaremos apenas pelas partes interessantes. +A maior parte do cliente é JavaScript de Dapp normal. Então, novamente, vamos abordar apenas as partes interessantes. ```javascript . @@ -807,20 +804,20 @@ A maioria dos clientes é Javascript Dapp normal. Então, novamente, passaremos const main = async () => { const func = await worm.WRITE_ENTRY_CACHED() - // Need a new key every time + // Precisa de uma nova chave a cada vez const key = await worm.encodeVal(Number(new Date())) ``` -Um dado slot pode ser apenas escrito uma vez, então usamos o carimbo de data/hora para ter certeza de que não vamos reutilizar esses slots. +Um determinado slot só pode ser escrito uma vez, então usamos o carimbo de data/hora para garantir que não reutilizamos slots. ```javascript const val = await worm.encodeVal("0x600D") -// Write an entry +// Escreve uma entrada const calldata = func + key.slice(2) + val.slice(2) ``` -Ethers espera que o dado da chamada seja uma cadeia de caracteres hexadecimal, `0x` seguida de um número par de dígitos hexadecimais. Como `key` e `val` começam com `0x`, precisamos remover esses cabeçalhos. +O Ethers espera que os dados da chamada sejam uma string hexadecimal, `0x` seguido por um número par de dígitos hexadecimais. Como tanto `key` quanto `val` começam com `0x`, precisamos remover esses cabeçalhos. ```javascript const tx = await worm.populateTransaction.writeEntryCached() @@ -829,39 +826,42 @@ tx.data = calldata sentTx = await wallet.sendTransaction(tx) ``` -Como no código de teste Solidity, não podemos chamar uma função em cache normalmente. Ao invés disso, nós precisamos usar um mecanismo de nível mais baixo. +Assim como no código de teste do Solidity, não podemos chamar uma função em cache normalmente. Em vez disso, precisamos usar um mecanismo de nível inferior. ```javascript . . . - // Read the entry just written - const realKey = '0x' + key.slice(4) // remove the FF flag + // Lê a entrada que acabou de ser escrita + const realKey = '0x' + key.slice(4) // remove o sinalizador FF const entryRead = await worm.readEntry(realKey) . . . ``` -Para ler entradas, podemos usar o mecanismo normal. Não há necessidade de armazenar em cache parâmetros com funções `view`. +Para ler as entradas, podemos usar o mecanismo normal. Não há necessidade de usar cache de parâmetros com funções `view`. ## Conclusão {#conclusion} -O código neste artigo é uma prova de conceito, a finalidade é tornar a ideia fácil de entender. Para um sistema pronto para produção, recomenda-se implementar funcionalidades adicionais: +O código neste artigo é uma prova de conceito, o objetivo é tornar a ideia fácil de entender. Para um sistema pronto para produção, você pode querer implementar algumas funcionalidades adicionais: -- Manipular valores que não são `uint256`. Por exemplo, cadeias de caracteres. -- Em vez de um cache global, talvez ter um mapeamento entre usuários e caches. Usuários diferentes usam valores diferentes. -- Valores usados para endereços são distintos daqueles usados para outras finalidades. Pode fazer sentido ter um cache separado só para endereços. -- Atualmente, as chaves de cache estão em um algoritmo do tipo “o primeiro que chega tem a chave menor”. Os primeiros dezesseis valores podem ser enviados como um único byte. Os próximos 4.080 valores podem ser enviados como dois bytes. Os próximos milhões de valores são três bytes, etc. Um sistema de produção deveria manter contadores de uso nas entradas de cache e reorganizá-las para que os dezesseis _mais comuns_ valores sejam um byte, os próximos 4080 valores mais comuns sejam dois bytes, etc. +- Lidar com valores que não são `uint256`. Por exemplo, strings. +- Em vez de um cache global, talvez tenha um mapeamento entre usuários e caches. Diferentes usuários usam valores diferentes. +- Os valores usados para endereços são distintos daqueles usados para outros fins. Pode fazer sentido ter um cache separado apenas para endereços. +- Atualmente, as chaves do cache estão em um algoritmo "primeiro a chegar, chave menor". Os primeiros dezesseis valores podem ser enviados como um único byte. Os próximos 4080 valores podem ser enviados como dois bytes. Os próximos aproximadamente um milhão de valores são três bytes, etc. Um sistema de produção deve manter contadores de uso nas entradas de cache e reorganizá-los para que os dezesseis valores _mais comuns_ sejam de um byte, os próximos 4080 valores mais comuns de dois bytes, etc. No entanto, essa é uma operação potencialmente perigosa. Imagine a seguinte sequência de eventos: - 1. Noam Naive chama `encodeVal` para codificar o endereço para o qual ele quer enviar tokens. Este endereço é um dos primeiros usados na aplicação, então o valor codificado é 0x06. Trata-se de uma função `view`, e não uma transação, então ela diz respeito unicamente a Noam e ao nó que ele usa, e ninguém mais sabe disso + 1. Noam Naive chama `encodeVal` para codificar o endereço para o qual ele quer enviar tokens. Esse endereço é um dos primeiros usados no aplicativo, então o valor codificado é 0x06. Esta é uma função `view`, não uma transação, então é entre Noam e o nó que ele usa, e mais ninguém sabe sobre isso + + 2. Owen Owner executa a operação de reordenação do cache. Pouquíssimas pessoas realmente usam esse endereço, então ele agora é codificado como 0x201122. Um valor diferente, 1018, é atribuído a 0x06. + + 3. Noam Naive envia seus tokens para 0x06. Eles vão para o endereço `0x0000000000000000000000000de0b6b3a7640000`, e como ninguém conhece a chave privada para esse endereço, eles ficam presos lá. Noam _não está feliz_. - 2. Owen Owner executa a operação de reordenação de cache. Muito poucas pessoas realmente usam esse endereço, por isso, ele é agora codificado como 0x201122. Para um valor diferente, 1018, é atribuído 0x06. + Existem maneiras de resolver esse problema e o problema relacionado às transações que estão na mempool durante a reordenação do cache, mas você deve estar ciente disso. - 3. Noam Naive envia seus tokens para 0x06. Eles vão para o endereço `0x0000000000000000000000000de0b6b3a7640000`, e já que ninguém sabe a chave privada para esse endereço, eles ficam presos lá. Noam _não está contente_. +Demonstrei o cache aqui com a Optimism, porque sou um funcionário da Optimism e este é o rollup que conheço melhor. Mas deve funcionar com qualquer rollup que cobre um custo mínimo para processamento interno, de modo que, em comparação, escrever os dados da transação na L1 seja a maior despesa. - Existem maneiras de resolver esse problema, e o problema relacionado às transações que estão na mempool durante a reordenação do cache, mas você deve estar atento a isso. +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). -Demonstrei o processo de armazenamento em cache aqui com o Optimism, porque sou funcionário da Optimism e esse é o roll-up que conheço melhor. Mas deve funcionar com qualquer rollup que cobre um mínimo custo por processamento interno, de modo que em comparação com escrever os dados da transação na L1 é a maior despesa. diff --git a/public/content/translations/pt-br/developers/tutorials/app-plasma/index.md b/public/content/translations/pt-br/developers/tutorials/app-plasma/index.md new file mode 100644 index 00000000000..ec6068d089b --- /dev/null +++ b/public/content/translations/pt-br/developers/tutorials/app-plasma/index.md @@ -0,0 +1,1261 @@ +--- +title: "Escreva um plasma específico de aplicativo que preserva a privacidade" +description: "Neste tutorial, criamos um banco semissecreto para depósitos. O banco é um componente centralizado; ele conhece o saldo de cada usuário. No entanto, esta informação não é armazenada na cadeia. Em vez disso, o banco publica um hash do estado. Sempre que uma transação ocorre, o banco publica o novo hash, juntamente com uma prova de conhecimento zero de que tem uma transação assinada que altera o estado do hash para o novo. Após ler este tutorial, você entenderá não apenas como usar provas de conhecimento zero, mas também por que você as usa e como fazê-lo com segurança." +author: Ori Pomerantz +tags: + [ + "conhecimento zero", + "servidor", + "fora da cadeia", + "privacidade" + ] +skill: advanced +lang: pt-br +published: 2025-10-15 +--- + +## Introdução {#introduction} + +Em contraste com [rollups](/developers/docs/scaling/zk-rollups/), [plasmas](/developers/docs/scaling/plasma) usam a mainnet do Ethereum para integridade, mas não para disponibilidade. Neste artigo, escrevemos um aplicativo que se comporta como um plasma, com o Ethereum garantindo integridade (sem alterações não autorizadas), mas não disponibilidade (um componente centralizado pode cair e desativar todo o sistema). + +O aplicativo que escrevemos aqui é um banco que preserva a privacidade. Diferentes endereços têm contas com saldos, e eles podem enviar dinheiro (ETH) para outras contas. O banco publica hashes do estado (contas e seus saldos) e transações, mas mantém os saldos reais fora da cadeia, onde eles podem permanecer privados. + +## Design {#design} + +Este não é um sistema pronto para produção, mas uma ferramenta de ensino. Como tal, é escrito com várias suposições simplificadoras. + +- Conjunto de contas fixo. Há um número específico de contas, e cada conta pertence a um endereço predeterminado. Isso torna o sistema muito mais simples, porque é difícil lidar com estruturas de dados de tamanho variável em provas de conhecimento zero. Para um sistema pronto para produção, podemos usar a [raiz de Merkle](/developers/tutorials/merkle-proofs-for-offline-data-integrity/) como o hash de estado e fornecer provas de Merkle para os saldos necessários. + +- Armazenamento de memória. Em um sistema de produção, precisamos escrever todos os saldos das contas no disco para preservá-los em caso de reinicialização. Aqui, não há problema se a informação for simplesmente perdida. + +- Apenas transferências. Um sistema de produção exigiria uma maneira de depositar ativos no banco e retirá-los. Mas o objetivo aqui é apenas ilustrar o conceito, então este banco está limitado a transferências. + +### Provas de conhecimento zero {#zero-knowledge-proofs} + +Em um nível fundamental, uma prova de conhecimento zero mostra que o provador conhece alguns dados, _Dadosprivados_ de tal forma que existe uma relação _Relação_ entre alguns dados públicos, _Dadospúblicos_, e _Dadosprivados_. O verificador conhece a _Relação_ e os _Dadospúblicos_. + +Para preservar a privacidade, precisamos que os estados e as transações sejam privados. Mas para garantir a integridade, precisamos que o [hash criptográfico](https://en.wikipedia.org/wiki/Cryptographic_hash_function) dos estados seja público. Para provar às pessoas que enviam transações que essas transações realmente aconteceram, também precisamos publicar os hashes das transações. + +Na maioria dos casos, _Dadosprivados_ são a entrada para o programa de prova de conhecimento zero, e _Dadospúblicos_ são a saída. + +Estes campos em _Dadosprivados_: + +- _Estadon_, o estado antigo +- _Estadon+1_, o novo estado +- _Transação_, uma transação que muda do estado antigo para o novo. Essa transação precisa incluir estes campos: + - _Endereço de destino_ que recebe a transferência + - _Valor_ sendo transferido + - _Nonce_ para garantir que cada transação possa ser processada apenas uma vez. + O endereço de origem não precisa estar na transação, porque pode ser recuperado da assinatura. +- _Assinatura_, uma assinatura que está autorizada a realizar a transação. No nosso caso, o único endereço autorizado a realizar uma transação é o endereço de origem. Como nosso sistema de conhecimento zero funciona da maneira que funciona, também precisamos da chave pública da conta, além da assinatura do Ethereum. + +Estes são os campos em _Dadospúblicos_: + +- _Hash(Estadon)_ o hash do estado antigo +- _Hash(Estadon+1)_ o hash do novo estado +- _Hash(Transação)_ o hash da transação que muda o estado de _Estadon_ para _Estadon+1_. + +A relação verifica várias condições: + +- Os hashes públicos são de fato os hashes corretos para os campos privados. +- A transação, quando aplicada ao estado antigo, resulta no novo estado. +- A assinatura vem do endereço de origem da transação. + +Devido às propriedades das funções de hash criptográficas, provar essas condições é suficiente para garantir a integridade. + +### Estruturas de dados {#data-structures} + +A estrutura de dados primária é o estado mantido pelo servidor. Para cada conta, o servidor rastreia o saldo da conta e um [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce), usado para prevenir [ataques de repetição](https://en.wikipedia.org/wiki/Replay_attack). + +### Componentes {#components} + +Este sistema requer dois componentes: + +- O _servidor_ que recebe transações, as processa e publica os hashes na cadeia juntamente com as provas de conhecimento zero. +- Um _contrato inteligente_ que armazena os hashes e verifica as provas de conhecimento zero para garantir que as transições de estado sejam legítimas. + +### Fluxo de dados e controle {#flows} + +Estas são as maneiras como os vários componentes se comunicam para transferir de uma conta para outra. + +1. Um navegador da web envia uma transação assinada solicitando uma transferência da conta do signatário para uma conta diferente. + +2. O servidor verifica se a transação é válida: + + - O signatário tem uma conta no banco com saldo suficiente. + - O destinatário tem uma conta no banco. + +3. O servidor calcula o novo estado subtraindo o valor transferido do saldo do signatário e adicionando-o ao saldo do destinatário. + +4. O servidor calcula uma prova de conhecimento zero de que a mudança de estado é válida. + +5. O servidor envia ao Ethereum uma transação que inclui: + + - O novo hash de estado + - O hash da transação (para que o remetente da transação saiba que foi processada) + - A prova de conhecimento zero que comprova que a transição para o novo estado é válida + +6. O contrato inteligente verifica a prova de conhecimento zero. + +7. Se a prova de conhecimento zero for verificada, o contrato inteligente executa estas ações: + - Atualiza o hash do estado atual para o novo hash de estado + - Emite uma entrada de log com o novo hash de estado e o hash da transação + +### Ferramentas {#tools} + +Para o código do lado do cliente, vamos usar [Vite](https://vite.dev/), [React](https://react.dev/), [Viem](https://viem.sh/) e [Wagmi](https://wagmi.sh/). Estas são ferramentas padrão da indústria; se você não estiver familiarizado com elas, pode usar [este tutorial](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/). + +A maior parte do servidor é escrita em JavaScript usando [Node](https://nodejs.org/en). A parte de conhecimento zero é escrita em [Noir](https://noir-lang.org/). Precisamos da versão `1.0.0-beta.10`, então depois de [instalar o Noir conforme as instruções](https://noir-lang.org/docs/getting_started/quick_start), execute: + +``` +noirup -v 1.0.0-beta.10 +``` + +A blockchain que usamos é a `anvil`, uma blockchain de teste local que faz parte da [Foundry](https://getfoundry.sh/introduction/installation). + +## Implementação {#implementation} + +Como este é um sistema complexo, vamos implementá-lo em etapas. + +### Etapa 1 - Conhecimento zero manual {#stage-1} + +Na primeira etapa, assinaremos uma transação no navegador e, em seguida, forneceremos manualmente as informações para a prova de conhecimento zero. O código de conhecimento zero espera obter essa informação em `server/noir/Prover.toml` (documentado [aqui](https://noir-lang.org/docs/getting_started/project_breakdown#provertoml-1)). + +Para ver em ação: + +1. Certifique-se de ter o [Node](https://nodejs.org/en/download) e o [Noir](https://noir-lang.org/install) instalados. De preferência, instale-os em um sistema UNIX como macOS, Linux ou [WSL](https://learn.microsoft.com/en-us/windows/wsl/install). + +2. Baixe o código da etapa 1 e inicie o servidor da web para servir o código do cliente. + + ```sh + git clone https://github.com/qbzzt/250911-zk-bank.git -b 01-manual-zk + cd 250911-zk-bank + cd client + npm install + npm run dev + ``` + + A razão pela qual você precisa de um servidor web aqui é que, para evitar certos tipos de fraude, muitas carteiras (como a MetaMask) não aceitam arquivos servidos diretamente do disco + +3. Abra um navegador com uma carteira. + +4. Na carteira, insira uma nova frase secreta. Observe que isso excluirá sua frase secreta existente, então _certifique-se de ter um backup_. + + A frase secreta é `test test test test test test test test test test test junk`, a frase secreta de teste padrão para o anvil. + +5. Acesse [o código do lado do cliente](http://localhost:5173/). + +6. Conecte-se à carteira e selecione sua conta de destino e o valor. + +7. Clique em **Assinar** e assine a transação. + +8. Sob o título **Prover.toml**, você encontrará um texto. Substitua `server/noir/Prover.toml` por esse texto. + +9. Execute a prova de conhecimento zero. + + ```sh + cd ../server/noir + nargo execute + ``` + + A saída deve ser semelhante a + + ``` + ori@CryptoDocGuy:~/noir/250911-zk-bank/server/noir$ nargo execute + + [zkBank] Circuit witness successfully solved + [zkBank] Witness saved to target/zkBank.gz + [zkBank] Circuit output: (0x199aa62af8c1d562a6ec96e66347bf3240ab2afb5d022c895e6bf6a5e617167b, 0x0cfc0a67cb7308e4e9b254026b54204e34f6c8b041be207e64c5db77d95dd82d, 0x450cf9da6e180d6159290554ae3d8787, 0x6d8bc5a15b9037e52fb59b6b98722a85) + ``` + +10. Compare os dois últimos valores com o hash que você vê no navegador da web para ver se a mensagem foi transformada em hash corretamente. + +#### `server/noir/Prover.toml` {#server-noir-prover-toml} + +[Este arquivo](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/server/noir/Prover.toml) mostra o formato de informação esperado pelo Noir. + +```toml +message="send 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 500 finney (milliEth) 0 " +``` + +A mensagem está em formato de texto, o que facilita o entendimento do usuário (o que é necessário ao assinar) e a análise pelo código Noir. O valor é cotado em finneys para permitir transferências fracionárias, por um lado, e ser facilmente legível, por outro. O último número é o [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce). + +A string tem 100 caracteres de comprimento. As provas de conhecimento zero não lidam bem com dados de tamanho variável, por isso muitas vezes é necessário preencher os dados. + +```toml +pubKeyX=["0x83",...,"0x75"] +pubKeyY=["0x35",...,"0xa5"] +signature=["0xb1",...,"0x0d"] +``` + +Esses três parâmetros são matrizes de bytes de tamanho fixo. + +```toml +[[accounts]] +address="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +balance=100_000 +nonce=0 + +[[accounts]] +address="0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +balance=100_000 +nonce=0 +``` + +Esta é a maneira de especificar uma matriz de estruturas. Para cada entrada, especificamos o endereço, o saldo (em milliETH, também conhecido como [finney](https://cryptovalleyjournal.com/glossary/finney/)), e o próximo valor do nonce. + +#### `client/src/Transfer.tsx` {#client-src-transfer-tsx} + +[Este arquivo](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/client/src/Transfer.tsx) implementa o processamento do lado do cliente e gera o arquivo `server/noir/Prover.toml` (aquele que inclui os parâmetros de conhecimento zero). + +Aqui está a explicação das partes mais interessantes. + +```tsx +export default attrs => { +``` + +Esta função cria o componente React `Transfer`, que outros arquivos podem importar. + +```tsx + const accounts = [ + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", + "0x90F79bf6EB2c4f870365E785982E1f101E93b906", + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65", + ] +``` + +Estes são os endereços das contas, os endereços criados pelo `test ...` frase secreta `test junk`. Se você quiser usar seus próprios endereços, basta modificar esta definição. + +```tsx + const account = useAccount() + const wallet = createWalletClient({ + transport: custom(window.ethereum!) + }) +``` + +Estes [hooks da Wagmi](https://wagmi.sh/react/api/hooks) nos permitem acessar a biblioteca [viem](https://viem.sh/) e a carteira. + +```tsx + const message = `send ${toAccount} ${ethAmount*1000} finney (milliEth) ${nonce}`.padEnd(100, " ") +``` + +Esta é a mensagem, preenchida com espaços. Toda vez que uma das variáveis [`useState`](https://react.dev/reference/react/useState) muda, o componente é redesenhado e a `message` é atualizada. + +```tsx + const sign = async () => { +``` + +Esta função é chamada quando o usuário clica no botão **Assinar**. A mensagem é atualizada automaticamente, mas a assinatura requer a aprovação do usuário na carteira, e não queremos pedi-la a menos que seja necessário. + +```tsx + const signature = await wallet.signMessage({ + account: fromAccount, + message, + }) +``` + +Peça à carteira para [assinar a mensagem](https://viem.sh/docs/accounts/local/signMessage). + +```tsx + const hash = hashMessage(message) +``` + +Obtenha o hash da mensagem. É útil fornecê-lo ao usuário para depuração (do código Noir). + +```tsx + const pubKey = await recoverPublicKey({ + hash, + signature + }) +``` + +[Obtenha a chave pública](https://viem.sh/docs/utilities/recoverPublicKey). Isso é necessário para a função `ecrecover` do [Noir](https://github.com/colinnielsen/ecrecover-noir). + +```tsx + setSignature(signature) + setHash(hash) + setPubKey(pubKey) +``` + +Defina as variáveis de estado. Fazer isso redesenha o componente (após a saída da função `sign`) e mostra ao usuário os valores atualizados. + +```tsx + let proverToml = ` +``` + +O texto para `Prover.toml`. + +```tsx +message="${message}" + +pubKeyX=${hexToArray(pubKey.slice(4,4+2*32))} +pubKeyY=${hexToArray(pubKey.slice(4+2*32))} +``` + +Viem nos fornece a chave pública como uma string hexadecimal de 65 bytes. O primeiro byte é `0x04`, um marcador de versão. Isso é seguido por 32 bytes para o `x` da chave pública e, em seguida, 32 bytes para o `y` da chave pública. + +No entanto, o Noir espera obter essa informação como duas matrizes de bytes, uma para `x` e outra para `y`. É mais fácil analisá-lo aqui no cliente do que como parte da prova de conhecimento zero. + +Observe que esta é uma boa prática em conhecimento zero em geral. O código dentro de uma prova de conhecimento zero é caro, então qualquer processamento que possa ser feito fora da prova de conhecimento zero _deve_ ser feito fora da prova de conhecimento zero. + +```tsx +signature=${hexToArray(signature.slice(2,-2))} +``` + +A assinatura também é fornecida como uma string hexadecimal de 65 bytes. No entanto, o último byte só é necessário para recuperar a chave pública. Como a chave pública já será fornecida ao código Noir, não precisamos dela para verificar a assinatura, e o código Noir não a exige. + +```tsx +${accounts.map(accountInProverToml).reduce((a,b) => a+b, "")} +` +``` + +Forneça as contas. + +```tsx + setProverToml(proverToml) + } + + return ( + <> +

Transferência

+``` + +Este é o formato HTML (mais precisamente, [JSX](https://react.dev/learn/writing-markup-with-jsx)) do componente. + +#### `server/noir/src/main.nr` {#server-noir-src-main-nr} + +[Este arquivo](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/server/noir/src/main.nr) é o código de conhecimento zero real. + +``` +use std::hash::pedersen_hash; +``` + +O [hash de Pedersen](https://rya-sge.github.io/access-denied/2024/05/07/pedersen-hash-function/) é fornecido com a [biblioteca padrão do Noir](https://noir-lang.org/docs/noir/standard_library/cryptographic_primitives/hashes#pedersen_hash). As provas de conhecimento zero comumente usam esta função de hash. É muito mais fácil de calcular dentro de [circuitos aritméticos](https://rareskills.io/post/arithmetic-circuit) em comparação com as funções de hash padrão. + +``` +use keccak256::keccak256; +use dep::ecrecover; +``` + +Estas duas funções são bibliotecas externas, definidas em [`Nargo.toml`](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/server/noir/Nargo.toml). Elas são precisamente o que seus nomes indicam, uma função que calcula o [hash keccak256](https://emn178.github.io/online-tools/keccak_256.html) e uma função que verifica assinaturas do Ethereum e recupera o endereço Ethereum do signatário. + +``` +global ACCOUNT_NUMBER : u32 = 5; +``` + +Noir é inspirado em [Rust](https://www.rust-lang.org/). As variáveis, por padrão, são constantes. É assim que definimos constantes de configuração globais. Especificamente, `ACCOUNT_NUMBER` é o número de contas que armazenamos. + +Tipos de dados nomeados `u` são esse número de bits, sem sinal. Os únicos tipos suportados são `u8`, `u16`, `u32`, `u64` e `u128`. + +``` +global FLAT_ACCOUNT_FIELDS : u32 = 2; +``` + +Essa variável é usada para o hash de Pedersen das contas, como explicado abaixo. + +``` +global MESSAGE_LENGTH : u32 = 100; +``` + +Como explicado acima, o comprimento da mensagem é fixo. Ele é especificado aqui. + +``` +global ASCII_MESSAGE_LENGTH : [u8; 3] = [0x31, 0x30, 0x30]; +global HASH_BUFFER_SIZE : u32 = 26+3+MESSAGE_LENGTH; +``` + +As [assinaturas EIP-191](https://eips.ethereum.org/EIPS/eip-191) requerem um buffer com um prefixo de 26 bytes, seguido pelo comprimento da mensagem em ASCII e, finalmente, a própria mensagem. + +``` +struct Account { + balance: u128, + address: Field, + nonce: u32, +} +``` + +A informação que armazenamos sobre uma conta. [`Field`](https://noir-lang.org/docs/noir/concepts/data_types/fields) é um número, normalmente até 253 bits, que pode ser usado diretamente no [circuito aritmético](https://rareskills.io/post/arithmetic-circuit) que implementa a prova de conhecimento zero. Aqui usamos o `Field` para armazenar um endereço Ethereum de 160 bits. + +``` +struct TransferTxn { + from: Field, + to: Field, + amount: u128, + nonce: u32 +} +``` + +A informação que armazenamos para uma transação de transferência. + +``` +fn flatten_account(account: Account) -> [Field; FLAT_ACCOUNT_FIELDS] { +``` + +Uma definição de função. O parâmetro é a informação da `Conta`. O resultado é uma matriz de variáveis `Field`, cujo comprimento é `FLAT_ACCOUNT_FIELDS` + +``` + let flat = [ + account.address, + ((account.balance << 32) + account.nonce.into()).into(), + ]; +``` + +O primeiro valor na matriz é o endereço da conta. O segundo inclui tanto o saldo quanto o nonce. As chamadas `.into()` mudam um número para o tipo de dados que ele precisa ser. `account.nonce` é um valor `u32`, mas para adicioná-lo a `account.balance << 32`, um valor `u128`, ele precisa ser um `u128`. Esse é o primeiro `.into()`. O segundo converte o resultado `u128` em um `Field` para que ele se encaixe na matriz. + +``` + flat +} +``` + +No Noir, as funções só podem retornar um valor no final (não há retorno antecipado). Para especificar o valor de retorno, você o avalia pouco antes do colchete de fechamento da função. + +``` +fn flatten_accounts(accounts: [Account; ACCOUNT_NUMBER]) -> [Field; FLAT_ACCOUNT_FIELDS*ACCOUNT_NUMBER] { +``` + +Esta função transforma a matriz de contas em uma matriz `Field`, que pode ser usada como entrada para um Hash de Petersen. + +``` + let mut flat: [Field; FLAT_ACCOUNT_FIELDS*ACCOUNT_NUMBER] = [0; FLAT_ACCOUNT_FIELDS*ACCOUNT_NUMBER]; +``` + +Esta é a forma de especificar uma variável mutável, ou seja, _não_ uma constante. As variáveis no Noir devem sempre ter um valor, então inicializamos esta variável com todos os zeros. + +``` + for i in 0..ACCOUNT_NUMBER { +``` + +Este é um loop `for`. Note que os limites são constantes. Os loops do Noir precisam ter seus limites conhecidos em tempo de compilação. A razão é que os circuitos aritméticos não suportam o controle de fluxo. Ao processar um loop `for`, o compilador simplesmente coloca o código dentro dele várias vezes, uma para cada iteração. + +``` + let fields = flatten_account(accounts[i]); + for j in 0..FLAT_ACCOUNT_FIELDS { + flat[i*FLAT_ACCOUNT_FIELDS + j] = fields[j]; + } + } + + flat +} + +fn hash_accounts(accounts: [Account; ACCOUNT_NUMBER]) -> Field { + pedersen_hash(flatten_accounts(accounts)) +} +``` + +Finalmente, chegamos à função que gera o hash da matriz de contas. + +``` +fn find_account(accounts: [Account; ACCOUNT_NUMBER], address: Field) -> u32 { + let mut account : u32 = ACCOUNT_NUMBER; + + for i in 0..ACCOUNT_NUMBER { + if accounts[i].address == address { + account = i; + } + } +``` + +Essa função encontra a conta com um endereço específico. Esta função seria terrivelmente ineficiente em código padrão porque itera sobre todas as contas, mesmo depois de ter encontrado o endereço. + +No entanto, em provas de conhecimento zero, não há controle de fluxo. Se precisarmos verificar uma condição, teremos que verificá-la todas as vezes. + +Algo semelhante acontece com as instruções `if`. A instrução `if` no loop acima é traduzida para estas declarações matemáticas. + +_resultadocondição = contas[i].endereço == endereço_ // um se forem iguais, zero caso contrário + +_contanova = resultadocondição\*i + (1-resultadocondição)\*contaantiga_ + +```rust + assert (account < ACCOUNT_NUMBER, f"{address} does not have an account"); + + account +} +``` + +A função [`assert`](https://noir-lang.org/docs/dev/noir/concepts/assert) faz com que a prova de conhecimento zero falhe se a asserção for falsa. Neste caso, se não conseguirmos encontrar uma conta com o endereço relevante. Para relatar o endereço, usamos uma [string de formatação](https://noir-lang.org/docs/noir/concepts/data_types/strings#format-strings). + +```rust +fn apply_transfer_txn(accounts: [Account; ACCOUNT_NUMBER], txn: TransferTxn) -> [Account; ACCOUNT_NUMBER] { +``` + +Esta função aplica uma transação de transferência e retorna a nova matriz de contas. + +```rust + let from = find_account(accounts, txn.from); + let to = find_account(accounts, txn.to); + + let (txnFrom, txnAmount, txnNonce, accountNonce) = + (txn.from, txn.amount, txn.nonce, accounts[from].nonce); +``` + +Não podemos acessar elementos da estrutura dentro de uma string de formato no Noir, então criamos uma cópia utilizável. + +```rust + assert (accounts[from].balance >= txn.amount, + f"{txnFrom} does not have {txnAmount} finney"); + + assert (accounts[from].nonce == txn.nonce, + f"Transaction has nonce {txnNonce}, but the account is expected to use {accountNonce}"); +``` + +Estas são duas condições que podem tornar uma transação inválida. + +```rust + let mut newAccounts = accounts; + + newAccounts[from].balance -= txn.amount; + newAccounts[from].nonce += 1; + newAccounts[to].balance += txn.amount; + + newAccounts +} +``` + +Crie a nova matriz de contas e, em seguida, retorne-a. + +```rust +fn readAddress(messageBytes: [u8; MESSAGE_LENGTH]) -> Field +``` + +Esta função lê o endereço da mensagem. + +```rust +{ + let mut result : Field = 0; + + for i in 7..47 { +``` + +O endereço tem sempre 20 bytes (ou seja, 40 dígitos hexadecimais) de comprimento e começa no caractere #7. + +```rust + result *= 0x10; + if messageBytes[i] >= 48 & messageBytes[i] <= 57 { // 0-9 + result += (messageBytes[i]-48).into(); + } + if messageBytes[i] >= 65 & messageBytes[i] <= 70 { // A-F + result += (messageBytes[i]-65+10).into() + } + if messageBytes[i] >= 97 & messageBytes[i] <= 102 { // a-f + result += (messageBytes[i]-97+10).into() + } + } + + result +} + +fn readAmountAndNonce(messageBytes: [u8; MESSAGE_LENGTH]) -> (u128, u32) +``` + +Leia o valor e o nonce da mensagem. + +```rust +{ + let mut amount : u128 = 0; + let mut nonce: u32 = 0; + let mut stillReadingAmount: bool = true; + let mut lookingForNonce: bool = false; + let mut stillReadingNonce: bool = false; +``` + +Na mensagem, o primeiro número após o endereço é a quantidade de finney (também conhecido como milésimo de um ETH) a ser transferido. O segundo número é o nonce. Qualquer texto entre eles é ignorado. + +```rust + for i in 48..MESSAGE_LENGTH { + if messageBytes[i] >= 48 & messageBytes[i] <= 57 { // 0-9 + let digit = (messageBytes[i]-48); + + if stillReadingAmount { + amount = amount*10 + digit.into(); + } + + if lookingForNonce { // We just found it + stillReadingNonce = true; + lookingForNonce = false; + } + + if stillReadingNonce { + nonce = nonce*10 + digit.into(); + } + } else { + if stillReadingAmount { + stillReadingAmount = false; + lookingForNonce = true; + } + if stillReadingNonce { + stillReadingNonce = false; + } + } + } + + (amount, nonce) +} +``` + +Retornar uma [tupla](https://noir-lang.org/docs/noir/concepts/data_types/tuples) é a maneira Noir de retornar múltiplos valores de uma função. + +```rust +fn readTransferTxn(message: str) -> TransferTxn +{ + let mut txn: TransferTxn = TransferTxn { from: 0, to: 0, amount:0, nonce:0 }; + let messageBytes = message.as_bytes(); + + txn.to = readAddress(messageBytes); + let (amount, nonce) = readAmountAndNonce(messageBytes); + txn.amount = amount; + txn.nonce = nonce; + + txn +} +``` + +Esta função converte a mensagem em bytes e, em seguida, converte os valores em um `TransferTxn`. + +```rust +// O equivalente a hashMessage do Viem +// https://viem.sh/docs/utilities/hashMessage#hashmessage +fn hashMessage(message: str) -> [u8;32] { +``` + +Conseguimos usar o Hash de Pedersen para as contas porque elas só são hasheadas dentro da prova de conhecimento zero. No entanto, neste código, precisamos verificar a assinatura da mensagem, que é gerada pelo navegador. Para isso, precisamos seguir o formato de assinatura do Ethereum no [EIP 191](https://eips.ethereum.org/EIPS/eip-191). Isso significa que precisamos criar um buffer combinado com um prefixo padrão, o comprimento da mensagem em ASCII e a própria mensagem, e usar o keccak256 padrão do Ethereum para gerar o hash. + +```rust + // ASCII prefix + let prefix_bytes = [ + 0x19, // \x19 + 0x45, // 'E' + 0x74, // 't' + 0x68, // 'h' + 0x65, // 'e' + 0x72, // 'r' + 0x65, // 'e' + 0x75, // 'u' + 0x6D, // 'm' + 0x20, // ' ' + 0x53, // 'S' + 0x69, // 'i' + 0x67, // 'g' + 0x6E, // 'n' + 0x65, // 'e' + 0x64, // 'd' + 0x20, // ' ' + 0x4D, // 'M' + 0x65, // 'e' + 0x73, // 's' + 0x73, // 's' + 0x61, // 'a' + 0x67, // 'g' + 0x65, // 'e' + 0x3A, // ':' + 0x0A // '\n' + ]; +``` + +Para evitar casos em que um aplicativo peça ao usuário para assinar uma mensagem que possa ser usada como uma transação ou para algum outro propósito, o EIP 191 especifica que todas as mensagens assinadas comecem com o caractere 0x19 (não é um caractere ASCII válido) seguido por `Ethereum Signed Message:` e uma nova linha. + +```rust + let mut buffer: [u8; HASH_BUFFER_SIZE] = [0u8; HASH_BUFFER_SIZE]; + for i in 0..26 { + buffer[i] = prefix_bytes[i]; + } + + let messageBytes : [u8; MESSAGE_LENGTH] = message.as_bytes(); + + if MESSAGE_LENGTH <= 9 { + for i in 0..1 { + buffer[i+26] = ASCII_MESSAGE_LENGTH[i]; + } + + for i in 0..MESSAGE_LENGTH { + buffer[i+26+1] = messageBytes[i]; + } + } + + if MESSAGE_LENGTH >= 10 & MESSAGE_LENGTH <= 99 { + for i in 0..2 { + buffer[i+26] = ASCII_MESSAGE_LENGTH[i]; + } + + for i in 0..MESSAGE_LENGTH { + buffer[i+26+2] = messageBytes[i]; + } + } + + if MESSAGE_LENGTH >= 100 { + for i in 0..3 { + buffer[i+26] = ASCII_MESSAGE_LENGTH[i]; + } + + for i in 0..MESSAGE_LENGTH { + buffer[i+26+3] = messageBytes[i]; + } + } + + assert(MESSAGE_LENGTH < 1000, "Messages whose length is over three digits are not supported"); +``` + +Lida com comprimentos de mensagem de até 999 e falha se for maior. Adicionei este código, embora o comprimento da mensagem seja uma constante, porque torna mais fácil alterá-lo. Em um sistema de produção, você provavelmente apenas assumiria que `MESSAGE_LENGTH` não muda para obter um melhor desempenho. + +```rust + keccak256::keccak256(buffer, HASH_BUFFER_SIZE) +} +``` + +Use a função `keccak256` padrão do Ethereum. + +```rust +fn signatureToAddressAndHash( + message: str, + pubKeyX: [u8; 32], + pubKeyY: [u8; 32], + signature: [u8; 64] + ) -> (Field, Field, Field) // address, first 16 bytes of hash, last 16 bytes of hash +{ +``` + +Esta função verifica a assinatura, o que requer o hash da mensagem. Em seguida, nos fornece o endereço que a assinou e o hash da mensagem. O hash da mensagem é fornecido em dois valores de `Field` porque eles são mais fáceis de usar no resto do programa do que uma matriz de bytes. + +Precisamos usar dois valores `Field` porque os cálculos de campo são feitos [módulo](https://en.wikipedia.org/wiki/Modulo) um número grande, mas esse número é tipicamente menor que 256 bits (caso contrário, seria difícil realizar esses cálculos no EVM). + +```rust + let hash = hashMessage(message); + + let mut (hash1, hash2) = (0,0); + + for i in 0..16 { + hash1 = hash1*256 + hash[31-i].into(); + hash2 = hash2*256 + hash[15-i].into(); + } +``` + +Especifique `hash1` e `hash2` como variáveis mutáveis e escreva o hash nelas byte a byte. + +```rust + ( + ecrecover::ecrecover(pubKeyX, pubKeyY, signature, hash), +``` + +Isto é semelhante ao `ecrecover` do [Solidity](https://docs.soliditylang.org/en/v0.8.30/cheatsheet.html#mathematical-and-cryptographic-functions), com duas diferenças importantes: + +- Se a assinatura não for válida, a chamada falha em um `assert` e o programa é abortado. +- Embora a chave pública possa ser recuperada da assinatura e do hash, este é um processamento que pode ser feito externamente e, portanto, não vale a pena fazer dentro da prova de conhecimento zero. Se alguém tentar nos enganar aqui, a verificação da assinatura falhará. + +```rust + hash1, + hash2 + ) +} + +fn main( + accounts: [Account; ACCOUNT_NUMBER], + message: str, + pubKeyX: [u8; 32], + pubKeyY: [u8; 32], + signature: [u8; 64], + ) -> pub ( + Field, // Hash of old accounts array + Field, // Hash of new accounts array + Field, // First 16 bytes of message hash + Field, // Last 16 bytes of message hash + ) +``` + +Finalmente, chegamos à função `main`. Precisamos provar que temos uma transação que altera validamente o hash das contas do valor antigo para o novo. Também precisamos provar que tem este hash de transação específico para que a pessoa que a enviou saiba que a sua transação foi processada. + +```rust +{ + let mut txn = readTransferTxn(message); +``` + +Precisamos que `txn` seja mutável porque não lemos o endereço de origem da mensagem, nós o lemos da assinatura. + +```rust + let (fromAddress, txnHash1, txnHash2) = signatureToAddressAndHash( + message, + pubKeyX, + pubKeyY, + signature); + + txn.from = fromAddress; + + let newAccounts = apply_transfer_txn(accounts, txn); + + ( + hash_accounts(accounts), + hash_accounts(newAccounts), + txnHash1, + txnHash2 + ) +} +``` + +### Estágio 2 - Adicionando um servidor {#stage-2} + +No segundo estágio, adicionamos um servidor que recebe e implementa transações de transferência do navegador. + +Para ver em ação: + +1. Pare o Vite se ele estiver em execução. + +2. Baixe o branch que inclui o servidor e certifique-se de que você tem todos os módulos necessários. + + ```sh + git checkout 02-add-server + cd client + npm install + cd ../server + npm install + ``` + + Não há necessidade de compilar o código Noir, é o mesmo código que você usou na etapa 1. + +3. Inicie o servidor. + + ```sh + npm run start + ``` + +4. Em uma janela de linha de comando separada, execute o Vite para servir o código do navegador. + + ```sh + cd client + npm run dev + ``` + +5. Acesse o código do cliente em [http://localhost:5173](http://localhost:5173) + +6. Antes de emitir uma transação, você precisa saber o nonce, bem como o valor que pode enviar. Para obter esta informação, clique em **Atualizar dados da conta** e assine a mensagem. + + Temos um dilema aqui. Por um lado, não queremos assinar uma mensagem que pode ser reutilizada (um [ataque de repetição](https://en.wikipedia.org/wiki/Replay_attack)), e é por isso que queremos um nonce em primeiro lugar. No entanto, ainda não temos um nonce. A solução é escolher um nonce que possa ser usado apenas uma vez e que já tenhamos em ambos os lados, como a hora atual. + + O problema com esta solução é que o tempo pode não estar perfeitamente sincronizado. Então, em vez disso, assinamos um valor que muda a cada minuto. Isso significa que nossa janela de vulnerabilidade a ataques de repetição é de no máximo um minuto. Considerando que em produção a solicitação assinada será protegida por TLS, e que o outro lado do túnel - o servidor - já pode divulgar o saldo e o nonce (ele precisa conhecê-los para funcionar), este é um risco aceitável. + +7. Uma vez que o navegador recebe de volta o saldo e o nonce, ele mostra o formulário de transferência. Selecione o endereço de destino e o valor e clique em **Transferir**. Assine este pedido. + +8. Para ver a transferência, **Atualize os dados da conta** ou olhe na janela onde você executa o servidor. O servidor registra o estado sempre que ele muda. + + ``` + ori@CryptoDocGuy:~/x/250911-zk-bank/server$ npm run start + + > server@1.0.0 start + > node --experimental-json-modules index.mjs + + Listening on port 3000 + Txn send 0x90F79bf6EB2c4f870365E785982E1f101E93b906 36000 finney (milliEth) 0 processed + New state: + 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 has 64000 (1) + 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 has 100000 (0) + 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC has 100000 (0) + 0x90F79bf6EB2c4f870365E785982E1f101E93b906 has 136000 (0) + 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 has 100000 (0) + Txn send 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 7200 finney (milliEth) 1 processed + New state: + 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 has 56800 (2) + 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 has 107200 (0) + 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC has 100000 (0) + 0x90F79bf6EB2c4f870365E785982E1f101E93b906 has 136000 (0) + 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 has 100000 (0) + Txn send 0x90F79bf6EB2c4f870365E785982E1f101E93b906 3000 finney (milliEth) 2 processed + New state: + 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 has 53800 (3) + 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 has 107200 (0) + 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC has 100000 (0) + 0x90F79bf6EB2c4f870365E785982E1f101E93b906 has 139000 (0) + 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 has 100000 (0) + ``` + +#### `server/index.mjs` {#server-index-mjs-1} + +[Este arquivo](https://github.com/qbzzt/250911-zk-bank/blob/02-add-server/server/index.mjs) contém o processo do servidor e interage com o código Noir em [`main.nr`](https://github.com/qbzzt/250911-zk-bank/blob/02-add-server/server/noir/src/main.nr). Aqui está uma explicação das partes interessantes. + +```js +import { Noir } from '@noir-lang/noir_js' +``` + +A biblioteca [noir.js](https://www.npmjs.com/package/@noir-lang/noir_js) faz a interface entre o código JavaScript e o código Noir. + +```js +const circuit = JSON.parse(await fs.readFile("./noir/target/zkBank.json")) +const noir = new Noir(circuit) +``` + +Carregue o circuito aritmético - o programa Noir compilado que criamos na etapa anterior - e prepare-se para executá-lo. + +```js +// Só fornecemos informações da conta em resposta a uma solicitação assinada +const accountInformation = async signature => { + const fromAddress = await recoverAddress({ + hash: hashMessage("Get account data " + Math.floor((new Date().getTime())/60000)), + signature + }) +``` + +Para fornecer informações da conta, só precisamos da assinatura. A razão é que já sabemos qual será a mensagem e, portanto, o hash da mensagem. + +```js +const processMessage = async (message, signature) => { +``` + +Processe uma mensagem e execute a transação que ela codifica. + +```js + // Obtenha a chave pública + const pubKey = await recoverPublicKey({ + hash, + signature + }) +``` + +Agora que executamos o JavaScript no servidor, podemos recuperar a chave pública lá, em vez de no cliente. + +```js + let noirResult + try { + noirResult = await noir.execute({ + message, + signature: signature.slice(2,-2).match(/.{2}/g).map(x => `0x${x}`), + pubKeyX, + pubKeyY, + accounts: Accounts + }) +``` + +`noir.execute` executa o programa Noir. Os parâmetros são equivalentes aos fornecidos em [`Prover.toml`](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/server/noir/Prover.toml). Note que valores longos são fornecidos como um array de strings hexadecimais (`["0x60", "0xA7"]`), e não como um valor hexadecimal único (`0x60A7`), como faz o Viem. + +```js + } catch (err) { + console.log(`Noir error: ${err}`) + throw Error("Invalid transaction, not processed") + } +``` + +Se houver um erro, capture-o e, em seguida, retransmita uma versão simplificada para o cliente. + +```js + Accounts[fromAccountNumber].nonce++ + Accounts[fromAccountNumber].balance -= amount + Accounts[toAccountNumber].balance += amount +``` + +Aplique a transação. Já fizemos isso no código Noir, mas é mais fácil fazer de novo aqui do que extrair o resultado de lá. + +```js +let Accounts = [ + { + address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + balance: 5000, + nonce: 0, + }, +``` + +A estrutura `Contas` inicial. + +### Estágio 3 - Contratos inteligentes Ethereum {#stage-3} + +1. Pare os processos do servidor e do cliente. + +2. Baixe o branch com os contratos inteligentes e certifique-se de que você tem todos os módulos necessários. + + ```sh + git checkout 03-smart-contracts + cd client + npm install + cd ../server + npm install + ``` + +3. Execute `anvil` em uma janela de linha de comando separada. + +4. Gere a chave de verificação e o verificador solidity, em seguida, copie o código do verificador para o projeto Solidity. + + ```sh + cd noir + bb write_vk -b ./target/zkBank.json -o ./target --oracle_hash keccak + bb write_solidity_verifier -k ./target/vk -o ./target/Verifier.sol + cp target/Verifier.sol ../../smart-contracts/src + ``` + +5. Vá para os contratos inteligentes e defina as variáveis de ambiente para usar a blockchain `anvil`. + + ```sh + cd ../../smart-contracts + export ETH_RPC_URL=http://localhost:8545 + ETH_PRIVATE_KEY=ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ``` + +6. Implante `Verifier.sol` e armazene o endereço em uma variável de ambiente. + + ```sh + VERIFIER_ADDRESS=`forge create src/Verifier.sol:HonkVerifier --private-key $ETH_PRIVATE_KEY --optimize --broadcast | awk '/Deployed to:/ {print $3}'` + echo $VERIFIER_ADDRESS + ``` + +7. Implante o contrato `ZkBank`. + + ```sh + ZKBANK_ADDRESS=`forge create ZkBank --private-key $ETH_PRIVATE_KEY --broadcast --constructor-args $VERIFIER_ADDRESS 0x199aa62af8c1d562a6ec96e66347bf3240ab2afb5d022c895e6bf6a5e617167b | awk '/Deployed to:/ {print $3}'` + echo $ZKBANK_ADDRESS + ``` + + O valor `0x199..67b` é o hash Pederson do estado inicial de `Contas`. Se você modificar este estado inicial em `server/index.mjs`, você pode executar uma transação para ver o hash inicial relatado pela prova de conhecimento zero. + +8. Execute o servidor. + + ```sh + cd ../server + npm run start + ``` + +9. Execute o cliente em uma janela de linha de comando diferente. + + ```sh + cd client + npm run dev + ``` + +10. Execute algumas transações. + +11. Para verificar se o estado mudou na cadeia, reinicie o processo do servidor. Veja que o `ZkBank` não aceita mais transações, porque o valor original do hash nas transações difere do valor do hash armazenado na cadeia. + + Este é o tipo de erro esperado. + + ``` + ori@CryptoDocGuy:~/x/250911-zk-bank/server$ npm run start + + > server@1.0.0 start + > node --experimental-json-modules index.mjs + + Listening on port 3000 + Verification error: ContractFunctionExecutionError: The contract function "processTransaction" reverted with the following reason: + Wrong old state hash + + Contract Call: + address: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 + function: processTransaction(bytes _proof, bytes32[] _publicInputs) + args: (0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf00000000000000000000000000000000000000000000000b75c020998797da7800000000000000000000000000000000000000000000000 + ``` + +#### `server/index.mjs` {#server-index-mjs-2} + +As mudanças neste arquivo se relacionam principalmente com a criação da prova real e seu envio na cadeia. + +```js +import { exec } from 'child_process' +import util from 'util' + +const execPromise = util.promisify(exec) +``` + +Precisamos usar [o pacote Barretenberg](https://github.com/AztecProtocol/aztec-packages/tree/next/barretenberg) para criar a prova real a ser enviada na cadeia. Podemos usar este pacote executando a interface de linha de comando (`bb`) ou usando a [biblioteca JavaScript, `bb.js`](https://www.npmjs.com/package/@aztec/bb.js). A biblioteca JavaScript é muito mais lenta do que executar o código nativamente, então usamos [`exec`](https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback) aqui para usar a linha de comando. + +Note que se você decidir usar `bb.js`, você precisa usar uma versão que seja compatível com a versão do Noir que você está usando. No momento da escrita, a versão atual do Noir (1.0.0-beta.11) usa a versão 0.87 do `bb.js`. + +```js +const zkBankAddress = process.env.ZKBANK_ADDRESS || "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" +``` + +O endereço aqui é o que você obtém quando começa com um `anvil` limpo e segue as instruções acima. + +```js +const walletClient = createWalletClient({ + chain: anvil, + transport: http(), + account: privateKeyToAccount("0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6") +}) +``` + +Esta chave privada é uma das contas pré-financiadas padrão em `anvil`. + +```js +const generateProof = async (witness, fileID) => { +``` + +Gere uma prova usando o executável `bb`. + +```js + const fname = `witness-${fileID}.gz` + await fs.writeFile(fname, witness) +``` + +Escreva a testemunha em um arquivo. + +```js + await execPromise(`bb prove -b ./noir/target/zkBank.json -w ${fname} -o ${fileID} --oracle_hash keccak --output_format fields`) +``` + +Realmente crie a prova. Este passo também cria um arquivo com as variáveis públicas, mas não precisamos disso. Já obtivemos essas variáveis de `noir.execute`. + +```js + const proof = "0x" + JSON.parse(await fs.readFile(`./${fileID}/proof_fields.json`)).reduce((a,b) => a+b, "").replace(/0x/g, "") +``` + +A prova é um array JSON de valores `Field`, cada um representado como um valor hexadecimal. No entanto, precisamos enviá-lo na transação como um único valor de `bytes`, que o Viem representa por uma grande string hexadecimal. Aqui, alteramos o formato concatenando todos os valores, removendo todos os `0x`'s e, em seguida, adicionando um no final. + +```js + await execPromise(`rm -r ${fname} ${fileID}`) + + return proof +} +``` + +Limpe e retorne a prova. + +```js +const processMessage = async (message, signature) => { + . + . + . + + const publicFields = noirResult.returnValue.map(x=>'0x' + x.slice(2).padStart(64, "0")) +``` + +Os campos públicos precisam ser uma matriz de valores de 32 bytes. No entanto, como precisávamos dividir o hash da transação entre dois valores de `Field`, ele aparece como um valor de 16 bytes. Aqui adicionamos zeros para que Viem entenda que na verdade são 32 bytes. + +```js + const proof = await generateProof(noirResult.witness, `${fromAddress}-${nonce}`) +``` + +Cada endereço usa cada nonce apenas uma vez, para que possamos usar uma combinação de `fromAddress` e `nonce` como um identificador único para o arquivo testemunha e o diretório de saída. + +```js + try { + await zkBank.write.processTransaction([ + proof, publicFields]) + } catch (err) { + console.log(`Verification error: ${err}`) + throw Error("Can't verify the transaction onchain") + } + . + . + . +} +``` + +Envie a transação para a cadeia. + +#### `smart-contracts/src/ZkBank.sol` {#smart-contracts-src-zkbank-sol} + +Este é o código na cadeia que recebe a transação. + +```solidity +// SPDX-License-Identifier: MIT + +pragma solidity >=0.8.21; + +import {HonkVerifier} from "./Verifier.sol"; + +contract ZkBank { + HonkVerifier immutable myVerifier; + bytes32 currentStateHash; + + constructor(address _verifierAddress, bytes32 _initialStateHash) { + currentStateHash = _initialStateHash; + myVerifier = HonkVerifier(_verifierAddress); + } +``` + +O código na cadeia precisa manter o controle de duas variáveis: o verificador (um contrato separado que é criado por `nargo`) e o hash do estado atual. + +```solidity + event TransactionProcessed( + bytes32 indexed transactionHash, + bytes32 oldStateHash, + bytes32 newStateHash + ); +``` + +Toda vez que o estado muda, emitimos um evento `TransactionProcessed`. + +```solidity + function processTransaction( + bytes calldata _proof, + bytes32[] calldata _publicFields + ) public { +``` + +Esta função processa transações. Ele obtém a prova (como `bytes`) e as entradas públicas (como uma matriz `bytes32`), no formato que o verificador exige (para minimizar o processamento na cadeia e, portanto, os custos de gás). + +```solidity + require(_publicInputs[0] == currentStateHash, + "Wrong old state hash"); +``` + +A prova de conhecimento zero precisa ser que a transação muda do nosso hash atual para um novo. + +```solidity + myVerifier.verify(_proof, _publicFields); +``` + +Chame o contrato do verificador para verificar a prova de conhecimento zero. Este passo reverte a transação se a prova de conhecimento zero estiver errada. + +```solidity + currentStateHash = _publicFields[1]; + + emit TransactionProcessed( + _publicFields[2]<<128 | _publicFields[3], + _publicFields[0], + _publicFields[1] + ); + } +} +``` + +Se tudo estiver correto, atualize o hash de estado para o novo valor e emita um evento `TransactionProcessed`. + +## Abusos pelo componente centralizado {#abuses} + +A segurança da informação consiste em três atributos: + +- _Confidencialidade_, os usuários não podem ler informações que não estão autorizados a ler. +- _Integridade_, as informações não podem ser alteradas, exceto por usuários autorizados de maneira autorizada. +- _Disponibilidade_, usuários autorizados podem usar o sistema. + +Neste sistema, a integridade é fornecida por meio de provas de conhecimento zero. A disponibilidade é muito mais difícil de garantir, e a confidencialidade é impossível, porque o banco precisa saber o saldo de cada conta e todas as transações. Não há como impedir que uma entidade que possui informações compartilhe essas informações. + +Pode ser possível criar um banco verdadeiramente confidencial usando [endereços furtivos](https://vitalik.eth.limo/general/2023/01/20/stealth.html), mas isso está além do escopo deste artigo. + +### Informações falsas {#false-info} + +Uma maneira pela qual o servidor pode violar a integridade é fornecer informações falsas quando [os dados são solicitados](https://github.com/qbzzt/250911-zk-bank/blob/03-smart-contracts/server/index.mjs#L278-L291). + +Para resolver isso, podemos escrever um segundo programa Noir que recebe as contas como uma entrada privada e o endereço para o qual as informações são solicitadas como uma entrada pública. A saída é o saldo e o nonce desse endereço e o hash das contas. + +Claro, essa prova não pode ser verificada na cadeia, porque não queremos publicar nonces e saldos na cadeia. No entanto, pode ser verificado pelo código do cliente em execução no navegador. + +### Transações forçadas {#forced-txns} + +O mecanismo usual para garantir a disponibilidade e prevenir a censura em L2s é o de [transações forçadas](https://docs.optimism.io/stack/transactions/forced-transaction). Mas as transações forçadas não combinam com as provas de conhecimento zero. O servidor é a única entidade que pode verificar transações. + +Podemos modificar `smart-contracts/src/ZkBank.sol` para aceitar transações forçadas e impedir que o servidor altere o estado até que sejam processadas. No entanto, isso nos abre a um simples ataque de negação de serviço. E se uma transação forçada for inválida e, portanto, impossível de processar? + +A solução é ter uma prova de conhecimento zero de que uma transação forçada é inválida. Isso dá ao servidor três opções: + +- Processe a transação forçada, fornecendo uma prova de conhecimento zero de que ela foi processada e o novo hash de estado. +- Rejeitar a transação forçada e fornecer uma prova de conhecimento zero ao contrato de que a transação é inválida (endereço desconhecido, nonce incorreto ou saldo insuficiente). +- Ignorar a transação forçada. Não há como forçar o servidor a realmente processar a transação, mas isso significa que todo o sistema está indisponível. + +#### Garantias de disponibilidade {#avail-bonds} + +Em uma implementação real, provavelmente haveria algum tipo de motivo de lucro para manter o servidor funcionando. Podemos fortalecer esse incentivo fazendo com que o servidor publique uma garantia de disponibilidade que qualquer pessoa pode queimar se uma transação forçada não for processada dentro de um determinado período. + +### Código Noir ruim {#bad-noir-code} + +Normalmente, para que as pessoas confiem em um contrato inteligente, carregamos o código-fonte em um [explorador de blocos](https://eth.blockscout.com/address/0x7D16d2c4e96BCFC8f815E15b771aC847EcbDB48b?tab=contract). No entanto, no caso de provas de conhecimento zero, isso é insuficiente. + +`Verifier.sol` contém a chave de verificação, que é uma função do programa Noir. No entanto, essa chave não nos diz qual era o programa Noir. Para realmente ter uma solução confiável, você precisa carregar o programa Noir (e a versão que o criou). Caso contrário, as provas de conhecimento zero podem refletir um programa diferente, um com uma porta dos fundos. + +Até que os exploradores de blocos comecem a nos permitir carregar e verificar programas Noir, você deve fazer isso sozinho (de preferência para [IPFS](/developers/tutorials/ipfs-decentralized-ui/)). Então, usuários sofisticados poderão baixar o código-fonte, compilá-lo, criar o `Verifier.sol` e verificar se ele é idêntico ao que está na cadeia. + +## Conclusão {#conclusion} + +Os aplicativos do tipo plasma requerem um componente centralizado como armazenamento de informações. Isso abre vulnerabilidades potenciais, mas, em troca, nos permite preservar a privacidade de maneiras não disponíveis na própria blockchain. Com as provas de conhecimento zero, podemos garantir a integridade e, possivelmente, torná-lo economicamente vantajoso para quem estiver executando o componente centralizado para manter a disponibilidade. + +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). + +## Agradecimentos {#acknowledgements} + +- Josh Crites leu um rascunho deste artigo e me ajudou com um problema espinhoso no Noir. + +Quaisquer erros remanescentes são de minha responsabilidade. diff --git a/public/content/translations/pt-br/developers/tutorials/calling-a-smart-contract-from-javascript/index.md b/public/content/translations/pt-br/developers/tutorials/calling-a-smart-contract-from-javascript/index.md index d56ba75f58f..b052d3edea3 100644 --- a/public/content/translations/pt-br/developers/tutorials/calling-a-smart-contract-from-javascript/index.md +++ b/public/content/translations/pt-br/developers/tutorials/calling-a-smart-contract-from-javascript/index.md @@ -1,12 +1,8 @@ --- title: Chamando um contrato inteligente a partir do JavaScript -description: Como chamar uma função do contrato inteligente a partir do JavaScript usando um token Dai como exemplo +description: "Como chamar uma função de um contrato inteligente a partir do JavaScript usando um token Dai como exemplo" author: jdourlens -tags: - - "transações" - - "front-end" - - "JavaScript" - - "web3.js" +tags: [ "transações", "front-end", "JavaScript", "web3.js" ] skill: beginner lang: pt-br published: 2020-04-19 @@ -15,15 +11,15 @@ sourceUrl: https://ethereumdev.io/calling-a-smart-contract-from-javascript/ address: "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE" --- -Neste tutorial, veremos como chamar uma função do [contrato inteligente](/developers/docs/smart-contracts/) a partir do JavaScript. Primeiro vamos ler o estado de um contrato inteligente (por exemplo, o saldo de um titular do ERC20) e logo vamos modificar o estado da blockchain fazendo uma transferência de token. Você já deve estar familiarizado com [configurando um ambiente JavaScript para interagir com a blockchain](/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/). +Neste tutorial, veremos como chamar uma função de [contrato inteligente](/developers/docs/smart-contracts/) a partir do JavaScript. Primeiro, leremos o estado de um contrato inteligente (p. ex., o saldo de um detentor de ERC20), depois modificaremos o estado da cadeia de blocos fazendo uma transferência de token. Você já deve estar familiarizado com a [configuração de um ambiente JS para interagir com a cadeia de blocos](/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/). -Para esses exemplos, vamos usar o token DAI. Para fins de teste, vamos fazer um fork do blockchain usando ganache-cli e desbloquear um endereço que já possui muitos DAI: +Para este exemplo, vamos interagir com o token DAI. Para fins de teste, faremos uma bifurcação da cadeia de blocos usando ganache-cli e desbloquearemos um endereço que já tenha muito DAI: ```bash ganache-cli -f https://mainnet.infura.io/v3/[YOUR INFURA KEY] -d -i 66 1 --unlock 0x4d10ae710Bd8D1C31bd7465c8CBC3add6F279E81 ``` -Para interagir com um contrato inteligente, precisaremos do seu endereço e ABI: +Para interagir com um contrato inteligente, precisaremos de seu endereço e IAB: ```js const ERC20TransferABI = [ @@ -74,9 +70,9 @@ const ERC20TransferABI = [ const DAI_ADDRESS = "0x6b175474e89094c44da98b954eedeac495271d0f" ``` -Para este projeto, nós removemos parte do ERC20 ABI para manter apenas as funções `balanceOf` e `transfer`, mas você pode encontrar [aqui o ERC20 ABI completo](https://ethereumdev.io/abi-for-erc20-contract-on-ethereum/). +Para este projeto, removemos parte da IAB do ERC20 para manter apenas as funções `balanceOf` e `transfer`, mas você pode encontrar [a IAB completa do ERC20 aqui](https://ethereumdev.io/abi-for-erc20-contract-on-ethereum/). -Precisamos então instanciar nosso contrato inteligente: +Em seguida, precisamos instanciar nosso contrato inteligente: ```js const web3 = new Web3("http://localhost:8545") @@ -84,52 +80,52 @@ const web3 = new Web3("http://localhost:8545") const daiToken = new web3.eth.Contract(ERC20TransferABI, DAI_ADDRESS) ``` -Também vamos configurar dois endereços: +Também configuraremos dois endereços: -- quem receberá a transferência e -- o que nós já desbloqueamos que irá enviá-lo: +- aquele que receberá a transferência e +- aquele que já desbloqueamos e que fará o envio: ```js -const senderAddress = "0x4d10ae710Bd8D1C31bd7465c8CB3add6F279E81" +const senderAddress = "0x4d10ae710Bd8D1C31bd7465c8CBC3add6F279E81" const receiverAddress = "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE" ``` -Na próxima parte, chamaremos a função `balanceOf` para recuperar a quantidade atual de tokens que os dois endereços possuem. +Na próxima parte, chamaremos a função `balanceOf` para recuperar a quantidade atual de tokens que ambos os endereços possuem. -## Chamada: valor de leitura de um contrato inteligente {#call-reading-value-from-a-smart-contract} +## Chamada: lendo o valor de um contrato inteligente {#call-reading-value-from-a-smart-contract} -O primeiro exemplo chamará um método "constant" e executará seu método de contrato inteligente na EVM sem enviar qualquer transação. Para isso, vamos ler o saldo do ERC20 de um endereço. [Leia o nosso artigo sobre tokens ERC20](/developers/tutorials/understand-the-erc-20-token-smart-contract/). +O primeiro exemplo chamará um método "constante" e executará seu método de contrato inteligente na EVM sem enviar nenhuma transação. Para isso, leremos o saldo ERC20 de um endereço. [Leia nosso artigo sobre tokens ERC20](/developers/tutorials/understand-the-erc-20-token-smart-contract/). -Você pode acessar um método instanciado do contrato inteligente para o qual forneceu o ABI. Exemplo: `yourContract.methods.methodname`. Usando a função `call` você receberá o resultado da execução da função. +Você pode acessar os métodos de um contrato inteligente instanciado, para o qual você forneceu a IAB, da seguinte forma: `yourContract.methods.methodname`. Ao usar a função `call`, você receberá o resultado da execução da função. ```js -daiToken.methods.balanceOf(senderAddress).call(função (err, res) { +daiToken.methods.balanceOf(senderAddress).call(function (err, res) { if (err) { - console.log("Um erro ocorreu", err) + console.log("Ocorreu um erro", err) return } console.log("O saldo é: ", res) }) ``` -Lembre-se que DAI ERC20 tem 18 decimais, o que significa que você precisa remover 18 zeros para obter o valor correto. uint256 são retornados como cadeias de caracteres, pois o JavaScript não lida com grandes valores numéricos. Se não tiver certeza [de como lidar com grandes números em JS, verifique nosso tutorial sobre bignumber.js](https://ethereumdev.io/how-to-deal-with-big-numbers-in-javascript/). +Lembre-se de que o DAI ERC20 tem 18 casas decimais, o que significa que você precisa remover 18 zeros para obter o valor correto. Valores `uint256` são retornados como strings, pois o JavaScript não lida com valores numéricos grandes. Se você não tiver certeza de [como lidar com números grandes em JS, confira nosso tutorial sobre bignumber.js](https://ethereumdev.io/how-to-deal-with-big-numbers-in-javascript/). -## Enviar: enviando transação para uma função de contrato inteligente {#send-sending-a-transaction-to-a-smart-contract-function} +## Envio: enviando uma transação para uma função de contrato inteligente {#send-sending-a-transaction-to-a-smart-contract-function} -Para o segundo exemplo, chamaremos a função de transferência do contrato inteligente DAI para enviar 10 DAI para o nosso segundo endereço. A função de transferência aceita dois parâmetros: o endereço do destinatário e a quantidade de token para transferências: +Para o segundo exemplo, chamaremos a função de transferência do contrato inteligente DAI para enviar 10 DAI para nosso segundo endereço. A função de transferência aceita dois parâmetros: o endereço do destinatário e a quantidade de tokens a ser transferida: ```js daiToken.methods .transfer(receiverAddress, "100000000000000000000") .send({ from: senderAddress }, function (err, res) { if (err) { - console.log("An error occurred", err) + console.log("Ocorreu um erro", err) return } - console.log("Hash of the transaction: " + res) + console.log("Hash da transação: " + res) }) ``` -A função de chamada retorna o hash da transação que será minerada no blockchain. No Ethereum, hashes de transação são previsívei. É assim que podemos obter o hash da transação antes de ela ser executada ([saiba aqui como os hashes são calculados](https://ethereum.stackexchange.com/questions/45648/how-to-calculate-the-assigned-txhash-of-a-transaction)). +A função de chamada retorna o hash da transação que será minerada na cadeia de blocos. No Ethereum, os hashes de transação são previsíveis - é assim que podemos obter o hash da transação antes de ela ser executada ([aprenda como os hashes são calculados aqui](https://ethereum.stackexchange.com/questions/45648/how-to-calculate-the-assigned-txhash-of-a-transaction)). -Como função só envia a transação para a blockchain, não podemos ver o resultado até sabermos quando ela é minerada e incluída na blockchain. No próximo tutorial, aprenderemos [como aguardar por uma transação que será executada na blockchain com base no hash dela](https://ethereumdev.io/waiting-for-a-transaction-to-be-mined-on-ethereum-with-js/). +Como a função apenas envia a transação para a cadeia de blocos, não podemos ver o resultado até sabermos quando ela for minerada e incluída na cadeia de blocos. No próximo tutorial, aprenderemos [como esperar que uma transação seja executada na cadeia de blocos, conhecendo seu hash](https://ethereumdev.io/waiting-for-a-transaction-to-be-mined-on-ethereum-with-js/). diff --git a/public/content/translations/pt-br/developers/tutorials/creating-a-wagmi-ui-for-your-contract/index.md b/public/content/translations/pt-br/developers/tutorials/creating-a-wagmi-ui-for-your-contract/index.md new file mode 100644 index 00000000000..19a99b020c8 --- /dev/null +++ b/public/content/translations/pt-br/developers/tutorials/creating-a-wagmi-ui-for-your-contract/index.md @@ -0,0 +1,585 @@ +--- +title: "Construindo uma interface de usuário para seu contrato" +description: "Usando componentes modernos como TypeScript, React, Vite e Wagmi, vamos abordar uma interface de usuário moderna, mas minimalista, e aprender como conectar uma carteira à interface do usuário, chamar um contrato inteligente para ler informações, enviar uma transação para um contrato inteligente e monitorar eventos de um contrato inteligente para identificar alterações." +author: Ori Pomerantz +tags: [ "TypeScript", "react", "vite", "wagmi", "front-end" ] +skill: beginner +published: 2023-11-01 +lang: pt-br +sidebarDepth: 3 +--- + +Você encontrou um recurso que precisamos no ecossistema Ethereum. Você escreveu os contratos inteligentes para implementá-lo, e talvez até algum código relacionado que é executado fora da cadeia. Isso é ótimo! Infelizmente, sem uma interface de usuário, você não terá nenhum usuário, e da última vez que você escreveu um site, as pessoas usavam modems de discagem e o JavaScript era novo. + +Este artigo é para você. Presumo que você saiba programar, e talvez um pouco de JavaScript e HTML, mas que suas habilidades de interface de usuário estejam enferrujadas e desatualizadas. Juntos, vamos analisar uma aplicação moderna simples para que você veja como isso é feito hoje em dia. + +## Por que isso é importante {#why-important} + +Na teoria, você poderia simplesmente fazer com que as pessoas usassem o [Etherscan](https://holesky.etherscan.io/address/0x432d810484add7454ddb3b5311f0ac2e95cecea8#writeContract) ou o [Blockscout](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=write_contract) para interagir com seus contratos. Isso será ótimo para os Ethereans experientes. Mas estamos tentando servir a [mais um bilhão de pessoas](https://blog.ethereum.org/2021/05/07/ethereum-for-the-next-billion). Isso não acontecerá sem uma ótima experiência do usuário, e uma interface de usuário amigável é uma grande parte disso. + +## Aplicação Greeter {#greeter-app} + +Há muita teoria por trás do funcionamento de uma UI moderna, e [muitos sites bons](https://react.dev/learn/thinking-in-react) [que explicam isso](https://wagmi.sh/core/getting-started). Em vez de repetir o bom trabalho feito por esses sites, vou presumir que você prefere aprender fazendo e começar com uma aplicação com a qual possa interagir. Você ainda precisa da teoria para fazer as coisas, e chegaremos lá — vamos apenas passar de arquivo fonte por arquivo fonte e discutir as coisas à medida que as encontrarmos. + +### Instalação {#installation} + +1. Se necessário, adicione a [cadeia de blocos Holesky](https://chainlist.org/?search=holesky&testnets=true) à sua carteira e [obtenha ETH de teste](https://www.holeskyfaucet.io/). + +2. Clone o repositório do github. + + ```sh + git clone https://github.com/qbzzt/20230801-modern-ui.git + ``` + +3. Instale os pacotes necessários. + + ```sh + cd 20230801-modern-ui + pnpm install + ``` + +4. Inicie a aplicação. + + ```sh + pnpm dev + ``` + +5. Navegue até o URL mostrado pela aplicação. Na maioria dos casos, é [http://localhost:5173/](http://localhost:5173/). + +6. Você pode ver o código-fonte do contrato, uma versão ligeiramente modificada do Greeter da Hardhat, [em um explorador de blockchain](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=contract). + +### Passo a passo dos arquivos {#file-walk-through} + +#### `index.html` {#index-html} + +Este arquivo é um boilerplate HTML padrão, exceto por esta linha, que importa o arquivo de script. + +```html + +``` + +#### `src/main.tsx` {#main-tsx} + +A extensão do arquivo nos diz que este arquivo é um [componente React](https://www.w3schools.com/react/react_components.asp) escrito em [TypeScript](https://www.typescriptlang.org/), uma extensão do JavaScript que suporta [verificação de tipo](https://en.wikipedia.org/wiki/Type_system#Type_checking). O TypeScript é compilado para JavaScript, então podemos usá-lo para execução do lado do cliente. + +```tsx +import '@rainbow-me/rainbowkit/styles.css' +import { RainbowKitProvider } from '@rainbow-me/rainbowkit' +import * as React from 'react' +import * as ReactDOM from 'react-dom/client' +import { WagmiConfig } from 'wagmi' +import { chains, config } from './wagmi' +``` + +Importe o código da biblioteca que precisamos. + +```tsx +import { App } from './App' +``` + +Importe o componente React que implementa a aplicação (veja abaixo). + +```tsx +ReactDOM.createRoot(document.getElementById('root')!).render( +``` + +Crie o componente React raiz. O parâmetro para `render` é [JSX](https://www.w3schools.com/react/react_jsx.asp), uma linguagem de extensão que usa tanto HTML quanto JavaScript/TypeScript. O ponto de exclamação aqui diz ao componente TypeScript: "você não sabe que `document.getElementById('root')` será um parâmetro válido para `ReactDOM.createRoot`, mas não se preocupe - eu sou o desenvolvedor e estou lhe dizendo que haverá". + +```tsx + +``` + +A aplicação está dentro de um [componente `React.StrictMode`](https://react.dev/reference/react/StrictMode). Este componente diz à biblioteca React para inserir verificações de depuração adicionais, o que é útil durante o desenvolvimento. + +```tsx + +``` + +A aplicação também está dentro de um [componente `WagmiConfig`](https://wagmi.sh/react/api/WagmiProvider). [A biblioteca wagmi (we are going to make it)](https://wagmi.sh/) conecta as definições da UI do React com [a biblioteca viem](https://viem.sh/) para escrever um aplicativo descentralizado da Ethereum. + +```tsx + +``` + +E, finalmente, [um componente `RainbowKitProvider`](https://www.rainbowkit.com/). Este componente lida com o login e a comunicação entre a carteira e a aplicação. + +```tsx + +``` + +Agora podemos ter o componente para a aplicação, que realmente implementa a UI. O `/>` no final do componente diz ao React que este componente não tem nenhuma definição dentro dele, conforme o padrão XML. + +```tsx + + + , +) +``` + +Claro, temos que fechar os outros componentes. + +#### `src/App.tsx` {#app-tsx} + +```tsx +import { ConnectButton } from '@rainbow-me/rainbowkit' +import { useAccount } from 'wagmi' +import { Greeter } from './components/Greeter' + +export function App() { +``` + +Esta é a maneira padrão de criar um componente React - definir uma função que é chamada toda vez que precisa ser renderizada. Esta função normalmente tem algum código TypeScript ou JavaScript no início, seguido por uma declaração `return` que retorna o código JSX. + +```tsx + const { isConnected } = useAccount() +``` + +Aqui usamos [`useAccount`](https://wagmi.sh/react/api/hooks/useAccount) para verificar se estamos conectados a uma cadeia de blocos através de uma carteira ou não. + +Por convenção, em React, funções chamadas `use...` são [hooks](https://www.w3schools.com/react/react_hooks.asp) que retornam algum tipo de dado. Quando você usa esses hooks, não apenas seu componente obtém os dados, mas quando esses dados mudam, o componente é renderizado novamente com as informações atualizadas. + +```tsx + return ( + <> +``` + +O JSX de um componente React _tem_ que retornar um componente. Quando temos múltiplos componentes e não temos nada que os envolva "naturalmente", usamos um componente vazio (`<> ... `) para transformá-los em um único componente. + +```tsx +

Greeter

+ +``` + +Obtemos o [componente `ConnectButton`](https://www.rainbowkit.com/docs/connect-button) do RainbowKit. Quando não estamos conectados, ele nos dá um botão `Conectar Carteira` que abre um modal que explica sobre carteiras e permite que você escolha qual usar. Quando estamos conectados, ele exibe a cadeia de blocos que usamos, o endereço da nossa conta e nosso saldo de ETH. Podemos usar essas exibições para trocar de rede ou para desconectar. + +```tsx + {isConnected && ( +``` + +Quando precisamos inserir JavaScript real (ou TypeScript que será compilado para JavaScript) em um JSX, usamos chaves (`{}`). + +A sintaxe `a && b` é uma abreviação de [`a ? b : a`](https://www.w3schools.com/react/react_es6_ternary.asp). Ou seja, se `a` for verdadeiro, ele avalia para `b`, caso contrário, avalia para `a` (que pode ser `falso`, `0`, etc.). Esta é uma maneira fácil de dizer ao React que um componente só deve ser exibido se uma determinada condição for satisfeita. + +Neste caso, só queremos mostrar `Greeter` ao usuário se o usuário estiver conectado a uma cadeia de blocos. + +```tsx + + )} + + ) +} +``` + +#### `src/components/Greeter.tsx` {#greeter-tsx} + +Este arquivo contém a maior parte da funcionalidade da UI. Ele inclui definições que normalmente estariam em vários arquivos, mas como este é um tutorial, o programa é otimizado para ser fácil de entender na primeira vez, em vez de desempenho ou facilidade de manutenção. + +```tsx +import { useState, ChangeEventHandler } from 'react' +import { useNetwork, + useReadContract, + usePrepareContractWrite, + useContractWrite, + useContractEvent + } from 'wagmi' +``` + +Usamos estas funções de biblioteca. Novamente, elas são explicadas abaixo onde são usadas. + +```tsx +import { AddressType } from 'abitype' +``` + +[A biblioteca `abitype`](https://abitype.dev/) nos fornece definições TypeScript para vários tipos de dados do Ethereum, como [`AddressType`](https://abitype.dev/config#addresstype). + +```tsx +let greeterABI = [ + . + . + . +] as const // greeterABI +``` + +A ABI para o contrato `Greeter`. +Se você estiver desenvolvendo os contratos e a UI ao mesmo tempo, normalmente os colocaria no mesmo repositório e usaria a ABI gerada pelo compilador Solidity como um arquivo em sua aplicação. No entanto, isso não é necessário aqui porque o contrato já está desenvolvido e não vai mudar. + +```tsx +type AddressPerBlockchainType = { + [key: number]: AddressType +} +``` + +O TypeScript é fortemente tipado. Usamos essa definição para especificar o endereço em que o contrato `Greeter` é implantado em diferentes cadeias. A chave é um número (o chainId), e o valor é um `AddressType` (um endereço). + +```tsx +const contractAddrs: AddressPerBlockchainType = { + // Holesky + 17000: '0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8', + + // Sepolia + 11155111: '0x7143d5c190F048C8d19fe325b748b081903E3BF0' +} +``` + +O endereço do contrato nas duas redes suportadas: [Holesky](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=contact_code) e [Sepolia](https://eth-sepolia.blockscout.com/address/0x7143d5c190F048C8d19fe325b748b081903E3BF0?tab=contact_code). + +Nota: Existe na verdade uma terceira definição, para Redstone Holesky, que será explicada abaixo. + +```tsx +type ShowObjectAttrsType = { + name: string, + object: any +} +``` + +Este tipo é usado como um parâmetro para o componente `ShowObject` (explicado mais adiante). Ele inclui o nome do objeto e seu valor, que são exibidos para fins de depuração. + +```tsx +type ShowGreetingAttrsType = { + greeting: string | undefined +} +``` + +A qualquer momento, podemos saber qual é a saudação (porque a lemos da cadeia de blocos) ou não saber (porque ainda não a recebemos). Portanto, é útil ter um tipo que pode ser uma string ou nada. + +##### Componente `Greeter` {#greeter-component} + +```tsx +const Greeter = () => { +``` + +Finalmente, chegamos à definição do componente. + +```tsx + const { chain } = useNetwork() +``` + +Informações sobre a cadeia que estamos usando, cortesia de [wagmi](https://wagmi.sh/react/hooks/useNetwork). +Como isso é um hook (`use...`), toda vez que essa informação muda, o componente é redesenhado. + +```tsx + const greeterAddr = chain && contractAddrs[chain.id] +``` + +O endereço do contrato Greeter, que varia por cadeia (e que é `undefined` se não tivermos informações da cadeia ou estivermos em uma cadeia sem esse contrato). + +```tsx + const readResults = useReadContract({ + address: greeterAddr, + abi: greeterABI, + functionName: "greet" , // Sem argumentos + watch: true + }) +``` + +[O hook `useReadContract`](https://wagmi.sh/react/api/hooks/useReadContract) lê informações de um contrato. Você pode ver exatamente quais informações ele retorna expandindo `readResults` na UI. Neste caso, queremos que ele continue verificando para sermos informados quando a saudação mudar. + +**Nota:** Poderíamos escutar os [eventos `setGreeting`](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=logs) para saber quando a saudação muda e atualizar dessa forma. No entanto, embora possa ser mais eficiente, não se aplicará em todos os casos. Quando o usuário muda para uma cadeia diferente, a saudação também muda, mas essa mudança não é acompanhada por um evento. Poderíamos ter uma parte do código escutando eventos e outra para identificar mudanças de cadeia, mas isso seria mais complicado do que apenas definir [o parâmetro `watch`](https://wagmi.sh/react/api/hooks/useReadContract#watch-optional). + +```tsx + const [ newGreeting, setNewGreeting ] = useState("") +``` + +O [hook `useState`](https://www.w3schools.com/react/react_usestate.asp) do React nos permite especificar uma variável de estado, cujo valor persiste de uma renderização do componente para outra. O valor inicial é o parâmetro, neste caso, a string vazia. + +O hook `useState` retorna uma lista com dois valores: + +1. O valor atual da variável de estado. +2. Uma função para modificar a variável de estado quando necessário. Como este é um hook, toda vez que ele é chamado, o componente é renderizado novamente. + +Neste caso, estamos usando uma variável de estado para a nova saudação que o usuário deseja definir. + +```tsx + const greetingChange : ChangeEventHandler = (evt) => + setNewGreeting(evt.target.value) +``` + +Este é o manipulador de eventos para quando o campo de entrada da nova saudação muda. O tipo, [`ChangeEventHandler`](https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/forms_and_events/), especifica que este é um manipulador para uma mudança de valor de um elemento de entrada HTML. A parte `` é usada porque este é um [tipo genérico](https://www.w3schools.com/typescript/typescript_basic_generics.php). + +```tsx + const preparedTx = usePrepareContractWrite({ + address: greeterAddr, + abi: greeterABI, + functionName: 'setGreeting', + args: [ newGreeting ] + }) + const workingTx = useContractWrite(preparedTx.config) +``` + +Este é o processo para enviar uma transação de blockchain da perspectiva do cliente: + +1. Envie a transação para um nó na cadeia de blocos usando [`eth_estimateGas`](https://docs.alchemy.com/reference/eth-estimategas). +2. Aguarde uma resposta do nó. +3. Quando a resposta for recebida, peça ao usuário para assinar a transação através da carteira. Esta etapa _tem_ que acontecer depois que a resposta do nó for recebida, porque o custo do gás da transação é mostrado ao usuário antes que ele a assine. +4. Aguarde a aprovação do usuário. +5. Envie a transação novamente, desta vez usando [`eth_sendRawTransaction`](https://docs.alchemy.com/reference/eth-sendrawtransaction). + +A etapa 2 provavelmente levará um tempo perceptível, durante o qual os usuários se perguntariam se seu comando foi realmente recebido pela interface do usuário e por que ainda não lhes foi pedido para assinar a transação. Isso gera uma má experiência do usuário (UX). + +A solução é usar [hooks de preparação](https://wagmi.sh/react/prepare-hooks). Toda vez que um parâmetro muda, envie imediatamente ao nó a solicitação `eth_estimateGas`. Então, quando o usuário realmente quer enviar a transação (neste caso, pressionando **Atualizar saudação**), o custo do gás é conhecido e o usuário pode ver a página da carteira imediatamente. + +```tsx + return ( +``` + +Agora podemos finalmente criar o HTML real para retornar. + +```tsx + <> +

Greeter

+ { + !readResults.isError && !readResults.isLoading && + + } +
+``` + +Crie um componente `ShowGreeting` (explicado abaixo), mas somente se a saudação for lida com sucesso da cadeia de blocos. + +```tsx + +``` + +Este é o campo de texto de entrada onde o usuário pode definir uma nova saudação. Toda vez que o usuário pressiona uma tecla, chamamos `greetingChange`, que chama `setNewGreeting`. Como `setNewGreeting` vem do hook `useState`, ele faz com que o componente `Greeter` seja renderizado novamente. Isso significa que: + +- Precisamos especificar `value` para manter o valor da nova saudação, porque, caso contrário, ele voltaria ao padrão, a string vazia. +- `usePrepareContractWrite` é chamado toda vez que `newGreeting` muda, o que significa que ele sempre terá o `newGreeting` mais recente na transação preparada. + +```tsx + +``` + +Se não houver `workingTx.write`, ainda estamos aguardando as informações necessárias para enviar a atualização da saudação, então o botão está desabilitado. Se houver um valor `workingTx.write`, essa é a função a ser chamada para enviar a transação. + +```tsx +
+ + + + + ) +} +``` + +Finalmente, para ajudar você a ver o que estamos fazendo, mostramos os três objetos que usamos: + +- `readResults` +- `preparedTx` +- `workingTx` + +##### Componente `ShowGreeting` {#showgreeting-component} + +Este componente mostra + +```tsx +const ShowGreeting = (attrs : ShowGreetingAttrsType) => { +``` + +A função de um componente recebe um parâmetro com todos os atributos do componente. + +```tsx + return {attrs.greeting} +} +``` + +##### Componente `ShowObject` {#showobject-component} + +Para fins informativos, usamos o componente `ShowObject` para mostrar os objetos importantes (`readResults` para ler a saudação e `preparedTx` e `workingTx` para as transações que criamos). + +```tsx +const ShowObject = (attrs: ShowObjectAttrsType ) => { + const keys = Object.keys(attrs.object) + const funs = keys.filter(k => typeof attrs.object[k] == "function") + return <> +
+``` + +Não queremos poluir a UI com todas as informações, então para tornar possível visualizá-las ou fechá-las, usamos uma tag [`details`](https://www.w3schools.com/tags/tag_details.asp). + +```tsx + {attrs.name} +
+        {JSON.stringify(attrs.object, null, 2)}
+```
+
+A maioria dos campos é exibida usando [`JSON.stringify`](https://www.w3schools.com/js/js_json_stringify.asp).
+
+```tsx
+      
+ { funs.length > 0 && + <> + Functions: +
    +``` + +A exceção são as funções, que não fazem parte do [padrão JSON](https://www.json.org/json-en.html), então elas têm que ser exibidas separadamente. + +```tsx + {funs.map((f, i) => +``` + +Dentro do JSX, o código dentro de chaves `{` `}` é interpretado como JavaScript. Então, o código dentro dos parênteses `(` `)`, é interpretado novamente como JSX. + +```tsx + (
  • {f}
  • ) + )} +``` + +O React requer que as tags na [Árvore DOM](https://www.w3schools.com/js/js_htmldom.asp) tenham identificadores distintos. Isso significa que os filhos da mesma tag (neste caso, [a lista não ordenada](https://www.w3schools.com/tags/tag_ul.asp)), precisam de atributos `key` diferentes. + +```tsx +
+ + } +
+ +} +``` + +Finalize as várias tags HTML. + +##### O `export` final {#the-final-export} + +```tsx +export { Greeter } +``` + +O componente `Greeter` é o que precisamos exportar para a aplicação. + +#### `src/wagmi.ts` {#wagmi-ts} + +Finalmente, várias definições relacionadas ao WAGMI estão em `src/wagmi.ts`. Não vou explicar tudo aqui, porque a maior parte é boilerplate que você provavelmente não precisará mudar. + +O código aqui não é exatamente o mesmo que [no github](https://github.com/qbzzt/20230801-modern-ui/blob/main/src/wagmi.ts) porque mais adiante no artigo adicionamos outra cadeia ([Redstone Holesky](https://redstone.xyz/docs/network-info)). + +```ts +import { getDefaultWallets } from '@rainbow-me/rainbowkit' +import { configureChains, createConfig } from 'wagmi' +import { holesky, sepolia } from 'wagmi/chains' +``` + +Importe as blockchains que a aplicação suporta. Você pode ver a lista de cadeias suportadas [no github do viem](https://github.com/wagmi-dev/viem/tree/main/src/chains/definitions). + +```ts +import { publicProvider } from 'wagmi/providers/public' + +const walletConnectProjectId = 'c96e690bb92b6311e8e9b2a6a22df575' +``` + +Para poder usar o [WalletConnect](https://walletconnect.com/), você precisa de um ID de projeto para sua aplicação. Você pode obtê-lo em [cloud.walletconnect.com](https://cloud.walletconnect.com/sign-in). + +```ts +const { chains, publicClient, webSocketPublicClient } = configureChains( + [ holesky, sepolia ], + [ + publicProvider(), + ], +) + +const { connectors } = getDefaultWallets({ + appName: 'My wagmi + RainbowKit App', + chains, + projectId: walletConnectProjectId, +}) + +export const config = createConfig({ + autoConnect: true, + connectors, + publicClient, + webSocketPublicClient, +}) + +export { chains } +``` + +### Adicionando outra blockchain {#add-blockchain} + +Hoje em dia há muitas [soluções de escalabilidade L2](/layer-2/), e você pode querer suportar algumas que o viem ainda não suporta. Para fazer isso, você modifica `src/wagmi.ts`. Estas instruções explicam como adicionar a [Redstone Holesky](https://redstone.xyz/docs/network-info). + +1. Importe o tipo `defineChain` do viem. + + ```ts + import { defineChain } from 'viem' + ``` + +2. Adicione a definição de rede. + + ```ts + const redstoneHolesky = defineChain({ + id: 17_001, + name: 'Redstone Holesky', + network: 'redstone-holesky', + nativeCurrency: { + decimals: 18, + name: 'Ether', + symbol: 'ETH', + }, + rpcUrls: { + default: { + http: ['https://rpc.holesky.redstone.xyz'], + webSocket: ['wss://rpc.holesky.redstone.xyz/ws'], + }, + public: { + http: ['https://rpc.holesky.redstone.xyz'], + webSocket: ['wss://rpc.holesky.redstone.xyz/ws'], + }, + }, + blockExplorers: { + default: { name: 'Explorer', url: 'https://explorer.holesky.redstone.xyz' }, + }, + }) + ``` + +3. Adicione a nova cadeia à chamada `configureChains`. + + ```ts + const { chains, publicClient, webSocketPublicClient } = configureChains( + [ holesky, sepolia, redstoneHolesky ], + [ publicProvider(), ], + ) + ``` + +4. Certifique-se de que a aplicação saiba o endereço para seus contratos na nova rede. Neste caso, modificamos `src/components/Greeter.tsx`: + + ```ts + const contractAddrs : AddressPerBlockchainType = { + // Holesky + 17000: '0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8', + + // Redstone Holesky + 17001: '0x4919517f82a1B89a32392E1BF72ec827ba9986D3', + + // Sepolia + 11155111: '0x7143d5c190F048C8d19fe325b748b081903E3BF0' + } + ``` + +## Conclusão {#conclusion} + +Claro, você não se importa realmente em fornecer uma interface de usuário para o `Greeter`. Você quer criar uma interface de usuário para seus próprios contratos. Para criar sua própria aplicação, siga estes passos: + +1. Especifique para criar uma aplicação wagmi. + + ```sh copy + pnpm create wagmi + ``` + +2. Nomeie a aplicação. + +3. Selecione a estrutura **React**. + +4. Selecione a variante **Vite**. + +5. Você pode [adicionar o kit Rainbow](https://www.rainbowkit.com/docs/installation#manual-setup). + +Agora vá e torne seus contratos utilizáveis para o mundo inteiro. + +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). + diff --git a/public/content/translations/pt-br/developers/tutorials/deploying-your-first-smart-contract/index.md b/public/content/translations/pt-br/developers/tutorials/deploying-your-first-smart-contract/index.md index 4d78c0a3e2e..b2c0a9b3b21 100644 --- a/public/content/translations/pt-br/developers/tutorials/deploying-your-first-smart-contract/index.md +++ b/public/content/translations/pt-br/developers/tutorials/deploying-your-first-smart-contract/index.md @@ -1,12 +1,8 @@ --- -title: Implementando seu primeiro contrato inteligente -description: Uma introdução à implantação do seu primeiro contrato inteligente em uma rede de teste Ethereum +title: Implantando seu primeiro contrato inteligente +description: "Uma introdução à implantação do seu primeiro contrato inteligente em uma rede de teste Ethereum" author: "jdourlens" -tags: - - "contratos inteligentes" - - "remix" - - "solidity" - - "implementação" +tags: [ "smart contracts", "Remix", "Solidity", "implantação" ] skill: beginner lang: pt-br published: 2020-04-03 @@ -15,17 +11,17 @@ sourceUrl: https://ethereumdev.io/deploying-your-first-smart-contract/ address: "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE" --- -Acho que você está tão animado quanto nós para [implantar](/developers/docs/smart-contracts/deploying/) e interagir com o seu primeiro [contrato inteligente](/developers/docs/smart-contracts/) na blockchain Ethereum. +Imagino que você esteja tão animado quanto nós para [implantar](/developers/docs/smart-contracts/deploying/) e interagir com seu primeiro [contrato inteligente](/developers/docs/smart-contracts/) na blockchain Ethereum. -Não se preocupe, pois como este é o nosso primeiro contrato inteligente, vamos publicá-lo em uma [rede de testes local](/developers/docs/networks/), assim não custa nada para você implementar e brincar com ele o quanto quiser. +Não se preocupe, pois como este é o nosso primeiro contrato inteligente, vamos implantá-lo em uma [rede de teste local](/developers/docs/networks/) para que não custe nada para você implantar e brincar com ele o quanto quiser. ## Escrevendo nosso contrato {#writing-our-contract} -O primeiro passo é [visitar a Remix](https://remix.ethereum.org/) e criar um novo arquivo. Na parte superior esquerda da interface Remix adicione um novo arquivo e digite o nome do arquivo desejado. +O primeiro passo é [visitar o Remix](https://remix.ethereum.org/) e criar um novo arquivo. Na parte superior esquerda da interface do Remix, adicione um novo arquivo e digite o nome do arquivo que desejar. -![Adicionando um novo arquivo na interface Remix](./remix.png) +![Adicionando um novo arquivo na interface do Remix](./remix.png) -No novo arquivo, vamos colar o seguinte código. +No novo arquivo, colaremos o código a seguir. ```solidity // SPDX-License-Identifier: MIT @@ -33,15 +29,15 @@ pragma solidity >=0.5.17; contract Counter { - // Public variable of type unsigned int to keep the number of counts + // Variável pública do tipo inteiro não assinado para manter o número de contagens uint256 public count = 0; - // Function that increments our counter + // Função que incrementa nosso contador function increment() public { count += 1; } - // Not necessary getter to get the count value + // Getter não necessário para obter o valor da contagem function getCount() public view returns (uint256) { return count; } @@ -49,51 +45,51 @@ contract Counter { } ``` -Se você está acostumado com programação, você pode facilmente adivinhar o que este programa faz. Aqui está uma explicação linha a linha: +Se você tem experiência com programação, pode adivinhar facilmente o que este programa faz. Aqui está uma explicação linha por linha: - Linha 4: Definimos um contrato com o nome `Counter`. -- Linha 7: Nosso contrato armazena um inteiro não assinado chamado `count` começando com 0. -- Linha 10: A primeira função vai modificar o estado do contrato e `increment()` nossa variável `count`. -- Linha 15: A segunda função é apenas um getter para ser capaz de ler o valor da variável `count` fora do contrato inteligente. Observe que, como definimos nossa variável `count` como pública, isso não é necessário, mas é mostrado como um exemplo. +- Linha 7: Nosso contrato armazena um inteiro sem sinal chamado `count` começando em 0. +- Linha 10: A primeira função modificará o estado do contrato e `increment()` nossa variável `count`. +- Linha 15: A segunda função é apenas um getter para poder ler o valor da variável `count` fora do contrato inteligente. Observe que, como definimos nossa variável `count` como pública, isso não é necessário, mas é mostrado como um exemplo. -Tudo isso para o nosso primeiro contrato inteligente simples. Como você deve saber, ele se parece com uma classe de linguagens OOP (Object-Oriented Programming, programação orientada a objetos) como Java ou C++. Agora é hora de brincar com o nosso contrato. +Isto é tudo para o nosso primeiro contrato inteligente simples. Como você deve saber, ele se parece com uma classe de linguagens OOP (Programação Orientada a Objetos) como Java ou C++. Agora é hora de brincar com o nosso contrato. ## Implantando nosso contrato {#deploying-our-contract} -Como escrevemos nosso primeiro contrato inteligente, nós agora faremos deploy para a blockchain para poder brincar com ele. +Como escrevemos nosso primeiro contrato inteligente, agora vamos implantá-lo na blockchain para podermos brincar com ele. -[Implantar o contrato inteligente no blockchain](/developers/docs/smart-contracts/deploying/) é, na verdade, apenas enviar uma transação que contém o código do contrato inteligente compilado sem especificar os destinatários. +[Implantar o contrato inteligente na blockchain](/developers/docs/smart-contracts/deploying/) é, na verdade, apenas enviar uma transação que contém o código do contrato inteligente compilado sem especificar nenhum destinatário. Primeiro, vamos [compilar o contrato](/developers/docs/smart-contracts/compiling/) clicando no ícone de compilação no lado esquerdo: -![O ícone de compilação na barra de ferramentas Remix](./remix-compile-button.png) +![O ícone de compilação na barra de ferramentas do Remix](./remix-compile-button.png) Em seguida, clique no botão de compilação: -![O botão de compilação no compilador do solidity Remix](./remix-compile.png) +![O botão de compilação no compilador Solidity do Remix](./remix-compile.png) -Você pode escolher selecionar a opção "Compilação automática", para que o contrato sempre seja compilado quando você salvar o conteúdo no editor de texto. +Você pode selecionar a opção "Compilação automática" para que o contrato seja sempre compilado quando você salvar o conteúdo no editor de texto. -Em seguida, navegue para a tela de implantação e execução de transações: +Em seguida, navegue para a tela "DEPLOY & RUN TRANSACTIONS": -![O ícone de compilação na barra de ferramentas do Remix](./remix-deploy.png) +![O ícone de implantação na barra de ferramentas do Remix](./remix-deploy.png) -Assim que você estiver na tela de transações "deploy and run" verifique se o nome do seu contrato aparece e clique em Deploy. Como você pode ver no topo da página, o ambiente atual é o "Javascript VM", o que significa que iremos implantar e interagir com nosso contrato inteligente em uma blockchain de teste local para podermos testar mais rápido e sem quaisquer custos. +Quando estiver na tela "DEPLOY & RUN TRANSACTIONS", verifique se o nome do seu contrato aparece e clique em Deploy. Como você pode ver na parte superior da página, o ambiente atual é "JavaScript VM", o que significa que vamos implantar e interagir com nosso contrato inteligente em uma blockchain de teste local para podermos testar mais rápido e sem nenhuma taxa. -![O botão de deploy no compilador do solidity Remix](./remix-deploy-button.png) +![O botão de implantação no compilador Solidity do Remix](./remix-deploy-button.png) -Quando você clicar no botão "Deploy", você verá seu contrato aparecer abaixo. Clique na seta à esquerda para expandi-la, para que possamos ver o conteúdo de nosso contrato. Esta é nossa variável `counter`, nossa função `increment()` e a getter `getCounter()`. +Depois de clicar no botão "Deploy", você verá seu contrato aparecer na parte inferior. Clique na seta à esquerda para expandi-lo para vermos o conteúdo do nosso contrato. Esta é a nossa variável `counter`, a nossa função `increment()` e o getter `getCounter()`. Se você clicar no botão `count` ou `getCount`, ele recuperará o conteúdo da variável `count` do contrato e o exibirá. Como ainda não chamamos a função `increment`, ela deve exibir 0. -![O botão de função no compilador do solidity Remix](./remix-function-button.png) +![O botão de função no compilador Solidity do Remix](./remix-function-button.png) -Vamos agora chamar a função `increment` clicando no botão. Você verá logs das transações que são feitas aparecendo no parte inferior da janela. Você verá que os logs são diferentes quando estiver pressionando o botão para recuperar os dados em vez do botão `increment`. Isso porque a leitura de dados na blockchain não necessita de quaisquer transações (escritas) ou taxas. Porque somente modificar o estado do blockchain requer fazer uma transação: +Vamos agora chamar a função `increment` clicando no botão. Você verá os logs das transações realizadas aparecendo na parte inferior da janela. Você verá que os logs são diferentes quando você pressiona o botão para recuperar os dados em vez do botão `increment`. Isso porque a leitura de dados na blockchain não precisa de nenhuma transação (escrita) ou taxa. Porque apenas a modificação do estado da blockchain exige a realização de uma transação: ![Um log de transações](./transaction-log.png) -Após pressionar o botão de incremento que gerará uma transação para chamar nossa função `increment()` se clicarmos novamente nos botões count ou getCount, iremos ler o estado recém-atualizado de nosso contrato inteligente com a variável de contagem maior que 0. +Depois de pressionar o botão de incremento que irá gerar uma transação para chamar nossa função `increment()`, se clicarmos de volta nos botões `count` ou `getCount`, leremos o estado recém-atualizado de nosso contrato inteligente com a variável de contagem sendo maior que 0. -![Estado recentemente atualizado do contrato inteligente](./updated-state.png) +![Estado recém-atualizado do contrato inteligente](./updated-state.png) -No próximo tutorial, explicaremos [como você pode adicionar eventos aos seus contratos inteligentes](/developers/tutorials/logging-events-smart-contracts/). Eventos de registro são uma maneira conveniente para depurar seu contrato inteligente e entender o que está acontecendo durante a chamada de uma função. +No próximo tutorial, abordaremos [como você pode adicionar eventos aos seus contratos inteligentes](/developers/tutorials/logging-events-smart-contracts/). Registrar eventos é uma maneira conveniente de depurar seu contrato inteligente e entender o que está acontecendo ao chamar uma função. diff --git a/public/content/translations/pt-br/developers/tutorials/develop-and-test-dapps-with-a-multi-client-local-eth-testnet/index.md b/public/content/translations/pt-br/developers/tutorials/develop-and-test-dapps-with-a-multi-client-local-eth-testnet/index.md new file mode 100644 index 00000000000..db6a6ad0e50 --- /dev/null +++ b/public/content/translations/pt-br/developers/tutorials/develop-and-test-dapps-with-a-multi-client-local-eth-testnet/index.md @@ -0,0 +1,372 @@ +--- +title: Como desenvolver e testar um dApp em uma rede de teste local multicliente +description: "Este guia primeiro o guiará por como instanciar e configurar uma rede de teste local multicliente do Ethereum antes de usar a rede de teste para implantar e testar um dApp." +author: "Tedi Mitiku" +tags: + [ + "clientes", + "nós", + "smart contracts", + "componibilidade", + "camada de consenso", + "camada de execução", + "testando" + ] +skill: intermediate +lang: pt-br +published: 2023-04-11 +--- + +## Introdução {#introduction} + +Este guia o orienta no processo de instanciar uma rede de teste local configurável do Ethereum, implantar um contrato inteligente nela e usar a rede de teste para executar testes em seu dApp. Este guia foi elaborado para desenvolvedores de dApps que queiram desenvolver e testar seus dApps localmente em diferentes configurações de rede antes de implantar em uma rede de teste ativa ou na rede principal. + +Neste guia, você irá: + +- Instanciar uma rede de teste local do Ethereum com o [`eth-network-package`](https://github.com/kurtosis-tech/eth-network-package) usando [Kurtosis](https://www.kurtosis.com/), +- Conectar seu ambiente de desenvolvimento de dApp Hardhat à rede de teste local para compilar, implantar e testar um dApp, e +- Configurar a rede de teste local, incluindo parâmetros como o número de nós e pares de clientes EL/CL específicos, para permitir fluxos de trabalho de desenvolvimento e teste em várias configurações de rede. + +### O que é Kurtosis? {#what-is-kurtosis} + +[Kurtosis](https://www.kurtosis.com/) é um sistema de compilação componível projetado para configurar ambientes de teste de múltiplos contêineres. Ele permite especificamente que os desenvolvedores criem ambientes reprodutíveis que exigem lógica de configuração dinâmica, como redes de teste de blockchain. + +Neste guia, o eth-network-package da Kurtosis inicia uma rede de teste local do Ethereum com suporte para o cliente da Camada de Execução (EL) [`geth`](https://geth.ethereum.org/), bem como para os clientes da Camada de Consenso (CL) [`teku`](https://consensys.io/teku), [`lighthouse`](https://lighthouse.sigmaprime.io/) e [`lodestar`](https://lodestar.chainsafe.io/). Este pacote serve como uma alternativa configurável e componível para redes em frameworks como Hardhat Network, Ganache e Anvil. O Kurtosis oferece aos desenvolvedores maior controle e flexibilidade sobre as redes de teste que utilizam, que é uma das principais razões pelas quais a [Ethereum Foundation usou o Kurtosis para testar a Fusão](https://www.kurtosis.com/blog/testing-the-ethereum-merge) e continua a usá-lo para testar atualizações de rede. + +## Configurando o Kurtosis {#setting-up-kurtosis} + +Antes de prosseguir, certifique-se de que você tenha: + +- [Instalado e iniciado o motor Docker](https://docs.kurtosis.com/install/#i-install--start-docker) em sua máquina local +- [Instalado o Kurtosis CLI](https://docs.kurtosis.com/install#ii-install-the-cli) (ou o atualizou para a versão mais recente, se você já tiver o CLI instalado) +- Instalado [Node.js](https://nodejs.org/en), [yarn](https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable) e [npx](https://www.npmjs.com/package/npx) (para o seu ambiente dApp) + +## Instanciando uma rede de teste local do Ethereum {#instantiate-testnet} + +Para iniciar uma rede de teste local do Ethereum, execute: + +```python +kurtosis --enclave local-eth-testnet run github.com/kurtosis-tech/eth-network-package +``` + +Observação: Este comando nomeia sua rede: "local-eth-testnet" usando a flag `--enclave`. + +O Kurtosis imprimirá os passos que está a tomar internamente enquanto trabalha para interpretar, validar e executar as instruções. Ao final, você deverá ver um resultado semelhante ao seguinte: + +```python +INFO[2023-04-04T18:09:44-04:00] ====================================================== +INFO[2023-04-04T18:09:44-04:00] || Enclave criado: local-eth-testnet || +INFO[2023-04-04T18:09:44-04:00] ====================================================== +Nome: local-eth-testnet +UUID: 39372d756ae8 +Status: EM EXECUÇÃO +Horário da criação: Ter, 04 Abr 2023 18:09:03 EDT + +========================================= Artefatos de Arquivos ========================================= +UUID Nome +d4085a064230 cl-genesis-data +1c62cb792e4c el-genesis-data +bd60489b73a7 genesis-generation-config-cl +b2e593fe5228 genesis-generation-config-el +d552a54acf78 geth-prefunded-keys +5f7e661eb838 prysm-password +054e7338bb59 validator-keystore-0 + +========================================== Serviços de Usuário ========================================== +UUID Nome Portas Status +e20f129ee0c5 cl-client-0-beacon http: 4000/tcp -> EM EXECUÇÃO + metrics: 5054/tcp -> + tcp-discovery: 9000/tcp -> 127.0.0.1:54263 + udp-discovery: 9000/udp -> 127.0.0.1:60470 +a8b6c926cdb4 cl-client-0-validator http: 5042/tcp -> 127.0.0.1:54267 EM EXECUÇÃO + metrics: 5064/tcp -> +d7b802f623e8 el-client-0 engine-rpc: 8551/tcp -> 127.0.0.1:54253 EM EXECUÇÃO + rpc: 8545/tcp -> 127.0.0.1:54251 + tcp-discovery: 30303/tcp -> 127.0.0.1:54254 + udp-discovery: 30303/udp -> 127.0.0.1:53834 + ws: 8546/tcp -> 127.0.0.1:54252 +514a829c0a84 prelaunch-data-generator-1680646157905431468 PARADO +62bd62d0aa7a prelaunch-data-generator-1680646157915424301 PARADO +05e9619e0e90 prelaunch-data-generator-1680646157922872635 PARADO + +``` + +Parabéns! Você usou o Kurtosis para instanciar uma rede de teste local do Ethereum, com um cliente CL (`lighthouse`) e um cliente EL (`geth`), sobre Docker. + +### Revisão {#review-instantiate-testnet} + +Nesta seção, você executou um comando que instruiu o Kurtosis a usar o [`eth-network-package` hospedado remotamente no GitHub](https://github.com/kurtosis-tech/eth-network-package) para iniciar uma rede de teste local do Ethereum dentro de um [Enclave](https://docs.kurtosis.com/advanced-concepts/enclaves/) do Kurtosis. Dentro do seu enclave, você encontrará "artefatos de arquivo" e "serviços de usuário". + +Os [Artefatos de arquivo](https://docs.kurtosis.com/advanced-concepts/files-artifacts/) no seu enclave incluem todos os dados gerados e utilizados para inicializar os clientes EL e CL. Os dados foram criados usando o serviço `prelaunch-data-generator` construído a partir desta [imagem Docker](https://github.com/ethpandaops/ethereum-genesis-generator) + +Os serviços de usuário exibem todos os serviços em contêineres operando no seu enclave. Você notará que um único nó, com um cliente EL e um cliente CL, foi criado. + +## Conecte seu ambiente de desenvolvimento de dApp à rede de teste local do Ethereum {#connect-your-dapp} + +### Configure o ambiente de desenvolvimento de dApp {#set-up-dapp-env} + +Agora que você tem uma rede de teste local em execução, você pode conectar seu ambiente de desenvolvimento de dApp para usar sua rede de teste local. O framework Hardhat será usado neste guia para implantar um dApp de blackjack na sua rede de teste local. + +Para configurar seu ambiente de desenvolvimento de dApp, clone o repositório que contém nosso dApp de exemplo e instale suas dependências, execute: + +```python +git clone https://github.com/kurtosis-tech/awesome-kurtosis.git && cd awesome-kurtosis/smart-contract-example && yarn +``` + +A pasta [smart-contract-example](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/smart-contract-example) usada aqui contém a configuração típica para um desenvolvedor de dApp usando o framework [Hardhat](https://hardhat.org/): + +- [`contracts/`](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/smart-contract-example/contracts) contém alguns contratos inteligentes simples para um dApp de Blackjack +- [`scripts/`](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/smart-contract-example/scripts) contém um script para implantar um contrato de token em sua rede Ethereum local +- [`test/`](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/smart-contract-example/test) contém um teste .js simples para seu contrato de token para confirmar que cada jogador em nosso dApp de Blackjack tem 1000 tokens emitidos para eles +- [`hardhat.config.ts`](https://github.com/kurtosis-tech/awesome-kurtosis/blob/main/smart-contract-example/hardhat.config.ts) configura sua instalação do Hardhat + +### Configurar o Hardhat para usar a rede de teste local {#configure-hardhat} + +Com seu ambiente de desenvolvimento de dApp configurado, você agora conectará o Hardhat para usar a rede de teste local do Ethereum gerada usando o Kurtosis. Para fazer isso, substitua `<$YOUR_PORT>` na estrutura `localnet` no seu arquivo de configuração `hardhat.config.ts` pela porta da saída do URI rpc de qualquer serviço `el-client-`. Neste caso de exemplo, a porta seria `64248`. Sua porta será diferente. + +Exemplo em `hardhat.config.ts`: + +```js +localnet: { +url: 'http://127.0.0.1:<$YOUR_PORT>',// TODO: SUBSTITUA $YOUR_PORT PELA PORTA DE UM URI DE NÓ PRODUZIDO PELO PACOTE DE REDE ETH KURTOSIS + +// Estas são chaves privadas associadas a contas de teste pré-financiadas criadas pelo eth-network-package +// +accounts: [ + "ef5177cd0b6b21c87db5a0bf35d4084a8a57a9d6a064f86d51ac85f2b873a4e2", + "48fcc39ae27a0e8bf0274021ae6ebd8fe4a0e12623d61464c498900b28feb567", + "7988b3a148716ff800414935b305436493e1f25237a2a03e5eebc343735e2f31", + "b3c409b6b0b3aa5e65ab2dc1930534608239a478106acf6f3d9178e9f9b00b35", + "df9bb6de5d3dc59595bcaa676397d837ff49441d211878c024eabda2cd067c9f", + "7da08f856b5956d40a72968f93396f6acff17193f013e8053f6fbb6c08c194d6", + ], +}, +``` + +Depois de salvar seu arquivo, seu ambiente de desenvolvimento de dApp Hardhat está agora conectado à sua rede de teste local do Ethereum! Você pode verificar se sua rede de teste está funcionando executando: + +```python +npx hardhat balances --network localnet +``` + +A saída deve ser algo como: + +```python +0x878705ba3f8Bc32FCf7F4CAa1A35E72AF65CF766 has balance 10000000000000000000000000 +0x4E9A3d9D1cd2A2b2371b8b3F489aE72259886f1A has balance 10000000000000000000000000 +0xdF8466f277964Bb7a0FFD819403302C34DCD530A has balance 10000000000000000000000000 +0x5c613e39Fc0Ad91AfDA24587e6f52192d75FBA50 has balance 10000000000000000000000000 +0x375ae6107f8cC4cF34842B71C6F746a362Ad8EAc has balance 10000000000000000000000000 +0x1F6298457C5d76270325B724Da5d1953923a6B88 has balance 10000000000000000000000000 +``` + +Isso confirma que o Hardhat está usando sua rede de teste local e detecta as contas pré-financiadas criadas pelo `eth-network-package`. + +### Implantar e testar seu dApp localmente {#deploy-and-test-dapp} + +Com o ambiente de desenvolvimento de dApp totalmente conectado à rede de teste local do Ethereum, agora você pode executar fluxos de trabalho de desenvolvimento e teste em seu dApp usando a rede de teste local. + +Para compilar e implantar o contrato inteligente `ChipToken.sol` para prototipagem e desenvolvimento local, execute: + +```python +npx hardhat compile +npx hardhat run scripts/deploy.ts --network localnet +``` + +A saída deve se parecer com: + +```python +ChipToken implantado em: 0xAb2A01BC351770D09611Ac80f1DE076D56E0487d +``` + +Agora tente executar o teste `simple.js` em seu dApp local para confirmar que cada jogador em nosso dApp de Blackjack tem 1000 tokens emitidos para eles: + +A saída deve ser algo como: + +```python +npx hardhat test --network localnet +``` + +A saída deve ser algo como: + +```python +ChipToken + emissão + ✔ deve emitir 1000 fichas para o JOGADOR UM + + 1 aprovado (654ms) +``` + +### Revisão {#review-dapp-workflows} + +Neste ponto, você configurou um ambiente de desenvolvimento de dApp, conectou-o a uma rede Ethereum local criada pelo Kurtosis e compilou, implantou e executou um teste simples em seu dApp. + +Agora vamos explorar como você pode configurar a rede subjacente para testar nossos dApps sob várias configurações de rede. + +## Configurando a rede de teste local do Ethereum {#configure-testnet} + +### Alterando as configurações do cliente e o número de nós {#configure-client-config-and-num-nodes} + +Sua rede de teste local do Ethereum pode ser configurada para usar diferentes pares de clientes EL e CL, bem como um número variável de nós, dependendo do cenário e da configuração de rede específica que você deseja desenvolver ou testar. Isso significa que, uma vez configurado, você pode iniciar uma rede de teste local personalizada e usá-la para executar os mesmos fluxos de trabalho (implantação, testes, etc.) sob várias configurações de rede para garantir que tudo funcione como esperado. Para saber mais sobre os outros parâmetros que você pode modificar, visite este link. + +Experimente! Você pode passar várias opções de configuração para o `eth-network-package` através de um arquivo JSON. Este arquivo JSON de parâmetros de rede fornece as configurações específicas que o Kurtosis usará para configurar a rede Ethereum local. + +Pegue o arquivo de configuração padrão e edite-o para iniciar três nós com pares EL/CL diferentes: + +- Nó 1 com `geth`/`lighthouse` +- Nó 2 com `geth`/`lodestar` +- Nó 3 com `geth`/`teku` + +Essa configuração cria uma rede heterogênea de implementações de nós Ethereum para testar seu dApp. Seu arquivo de configuração deve ficar assim: + +```yaml +{ + "participants": + [ + { + "el_client_type": "geth", + "el_client_image": "", + "el_client_log_level": "", + "cl_client_type": "lighthouse", + "cl_client_image": "", + "cl_client_log_level": "", + "beacon_extra_params": [], + "el_extra_params": [], + "validator_extra_params": [], + "builder_network_params": null, + }, + { + "el_client_type": "geth", + "el_client_image": "", + "el_client_log_level": "", + "cl_client_type": "lodestar", + "cl_client_image": "", + "cl_client_log_level": "", + "beacon_extra_params": [], + "el_extra_params": [], + "validator_extra_params": [], + "builder_network_params": null, + }, + { + "el_client_type": "geth", + "el_client_image": "", + "el_client_log_level": "", + "cl_client_type": "teku", + "cl_client_image": "", + "cl_client_log_level": "", + "beacon_extra_params": [], + "el_extra_params": [], + "validator_extra_params": [], + "builder_network_params": null, + }, + ], + "network_params": + { + "preregistered_validator_keys_mnemonic": "giant issue aisle success illegal bike spike question tent bar rely arctic volcano long crawl hungry vocal artwork sniff fantasy very lucky have athlete", + "num_validator_keys_per_node": 64, + "network_id": "3151908", + "deposit_contract_address": "0x4242424242424242424242424242424242424242", + "seconds_per_slot": 12, + "genesis_delay": 120, + "capella_fork_epoch": 5, + }, +} +``` + +Cada estrutura `participants` mapeia para um nó na rede, portanto, 3 estruturas `participants` instruirão o Kurtosis a iniciar 3 nós em sua rede. Cada estrutura `participants` permitirá que você especifique o par EL e CL usado para aquele nó específico. + +A estrutura `network_params` configura as definições de rede que são usadas para criar os arquivos de gênese para cada nó, bem como outras configurações, como os segundos por slot da rede. + +Salve seu arquivo de parâmetros editado em qualquer diretório que desejar (no exemplo abaixo, ele é salvo na área de trabalho) e, em seguida, use-o para executar seu pacote Kurtosis executando: + +```python +kurtosis clean -a && kurtosis run --enclave local-eth-testnet github.com/kurtosis-tech/eth-network-package "$(cat ~/eth-network-params.json)" +``` + +Observação: o comando `kurtosis clean -a` é usado aqui para instruir o Kurtosis a destruir a antiga rede de teste e seu conteúdo antes de iniciar uma nova. + +Novamente, o Kurtosis trabalhará por um tempo e imprimirá os passos individuais que estão ocorrendo. Eventualmente, a saída deve ser algo como: + +```python +Código Starlark executado com sucesso. Nenhum resultado foi retornado. +INFO[2023-04-07T11:43:16-04:00] ========================================================== +INFO[2023-04-07T11:43:16-04:00] || Enclave criado: local-eth-testnet || +INFO[2023-04-07T11:43:16-04:00] ========================================================== +Nome: local-eth-testnet +UUID: bef8c192008e +Status: EM EXECUÇÃO +Horário de criação: Sex, 07 Abr 2023 11:41:58 EDT + +========================================= Artefatos de Arquivos ========================================= +UUID Nome +cc495a8e364a cl-genesis-data +7033fcdb5471 el-genesis-data +a3aef43fc738 genesis-generation-config-cl +8e968005fc9d genesis-generation-config-el +3182cca9d3cd geth-prefunded-keys +8421166e234f prysm-password +d9e6e8d44d99 validator-keystore-0 +23f5ba517394 validator-keystore-1 +4d28dea40b5c validator-keystore-2 + +========================================== Serviços de Usuário ========================================== +UUID Nome Portas Status +485e6fde55ae cl-client-0-beacon http: 4000/tcp -> http://127.0.0.1:65010 EM EXECUÇÃO + metrics: 5054/tcp -> http://127.0.0.1:65011 + tcp-discovery: 9000/tcp -> 127.0.0.1:65012 + udp-discovery: 9000/udp -> 127.0.0.1:54455 +73739bd158b2 cl-client-0-validator http: 5042/tcp -> 127.0.0.1:65016 EM EXECUÇÃO + metrics: 5064/tcp -> http://127.0.0.1:65017 +1b0a233cd011 cl-client-1-beacon http: 4000/tcp -> 127.0.0.1:65021 EM EXECUÇÃO + metrics: 8008/tcp -> 127.0.0.1:65023 + tcp-discovery: 9000/tcp -> 127.0.0.1:65024 + udp-discovery: 9000/udp -> 127.0.0.1:56031 + validator-metrics: 5064/tcp -> 127.0.0.1:65022 +949b8220cd53 cl-client-1-validator http: 4000/tcp -> 127.0.0.1:65028 EM EXECUÇÃO + metrics: 8008/tcp -> 127.0.0.1:65030 + tcp-discovery: 9000/tcp -> 127.0.0.1:65031 + udp-discovery: 9000/udp -> 127.0.0.1:60784 + validator-metrics: 5064/tcp -> 127.0.0.1:65029 +c34417bea5fa cl-client-2 http: 4000/tcp -> 127.0.0.1:65037 EM EXECUÇÃO + metrics: 8008/tcp -> 127.0.0.1:65035 + tcp-discovery: 9000/tcp -> 127.0.0.1:65036 + udp-discovery: 9000/udp -> 127.0.0.1:63581 +e19738e6329d el-client-0 engine-rpc: 8551/tcp -> 127.0.0.1:64986 EM EXECUÇÃO + rpc: 8545/tcp -> 127.0.0.1:64988 + tcp-discovery: 30303/tcp -> 127.0.0.1:64987 + udp-discovery: 30303/udp -> 127.0.0.1:55706 + ws: 8546/tcp -> 127.0.0.1:64989 +e904687449d9 el-client-1 engine-rpc: 8551/tcp -> 127.0.0.1:64993 EM EXECUÇÃO + rpc: 8545/tcp -> 127.0.0.1:64995 + tcp-discovery: 30303/tcp -> 127.0.0.1:64994 + udp-discovery: 30303/udp -> 127.0.0.1:58096 + ws: 8546/tcp -> 127.0.0.1:64996 +ad6f401126fa el-client-2 engine-rpc: 8551/tcp -> 127.0.0.1:65003 EM EXECUÇÃO + rpc: 8545/tcp -> 127.0.0.1:65001 + tcp-discovery: 30303/tcp -> 127.0.0.1:65000 + udp-discovery: 30303/udp -> 127.0.0.1:57269 + ws: 8546/tcp -> 127.0.0.1:65002 +12d04a9dbb69 prelaunch-data-generator-1680882122181135513 PARADO +5b45f9c0504b prelaunch-data-generator-1680882122192182847 PARADO +3d4aaa75e218 prelaunch-data-generator-1680882122201668972 PARADO +``` + +Parabéns! Você configurou com sucesso sua rede de teste local para ter 3 nós em vez de 1. Para executar os mesmos fluxos de trabalho que você fez antes em seu dApp (implantar e testar), realize as mesmas operações que fizemos antes, substituindo `<$YOUR_PORT>` na estrutura `localnet` em seu arquivo de configuração `hardhat.config.ts` pela porta da saída do URI rpc de qualquer serviço `el-client-` em sua nova rede de teste local de 3 nós. + +## Conclusão {#conclusion} + +E é isso! Para recapitular este breve guia, você: + +- Criou uma rede de teste local do Ethereum sobre Docker usando o Kurtosis +- Conectou seu ambiente de desenvolvimento de dApp local à rede Ethereum local +- Implantou um dApp e executou um teste simples nele na rede Ethereum local +- Configurou a rede Ethereum subjacente para ter 3 nós + +Gostaríamos muito de saber sua opinião sobre o que deu certo para você, o que poderia ser melhorado, ou para responder a qualquer uma de suas perguntas. Não hesite em nos contatar via [GitHub](https://github.com/kurtosis-tech/kurtosis/issues/new/choose) ou [envie-nos um e-mail](mailto:feedback@kurtosistech.com)! + +### Outros exemplos e guias {#other-examples-guides} + +Nós o encorajamos a conferir nosso [início rápido](https://docs.kurtosis.com/quickstart) (onde você construirá um banco de dados Postgres e uma API sobre ele) e nossos outros exemplos em nosso [repositório awesome-kurtosis](https://github.com/kurtosis-tech/awesome-kurtosis) onde você encontrará ótimos exemplos, incluindo pacotes para: + +- [Iniciar a mesma rede de teste local do Ethereum](https://github.com/kurtosis-tech/eth2-package), mas com serviços adicionais conectados, como um spammer de transações (para simular transações), um monitor de bifurcação e uma instância conectada do Grafana e do Prometheus +- Executar um [teste de sub-rede](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/ethereum-network-partition-test) na mesma rede Ethereum local diff --git a/public/content/translations/pt-br/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/index.md b/public/content/translations/pt-br/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/index.md index 1772d38da05..664674597b9 100644 --- a/public/content/translations/pt-br/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/index.md +++ b/public/content/translations/pt-br/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/index.md @@ -1,60 +1,55 @@ --- title: "Reduzir contratos para combater o limite de tamanho do contrato" -description: O que você pode fazer para evitar que seus contratos inteligentes fiquem muito grandes? +description: "O que você pode fazer para evitar que seus contratos inteligentes se tornem muito grandes?" author: Markus Waas lang: pt-br -tags: - - "solidez" - - "smart contracts" - - "armazenamento" +tags: [ "Solidity", "smart contracts", "armazenamento" ] skill: intermediate published: 2020-06-26 source: soliditydeveloper.com sourceUrl: https://soliditydeveloper.com/max-contract-size --- -## Por que há um limite? {#why-is-there-a-limit} +## Por que existe um limite? {#why-is-there-a-limit} -Em [22 de novembro de 2016](https://blog.ethereum.org/2016/11/18/hard-fork-no-4-spurious-dragon) o fork Spurius Dragon introduziu a [EIP-170](https://eips.ethereum.org/EIPS/eip-170) que adicionou um limite de tamanho do contrato inteligente de 24.576 kb. Para você como desenvolvedor de Solidity isso significa que quando você adiciona mais e mais funcionalidade ao seu contrato, em algum momento você alcançará o limite e quando implantado verá o erro: +Em [22 de novembro de 2016](https://blog.ethereum.org/2016/11/18/hard-fork-no-4-spurious-dragon/), o hard-fork Spurious Dragon introduziu o [EIP-170](https://eips.ethereum.org/EIPS/eip-170), que adicionou um limite de tamanho de contrato inteligente de 24.576 kb. Para você, como um desenvolvedor de Solidity, isso significa que, quando você adiciona cada vez mais funcionalidades ao seu contrato, em algum momento você atingirá o limite e, ao implantar, verá o erro: -`Aviso: O código do contrato excede 24576 bytes (um limite introduzido no Dragão Purioso). This contract may not be deployable on Mainnet. Considere habilitar o otimizador (com um valor baixo de "execução"!), desligar as strings de reverter ou usar bibliotecas.` +`Warning: Contract code size exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries.` -Este limite foi introduzido para impedir ataques de negação de serviço (DOS). Qualquer apelo a um contrato é relativamente barato. No entanto, o impacto de uma chamada de contrato para os nós da Ethereum aumenta de forma desproporcionada, dependendo do tamanho do código do contrato chamado (lendo o código do disco, pré-processando o código, adicionando dados à prova de Merkle). Sempre que você tiver uma situação em que o agressor requer poucos recursos para causar muito trabalho para os outros, você tem o potencial para ataques DOS. +Este limite foi introduzido para evitar ataques de negação de serviço (denial-of-service, DOS). Qualquer chamada para um contrato é relativamente barata em termos de gás. No entanto, o impacto de uma chamada de contrato para os nós do Ethereum aumenta desproporcionalmente, dependendo do tamanho do código do contrato chamado (leitura do código do disco, pré-processamento do código, adição de dados à prova de Merkle). Sempre que você tiver uma situação em que o invasor requer poucos recursos para causar muito trabalho para outros, você tem o potencial para ataques de DOS. -Originalmente, tratava-se de um problema menor, porque um limite de tamanho natural do contrato é o limite de gas por bloco. Obviamente, um contrato precisa ser implementado dentro de uma transação que tenha todo o bytecode do contrato. Se você incluir apenas essa transação em um bloco, você pode usar todo esse gas, mas não é infinito. Desde a [London Upgrade](/ethereum-forks/#london), o limite de gas de bloco tem sido capaz de variar entre 15M e 30M de unidades, de acordo com a demanda da rede. +Originalmente, isso era um problema menor porque um limite de tamanho de contrato natural é o limite de gás do bloco. Obviamente, um contrato deve ser implantado dentro de uma transação que contenha todo o bytecode do contrato. Se você incluir apenas essa transação em um bloco, poderá usar todo esse gás, mas não é infinito. Desde a [Atualização London](/ethereum-forks/#london), o limite de gás do bloco tem variado entre 15 e 30 milhões de unidades, dependendo da demanda da rede. -A seguir, analisaremos alguns métodos ordenados pelo seu potencial impacto. Pense nisso em termos de perda de peso. A melhor estratégia para alguém atingir o seu peso alvo (no nosso caso 24kb) é concentrar-se primeiro nos grandes métodos de impacto. Na maioria dos casos, só de ajustar a sua dieta já ajudará, mas às vezes é necessário de um pouco mais. Então você pode adicionar algum exercício (impacto médio) ou até suplementos (impacto pequeno). +A seguir, veremos alguns métodos ordenados por seu potencial impacto. Pense nisso em termos de perda de peso. A melhor estratégia para alguém atingir seu peso-alvo (em nosso caso, 24 kb) é focar primeiro nos métodos de grande impacto. Na maioria dos casos, apenas ajustar sua dieta o levará lá, mas às vezes você precisa de um pouco mais. Então você pode adicionar algum exercício (impacto médio) ou até mesmo suplementos (pequeno impacto). ## Grande impacto {#big-impact} -### Separe os seus contratos {#separate-your-contracts} +### Separe seus contratos {#separate-your-contracts} -Esta deve ser sempre sua primeira abordagem. Como você pode separar o contrato em vários contratos menores? Geralmente isso te força a criar uma boa arquitetura para seus contratos. Os contratos menores são sempre preferidos por uma perspectiva de legibilidade de código. Para dividir contratos, pergunte a si mesmo: +Essa deve ser sempre sua primeira abordagem. Como você pode separar o contrato em vários outros menores? Geralmente, isso o força a criar uma boa arquitetura para seus contratos. Contratos menores são sempre preferíveis do ponto de vista da legibilidade do código. Para dividir contratos, pergunte-se: -- Quais as funções que devem estar juntas? Cada conjunto de funções pode ser o melhor em seu próprio contrato. -- Que funções não requerem leitura do estado do contrato ou apenas um subconjunto específico do estado? +- Quais funções pertencem umas às outras? Cada conjunto de funções pode funcionar melhor em seu próprio contrato. +- Quais funções não exigem a leitura do estado do contrato ou apenas um subconjunto específico do estado? - Você pode dividir o armazenamento e a funcionalidade? ### Bibliotecas {#libraries} -Uma maneira simples de mover o código de funcionalidade para longe do armazenamento é usando [uma biblioteca](https://solidity.readthedocs.io/en/v0.6.10/contracts.html#libraries). Não declarar as funções da biblioteca como internas, como essas, serão [adicionadas ao contrato](https://ethereum.stackexchange.com/questions/12975/are-internal-functions-in-libraries-not-covered-by-linking) diretamente durante a compilação. Mas se usarmos funções públicas, elas estarão então de fato, num contrato separado de biblioteca. Considere [o uso de](https://solidity.readthedocs.io/en/v0.6.10/contracts.html#using-for) para fazer o uso de bibliotecas mais convenientes. +Uma maneira simples de mover o código de funcionalidade para longe do armazenamento é usando uma [biblioteca](https://solidity.readthedocs.io/en/v0.6.10/contracts.html#libraries). Não declare as funções da biblioteca como `internal`, pois elas serão [adicionadas ao contrato](https://ethereum.stackexchange.com/questions/12975/are-internal-functions-in-libraries-not-covered-by-linking) diretamente durante a compilação. Mas se você usar funções públicas, elas estarão de fato em um contrato de biblioteca separado. Considere usar [using for](https://solidity.readthedocs.io/en/v0.6.10/contracts.html#using-for) para tornar o uso de bibliotecas mais conveniente. ### Proxies {#proxies} -Uma estratégia mais avançada seria um sistema de procuração. As bibliotecas usam `DELEGATECALL` na parte traseira, que simplesmente executa a função de outro contrato com o estado do contrato de chamada. Confira [esta postagem no blog](https://hackernoon.com/how-to-make-smart-contracts-upgradable-2612e771d5a2) para saber mais sobre sistemas de proxy. Eles lhe dão mais funcionalidade, por exemplo, permitem a atualização, mas também adicionam muita complexidade. Eu não adicionaria aquelas apenas para reduzir os tamanhos dos contratos, a menos que fosse a sua única opção por qualquer motivo. +Uma estratégia mais avançada seria um sistema de proxy. As bibliotecas usam `DELEGATECALL` nos bastidores, o que simplesmente executa a função de outro contrato com o estado do contrato que está chamando. Confira [esta postagem do blog](https://hackernoon.com/how-to-make-smart-contracts-upgradable-2612e771d5a2) para saber mais sobre sistemas de proxy. Eles dão a você mais funcionalidade, por exemplo, eles permitem a capacidade de atualização, mas também adicionam muita complexidade. Eu não os adicionaria apenas para reduzir o tamanho dos contratos, a menos que seja sua única opção por algum motivo. -## Médio impacto {#medium-impact} +## Impacto médio {#medium-impact} -### Remover funções {#remove-functions} +### Remova funções {#remove-functions} -Este deveria ser óbvio. Funções aumentam um pouco o tamanho de um contrato. +Isso deve ser óbvio. As funções aumentam um pouco o tamanho de um contrato. -- **Externo**: Frequentemente adicionamos muitas funções de exibição por motivos de conveniência. Está perfeitamente tudo bem até que você atinja o limite de tamanho. Então talvez queiram realmente pensar na eliminação de todos que não os absolutamente essenciais. -- **Interno**: Você também pode remover funções internas/privadas e simplesmente inserir o código, desde que a função seja chamada apenas uma vez. +- **Externas**: muitas vezes, adicionamos muitas funções de visualização por conveniência. Isso é perfeitamente normal até você atingir o limite de tamanho. Então, você pode querer realmente pensar em remover todas, exceto as absolutamente essenciais. +- **Internas**: você também pode remover funções internas/privadas e simplesmente embutir o código, desde que a função seja chamada apenas uma vez. -### Evitar variáveis adicionais {#avoid-additional-variables} - -Uma mudança simples assim: +### Evite variáveis adicionais {#avoid-additional-variables} ```solidity function get(uint id) returns (address,address) { @@ -69,24 +64,23 @@ function get(uint id) returns (address,address) { } ``` -faz diferença de **0.28kb**. Você pode encontrar muitas situações semelhantes nos seus contratos e isso pode realmente somar quantias significativas. +Uma simples alteração como essa faz uma diferença de **0.28kb**. É provável que você encontre muitas situações semelhantes em seus contratos e elas podem realmente somar valores significativos. -### Encurtar mensagem de erro {#shorten-error-message} +### Encurte as mensagens de erro {#shorten-error-message} -Mensagens de reversão longa e, em particular, muitas mensagens de reversão diferentes podem bloquear o contrato. Em vez disso, use códigos de erro curtos e decodifique-os no contrato. Uma mensagem longa poderia ser muito mais curta: +Mensagens de reversão longas e, em particular, muitas mensagens de reversão diferentes podem inchar o contrato. Em vez disso, use códigos de erro curtos e decodifique-os em seu contrato. Uma mensagem longa pode se tornar muito mais curta: ```solidity require(msg.sender == owner, "Only the owner of this contract can call this function"); - ``` ```solidity require(msg.sender == owner, "OW1"); ``` -### Use erros personalizados ao invés de mensagens de erro +### Use erros personalizados em vez de mensagens de erro -Erros personalizados foram introduzidos no [Solidity 0.8.4](https://blog.soliditylang.org/2021/04/21/custom-errors/). Eles são uma ótima maneira de reduzir o tamanho de seus contratos, porque são codificados por ABI como seletores (assim como as funções são). +Erros personalizados foram introduzidos no [Solidity 0.8.4](https://blog.soliditylang.org/2021/04/21/custom-errors/). Eles são uma ótima maneira de reduzir o tamanho de seus contratos, porque são codificados pela ABI como seletores (assim como as funções). ```solidity error Unauthorized(); @@ -96,15 +90,15 @@ if (msg.sender != owner) { } ``` -### Considere um valor de baixa execução no otimizador {#consider-a-low-run-value-in-the-optimizer} +### Considere um valor baixo de execução no otimizador {#consider-a-low-run-value-in-the-optimizer} -Você também pode alterar as configurações do otimizador. O valor padrão de 200 significa que está tentando otimizar o bytecode como se uma função fosse chamada 200 vezes. Se você alterá-lo para 1, basicamente diga ao otimizador para otimizar em caso de executar cada função apenas uma vez. Uma função otimizada para rodar apenas uma vez significa que ela é otimizada para a própria implantação. Esteja ciente de que **isso aumenta o custo do [gás](/developers/docs/gas/) por executar as funções**, então você pode querer não otimizá-la. +Você também pode alterar as configurações do otimizador. O valor padrão de 200 significa que ele está tentando otimizar o bytecode como se uma função fosse chamada 200 vezes. Se você alterá-lo para 1, basicamente diz ao otimizador para otimizar para o caso de executar cada função apenas uma vez. Uma função otimizada para ser executada apenas uma vez significa que ela é otimizada para a própria implantação. Esteja ciente de que **isso aumenta os [custos de gás](/developers/docs/gas/) para executar as funções**, então talvez você não queira fazer isso. ## Pequeno impacto {#small-impact} -### Evite passar instruções para funções {#avoid-passing-structs-to-functions} +### Evite passar structs para funções {#avoid-passing-structs-to-functions} -Se você estiver usando o [ABIEncoderV2](https://solidity.readthedocs.io/en/v0.6.10/layout-of-source-files.html#abiencoderv2), ele pode ajudar a não passar de structs para uma função. Em vez de passar o parâmetro como uma estrutura... +Se você estiver usando o [ABIEncoderV2](https://solidity.readthedocs.io/en/v0.6.10/layout-of-source-files.html#abiencoderv2), pode ajudar não passar structs para uma função. Em vez de passar o parâmetro como um struct, passe os parâmetros necessários diretamente. Neste exemplo, economizamos mais **0.1kb**. ```solidity function get(uint id) returns (address,address) { @@ -126,16 +120,14 @@ function _get(address addr1, address addr2) private view returns(address,address } ``` -... passe os parâmetros necessários diretamente. Neste exemplo, salvamos outro **0.1kb**. - -### Declarar a visibilidade correta para funções e variáveis {#declare-correct-visibility-for-functions-and-variables} +### Declare a visibilidade correta para funções e variáveis {#declare-correct-visibility-for-functions-and-variables} -- Funções ou variáveis que são chamadas apenas do lado de fora? Declará-las como `externas` em vez de `públicas`. -- Funções ou variáveis apenas chamadas dentro do contrato? Declará-las como `private` ou `internal` em vez de `public`. +- Funções ou variáveis que são chamadas apenas de fora? Declare-as como `external` em vez de `public`. +- Funções ou variáveis chamadas apenas de dentro do contrato? Declare-as como `private` ou `internal` em vez de `public`. -### Remover modificadores {#remove-modifiers} +### Remova modificadores {#remove-modifiers} -Os modificadores, especialmente quando usados intencionalmente, podem ter um impacto significativo no tamanho do contrato. Considere removê-los e, em vez disso, usar funções. +Modificadores, especialmente quando usados intensamente, podem ter um impacto significativo no tamanho do contrato. Considere removê-los e, em vez disso, usar funções. ```solidity modifier checkStuff() {} @@ -149,4 +141,4 @@ function checkStuff() private {} function doSomething() { checkStuff(); } ``` -Essas dicas devem ajudá-lo a reduzir significativamente o tamanho do contrato. Mais uma vez, nunca é demais salientar que se foca sempre na divisão dos contratos, se possível para o maior impacto. +Essas dicas devem ajudá-lo a reduzir significativamente o tamanho do contrato. Mais uma vez, não custa reforçar: sempre se concentre em dividir os contratos, se possível, para obter o maior impacto. diff --git a/public/content/translations/pt-br/developers/tutorials/eip-1271-smart-contract-signatures/index.md b/public/content/translations/pt-br/developers/tutorials/eip-1271-smart-contract-signatures/index.md index fd950d155e5..a3e2ce0f281 100644 --- a/public/content/translations/pt-br/developers/tutorials/eip-1271-smart-contract-signatures/index.md +++ b/public/content/translations/pt-br/developers/tutorials/eip-1271-smart-contract-signatures/index.md @@ -1,20 +1,22 @@ --- title: "EIP-1271: Assinatura e verificação de contratos inteligentes" -description: Uma visão geral de geração de assinatura de contratos inteligentes e verificação com a EIP-1271. Também passaremos pela implementação da EIP-1271 usada no Safe (anteriormente Gnosis Safe) para fornecer um exemplo concreto de contrato inteligente para que desenvolvedores possam construir por cima dele. +description: "Uma visão geral de geração de assinatura de contratos inteligentes e verificação com a EIP-1271. Também passaremos pela implementação da EIP-1271 usada no Safe (anteriormente Gnosis Safe) para fornecer um exemplo concreto de contrato inteligente para que desenvolvedores possam construir por cima dele." author: Nathan H. Leung lang: pt-br tags: - - "eip-1271" - - "contratos inteligentes" - - "verificando" - - "assinatura" + [ + "eip-1271", + "smart contracts", + "verificando", + "signing" + ] skill: intermediate published: 2023-01-12 --- -A norma [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) permite a contratos inteligentes verificarem assinaturas. +O padrão [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) permite que contratos inteligentes verifiquem assinaturas. -Neste tutorial, forneceremos uma visão geral das assinaturas digitais, noções básicas sobre a EIP-1271, e a implementação específica da EIP-1271 usada pelo [Safe](https://safe.global/) (previamente Gnosis Safe). Tudo isso pode servir como ponto de partida para a implementação da EIP-1271 nos seus próprios contratos. +Neste tutorial, damos uma visão geral de assinaturas digitais, o histórico do EIP-1271 e a implementação específica do EIP-1271 usada pelo [Safe](https://safe.global/) (anteriormente Gnosis Safe). Tudo isso pode servir como ponto de partida para a implementação da EIP-1271 nos seus próprios contratos. ## O que é assinatura? @@ -24,7 +26,7 @@ Por exemplo, uma assinatura digital pode se parecer com isto: 1. Mensagem: “Quero me conectar a este website com minha carteira Ethereum.” 2. Assinante: Meu endereço é `0x000…` -3. Prova: Aqui está uma prova de que eu, `0x000…`, realmente criei esta mensagem inteira (isto é geralmente algo criptográfico). +3. Prova: aqui está uma prova de que eu, `0x000…`, realmente criei esta mensagem inteira (geralmente é algo criptográfico). É importante observar que uma assinatura digital inclui ambos, uma “mensagem” e uma “assinatura”. @@ -36,11 +38,11 @@ Da mesma maneira, uma assinatura digital não significa nada sem uma mensagem as Para criar uma assinatura digital para uso em blockchains baseados em Ethereum, você geralmente precisa de uma chave secreta que ninguém mais conhece. Isto é o que faz sua assinatura, sua (ninguém mais pode criar a mesma assinatura sem o conhecimento da chave secreta). -Sua conta Ethereum (ou seja, conta de propriedade externa / EOA) tem uma chave privada associada a ela quando um website ou dapp pergunta por sua assinatura (por exemplo: “Log in with Ethereum”). +Sua conta Ethereum (ou seja, sua conta de propriedade externa/EOA) tem uma chave privada associada a ela, e essa é a chave privada que normalmente é usada quando um site ou dapp solicita sua assinatura (por exemplo, para “Fazer login com a Ethereum”). -Um app pode [verificar uma assinatura](https://docs.alchemy.com/docs/how-to-verify-a-message-signature-on-ethereum) que você criou usando uma biblioteca de terceiros, como ethers.js [sem conhecer sua chave privada](https://en.wikipedia.org/wiki/Public-key_cryptography) e estar confiante de que foi _você_ quem criou a assinatura. +Um aplicativo pode [verificar uma assinatura](https://www.alchemy.com/docs/how-to-verify-a-message-signature-on-ethereum) que você cria usando uma biblioteca de terceiros como o ethers.js [sem saber sua chave privada](https://en.wikipedia.org/wiki/Public-key_cryptography) e ter a certeza de que foi _você_ quem criou a assinatura. -> De fato, como as assinaturas digitais EOA usam criptografia de chave pública, elas podem ser geradas e verificadas **off-chain**! É assim que a votação em DAO sem gás funciona — em vez de submeter votos on-chain, as assinaturas digitais podem ser criadas e verificadas off-chain usando bibliotecas criptográficas. +> Na verdade, como as assinaturas digitais de EOA usam criptografia de chave pública, elas podem ser geradas e verificadas **fora da cadeia**! É assim que a votação em DAO sem gás funciona — em vez de enviar votos na cadeia, as assinaturas digitais podem ser criadas e verificadas fora da cadeia usando bibliotecas criptográficas. Enquanto as contas EOA têm uma chave privada, as contas de contrato inteligente não têm nenhum tipo de chave privada ou secreta (portanto, “Entrar com Ethereum”, etc. não pode funcionar nativamente com contas de contratos inteligentes). @@ -50,17 +52,17 @@ O problema que a EIP-1271 visa resolver: como podemos dizer que uma assinatura d Contratos inteligentes não têm chaves privadas que possam ser usadas para assinar mensagens. Então, como podemos saber se uma assinatura é autêntica? -Bem, uma ideia é que podemos _perguntar_ ao contrato inteligente se uma assinatura é autêntica! +Bem, uma ideia é que podemos simplesmente _perguntar_ ao contrato inteligente se uma assinatura é autêntica! O que o EIP-1271 faz é padronizar a ideia de "perguntar" ao contrato inteligente se uma dada assinatura é válida. -Um contrato que implementa EIP-1271 deve ter uma função chamada `isValidSignature` que recebe a mensagem e a assinatura. O contrato pode então executar alguma lógica de validação (a especificação não força nada específico aqui) e então retornar um valor indicando se a assinatura é válida ou não. +Um contrato que implementa o EIP-1271 deve ter uma função chamada `isValidSignature` que recebe uma mensagem e uma assinatura. O contrato pode então executar alguma lógica de validação (a especificação não força nada específico aqui) e então retornar um valor indicando se a assinatura é válida ou não. -Se `isValidSignature` retornar um resultado válido, isso é basicamente o contrato dizendo “sim, eu aprovo esta assinatura + mensagem!” +Se `isValidSignature` retornar um resultado válido, é basicamente o contrato dizendo: “sim, eu aprovo esta assinatura + mensagem!” ### Interface -Aqui está a interface exata na especificação da EIP-1271 (falaremos sobre o parâmetro `_hash` abaixo, mas por enquanto, pense nele como a mensagem que está sendo verificada): +Aqui está a interface exata na especificação do EIP-1271 (falaremos sobre o parâmetro `_hash` abaixo, mas, por enquanto, pense nele como a mensagem que está sendo verificada): ```jsx pragma solidity ^0.5.0; @@ -71,13 +73,13 @@ contract ERC1271 { bytes4 constant internal MAGICVALUE = 0x1626ba7e; /** - * @dev Should return whether the signature provided is valid for the provided hash - * @param _hash Hash of the data to be signed - * @param _signature Signature byte array associated with _hash + * @dev Deve retornar se a assinatura fornecida é válida para o hash fornecido + * @param _hash Hash dos dados a serem assinados + * @param _signature Array de bytes de assinatura associado a _hash * - * MUST return the bytes4 magic value 0x1626ba7e when function passes. - * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5) - * MUST allow external calls + * DEVE retornar o valor mágico bytes4 0x1626ba7e quando a função for bem-sucedida. + * NÃO DEVE modificar o estado (usando STATICCALL para solc < 0.5, modificador view para solc > 0.5) + * DEVE permitir chamadas externas */ function isValidSignature( bytes32 _hash, @@ -90,28 +92,28 @@ contract ERC1271 { ## Exemplo de implementação da EIP-1271: Safe -Os contratos podem implementar `isValidSignature` de várias maneiras — a especificação somente não diz muito sobre a implementação exata. +Os contratos podem implementar `isValidSignature` de muitas maneiras — a especificação não diz muito sobre a implementação exata. Um contrato importante que implementa a EIP-1271 é o Safe (anteriormente Gnosis Safe). -No código do Safe, `isValidSignature` [ é implementada](https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/CompatibilityFallbackHandler.sol) para que assinaturas possam ser criadas e verificadas de [duas maneiras](https://ethereum.stackexchange.com/questions/122635/signing-messages-as-a-gnosis-safe-eip1271-support): +No código do Safe, `isValidSignature` [é implementado](https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/CompatibilityFallbackHandler.sol) para que as assinaturas possam ser criadas e verificadas de [duas maneiras](https://ethereum.stackexchange.com/questions/122635/signing-messages-as-a-gnosis-safe-eip1271-support): -1. Mensagens on-chain - 1. Criação: um proprietário Safe cria uma nova transação Safe para “assinar” a mensagem, passando a mensagem como um dado na transação. Uma vez que proprietários suficientes assinam a transação para alcançar o limite multisig, a transação é enviada e executada. Na transação, há uma função Safe chamada, que adiciona a mensagem à lista de mensagens “aprovadas”. - 2. Verificação: chame `isValidSignature` no contrato Safe, e transmita a mensagem para verificar enquanto parâmetro da mensagem e [ um parâmetro vazio como parâmetro da assinatura](https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/CompatibilityFallbackHandler.sol#L32) (i.e., `0x`). O Safe verá que o parâmetro da assinatura está vazio e, em vez de verificar a assinatura criptograficamente, ele saberá que deve prosseguir e verificar se a mensagem está na lista de mensagens “aprovadas”. -2. Mensagens off-chain: - 1. Criação: um proprietário Safe cria uma mensagem off-chain, e então consegue outros proprietários Safe para assinar a mensagem, cada um individualmente, até que haja assinaturas suficientes para conseguir a aprovação pelo limite do multisig. - 2. Verificação: chama `isValidSignature`. No parâmetro da mensagem, passa a mensagem para ser verificada. No parâmetro da assinatura, passa cada assinatura individual de proprietário Safe todas concatenadas juntas. O Safe irá checar que há assinaturas suficientes para atingir o limite **e** que cada assinatura é válida. Acontecendo isso, ele retornará um valor indicando verificação da assinatura com sucesso. +1. Mensagens na cadeia + 1. Criação: um proprietário Safe cria uma nova transação Safe para “assinar” a mensagem, passando a mensagem como um dado na transação. Uma vez que proprietários suficientes assinam a transação para alcançar o limite multisig, a transação é enviada e executada. Na transação, há uma função do Safe chamada (`signMessage(bytes calldata _data)`) que adiciona a mensagem a uma lista de mensagens “aprovadas”. + 2. Verificação: chame `isValidSignature` no contrato Safe e passe a mensagem a ser verificada como o parâmetro da mensagem e [um valor vazio para o parâmetro da assinatura](https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/CompatibilityFallbackHandler.sol#L32) (ou seja, `0x`). O Safe verá que o parâmetro da assinatura está vazio e, em vez de verificar a assinatura criptograficamente, ele saberá que deve prosseguir e verificar se a mensagem está na lista de mensagens “aprovadas”. +2. Mensagens fora da cadeia: + 1. Criação: um proprietário do Safe cria uma mensagem fora da cadeia, em seguida, faz com que outros proprietários do Safe assinem a mensagem individualmente, até que haja assinaturas suficientes para atingir o limite de aprovação da multisig. + 2. Verificação: chame `isValidSignature`. No parâmetro da mensagem, passa a mensagem para ser verificada. No parâmetro da assinatura, passa cada assinatura individual de proprietário Safe todas concatenadas juntas. O Safe verificará se há assinaturas suficientes para atingir o limite **e** se cada assinatura é válida. Acontecendo isso, ele retornará um valor indicando verificação da assinatura com sucesso. ## O que é exatamente o parâmetro `_hash`? Por que não passar a mensagem inteira? -Você pode ter notado que a função `isValidSignature` na interface [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) não pega a mensagem propriamente dita, mas, em vezés disso, um parâmetro `_hash`. O que isto significa é que ao invés de passar a mensagem inteira de tamanho arbitrário para `isValidSignature`, nós passamos um hash de 32-bytes da mensagem (geralmente keccak256). +Você deve ter notado que a função `isValidSignature` na [interface do EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) não recebe a mensagem em si, mas sim um parâmetro `_hash`. O que isso significa é que, em vez de passar a mensagem completa de tamanho arbitrário para `isValidSignature`, nós passamos um hash de 32 bytes da mensagem (geralmente keccak256). -Cada byte de calldata — ou seja, dados de parâmetro da função passados para uma função de contrato inteligente — [custa16 gás (4 gás se zero byte)](https://eips.ethereum.org/EIPS/eip-2028), então, isso pode economizar um monte de gás se a mensagem for longa. +Cada byte de calldata — ou seja, dados de parâmetro de função passados para uma função de contrato inteligente — [custa 16 de gás (4 de gás se for um byte zero)](https://eips.ethereum.org/EIPS/eip-2028), então isso pode economizar muito gás se uma mensagem for longa. ### Especificações EIP-1271 anteriores -Existem outras especificações EIP-1271 por aí, que têm uma função `isValidSignature` com um primeiro parâmetro do tipo `bytes` (tamanho arbitrário, em vez de tamanho fixo `bytes32`) e nome de parâmetro `message`. Essa é uma [versão mais antiga](https://github.com/safe-global/safe-contracts/issues/391#issuecomment-1075427206) da norma EIP-1271. +Existem especificações EIP-1271 por aí que têm uma função `isValidSignature` com um primeiro parâmetro do tipo `bytes` (comprimento arbitrário, em vez de um `bytes32` de comprimento fixo) e o nome de parâmetro `message`. Esta é uma [versão mais antiga](https://github.com/safe-global/safe-contracts/issues/391#issuecomment-1075427206) do padrão EIP-1271. ## Como o EIP-1271 poderia ser implementado nos meus próprios contratos? @@ -124,4 +126,4 @@ No final, depende de você, como desenvolvedor do contrato! ## Conclusão -A [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) é uma norma versátil que permite contratos inteligentes verificar assinaturas. Ele abre a porta para contratos inteligentes que funcionam mais como EOAs - por exemplo fornecendo uma maneira de se "conectar via Ethereum" para trabalhar com contratos inteligentes - e ele pode ser implementado de várias maneiras (Safe tendo uma implementação interessante e não trivial a se considerar). +O [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) é um padrão versátil que permite que contratos inteligentes verifiquem assinaturas. Ele abre a porta para contratos inteligentes que funcionam mais como EOAs - por exemplo fornecendo uma maneira de se "conectar via Ethereum" para trabalhar com contratos inteligentes - e ele pode ser implementado de várias maneiras (Safe tendo uma implementação interessante e não trivial a se considerar). diff --git a/public/content/translations/pt-br/developers/tutorials/erc-721-vyper-annotated-code/index.md b/public/content/translations/pt-br/developers/tutorials/erc-721-vyper-annotated-code/index.md index b782878b951..ea4bb6c680f 100644 --- a/public/content/translations/pt-br/developers/tutorials/erc-721-vyper-annotated-code/index.md +++ b/public/content/translations/pt-br/developers/tutorials/erc-721-vyper-annotated-code/index.md @@ -1,31 +1,34 @@ --- -title: "Passo a passo do contrato Vyper ERC-721" -description: Ryuya Nakamura's ERC-721 contrato e como funciona +title: "Passo a passo do Contrato Vyper ERC-721" +description: Contrato ERC-721 de Ryuya Nakamura e como ele funciona author: Ori Pomerantz lang: pt-br -tags: - - "vyper" - - "erc-721" - - "python" +tags: [ "Vyper", "erc-721", "Python" ] skill: beginner published: 2021-04-01 --- ## Introdução {#introduction} -O [ERC-721](/developers/docs/standards/tokens/erc-721/) padrão é usado para manter a propriedade de tokens não fungíveis (NFT). [ERC-20](/developers/docs/standards/tokens/erc-20/) os tokens se comportam como uma mercadoria, porque não há diferença entre os totens individuais. Em contraste com isso, ERC-721 tokens são projetados para ativos semelhantes, mas não idênticos, como diferentes [cat cartoons](https://www.cryptokitties.co/) ou títulos de diferentes imóveis. +O padrão [ERC-721](/developers/docs/standards/tokens/erc-721/) é usado para manter a propriedade de Tokens Não Fungíveis (NFT). +Os tokens [ERC-20](/developers/docs/standards/tokens/erc-20/) se comportam como uma commodity, porque não há diferença entre tokens individuais. +Em contraste com isso, os tokens ERC-721 são projetados para ativos que são semelhantes, mas não idênticos, como diferentes [desenhos de gatos](https://www.cryptokitties.co/) +ou títulos para diferentes peças de imóveis. -Neste artigo, vamos analisar o [contrato ERC-721 de Ryuya Nakamura](https://github.com/vyperlang/vyper/blob/master/examples/tokens/ERC721.vy). Este contrato é escrito em [Vyper](https://vyper.readthedocs.io/en/latest/index.html), a Python-like linguagem de contrato projetada para tornar é mais difícil escrever código inseguro do que na solidez. +Neste artigo, analisaremos o [contrato ERC-721 de Ryuya Nakamura](https://github.com/vyperlang/vyper/blob/master/examples/tokens/ERC721.vy). +Este contrato é escrito em [Vyper](https://vyper.readthedocs.io/en/latest/index.html), uma linguagem de contrato semelhante ao Python, projetada para tornar mais difícil escrever código inseguro do que em Solidity. ## O Contrato {#contract} ```python -# @dev Implementation of ERC-721 non-fungible token standard. +# @dev Implementação do padrão de token não fungível ERC-721. # @author Ryuya Nakamura (@nrryuya) -# Modified from: https://github.com/vyperlang/vyper/blob/de74722bf2d8718cca46902be165f9fe0e3641dd/examples/tokens/ERC721.vy +# Modificado de: https://github.com/vyperlang/vyper/blob/de74722bf2d8718cca46902be165f9fe0e3641dd/examples/tokens/ERC721.vy ``` -Comentários em Vyper, como em Python, começam com um hash (`#`) e continuam até o final da linha. Comentários que incluem `@` são usados ​​por [NatSpec](https://vyper.readthedocs.io/en/latest/natspec.html) para produzir documentação legível para humanos. +Comentários em Vyper, como em Python, começam com um hash (`#`) e continuam até o final da linha. Comentários que incluem +`@` são usados pelo [NatSpec](https://vyper.readthedocs.io/en/latest/natspec.html) para produzir documentação legível +por humanos. ```python from vyper.interfaces import ERC721 @@ -33,155 +36,192 @@ from vyper.interfaces import ERC721 implements: ERC721 ``` -A interface ERC-721 é construída na linguagem Vyper. [você pode ver o código definido aqui](https://github.com/vyperlang/vyper/blob/master/vyper/builtin_interfaces/ERC721.py). A definição da interface é escrita em Python, em vez de Vyper, porque as interfaces são usadas não apenas dentro da blockchain, mas também ao enviar à blockchain uma transação de um cliente externo, que pode ser escrito em Python. +A interface ERC-721 é integrada à linguagem Vyper. +[Você pode ver a definição do código aqui](https://github.com/vyperlang/vyper/blob/master/vyper/builtin_interfaces/ERC721.py). +A definição da interface é escrita em Python, em vez de Vyper, porque as interfaces são usadas não apenas dentro da +blockchain, mas também ao enviar uma transação para a blockchain a partir de um cliente externo, que pode ser escrito em +Python. -A primeira linha importa a ‘interface’, e o segundo especifica o que estamos incrementando aqui. +A primeira linha importa a interface, e a segunda especifica que estamos implementando-a aqui. ### A interface ERC721Receiver {#receiver-interface} ```python -# Interface for the contract called by safeTransferFrom() +# Interface para o contrato chamado por safeTransferFrom() interface ERC721Receiver: def onERC721Received( ``` -ERC-721 suporta dois tipos de transferência: +O ERC-721 suporta dois tipos de transferência: -- ` transfere de `, que permite ao remetente especifique qualquer endereço de destino e coloca a responsabilidade para a transferência no remetente. Isso significa que você pode transferir para um endereço inválido, caso em que o NFT será perdido para sempre. -- `safeTransferFrom`, que verifica se o endereço de destino é um contrato. Se for assim, o contrato ERC-721 pergunta ao contrato receptor se deseja receber o NFT. +- `transferFrom`, que permite ao remetente especificar qualquer endereço de destino e coloca a responsabilidade + da transferência no remetente. Isso significa que você pode transferir para um endereço inválido, caso em que + o NFT é perdido para sempre. +- `safeTransferFrom`, que verifica se o endereço de destino é um contrato. Se for, o contrato ERC-721 + pergunta ao contrato receptor se ele quer receber o NFT. -Para responder ` transferência segura de ` solicita um recebimento contrato deve implementar `ERC721 recebedor `. +Para responder às solicitações de `safeTransferFrom`, um contrato de recebimento precisa implementar o `ERC721Receiver`. ```python _operator: address, _from: address, ``` -O endereço `_de ` é o proprietário atual do token. O endereço `_operador` é aquele que solicitou a transferência (esses dois podem não ser o mesmo devido às provisões). +O endereço `_from` é o proprietário atual do token. O endereço `_operator` é aquele que +solicitou a transferência (esses dois podem não ser os mesmos, por causa das permissões). ```python _tokenId: uint256, ``` -ERC-721 token IDs está 256 bits. Normalmente, elas são criados por meio de uma execução de hash da descrição que o token representa. +Os IDs de token ERC-721 são de 256 bits. Normalmente, eles são criados por hashing de uma descrição do que +o token representa. ```python _data: Bytes[1024] ``` -O requerimento pode ter até 1024 bytes de dados do usuário. +A solicitação pode ter até 1024 bytes de dados do usuário. ```python ) -> bytes32: view ``` -Para evitar casos em que um contrato acidentalmente aceita uma transferência o valor de retorno não é um booleano, mas 256 bits com um valor específico. +Para evitar casos em que um contrato aceite acidentalmente uma transferência, o valor de retorno não é um booleano, +mas 256 bits com um valor específico. Essa função é uma `view`, o que significa que pode ler o estado da blockchain, mas não modificá-lo. ### Eventos {#events} -Os [eventos](https://media.consensys.net/technical-introduction-to-events-and-logs-in-ethereum-a074d65dd61e) são emitidos para informar usuários e servidores fora da blockchain de eventos. Observe que o conteúdo dos eventos não está disponível para contratos na blockchain. +[Eventos](https://media.consensys.net/technical-introduction-to-events-and-logs-in-ethereum-a074d65dd61e) +são emitidos para informar usuários e servidores fora da blockchain sobre os eventos. Observe que o conteúdo dos eventos +não está disponível para contratos na blockchain. ```python -# @dev Emits when ownership of any NFT changes by any mechanism. This event emits when NFTs are -# created (`from` == 0) and destroyed (`to` == 0). Exception: during contract creation, any -# number of NFTs may be created and assigned without emitting Transfer. At the time of any -# transfer, the approved address for that NFT (if any) is reset to none. -# @param _from Sender of NFT (if address is zero address it indicates token creation). -# @param _to Receiver of NFT (if address is zero address it indicates token destruction). -# @param _tokenId The NFT that got transferred. +# @dev Emite quando a propriedade de qualquer NFT muda por qualquer mecanismo. Este evento é emitido quando os NFTs são +# criados (`from` == 0) e destruídos (`to` == 0). Exceção: durante a criação do contrato, qualquer +# número de NFTs pode ser criado e atribuído sem emitir Transfer. No momento de qualquer +# transferência, o endereço aprovado para esse NFT (se houver) é redefinido para nenhum. +# @param _from Remetente do NFT (se o endereço for o endereço zero, isso indica a criação do token). +# @param _to Receptor do NFT (se o endereço for o endereço zero, indica a destruição do token). +# @param _tokenId O NFT que foi transferido. event Transfer: sender: indexed(address) receiver: indexed(address) tokenId: indexed(uint256) ``` -Isso é similar para o evento ERC-20 Transfer, exceto que informamos um `tokenId` em vez de um valor. Ninguém possui o endereço zero, portanto, por convenção, o usamos para relatar a criação e a destruição de tokens. +Isso é semelhante ao evento Transfer do ERC-20, exceto que relatamos um `tokenId` em vez de um valor. +Ninguém é dono do endereço zero, então, por convenção, nós o usamos para relatar a criação e a destruição de tokens. ```python -# @dev This emits when the approved address for an NFT is changed or reaffirmed. The zero -# address indicates there is no approved address. When a Transfer event emits, this also -# indicates that the approved address for that NFT (if any) is reset to none. -# @param _owner Owner of NFT. -# @param _approved Address that we are approving. -# @param _tokenId NFT which we are approving. +# @dev Isto emite quando o endereço aprovado para um NFT é alterado ou reafirmado. O endereço +# zero indica que não há endereço aprovado. Quando um evento Transfer emite, isso também +# indica que o endereço aprovado para esse NFT (se houver) é redefinido para nenhum. +# @param _owner Proprietário do NFT. +# @param _approved Endereço que estamos aprovando. +# @param _tokenId NFT que estamos aprovando. event Approval: owner: indexed(address) approved: indexed(address) tokenId: indexed(uint256) ``` -Uma aprovação ERC-721 é semelhante a uma permissão ERC-20. Um endereço específico é autorizado a transferir um determinado símbolo. Isso fornece um mecanismo para os contratos responderem quando aceitam um token. Os contratos não podem ouvir os eventos, portanto, se você apenas transferir o token para eles, eles não “saberão” disso. Desta forma, primeiro, o proprietário envia uma aprovação e, em seguida, envia uma solicitação ao contrato: “Aprovei para você transferir o token X, faça…”. +Uma aprovação ERC-721 é semelhante a uma permissão ERC-20. Um endereço específico tem permissão para transferir um token +específico. Isso dá um mecanismo para os contratos responderem quando aceitam um token. Contratos não podem +escutar eventos, então se você apenas transferir o token para eles, eles não "sabem" sobre isso. Dessa forma, o +proprietário primeiro envia uma aprovação e, em seguida, envia uma solicitação ao contrato: "Eu aprovei que você transfira o token +X, por favor, faça ...". -Esse é o designe escolhido por fazer o ERC-721 padrão semelhante ao padrão ERC-20. Como os tokens ERC-721 não são fungíveis, um contrato também pode identificar que obteve um token específico olhando a propriedade do token. +Esta é uma escolha de design para tornar o padrão ERC-721 semelhante ao padrão ERC-20. Como +os tokens ERC-721 não são fungíveis, um contrato também pode identificar que obteve um token específico +observando a propriedade do token. ```python -# @dev This emits when an operator is enabled or disabled for an owner. The operator can manage -# all NFTs of the owner. -# @param _owner Owner of NFT. -# @param _operator Address to which we are setting operator rights. -# @param _approved Status of operator rights(true if operator rights are given and false if -# revoked). +# @dev Isto emite quando um operador é habilitado ou desabilitado para um proprietário. O operador pode gerenciar +# todos os NFTs do proprietário. +# @param _owner Proprietário do NFT. +# @param _operator Endereço para o qual estamos definindo os direitos do operador. +# @param _approved Status dos direitos do operador (verdadeiro se os direitos do operador forem concedidos e falso se +# revogado). event ApprovalForAll: owner: indexed(address) operator: indexed(address) approved: bool ``` -Às vezes, é útil ter um _operador_ que pode gerenciar todos os tokens da conta de um tipo específico (aqueles gerenciados por um contrato específico), semelhante a uma procuração. Por exemplo, eu posso querer dar tal poder a um contrato que verifica se Eu não tenho contatado ele por seis meses, e se assim for distribuo os meus bens aos meus herdeiros (se um deles o pedir, contrata não pode fazer nada sem ser chamado por uma transação). No ERC-20, podemos simplesmente atribuir uma provisão alta a um contrato de herança, mas isso não funciona para ERC-721, pois os tokens não são fungíveis. Isso é o equivalente. +Às vezes é útil ter um _operador_ que pode gerenciar todos os tokens de um tipo específico de uma conta (aqueles que são gerenciados por +um contrato específico), semelhante a uma procuração. Por exemplo, eu talvez queira dar esse poder a um contrato que verifica se +eu não o contatei por seis meses e, em caso afirmativo, distribui meus ativos para meus herdeiros (se um deles pedir, os contratos +não podem fazer nada sem serem chamados por uma transação). No ERC-20, podemos simplesmente dar uma alta permissão a um contrato de herança, +mas isso não funciona para o ERC-721 porque os tokens não são fungíveis. Este é o equivalente. -O valor `approved` nos informa se o evento é para uma aprovação ou a retirada de uma aprovação. +O valor `aprovado` nos diz se o evento é para uma aprovação ou a retirada de uma aprovação. -### Variáveis ​​de Estado {#state-vars} +### Variáveis de Estado {#state-vars} -Essas variáveis contêm o estado atual dos tokens: os quais estão disponíveis e a quem os possui. A maioria delas são objetos `HashMap`, [mapeamentos unidirecionais que existem entre dois tipos](https://vyper.readthedocs.io/en/latest/types.html#mappings). +Essas variáveis contêm o estado atual dos tokens: quais estão disponíveis e quem os possui. A maioria deles +são objetos `HashMap`, [mapeamentos unidirecionais que existem entre dois tipos](https://vyper.readthedocs.io/en/latest/types.html#mappings). ```python -# @dev Mapping from NFT ID to the address that owns it. +# @dev Mapeamento do ID do NFT para o endereço que o possui. idToOwner: HashMap[uint256, address] -# @dev Mapping from NFT ID to approved address. +# @dev Mapeamento do ID do NFT para o endereço aprovado. idToApprovals: HashMap[uint256, address] ``` -As identidades de usuários e contratos no Ethereum são representados por endereços de 160 bits. Essas duas variáveis mapeiam IDs de tokens para seus proprietários e aqueles aprovados a transferi-los (no máximo um para cada). No Ethereum, os dados não inicializados são sempre zero, pois, se não houver proprietário ou transferidor aprovado, o valor desse token será zero. +As identidades de usuários e contratos no Ethereum são representadas por endereços de 160 bits. Essas duas variáveis mapeiam +de IDs de token para seus proprietários e aqueles aprovados para transferi-los (no máximo um para cada). No Ethereum, +os dados não inicializados são sempre zero, então se não houver proprietário ou transferidor aprovado, o valor para aquele token +será zero. ```python -# @dev Mapping from owner address to count of his tokens. +# @dev Mapeamento do endereço do proprietário para a contagem de seus tokens. ownerToNFTokenCount: HashMap[address, uint256] ``` -Essa variável possui a contagem de tokens para cada proprietário. Não há mapeamento de proprietários para tokens, então, a única forma de identificar os tokens que um proprietário específico possui é olhar para trás no histórico de eventos da blockchain e ver os eventos `Transfer` apropriados. Podemos usar essa variável para saber quando temos todos os NFTs e não precisaremos mais olhar ainda mais no tempo. +Esta variável contém a contagem de tokens para cada proprietário. Não há mapeamento de proprietários para tokens, então +a única maneira de identificar os tokens que um proprietário específico possui é olhar para trás no histórico de eventos da blockchain +e ver os eventos `Transfer` apropriados. Podemos usar essa variável para saber quando temos todos os NFTs e não +precisamos procurar ainda mais no tempo. -Observe que esse algoritmo funciona apenas para interfaces do usuário e servidores externos. Código em execução na blockchain em si não pode ler eventos passados. +Note que este algoritmo funciona apenas para interfaces de usuário e servidores externos. Código rodando na blockchain +em si não pode ler eventos passados. ```python -# @dev Mapping from owner address to mapping of operator addresses. +# @dev Mapeamento de endereço de proprietário para mapeamento de endereços de operador. ownerToOperators: HashMap[address, HashMap[address, bool]] ``` -Uma conta pode ter mais de um único operador. Um simples `HashMap` é insuficiente para mantê-los, pois cada chave gera um único valor. Em vez disso, você pode usar `HashMap[address, bool]` como valor. Por padrão, o valor para cada endereço é `False`, o que significa que ele não é um operador. Você pode definir valores como `True` conforme necessário. +Uma conta pode ter mais de um único operador. Um simples `HashMap` é insuficiente para +rastreá-los, porque cada chave leva a um único valor. Em vez disso, você pode usar +`HashMap[address, bool]` como o valor. Por padrão, o valor para cada endereço é `False`, o que significa que ele +não é um operador. Você pode definir os valores como `True` conforme necessário. ```python -# @dev Address of minter, who can mint a token +# @dev Endereço do minter, que pode cunhar um token minter: address ``` -Novos tokens têm de ser criados de alguma forma. Neste contrato há uma única entidade que está autorizada a fazê-lo, o `minter`. É provável que isso seja suficiente para um jogo, por exemplo. Para outros propósitos, pode ser necessário criar uma lógica de negócio mais complicada. +Novos tokens precisam ser criados de alguma forma. Neste contrato, há uma única entidade que tem permissão para fazer isso, o +`minter`. Isso provavelmente é suficiente para um jogo, por exemplo. Para outros fins, pode ser necessário +criar uma lógica de negócios mais complicada. ```python -# @dev Mapping of interface id to bool about whether or not it's supported +# @dev Mapeamento do ID da interface para bool sobre se é ou não suportado supportedInterfaces: HashMap[bytes32, bool] -# @dev ERC165 interface ID of ERC165 +# @dev ID da interface ERC165 do ERC165 ERC165_INTERFACE_ID: constant(bytes32) = 0x0000000000000000000000000000000000000000000000000000000001ffc9a7 -# @dev ERC165 interface ID of ERC721 +# @dev ID da interface ERC165 do ERC721 ERC721_INTERFACE_ID: constant(bytes32) = 0x0000000000000000000000000000000000000000000000000000000080ac58cd ``` -[ERC-165](https://eips.ethereum.org/EIPS/eip-165) especifica um mecanismo para um contrato divulgar como aplicações podem se comunicar com ele, com os quais ERCs ele está em conformidade. Neste caso, o contrato está em conformidade com ERC-165 e ERC-721. +O [ERC-165](https://eips.ethereum.org/EIPS/eip-165) especifica um mecanismo para um contrato divulgar como os aplicativos +podem se comunicar com ele, e a quais ERCs ele se conforma. Nesse caso, o contrato está em conformidade com o ERC-165 e o ERC-721. ### Funções {#functions} @@ -198,11 +238,13 @@ No Vyper, assim como no Python, a função construtora é chamada `__init__`. ```python """ - @dev Contract constructor. + @dev Construtor do contrato. """ ``` -No Python e no Vyper, você também pode criar um comentário especificando uma string de múltiplas linhas (que começa e termina com `"""`), e não usá-lo de qualquer forma. Esses comentários também podem incluir [NatSpec](https://vyper.readthedocs.io/en/latest/natspec.html). +Em Python, e em Vyper, você também pode criar um comentário especificando uma string de várias linhas (que começa e termina +com `"""`), e não usá-la de forma alguma. Esses comentários também podem incluir +[NatSpec](https://vyper.readthedocs.io/en/latest/natspec.html). ```python self.supportedInterfaces[ERC165_INTERFACE_ID] = True @@ -210,57 +252,65 @@ No Python e no Vyper, você também pode criar um comentário especificando uma self.minter = msg.sender ``` -Para acessar variáveis de estado, você usa `self.` (novamente, o mesmo que em Python). +Para acessar as variáveis de estado, você usa `self.` (novamente, como em Python). -#### Exibir funções {#views} +#### Funções de Visualização {#views} -São funções que não modificam o estado da blockchain e, por isso, podem ser executadas gratuitamente se chamadas externamente. Se as funções de exibição forem chamadas por um contrato, elas ainda têm de ser executadas em cada nó e, portanto, custam gás. +Estas são funções que não modificam o estado da blockchain e, portanto, podem ser executadas +gratuitamente se forem chamadas externamente. Se as funções de visualização forem chamadas por um contrato, elas ainda precisarão ser executadas em +cada nó e, portanto, custarão gás. ```python @view @external ``` -Essas palavras-chave anteriores a uma definição de função que começam com um sinal de (`@`) são chamadas de _decoradores_. Elas especificam as circunstâncias em que uma função pode ser chamada. +Essas palavras-chave antes de uma definição de função que começam com um sinal de arroba (`@`) são chamadas de _decorações_. Elas +especificam as circunstâncias em que uma função pode ser chamada. -- `@view` especifica que esta função é um modo de exibição. -- `@external` especifica que essa função em particular pode ser chamada por transações e por outros contratos. +- `@view` especifica que esta função é uma visualização. +- `@external` especifica que esta função específica pode ser chamada por transações e por outros contratos. ```python def supportsInterface(_interfaceID: bytes32) -> bool: ``` -Ao contrário do Python, o Vyper é uma [linguagem de tipo estática](https://wikipedia.org/wiki/Type_system#Static_type_checking). Você não pode declarar uma variável ou um parâmetro de função, sem identificar os tipos de [dados](https://vyper.readthedocs.io/en/latest/types.html). Neste caso, o parâmetro de entrada é `bytes32`, um valor de 256 bits (256 bits é o tamanho da palavra nativa da [Máquina Virtual do Ethereum](/developers/docs/evm/)). A saída é um booleano valor. Por convenção, os nomes dos parâmetros da função começam com um sublinhado (`_`). +Ao contrário do Python, o Vyper é uma [linguagem de tipagem estática](https://wikipedia.org/wiki/Type_system#Static_type_checking). +Você não pode declarar uma variável, ou um parâmetro de função, sem identificar o [tipo de dados](https://vyper.readthedocs.io/en/latest/types.html). Nesse caso, o parâmetro de entrada é `bytes32`, um valor de 256 bits +(256 bits é o tamanho de palavra nativo da [Máquina Virtual Ethereum](/developers/docs/evm/)). A saída é um valor +booleano. Por convenção, os nomes dos parâmetros da função começam com um sublinhado (`_`). ```python """ - @dev Interface identification is specified in ERC-165. - @param _interfaceID Id of the interface + @dev A identificação da interface é especificada no ERC-165. + @param _interfaceID Id da interface """ return self.supportedInterfaces[_interfaceID] ``` -Retorne o valor do `self.supportedInterfaces` HashMap, o qual é definido no construtor (`__init__`). +Retorne o valor do HashMap `self.supportedInterfaces`, que é definido no construtor (`__init__`). ```python -### VIEW FUNCTIONS ### +### FUNÇÕES DE VISUALIZAÇÃO ### + ``` -Estas são as funções de visualização que fornecem informações sobre os tokens disponíveis para usuários e outros contratos. +Estas são as funções de visualização que disponibilizam informações sobre os tokens para usuários e outros contratos. ```python @view @external def balanceOf(_owner: address) -> uint256: """ - @dev Returns the number of NFTs owned by `_owner`. - Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid. - @param _owner Address for whom to query the balance. + @dev Retorna o número de NFTs de propriedade de `_owner`. + Lança uma exceção se `_owner` for o endereço zero. NFTs atribuídos ao endereço zero são considerados inválidos. + @param _owner Endereço para o qual consultar o saldo. """ assert _owner != ZERO_ADDRESS ``` -Esta linha [afirma](https://vyper.readthedocs.io/en/latest/statements.html#assert) que `_owner` não é zero. Se for zero, há um erro e a operação é anulada. +Esta linha [afirma](https://vyper.readthedocs.io/en/latest/statements.html#assert) que `_owner` não é +zero. Se for, há um erro e a operação é revertida. ```python return self.ownerToNFTokenCount[_owner] @@ -269,47 +319,51 @@ Esta linha [afirma](https://vyper.readthedocs.io/en/latest/statements.html#asser @external def ownerOf(_tokenId: uint256) -> address: """ - @dev Returns the address of the owner of the NFT. - Throws if `_tokenId` is not a valid NFT. - @param _tokenId The identifier for an NFT. + @dev Retorna o endereço do proprietário do NFT. + Lança uma exceção se `_tokenId` não for um NFT válido. + @param _tokenId O identificador para um NFT. """ owner: address = self.idToOwner[_tokenId] - # Throws if `_tokenId` is not a valid NFT + # Lança uma exceção se `_tokenId` não for um NFT válido assert owner != ZERO_ADDRESS return owner ``` -Na Máquina Virtual do Ethereum (EVM) qualquer armazenamento que não tenha um valor armazenado nele é zero. Se não houver token em `_tokenId`, o valor de `self.idToOwner[_tokenId]` é zero. Naquilo caso a função reverta. +Na Máquina Virtual Ethereum (EVM), qualquer armazenamento que não tenha um valor armazenado nele é zero. +Se não houver token em `_tokenId`, o valor de `self.idToOwner[_tokenId]` será zero. Nesse +caso, a função é revertida. ```python @view @external def getApproved(_tokenId: uint256) -> address: """ - @dev Get the approved address for a single NFT. - Throws if `_tokenId` is not a valid NFT. - @param _tokenId ID of the NFT to query the approval of. + @dev Obtenha o endereço aprovado para um único NFT. + Lança uma exceção se `_tokenId` não for um NFT válido. + @param _tokenId ID do NFT para consultar a aprovação. """ - # Throws if `_tokenId` is not a valid NFT + # Lança uma exceção se `_tokenId` não for um NFT válido assert self.idToOwner[_tokenId] != ZERO_ADDRESS return self.idToApprovals[_tokenId] ``` -Observe que `getApproved` _pode_ retornar zero. Se o token for válido, ele retorna `self.idToApprovals[_tokenId]`. Se não houver aprovador, esse valor é zero. +Observe que `getApproved` _pode_ retornar zero. Se o token for válido, ele retorna `self.idToApprovals[_tokenId]`. +Se não houver aprovador, esse valor é zero. ```python @view @external def isApprovedForAll(_owner: address, _operator: address) -> bool: """ - @dev Checks if `_operator` is an approved operator for `_owner`. - @param _owner The address that owns the NFTs. - @param _operator The address that acts on behalf of the owner. + @dev Verifica se `_operator` é um operador aprovado para `_owner`. + @param _owner O endereço que possui os NFTs. + @param _operator O endereço que atua em nome do proprietário. """ return (self.ownerToOperators[_owner])[_operator] ``` -Esta função checa se `_operator` tem permissão para gerenciar todos os tokens de `_owner` neste contrato. Como pode haver vários operadores, este é um Hashmap de dois níveis. +Esta função verifica se o `_operator` tem permissão para gerenciar todos os tokens do `_owner` neste contrato. +Como pode haver vários operadores, este é um HashMap de dois níveis. #### Funções Auxiliares de Transferência {#transfer-helpers} @@ -317,22 +371,23 @@ Essas funções implementam operações que fazem parte da transferência ou ger ```python -### TRANSFER FUNCTION HELPERS ### +### FUNÇÕES AUXILIARES DE TRANSFERÊNCIA ### @view @internal ``` -Este decorador, `@internal`, significa que a função é somente acessível de outras funções dentro do mesmo contrato. Por convenção, estes nomes de função também começam com um sublinhado (`_`). +Esta decoração, `@internal`, significa que a função só é acessível a partir de outras funções dentro do +mesmo contrato. Por convenção, esses nomes de função também começam com um sublinhado (`_`). ```python def _isApprovedOrOwner(_spender: address, _tokenId: uint256) -> bool: """ - @dev Returns whether the given spender can transfer a given token ID - @param spender address of the spender to query - @param tokenId uint256 ID of the token to be transferred - @return bool whether the msg.sender is approved for the given token ID, - is an operator of the owner, or is the owner of the token + @dev Retorna se o gastador informado pode transferir um determinado ID de token + @param spender endereço do gastador para consultar + @param tokenId uint256 ID do token a ser transferido + @return bool se o msg.sender está aprovado para o ID de token informado, + é um operador do proprietário ou é o proprietário do token """ owner: address = self.idToOwner[_tokenId] spenderIsOwner: bool = owner == _spender @@ -341,117 +396,123 @@ def _isApprovedOrOwner(_spender: address, _tokenId: uint256) -> bool: return (spenderIsOwner or spenderIsApproved) or spenderIsApprovedForAll ``` -Há três maneiras na qual um endereço pode ser permitido a transferir um token: +Há três maneiras pelas quais um endereço pode ter permissão para transferir um token: 1. O endereço é o proprietário do token -2. O endereço é aprovado a gastar o token -3. O endereço é um operador do proprietário do token +2. O endereço é aprovado para gastar esse token +3. O endereço é um operador para o proprietário do token -A função acima pode ser uma view porque ela não muda o estado. Para reduzir custos operacionais, qualquer função que _possa_ ser uma view, _deve_ ser uma view. +A função acima pode ser uma visualização porque não altera o estado. Para reduzir os custos operacionais, qualquer +função que _possa_ ser uma visualização _deve_ ser uma visualização. ```python @internal def _addTokenTo(_to: address, _tokenId: uint256): """ - @dev Add a NFT to a given address - Throws if `_tokenId` is owned by someone. + @dev Adiciona um NFT a um determinado endereço + Lança uma exceção se `_tokenId` for de propriedade de alguém. """ - # Throws if `_tokenId` is owned by someone + # Lança uma exceção se `_tokenId` for de propriedade de alguém assert self.idToOwner[_tokenId] == ZERO_ADDRESS - # Change the owner + # Altera o proprietário self.idToOwner[_tokenId] = _to - # Change count tracking + # Altera o rastreamento da contagem self.ownerToNFTokenCount[_to] += 1 @internal def _removeTokenFrom(_from: address, _tokenId: uint256): """ - @dev Remove a NFT from a given address - Throws if `_from` is not the current owner. + @dev Remove um NFT de um determinado endereço + Lança uma exceção se `_from` não for o proprietário atual. """ - # Throws if `_from` is not the current owner + # Lança uma exceção se `_from` não for o proprietário atual assert self.idToOwner[_tokenId] == _from - # Change the owner + # Altera o proprietário self.idToOwner[_tokenId] = ZERO_ADDRESS - # Change count tracking + # Altera o rastreamento da contagem self.ownerToNFTokenCount[_from] -= 1 ``` -Quando há um problema com uma transferência, anulamos a chamada. +Quando há um problema com uma transferência, revertemos a chamada. ```python @internal def _clearApproval(_owner: address, _tokenId: uint256): """ - @dev Clear an approval of a given address - Throws if `_owner` is not the current owner. + @dev Limpa a aprovação de um determinado endereço + Lança uma exceção se `_owner` não for o proprietário atual. """ - # Throws if `_owner` is not the current owner + # Lança uma exceção se `_owner` não for o proprietário atual assert self.idToOwner[_tokenId] == _owner if self.idToApprovals[_tokenId] != ZERO_ADDRESS: - # Reset approvals + # Redefinir aprovações self.idToApprovals[_tokenId] = ZERO_ADDRESS ``` -Altere o valor apenas se necessário. Variáveis de estado vivem no armazenamento. Escrever para o storage é uma das operações mais caras que a EVM (Máquina Virtual Ethereum) faz (em termos de [gas](/developers/docs/gas/)). Portanto, é uma boa ideia minimizá-lo, mesmo escrevendo o valor existente tem um custo alto. +Altere o valor apenas se necessário. As variáveis de estado ficam no armazenamento. Gravar no armazenamento é +uma das operações mais caras que a EVM (Máquina Virtual Ethereum) faz (em termos de +[gás](/developers/docs/gas/)). Portanto, é uma boa ideia minimizá-la, mesmo que a escrita do +valor existente tenha um custo alto. ```python @internal def _transferFrom(_from: address, _to: address, _tokenId: uint256, _sender: address): """ - @dev Execute transfer of a NFT. - Throws unless `msg.sender` is the current owner, an authorized operator, or the approved - address for this NFT. (NOTE: `msg.sender` not allowed in private function so pass `_sender`.) - Throws if `_to` is the zero address. - Throws if `_from` is not the current owner. - Throws if `_tokenId` is not a valid NFT. + @dev Executa a transferência de um NFT. + Lança uma exceção, a menos que `msg.sender` seja o proprietário atual, um operador autorizado ou o endereço + aprovado para este NFT. (NOTA: `msg.sender` não é permitido em função privada, então passe `_sender`.) + Lança uma exceção se `_to` for o endereço zero. + Lança uma exceção se `_from` não for o proprietário atual. + Lança uma exceção se `_tokenId` não for um NFT válido. """ ``` -Nós temos esta função interna porque há duas maneiras de transferir tokens (normal e segura), mas nós queremos somente uma única localização no código onde nós fazemos isso para facilitar auditoria. +Temos essa função interna porque há duas maneiras de transferir tokens (regular e segura), mas +queremos apenas um único local no código onde fazemos isso para facilitar a auditoria. ```python - # Check requirements + # Verificar requisitos assert self._isApprovedOrOwner(_sender, _tokenId) - # Throws if `_to` is the zero address + # Lança uma exceção se `_to` for o endereço zero assert _to != ZERO_ADDRESS - # Clear approval. Throws if `_from` is not the current owner + # Limpar aprovação. Lança uma exceção se `_from` não for o proprietário atual self._clearApproval(_from, _tokenId) - # Remove NFT. Throws if `_tokenId` is not a valid NFT + # Remover NFT. Lança uma exceção se `_tokenId` não for um NFT válido self._removeTokenFrom(_from, _tokenId) - # Add NFT + # Adicionar NFT self._addTokenTo(_to, _tokenId) - # Log the transfer + # Registrar a transferência log Transfer(_from, _to, _tokenId) ``` -Para emitir um evento em Vyper você usa uma declaração de `log` ([veja aqui para mais detalhes](https://vyper.readthedocs.io/en/latest/event-logging.html#event-logging)). +Para emitir um evento em Vyper, você usa uma instrução `log` ([veja aqui para mais detalhes](https://vyper.readthedocs.io/en/latest/event-logging.html#event-logging)). #### Funções de Transferência {#transfer-funs} ```python -### TRANSFER FUNCTIONS ### +### FUNÇÕES DE TRANSFERÊNCIA ### @external def transferFrom(_from: address, _to: address, _tokenId: uint256): """ - @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved - address for this NFT. - Throws if `_from` is not the current owner. - Throws if `_to` is the zero address. - Throws if `_tokenId` is not a valid NFT. - @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else - they maybe be permanently lost. - @param _from The current owner of the NFT. - @param _to The new owner. - @param _tokenId The NFT to transfer. + @dev Lança uma exceção, a menos que `msg.sender` seja o proprietário atual, um operador autorizado ou o + endereço aprovado para este NFT. + Lança uma exceção se `_from` não for o proprietário atual. + Lança uma exceção se `_to` for o endereço zero. + Lança uma exceção se `_tokenId` não for um NFT válido. + @notice O chamador é responsável por confirmar que `_to` é capaz de receber NFTs, caso contrário + eles podem ser permanentemente perdidos. + @param _from O proprietário atual do NFT. + @param _to O novo proprietário. + @param _tokenId O NFT a ser transferido. """ self._transferFrom(_from, _to, _tokenId, msg.sender) ``` -Esta função deixa você transferir para um endereço arbitrário. A não ser que o endereço é um usuário, ou um contrato que sabe como transferir tokens, qualquer token que você transferir ficará preso no endereço e inútil. +Esta função permite que você transfira para um endereço arbitrário. A menos que o endereço seja de um usuário ou de um contrato que +saiba como transferir tokens, qualquer token que você transferir ficará preso nesse endereço e será inútil. ```python @external @@ -462,75 +523,80 @@ def safeTransferFrom( _data: Bytes[1024]=b"" ): """ - @dev Transfers the ownership of an NFT from one address to another address. - Throws unless `msg.sender` is the current owner, an authorized operator, or the - approved address for this NFT. - Throws if `_from` is not the current owner. - Throws if `_to` is the zero address. - Throws if `_tokenId` is not a valid NFT. - If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if - the return value is not `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. - NOTE: bytes4 is represented by bytes32 with padding - @param _from The current owner of the NFT. - @param _to The new owner. - @param _tokenId The NFT to transfer. - @param _data Additional data with no specified format, sent in call to `_to`. + @dev Transfere a propriedade de um NFT de um endereço para outro. + Lança uma exceção, a menos que `msg.sender` seja o proprietário atual, um operador autorizado ou o + endereço aprovado para este NFT. + Lança uma exceção se `_from` não for o proprietário atual. + Lança uma exceção se `_to` for o endereço zero. + Lança uma exceção se `_tokenId` não for um NFT válido. + Se `_to` for um contrato inteligente, ele chama `onERC721Received` em `_to` e lança uma exceção se + o valor de retorno não for `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. + NOTA: bytes4 é representado por bytes32 com preenchimento + @param _from O proprietário atual do NFT. + @param _to O novo proprietário. + @param _tokenId O NFT a ser transferido. + @param _data Dados adicionais sem formato especificado, enviados na chamada para `_to`. """ self._transferFrom(_from, _to, _tokenId, msg.sender) ``` -Tudo bem fazer a transferência primeiro, porque se der um problema, vamos revertê-la de qualquer maneira, a fim de anular tudo o que foi feito durante a chamada. +Não há problema em fazer a transferência primeiro porque, se houver um problema, vamos reverter de qualquer maneira, +então tudo o que for feito na chamada será cancelado. ```python - if _to.is_contract: # check if `_to` is a contract address + if _to.is_contract: # verifica se `_to` é um endereço de contrato ``` -Primeiro cheque para ver se o endereço é um contrato (se ele tem código). Se não, assuma que ele é um endereço de usuário e o usuário será capaz de usar o token ou transferi-lo. Mas não deixe que isso engane você com uma falsa sensação de segurança. Você pode perder tokens, mesmo com `safeTransferFrom`, se você transferi-los para um endereço que ninguém conhece a chave privada. +Primeiro, verifique se o endereço é um contrato (se ele tem código). Caso contrário, presuma que é um endereço de +usuário e que o usuário poderá usar o token ou transferi-lo. Mas não deixe que isso o iluda +com uma falsa sensação de segurança. Você pode perder tokens, mesmo com `safeTransferFrom`, se os transferir +para um endereço cuja chave privada ninguém conhece. ```python returnValue: bytes32 = ERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) ``` -Chame o contrato-alvo para ver se ele pode receber tokens ERC-721. +Chame o contrato de destino para ver se ele pode receber tokens ERC-721. ```python - # Throws if transfer destination is a contract which does not implement 'onERC721Received' + # Lança uma exceção se o destino da transferência for um contrato que não implementa 'onERC721Received' assert returnValue == method_id("onERC721Received(address,address,uint256,bytes)", output_type=bytes32) ``` -Se o destino é um contrato, mas um que não aceita tokens ERC-721 (ou que decide não aceitar esta transferência em particular), reverta. +Se o destino for um contrato, mas um que não aceita tokens ERC-721 (ou que decidiu não aceitar esta +transferência em particular), reverta. ```python @external def approve(_approved: address, _tokenId: uint256): """ - @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address. - Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. - Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP) - Throws if `_approved` is the current owner. (NOTE: This is not written the EIP) - @param _approved Address to be approved for the given NFT ID. - @param _tokenId ID of the token to be approved. + @dev Define ou reafirma o endereço aprovado para um NFT. O endereço zero indica que não há endereço aprovado. + Lança uma exceção, a menos que `msg.sender` seja o proprietário atual do NFT ou um operador autorizado do proprietário atual. + Lança uma exceção se `_tokenId` não for um NFT válido. (NOTA: Isso não está escrito no EIP) + Lança uma exceção se `_approved` for o proprietário atual. (NOTA: Isso não está escrito no EIP) + @param _approved Endereço a ser aprovado para o ID de NFT fornecido. + @param _tokenId ID do token a ser aprovado. """ owner: address = self.idToOwner[_tokenId] - # Throws if `_tokenId` is not a valid NFT + # Lança uma exceção se `_tokenId` não for um NFT válido assert owner != ZERO_ADDRESS - # Throws if `_approved` is the current owner + # Lança uma exceção se `_approved` for o proprietário atual assert _approved != owner ``` -Por convenção, se você não quiser ter um aprovador, designe o endereço zero, não você mesmo. +Por convenção, se você não quiser ter um aprovador, você nomeia o endereço zero, não a si mesmo. ```python - # Check requirements + # Verificar requisitos senderIsOwner: bool = self.idToOwner[_tokenId] == msg.sender senderIsApprovedForAll: bool = (self.ownerToOperators[owner])[msg.sender] assert (senderIsOwner or senderIsApprovedForAll) ``` -Para configurar um aprovador você pode ou ser o proprietário, ou um operador autorizado pelo proprietário. +Para definir uma aprovação, você pode ser o proprietário ou um operador autorizado pelo proprietário. ```python - # Set the approval + # Definir a aprovação self.idToApprovals[_tokenId] = _approved log Approval(owner, _approved, _tokenId) @@ -538,25 +604,27 @@ Para configurar um aprovador você pode ou ser o proprietário, ou um operador a @external def setApprovalForAll(_operator: address, _approved: bool): """ - @dev Enables or disables approval for a third party ("operator") to manage all of - `msg.sender`'s assets. It also emits the ApprovalForAll event. - Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP) - @notice This works even if sender doesn't own any tokens at the time. - @param _operator Address to add to the set of authorized operators. - @param _approved True if the operators is approved, false to revoke approval. + @dev Habilita ou desabilita a aprovação para um terceiro ("operador") gerenciar todos os + ativos de `msg.sender`. Também emite o evento ApprovalForAll. + Lança uma exceção se `_operator` for o `msg.sender`. (NOTA: Isso não está escrito no EIP) + @notice Isso funciona mesmo que o remetente não possua nenhum token no momento. + @param _operator Endereço a ser adicionado ao conjunto de operadores autorizados. + @param _approved Verdadeiro se os operadores forem aprovados, falso para revogar a aprovação. """ - # Throws if `_operator` is the `msg.sender` + # Lança uma exceção se `_operator` for o `msg.sender` assert _operator != msg.sender self.ownerToOperators[msg.sender][_operator] = _approved log ApprovalForAll(msg.sender, _operator, _approved) ``` -#### Cunhar novos tokens e destruir os existentes {#mint-burn} +#### Cunhar Novos Tokens e Destruir os Existentes {#mint-burn} -A conta que criou o contrato é o `minter`, o superusuário autorizado a cunhar novos NFTs. No entanto, mesmo isso não é autorizado para queimar tokens existentes. Somente o proprietário, ou uma entidade autorizada pelo proprietário, podem fazer isso. +A conta que criou o contrato é o `minter`, o superusuário que está autorizado a cunhar +novos NFTs. No entanto, mesmo ele não tem permissão para queimar tokens existentes. Apenas o proprietário, ou uma entidade +autorizada pelo proprietário, pode fazer isso. ```python -### MINT & BURN FUNCTIONS ### +### FUNÇÕES DE CUNHAGEM E QUEIMA ### @external def mint(_to: address, _tokenId: uint256) -> bool: @@ -566,24 +634,27 @@ Esta função sempre retorna `True`, porque se a operação falhar, ela é rever ```python """ - @dev Function to mint tokens - Throws if `msg.sender` is not the minter. - Throws if `_to` is zero address. - Throws if `_tokenId` is owned by someone. - @param _to The address that will receive the minted tokens. - @param _tokenId The token id to mint. - @return A boolean that indicates if the operation was successful. + @dev Função para cunhar tokens + Lança uma exceção se `msg.sender` não for o minter. + Lança uma exceção se `_to` for o endereço zero. + Lança uma exceção se `_tokenId` for de propriedade de alguém. + @param _to O endereço que receberá os tokens cunhados. + @param _tokenId O id do token a ser cunhado. + @return Um booleano que indica se a operação foi bem-sucedida. """ - # Throws if `msg.sender` is not the minter + # Lança uma exceção se `msg.sender` não for o minter assert msg.sender == self.minter ``` -Somente o minter (a conta que criou o contrato ERC-721) pode cunhar novos tokens. Isso pode ser um problema no futuro se você quiser mudar a identidade do minter. Em um contrato de produção, provavelmente seria desejável ter uma função que permita ao minter transferir privilégios de minter para uma outra pessoa. +Apenas o minter (a conta que criou o contrato ERC-721) pode cunhar novos tokens. Isso pode ser um +problema no futuro se quisermos mudar a identidade do minter. Em +um contrato de produção, você provavelmente desejaria uma função que permitisse ao minter transferir +os privilégios de minter para outra pessoa. ```python - # Throws if `_to` is zero address + # Lança uma exceção se `_to` for o endereço zero assert _to != ZERO_ADDRESS - # Add NFT. Throws if `_tokenId` is owned by someone + # Adicionar NFT. Lança uma exceção se `_tokenId` for de propriedade de alguém self._addTokenTo(_to, _tokenId) log Transfer(ZERO_ADDRESS, _to, _tokenId) return True @@ -596,37 +667,48 @@ Por convenção, a cunhagem de novos tokens conta como uma transferência do end @external def burn(_tokenId: uint256): """ - @dev Burns a specific ERC721 token. - Throws unless `msg.sender` is the current owner, an authorized operator, or the approved - address for this NFT. - Throws if `_tokenId` is not a valid NFT. - @param _tokenId uint256 id of the ERC721 token to be burned. + @dev Queima um token ERC721 específico. + Lança uma exceção, a menos que `msg.sender` seja o proprietário atual, um operador autorizado ou o endereço + aprovado para este NFT. + Lança uma exceção se `_tokenId` não for um NFT válido. + @param _tokenId id uint256 do token ERC721 a ser queimado. """ - # Check requirements + # Verificar requisitos assert self._isApprovedOrOwner(msg.sender, _tokenId) owner: address = self.idToOwner[_tokenId] - # Throws if `_tokenId` is not a valid NFT + # Lança uma exceção se `_tokenId` não for um NFT válido assert owner != ZERO_ADDRESS self._clearApproval(owner, _tokenId) self._removeTokenFrom(owner, _tokenId) log Transfer(owner, ZERO_ADDRESS, _tokenId) ``` -Qualquer pessoa autorizada a transferir um token, tem permissão para queimá-lo. Enquanto uma queima aparece equivalente à transferência para o endereço zero, o endereço zero não recebe de verdade o token. Isso permite-nos liberar todo o armazenamento usado pelo token, o que pode reduzir o custo de gás da transação. +Qualquer pessoa que tenha permissão para transferir um token tem permissão para queimá-lo. Embora uma queima pareça equivalente a uma +transferência para o endereço zero, o endereço zero na verdade não recebe o token. Isso nos permite +liberar todo o armazenamento que foi usado para o token, o que pode reduzir o custo de gás da transação. + +## Usando este Contrato {#using-contract} + +Em contraste com o Solidity, o Vyper não tem herança. Essa é uma escolha de design deliberada para tornar o +código mais claro e, portanto, mais fácil de proteger. Então, para criar seu próprio contrato Vyper ERC-721, você pega este +contrato e o modifica +para implementar a lógica de negócios que você deseja. -## Usando este contrato {#using-contract} +## Conclusão {#conclusion} -Ao contrário do Solidity, o Vyper não tem herança. Esta é uma escolha de design deliberada para tornar o código mais claro e, com isso, mais fácil de proteger. Portanto, para criar seu próprio contrato Vyper ERC-721, você usa [este contrato](https://github.com/vyperlang/vyper/blob/master/examples/tokens/ERC721.vy) e o modifica para implementar a lógica comercial que você desejar. +Para revisão, aqui estão algumas das ideias mais importantes deste contrato: -### Conclusão {#conclusion} +- Para receber tokens ERC-721 com uma transferência segura, os contratos precisam implementar a interface `ERC721Receiver`. +- Mesmo se você usar a transferência segura, os tokens ainda podem ficar presos se você os enviar para um endereço cuja chave privada + é desconhecida. +- Quando há um problema com uma operação, é uma boa ideia `reverter` a chamada, em vez de apenas retornar + um valor de falha. +- Os tokens ERC-721 existem quando têm um proprietário. +- Existem três maneiras de ser autorizado a transferir um NFT. Você pode ser o proprietário, ser aprovado para um token específico + ou ser um operador para todos os tokens do proprietário. +- Eventos passados são visíveis apenas fora da blockchain. O código em execução dentro da blockchain não pode visualizá-los. -Recapitulando, aqui estão algumas das ideias mais importantes neste contrato: +Agora, vá e implemente contratos Vyper seguros. -- Para receber os tokens ERC-721 com uma transferência segura, os contratos têm de implementar a interface `ERC721Receiver`. -- Mesmo que você use a transferência segura, os tokens ainda podem ficar presos se você os enviar para um endereço cuja chave privada. -- Quando há um problema com uma operação, é uma boa ideia fazer o `revert` da chamada, em vez de apenas retornar um valor de falha. -- Os tokens ERC-721 existem quando eles têm um proprietário. -- Existem três formas de ser autorizado a transferir um NFT. Você pode ser o proprietário, ser aprovado para um token específico, ou ser um operador para todos os tokens do proprietário. -- Eventos passados são visíveis apenas fora da blockchain. O código executando dentro da blockchain não pode visualizá-los. +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). -Agora, você está pronto para implementar contratos Vyper seguros. diff --git a/public/content/translations/pt-br/developers/tutorials/erc20-annotated-code/index.md b/public/content/translations/pt-br/developers/tutorials/erc20-annotated-code/index.md index bd328aaf93c..2754dd3f9cb 100644 --- a/public/content/translations/pt-br/developers/tutorials/erc20-annotated-code/index.md +++ b/public/content/translations/pt-br/developers/tutorials/erc20-annotated-code/index.md @@ -1,30 +1,39 @@ --- -title: "Demonstração do Contrato ERC-20" -description: O que é o contrato OpenZeppelin ERC-20 e por que está lá? +title: "Passo a passo do contrato ERC-20" +description: "O que está no contrato ERC-20 da OpenZeppelin e por que está lá?" author: Ori Pomerantz lang: pt-br -tags: - - "solidez" - - "erc-20" +tags: [ "Solidity", "erc-20" ] skill: beginner published: 2021-03-09 --- ## Introdução {#introduction} -Um dos usos mais comuns do Ethereum é a criação por um grupo de pessoas de um token negociável que, de certa forma, criam sua própria moeda. Essas moedas seguem a norma [ERC-20](/developers/docs/standards/tokens/erc-20/). Essa norma possibilita a criação de ferramentas, como os pools de liquidez e carteiras, que funcionam com todos os tokens ERC-20. Neste artigo, analisaremos a [Implementação do OpenZeppelin Solidity ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol), assim como a [definição de interface](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol). +Um dos usos mais comuns do Ethereum é a criação por um grupo de pessoas de um token negociável que, de certa forma, criam sua própria moeda. Esses tokens geralmente seguem um padrão, +o [ERC-20](/developers/docs/standards/tokens/erc-20/). Esse padrão possibilita escrever ferramentas, como pools de liquidez e carteiras, que funcionam com todos os tokens +ERC-20. Neste artigo, analisaremos a +implementação [ERC20 em Solidity da OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol), bem como a +[definição da interface](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol). -Este é o código-fonte anotado. Se você deseja implementar ERC-20, [leia este tutorial](https://docs.openzeppelin.com/contracts/2.x/erc20-supply). +Este é um código-fonte anotado. Se você quiser implementar o ERC-20, +[leia este tutorial](https://docs.openzeppelin.com/contracts/2.x/erc20-supply). -## A 'Interface' {#the-interface} +## A interface {#the-interface} -O objetivo de uma norma como a ERC-20 é permitir que as implementações das várias moedas sejam interoperáveis entre aplicativos, como carteiras e corretoras descentralizadas. Para atingirmos tal objetivo, criamos uma ['interface'](https://www.geeksforgeeks.org/solidity-basics-of-interface/). Qualquer código que necessite utilizar o contrato pode usar as mesmas definições de interface e ser compatível com todos os contratos de token que o usem, seja uma carteira de criptomoedas como a MetaMask, um aplicativo descentralizado como o Etherscan.io, ou um contrato diferente como um pool de liquidez. +O objetivo de um padrão como o ERC-20 é permitir que muitas implementações de tokens sejam interoperáveis entre aplicativos, como carteiras e corretoras descentralizadas. Para conseguir isso, criamos uma +[interface](https://www.geeksforgeeks.org/solidity/solidity-basics-of-interface/). Qualquer código que precise usar o contrato de token +pode usar as mesmas definições na interface e ser compatível com todos os contratos de token que a utilizam, seja uma carteira como a +MetaMask, um dapp como o etherscan.io ou um contrato diferente, como um pool de liquidez. ![Ilustração da interface ERC-20](erc20_interface.png) -Se você é um programador experiente, provavelmente se lembra de ver constructos semelhantes em [Java](https://www.w3schools.com/java/java_interface.asp) ou mesmo em [arquivos de cabeçalho em C](https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html). +Se você é um programador experiente, provavelmente se lembra de ter visto construções semelhantes em [Java](https://www.w3schools.com/java/java_interface.asp) +ou até mesmo em [arquivos de cabeçalho C](https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html). -Essa é a definição da [interface ERC-20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol) do OpenZeppelin. Ela é uma tradução do [padrão legível para humanos](https://eips.ethereum.org/EIPS/eip-20) em código Solidity. Obviamente, a interface por si só não define _como_ fazer algo. Isso é explicado no código-fonte do contrato abaixo. +Esta é uma definição da [Interface ERC-20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol) +da OpenZeppelin. É uma tradução do [padrão legível por humanos](https://eips.ethereum.org/EIPS/eip-20) para o código Solidity. Claro, a +interface em si não define _como_ fazer nada. Isso é explicado no código-fonte do contrato abaixo.   @@ -32,7 +41,8 @@ Essa é a definição da [interface ERC-20](https://github.com/OpenZeppelin/open // SPDX-License-Identifier: MIT ``` -Os arquivos Solidity devem incluir um identificador de licença. [Você pode ver a lista de licenças aqui](https://spdx.org/licenses/). Se você necessitar de uma licença diferente, explique nos comentários. +Os arquivos Solidity devem incluir um identificador de licença. [Você pode ver a lista de licenças aqui](https://spdx.org/licenses/). Se você precisar de uma licença +diferente, basta explicá-la nos comentários.   @@ -40,17 +50,20 @@ Os arquivos Solidity devem incluir um identificador de licença. [Você pode ver pragma solidity >=0.6.0 <0.8.0; ``` -A linguagem Solidity continua evoluindo rapidamente, e novas versões podem não ser compatíveis com o código antigo. ([confira aqui](https://docs.soliditylang.org/en/v0.7.0/070-breaking-changes.html)). Portanto, é uma boa ideia especificar não apenas uma versão mínima da linguagem, mas também uma versão máxima com a qual você testou o código. +A linguagem Solidity ainda está evoluindo rapidamente, e novas versões podem não ser compatíveis com códigos antigos +([veja aqui](https://docs.soliditylang.org/en/v0.7.0/070-breaking-changes.html)). Portanto, é uma boa ideia especificar não apenas uma versão mínima +da linguagem, mas também uma versão máxima, a mais recente com a qual você testou o código.   ```solidity /** - * @dev Interface of the ERC20 standard as defined in the EIP. + * @dev Interface do padrão ERC20, conforme definido na EIP. */ ``` -O `@dev` no comentário faz parte do [formato NatSpec](https://docs.soliditylang.org/en/develop/natspec-format.html), usado para produzir a documentação a partir de um código-fonte. +O `@dev` no comentário faz parte do [formato NatSpec](https://docs.soliditylang.org/en/develop/natspec-format.html), usado para produzir +documentação a partir do código-fonte.   @@ -58,134 +71,164 @@ O `@dev` no comentário faz parte do [formato NatSpec](https://docs.soliditylang interface IERC20 { ``` -Convenientemente, nomes de Interface começam com `I`. +Por convenção, os nomes de interface começam com `I`.   ```solidity /** - * @dev Returns the amount of tokens in existence. + * @dev Retorna a quantidade de tokens existentes. */ function totalSupply() external view returns (uint256); ``` -Essa função é `external`, ou seja, [só pode ser chamada de fora do contrato](https://docs.soliditylang.org/en/v0.7.0/cheatsheet.html#index-2). Ela retorna o fornecimento total de tokens no contrato. Esse valor é retornado usando o tipo mais comum no Ethereum, 256 bits não assinado (256 bits é o tamanho de fonte nativo da EVM). Essa função também é uma `view`, ou seja, ela não pode alterar o estado, portanto, ela pode ser executada em apenas um nó em vez de fazer com que todos os nós da blockchain a executem. Esse tipo de função não gera transação e não custa [gás](/developers/docs/Gas/). +Esta função é `external`, o que significa que [só pode ser chamada de fora do contrato](https://docs.soliditylang.org/en/v0.7.0/cheatsheet.html#index-2). +Ela retorna o fornecimento total de tokens no contrato. Este valor é retornado usando o tipo mais comum no Ethereum, 256 bits sem sinal (256 bits é o +tamanho nativo da palavra da EVM). Essa função também é uma `view`, o que significa que ela não altera o estado, portanto, pode ser executada em um único nó, em vez de fazer com que +todos os nós da blockchain a executem. Esse tipo de função não gera uma transação e não custa [gás](/developers/docs/gas/). -**Observação:** Em teoria, pode-se ter a impressão de que o criador do contrato conseguiria trapacear retornando uma quantia menor do fornecimento total do que a quantia real, fazendo com que cada moeda valha mais do que realmente vale. De qualquer forma, este medo ignora a verdadeira natureza da blockchain. Tudo que acontece na blockchain pode ser verificado em cada nó. Para conseguir isso, cada contrato da linguagem de código e armazenamento esta disponível em cada nó. Embora não seja obrigatório publicar o código Solidity, mas ninguém confiará em você a menos que publique o código-fonte e a versão do Solidity usados na compilação, para que ele possa ser comparado com o código de linguagem da máquina que você forneceu. Por exemplo, confira [este contrato](https://etherscan.io/address/0xa530F85085C6FE2f866E7FdB716849714a89f4CD#code). +**Observação:** em teoria, pode parecer que o criador de um contrato poderia trapacear retornando um fornecimento total menor que o valor real, fazendo com que cada token pareça +mais valioso do que realmente é. No entanto, esse medo ignora a verdadeira natureza da blockchain. Tudo o que acontece na blockchain pode ser verificado por +todos os nós. Para conseguir isso, o código de linguagem de máquina e o armazenamento de cada contrato estão disponíveis em todos os nós. Embora você não seja obrigado a publicar o código Solidity +do seu contrato, ninguém o levaria a sério, a menos que você publique o código-fonte e a versão do Solidity com a qual ele foi compilado, para que possa +ser verificado com o código de linguagem de máquina que você forneceu. +Por exemplo, veja [este contrato](https://eth.blockscout.com/address/0xa530F85085C6FE2f866E7FdB716849714a89f4CD?tab=contract).   ```solidity /** - * @dev Returns the amount of tokens owned by `account`. + * @dev Retorna a quantidade de tokens de propriedade de `account`. */ function balanceOf(address account) external view returns (uint256); ``` -Como o próprio nome já diz, `balanceOf` retorna o saldo de uma conta. Contas de Ethereum são identificadas em Solidity usando `address`, que contem 160 bits. Também são `external` e `view`. +Como o nome diz, `balanceOf` retorna o saldo de uma conta. As contas Ethereum são identificadas no Solidity usando o tipo `address`, que contém 160 bits. +Ela também é `external` e `view`.   ```solidity /** - * @dev Moves `amount` tokens from the caller's account to `recipient`. + * @dev Move a quantidade `amount` de tokens da conta do chamador para o `recipient`. * - * Returns a boolean value indicating whether the operation succeeded. + * Retorna um valor booleano que indica se a operação foi bem-sucedida. * - * Emits a {Transfer} event. + * Emite um evento {Transfer}. */ function transfer(address recipient, uint256 amount) external returns (bool); ``` -A função `transfer` transfere as moedas de um chamador para outro endereço. Isso envolve uma mudança de estado, então não é um `view`. Quando um usuário chama essa função, ele cria uma transação a um custo cobrada em gás. Ele também emite um evento, `Transfer`, para informar a todos na blockchain sobre esse evento. +A função `transfer` transfere tokens do chamador para um endereço diferente. Isso envolve uma mudança de estado, então não é uma `view`. +Quando um usuário chama essa função, ela cria uma transação e custa gás. Ela também emite um evento, `Transfer`, para informar a todos na +blockchain sobre o evento. -Essa função possui duas saídas para dois chamadores diferentes: +A função tem dois tipos de saída para dois tipos diferentes de chamadores: -- Os usuários que chamam a função diretamente de uma interface de usuário. Normalmente o usuário envia uma transação e não espera por uma resposta, que pode demorar uma quantidade indefinida de tempo. O usuário pode ver o que ocorreu procurando pelo recibo da transação (identificado pela transação hash) ou procurando pelo evento `transfer`. -- Outros contratos, nos quais chamam a função como parte de uma transação inteira. Esses contratos obtêm o resultado imediatamente, pois eles executam a mesma transação, para usar o valor de retorno da função. +- Usuários que chamam a função diretamente de uma interface de usuário. Normalmente, o usuário envia uma transação + e não espera por uma resposta, que pode levar um tempo indefinido. O usuário pode ver o que aconteceu + procurando o recibo da transação (que é identificado pelo hash da transação) ou procurando pelo + evento `Transfer`. +- Outros contratos, que chamam a função como parte de uma transação geral. Esses contratos obtêm o resultado imediatamente, + porque são executados na mesma transação, para que possam usar o valor de retorno da função. -O mesmo tipo de saída é criado por outras funções que mudam o estado do contrato. +O mesmo tipo de saída é criado pelas outras funções que alteram o estado do contrato.   -As provisões permitem que uma conta gaste tokens que pertencem a um proprietário diferente. Isso é útil, por exemplo, para contratos que agem como vendedores. Contratos não podem monitorar eventos, portanto, se um comprador quiser transferir diretamente, tokens para o contrato do vendedor, esse contrato não saberá se foi pago. Em vez disso, o comprador permite que o contrato do vendedor gaste uma certa quantia, e o vendedor transfere essa quantia. Isso é feito por meio de uma função do contrato do vendedor, para que o contrato do vendedor possa saber se a operação foi bem-sucedida. +As permissões (allowances) permitem que uma conta gaste alguns tokens que pertencem a um proprietário diferente. +Isso é útil, por exemplo, para contratos que atuam como vendedores. Os contratos não podem +monitorar eventos; portanto, se um comprador transferisse tokens para o contrato do vendedor +diretamente, esse contrato não saberia que foi pago. Em vez disso, o comprador permite que o contrato do +vendedor gaste uma certa quantia, e o vendedor transfere essa quantia. +Isso é feito por meio de uma função que o contrato do vendedor chama, para que o contrato do vendedor +possa saber se foi bem-sucedido. ```solidity /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. Isso é - * zero por padrão. + * @dev Retorna o número restante de tokens que o `spender` terá + * permissão para gastar em nome do `owner` por meio de {transferFrom}. O padrão + * é zero. * - * This value changes when {approve} or {transferFrom} are called. + * Esse valor muda quando {approve} ou {transferFrom} são chamados. */ function allowance(address owner, address spender) external view returns (uint256); ``` -A função `allowance` permite que qualquer pessoa consulte qual é a provisão que um endereço (`owner`) permite que outro endereço (`spender`) gaste. +A função `allowance` permite que qualquer pessoa consulte para ver qual é a permissão que um +endereço (`owner`) permite que outro endereço (`spender`) gaste.   ```solidity /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + * @dev Define `amount` como a permissão de `spender` sobre os tokens do chamador. * - * Returns a boolean value indicating whether the operation succeeded. + * Retorna um valor booleano que indica se a operação foi bem-sucedida. * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. Uma solução possível para mitigar esta corrida - * é primeiramente reduzir a tolerância do remetente para 0 e definir o - * valor desejado depois: + * IMPORTANTE: Cuidado, pois alterar uma permissão com este método traz o risco + * de que alguém possa usar tanto a permissão antiga quanto a nova por meio de uma + * ordem de transação infeliz. Uma solução possível para mitigar essa condição + * de corrida é primeiro reduzir a permissão do gastador para 0 e depois definir o + * valor desejado: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * - * Emite um evento de {Approval}. + * Emite um evento {Approval}. */ function approve(address spender, uint256 amount) external returns (bool); ``` -A função `approve` cria uma provisão. Certifique-se de ler a mensagem sobre como ela pode ser usada indevidamente. No Ethereum, você controla a ordem de suas próprias transações, mas não é possível controlar a ordem na qual as transações de outras pessoas serão executadas, a menos que você não envie sua própria transação até ver a transação de outro lado ser executada. +A função `approve` cria uma permissão. Certifique-se de ler a mensagem sobre +como ela pode ser usada indevidamente. No Ethereum, você controla a ordem de suas próprias transações, +mas não pode controlar a ordem em que as transações de outras pessoas serão +executadas, a menos que você não envie sua própria transação até ver que a +transação da outra parte aconteceu.   ```solidity /** - * @dev Moves `amount` tokens from `sender` to `recipient` using the - * allowance mechanism. O valor é então deduzido do rendimento do chamador. + * @dev Move `amount` tokens de `sender` para `recipient` usando o + * mecanismo de permissão. `amount` é então deduzido da + * permissão do chamador. * - * Returns a boolean value indicating whether the operation succeeded. + * Retorna um valor booleano que indica se a operação foi bem-sucedida. * - * Emits a {Transfer} event. + * Emite um evento {Transfer}. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); ``` -Por fim, `transferFrom` é utilizado pelo cliente para realmente gastar a provisão. +Finalmente, `transferFrom` é usado pelo gastador para realmente gastar a permissão.   ```solidity /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). + * @dev Emitido quando `value` tokens são movidos de uma conta (`from`) para + * outra (`to`). * - * Note that `value` may be zero. + * Note que `value` pode ser zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `Valor` é a nova permissão. + * @dev Emitido quando a permissão de um `spender` para um `owner` é definida por + * uma chamada para {approve}. `value` é a nova permissão. */ event Approval(address indexed owner, address indexed spender, uint256 value); } ``` -Esses eventos são emitidos quando o estado do contrato ERC-20 é alterado. +Esses eventos são emitidos quando o estado do contrato ERC-20 muda. ## O contrato real {#the-actual-contract} -Este é o contrato que implementa o padrão ERC-20, [retirado daqui](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol). Ele não é destinado a ser usado tal como é, mas você pode [herdar](https://www.tutorialspoint.com/solidity/solidity_inheritance.htm) dele para estendê-lo para algo utilizável. +Este é o contrato real que implementa o padrão ERC-20, +[retirado daqui](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol). +Ele não se destina a ser usado como está, mas você pode +[herdar](https://www.tutorialspoint.com/solidity/solidity_inheritance.htm) dele para estendê-lo para algo utilizável. ```solidity // SPDX-License-Identifier: MIT @@ -194,9 +237,9 @@ pragma solidity >=0.6.0 <0.8.0;   -### Importar declarações {#import-statements} +### Declarações de importação {#import-statements} -Além das definições de interface acima, o contrato de definição importa outros dois arquivos: +Além das definições de interface acima, a definição do contrato importa dois outros arquivos: ```solidity @@ -205,8 +248,13 @@ import "./IERC20.sol"; import "../../math/SafeMath.sol"; ``` -- `GSN/Context.sol` são as definições necessárias para usar [OpenGSN](https://www.opengsn.org/), um sistema que permite que usuários sem ether possam usar a blockchain. Observe que esta é uma versão antiga. Se você quiser integrá-la com o OpenGSN [use este tutorial](https://docs.opengsn.org/javascript-client/tutorial.html). -- [A biblioteca SafeMath](https://ethereumdev.io/using-safe-math-library-to-prevent-from-‘overflows’/), que é usada para fazer adições e subtrações sem estouros. Isso é necessário, pois, do contrário, uma pessoa pode ter um token, dois tokens, e então ter 2^256-1 tokens. +- `GSN/Context.sol` são as definições necessárias para usar o [OpenGSN](https://www.opengsn.org/), um sistema que permite que usuários sem ether + usem a blockchain. Observe que esta é uma versão antiga; se você quiser integrar com o OpenGSN, + [use este tutorial](https://docs.opengsn.org/javascript-client/tutorial.html). +- [A biblioteca SafeMath](https://ethereumdev.io/using-safe-math-library-to-prevent-from-overflows/), que impede + estouros/subfluxos aritméticos para versões do Solidity **<0.8.0**. No Solidity ≥0.8.0, as operações aritméticas revertem + automaticamente em caso de estouro/subfluxo, tornando o SafeMath desnecessário. Este contrato usa o SafeMath para compatibilidade com versões anteriores + de compiladores mais antigos.   @@ -214,33 +262,33 @@ Este comentário explica o propósito do contrato. ```solidity /** - * @dev Implementation of the {IERC20} interface. + * @dev Implementação da interface {IERC20}. * - * This implementation is agnostic to the way tokens are created. Isto significa -* que um mecanismo de oferta deve ser adicionado em um contrato derivado usando {_mint}. - * For a generic mechanism see {ERC20PresetMinterPauser}. + * Esta implementação é agnóstica à forma como os tokens são criados. Isso significa + * que um mecanismo de fornecimento deve ser adicionado em um contrato derivado usando {_mint}. + * Para um mecanismo genérico, veja {ERC20PresetMinterPauser}. * - * TIP: For a detailed writeup see our guide - * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How - * to implement supply mechanisms]. + * DICA: Para um artigo detalhado, consulte nosso guia + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[Como + * implementar mecanismos de fornecimento]. * - * We have followed general OpenZeppelin guidelines: functions revert instead - * of returning `false` on failure. Esse comportamento é, no entanto, convencional - * e não entra em conflito com as expectativas das aplicações do ERC20. + * Seguimos as diretrizes gerais da OpenZeppelin: as funções são revertidas em vez + * de retornar `false` em caso de falha. Esse comportamento, no entanto, é convencional + * e não entra em conflito com as expectativas dos aplicativos ERC20. * - * Additionally, an {Approval} event is emitted on calls to {transferFrom}. - * This allows applications to reconstruct the allowance for all accounts just - * by listening to said events. Outras implementações do EIP podem não emitir + * Além disso, um evento {Approval} é emitido em chamadas para {transferFrom}. + * Isso permite que os aplicativos reconstruam a permissão para todas as contas apenas + * ouvindo esses eventos. Outras implementações da EIP podem não emitir * esses eventos, pois não é exigido pela especificação. * - * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} - * functions have been added to mitigate the well-known issues around setting - * allowances. Veja {IERC20-approve}. + * Finalmente, as funções não padrão {decreaseAllowance} e {increaseAllowance} + * foram adicionadas para mitigar os problemas conhecidos em torno da definição + * de permissões. Veja {IERC20-approve}. */ ``` -### Definição de contrato {#contract-definition} +### Definição do Contrato {#contract-definition} ```solidity contract ERC20 is Context, IERC20 { @@ -256,19 +304,27 @@ Esta linha especifica a herança, neste caso de `IERC20` acima e `Context`, para ``` -Essa linha anexa a biblioteca `SafeMath` ao tipo `uint256`. Você pode encontrar essa biblioteca [aqui](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol). +Essa linha anexa a biblioteca `SafeMath` ao tipo `uint256`. Você pode encontrar esta biblioteca +[aqui](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol). -### Definições de variáveis {#variable-definitions} +### Definições de Variáveis {#variable-definitions} -Essas definições especificam as variáveis de estado do contrato. Existem variáveis declaradas como `private`, mas isso apenas significa que outros contratos na blockchain não as podem ler. _Não há segredos na blockchain_, o software em cada nó possui o estado de cada contrato em cada bloco. Por convenção, as variáveis de estado são denominadas `_`. +Essas definições especificam as variáveis de estado do contrato. Essas variáveis são declaradas como `private`, mas +isso significa apenas que outros contratos na blockchain não podem lê-las. _Não há +segredos na blockchain_, o software em cada nó tem o estado de cada contrato +em cada bloco. Por convenção, as variáveis de estado são nomeadas `_`. -As duas primeiras variáveis são [mapeamentos](https://www.tutorialspoint.com/solidity/solidity_mappings.htm), ou seja, se comportam mais ou menos da mesma forma que [matrizes associativas](https://wikipedia.org/wiki/Associative_array), com exceção das chaves, que são valores numéricos. O armazenamento é alocado apenas para as entradas que possuem valores diferentes do padrão (zero). +As duas primeiras variáveis são [mapeamentos](https://www.tutorialspoint.com/solidity/solidity_mappings.htm), +, o que significa que elas se comportam de forma semelhante a [matrizes associativas](https://wikipedia.org/wiki/Associative_array), +, exceto que as chaves são valores numéricos. O armazenamento só é alocado para entradas que têm valores diferentes +do padrão (zero). ```solidity mapping (address => uint256) private _balances; ``` -O primeiro mapeamento, `_balances`, é composta por endereços e seus respectivos saldos desse token. Para acessar o saldo, utilize a sintaxe: `_balances[
]`. +O primeiro mapeamento, `_balances`, são os endereços e seus respectivos saldos deste token. Para acessar +o saldo, use esta sintaxe: `_balances[]`.   @@ -276,7 +332,9 @@ O primeiro mapeamento, `_balances`, é composta por endereços e seus respectivo mapping (address => mapping (address => uint256)) private _allowances; ``` -Esta variável, `_allowances`, armazena as margens explicadas anteriormente. O primeiro índice é o proprietário das moedas, e o segundo é o contrato com a provisão. Para acessar a quantia que o endereço A pode gastar na conta do endereço B, use `_allowances[B][A]`. +Essa variável, `_allowances`, armazena as permissões explicadas anteriormente. O primeiro índice é o proprietário +dos tokens, e o segundo é o contrato com a permissão. Para acessar a quantia que o endereço A pode +gastar da conta do endereço B, use `_allowances[B][A]`.   @@ -284,7 +342,7 @@ Esta variável, `_allowances`, armazena as margens explicadas anteriormente. O p uint256 private _totalSupply; ``` -Como o nome sugere, essa variável mantém registro do fornecimento total de tokens. +Como o nome sugere, essa variável acompanha o fornecimento total de tokens.   @@ -294,90 +352,102 @@ Como o nome sugere, essa variável mantém registro do fornecimento total de tok uint8 private _decimals; ``` -Essas três variáveis são usadas para melhorar a legibilidade. As duas primeiras são autoexplicativas, mas `_decimals` não. +Essas três variáveis são usadas para melhorar a legibilidade. As duas primeiras são autoexplicativas, mas `_decimals` +não é. -De um lado, o Ethereum não possui ponto flutuante ou variáveis fracionadas. De outro, as pessoas gostam de poder dividir tokens. Uma das razões pelas quais as pessoas estabeleceram o uso do ouro como moeda foi devido à dificuldade de trocá-lo quando alguém queria, por exemplo, comprar vaca pelo valor de um pato. +Por um lado, o Ethereum não tem variáveis de ponto flutuante ou fracionárias. Por outro lado, +os humanos gostam de poder dividir tokens. Uma das razões pelas quais as pessoas optaram pelo ouro como moeda foi porque +era difícil dar troco quando alguém queria comprar o equivalente a um pato em uma vaca. -A solução é manter o registro dos inteiros, mas em vez de contar o token real, contar o token fracionário, que praticamente não tem valor. No caso do ether, a moeda fracionária é chamada de wei, e 10^18 WEI é igual a um ETH. No momento da criação deste artigo, 10.000.000.000.000 WEI equivalem a cerca de um centavo de Dólar ou Euro. +A solução é manter o controle de números inteiros, mas contar, em vez do token real, um token fracionário que é +quase sem valor. No caso do ether, o token fracionário é chamado de wei, e 10^18 wei é igual a um +ETH. No momento em que este artigo foi escrito, 10.000.000.000.000 wei equivalem a aproximadamente um centavo de dólar americano ou euro. -Os aplicativos precisam saber como exibir o saldo do token. Se um usuário tiver 3.141.000.000.000.000.000 WEI, seria equivalente a 3,14 ETH? 31,41 ETH? 3,141 ETH? No caso do ETH, é definido 10^18 WEI para o ETH, mas para sua moeda, você pode escolher um valor diferente. Se dividir uma moeda não fizer sentido, você pode usar um valor `_decimals` de zero. Se você quiser utilizar o mesmo padrão utilizado em ETH, use o valor **18**. +Os aplicativos precisam saber como exibir o saldo do token. Se um usuário tiver 3.141.000.000.000.000.000 wei, isso é +3,14 ETH? 31,41 ETH? 3.141 ETH? No caso do ether, é definido 10^18 wei para o ETH, mas para o seu +token você pode selecionar um valor diferente. Se a divisão do token não fizer sentido, você pode usar um +valor `_decimals` de zero. Se você quiser usar o mesmo padrão do ETH, use o valor **18**. -### O Constructor {#the-constructor} +### O construtor {#the-constructor} ```solidity /** - * @dev Sets the values for {name} and {symbol}, initializes {decimals} with - * a default value of 18. + * @dev Define os valores para {name} e {symbol}, inicializa {decimals} com + * um valor padrão de 18. * - * To select a different value for {decimals}, use {_setupDecimals}. + * Para selecionar um valor diferente para {decimals}, use {_setupDecimals}. * - * All three of these values are immutable: they can only be set once during - * construction. + * Todos esses três valores são imutáveis: eles só podem ser definidos uma vez durante + * a construção. */ constructor (string memory name_, string memory symbol_) public { + // No Solidity ≥0.7.0, 'public' é implícito e pode ser omitido. + _name = name_; _symbol = symbol_; _decimals = 18; } ``` -O construtor é chamado quando o contrato é criado pela primeira vez. Por convenção, os parâmetros da função são denominados `_`. +O construtor é chamado quando o contrato é criado pela primeira vez. Por convenção, os parâmetros da função são nomeados `_`. -### Funções da interface do usuário {#user-interface-functions} +### Funções da Interface do Usuário {#user-interface-functions} ```solidity /** - * @dev Returns the name of the token. + * @dev Retorna o nome do token. */ function name() public view returns (string memory) { return _name; } /** - * @dev Returns the symbol of the token, usually a shorter version of the - * name. + * @dev Retorna o símbolo do token, geralmente uma versão mais curta do + * nome. */ function symbol() public view returns (string memory) { return _symbol; } /** - * @dev Returns the number of decimals used to get its user representation. - * For example, if `decimals` equals `2`, a balance of `505` tokens should - * be displayed to a user as `5,05` (`505 / 10 ** 2`). + * @dev Retorna o número de casas decimais usadas para obter sua representação de usuário. + * Por exemplo, se `decimals` for igual a `2`, um saldo de `505` tokens deve + * ser exibido para um usuário como `5,05` (`505 / 10 ** 2`). * - * Tokens usually opt for a value of 18, imitating the relationship between - * ether and wei. Esse é o valor {ERC20} usado, a menos que {_setupDecimals} seja + * Geralmente, os tokens optam por um valor de 18, imitando a relação entre + * ether e wei. Este é o valor que {ERC20} usa, a menos que {_setupDecimals} seja * chamado. * - * NOTE: This information is only used for _display_ purposes: it in - * no way affects any of the arithmetic of the contract, including - * {IERC20-balanceOf} and {IERC20-transfer}. + * OBSERVAÇÃO: esta informação é usada apenas para fins de _exibição_: ela + * não afeta de forma alguma a aritmética do contrato, incluindo + * {IERC20-balanceOf} e {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } ``` -Essas funções, `nome`, `symbol` e `decimals`, ajudam as interfaces do usuário a conhecer o seu contrato para poderem exibi-lo corretamente. +Essas funções, `name`, `symbol` e `decimals` ajudam as interfaces de usuário a saber sobre o seu contrato para que possam exibi-lo corretamente. -O tipo do retorno é `string memory`, o que significa que retorna uma string que é armazenada na memória. Variáveis, como ‘strings’, podem ser armazenadas em três locais: +O tipo de retorno é `string memory`, o que significa retornar uma string que é armazenada na memória. Variáveis, como +strings, podem ser armazenadas em três locais: -| | Tempo de vida | Acesso ao contrato | Custo em gás | -| ------------- | ----------------- | ------------------ | ------------------------------------------------------------------------ | -| Memória | Chamada da função | Leitura/gravação | Dezenas ou centenas (maior para locais mais altos) | -| Calldata | Chamar Função | Somente leitura | Não pode ser usada como retorno, apenas como tipo de parâmetro de função | -| Armazenamento | Até ser alterado | Ler/Escrever | Alto (800 para leitura, 20 mil para gravação) | +| | Tempo de vida | Acesso ao contrato | Custo de gás | +| ------------- | ----------------- | ------------------ | --------------------------------------------------------------------------------- | +| Memória | Chamada de função | Leitura/Escrita | Dezenas ou centenas (maior para locais mais altos) | +| Calldata | Chamada de função | Somente leitura | Não pode ser usado como um tipo de retorno, apenas um tipo de parâmetro de função | +| Armazenamento | Até ser alterado | Leitura/Escrita | Alto (800 para leitura, 20 mil para escrita) | Neste caso, `memory` é a melhor escolha. -### Informação de leitura do token {#read-token-information} +### Ler informações do token {#read-token-information} -Essas funções fornecem informações sobre o token, seja o fornecimento total ou o saldo de uma conta. +Estas são funções que fornecem informações sobre o token, seja o fornecimento total ou o +saldo de uma conta. ```solidity /** - * @dev See {IERC20-totalSupply}. + * @dev Ver {IERC20-totalSupply}. */ function totalSupply() public view override returns (uint256) { return _totalSupply; @@ -390,30 +460,34 @@ A função `totalSupply` retorna o fornecimento total de tokens. ```solidity /** - * @dev See {IERC20-balanceOf}. + * @dev Ver {IERC20-balanceOf}. */ function balanceOf(address account) public view override returns (uint256) { return _balances[account]; } ``` -Leia o saldo de uma conta. Observe que qualquer um pode obter o saldo da conta de outra pessoa. Não há motivo para esconder essa informação, pois ela está disponível em todos os nós. _Não há segredos na blockchain._ +Leia o saldo de uma conta. Observe que qualquer um pode obter o saldo da conta +de qualquer outra pessoa. Não faz sentido tentar esconder essa informação, porque ela está disponível em todos os +nós de qualquer maneira. _Não há segredos na blockchain._ -### Transferência de tokens {#transfer-tokens} +### Transferir Tokens {#transfer-tokens} ```solidity /** - * @dev See {IERC20-transfer}. + * @dev Ver {IERC20-transfer}. * - * Requirements: + * Requisitos: * - * - `recipient` cannot be the zero address. - * - the caller must have a balance of at least `amount`. + * - `recipient` não pode ser o endereço zero. + * - o chamador deve ter um saldo de pelo menos `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { ``` -A função `transfer` é chamada para transferir os tokens do remetente para um destinatário. Observe que mesmo que ela retorne um valor booleano, o valor é sempre **true**. Se a transferência falhar, o contrato anulará a chamada. +A função `transfer` é chamada para transferir tokens da conta do remetente para uma diferente. Observe +que, embora retorne um valor booleano, esse valor é sempre **verdadeiro**. Se a transferência +falhar, o contrato reverte a chamada.   @@ -423,71 +497,80 @@ A função `transfer` é chamada para transferir os tokens do remetente para um } ``` -A função `_transfer` faz o trabalho real. Ela é uma função privada que só pode ser chamada por outras funções de contrato. Por convenção, funções privadas são denominadas `_`, assim como as variáveis de estado. +A função `_transfer` faz o trabalho real. É uma função privada que só pode ser chamada por +outras funções do contrato. Por convenção, as funções privadas são nomeadas como `_`, da mesma forma que as variáveis +de estado. -Normalmente, usamos `msg.sender` no Solidity para o remetente de mensagens. No entanto, isso rompe a [OpenGSN](http://opengsn.org/). Caso queiramos permitir transações sem Eth com nosso token, precisamos usar `_msgSender()`. Ela retornará `msg.sender` para transações normais, mas para transações sem Eth, ela indicará o signatário original e não o contrato que repassou a mensagem. +Normalmente no Solidity, usamos `msg.sender` para o remetente da mensagem. No entanto, isso quebra o +[OpenGSN](http://opengsn.org/). Se quisermos permitir transações sem ether com nosso token, precisamos +usar `_msgSender()`. Ele retorna `msg.sender` para transações normais, mas para as sem ether +retorna o assinante original e não o contrato que retransmitiu a mensagem. -### Funções de margem {#allowance-functions} +### Funções de Permissão {#allowance-functions} -Estas são as funções que implementam a funcionalidade da margem: `allowance`, `approve`, `transferFrom`, e `_approve`. Além disso, a implementação do OpenZeppelin vai além do padrão básico, para poder incluir alguns recursos que melhoram a segurança: `increaseAllowance`, e `decreaseAllowance`. +Estas são as funções que implementam a funcionalidade de permissão: `allowance`, `approve`, `transferFrom` +e `_approve`. Além disso, a implementação do OpenZeppelin vai além do padrão básico para incluir alguns recursos que melhoram +a segurança: `increaseAllowance` e `decreaseAllowance`. #### A função allowance {#allowance} ```solidity /** - * @dev See {IERC20-allowance}. + * @dev Ver {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } ``` -A função `allowance` permite que todo mundo confira qualquer margem. +A função `allowance` permite que todos verifiquem qualquer permissão. #### A função approve {#approve} ```solidity /** - * @dev See {IERC20-approve}. + * @dev Ver {IERC20-approve}. * - * Requirements: + * Requisitos: * - * - `spender` cannot be the zero address. + * - `spender` não pode ser o endereço zero. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { ``` -Essa função é chamada para criar uma provisão. Ela é semelhante à função `transfer` acima: +Esta função é chamada para criar uma permissão. É semelhante à função `transfer` acima: -- A função apenas chama uma função interna (neste caso, `_approve`) que realmente faz o trabalho. -- A função retorna `true` (se for bem-sucedida) ou é revertida (se falhar). +- A função apenas chama uma função interna (neste caso, `_approve`) que faz o trabalho real. +- A função ou retorna `true` (se for bem-sucedida) ou reverte (se não for).   ```solidity _approve(_msgSender(), spender, amount); - return tu; -} + return true; + } ``` -Usamos funções internas para minimizar a quantidade de lugares onde as mudanças de estado ocorrem. _Qualquer_ função que mude o estado constitui um risco de segurança em potencial que precisa ser auditado para segurança. Dessa forma, temos menos chances de errar. +Usamos funções internas para minimizar o número de locais onde ocorrem mudanças de estado. Qualquer função que altere o +estado é um risco potencial de segurança que precisa ser auditado para segurança. Dessa forma, temos menos chances de errar. #### A função transferFrom {#transferFrom} -Essa é a função que um gastador chama para gastar uma margem. Isso requer duas operações: transfira o valor sendo gasto e reduza a margem nesse valor. +Esta é a função que um gastador chama para gastar uma permissão. Isso requer duas operações: transferir o valor +gasto e reduzir a permissão por esse valor. ```solidity /** - * @dev See {IERC20-transferFrom}. + * @dev Ver {IERC20-transferFrom}. * - * Emits an {Approval} event indicating the updated allowance. Isso não é - * necessário para o EIP. Veja a nota no início do {ERC20}. + * Emite um evento {Approval} indicando a permissão atualizada. Isso não + * é exigido pela EIP. Veja a nota no início de {ERC20}. * - * Requirements: + * Requisitos: * - * - `sender` and `recipient` cannot be the zero address. - * - `sender` must have a balance of at least `amount`. - * - the caller must have allowance for ``sender``'s tokens of at least + * - `sender` e `recipient` não podem ser o endereço zero. + * - `sender` deve ter um saldo de pelo menos `amount`. + * - o chamador deve ter permissão para os tokens de ``sender`` de pelo menos * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual @@ -497,7 +580,9 @@ Essa é a função que um gastador chama para gastar uma margem. Isso requer dua   -A chamada da função `a.sub(b, "message")` faz duas coisas. Primeiro, ela calcula `a-b`, que é a nova margem. Em seguida, ela verifica se esse resultado não é negativo. Se for negativo, a chamada é revertida com a mensagem fornecida. Observe que, quando uma chamada reverte qualquer processamento feito anteriormente a essa chamada, ela é ignorada para não precisarmos desfazer a `_transfer`. +A chamada da função `a.sub(b, "mensagem")` faz duas coisas. Primeiro, calcula `a-b`, que é a nova permissão. +Segundo, verifica se esse resultado não é negativo. Se for negativo, a chamada reverte com a mensagem fornecida. Observe que, quando uma chamada reverte, qualquer processamento feito anteriormente durante essa chamada é ignorado, então não precisamos +desfazer a `_transfer`. ```solidity _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, @@ -506,50 +591,62 @@ A chamada da função `a.sub(b, "message")` faz duas coisas. Primeiro, ela calcu } ``` -#### Adições de segurança do OpenZeppelin {#openzeppelin-safety-additions} +#### Adições de segurança da OpenZeppelin {#openzeppelin-safety-additions} -É perigoso definir uma margem que não seja zero como outro valor que não seja zero, porque você só controla a ordem de suas próprias transações, mas não as de outras pessoas. Imagine que você tenha dois usuários: Alice, que é ingênua, e Bill, que é desonesto. Alice quer solicitar um serviço de Bill que, segundo ela, custa cinco tokens — então, ela dá a Bill uma provisão de cinco tokens. +É perigoso definir uma permissão diferente de zero para outro valor diferente de zero, +porque você só controla a ordem de suas próprias transações, não a de mais ninguém. Imagine que você +tenha dois usuários, Alice, que é ingênua, e Bill, que é desonesto. Alice quer algum serviço de +Bill, que ela acha que custa cinco tokens — então ela dá a Bill uma permissão de cinco tokens. -Então, algo muda e o preço de Bill aumenta para dez tokens. Alice, que ainda quer o serviço, envia uma transação que define a provisão de Bill para dez. No momento em que Bill vê essa nova transação no pool de transações, ele envia uma transação que gasta os cinco tokens de Alice e com uma tarifa de gás muito mais alta que, portanto, será minerada mais rápido. Dessa forma, Bill pode gastar os cinco primeiros tokens e, quando a nova provisão de Alice for minerada, pode gastar mais dez por um preço total de quinze tokens, mais do que Alice queria autorizar. Essa técnica é chamada de [front-running](https://consensysdiligence.github.io/smart-contract-best-practices/attacks/#front-running) +Então algo muda e o preço de Bill sobe para dez tokens. Alice, que ainda quer o serviço, +envia uma transação que define a permissão de Bill para dez. No momento em que Bill vê essa nova transação +no pool de transações, ele envia uma transação que gasta os cinco tokens de Alice e tem um +preço de gás muito mais alto para que seja minerado mais rápido. Dessa forma, Bill pode gastar primeiro cinco tokens e, em seguida, +uma vez que a nova permissão de Alice seja minerada, gastar mais dez por um preço total de quinze tokens, mais do que +Alice pretendia autorizar. Essa técnica é chamada de +[front-running](https://consensysdiligence.github.io/smart-contract-best-practices/attacks/#front-running) -| Transação de Alice | Nonce de Alice | Transação de Bill | Nonce de Bill | A provisão de Bill | Total faturado por Bill de Alice | -| ------------------ | -------------- | ----------------------------- | ------------- | ------------------ | -------------------------------- | -| approve(Bill, 5) | 10 | | | 5 | 0 | -| | | transferFrom(Alice, Bill, 5) | 10.123 | 0 | 5 | -| approve(Bill, 10) | 11 | | | 10 | 5 | -| | | transferFrom(Alice, Bill, 10) | 10.124 | 0 | 15 | +| Transação de Alice | Nonce de Alice | Transação de Bill | Nonce de Bill | Permissão de Bill | Renda Total de Bill vinda de Alice | +| ------------------------------------ | -------------- | ------------------------------------------------ | ---------------------- | ----------------- | ---------------------------------- | +| approve(Bill, 5) | 10 | | | 5 | 0 | +| | | transferFrom(Alice, Bill, 5) | 10.123 | 0 | 5 | +| approve(Bill, 10) | 11 | | | 10 | 5 | +| | | transferFrom(Alice, Bill, 10) | 10.124 | 0 | 15 | -Para evitar esse problema, essas duas funções (`increaseAllowance` e `reduaseAllowance`) permitem que você modifique a provisão por um valor específico. Então, se Bill já tinha gastado cinco tokens, ele só poderá gastar mais cinco tokens. Dependendo do tempo disponível, há duas maneiras de proceder, sendo que as duas acabam com Bill obtendo os dez tokens: +Para evitar esse problema, essas duas funções (`increaseAllowance` e `decreaseAllowance`) permitem que você +modifique a permissão por um valor específico. Então, se Bill já gastou cinco tokens, ele só +conseguirá gastar mais cinco. Dependendo do tempo, existem duas maneiras de isso funcionar, ambas +terminando com Bill recebendo apenas dez tokens: A: -| Transação de Alice | Nonce de Alice | Transação de Bill | Nonce de Bill | Permissão de Bill | Cobrança Total de Alice | -| -------------------------- | --------------:| ---------------------------- | -------------:| -----------------:| ----------------------- | -| approve(Bill, 5) | 10 | | | 5 | 0 | -| | | transferFrom(Alice, Bill, 5) | 10,123 | 0 | 5 | -| increaseAllowance(Bill, 5) | 11 | | | 0+5 = 5 | 5 | -| | | transferFrom(Alice, Bill, 5) | 10,124 | 0 | 10 | +| Transação de Alice | Nonce de Alice | Transação de Bill | Nonce de Bill | Permissão de Bill | Renda Total de Bill vinda de Alice | +| --------------------------------------------- | -------------: | ----------------------------------------------- | ---------------------: | ----------------: | ---------------------------------- | +| approve(Bill, 5) | 10 | | | 5 | 0 | +| | | transferFrom(Alice, Bill, 5) | 10.123 | 0 | 5 | +| increaseAllowance(Bill, 5) | 11 | | | 0+5 = 5 | 5 | +| | | transferFrom(Alice, Bill, 5) | 10.124 | 0 | 10 | B: -| Transação de Alice | Nonce de Alice | Transação de Bill | Nonce de Bill | Permissão de Bill | Cobrança Total de Alice | -| -------------------------- | --------------:| ----------------------------- | -------------:| -----------------:| -----------------------:| -| approve(Bill, 5) | 10 | | | 5 | 0 | -| increaseAllowance(Bill, 5) | 11 | | | 5+5 = 10 | 0 | -| | | transferFrom(Alice, Bill, 10) | 10,124 | 0 | 10 | +| Transação de Alice | Nonce de Alice | Transação de Bill | Nonce de Bill | Permissão de Bill | Renda Total de Bill vinda de Alice | +| --------------------------------------------- | -------------: | ------------------------------------------------ | ---------------------: | ----------------: | ---------------------------------: | +| approve(Bill, 5) | 10 | | | 5 | 0 | +| increaseAllowance(Bill, 5) | 11 | | | 5+5 = 10 | 0 | +| | | transferFrom(Alice, Bill, 10) | 10.124 | 0 | 10 | ```solidity /** - * @dev Atomically increases the allowance granted to `spender` by the caller. + * @dev Aumenta atomicamente a permissão concedida ao `spender` pelo chamador. * - * This is an alternative to {approve} that can be used as a mitigation for - * problems described in {IERC20-approve}. + * Esta é uma alternativa para {approve} que pode ser usada como uma mitigação para + * os problemas descritos em {IERC20-approve}. * - * Emits an {Approval} event indicating the updated allowance. + * Emite um evento {Approval} indicando a permissão atualizada. * - * Requirements: + * Requisitos: * - * - `spender` cannot be the zero address. + * - `spender` não pode ser o endereço zero. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); @@ -557,22 +654,23 @@ B: } ``` -A função `a.add(b)` é uma adição segura. No caso improvável de `um`+`b`>=`2^256`, ele não é contornado da mesma maneira que uma adição normal. +A função `a.add(b)` é uma adição segura. No caso improvável de `a`+`b`>=`2^256`, ele não dá a volta +como a adição normal faz. ```solidity /** - * @dev Atomically decreases the allowance granted to `spender` by the caller. + * @dev Diminui atomicamente a permissão concedida ao `spender` pelo chamador. * - * This is an alternative to {approve} that can be used as a mitigation for - * problems described in {IERC20-approve}. + * Esta é uma alternativa para {approve} que pode ser usada como uma mitigação para + * os problemas descritos em {IERC20-approve}. * - * Emits an {Approval} event indicating the updated allowance. + * Emite um evento {Approval} indicando a permissão atualizada. * - * Requirements: + * Requisitos: * - * - `spender` cannot be the zero address. - * - `spender` must have allowance for the caller of at least + * - `spender` não pode ser o endereço zero. + * - `spender` deve ter uma permissão para o chamador de pelo menos * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { @@ -582,31 +680,33 @@ A função `a.add(b)` é uma adição segura. No caso improvável de `um`+`b`>=` } ``` -### Funções que modificam informações do token {#functions-that-modify-token-information} +### Funções que modificam as informações do token {#functions-that-modify-token-information} -Essas são as quatro funções que realmente funcionam: `_transfer`, `_mint`, `_burn`, e `_appro`. +Estas são as quatro funções que fazem o trabalho real: `_transfer`, `_mint`, `_burn` e `_approve`. -#### A função \_transfer {#_transfer} +#### A função _transfer {#_transfer} ```solidity /** - * @dev Moves tokens `amount` from `sender` to `recipient`. + * @dev Move `amount` de tokens de `sender` para `recipient`. * - * This is internal function is equivalent to {transfer}, and can be used to - * e.g., implement automatic token fees, slashing mechanisms, etc. + * Esta função interna é equivalente a {transfer} e pode ser usada para + * implementar, por exemplo, taxas automáticas de tokens, mecanismos de slashing, etc. * - * Emits a {Transfer} event. + * Emite um evento {Transfer}. * - * Requirements: + * Requisitos: * - * - `sender` cannot be the zero address. - * - `recipient` cannot be the zero address. - * - `sender` must have a balance of at least `amount`. + * - `sender` não pode ser o endereço zero. + * - `recipient` não pode ser o endereço zero. + * - `sender` deve ter um saldo de pelo menos `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { ``` -Esta função, `_transfer`, transfere moedas de uma conta para outra. Ela é chamada por `transfer` (para transferências da própria conta do remetente) e `transferFrom` (para usar as provisões a serem transferidas da conta de outra pessoa). +Esta função, `_transfer`, transfere tokens de uma conta para outra. Ela é chamada tanto por +`transfer` (para transferências da própria conta do remetente) quanto por `transferFrom` (para usar permissões +para transferir da conta de outra pessoa).   @@ -615,7 +715,9 @@ Esta função, `_transfer`, transfere moedas de uma conta para outra. Ela é cha require(recipient != address(0), "ERC20: transfer to the zero address"); ``` -Na verdade, ninguém possui o endereço zero no Ethereum (ou seja, ninguém conhece uma chave privada cuja chave pública correspondente tenha sido transformada no endereço zero). Quando as pessoas usam esse endereço, geralmente se trata de um bug de software, portanto, falhamos se o endereço zero é usado como o remetente ou o destinatário. +Ninguém realmente possui o endereço zero no Ethereum (ou seja, ninguém conhece uma chave privada cuja chave pública correspondente +seja transformada no endereço zero). Quando as pessoas usam esse endereço, geralmente é um bug de software — então, +falhamos se o endereço zero for usado como remetente ou destinatário.   @@ -627,11 +729,14 @@ Na verdade, ninguém possui o endereço zero no Ethereum (ou seja, ninguém conh Existem duas maneiras de usar esse contrato: 1. Use-o como um modelo para o seu próprio código -1. [Herde a partir daqui](https://www.bitdegree.org/learn/solidity-inheritance) e substitua apenas as funções que você precisa modificar +2. [Herdar dele](https://www.bitdegree.org/learn/solidity-inheritance), e substituir apenas as funções que você precisa modificar -O segundo método é muito melhor, porque o código OpenZeppelin ERC-20 já foi auditado e comprovado como seguro. Ao usar a herança, é fácil distinguir quais são as funções que você modificou e, para confiar nos seus contratos, as pessoas só precisam auditar essas funções específicas. +O segundo método é muito melhor porque o código ERC-20 da OpenZeppelin já foi auditado e demonstrou ser seguro. Quando você usa herança, +fica claro quais são as funções que você modifica, e para confiar em seu contrato, as pessoas só precisam auditar essas funções específicas. -Geralmente, é útil executar uma função toda vez que os tokens mudam de mãos. No entanto,`_transfer` é uma função muito importante e é possível escrevê-la de forma não segura (veja abaixo). Portanto, é melhor não substituí-la. A solução é `_beforeTokenTransfer`, uma [função hook](https://wikipedia.org/wiki/Hooking). Você pode substituir essa função e ela será chamada em cada transferência. +Muitas vezes, é útil executar uma função cada vez que os tokens trocam de mãos. No entanto, `_transfer` é uma função muito importante e é +possível escrevê-la de forma insegura (veja abaixo), então é melhor não substituí-la. A solução é `_beforeTokenTransfer`, uma +[função de gancho (hook)](https://wikipedia.org/wiki/Hooking). Você pode substituir essa função e ela será chamada em cada transferência.   @@ -640,7 +745,10 @@ Geralmente, é útil executar uma função toda vez que os tokens mudam de mãos _balances[recipient] = _balances[recipient].add(amount); ``` -Essas são as linhas que realmente executam a transferência. Observe que não há **nada** entre elas, e que subtraímos o valor transferido do remetente antes de adicioná-lo ao destinatário. Isso é importante, pois se tivesse ocorrido uma chamada para um contrato diferente nesse meio tempo, ela poderia ter sido utilizada para enganar esse contrato. Dessa forma, a transferência é atômica, ou seja, nada pode acontecer enquanto ela está em execução. +Estas são as linhas que realmente fazem a transferência. Note que não há **nada** entre elas, e que subtraímos +o valor transferido do remetente antes de adicioná-lo ao destinatário. Isso é importante porque, se houvesse uma +chamada para um contrato diferente no meio, isso poderia ter sido usado para enganar este contrato. Desta forma, a transferência +é atômica, nada pode acontecer no meio dela.   @@ -649,23 +757,31 @@ Essas são as linhas que realmente executam a transferência. Observe que não h } ``` -Essa função emite o evento `Transfer`. Os eventos não são acessíveis para contratos inteligentes, mas o código executado fora da blockchain pode ouvir os eventos e reagir a eles. Por exemplo, uma carteira pode monitorar quando o proprietário obtém mais tokens. +Finalmente, emita um evento `Transfer`. Eventos não são acessíveis a contratos inteligentes, mas o código executado fora da blockchain +pode ouvir eventos e reagir a eles. Por exemplo, uma carteira pode acompanhar quando o proprietário recebe mais tokens. -#### As funções \_mint e \_burn {#_mint-and-_burn} +#### As funções _mint e _burn {#_mint-and-_burn} -Essas duas funções (`_mint` e `_burn`) modificam o fornecimento total de moedas. Elas são internas e não há nenhuma função que as chame nesse contrato, portanto, elas só são úteis se você herdar do contrato e adicionar sua própria lógica para decidir em que condições gerar novos tokens ou usar os tokens já existentes. +Essas duas funções (`_mint` e `_burn`) modificam o fornecimento total de tokens. +Elas são internas e não há nenhuma função que as chame neste contrato, +então elas só são úteis se você herdar do contrato e adicionar sua própria +lógica para decidir sob quais condições criar (mint) novos tokens ou queimar (burn) os existentes. -**OBSERVAÇÃO:** Todos os tokens ERC-20 têm sua própria lógica comercial que dita o gerenciamento de tokens. Por exemplo, um contrato de fornecimento fixo só pode chamar `_mint` no construtor e nunca chamar `_burn`. Um contrato que vende tokens chamará `_mint` quando for pago, e provavelmente chamará `_burn` em algum momento para evitar hiperinflação. +**NOTA:** todo token ERC-20 tem sua própria lógica de negócios que dita o gerenciamento de tokens. +Por exemplo, um contrato de fornecimento fixo pode chamar `_mint` apenas +no construtor e nunca chamar `_burn`. Um contrato que vende tokens +chamará `_mint` quando for pago e, presumivelmente, chamará `_burn` em algum momento +para evitar uma inflação descontrolada. ```solidity - /** @dev Creates `amount` tokens and assigns them to `account`, increasing - * the total supply. + /** @dev Cria `amount` de tokens e os atribui a `account`, aumentando + * o fornecimento total. * - * Emits a {Transfer} event with `from` set to the zero address. + * Emite um evento {Transfer} com `from` definido para o endereço zero. * - * Requirements: + * Requisitos: * - * - `to` cannot be the zero address. + * - `to` não pode ser o endereço zero. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); @@ -676,21 +792,21 @@ Essas duas funções (`_mint` e `_burn`) modificam o fornecimento total de moeda } ``` -Certifique-se de atualizar o `_totalSupply` quando o número total de tokens mudar. +Certifique-se de atualizar `_totalSupply` quando o número total de tokens mudar.   -``` +```solidity /** - * @dev Destroys `amount` tokens from `account`, reducing the - * total supply. + * @dev Destrói `amount` de tokens da `account`, reduzindo o + * fornecimento total. * - * Emits a {Transfer} event with `to` set to the zero address. + * Emite um evento {Transfer} com `to` definido para o endereço zero. * - * Requirements: + * Requisitos: * - * - `account` cannot be the zero address. - * - `account` must have at least `amount` tokens. + * - `account` não pode ser o endereço zero. + * - `account` deve ter pelo menos `amount` de tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); @@ -703,25 +819,28 @@ Certifique-se de atualizar o `_totalSupply` quando o número total de tokens mud } ``` -A função `_burn` é quase idêntica à `_mint`, exceto que ela funciona na direção inversa. +A função `_burn` é quase idêntica a `_mint`, exceto que vai na outra direção. -#### A função \_approve {#_approve} +#### A função _approve {#_approve} -Essa é a função que especifica as provisões. Observe que ela permite que um proprietário especifique uma provisão superior ao saldo atual do proprietário. Isso não tem problema, pois o saldo é verificado no momento da transferência, quando ele poderia diferir do saldo no momento da criação da provisão. +Esta é a função que realmente especifica as permissões. Observe que ela permite que um proprietário especifique +uma permissão que é maior que o saldo atual do proprietário. Isso não é um problema, porque o saldo é +verificado no momento da transferência, quando poderia ser diferente do saldo quando a permissão foi +criada. ```solidity /** - * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * @dev Define `amount` como a permissão de `spender` sobre os tokens do `owner`. * - * This internal function is equivalent to `approve`, and can be used to - * e.g., set automatic allowances for certain subsystems, etc. + * Essa função interna é equivalente a `approve` e pode ser usada para + * por exemplo, definir permissões automáticas para certos subsistemas, etc. * - * Emits an {Approval} event. + * Emite um evento {Approval}. * - * Requirements: + * Requisitos: * - * - `owner` cannot be the zero address. - * - `spender` cannot be the zero address. + * - `owner` não pode ser o endereço zero. + * - `spender` não pode ser o endereço zero. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); @@ -732,7 +851,8 @@ Essa é a função que especifica as provisões. Observe que ela permite que um   -Emita um evento `Approval`. Dependendo de como o aplicativo é escrito, o contrato do gastador pode ser informado sobre a aprovação, seja pelo proprietário, seja pelo servidor que realiza esses eventos. +Emita um evento `Approval`. Dependendo de como o aplicativo é escrito, o contrato do gastador pode ser informado sobre a +aprovação pelo proprietário ou por um servidor que escuta esses eventos. ```solidity emit Approval(owner, spender, amount); @@ -740,57 +860,74 @@ Emita um evento `Approval`. Dependendo de como o aplicativo é escrito, o contra ``` -### Modificando as variáveis decimais {#modify-the-decimals-variable} +### Modificar a variável Decimals {#modify-the-decimals-variable} ```solidity /** - * @dev Sets {decimals} to a value other than the default one of 18. + * @dev Define {decimals} para um valor diferente do padrão de 18. * - * WARNING: This function should only be called from the constructor. A maioria dos - * aplicativos que interagem com contratos das moedas não esperarão que - * {decimals} altere, e pode funcionar incorretamente se ele o fizer. + * AVISO: Esta função só deve ser chamada a partir do construtor. A maioria dos + * aplicativos que interagem com contratos de token não esperam que + * {decimals} mude, e podem funcionar incorretamente se isso acontecer. */ function _setupDecimals(uint8 decimals_) internal { _decimals = decimals_; } ``` -Essa função modifica a variável `_decimals` utilizada para dizer às ‘interfaces’ de usuário como interpretar o valor. Você deve chamá-la a partir do construtor. Seria desonesto chamá-la em qualquer ponto subsequente, ainda mais que aplicativos não são projetados para lidar com isso. +Esta função modifica a variável `_decimals`, que é usada para dizer às interfaces de usuário como interpretar o valor. +Você deve chamá-la a partir do construtor. Seria desonesto chamá-la em qualquer ponto subsequente, e os aplicativos +não são projetados para lidar com isso. ### Ganchos {#hooks} ```solidity /** - * @dev Hook that is called before any transfer of tokens. This includes - * minting and burning. + * @dev Gancho (hook) que é chamado antes de qualquer transferência de tokens. Isso inclui + * criação (minting) e queima (burning). * - * Calling conditions: + * Condições de chamada: * - * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens - * will be to transferred to `to`. - * - when `from` is zero, `amount` tokens will be minted for `to`. - * - when `to` is zero, `amount` of ``from``'s tokens will be burned. - * - `from` and `to` are never both zero. + * - quando `from` e `to` são ambos diferentes de zero, `amount` dos tokens de `from` + * serão transferidos para `to`. + * - quando `from` é zero, `amount` de tokens serão criados (minted) para `to`. + * - quando `to` é zero, `amount` dos tokens de `from` serão queimados (burned). + * - `from` e `to` nunca são ambos zero. * - * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + * Para saber mais sobre ganchos (hooks), acesse xref:ROOT:extending-contracts.adoc#using-hooks[Usando Ganchos (Hooks)]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } } ``` -Essa é a função hook a ser chamada durante as transferências. Ela está vazia, mas se precisar dela para fazer algo, basta sobrescrevê-la. +Esta é a função de gancho (hook) a ser chamada durante as transferências. Está vazia aqui, mas se você precisar +que ela faça algo, basta substituí-la. ## Conclusão {#conclusion} -Resumindo, aqui estão algumas das ideias mais importantes neste contrato (na minha opinião, pode ser que as suas não sejam as mesmas): - -- _Não há segredos na blockchain_. Qualquer informação que um contrato inteligente possa acessar está disponível para o mundo inteiro. -- Você pode controlar a ordem de suas transações, mas não quando transações de outras pessoas estão em andamento. É por isso que alterar uma provisão pode ser perigoso, porque permite que o gastador gaste a soma das duas provisões. -- Valores do tipo `uint256` aproximados. Em outras palavras, _0-1=2^256-1_. Se esse não for o comportamento desejado, você precisa verificá-lo (ou usar a biblioteca SafeMath que faz isso por você). Observe que isso foi alterado em [Solidity 0.8.0](https://docs.soliditylang.org/en/breaking/080-breaking-changes.html). -- Faça todas as mudanças de estado de um tipo específico e em um local específico, pois isso facilita a auditoria. Esse é o motivo pelo qual temos, por exemplo, `_approve`, chamado por `approve`, `transferFrom`, `increaseAllowance` e `decreaseAllowance` -- Mudanças de estado devem ser atômicas, sem qualquer outra ação no meio (como se pode ver em `_transfer`). Isso ocorre, pois, durante a mudança de estado, o estado é inconsistente. Por exemplo, entre o tempo que você deduz do saldo do remetente e o tempo de adicionar ao saldo do beneficiário, há menos tokens existentes do que deveria haver. Isto pode ser potencialmente explorado mal-intencionadamente se houver operações entre eles, especialmente chamadas para um contrato diferente. - -Agora que você já viu como o contrato do OpenZeppelin ERC-20 é escrito, e especialmente como ele se tornou mais seguro, escreva seus próprios contratos e aplicativos seguros. +Para revisar, aqui estão algumas das ideias mais importantes neste contrato (na minha opinião, a sua provavelmente irá variar): + +- _Não há segredos na blockchain_. Qualquer informação que um contrato inteligente possa acessar + está disponível para o mundo todo. +- Você pode controlar a ordem de suas próprias transações, mas não quando as transações de outras pessoas + acontecem. Esta é a razão pela qual alterar uma permissão pode ser perigoso, porque permite + que o gastador gaste a soma de ambas as permissões. +- Valores do tipo `uint256` dão a volta (wrap around). Em outras palavras, _0-1=2^256-1_. Se esse não for o comportamento + desejado, você deve verificá-lo (ou usar a biblioteca SafeMath que faz isso por você). Observe que isso mudou no + [Solidity 0.8.0](https://docs.soliditylang.org/en/breaking/080-breaking-changes.html). +- Faça todas as mudanças de estado de um tipo específico em um local específico, porque isso facilita a auditoria. + Esta é a razão pela qual temos, por exemplo, `_approve`, que é chamado por `approve`, `transferFrom`, + `increaseAllowance` e `decreaseAllowance` +- As mudanças de estado devem ser atômicas, sem qualquer outra ação no meio delas (como você pode ver + em `_transfer`). Isso ocorre porque, durante a mudança de estado, você tem um estado inconsistente. Por exemplo, + entre o momento em que você deduz do saldo do remetente e o momento em que adiciona ao saldo do + destinatário, existem menos tokens em existência do que deveria haver. Isso poderia ser potencialmente explorado se houver + operações entre eles, especialmente chamadas para um contrato diferente. + +Agora que você viu como o contrato ERC-20 da OpenZeppelin é escrito, e especialmente como ele é +tornado mais seguro, vá e escreva seus próprios contratos e aplicativos seguros. + +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). diff --git a/public/content/translations/pt-br/developers/tutorials/erc20-with-safety-rails/index.md b/public/content/translations/pt-br/developers/tutorials/erc20-with-safety-rails/index.md index 71039047adb..c9ebdfe9fb1 100644 --- a/public/content/translations/pt-br/developers/tutorials/erc20-with-safety-rails/index.md +++ b/public/content/translations/pt-br/developers/tutorials/erc20-with-safety-rails/index.md @@ -1,62 +1,64 @@ --- -title: ERC-20 com Trilhos de Segurança -description: Como ajudar pessoas para evitar erros tolos +title: "ERC-20 com Trilhos de Segurança" +description: Como ajudar as pessoas a evitar erros bobos author: Ori Pomerantz lang: pt-br -tags: - - "erc-20" -skill: intermediate +tags: [ "erc-20" ] +skill: beginner published: 2022-08-15 --- ## Introdução {#introduction} -Uma das melhores coisas sobre o Ethereum é que não há autoridade central que possa modificar ou desfazer transações. Um dos maiores problemas do Ethereum é que não há autoridade central com o poder de desfazer erros de usuário ou transações ilícitas. Neste artigo, você aprenderá sobre alguns dos erros comuns que usuários cometem com tokens [ERC-20](/developers/docs/standards/tokens/erc-20/), assim como criar contratos ERC-20 que ajudam usuários a evitar esses erros, ou que dão a uma autoridade central algum poder (por exemplo, congelar contas). +Uma das grandes vantagens do Ethereum é que não existe uma autoridade central que possa modificar ou desfazer suas transações. Um dos maiores problemas do Ethereum é que não há autoridade central com o poder de desfazer erros de usuário ou transações ilícitas. Neste artigo, você aprenderá sobre alguns dos erros comuns que os usuários cometem com tokens [ERC-20](/developers/docs/standards/tokens/erc-20/), bem como a criar contratos ERC-20 que ajudam os usuários a evitar esses erros ou que dão a uma autoridade central algum poder (por exemplo, para congelar contas). -Observe que, apesar de usarmos o [contrato de token ERC-20 da OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20), este artigo não o explica em maiores detalhes. Você pode encontrar esta informação [aqui](/developers/tutorials/erc20-annotated-code). +Observe que, embora usemos o [contrato de token ERC-20 da OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20), este artigo não o explica em grandes detalhes. Você pode encontrar esta informação [aqui](/developers/tutorials/erc20-annotated-code). Se você quiser ver o código-fonte completo: 1. Abra o [Remix IDE](https://remix.ethereum.org/). -2. Clique o ícone de clonar o github (![clone github icon](icon-clone.png)). -3. Clone o repositório github `https://github.com/qbzzt/20220815-erc20-safety-rails`. +2. Clique no ícone de clonagem do GitHub (![clone github icon](icon-clone.png)). +3. Clone o repositório do GitHub `https://github.com/qbzzt/20220815-erc20-safety-rails`. 4. Abra **contracts > erc20-safety-rails.sol**. ## Criando um contrato ERC-20 {#creating-an-erc-20-contract} -Antes que nós possamos adicionar funcionalidade de trilhos de segurança, nós precisamos de um contrato ERC-20. Neste artigo, usaremos o [o Assistente de contratos da OpenZeppelin](https://docs.openzeppelin.com/contracts/5.x/wizard). Abra-o em outro navegador e siga estas instruções: +Antes de podermos adicionar a funcionalidade de trilhos de segurança, precisamos de um contrato ERC-20. Neste artigo, usaremos o [Assistente de Contratos da OpenZeppelin](https://docs.openzeppelin.com/contracts/5.x/wizard). Abra-o em outro navegador e siga estas instruções: 1. Selecione **ERC20**. -2. Entre estas configurações: + +2. Insira estas configurações: | Parâmetro | Valor | | ------------------------- | ---------------- | | Nome | SafetyRailsToken | | Símbolo | SAFE | - | Pré-cunhagem | 1.000 | + | Pré-cunhagem | 1000 | | Recursos | Nenhum | - | Controle de acesso | Proprietário | + | Controle de acesso | Ownable | | Capacidade de atualização | Nenhum | -3. Suba e clique **Open in Remix** (para o Remix) ou **Download** para usar um ambiente diferente. Vou presumir que você está usando o Remix. Se você estiver usando algo diferente, faça as mudanças apropriadas. -4. Agora, temos um contrato ERC-20 totalmente funcional. Você pode expandir `.deps` e `npm` para ver o código importado. -5. Compile, implante e brinque com o contrato para ver se ele funciona como um contrato ERC-20. Se você precisar aprender como usar o Remix, [use este tutorial](https://remix.ethereum.org/?#activate=udapp,solidity,LearnEth). +3. Role para cima e clique em **Abrir no Remix** (para o Remix) ou **Download** para usar um ambiente diferente. Vou presumir que você está usando o Remix. Se estiver usando algo diferente, faça as alterações apropriadas. + +4. Agora, temos um contrato ERC-20 totalmente funcional. Você pode expandir `.deps` > `npm` para ver o código importado. + +5. Compile, implante e interaja com o contrato para ver que ele funciona como um contrato ERC-20. Se precisar aprender a usar o Remix, [use este tutorial](https://remix.ethereum.org/?#activate=udapp,solidity,LearnEth). ## Erros comuns {#common-mistakes} ### Os erros {#the-mistakes} -Às vezes, os usuários enviam tokens para o endereço errado. Embora não consigamos ler a mente dos usuários para saber o que querem fazer, há dois tipos de erros que ocorrem muitas vezes e são fáceis de detectar: +Às vezes, os usuários enviam tokens para o endereço errado. Embora não possamos ler suas mentes para saber o que eles pretendiam fazer, existem dois tipos de erro que acontecem com frequência e são fáceis de detectar: -1. Enviar os tokens para o próprio endereço do contrato. Por exemplo, [token Optimism's OP](https://optimism.mirror.xyz/qvd0WfuLKnePm1Gxb9dpGchPf5uDz5NSMEFdgirDS4c) acabou acumulando [mais de 120.000](https://optimistic.etherscan.io/address/0x4200000000000000000000000000000000000042#tokentxns) tokens OP em menos de dois meses. Isso representa uma quantia de dinheiro significativa, que presumimos que as pessoas tenham simplesmente perdido. +1. Enviar os tokens para o próprio endereço do contrato. Por exemplo, o [token OP da Optimism](https://optimism.mirror.xyz/qvd0WfuLKnePm1Gxb9dpGchPf5uDz5NSMEFdgirDS4c) conseguiu acumular [mais de 120.000](https://optimism.blockscout.com/address/0x4200000000000000000000000000000000000042) tokens OP em menos de dois meses. Isso representa uma quantia significativa de riqueza que, presumivelmente, as pessoas simplesmente perderam. -2. Enviar os tokens para um endereço vazio, um que não corresponde a uma [conta de propriedade externa](/developers/docs/accounts/#externally-owned-accounts-and-key-pairs) ou um [contrato inteligente](/developers/docs/smart-contracts). Enquanto eu não tenho estatísticas de quão frequente isso acontece, [um incidente poderia ter custado 20.000.000 de tokens](https://gov.optimism.io/t/message-to-optimism-community-from-wintermute/2595). +2. Enviar os tokens para um endereço vazio, um que não corresponde a uma [conta de propriedade externa](/developers/docs/accounts/#externally-owned-accounts-and-key-pairs) ou a um [contrato inteligente](/developers/docs/smart-contracts). Embora eu não tenha estatísticas sobre a frequência com que isso acontece, [um incidente poderia ter custado 20.000.000 de tokens](https://gov.optimism.io/t/message-to-optimism-community-from-wintermute/2595). -### Evitando transferências {#preventing-transfers} +### Impedindo transferências {#preventing-transfers} -O contrato OpenZeppelin ERC-20 inclui [um hook, `_beforeTokenTransfer`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol#L364-L368), que é chamado antes de um token ser transferido. Por padrão, esse hook não faz nada, mas podemos pendurar nossas próprias funcionalidades, como verificações que são anuladas se houver um problema. +O contrato ERC-20 da OpenZeppelin inclui [um hook, `_beforeTokenTransfer`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol#L364-L368), que é chamado antes da transferência de um token. Por padrão, este hook não faz nada, mas podemos vincular nossa própria funcionalidade a ele, como verificações que revertem a transação se houver um problema. -Para usar o hook, adicione esta função depois do construtor: +Para usar o hook, adicione esta função após o construtor: ```solidity function _beforeTokenTransfer(address from, address to, uint256 amount) @@ -73,36 +75,36 @@ Algumas partes desta função podem ser novas se você não estiver muito famili internal virtual ``` -A palavra-chave `virtual` significa que conforme herdamos funcionalidades do `ERC20` e substituímos essa função, outros contratos podem herdar de nós e substituir essa função. +A palavra-chave `virtual` significa que, assim como herdamos a funcionalidade do `ERC20` e substituímos essa função, outros contratos podem herdar de nós e substituir essa função. ```solidity override(ERC20) ``` -Temos que especificar explicitamente que estamos [substituindo](https://docs.soliditylang.org/en/v0.8.15/contracts.html#function-overriding) a definição de token ERC20 de `_beforeTokenTransfer`. Em geral, definições explícitas são muito melhores, do ponto de vista da segurança, do que as implícitas — você não pode se esquecer de que fez algo se isso estive bem na sua frente. Esta também é a razão que nós precisamos para especificar que superclasses `_beforeTokenTransfer` nós estamos sobrepondo. +Temos que especificar explicitamente que estamos [substituindo](https://docs.soliditylang.org/en/v0.8.15/contracts.html#function-overriding) a definição do token ERC20 de `_beforeTokenTransfer`. Em geral, definições explícitas são muito melhores, do ponto de vista da segurança, do que as implícitas — você não pode se esquecer de que fez algo se estiver bem na sua frente. Essa também é a razão pela qual precisamos especificar qual `_beforeTokenTransfer` da superclasse estamos substituindo. ```solidity super._beforeTokenTransfer(from, to, amount); ``` -Esta linha chama a função `_beforeTokenTransfer` do contrato ou contratos que herdamos e que a possui. Neste caso, isto é somente `ERC20`, `Ownable` não tem esse hook. Mesmo que, atualmente, o `ERC20._beforeTokenTransfer` não faça nada, nós o chamamos caso a funcionalidade seja adicionada no futuro (e nós então decidimos reimplantar o contrato, porque contratos não mudam depois da implantação). +Esta linha chama a função `_beforeTokenTransfer` do contrato ou contratos dos quais herdamos que a possuem. Neste caso, é apenas o `ERC20`, o `Ownable` não tem este hook. Mesmo que atualmente o `ERC20._beforeTokenTransfer` não faça nada, nós o chamamos caso uma funcionalidade seja adicionada no futuro (e então decidirmos reimplantar o contrato, porque os contratos não mudam após a implantação). ### Codificando os requisitos {#coding-the-requirements} -Nós queremos adicionar estes requisitos para a função: +Queremos adicionar estes requisitos à função: -- O endereço `to` não pode ser igual a `address(this)`, o endereço do contrato ERC-20 propriamente dito. -- O endereço `to` não pode ser vazio, ele tem de ser: - - Uma conta de propriedade externa (EOA). Nós não podemos checar se um endereço é um EOA diretamente, mas nós podemos checar o saldo em ETH de um endereço. EOAs quase sempre têm um saldo, mesmo que não estejam mais sendo usados — é difícil esvaziá-los até o último wei. - - Um contrato inteligente. Testar se um endereço é um contrato inteligente é um pouco mais difícil. Há um opcode que checa o tamanho do código externo, chamado [`EXTCODESIZE`](https://www.evm.codes/#3b), mas ele não é disponível diretamente em Solidity. Para isso, temos que usar [Yul](https://docs.soliditylang.org/en/v0.8.15/yul.html), que é um assembly da EVM. Há outros valores do Solidity que poderíamos usar ([`
.code` e `
.codehash`](https://docs.soliditylang.org/en/v0.8.15/units-and-global-variables.html#members-of-address-types)), mas eles são mais caros. +- O endereço `to` não pode ser igual a `address(this)`, o endereço do próprio contrato ERC-20. +- O endereço `to` não pode ser vazio, tem que ser: + - Uma conta de propriedade externa (EOA). Não podemos verificar diretamente se um endereço é uma EOA, mas podemos verificar o saldo em ETH de um endereço. As EOAs quase sempre têm um saldo, mesmo que não sejam mais usadas — é difícil limpá-las até o último wei. + - Um contrato inteligente. Testar se um endereço é um contrato inteligente é um pouco mais difícil. Existe um opcode que verifica o tamanho do código externo, chamado [`EXTCODESIZE`](https://www.evm.codes/#3b), mas ele não está disponível diretamente no Solidity. Temos que usar o [Yul](https://docs.soliditylang.org/en/v0.8.15/yul.html), que é o assembly da EVM, para isso. Existem outros valores que poderíamos usar do Solidity ([`
.code` e `
.codehash`](https://docs.soliditylang.org/en/v0.8.15/units-and-global-variables.html#members-of-address-types)), mas eles custam mais. -Vamos passar sobre o código novo, linha a linha: +Vamos analisar o novo código linha por linha: ```solidity - require(to != address(this), "Can't send tokens to the contract address"); + require(to != address(this), "Não é possível enviar tokens para o endereço do contrato"); ``` -Este é o primeiro requisito, verificar se `to` e `this(address)` não são a mesma coisa. +Este é o primeiro requisito, verificar que `to` e `this(address)` não são a mesma coisa. ```solidity bool isToContract; @@ -111,53 +113,53 @@ Este é o primeiro requisito, verificar se `to` e `this(address)` não são a me } ``` -É assim que verificamos se um endereço é um contrato. Não podemos receber saídas diretamente do Yul, então, em vez disso, definimos uma variável para manter o resultado (`isToContract` neste caso). A maneira como o Yul trabalha é considerando cada opcode como uma função. Então, primeiro chamamos [`EXTCODESIZE`](https://www.evm.codes/#3b) para obter o tamanho do contrato e, em seguida, usamos [`GT`](https://www.evm.codes/#11) para verificar se não é zero (estamos lidando com inteiros sem sinal, então claro que ele não pode ser negativo). Então, escrevemos o resultado em `isToContract`. +É assim que verificamos se um endereço é um contrato. Não podemos receber saídas diretamente do Yul, então, em vez disso, definimos uma variável para manter o resultado (`isToContract` neste caso). A maneira como o Yul funciona é que cada opcode é considerado uma função. Então, primeiro chamamos o [`EXTCODESIZE`](https://www.evm.codes/#3b) para obter o tamanho do contrato e, em seguida, usamos o [`GT`](https://www.evm.codes/#11) para verificar se não é zero (estamos lidando com inteiros sem sinal, então, claro, ele não pode ser negativo). Em seguida, escrevemos o resultado em `isToContract`. ```solidity - require(to.balance != 0 || isToContract, "Can't send tokens to an empty address"); + require(to.balance != 0 || isToContract, "Não é possível enviar tokens para um endereço vazio"); ``` -Por fim, temos a verificação real de endereços vazios. +E, finalmente, temos a verificação real para endereços vazios. ## Acesso administrativo {#admin-access} -Algumas vezes é útil ter um administrador que pode desfazer erros. Para reduzir o potencial de abuso, esse administrador pode ser um [multisig](https://blog.logrocket.com/security-choices-multi-signature-wallets/) para que várias pessoas tenham que concordar com uma ação. Neste artigo, teremos dois recursos administrativos: +Às vezes, é útil ter um administrador que possa desfazer erros. Para reduzir o potencial de abuso, este administrador pode ser uma [multisig](https://blog.logrocket.com/security-choices-multi-signature-wallets/) para que várias pessoas tenham que concordar com uma ação. Neste artigo, teremos dois recursos administrativos: -1. Congelar e descongelar contas. Isto pode ser útil, por exemplo, quando uma conta for comprometida. +1. Congelar e descongelar contas. Isso pode ser útil, por exemplo, quando uma conta pode ser comprometida. 2. Limpeza de ativos. - Às vezes, fraudadores enviam tokens fraudulentos para o contrato do token real para ganhar legitimidade. Por exemplo, [veja aqui](https://optimistic.etherscan.io/token/0x2348b1a1228ddcd2db668c3d30207c3e1852fbbe?a=0x4200000000000000000000000000000000000042). O contrato ERC-20 legítimo é [0x4200....0042](https://optimistic.etherscan.io/address/0x4200000000000000000000000000000000000042). A fraude que finge ser o contrato é [0x234....bbe](https://optimistic.etherscan.io/address/0x2348b1a1228ddcd2db668c3d30207c3e1852fbbe). + Às vezes, fraudadores enviam tokens fraudulentos para o contrato do token real para ganhar legitimidade. Por exemplo, [veja aqui](https://optimism.blockscout.com/token/0x2348B1a1228DDCd2dB668c3d30207c3E1852fBbe?tab=holders). O contrato ERC-20 legítimo é [0x4200....0042](https://optimism.blockscout.com/token/0x4200000000000000000000000000000000000042). O golpe que finge ser ele é [0x234....bbe](https://optimism.blockscout.com/token/0x2348B1a1228DDCd2dB668c3d30207c3E1852fBbe). - Também é possível que pessoas enviem tokens ERC-20 legítimos para nosso contrato por erro, que é outra razão para querer ter uma maneira de tirá-los de lá. + Também é possível que as pessoas enviem tokens ERC-20 legítimos para nosso contrato por engano, que é outra razão para querer ter uma maneira de retirá-los. -OpenZeppelin fornece dois mecanismos para habilitar acesso administrativo: +O OpenZeppelin fornece dois mecanismos para habilitar o acesso administrativo: -- [`Ownable`](https://docs.openzeppelin.com/contracts/5.x/access-control#ownership-and-ownable) contratos tem um único priprietário. Funções que tem o [modifier](https://www.tutorialspoint.com/solidity/solidity_function_modifiers.htm) `onlyOwner` só podem ser chamadas por este proprietário. Os proprietários podem transferir a propriedade para outra pessoa ou renunciar a ela completamente. Os direitos de todas as outras contas são geralmente idênticas. -- Os contratos [`AccessControl`](https://docs.openzeppelin.com/contracts/5.x/access-control#role-based-access-control) têm [controle de acesso baseado em função (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control). +- Contratos [`Ownable`](https://docs.openzeppelin.com/contracts/5.x/access-control#ownership-and-ownable) têm um único proprietário. Funções que têm o [modificador](https://www.tutorialspoint.com/solidity/solidity_function_modifiers.htm) `onlyOwner` só podem ser chamadas por esse proprietário. Os proprietários podem transferir a propriedade para outra pessoa ou renunciá-la completamente. Os direitos de todas as outras contas são normalmente idênticos. +- Contratos [`AccessControl`](https://docs.openzeppelin.com/contracts/5.x/access-control#role-based-access-control) têm [controle de acesso baseado em função (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control). -Por simplicidade, neste artigo usamos `Ownable`. +Por uma questão de simplicidade, neste artigo usamos o `Ownable`. ### Congelando e descongelando contratos {#freezing-and-thawing-contracts} Congelar e descongelar contratos requer várias mudanças: -- Um [mapeamento](https://www.tutorialspoint.com/solidity/solidity_mappings.htm) de endereços em [booleanos](https://en.wikipedia.org/wiki/Boolean_data_type) para manter o controle de quais endereços estão congelados. Todos os valores são inicialmente zero, o que, para valores booleanos, é interpretado como falso. Isto é o que queremos porque, por padrão, as contas não são congeladas. +- Um [mapeamento](https://www.tutorialspoint.com/solidity/solidity_mappings.htm) de endereços para [booleanos](https://en.wikipedia.org/wiki/Boolean_data_type) para rastrear quais endereços estão congelados. Todos os valores são inicialmente zero, o que para valores booleanos é interpretado como falso. É isso que queremos, porque, por padrão, as contas não são congeladas. ```solidity mapping(address => bool) public frozenAccounts; ``` -- [Eventos](https://www.tutorialspoint.com/solidity/solidity_events.htm) para informar qualquer pessoa interessada, quando uma conta é congelada ou descongelada. Tecnicamente falando, os eventos não são necessários para essas ações, mas ajuda o código fora da cadeia a ser capaz de ouvir esses eventos e saber o que está acontecendo. É considerado uma boa conduta para um contrato inteligente emiti-los quando acontece algo que pode ser relevante para outra pessoa. +- [Eventos](https://www.tutorialspoint.com/solidity/solidity_events.htm) para informar a qualquer pessoa interessada quando uma conta é congelada ou descongelada. Tecnicamente falando, eventos não são necessários para essas ações, mas ajuda o código off-chain a ser capaz de escutar esses eventos e saber o que está acontecendo. É considerado uma boa prática que um contrato inteligente os emita quando algo que possa ser relevante para outra pessoa acontecer. - Os eventos são indexados, então, será possível pesquisar todas as vezes que uma conta foi congelada ou descongelada. + Os eventos são indexados, portanto, será possível pesquisar todas as vezes que uma conta foi congelada ou descongelada. ```solidity - // When accounts are frozen or unfrozen + // Quando as contas são congeladas ou descongeladas event AccountFrozen(address indexed _addr); event AccountThawed(address indexed _addr); ``` -- Funções para congelar e descongelar contas. Essas duas funções são praticamente idênticas, por isso, analisaremos apenas a função de congelamento. +- Funções para congelar e descongelar contas. Essas duas funções são quase idênticas, então analisaremos apenas a função de congelamento. ```solidity function freezeAccount(address addr) @@ -165,27 +167,27 @@ Congelar e descongelar contratos requer várias mudanças: onlyOwner ``` - As funções marcadas como [`public`](https://www.tutorialspoint.com/solidity/solidity_contracts.htm) podem ser chamadas a partir de outros contratos inteligentes ou diretamente por uma transação. + Funções marcadas como [`public`](https://www.tutorialspoint.com/solidity/solidity_contracts.htm) podem ser chamadas de outros contratos inteligentes ou diretamente por uma transação. ```solidity { - require(!frozenAccounts[addr], "Account already frozen"); + require(!frozenAccounts[addr], "Conta já congelada"); frozenAccounts[addr] = true; emit AccountFrozen(addr); } // freezeAccount ``` - Se a conta já estiver congelada, reverta-a. Caso contrário, congele-a e envie um evento `emit`. + Se a conta já estiver congelada, a transação será revertida. Caso contrário, congele-a e emita um evento com `emit`. -- Mude o `_beforeTokenTransfer` para evitar que o dinheiro seja movido de uma conta congelada. Note que o dinheiro ainda pode ser transferido para a conta congelada. +- Altere o `_beforeTokenTransfer` para impedir que o dinheiro seja movido de uma conta congelada. Observe que o dinheiro ainda pode ser transferido para a conta congelada. ```solidity - require(!frozenAccounts[from], "The account is frozen"); + require(!frozenAccounts[from], "A conta está congelada"); ``` ### Limpeza de ativos {#asset-cleanup} -Para liberar os tokens ERC-20 mantidos por este contrato, precisamos chamar uma função no contrato do token ao qual eles fazem parte, [`transfer`](https://eips.ethereum.org/EIPS/eip-20#transfer) ou [`approve`](https://eips.ethereum.org/EIPS/eip-20#approve). Nesse caso, não faz sentido desperdiçar gás em provisões. Vale mais a pena transferir diretamente. +Para liberar os tokens ERC-20 mantidos por este contrato, precisamos chamar uma função no contrato do token ao qual eles pertencem, seja [`transfer`](https://eips.ethereum.org/EIPS/eip-20#transfer) ou [`approve`](https://eips.ethereum.org/EIPS/eip-20#approve). Não faz sentido desperdiçar gás neste caso com aprovações; é melhor transferir diretamente. ```solidity function cleanupERC20( @@ -198,7 +200,7 @@ Para liberar os tokens ERC-20 mantidos por este contrato, precisamos chamar uma IERC20 token = IERC20(erc20); ``` -Essa é a sintaxe para criar um objeto para um contrato quando recebemos o endereço. Podemos fazer isso porque temos a definição de tokens ERC20 como parte do código-fonte (veja a linha 4) e esse arquivo inclui [a definição para IERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol), a interface para um contrato OpenZeppelin ERC-20. +Essa é a sintaxe para criar um objeto para um contrato quando recebemos o endereço. Podemos fazer isso porque temos a definição para tokens ERC-20 como parte do código-fonte (consulte a linha 4), e esse arquivo inclui [a definição para IERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol), a interface para um contrato ERC-20 da OpenZeppelin. ```solidity uint balance = token.balanceOf(address(this)); @@ -206,8 +208,10 @@ Essa é a sintaxe para criar um objeto para um contrato quando recebemos o ender } ``` -Esta é uma função de limpeza, portanto, provavelmente não queremos deixar nenhum token. Em vez de obter o saldo do usuário manualmente, podemos também automatizar o processo. +Esta é uma função de limpeza, portanto, presumivelmente não queremos deixar nenhum token. Em vez de obter o saldo do usuário manually, podemos também automatizar o processo. ## Conclusão {#conclusion} -Esta não é uma solução perfeita — não há solução perfeita para o problema do “usuário que cometeu um erro”. No entanto, usar esses tipos de verificações pode, pelo menos, evitar alguns erros. A capacidade de congelar contas, embora seja perigosa, pode ser usada para limitar os danos de certos ataques ao negar ao hacker os fundos roubados. +Esta não é uma solução perfeita — não há solução perfeita para o problema do "usuário cometeu um erro". No entanto, o uso desses tipos de verificação pode, pelo menos, evitar alguns erros. A capacidade de congelar contas, embora perigosa, pode ser usada para limitar os danos de certos hacks, negando ao hacker os fundos roubados. + +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). diff --git a/public/content/translations/pt-br/developers/tutorials/ethereum-for-web2-auth/index.md b/public/content/translations/pt-br/developers/tutorials/ethereum-for-web2-auth/index.md new file mode 100644 index 00000000000..1d7e3700541 --- /dev/null +++ b/public/content/translations/pt-br/developers/tutorials/ethereum-for-web2-auth/index.md @@ -0,0 +1,888 @@ +--- +title: "Usando Ethereum para autenticação web2" +description: "Depois de ler este tutorial, um desenvolvedor poderá integrar o login do Ethereum (web3) com o login SAML, um padrão usado na web2 para fornecer single sign-on e outros serviços relacionados. Isso permite que o acesso aos recursos da web2 seja autenticado por meio de assinaturas do Ethereum, com os atributos do usuário provenientes de atestados." +author: Ori Pomerantz +tags: [ "web2", "autenticação", "eas" ] +skill: beginner +lang: pt-br +published: 2025-04-30 +--- + +## Introdução + +[SAML](https://www.onelogin.com/learn/saml) é um padrão usado na web2 para permitir que um [provedor de identidade (IdP)](https://en.wikipedia.org/wiki/Identity_provider#SAML_identity_provider) forneça informações do usuário para [provedores de serviço (SP)](https://en.wikipedia.org/wiki/Service_provider_\(SAML\)). + +Neste tutorial, você aprenderá como integrar assinaturas do Ethereum com SAML para permitir que os usuários usem suas carteiras Ethereum para se autenticarem em serviços da web2 que ainda não suportam o Ethereum nativamente. + +Observe que este tutorial foi escrito para dois públicos distintos: + +- Pessoas do Ethereum que entendem o Ethereum e precisam aprender sobre SAML +- Pessoas da Web2 que entendem de SAML e autenticação da web2 e precisam aprender sobre Ethereum + +Como resultado, ele conterá muito material introdutório que você já conhece. Sinta-se à vontade para pulá-lo. + +### SAML para pessoas do Ethereum + +SAML é um protocolo centralizado. Um provedor de serviço (SP) só aceita afirmações (como \"este é o meu usuário João, ele deve ter permissões para fazer A, B e C\") de um provedor de identidade (IdP) se tiver uma relação de confiança preexistente com ele, ou com a [autoridade certificadora](https://www.ssl.com/article/what-is-a-certificate-authority-ca/) que assinou o certificado daquele IdP. + +Por exemplo, o SP pode ser uma agência de viagens que presta serviços de viagens a empresas, e o IdP pode ser o site interno de uma empresa. Quando os funcionários precisam reservar uma viagem de negócios, a agência de viagens os envia para autenticação pela empresa antes de permitir que eles realmente reservem a viagem. + +![Passo a passo do processo SAML](./fig-01-saml.png) + +Esta é a forma como as três entidades, o navegador, o SP e o IdP, negociam o acesso. O SP não precisa saber nada sobre o usuário que está usando o navegador com antecedência, apenas confiar no IdP. + +### Ethereum para pessoas do SAML + +Ethereum é um sistema descentralizado. + +![Logon do Ethereum](./fig-02-eth-logon.png) + +Os usuários possuem uma chave privada (geralmente mantida em uma extensão do navegador). A partir da chave privada, você pode derivar uma chave pública e, a partir dela, um endereço de 20 bytes. Quando os usuários precisam fazer login em um sistema, eles são solicitados a assinar uma mensagem com um nonce (um valor de uso único). O servidor pode verificar se a assinatura foi criada por esse endereço. + +![Obtendo dados extras de atestados](./fig-03-eas-data.png) + +A assinatura verifica apenas o endereço do Ethereum. Para obter outros atributos do usuário, você normalmente usa [atestados](https://attest.org/). Um atestado normalmente tem estes campos: + +- **Atestador**, o endereço que fez o atestado +- **Destinatário**, o endereço ao qual o atestado se aplica +- **Dados**, os dados que estão sendo atestados, como nome, permissões, etc. +- **Esquema**, o ID do esquema usado para interpretar os dados. + +Devido à natureza descentralizada do Ethereum, qualquer usuário pode fazer atestados. A identidade do atestador é importante para identificar quais atestados consideramos confiáveis. + +## Configuração + +O primeiro passo é ter um SP SAML e um IdP SAML comunicando-se entre si. + +1. Baixe o software. O software de exemplo para este artigo está [no github](https://github.com/qbzzt/250420-saml-ethereum). Diferentes estágios são armazenados em diferentes branches, para este estágio você quer `saml-only` + + ```sh + git clone https://github.com/qbzzt/250420-saml-ethereum -b saml-only + cd 250420-saml-ethereum + pnpm install + ``` + +2. Crie chaves com certificados autoassinados. Isso significa que a chave é sua própria autoridade de certificação e precisa ser importada manualmente para o provedor de serviços. Consulte [a documentação do OpenSSL](https://docs.openssl.org/master/man1/openssl-req/) para obter mais informações. + + ```sh + mkdir keys + cd keys + openssl req -new -x509 -days 365 -nodes -sha256 -out saml-sp.crt -keyout saml-sp.pem -subj /CN=sp/ + openssl req -new -x509 -days 365 -nodes -sha256 -out saml-idp.crt -keyout saml-idp.pem -subj /CN=idp/ + cd .. + ``` + +3. Inicie os servidores (tanto o SP quanto o IdP) + + ```sh + pnpm start + ``` + +4. Acesse o SP na URL [http://localhost:3000/](http://localhost:3000/) e clique no botão para ser redirecionado para o IdP (porta 3001). + +5. Forneça ao IdP seu endereço de e-mail e clique em **Login no provedor de serviços**. Veja que você é redirecionado de volta para o provedor de serviços (porta 3000) e que ele o reconhece pelo seu endereço de e-mail. + +### Explicação detalhada + +Isto é o que acontece, passo a passo: + +![Logon SAML normal sem Ethereum](./fig-04-saml-no-eth.png) + +#### src/config.mts + +Este arquivo contém a configuração tanto para o Provedor de Identidade quanto para o Provedor de Serviços. Normalmente, essas duas seriam entidades diferentes, mas aqui podemos compartilhar código para simplificar. + +```typescript +const fs = await import("fs") + +const protocol="http" +``` + +Por enquanto estamos apenas testando, então não há problema em usar HTTP. + +```typescript +export const spCert = fs.readFileSync("keys/saml-sp.crt").toString() +export const idpCert = fs.readFileSync("keys/saml-idp.crt").toString() +``` + +Leia as chaves públicas, que normalmente estão disponíveis para ambos os componentes (e são confiáveis diretamente ou assinadas por uma autoridade de certificação confiável). + +```typescript +export const spPort = 3000 +export const spHostname = "localhost" +export const spDir = "sp" + +export const idpPort = 3001 +export const idpHostname = "localhost" +export const idpDir = "idp" + +export const spUrl = `${protocol}://${spHostname}:${spPort}/${spDir}` +export const idpUrl = `${protocol}://${idpHostname}:${idpPort}/${idpDir}` +``` + +As URLs para ambos os componentes. + +```typescript +export const spPublicData = { +``` + +Os dados públicos para o provedor de serviços. + +```typescript + entityID: `${spUrl}/metadata`, +``` + +Por convenção, em SAML, o `entityID` é a URL onde os metadados da entidade estão disponíveis. Esses metadados correspondem aos dados públicos aqui, exceto que estão em formato XML. + +```typescript + wantAssertionsSigned: true, + authnRequestsSigned: false, + signingCert: spCert, + allowCreate: true, + assertionConsumerService: [{ + Binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', + Location: `${spUrl}/assertion`, + }] + } +``` + +A definição mais importante para nossos propósitos é o `assertionConsumerServer`. Isso significa que para afirmar algo (por exemplo, \"o usuário que lhe envia esta informação é somebody@example.com\") para o provedor de serviços, precisamos usar [HTTP POST](https://www.w3schools.com/tags/ref_httpmethods.asp) para a URL `http://localhost:3000/sp/assertion`. + +```typescript +export const idpPublicData = { + entityID: `${idpUrl}/metadata`, + signingCert: idpCert, + wantAuthnRequestsSigned: false, + singleSignOnService: [{ + Binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", + Location: `${idpUrl}/login` + }], + singleLogoutService: [{ + Binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", + Location: `${idpUrl}/logout` + }], + } +``` + +Os dados públicos do provedor de identidade são semelhantes. Ele especifica que, para fazer login de um usuário, você envia um POST para `http://localhost:3001/idp/login` e para fazer logout de um usuário, você envia um POST para `http://localhost:3001/idp/logout`. + +#### src/sp.mts + +Este é o código que implementa um provedor de serviços. + +```typescript +import * as config from "./config.mts" +const fs = await import("fs") +const saml = await import("samlify") +``` + +Usamos a biblioteca [`samlify`](https://www.npmjs.com/package/samlify) para implementar o SAML. + +```typescript +import * as validator from "@authenio/samlify-node-xmllint" +saml.setSchemaValidator(validator) +``` + +A biblioteca `samlify` espera ter um pacote que valide se o XML está correto, assinado com a chave pública esperada, etc. Usamos [`@authenio/samlify-node-xmllint`](https://www.npmjs.com/package/@authenio/samlify-node-xmllint) para essa finalidade. + +```typescript +const express = (await import("express")).default +const spRouter = express.Router() +const app = express() +``` + +Um [`Router`](https://expressjs.com/en/5x/api.html#router) do [`express`](https://expressjs.com/) é um "mini site" que pode ser montado dentro de um site. Nesse caso, nós o usamos para agrupar todas as definições do provedor de serviços. + +```typescript +const spPrivateKey = fs.readFileSync("keys/saml-sp.pem").toString() + +const sp = saml.ServiceProvider({ + privateKey: spPrivateKey, + ...config.spPublicData +}) +``` + +A representação do próprio provedor de serviços de si mesmo são todos os dados públicos e a chave privada que ele usa para assinar informações. + +```typescript +const idp = saml.IdentityProvider(config.idpPublicData); +``` + +Os dados públicos contêm tudo o que o provedor de serviços precisa saber sobre o provedor de identidade. + +```typescript +spRouter.get(`/metadata`, + (req, res) => res.header("Content-Type", "text/xml").send(sp.getMetadata()) +) +``` + +Para permitir a interoperabilidade com outros componentes SAML, os provedores de serviços e de identidade devem ter seus dados públicos (chamados de metadados) disponíveis em formato XML em `/metadata`. + +```typescript +spRouter.post(`/assertion`, +``` + +Esta é a página acessada pelo navegador para se identificar. A afirmação inclui o identificador do usuário (aqui usamos o endereço de e-mail) e pode incluir atributos adicionais. Este é o manipulador para a etapa 7 no diagrama de sequência acima. + +```typescript + async (req, res) => { + // console.log(`SAML response:\n${Buffer.from(req.body.SAMLResponse, 'base64').toString('utf-8')}`) +``` + +Você pode usar o comando comentado para ver os dados XML fornecidos na asserção. Ele é [codificado em base64](https://en.wikipedia.org/wiki/Base64). + +```typescript + try { + const loginResponse = await sp.parseLoginResponse(idp, 'post', req); +``` + +Analise a solicitação de login do servidor de identidade. + +```typescript + res.send(` + + +

Hello ${loginResponse.extract.nameID}

+ + + `) + res.send(); +``` + +Envie uma resposta HTML, apenas para mostrar ao usuário que recebemos o login. + +```typescript + } catch (err) { + console.error('Error processing SAML response:', err); + res.status(400).send('SAML authentication failed'); + } + } +) +``` + +Informe o usuário em caso de falha. + +```typescript +spRouter.get('/login', +``` + +Crie uma solicitação de login quando o navegador tentar obter esta página. Este é o manipulador para a etapa 1 no diagrama de sequência acima. + +```typescript + async (req, res) => { + const loginRequest = await sp.createLoginRequest(idp, "post") +``` + +Obtenha as informações para postar uma solicitação de login. + +```typescript + res.send(` + + + +``` + +Esta página envia o formulário (veja abaixo) automaticamente. Dessa forma, o usuário não precisa fazer nada para ser redirecionado. Esta é a etapa 2 no diagrama de sequência acima. + +```typescript +
+``` + +Poste para `loginRequest.entityEndpoint` (a URL do ponto de extremidade do provedor de identidade). + +```typescript + +``` + +O nome da entrada é `loginRequest.type` (`SAMLRequest`). O conteúdo para esse campo é `loginRequest.context`, que é novamente XML codificado em base64. + +```typescript +
+ + + `) + } +) + +app.use(express.urlencoded({extended: true})) +``` + +[Este middleware](https://expressjs.com/en/5x/api.html#express.urlencoded) lê o corpo da [requisição HTTP](https://www.tutorialspoint.com/http/http_requests.htm). Por padrão, o express o ignora, porque a maioria das requisições não o exige. Nós precisamos dele porque o POST usa o corpo. + +```typescript +app.use(`/${config.spDir}`, spRouter) +``` + +Monte o roteador no diretório do provedor de serviços (`/sp`). + +```typescript +app.get("/", (req, res) => { + res.send(` + + + + + + `) +}) +``` + +Se um navegador tentar obter o diretório raiz, forneça a ele um link para a página de login. + +```typescript +app.listen(config.spPort, () => { + console.log(`service provider is running on http://${config.spHostname}:${config.spPort}`) +}) +``` + +Escute a `spPort` com este aplicativo express. + +#### src/idp.mts + +Este é o provedor de identidade. É muito semelhante ao provedor de serviços, as explicações abaixo são para as partes que são diferentes. + +```typescript +const xmlParser = new (await import("fast-xml-parser")).XMLParser( + { + ignoreAttributes: false, // Preserve attributes + attributeNamePrefix: "@_", // Prefix for attributes + } +) +``` + +Precisamos ler e entender a solicitação XML que recebemos do provedor de serviços. + +```typescript +const getLoginPage = requestId => ` +``` + +Esta função cria a página com o formulário enviado automaticamente que é retornado na etapa 4 do diagrama de sequência acima. + +```typescript + + + Página de login + + +

Página de login

+
+ + Endereço de e-mail: +
+ +``` + +Há dois campos que enviamos ao provedor de serviços: + +1. O `requestId` ao qual estamos respondendo. +2. O identificador do usuário (usamos o endereço de e-mail que o usuário fornece por enquanto). + +```typescript +
+ + + +const idpRouter = express.Router() + +idpRouter.post("/loginSubmitted", async (req, res) => { + const loginResponse = await idp.createLoginResponse( +``` + +Este é o manipulador para a etapa 5 no diagrama de sequência acima. [`idp.createLoginResponse`](https://github.com/tngan/samlify/blob/master/src/entity-idp.ts#L73-L125) cria a resposta de login. + +```typescript + sp, + { + authnContextClassRef: 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport', + audience: sp.entityID, +``` + +O público é o provedor de serviços. + +```typescript + extract: { + request: { + id: req.body.requestId + } + }, +``` + +Informações extraídas da solicitação. O único parâmetro que nos interessa na solicitação é o requestId, que permite ao provedor de serviços corresponder as solicitações e suas respostas. + +```typescript + signingKey: { privateKey: idpPrivateKey, publicKey: config.idpCert } // Ensure signing +``` + +Precisamos que o `signingKey` tenha os dados para assinar a resposta. O provedor de serviços não confia em solicitações não assinadas. + +```typescript + }, + "post", + { + email: req.body.email +``` + +Este é o campo com as informações do usuário que enviamos de volta ao provedor de serviços. + +```typescript + } + ); + + res.send(` + + + + +
+ +
+ + + `) +}) +``` + +Novamente, use um formulário enviado automaticamente. Esta é a etapa 6 do diagrama de sequência acima. + +```typescript + +// Ponto de extremidade do IdP para solicitações de login +idpRouter.post(`/login`, +``` + +Este é o ponto de extremidade que recebe uma solicitação de login do provedor de serviços. Este é o manipulador da etapa 3 do diagrama de sequência acima. + +```typescript + async (req, res) => { + try { + // Workaround because I couldn't get parseLoginRequest to work. + // const loginRequest = await idp.parseLoginRequest(sp, 'post', req) + const samlRequest = xmlParser.parse(Buffer.from(req.body.SAMLRequest, 'base64').toString('utf-8')) + res.send(getLoginPage(samlRequest["samlp:AuthnRequest"]["@_ID"])) +``` + +Deveríamos ser capazes de usar [`idp.parseLoginRequest`](https://github.com/tngan/samlify/blob/master/src/entity-idp.ts#L127-L144) para ler o ID da solicitação de autenticação. No entanto, não consegui fazê-lo funcionar e não valia a pena gastar muito tempo nisso, então eu apenas uso um [analisador de XML de propósito geral](https://www.npmjs.com/package/fast-xml-parser). A informação que precisamos é o atributo `ID` dentro da tag ``, que está no nível superior do XML. + +## Usando assinaturas do Ethereum + +Agora que podemos enviar uma identidade de usuário para o provedor de serviços, o próximo passo é obter a identidade do usuário de uma maneira confiável. O Viem nos permite apenas solicitar à carteira o endereço do usuário, mas isso significa solicitar a informação ao navegador. Nós não controlamos o navegador, então não podemos confiar automaticamente na resposta que recebemos dele. + +Em vez disso, o IdP enviará ao navegador uma string para assinar. Se a carteira no navegador assinar esta string, significa que é realmente aquele endereço (ou seja, ele conhece a chave privada que corresponde ao endereço). + +Para ver isso em ação, pare o IdP e o SP existentes e execute estes comandos: + +```sh +git checkout eth-signatures +pnpm install +pnpm start +``` + +Em seguida, acesse [o SP](http://localhost:3000) e siga as instruções. + +Note que, neste momento, não sabemos como obter o endereço de e-mail a partir do endereço do Ethereum, então, em vez disso, relatamos `@bad.email.address` para o SP. + +### Explicação detalhada + +As alterações estão nas etapas 4-5 no diagrama anterior. + +![SAML com uma assinatura do Ethereum](./fig-05-saml-w-signature.png) + +O único arquivo que alteramos foi `idp.mts`. Aqui estão as partes alteradas. + +```typescript +import { v4 as uuidv4 } from 'uuid' +import { verifyMessage } from 'viem' +``` + +Precisamos dessas duas bibliotecas adicionais. Usamos [`uuid`](https://www.npmjs.com/package/uuid) para criar o valor [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce). O valor em si não importa, apenas o fato de ser usado uma única vez. + +A biblioteca [`viem`](https://viem.sh/) nos permite usar definições do Ethereum. Aqui precisamos dela para verificar se a assinatura é realmente válida. + +```typescript +const loginPrompt = "Para acessar o provedor de serviços, assine este nonce: " +``` + +A carteira pede permissão ao usuário para assinar a mensagem. Uma mensagem que é apenas um nonce pode confundir os usuários, por isso incluímos esta solicitação. + +```typescript +// Manter requestIDs aqui +let nonces = {} +``` + +Precisamos das informações da solicitação para poder respondê-la. Poderíamos enviá-lo com a solicitação (etapa 4) e recebê-lo de volta (etapa 5). No entanto, não podemos confiar nas informações que obtemos do navegador, que está sob o controle de um usuário potencialmente hostil. Portanto, é melhor armazená-lo aqui, com o nonce como chave. + +Observe que estamos fazendo isso aqui como uma variável para simplificar. No entanto, isso tem várias desvantagens: + +- Estamos vulneráveis a um ataque de negação de serviço. Um usuário mal-intencionado pode tentar fazer login várias vezes, enchendo nossa memória. +- Se o processo do IdP precisar ser reiniciado, perdemos os valores existentes. +- Não podemos balancear a carga entre vários processos, porque cada um teria sua própria variável. + +Em um sistema de produção, usaríamos um banco de dados e implementaríamos algum tipo de mecanismo de expiração. + +```typescript +const getSignaturePage = requestId => { + const nonce = uuidv4() + nonces[nonce] = requestId +``` + +Crie um nonce e armazene o `requestId` para uso futuro. + +```typescript + return ` + + + + + +

Por favor, assine

+ +
+ + + +` +} +``` + +O resto é apenas HTML padrão. + +```typescript +idpRouter.get("/signature/:nonce/:account/:signature", async (req, res) => { +``` + +Este é o manipulador para a etapa 5 no diagrama de sequência. + +```typescript + const requestId = nonces[req.params.nonce] + if (requestId === undefined) { + res.send("Bad nonce") + return ; + } + + nonces[req.params.nonce] = undefined +``` + +Obtenha o ID da solicitação e exclua o nonce de `nonces` para garantir que ele não possa ser reutilizado. + +```typescript + try { +``` + +Como há muitas maneiras pelas quais a assinatura pode ser inválida, envolvemos isso em um bloco `try ... catch` para capturar quaisquer erros lançados. + +```typescript + const validSignature = await verifyMessage({ + address: req.params.account, + message: `${loginPrompt}${req.params.nonce}`, + signature: req.params.signature + }) +``` + +Use [`verifyMessage`](https://viem.sh/docs/actions/public/verifyMessage#verifymessage) para implementar a etapa 5.5 no diagrama de sequência. + +```typescript + if (!validSignature) + throw("Bad signature") + } catch (err) { + res.send("Error:" + err) + return ; + } +``` + +O restante do manipulador é equivalente ao que fizemos no manipulador `/loginSubmitted` anteriormente, exceto por uma pequena alteração. + +```typescript + const loginResponse = await idp.createLoginResponse( + . + . + . + { + email: req.params.account + "@bad.email.address" + } + ); +``` + +Não temos o endereço de e-mail real (o obteremos na próxima seção), então, por enquanto, retornamos o endereço do Ethereum e o marcamos claramente como não sendo um endereço de e-mail. + +```typescript +// Ponto de extremidade do IdP para solicitações de login +idpRouter.post(`/login`, + async (req, res) => { + try { + // Solução alternativa porque não consegui fazer o parseLoginRequest funcionar. + // const loginRequest = await idp.parseLoginRequest(sp, 'post', req) + const samlRequest = xmlParser.parse(Buffer.from(req.body.SAMLRequest, 'base64').toString('utf-8')) + res.send(getSignaturePage(samlRequest["samlp:AuthnRequest"]["@_ID"])) +``` + +Em vez de `getLoginPage`, agora use `getSignaturePage` no manipulador da etapa 3. + +## Obtendo o endereço de e-mail + +O próximo passo é obter o endereço de e-mail, o identificador solicitado pelo provedor de serviços. Para fazer isso, usamos o [Ethereum Attestation Service (EAS)](https://attest.org/). + +A maneira mais fácil de obter atestados é usar a [API GraphQL](https://docs.attest.org/docs/developer-tools/api). Usamos esta consulta: + +``` +query GetAttestationsByRecipient { + attestations( + where: { + recipient: { equals: "${getAddress(ethAddr)}" } + schemaId: { equals: "0xfa2eff59a916e3cc3246f9aec5e0ca00874ae9d09e4678e5016006f07622f977" } + } + take: 1 + ) { + data + id + attester + } +} +``` + +Este [`schemaId`](https://optimism.easscan.org/schema/view/0xfa2eff59a916e3cc3246f9aec5e0ca00874ae9d09e4678e5016006f07622f977) inclui apenas um endereço de e-mail. Esta consulta solicita atestados deste esquema. O sujeito do atestado é chamado de `destinatário`. É sempre um endereço do Ethereum. + +Aviso: a maneira como estamos obtendo os atestados aqui tem dois problemas de segurança. + +- Estamos indo para o ponto de extremidade da API, `https://optimism.easscan.org/graphql`, que é um componente centralizado. Podemos obter o atributo `id` e, em seguida, fazer uma pesquisa na cadeia para verificar se um atestado é real, mas o ponto de extremidade da API ainda pode censurar atestados ao não nos informar sobre eles. + + Este problema não é impossível de resolver, poderíamos executar nosso próprio ponto de extremidade GraphQL e obter os atestados dos registros da cadeia, mas isso é excessivo para nossos propósitos. + +- Nós não olhamos para a identidade do atestador. Qualquer um pode nos fornecer informações falsas. Em uma implementação do mundo real, teríamos um conjunto de atestadores confiáveis e olharíamos apenas para seus atestados. + +Para ver isso em ação, pare o IdP e o SP existentes e execute estes comandos: + +```sh +git checkout email-address +pnpm install +pnpm start +``` + +Em seguida, forneça seu endereço de e-mail. Você tem duas maneiras de fazer isso: + +- Importe uma carteira usando uma chave privada e use a chave privada de teste `0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80`. + +- Adicione um atestado para seu próprio endereço de e-mail: + + 1. Navegue até [o esquema no explorador de atestados](https://optimism.easscan.org/schema/view/0xfa2eff59a916e3cc3246f9aec5e0ca00874ae9d09e4678e5016006f07622f977). + + 2. Clique em **Atestar com Esquema**. + + 3. Insira seu endereço Ethereum como destinatário, seu endereço de e-mail como endereço de e-mail e selecione **Onchain**. Em seguida, clique em **Fazer Atestado**. + + 4. Aprove a transação na sua carteira. Você precisará de um pouco de ETH na [Blockchain da Optimism](https://app.optimism.io/bridge/deposit) para pagar pelo gás. + +De qualquer forma, depois de fazer isso, navegue até [http://localhost:3000](http://localhost:3000) e siga as instruções. Se você importou a chave privada de teste, o e-mail que você recebe é `test_addr_0@example.com`. Se você usou seu próprio endereço, deve ser o que você atestou. + +### Explicação detalhada + +![Obtendo do endereço Ethereum para o e-mail](./fig-06-saml-sig-n-email.png) + +Os novos passos são a comunicação GraphQL, passos 5.6 e 5.7. + +Novamente, aqui estão as partes alteradas de `idp.mts`. + +```typescript +import { GraphQLClient } from 'graphql-request' +import { SchemaEncoder } from '@ethereum-attestation-service/eas-sdk' +``` + +Importe as bibliotecas que precisamos. + +```typescript +const graphqlEndpointUrl = "https://optimism.easscan.org/graphql" +``` + +Existe [um endpoint separado para cada cadeia de blocos](https://docs.attest.org/docs/developer-tools/api). + +```typescript +Crie um novo cliente `GraphQLClient` que podemos usar para consultar o ponto de extremidade. +``` + +Para entendê-lo, precisamos do esquema. + +```typescript +Uma função para ir de um endereço Ethereum para um endereço de e-mail. +``` + +Esta é uma consulta GraphQL. attestations( + +```typescript +Estamos procurando por atestados. +``` + +``` + where: { + recipient: { equals: "${getAddress(ethAddr)}" } + schemaId: { equals: "0xfa2eff59a916e3cc3246f9aec5e0ca00874ae9d09e4678e5016006f07622f977" } + } +``` + +```typescript +Os atestados que queremos são aqueles em nosso esquema, onde o destinatário é `getAddress(ethAddr)`. +``` + +A função [`getAddress`](https://viem.sh/docs/utilities/getAddress#getaddress) garante que nosso endereço tenha o [checksum](https://github.com/ethereum/ercs/blob/master/ERCS/erc-55.md) correto. + +```typescript + atestações( +``` + +Isto é necessário porque GraphQL diferencia maiúsculas e minúsculas. + +```typescript +"0xBAD060A7", "0xBad060A7", and "0xbad060a7" são valores diferentes. +``` + +```typescript + take: 1 +``` + +Independentemente de quantos atestados encontrarmos, queremos apenas o primeiro. + +```typescript + ) { + data + id + attester + } + }` +``` + +Os campos que queremos receber. + +- `attester`: O endereço que enviou o atestado. Normalmente, isso é usado para decidir se confia no atestado ou não. +- `id`: O ID do atestado. Você pode usar este valor para [ler o atestado on-chain](https://optimism.blockscout.com/address/0x4200000000000000000000000000000000000021?tab=read_proxy&source_address=0x4E0275Ea5a89e7a3c1B58411379D1a0eDdc5b088#0xa3112a64) para verificar se a informação da consulta GraphQL está correta. +- `data`: Os dados do esquema (neste caso, o endereço de e-mail). + +```typescript + const queryResult = await graphqlClient.request(query) + + if (queryResult.attestations.length == 0) + return "no_address@available.is" +``` + +Se não houver atestado, retorne um valor que seja obviamente incorreto, mas que pareça válido para o provedor de serviços. + +```typescript + const attestationDataFields = graphqlEncoder.decodeData(queryResult.attestations[0].data) + return attestationDataFields[0].value.value +} +``` + +Se houver um valor, use `decodeData` para decodificar os dados. Não precisamos dos metadados que ele fornece, apenas do valor em si. + +```typescript +const loginResponse = await idp.createLoginResponse( +sp, +{ +. +. +. +}, +"post", +{ +email: await ethereumAddressToEmail(req.params.account) +} +); +``` + +```typescript +Use a nova função para obter o endereço de e-mail. +``` + +E a descentralização? Nesta configuração, os usuários não podem fingir ser alguém que não são, desde que confiemos em atestadores confiáveis para o mapeamento do endereço Ethereum para o endereço de e-mail. + +```typescript +No entanto, nosso provedor de identidade ainda é um componente centralizado. +``` + +Quem tiver a chave privada do provedor de identidade pode enviar informações falsas para o provedor de serviços. + +## Pode haver uma solução usando [computação multipartidária (MPC)](https://en.wikipedia.org/wiki/Secure_multi-party_computation). + +Espero escrever sobre isso em um futuro tutorial. Adoção de um padrão de logon, como assinaturas Ethereum, enfrenta um problema de ovo e galinha. Os provedores de serviços querem atrair o mercado mais amplo possível. + +Os usuários querem poder acessar serviços sem ter que se preocupar em suportar seu padrão de logon. A criação de adaptadores, como um IdP do Ethereum, pode nos ajudar a superar esse obstáculo. + +## Conclusão + +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). [Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). Os usuários têm uma chave privada (normalmente mantida em uma extensão de navegador). +Criar adaptadores, como um IdP da Ethereum, pode nos ajudar a superar este obstáculo. + +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). diff --git a/public/content/translations/pt-br/developers/tutorials/getting-started-with-ethereum-development-using-alchemy/index.md b/public/content/translations/pt-br/developers/tutorials/getting-started-with-ethereum-development-using-alchemy/index.md index 922ce204baa..cecb8e8e32f 100644 --- a/public/content/translations/pt-br/developers/tutorials/getting-started-with-ethereum-development-using-alchemy/index.md +++ b/public/content/translations/pt-br/developers/tutorials/getting-started-with-ethereum-development-using-alchemy/index.md @@ -1,60 +1,62 @@ --- -title: Introdução ao Desenvolvimento Ethereum -description: "Este é um guia para iniciantes no desenvolvimento do Ethereum. Iremos levá-lo desde a criação de um endpoint de API, para fazer uma solicitação de linha de comando, para escrever seu primeiro script web3! Não é necessário ter experiência em desenvolvimento de blockchain!" +title: "Introdução ao Desenvolvimento na Ethereum" +description: "Este é um guia para iniciantes no desenvolvimento na Ethereum. Vamos guiar você desde a criação de um ponto de extremidade de API, passando pela criação de uma solicitação de linha de comando, até a escrita de seu primeiro script web3! Não é necessária experiência em desenvolvimento de cadeia de blocos!" author: "Elan Halpern" tags: - - "javascript" - - "ethers.js" - - "nódulos" - - "consultando" - - "alchemy" + [ + "JavaScript", + "ethers.js", + "nós", + "consultando", + "Alchemy" + ] skill: beginner lang: pt-br published: 2020-10-30 -source: Médio +source: Medium sourceUrl: https://medium.com/alchemy-api/getting-started-with-ethereum-development-using-alchemy-c3d6a45c567f --- -![Logos do Ethereum e Alchemy](./ethereum-alchemy.png) +![Logos do Ethereum e da Alchemy](./ethereum-alchemy.png) -Este é um guia de iniciantes para começar com o desenvolvimento na Ethereum. Neste tutorial, usaremos a [Alchemy](https://alchemyapi.io/), a plataforma líder de desenvolvedores de blockchain, capacitando milhões de usuários em 70% dos principais aplicativos de blockchain, incluindo Maker, 0x, MyEtherWallet, Dharma e Kyber. A Alchemy nos dará acesso a um ponto de extremidade de API na cadeia do Ethereum para que possamos ler e escrever transações. +Este é um guia para iniciantes para começar o desenvolvimento na Ethereum. Para este tutorial, usaremos a [Alchemy](https://alchemyapi.io/), a plataforma líder para desenvolvedores de cadeia de blocos que atende a milhões de usuários de 70% dos principais aplicativos de cadeia de blocos, incluindo Maker, 0x, MyEtherWallet, Dharma e Kyber. A Alchemy nos dará acesso a um ponto de extremidade de API na cadeia Ethereum para que possamos ler e escrever transações. -Ajudaremos você a se inscrever na Alchemy para escrever o seu primeiro script web3! Não é necessário ter experiência em desenvolvimento de blockchain! +Vamos guiar você desde a inscrição na Alchemy até a escrita do seu primeiro script web3! Não é necessária experiência em desenvolvimento de cadeia de blocos! ## 1. Inscreva-se para obter uma conta gratuita da Alchemy {#sign-up-for-a-free-alchemy-account} -Criar uma conta em Alchemy é fácil, [inscreva-se gratuitamente aqui](https://auth.alchemyapi.io/signup). +Criar uma conta na Alchemy é fácil, [inscreva-se gratuitamente aqui](https://auth.alchemy.com/). -## 2. Criar um app Alchemy {#create-an-alchemy-app} +## 2. Crie um aplicativo da Alchemy {#create-an-alchemy-app} -Para se comunicar com a chain da Ethereum e usar os produtos da Alchemy, você precisa de uma chave de API para autenticar as suas solicitações. +Para se comunicar com a cadeia Ethereum e usar os produtos da Alchemy, você precisa de uma chave de API para autenticar suas solicitações. -Você pode [criar chaves de API a partir do painel de controle](http://dashboard.alchemyapi.io/). Para fazer uma nova chave, navegue até "Create app" como mostrado abaixo: +Você pode [criar chaves de API a partir do painel](https://dashboard.alchemy.com/). Para criar uma nova chave, navegue até "Create App", como mostrado abaixo: -Um agradecimento especial ao [_ShapeShift_](https://shapeshift.com/) _por nos permitir mostrar seu painel!_ +Agradecimentos especiais à [_ShapeShift_](https://shapeshift.com/) _por nos permitir mostrar o painel deles!_ -![Painel de controle Alchemy](./alchemy-dashboard.png) +![Painel da Alchemy](./alchemy-dashboard.png) -Preencha os detalhes em "Create app" para obter sua nova chave. Aqui você também pode ver os apps criados anteriormente, bem como os criados pela sua equipe. Pegue chaves existentes clicando em "View Key" para qualquer app. +Preencha os detalhes em "Create App" para obter sua nova chave. Você também pode ver aqui os aplicativos que criou anteriormente e os que foram feitos pela sua equipe. Obtenha chaves existentes clicando em "View Key" para qualquer aplicativo. -![Criar app com um Alchemy screenshot](./create-app.png) +![Captura de tela da criação de um aplicativo com a Alchemy](./create-app.png) -Você também pode extrair chaves de API existentes, passando o mouse sobre “Aplicativos” e selecionando uma. Você pode “Visualizar chave” aqui, bem como “Editar aplicativo” na lista de permissões de domínios específicos, ver várias ferramentas de desenvolvedor e visualizar análises. +Você também pode obter chaves de API existentes passando o mouse sobre "Apps" e selecionando uma. Você pode usar o "View Key" aqui, bem como o "Edit App" para adicionar domínios específicos à lista de permissões, ver várias ferramentas de desenvolvedor e visualizar as análises. -![Gif mostrando a um usuário como requisitar chaves API](./pull-api-keys.gif) +![Gif mostrando um usuário obtendo chaves de API](./pull-api-keys.gif) -## 3. Fazer uma requisição via Command line {#make-a-request-from-the-command-line} +## 3. Faça uma solicitação a partir da linha de comando {#make-a-request-from-the-command-line} -Interagir com a blockchain Ethereum através de Alchemy, usando JSON-RPC e curl. +Interaja com a cadeia de blocos Ethereum através da Alchemy usando JSON-RPC e curl. -Para solicitações manuais, recomendamos interagir com `JSON-RPC` via solicitações de `POST`. Simplesmente passe no header `Content-Type: application/json` e sua query como corpo do `POST` com os seguintes campos: +Para solicitações manuais, recomendamos interagir com o `JSON-RPC` por meio de solicitações `POST`. Basta passar o cabeçalho `Content-Type: application/json` e sua consulta como o corpo do `POST` com os seguintes campos: -- `jsonrpc`: Atualmente, somente a versão `2.0` do JSON-RPC é suportada. -- `method`: O método ETH API. [Veja a referência da API.](https://docs.alchemyapi.io/documentation/alchemy-api-reference/json-rpc) -- `params`: Uma lista de parâmetros para passar ao método. -- `id`: A ID da sua solicitação. Será retornado pela resposta para que você possa manter o controle sobre qual solicitação uma resposta pertence. +- `jsonrpc`: a versão do JSON-RPC — atualmente, apenas a `2.0` é suportada. +- `method`: o método da API ETH. [Consulte a referência da API.](https://docs.alchemyapi.io/documentation/alchemy-api-reference/json-rpc) +- `params`: uma lista de parâmetros a serem passados para o método. +- `id`: o ID da sua solicitação. Ele será retornado pela resposta para que você possa rastrear a qual solicitação uma resposta pertence. -Aqui está um exemplo que você pode executar a partir da linha de comando, para recuperar o preço atual do gás: +Aqui está um exemplo que você pode executar na linha de comando para obter o preço atual do gás: ```bash curl https://eth-mainnet.alchemyapi.io/v2/demo \ @@ -63,7 +65,7 @@ curl https://eth-mainnet.alchemyapi.io/v2/demo \ -d '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":73}' ``` -_**NOTA:** Substitua [https://eth-mainnet.alchemyapi.io/v2/demo](https://eth-mainnet.alchemyapi.io/jsonrpc/demo) por sua própria chave de API `https://eth-mainnet.alchemyapi.io/v2/**sua-chave-api`._ +_**OBSERVAÇÃO:** substitua [https://eth-mainnet.alchemyapi.io/v2/demo](https://eth-mainnet.alchemyapi.io/jsonrpc/demo) pela sua própria chave de API `https://eth-mainnet.alchemyapi.io/v2/**your-api-key`._ **Resultados:** @@ -71,17 +73,17 @@ _**NOTA:** Substitua [https://eth-mainnet.alchemyapi.io/v2/demo](https://eth-mai { "id": 73,"jsonrpc": "2.0","result": "0x09184e72a000" // 10000000000000 } ``` -## 4. Configure seu Cliente Web3 {#set-up-your-web3-client} +## 4. Configure seu cliente Web3 {#set-up-your-web3-client} -**Se você tem um cliente existente,** mude o URL do seu provedor de nó atual para uma URL de Alchemy com a sua chave API: `“https://eth-mainnet.alchemyapi.io/v2/your-api-key"` +**Se você já tiver um cliente,** altere o URL do provedor do nó atual para um URL da Alchemy com sua chave de API: `"https://eth-mainnet.alchemyapi.io/v2/your-api-key"` -**_NOTA:_** Os scripts abaixo precisam ser executados em um **contexto de nó** ou **salvo em um arquivo**. Não é executado na linha de comando. Se você ainda não instalou o Node ou o NPM, confira este rápido [guia de configuração para macs](https://app.gitbook.com/@alchemyapi/s/alchemy/guides/alchemy-for-macs). +**_OBSERVAÇÃO:_** os scripts abaixo precisam ser executados em um **contexto de nó** ou **salvos em um arquivo**, e não executados a partir da linha de comando. Se você ainda não tiver o Node ou o npm instalado, confira este [guia de configuração rápida para Macs](https://app.gitbook.com/@alchemyapi/s/alchemy/guides/alchemy-for-macs). -Há inúmeras [bibliotecas Web3](https://docs.alchemyapi.io/guides/getting-started#other-web3-libraries) que você pode integrar com Alchemy. No entanto, nós recomendamos usar [Alchemy Web3](https://docs.alchemy.com/reference/api-overview), um drop-in substituto para web3.js, construída e configurada para trabalhar sem interrupções com Alchemy. Isto fornece múltiplas vantagens, tais como novas tentativas automáticas e um suporte robusto a WebSocket. +Existem inúmeras [bibliotecas Web3](https://docs.alchemyapi.io/guides/getting-started#other-web3-libraries) que você pode integrar com a Alchemy. No entanto, recomendamos o uso da [Alchemy Web3](https://docs.alchemy.com/reference/api-overview), um substituto direto para web3.js, criado e configurado para funcionar perfeitamente com a Alchemy. Isso oferece várias vantagens, como novas tentativas automáticas e suporte robusto a WebSocket. -Para instalar AlchemyWeb3.js, **navegue até o diretório do seu projeto** e execute: +Para instalar o AlchemyWeb3.js, **navegue até o diretório do seu projeto** e execute: -**Com o Yarn:** +**Com Yarn:** ``` yarn add @alch/alchemy-web3 @@ -90,10 +92,10 @@ yarn add @alch/alchemy-web3 **Com NPM:** ``` -yarn add @alch/alchemy-web3 +npm install @alch/alchemy-web3 ``` -Para interagir com a infraestrutura dos nós de Alchemy, execute em NodeJS ou adicione isso a um arquivo JavaScript: +Para interagir com a infraestrutura de nós da Alchemy, execute no NodeJS ou adicione isto a um arquivo JavaScript: ```js const { createAlchemyWeb3 } = require("@alch/alchemy-web3") @@ -102,18 +104,18 @@ const web3 = createAlchemyWeb3( ) ``` -## 5. Escreva seu primeiro script Web3! {#write-your-first-web3-script} +## 5. Escreva seu primeiro Script Web3! {#write-your-first-web3-script} -Agora vamos colocar a mão na massa com um pouco de programação na Web3. Vamos escrever um script simples que exibe o número de bloco mais recente da Rede principal do Ethereum. +Agora, para pôr a mão na massa com um pouco de programação web3, escreveremos um script simples que imprime o número do bloco mais recente da Mainnet do Ethereum. -**1. Se você ainda não fez, no seu terminal, crie um novo diretório e cd do projeto dentro dele:** +**1. Se ainda não o fez, crie um novo diretório de projeto em seu terminal e acesse-o com o comando cd:** ``` mkdir web3-example cd web3-example ``` -**2. Instale a dependência do Alchemy web3 (ou qualquer web3) em seu projeto, se você ainda não tiver:** +**2. Instale a dependência do Alchemy web3 (ou qualquer web3) em seu projeto, caso ainda não o tenha feito:** ``` npm install @alch/alchemy-web3 @@ -121,34 +123,34 @@ npm install @alch/alchemy-web3 **3. Crie um arquivo chamado `index.js` e adicione o seguinte conteúdo:** -> Por fim, você deve substituir `demo` pela sua chave de API HTTP do Alchemy. +> Você deve, por fim, substituir `demo` por sua chave de API HTTP da Alchemy. ```js async function main() { const { createAlchemyWeb3 } = require("@alch/alchemy-web3") - const web3 = createAlchemyWeb3("https://eth- mainnet.alchemyapi.io/v2/demo") + const web3 = createAlchemyWeb3("https://eth-mainnet.alchemyapi.io/v2/demo") const blockNumber = await web3.eth.getBlockNumber() - console.log("The latest block number is " + blockNumber) + console.log("O número do bloco mais recente é " + blockNumber) } main() ``` -Não está familiarizado com programação assíncrona? Confira este [post no Medium](https://medium.com/better-programming/understanding-async-await-in-javascript-1d81bb079b2c). +Não está familiarizado com programação assíncrona? Confira esta [publicação no Medium](https://medium.com/better-programming/understanding-async-await-in-javascript-1d81bb079b2c). -**4. Executá-lo em seu terminal usando o nó** +\*\*4. Execute-o no seu terminal usando **node** ``` node index.js ``` -**5. Agora você deve ver a saída do último número de bloco no seu console!** +**5. Agora você deve ver o número do bloco mais recente exibido em seu console!** ``` -O último número de bloco é 11043912 +O número do bloco mais recente é 11043912 ``` -**Eba! Parabéns! Você acabou de escrever o seu primeiro script web3 usando Alchemy 🎉** +**Eba!** Parabéns! Você acabou de escrever seu primeiro script web3 usando a Alchemy 🎉\*\* -Não tem certeza do que fazer a seguir? Experimente implementar seu primeiro contrato inteligente e colocar a mão na massa com um pouco de programação Solidity em nosso [Guia de contratos inteligentes “Olá, mundo”](https://docs.alchemyapi.io/tutorials/hello-world-smart-contract), ou teste seus conhecimentos sobre painel de controle com o [Aplicativo de demonstração do painel](https://docs.alchemyapi.io/tutorials/demo-app)! +Não sabe o que fazer a seguir? Tente implantar seu primeiro contrato inteligente e se aventurar um pouco na programação em Solidity com nosso [Guia de Contrato Inteligente Hello World](https://www.alchemy.com/docs/hello-world-smart-contract), ou teste seus conhecimentos sobre o painel com o [Aplicativo de Demonstração do Painel](https://docs.alchemyapi.io/tutorials/demo-app)! -_[Cadastre-se com o Alchemy](https://auth.alchemyapi.io/signup) gratuitamente, confira [a nossa documentação](https://docs.alchemyapi.io/), e para receber as últimas notícias, siga-nos no [Twitter](https://twitter.com/AlchemyPlatform)_. +_[Inscreva-se na Alchemy gratuitamente](https://auth.alchemy.com/), confira nossa [documentação](https://www.alchemy.com/docs/) e, para receber as notícias mais recentes, siga-nos no [Twitter](https://twitter.com/AlchemyPlatform)_. diff --git a/public/content/translations/pt-br/developers/tutorials/guide-to-smart-contract-security-tools/index.md b/public/content/translations/pt-br/developers/tutorials/guide-to-smart-contract-security-tools/index.md index 5d23724b65e..7701dac09bc 100644 --- a/public/content/translations/pt-br/developers/tutorials/guide-to-smart-contract-security-tools/index.md +++ b/public/content/translations/pt-br/developers/tutorials/guide-to-smart-contract-security-tools/index.md @@ -1,105 +1,102 @@ --- -title: Um guia para ferramentas de segurança de contratos inteligentes -description: Uma visão geral de três diferentes técnicas de análise de testes e programas +title: "Um guia para ferramentas de segurança de contratos inteligentes" +description: "Uma visão geral de três técnicas diferentes de teste e análise de programas" author: "Trailofbits" lang: pt-br -tags: - - "solidez" - - "smart contracts" - - "segurança" +tags: [ "Solidity", "smart contracts", "segurança" ] skill: intermediate published: 2020-09-07 -source: Construindo contratos seguros +source: Building secure contracts sourceUrl: https://github.com/crytic/building-secure-contracts/tree/master/program-analysis --- -We are going to use three distinctive testing and program analysis techniques: +Usaremos três técnicas distintas de teste e análise de programas: -- **Análise estática com [Slither](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/).** Todos os caminhos do programa são aproximados e analisados ao mesmo tempo, por meio de diferentes apresentações de programa (por exemplo, um control-flow-graph) -- **Fuzzing com [Echidna](/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/).** O código é executado com uma geração pseudo-aleatória de transações. O fuzzer tentará encontrar uma sequência de transações para violar uma determinada propriedade. -- **A execução simbólica com a [Manticore](/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/).** Uma técnica de verificação formal, que traduz cada caminho de execução para uma fórmula matemática, na qual as restrições de cima podem ser verificadas. +- **Análise estática com [Slither](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/).** Todos os caminhos do programa são aproximados e analisados ao mesmo tempo, através de diferentes apresentações do programa (p. ex., gráfico de fluxo de controle) +- **Fuzzing com [Echidna](/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/).** O código é executado com uma geração pseudorrandômica de transações. O fuzzer tentará encontrar uma sequência de transações para violar uma determinada propriedade. +- **Execução simbólica com [Manticore](/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/).** Uma técnica de verificação formal, que traduz cada caminho de execução para uma fórmula matemática, sobre a qual as restrições podem ser verificadas. -Cada técnica tem vantagens e armadilhas, e será útil em [casos específicos](#determining-security-properties): +Cada técnica tem vantagens e desvantagens e será útil em [casos específicos](#determining-security-properties): -| Técnica | Ferramenta | Uso | Velocidade | Erros perdidos | Alarmes falso | -| ------------------ | ---------- | ------------------------------------ | ---------- | -------------- | ------------- | -| Análise estática | Slither | CLI & scripts | segundos | moderado | baixo | -| Fuzzing | Echidna | Propriedades da Solidity | minutos | baixo | nenhum | -| Execução simbólica | Manticore | Propriedades & scripts & da Solidity | horas | nenhum\* | nenhum | +| Técnica | Ferramenta | Uso | Velocidade | Bugs não detectados | Alarmes Falsos | +| ------------------ | ---------- | ---------------------------------- | ---------- | ------------------- | -------------- | +| Análise Estática | Slither | CLI e scripts | segundos | moderado | baixo | +| Fuzzing | Echidna | Propriedades do Solidity | minutos | baixo | nenhum | +| Execução Simbólica | Manticore | Propriedades do Solidity e scripts | horas | nenhum\* | nenhum | \* se todos os caminhos forem explorados sem tempo limite -**Slither** analisa contratos em poucos segundos, no entanto análise estática pode levar a alarmes falsos e será menos adequada para verificações complexas (e.. verificações aritméticas). Execute o Slither por meio da API para acesso com botão de comando para detectores internos ou por meio da API para verificações definidas pelo usuário. +**O Slither** analisa contratos em segundos, no entanto, a análise estática pode levar a alarmes falsos e será menos adequada para verificações complexas (p. ex., verificações aritméticas). Execute o Slither pela API para ter acesso fácil aos detectores integrados ou pela API para verificações definidas pelo usuário. -O **Echidna** precisa ser executado por vários minutos e só produzirá verdadeiros positivos. O Echidna verifica as propriedades de segurança fornecidas pelo usuário escritas em Solidity. Ele pode perder erros, pois é baseado em exploração aleatória. +**O Echidna** precisa ser executado por vários minutos e só produzirá verdadeiros positivos. O Echidna verifica as propriedades de segurança fornecidas pelo usuário, escritas em Solidity. Ele pode não encontrar bugs, pois se baseia em exploração aleatória. -O **Manticore** executa a análise com maior peso. Como o Echidna, o Manticore verifica as propriedades fornecidas pelo usuário. Será necessário mais tempo de execução, mas isso poderá comprovar a validade de uma propriedade e não relatará alarmes falsos. +**O Manticore** realiza a análise "mais pesada". Assim como o Echidna, o Manticore verifica as propriedades fornecidas pelo usuário. Ele precisará de mais tempo para ser executado, mas pode provar a validade de uma propriedade e não relatará alarmes falsos. ## Fluxo de trabalho sugerido {#suggested-workflow} -Comece com os detectores internos do Slither para garantir que nenhum bug simples esteja presente agora ou seja introduzido mais tarde. Use o Slither para verificar propriedades relacionadas a herança, dependências de variáveis e questões estruturais. À medida que a base de código cresce, use o Echidna para testar propriedades mais complexas da máquina de estado. Revisite o Slither para desenvolver verificações personalizadas de proteções indisponíveis na Solidity, como proteger contra uma função que está sendo substituída. Finalmente, use o Manticore para realizar a verificação direcionada de propriedades de segurança críticas, por exemplo, operações aritméticas. +Comece com os detectores integrados do Slither para garantir que nenhum bug simples esteja presente ou seja introduzido mais tarde. Use o Slither para verificar propriedades relacionadas à herança, dependências de variáveis e problemas estruturais. À medida que a base de código cresce, use o Echidna para testar propriedades mais complexas da máquina de estado. Revisite o Slither para desenvolver verificações personalizadas para proteções indisponíveis no Solidity, como a proteção contra a sobrescrita de uma função. Finalmente, use o Manticore para realizar a verificação direcionada de propriedades de segurança críticas, p. ex., operações aritméticas. -- Use a CLI do Slither para capturar problemas comuns +- Use a CLI do Slither para detectar problemas comuns - Use o Echidna para testar as propriedades de segurança de alto nível do seu contrato - Use o Slither para escrever verificações estáticas personalizadas - Use o Manticore quando quiser uma garantia aprofundada de propriedades de segurança críticas -**Uma nota sobre testes de unidade**. Testes de unidade são necessários para construir softwares de alta qualidade. No entanto, estas técnicas não são as mais adequadas para encontrar falhas de segurança. Normalmente, eles são usados para testar comportamentos positivos de código (ou seja, o código funciona conforme o esperado no contexto normal), enquanto as falhas de segurança tendem a residir em casos de risco que os desenvolvedores não consideraram. No nosso estudo sobre dezenas de revisões inteligentes de segurança do contrato, a [cobertura do teste de unidade não teve efeito sobre o número ou gravidade das falhas de segurança](https://blog.trailofbits.com/2019/08/08/246-findings-from-our-smart-contract-audits-an-executive-summary/) que encontramos no código do nosso cliente. +**Uma nota sobre testes de unidade**. Testes de unidade são necessários para criar software de alta qualidade. No entanto, essas técnicas não são as mais adequadas para encontrar falhas de segurança. Eles são normalmente usados para testar comportamentos positivos do código (ou seja, o código funciona como esperado em um contexto normal), enquanto as falhas de segurança tendem a residir em casos extremos que os desenvolvedores não consideraram. Em nosso estudo de dezenas de revisões de segurança de contratos inteligentes, a [cobertura de testes de unidade não teve efeito sobre o número ou a gravidade das falhas de segurança](https://blog.trailofbits.com/2019/08/08/246-findings-from-our-smart-contract-audits-an-executive-summary/) que encontramos no código de nossos clientes. -## Determinando propriedades de segurança {#determining-security-properties} +## Determinação de propriedades de segurança {#determining-security-properties} -Para testar e verificar efetivamente seu código, você deve identificar as áreas que precisam de atenção. Como seus recursos gastos com a segurança são limitados, é importante otimizar seus esforços para determinar o escopo das partes fracas ou de grande valor da sua base de código. A modelagem de ameaças pode ajudar nisso. Considere revisar: +Para testar e verificar seu código de forma eficaz, você deve identificar as áreas que precisam de atenção. Como seus recursos gastos em segurança são limitados, definir o escopo das partes fracas ou de alto valor de sua base de código é importante para otimizar seu esforço. A modelagem de ameaças pode ajudar. Considere analisar: -- [Avaliação de risco rápida](https://infosec.mozilla.org/guidelines/risk/rapid_risk_assessment.html) (nossa abordagem preferida quando o tempo é curto) -- [Guia de modelagem de ameaças do sistema centralizado de dados](https://csrc.nist.gov/publications/detail/sp/800-154/draft) (também conhecido como NIST 800-154) -- [Modelagem de ameaças Shostack](https://www.amazon.com/Threat-Modeling-Designing-Adam-Shostack/dp/1118809998) -- [STRIDE](https://wikipedia.org/wiki/STRIDE_(security)) / [DREAD](https://wikipedia.org/wiki/DREAD_(risk_assessment_model)) +- [Rapid Risk Assessments](https://infosec.mozilla.org/guidelines/risk/rapid_risk_assessment.html) (nossa abordagem preferida quando o tempo é curto) +- [Guide to Data-Centric System Threat Modeling](https://csrc.nist.gov/pubs/sp/800/154/ipd) (também conhecido como NIST 800-154) +- [Shostack threat modeling](https://www.amazon.com/Threat-Modeling-Designing-Adam-Shostack/dp/1118809998) +- [STRIDE](https://wikipedia.org/wiki/STRIDE_\(security\)) / [DREAD](https://wikipedia.org/wiki/DREAD_\(risk_assessment_model\)) - [PASTA](https://wikipedia.org/wiki/Threat_model#P.A.S.T.A.) -- [Uso de asserções](https://blog.regehr.org/archives/1091) +- [Use of Assertions](https://blog.regehr.org/archives/1091) ### Componentes {#components} -Saber o que você deseja verificar também ajudará a escolher a ferramenta certa. +Saber o que você quer verificar também o ajudará a selecionar a ferramenta certa. -As vastas áreas que são frequentemente relevantes para os contratos inteligentes incluem: +As áreas gerais que são frequentemente relevantes para contratos inteligentes incluem: -- **Máquina de estado.** A maioria dos contratos pode ser representada como uma máquina de estado. Recomendamos verificar que: (1) nenhum estado inválido pode ser alcançado, (2) se um estado é válido, que ele seja alcançável e (3) nenhum estado bloqueia o contrato. +- **Máquina de estado.** A maioria dos contratos pode ser representada como uma máquina de estado. Considere verificar se (1) nenhum estado inválido pode ser alcançado, (2) se um estado é válido, ele pode ser alcançado e (3) nenhum estado prende o contrato. - - Echidna e Manticore são as ferramentas para testar as especificações da máquina. + - Echidna e Manticore são as ferramentas a serem favorecidas para testar especificações de máquinas de estado. -- **Controles de acesso.** Se o seu sistema tiver usuários privilegiados (por exemplo, um proprietário, controladores, …), você deve garantir que (1) cada usuário pode executar apenas as ações autorizadas e (2) nenhum usuário pode bloquear ações de um usuário com mais privilégios. +- **Controles de acesso.** Se seu sistema tiver usuários privilegiados (p. ex., um proprietário, controladores, ...) você deve garantir que (1) cada usuário só possa realizar as ações autorizadas e (2) nenhum usuário possa bloquear ações de um usuário mais privilegiado. - - Slither, Echidna e Manticore podem verificar se há controles de acesso corretos. Por exemplo, o Slither pode verificar que apenas as funções da lista de permissões não possuem o modificador onlyOwner. O Echidna e a Manticore são úteis para um controle de acesso mais complexo, como uma autorização dada apenas se o contrato atingir um determinado estado. + - Slither, Echidna e Manticore podem verificar os controles de acesso corretos. Por exemplo, o Slither pode verificar que apenas as funções da lista de permissões não possuem o modificador onlyOwner. Echidna e Manticore são úteis para um controle de acesso mais complexo, como uma permissão concedida apenas se o contrato atingir um determinado estado. -- **Operações aritméticas.** É essencial verificar a solidez das operações aritméticas. Usar o `SafeMath` em todo lugar é um bom passo para evitar overflow/underflow, no entanto, ainda é importante considerar outras falhas aritméticas, incluindo problemas de arredondamento e falhas que atrapalham o contrato. +- **Operações aritméticas.** Verificar a solidez das operações aritméticas é fundamental. Usar o `SafeMath` em todos os lugares é um bom passo para evitar overflow/underflow, no entanto, você ainda deve considerar outras falhas aritméticas, incluindo problemas de arredondamento e falhas que prendem o contrato. - - A Manticore é a melhor escolha aqui. O Echidna pode ser utilizado se a aritmética estiver fora do escopo da solução SMT. + - O Manticore é a melhor escolha aqui. O Echidna pode ser usado se a aritmética estiver fora do escopo do solucionador SMT. -- **Exatidão da herança.** Os contratos do Solidity dependem fortemente de várias heranças. Erros como uma função de sombreamento faltando uma chamada `super` e uma ordem de linearização c3 interpretada erradamente podem ser facilmente introduzidos. +- **Correção da herança.** Contratos em Solidity dependem muito de herança múltipla. Erros como uma função de sombreamento sem uma chamada `super` e uma ordem de linearização c3 mal interpretada podem ser facilmente introduzidos. - - O Slither é a ferramenta que garante a detecção desses problemas. + - O Slither é a ferramenta para garantir a detecção desses problemas. -- **Interações externas.** Os contratos interagem entre si, e não se deve confiar em alguns contratos externos. Por exemplo, se o seu contrato depende de oráculos externos, ele permanecerá seguro se metade dos oráculos disponíveis estiverem comprometidos? +- **Interações externas.** Os contratos interagem entre si, e alguns contratos externos não devem ser confiáveis. Por exemplo, se seu contrato depende de oráculos externos, ele permanecerá seguro se metade dos oráculos disponíveis for comprometida? - - A Manticore e o Echidna são a melhor escolha para testar as interações externas com seus contratos. A Manticore possui um mecanismo integrado para o stub de contratos externos. + - Manticore e Echidna são a melhor escolha para testar interações externas com seus contratos. O Manticore tem um mecanismo integrado para criar stubs de contratos externos. -- **Conformidade padrão.** As normas do Ethereum (por exemplo, ERC20) têm um histórico de falhas em seu design. Esteja ciente das limitações da norma no qual você está construindo. - - Slither, Echidna e Manticore vão ajudar você a detectar desvios de uma determinada norma. +- **Conformidade com padrões.** Os padrões da Ethereum (p. ex., ERC20) têm um histórico de falhas em seu design. Esteja ciente das limitações do padrão sobre o qual você está construindo. + - Slither, Echidna e Manticore ajudarão você a detectar desvios de um determinado padrão. -### Folha de dicas de ferramentas {#tool-selection-cheatsheet} +### Guia rápido de seleção de ferramentas {#tool-selection-cheatsheet} -| Componentes | Ferramentas | Exemplos | -| --------------------- | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Máquina de estado | Echidna, Manticore | | -| Controle de acesso | Slither, Echidna, Manticore | [Slither exercise 2](https://github.com/crytic/slither/blob/7f54c8b948c34fb35e1d61adaa1bd568ca733253/docs/src/tutorials/exercise2.md), [Echidna exercício 2](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/exercises/Exercise-2.md) | -| Operações aritméticas | Manticore, Echidna | [Echidna exercício 1](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/exercises/Exercise-1.md), [Manticore exercícios 1 a 3](https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/manticore/exercises) | -| Exatidão da herança | Slither | [Slither exercício 1](https://github.com/crytic/slither/blob/7f54c8b948c34fb35e1d61adaa1bd568ca733253/docs/src/tutorials/exercise1.md) | -| Interações externas | Manticore, Echidna | | -| Conformidade padrão | Slither, Echidna, Manticore | [`slither-erc`](https://github.com/crytic/slither/wiki/ERC-Conformance) | +| Componente | Ferramentas | Exemplos | +| ------------------------ | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Máquina de estado | Echidna, Manticore | | +| Controle de acesso | Slither, Echidna, Manticore | [Slither exercise 2](https://github.com/crytic/slither/blob/7f54c8b948c34fb35e1d61adaa1bd568ca733253/docs/src/tutorials/exercise2.md), [Echidna exercise 2](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/exercises/Exercise-2.md) | +| Operações aritméticas | Manticore, Echidna | [Echidna exercise 1](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/exercises/Exercise-1.md), [Manticore exercises 1 - 3](https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/manticore/exercises) | +| Correção da herança | Slither | [Slither exercise 1](https://github.com/crytic/slither/blob/7f54c8b948c34fb35e1d61adaa1bd568ca733253/docs/src/tutorials/exercise1.md) | +| Interações externas | Manticore, Echidna | | +| Conformidade com padrões | Slither, Echidna, Manticore | [`slither-erc`](https://github.com/crytic/slither/wiki/ERC-Conformance) | -Outras áreas terão de ser verificadas dependendo dos seus objetivos, mas essas áreas gerais são um bom começo para qualquer sistema de contrato inteligente. +Outras áreas precisarão ser verificadas dependendo de seus objetivos, mas essas áreas de foco gerais são um bom começo para qualquer sistema de contrato inteligente. -Nossas auditorias públicas contêm exemplos de propriedades verificadas ou testadas. Considere a leitura das seções `Teste Automatizado e Verificação` dos seguintes relatórios para revisar as propriedades de segurança em situações reais: +Nossas auditorias públicas contêm exemplos de propriedades verificadas ou testadas. Considere ler as seções de `Teste e Verificação Automatizados` dos relatórios a seguir para analisar as propriedades de segurança do mundo real: - [0x](https://github.com/trailofbits/publications/blob/master/reviews/0x-protocol.pdf) -- [Balanceador](https://github.com/trailofbits/publications/blob/master/reviews/BalancerCore.pdf) +- [Balancer](https://github.com/trailofbits/publications/blob/master/reviews/BalancerCore.pdf) diff --git a/public/content/translations/pt-br/developers/tutorials/hello-world-smart-contract-fullstack/index.md b/public/content/translations/pt-br/developers/tutorials/hello-world-smart-contract-fullstack/index.md index e200f993cab..e817b7591ca 100644 --- a/public/content/translations/pt-br/developers/tutorials/hello-world-smart-contract-fullstack/index.md +++ b/public/content/translations/pt-br/developers/tutorials/hello-world-smart-contract-fullstack/index.md @@ -1,107 +1,110 @@ --- title: Contrato inteligente "Hello World" para iniciantes - Fullstack -description: Tutorial introdutório sobre como escrever e implementar um contrato inteligente simples no Ethereum. +description: "Tutorial introdutório sobre como escrever e implantar um contrato inteligente simples no Ethereum." author: "nstrike2" tags: - - "solidity" - - "hardhat" - - "alchemy" - - "contratos inteligentes" - - "implementação" - - "blockexplorer" - - "front-end" - - "transações" + [ + "Solidity", + "Hardhat", + "Alchemy", + "smart contracts", + "implantação", + "explorador de blocos", + "front-end", + "transações" + ] skill: beginner lang: pt-br published: 2021-10-25 --- -Este guia é para você que é iniciante em desenvolvimento de blockchain e não sabe por onde começar ou como implantar e interagir com contratos inteligentes. Nós iremos passar por criação e implantação de um contrato inteligente simples na rede de teste Goerli, usando [MetaMask](https://metamask.io), [Solidity](https://docs.soliditylang.org/en/v0.8.0/), [Hardhat](https://hardhat.org), e [Alchemy](https://alchemyapi.io/eth). +Este guia é para você que é iniciante em desenvolvimento de blockchain e não sabe por onde começar ou como implantar e interagir com contratos inteligentes. Vamos percorrer a criação e implantação de um contrato inteligente simples na rede de teste Goerli usando [MetaMask](https://metamask.io), [Solidity](https://docs.soliditylang.org/en/v0.8.0/), [Hardhat](https://hardhat.org) e [Alchemy](https://alchemy.com/eth). -Você irá precisar de uma conta Alchemy para completar este tutorial. [Registre-se para uma conta grátis](https://www.alchemy.com/). +Você precisará de uma conta Alchemy para concluir este tutorial. [Cadastre-se para obter uma conta gratuita](https://www.alchemy.com/). -E claro, se você tiver alguma dúvida em qualquer momento, não hesite em entrar no [Discord da Alchemy](https://discord.gg/gWuC7zB)! +Se você tiver dúvidas a qualquer momento, sinta-se à vontade para entrar em contato no [Discord da Alchemy](https://discord.gg/gWuC7zB)! -## Parte 1 - Criando e Implantando seu Contrato Inteligente usando Hardhat {#part-1} +## Parte 1 - Criar e implantar seu contrato inteligente usando Hardhat {#part-1} -### Conectar-se à rede Ethereum {#connect-to-the-ethereum-network} +### Conectar à rede Ethereum {#connect-to-the-ethereum-network} -Existem muitas maneiras de fazer solicitações à cadeia de Ethereum. Para simplificar, usaremos uma conta gratuita na Alchemy, uma plataforma de desenvolvedores de blockchain e API que nos permite comunicar com a cadeia Ethereum sem termos que executar nosso próprio nó. A Alchemy também possui ferramentas de desenvolvedor para monitoração e análise. Neste tutorial, vamos aproveitá-las para entender o que está acontecendo nos bastidores da implantação do nosso contrato inteligente. +Existem muitas maneiras de fazer solicitações para a cadeia Ethereum. Para simplificar, usaremos uma conta gratuita na Alchemy, uma plataforma de desenvolvedores de blockchain e API que nos permite comunicar com a cadeia Ethereum sem termos que executar nosso próprio nó. A Alchemy também possui ferramentas de desenvolvedor para monitoração e análise. Neste tutorial, vamos aproveitá-las para entender o que está acontecendo nos bastidores da implantação do nosso contrato inteligente. -### Crie o seu app e sua chave API {#create-your-app-and-api-key} +### Crie seu aplicativo e sua chave de API {#create-your-app-and-api-key} -Assim que criar uma conta na Alchemy, você poderá gerar uma chave API criando um app. Isso nos permitirá fazer solicitações na rede de teste Goerli. Se você não estiver familiarizado com redes de teste, você pode [ler o guia da Alchemy para escolher uma rede](https://docs.alchemyapi.io/guides/choosing-a-network). +Assim que criar uma conta na Alchemy, você poderá gerar uma chave de API criando um aplicativo. Isso permitirá que você faça solicitações à rede de teste Goerli. Se você não está familiarizado com redes de teste, pode [ler o guia da Alchemy para escolher uma rede](https://www.alchemy.com/docs/choosing-a-web3-network). -No painel da Alchemy, encontre o item **Apps** no menu suspenso na barra de navegação e selecione **Criar aplicativo**. +No painel da Alchemy, encontre o menu suspenso **Apps** na barra de navegação e clique em **Criar App**. -![Criar um aplicativo Hello World](./hello-world-create-app.png) +![Hello world criar aplicativo](./hello-world-create-app.png) -Dê ao seu app o nome “_Olá, Mundo_” e escreva uma breve descrição. Selecione **Staging** como o seu ambiente, e **Goerli** como a sua rede. +Dê ao seu aplicativo o nome '_Hello World_' e escreva uma breve descrição. Selecione **Staging** como seu ambiente e **Goerli** como sua rede. -![criar uma visualização do app hello world](./create-app-view-hello-world.png) +![visualização de criação de aplicativo hello world](./create-app-view-hello-world.png) _Observação: certifique-se de selecionar **Goerli**, ou este tutorial não funcionará._ -Clique em **Criar app**. Seu app aparecerá na tabela abaixo. +Clique em **Create app**. Seu aplicativo aparecerá na tabela abaixo. -### Cria uma conta Ethereum {#create-an-ethereum-account} +### Crie uma conta Ethereum {#create-an-ethereum-account} -Você precisa de uma conta Ethereum para enviar e receber transações. Nós usaremos MetaMask, a carteira virtual no navegador que permite usuários gerenciarem o endereço da sua conta Ethereum. +Você precisa de uma conta Ethereum para enviar e receber transações. Usaremos o MetaMask, uma carteira virtual no navegador que permite aos usuários gerenciar o endereço de sua conta Ethereum. -Você pode baixar e criar uma conta MetaMask gratuitamente [neste link](https://metamask.io/download). Quando você estiver criando uma conta, ou se já tiver uma conta, certifique-se de mudar para a “Rede de teste Goerli”, no canto superior direito (para que não estejamos lidando com dinheiro real). +Você pode baixar e criar uma conta MetaMask gratuitamente [aqui](https://metamask.io/download). Quando você estiver criando uma conta, ou se já tiver uma, certifique-se de mudar para a “Rede de Teste Goerli” no canto superior direito (para não lidarmos com dinheiro real). -### Etapa 4: Adicionar ether de um faucet {#step-4-add-ether-from-a-faucet} +### Etapa 4: Adicione ether de um Faucet {#step-4-add-ether-from-a-faucet} -Para implantar nosso contrato inteligente na rede de teste, precisaremos de alguns ETHs falsos. Para conseguir ETH da rede Goerli, vá para o Goerli faucet e entre o endereço da sua conta Goerli. Note that Goerli faucets can be a bit unreliable recently - see the [test networks page](/developers/docs/networks/#goerli) for a list of options to try: +Para implantar nosso contrato inteligente na rede de teste, precisaremos de um pouco de ETH falso. Para obter ETH na rede Goerli, vá a um faucet da Goerli e insira o endereço de sua conta Goerli. Observe que as faucets da Goerli podem ser um pouco instáveis recentemente - consulte a [página de redes de teste](/developers/docs/networks/#goerli) para uma lista de opções para tentar: -_Nota: devido a tráfego de rede, isto pode demorar um pouco._ +_Observação: devido ao congestionamento da rede, isso pode demorar um pouco._ +`` -### Etapa 5: Verificar seu saldo {#step-5-check-your-balance} +### Passo 5: Verifique seu saldo {#step-5-check-your-balance} -Para garantir que o ETH está na sua carteira, vamos fazer uma chamada [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) usando a [ferramenta de composição da Alchemy](https://composer.alchemyapi.io/?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D). Ele mostrará a quantidade de ETH em nossa carteira. Para saber mais, confira o [Breve tutorial da Alchemy sobre como usar a ferramenta de composição](https://youtu.be/r6sjRxBZJuU). +Para verificar se o ETH está em sua carteira, vamos fazer uma solicitação [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) usando a [ferramenta de composição da Alchemy](https://composer.alchemyapi.io/?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D). Ele mostrará a quantidade de ETH em nossa carteira. Para saber mais, confira o [breve tutorial da Alchemy sobre como usar a ferramenta de composição](https://youtu.be/r6sjRxBZJuU). -Insira o endereço da sua conta MetaMask e clique em **Send Request**. Você verá a resposta que se parece com o pedação de código abaixo. +Insira o endereço da sua conta MetaMask e clique em **Send Request**. Você verá uma resposta que se parece com o trecho de código abaixo. ```json { "jsonrpc": "2.0", "id": 0, "result": "0x2B5E3AF16B1880000" } ``` -> _Nota: Este resultado é em wei, não ETH. Lembre-se de que "Wei" é a menor unidade de ether._ +> _Observação: Este resultado está em wei, não em ETH. Wei é usado como a menor denominação de ether._ Ufa! O nosso dinheiro falso está todo lá. -### Etapa 6: Dar início a nosso projeto {#step-6-initialize-our-project} +### Passo 6: Inicialize nosso projeto {#step-6-initialize-our-project} -Primeiro, precisamos criar uma pasta para o nosso projeto. Navegue para a sua linha de comando e entre o seguinte. +Primeiro, precisaremos criar uma pasta para o nosso projeto. Navegue para a sua linha de comando e insira o seguinte. ``` mkdir hello-world cd hello-world ``` -Agora que estamos dentro da pasta do nosso projeto, vamos usar o comando `npm init `para inicializar o projeto. +Agora que estamos dentro da pasta do nosso projeto, usaremos o `npm init` para inicializar o projeto. -> Se você não tem npm instalado ainda, siga [essas instruções para instalar o Node.js e o npm](https://docs.alchemyapi.io/alchemy/guides/alchemy-for-macs#1-install-nodejs-and-npm). +> Se você ainda não tiver o npm instalado, siga [estas instruções para instalar o Node.js e o npm](https://docs.alchemyapi.io/alchemy/guides/alchemy-for-macs#1-install-nodejs-and-npm). -Para finalidade deste tutorial, não importa como você responde às questões de inicialização. Aqui está como nós fizemos para referência: +Para a finalidade deste tutorial, não importa como você responde às perguntas de inicialização. Veja como fizemos isso para referência: ``` -package name: (hello-world) -version: (1.0.0) -description: hello world smart contract -entry point: (index.js) -test command: -git repository: -keywords: -author: -license: (ISC) +nome do pacote: (hello-world) +versão: (1.0.0) +descrição: contrato inteligente hello world +ponto de entrada: (index.js) +comando de teste: +repositório git: +palavras-chave: +autor: +licença: (ISC) -About to write to /Users/.../.../.../hello-world/package.json: +Prestes a escrever para /Users/.../.../.../hello-world/package.json: { "name": "hello-world", "version": "1.0.0", - "description": "hello world smart contract", + "description": "contrato inteligente hello world", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" @@ -111,23 +114,23 @@ About to write to /Users/.../.../.../hello-world/package.json: } ``` -Aprove o package.json e estaremos prontos para começar! +Aprove o package.json e estamos prontos! -### Passo 7: Baixar Hardhat {#step-7-download-hardhat} +### Passo 7: Baixe o Hardhat {#step-7-download-hardhat} Hardhat é um ambiente de desenvolvimento para compilar, implementar, testar e depurar seu software de Ethereum. Ele ajuda os desenvolvedores na criação de contratos inteligentes e dapps localmente antes de implantar na cadeia real. -Dentro de nosso projeto `hello-world` execute: +Dentro do nosso projeto `hello-world`, execute: ``` npm install --save-dev hardhat ``` -Para mais detalhes, confira esta página sobre as [instruções de instalação](https://hardhat.org/getting-started/#overview). +Confira esta página para mais detalhes sobre as [instruções de instalação](https://hardhat.org/getting-started/#overview). -### Etapa 8: Criar o projeto Hardhat {#step-8-create-hardhat-project} +### Passo 8: Crie um projeto Hardhat {#step-8-create-hardhat-project} -Dentro da pasta do nosso projeto `hello-world`, rode: +Dentro da pasta do nosso projeto `hello-world`, execute: ``` npx hardhat @@ -145,65 +148,65 @@ Você deve então ver uma mensagem de boas-vindas e a opção de selecionar o qu 888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. 888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 -👷 Welcome to Hardhat v2.0.11 👷‍ +👷 Bem-vindo ao Hardhat v2.0.11 👷‍ -What do you want to do? … -Create a sample project -❯ Create an empty hardhat.config.js -Quit +O que você quer fazer? … +Crie um projeto de exemplo +❯ Crie um arquivo hardhat.config.js vazio +Sair ``` -Isto irá gerar um arquivo `hardhat.config.js` no projeto. Usaremos isso mais tarde neste tutorial para especificar a configuração do nosso projeto. +Isso gerará um arquivo `hardhat.config.js` no projeto. Usaremos isso mais tarde no tutorial para especificar a configuração do nosso projeto. -### Etapa 9: Adicionar as pastas do projeto {#step-9-add-project-folders} +### Passo 9: Adicione pastas de projeto {#step-9-add-project-folders} -Para manter a organização do nosso projeto, vamos criar duas novas pastas. No comando de linha, navegue para o diretório raiz do nosso projeto `hello-world` e digite: +Para manter o projeto organizado, vamos criar duas novas pastas. Na linha de comando, navegue para o diretório raiz do seu projeto `hello-world` e digite: ``` mkdir contracts mkdir scripts ``` -- `contracts/` é onde nós vamos manter o arquivo de código do contrato inteligente "hello world" -- `scripts/` é onde nós vamos manter scripts para implantar e interagir com nosso contrato +- `contracts/` é onde manteremos nosso arquivo de código do contrato inteligente hello world +- `scripts/` é onde manteremos os scripts para implantar e interagir com nosso contrato -### Etapa 10: Escrever nosso contrato {#step-10-write-our-contract} +### Passo 10: Escreva nosso contrato {#step-10-write-our-contract} -Você pode estar se perguntando, quando é que nós vamos escrever código? Está na hora! +Você pode estar se perguntando: quando vamos escrever código? Está na hora! -Abra o projeto hello-world no seu editor favorito. Contratos inteligentes são mais comumente escritos em Solidity, o que nós usaremos para escrever o nosso contrato inteligente. +Abra o projeto hello-world no seu editor favorito. Contratos inteligentes são mais comumente escritos em Solidity, que usaremos para escrever nosso contrato inteligente.‌ 1. Navegue para a pasta `contracts` e crie um novo arquivo chamado `HelloWorld.sol` -2. Veja abaixo uma amostra de contrato inteligente “Hello World”, que usaremos neste tutorial. Copie o conteúdo abaixo no arquivo `HelloWorld.sol`. +2. Abaixo está um exemplo de contrato inteligente "Hello World" que usaremos neste tutorial. Copie o conteúdo abaixo no arquivo `HelloWorld.sol`. -_Nota: Certifique-se de ler os comentários para entender o que o contrato faz._ +_Observação: certifique-se de ler os comentários para entender o que este contrato faz._ ``` -// Especifica a versão do Solidity usando a versão semântica. -// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma +// Especifica a versão do Solidity, usando versionamento semântico. +// Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma pragma solidity >=0.7.3; -// Defines a contract named `HelloWorld`. -// Um contrato é uma coleção de funções e dados (seu estado). Uma vez implantado, um contrato reside em um endereço específico na blockchain Ethereum. Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html +// Define um contrato chamado `HelloWorld`. +// Um contrato é uma coleção de funções e dados (seu estado). Depois de implantado, um contrato reside em um endereço específico na blockchain Ethereum. Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html contract HelloWorld { - //Emitted when update function is called - //Smart contract events are a way for your contract to communicate that something happened on the blockchain to your app front-end, which can be 'listening' for certain events and take action when they happen. + //Emitido quando a função de atualização é chamada + //Os eventos de contratos inteligentes são uma forma de o seu contrato comunicar que algo aconteceu na blockchain para o front-end do seu aplicativo, que pode estar 'ouvindo' certos eventos e agir quando eles acontecem. event UpdatedMessages(string oldStr, string newStr); - // Declares a state variable `message` of type `string`. - // Variáveis de estado são variáveis cujos valores são permanentemente armazenados no armazenamento do contrato. The keyword `public` makes variables accessible from outside a contract and creates a function that other contracts or clients can call to access the value. + // Declara uma variável de estado `message` do tipo `string`. + // As variáveis de estado são variáveis cujos valores são permanentemente armazenados no armazenamento do contrato. A palavra-chave `public` torna as variáveis acessíveis de fora de um contrato e cria uma função que outros contratos ou clientes podem chamar para acessar o valor. string public message; - // Similar to many class-based object-oriented languages, a constructor is a special function that is only executed upon contract creation. - // Os construtores são usados para inicializar os dados do contrato. Learn more:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors + // Semelhante a muitas linguagens orientadas a objetos baseadas em classes, um construtor é uma função especial que só é executada na criação do contrato. + // Os construtores são usados para inicializar os dados do contrato. Saiba mais:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors constructor(string memory initMessage) { - // Accepts a string argument `initMessage` and sets the value into the contract's `message` storage variable). + // Aceita um argumento de string `initMessage` e define o valor na variável de armazenamento `message` do contrato. message = initMessage; } - // A public function that accepts a string argument and updates the `message` storage variable. + // Uma função pública que aceita um argumento de string e atualiza a variável de armazenamento `message`. function update(string memory newMessage) public { string memory oldMsg = message; message = newMessage; @@ -212,15 +215,15 @@ contract HelloWorld { } ``` -Este é um contrato inteligente básico que armazena uma mensagem quando da sua criação. Ele pode ser atualizado chamando-se a função `update`. +Este é um contrato inteligente básico que armazena uma mensagem quando da sua criação. Ele pode ser atualizado chamando a função `update`. -### Etapa 11: Vincular as contas MetaMask e Alchemy a seu projeto {#step-11-connect-metamask-alchemy-to-your-project} +### Passo 11: Conecte o MetaMask e o Alchemy ao seu projeto {#step-11-connect-metamask-alchemy-to-your-project} -Nós já criamos uma carteira Metamask, uma conta Alchemy e já escrevemos nosso contrato inteligente. Agora é hora de vincularmos os três. +Nós criamos uma carteira MetaMask, uma conta da Alchemy e escrevemos nosso contrato inteligente. Agora é hora de conectar os três. -Toda transação enviada da sua carteira requer uma assinatura, usando sua chave privada única. Para fornecer esta permissão ao nosso programa, podemos armazenar seguramente nossa chave privada em um arquivo de ambiente. Nós armazenaremos também uma chave de API da Alchemy aqui. +Toda transação enviada da sua carteira requer uma assinatura usando sua chave privada única. Para fornecer essa permissão ao nosso programa, podemos armazenar nossa chave privada com segurança em um arquivo de ambiente. Também armazenaremos uma chave de API para o Alchemy aqui. -> Para saber mais sobre o envio de transações, confira [este tutorial](https://docs.alchemyapi.io/alchemy/tutorials/sending-transactions-using-web3-and-alchemy) sobre o envio de transações usando web3. +> Para saber mais sobre o envio de transações, confira [este tutorial](https://www.alchemy.com/docs/hello-world-smart-contract#step-11-connect-metamask--alchemy-to-your-project) sobre como enviar transações usando web3. Primeiro, instale o pacote dotenv na pasta do seu projeto: @@ -228,41 +231,41 @@ Primeiro, instale o pacote dotenv na pasta do seu projeto: npm install dotenv --save ``` -Então, crie um arquivo `.env` no diretório raiz do projeto. Adicione sua chave privada MetaMask e URL da API HTTP Alchemy a ele. +Em seguida, crie um arquivo `.env` no diretório raiz do projeto. Adicione sua chave privada do MetaMask e o URL da API HTTP da Alchemy a ele. -Seu arquivo de ambiente deve ser nomeado `.env` or ele não será reconhecido como arquivo de ambiente. +Seu arquivo de ambiente deve ser nomeado `.env`, caso contrário, não será reconhecido como um arquivo de ambiente. Não o nomeie como `process.env` ou `.env-custom` ou qualquer outra coisa. - Siga [estas instruções](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key) para exportar sua chave privada -- Veja abaixo como obter o URL da API HTTP Alchemy +- Veja abaixo para obter o URL da API HTTP da Alchemy -![](./get-alchemy-api-key.gif) +![Passo a passo animado para obter uma chave de API Alchemy](./get-alchemy-api-key.gif) -Seu arquivo `.env` ficará assim: +Seu `.env` deve ficar assim: ``` -API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key" -PRIVATE_KEY = "your-metamask-private-key" +API_URL = "https://eth-goerli.alchemyapi.io/v2/sua-chave-de-api" +PRIVATE_KEY = "sua-chave-privada-metamask" ``` -Para realmente vinculá-los a nosso código, vamos fazer referência a essas variáveis em nosso arquivo `hardhat.config.js` no passo 13. +Para realmente conectar isso ao nosso código, faremos referência a essas variáveis em nosso arquivo `hardhat.config.js` na etapa 13. ### Etapa 12: Instalar o Ethers.js {#step-12-install-ethersjs} -Ethers.js é uma biblioteca que facilita a interação e o envio de solicitações ao Ethereum ao incorporar [métodos padrões JSON-RPC](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc) a outros métodos mais amigáveis ao usuário. +Ethers.js é uma biblioteca que facilita a interação e o envio de solicitações ao Ethereum ao incorporar métodos padrões JSON-RPC a outros métodos mais amigáveis ao usuário. -O Hardhat nos permite integrar [plugins](https://hardhat.org/plugins/) para ferramentas adicionais e funcionalidade estendida. Aproveitaremos o [plugin Ethers](https://hardhat.org/docs/plugins/official-plugins#hardhat-ethers) para implantar o contrato. +O Hardhat nos permite integrar [plugins](https://hardhat.org/plugins/) para ferramentas adicionais e funcionalidades estendidas. Aproveitaremos o [plugin Ethers](https://hardhat.org/docs/plugins/official-plugins#hardhat-ethers) para a implantação do contrato. -No diretório do projeto, digite: +No diretório do seu projeto, digite: ```bash npm install --save-dev @nomiclabs/hardhat-ethers "ethers@^5.0.0" ``` -### Etapa 13: Atualizar hardhat.config.js {#step-13-update-hardhat-configjs} +### Passo 13: Atualize o hardhat.config.js {#step-13-update-hardhat-configjs} -Até aqui, já adicionamos diversas dependências e plugins. Agora precisamos atualizar o `hardhat.config.js` para que nosso projeto reconheça todos eles. +Adicionamos várias dependências e plugins até agora. Agora precisamos atualizar o `hardhat.config.js` para que nosso projeto saiba sobre todos eles. Atualize seu `hardhat.config.js` para ficar assim: @@ -289,9 +292,9 @@ module.exports = { } ``` -### Etapa 14: Compilar nosso contrato {#step-14-compile-our-contract} +### Passo 14: Compile nosso contrato {#step-14-compile-our-contract} -Para ter certeza de que tudo está funcionando, vamos compilar nosso contrato. A tarefa `compile` é uma das tarefas integradas do Hardhat. +Para ter certeza de que tudo está funcionando, vamos compilar nosso contrato. A tarefa `compile` é uma das tarefas incorporadas do hardhat. Na linha de comando, execute: @@ -299,21 +302,21 @@ Na linha de comando, execute: npx hardhat compile ``` -Você pode receber o aviso `SPDX license identifier not provided in source file`, mas não há necessidade de se preocupar com isso. Esperemos que tudo mais esteja bem! Se não, você sempre pode enviar uma mensagem no [discord Alchemy](https://discord.gg/u72VCg3). +Você pode receber um aviso sobre `identificador de licença SPDX não fornecido no arquivo de origem`, mas não precisa se preocupar com isso — esperamos que todo o resto esteja bem! Se não, você sempre pode enviar uma mensagem no [Discord da Alchemy](https://discord.gg/u72VCg3). -### Etapa 15: Escrever nosso script de implantação {#step-15-write-our-deploy-script} +### Passo 15: Escreva nosso script de implantação {#step-15-write-our-deploy-script} Agora que nosso contrato está escrito e nosso arquivo de configuração está pronto, é hora de escrever o script de implantação do contrato. -Navegue até a pasta `scripts/` e crie um novo arquivo chamado `deploy.js`, adicionando o seguinte conteúdo: +Navegue até a pasta `scripts/` e crie um novo arquivo chamado `deploy.js`, adicionando o seguinte conteúdo a ele: ```javascript async function main() { const HelloWorld = await ethers.getContractFactory("HelloWorld") - // Start deployment, returning a promise that resolves to a contract object + // Iniciar a implantação, retornando uma promessa que resolve para um objeto de contrato const hello_world = await HelloWorld.deploy("Hello World!") - console.log("Contract deployed to address:", hello_world.address) + console.log("Contrato implantado no endereço:", hello_world.address) } main() @@ -324,23 +327,23 @@ main() }) ``` -A Hardhat fez um trabalho incrível ao explicar o que cada uma dessas linhas de código faz em seu [Tutorial sobre contratos](https://hardhat.org/tutorial/testing-contracts.html#writing-tests). Adotamos aqui as explicações deles. +A Hardhat faz um trabalho incrível explicando o que cada uma dessas linhas de código faz em seu [tutorial de Contratos](https://hardhat.org/tutorial/testing-contracts.html#writing-tests), nós adotamos as explicações deles aqui. ```javascript const HelloWorld = await ethers.getContractFactory("HelloWorld") ``` -Uma `ContractFactory` em ethers.js é uma abstração usada para implantar novos contratos inteligentes, então, aqui, `HelloWorld` representa uma [fábrica](https://en.wikipedia.org/wiki/Factory_(object-oriented_programming)) para instâncias do nosso contrato Hello World. Quando usar o plugin `hardhat-ethers` `ContractFactory` e `Contract`, as instâncias estão conectadas ao primeiro assinante (proprietário) por padrão. +Uma `ContractFactory` no ethers.js é uma abstração usada para implantar novos contratos inteligentes, então, `HelloWorld` aqui é uma [fábrica](https://en.wikipedia.org/wiki/Factory_\(object-oriented_programming\)) para instâncias do nosso contrato "olá, mundo". Ao usar o plugin `hardhat-ethers` `ContractFactory` e `Contract`, as instâncias são conectadas ao primeiro signatário (proprietário) por padrão. ```javascript const hello_world = await HelloWorld.deploy() ``` -Chamar `deploy()` em uma `ContractFactory`, irá iniciar a implantação, e retornará uma `Promise` que se resolve em um objeto `Contract`. Este é o objeto que tem um método para cada uma de nossas funções de contrato inteligente. +Chamar `deploy()` em uma `ContractFactory` iniciará a implantação e retornará uma `Promise` que resolve para um objeto `Contract`. Este é o objeto que tem um método para cada uma de nossas funções de contrato inteligente. ### Etapa 16: Implantar nosso contrato {#step-16-deploy-our-contract} -Finalmente estamos prontos para implantar o nosso contrato inteligente! Navegue até a linha de comando e digite: +Finalmente estamos prontos para implantar o nosso contrato inteligente! Navegue até a linha de comando e execute: ```bash npx hardhat run scripts/deploy.js --network goerli @@ -349,36 +352,36 @@ npx hardhat run scripts/deploy.js --network goerli Você deverá ver algo assim: ```bash -Contract deployed to address: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570 +Contrato implantado no endereço: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570 ``` -**Por favor, grave este endereço**. Nós o usaremos mais tarde neste tutorial. +**Por favor, salve este endereço**. Nós o usaremos mais tarde neste tutorial. -Se formos ao [etherscan da Goerli](https://goerli.etherscan.io) e procurarmos nosso endereço de contrato, devemos ser capazes de ver que ele foi implantado com sucesso. A transação ficará parecida com isto: +Se formos ao [etherscan da Goerli](https://goerli.etherscan.io) e procurarmos o endereço do nosso contrato, devemos conseguir ver que ele foi implantado com sucesso. A transação ficará parecida com isto: ![](./etherscan-contract.png) -O endereço `From` deve combinar com o endereço da sua conta MetaMask, e o endereço `To` conterá **Contract Creation**. Se clicarmos na transação, veremos o nosso endereço de contrato no campo `To`. +O endereço `From` deve corresponder ao endereço da sua conta MetaMask e o endereço `To` dirá **Criação de Contrato**. Se clicarmos na transação, veremos o nosso endereço de contrato no campo `To`. ![](./etherscan-transaction.png) Parabéns! Você acaba de implantar um contrato inteligente em uma rede de teste Ethereum. -Para entender o que está acontecendo nos bastidores, vamos navegar até a guia Explorer no [painel do Alchemy](https://dashboard.alchemyapi.io/explorer). Se você tem vários aplicativos Alchemy, certifique-se de filtrar por app e selecionar **Hello World**. +Para entender o que está acontecendo nos bastidores, vamos navegar até a guia Explorer no nosso [painel da Alchemy](https://dashboard.alchemy.com/explorer). Se você tem vários aplicativos Alchemy, certifique-se de filtrar por aplicativo e selecionar **Hello World**. ![](./hello-world-explorer.png) -Aqui você verá um punhado de métodos JSON-RPC que Hardhat/Ethers fizeram em segundo plano para nós quando chamamos a função `.deploy() `. Dois importantes métodos aqui são [`eth_sendRawTransaction`](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_sendrawtransaction), que é a requisição para escrever nosso contrato na cadeia Goerli, e [`eth_getTransactionByHash`](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_gettransactionbyhash) que é uma requisição para ler informações sobre nossa transação, dado o hash. Para saber mais sobre o envio de transações, confira [este tutorial sobre o envio de transações usando web3](/developers/tutorials/sending-transactions-using-web3-and-alchemy/). +Aqui você verá alguns métodos JSON-RPC que Hardhat/Ethers fizeram nos bastidores para nós quando chamamos a função `.deploy()`. Dois métodos importantes aqui são [`eth_sendRawTransaction`](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_sendrawtransaction), que é a solicitação para escrever nosso contrato na cadeia Goerli, e [`eth_getTransactionByHash`](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_gettransactionbyhash), que é uma solicitação para ler informações sobre nossa transação a partir do hash. Para saber mais sobre como enviar transações, confira [nosso tutorial sobre como enviar transações usando Web3](/developers/tutorials/sending-transactions-using-web3-and-alchemy/). -## Parte 2: Interaja com o seu Contrato Inteligente {#part-2-interact-with-your-smart-contract} +## Parte 2: Interaja com seu contrato inteligente {#part-2-interact-with-your-smart-contract} -Agora que você implantou com sucesso um contrato inteligente na rede Goerli, vamos aprender como interagir com ele. +Agora que implantamos com sucesso um contrato inteligente na rede Goerli, vamos aprender como interagir com ele. ### Crie um arquivo interact.js {#create-a-interactjs-file} -Este é o arquivo onde nós iremos escrever nosso script de interação. Nós usaremos a biblioteca Ether.js que você instalou anteriormente na Parte1. +Este é o arquivo onde escreveremos nosso script de interação. Usaremos a biblioteca Ethers.js que você instalou anteriormente na Parte 1. -Dentro da pasta `scripts/` crie um novo arquivo chamado `interact.js`, adicionando o seguinte código: +Dentro da pasta `scripts/`, crie um novo arquivo chamado `interact.js` e adicione o seguinte código: ```javascript // interact.js @@ -390,65 +393,65 @@ const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS ### Atualize seu arquivo .env {#update-your-env-file} -Nós usaremos novas variáveis de ambiente, portanto nós precisamos defini-las no arquivo `.env` que [ nós criamos antes](#step-11-connect-metamask-&-alchemy-to-your-project). +Usaremos novas variáveis de ambiente, então precisamos defini-las no arquivo `.env` que [criamos anteriormente](#step-11-connect-metamask-&-alchemy-to-your-project). -Nós precisaremos adicionar uma definição para a nossa `API_KEY` Alchemy e o `CONTRACT_ADDRESS` onde o nosso contrato inteligente foi implantado. +Precisaremos adicionar uma definição para a nossa `API_KEY` da Alchemy e o `CONTRACT_ADDRESS` onde nosso contrato inteligente foi implantado. -Seu arquivo `.env` deverá se parecer com isto: +Seu arquivo `.env` deve ter a seguinte aparência: ```bash # .env -API_URL = "https://eth-goerli.alchemyapi.io/v2/" -API_KEY = "" -PRIVATE_KEY = "" -CONTRACT_ADDRESS = "0x" +API_URL = "https://eth-goerli.alchemyapi.io/v2/" +API_KEY = "" +PRIVATE_KEY = "" +CONTRACT_ADDRESS = "0x" ``` -### Pegue a ABI do seu contrato {#grab-your-contract-ABI} +### Obtenha a ABI do seu contrato {#grab-your-contract-ABI} -O [ABI (Interface binária da aplicação)](/glossary/#abi) do nosso contrato é a interface para interagir com o nosso contrato inteligente. O Hardhat automaticamente gera uma ABI e a salva no arquivo `HelloWorld.json`. Para usar a ABI, precisaremos analisar o conteúdo adicionando as seguintes linhas de código ao nosso arquivo `interact.js`: +A [ABI (Application Binary Interface)](/glossary/#abi) do nosso contrato é a interface para interagir com nosso contrato inteligente. O Hardhat gera automaticamente uma ABI e a salva em `HelloWorld.json`. Para usar a ABI, precisaremos analisar o conteúdo adicionando as seguintes linhas de código ao nosso arquivo `interact.js`: ```javascript // interact.js const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json") ``` -Se quiser ver a ABI, pode imprimi-la no console: +Se quiser ver a ABI, você pode imprimi-la no seu console: ```javascript console.log(JSON.stringify(contract.abi)) ``` -Para ver o seu ABI impresso no console, navegue até seu terminal e execute: +Para ver sua ABI impressa no console, navegue até seu terminal e execute: ```bash npx hardhat run scripts/interact.js ``` -### Criar uma instância do seu contrato {#create-an-instance-of-your-contract} +### Crie uma instância do seu contrato {#create-an-instance-of-your-contract} -Para interagir com o nosso contrato, precisamos criar uma instância dele em nosso código. Para fazer isso com Ether.js, nós precisaremos trabalhar com três conceitos: +Para interagir com nosso contrato, precisamos criar uma instância dele em nosso código. Para fazer isso com Ethers.js, precisaremos trabalhar com três conceitos: -1. Provedor — um nó fornecedor que lhe dá acesso de leitura e escrita ao blockchain -2. Signatário — representa uma conta Ethereum que pode assinar transações -3. Contrato — um objeto Ether.js representando um contrato específico implantado on-chain +1. Provedor - um provedor de nós que lhe dá acesso de leitura e escrita ao blockchain +2. Signatário - representa uma conta Ethereum que pode assinar transações +3. Contrato - um objeto Ethers.js representando um contrato específico implantado on-chain Usaremos a ABI do contrato da etapa anterior para criar nossa instância do contrato: ```javascript // interact.js -// Provider +// Provedor const alchemyProvider = new ethers.providers.AlchemyProvider( (network = "goerli"), API_KEY ) -// Signer +// Signatário const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider) -// Contract +// Contrato const helloWorldContract = new ethers.Contract( CONTRACT_ADDRESS, contract.abi, @@ -456,15 +459,15 @@ const helloWorldContract = new ethers.Contract( ) ``` -Aprenda mais sobre Provedores, Signatários e Contratos na [documentação ethers.js](https://docs.ethers.io/v5/). +Saiba mais sobre Provedores, Signatários e Contratos na [documentação do ethers.js](https://docs.ethers.io/v5/). -### Leia a mensagem init {#read-the-init-message} +### Leia a mensagem inicial {#read-the-init-message} -Lembra-se de quando implantamos nosso contrato com o `initMessage = "Hello world!"`? Nós vamos agora ler a mensagem armazenada no nosso contrato inteligente e imprimi-la no console. +Lembra-se quando implantamos nosso contrato com a `initMessage = "Hello world!"`? Agora vamos ler essa mensagem armazenada em nosso contrato inteligente e imprimi-la no console. -Em JavaScript, funções assíncronas são usadas quando interagindo com redes. Para aprender mais sobre funções assíncronas, [leia este artigo](https://blog.bitsrc.io/understanding-asynchronous-javascript-the-event-loop-74cd408419ff). +Em JavaScript, funções assíncronas são usadas ao interagir com redes. Para saber mais sobre funções assíncronas, [leia este artigo do Medium](https://blog.bitsrc.io/understanding-asynchronous-javascript-the-event-loop-74cd408419ff). -Use o código abaixo para chamar a função `message` no nosso contrato inteligente e ler a mensagem init: +Use o código abaixo para chamar a função `message` em nosso contrato inteligente e ler a mensagem inicial: ```javascript // interact.js @@ -473,24 +476,24 @@ Use o código abaixo para chamar a função `message` no nosso contrato intelige async function main() { const message = await helloWorldContract.message() - console.log("The message is: " + message) + console.log("A mensagem é: " + message) } main() ``` -Depois de rodar o arquivo usando `npx hardhat run scripts/interact.js` no terminal, nós devemos ver esta resposta: +Depois de executar o arquivo usando `npx hardhat run scripts/interact.js` no terminal, devemos ver esta resposta: ``` -The message is: Hello world! +A mensagem é: Hello world! ``` -Parabéns! Você acabou de ler com sucesso dados de contrato inteligente do blockchain Ethereum, continue assim! +Parabéns! Você leu com sucesso os dados do contrato inteligente da blockchain Ethereum, parabéns! ### Atualize a mensagem {#update-the-message} -Ao invés de só ler a mensagem, nós podemos também atualizar a mensagem salva no nosso contrato inteligente usando a função `update`! Muito bacana, não? +Em vez de apenas ler a mensagem, também podemos atualizar a mensagem salva em nosso contrato inteligente usando a função `update`! Muito legal, não é? -Para atualizar a mensagem, nós podemos chamar diretamente a função `update` no nosso objeto Contract instanciado: +Para atualizar a mensagem, podemos chamar diretamente a função `update` em nosso objeto de Contrato instanciado: ```javascript // interact.js @@ -499,22 +502,22 @@ Para atualizar a mensagem, nós podemos chamar diretamente a função `update` n async function main() { const message = await helloWorldContract.message() - console.log("The message is: " + message) + console.log("A mensagem é: " + message) - console.log("Updating the message...") - const tx = await helloWorldContract.update("This is the new message.") + console.log("Atualizando a mensagem...") + const tx = await helloWorldContract.update("Esta é a nova mensagem.") await tx.wait() } main() ``` -Note que na linha 11, nós fazemos uma chamada para `.wait()` no objeto da transação retornada. Isso garante que nosso script espere pela transação ser minerada no blockchain antes de sair da função. Se a chamada `.wait()` não estiver incluída, o script pode não ver o valor da `message` atualizada no contrato. +Note que na linha 11, fazemos uma chamada para `.wait()` no objeto da transação retornada. Isso garante que nosso script espere a transação ser minerada na blockchain antes de sair da função. Se a chamada `.wait()` não for incluída, o script pode não ver o valor da `message` atualizada no contrato. ### Leia a nova mensagem {#read-the-new-message} -Você deve ser capaz de repetir o [passo anterior](#read-the-init-message) para ler o valor atualizado da `message`. Pegue um momento e veja se você pode fazer as mudanças necessárias para imprimir o novo valor! +Você deve ser capaz de repetir o [passo anterior](#read-the-init-message) para ler o valor atualizado da `message`. Tire um momento para ver se você consegue fazer as alterações necessárias para imprimir esse novo valor! -Se você precisar de uma dica, aqui está o que o seu arquivo `interact.js` deve se parecer neste ponto: +Se precisar de uma dica, veja como seu arquivo `interact.js` deve se parecer neste ponto: ```javascript // interact.js @@ -525,16 +528,16 @@ const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json") -// provider - Alchemy +// provedor - Alchemy const alchemyProvider = new ethers.providers.AlchemyProvider( (network = "goerli"), API_KEY ) -// signer - you +// signatário - você const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider) -// contract instance +// instância do contrato const helloWorldContract = new ethers.Contract( CONTRACT_ADDRESS, contract.abi, @@ -543,72 +546,72 @@ const helloWorldContract = new ethers.Contract( async function main() { const message = await helloWorldContract.message() - console.log("The message is: " + message) + console.log("A mensagem é: " + message) - console.log("Updating the message...") - const tx = await helloWorldContract.update("this is the new message") + console.log("Atualizando a mensagem...") + const tx = await helloWorldContract.update("esta é a nova mensagem") await tx.wait() const newMessage = await helloWorldContract.message() - console.log("The new message is: " + newMessage) + console.log("A nova mensagem é: " + newMessage) } main() ``` -Agora apenas rode o script e você deve ser capaz de ver a mensagem antiga, o estado atualizado, e a nova mensagem impressa no seu terminal! +Agora, apenas execute o script e você deverá ver a mensagem antiga, o status de atualização e a nova mensagem impressa em seu terminal! `npx hardhat run scripts/interact.js --network goerli` ``` -The message is: Hello World! -Updating the message... -The new message is: This is the new message. +A mensagem é: Hello World! +Atualizando a mensagem... +A nova mensagem é: Esta é a nova mensagem. ``` -Enquanto estiver rodando este script, você pode perceber que o passo `Updating the message...` leva um tempo para carregar antes da nova mensagem carregar. Isto é por causa do processo de mineração; se você é curioso sobre rastrear transações enquanto elas estão sendo mineradas, visite o [Alchemy mempool](https://dashboard.alchemyapi.io/mempool) para ver o estado da transação. Se a transação for derrubada, também é útil checar o [Goerli Etherscan](https://goerli.etherscan.io) e procurar pelo hash da sua transação. +Ao executar esse script, você pode perceber que a etapa `Atualizando a mensagem...` leva um tempo para carregar antes que a nova mensagem seja carregada. Isso se deve ao processo de mineração; se você tiver curiosidade em rastrear transações enquanto elas estão sendo mineradas, visite o [mempool da Alchemy](https://dashboard.alchemyapi.io/mempool) para ver o status de uma transação. Se a transação for descartada, também é útil verificar o [Goerli Etherscan](https://goerli.etherscan.io) e pesquisar pelo hash da sua transação. -## Parte 3: Publique seu Contrato Inteligente no Etherscan {#part-3-publish-your-smart-contract-to-etherscan} +## Parte 3: Publique seu contrato inteligente no Etherscan {#part-3-publish-your-smart-contract-to-etherscan} -Você fez todo o trabalho duro dar vida ao seu contrato inteligente; agora é hora de compartilhá-lo com o mundo! +Você fez todo o trabalho duro de dar vida ao seu contrato inteligente; agora é hora de compartilhá-lo com o mundo! -Verificando seu contrato inteligente no Etherscan, qualquer um pode ver seu código-fonte e interagir com o seu contrato inteligente. Vamos começar! +Ao verificar seu contrato inteligente no Etherscan, qualquer pessoa pode visualizar seu código-fonte e interagir com seu contrato inteligente. Vamos começar! -### Passo 1: Gere a Chave API na sua conta Etherscan {#step-1-generate-an-api-key-on-your-etherscan-account} +### Passo 1: Gere uma chave de API na sua conta Etherscan {#step-1-generate-an-api-key-on-your-etherscan-account} -Uma Chave API Etherscan é necessária para verificar que você possui o contrato inteligente que você está tentando publicar. +Uma chave de API do Etherscan é necessária para verificar que você é o proprietário do contrato inteligente que está tentando publicar. -Se você não tem uma conta Etherscan ainda, [se inscreva para uma conta](https://etherscan.io/register). +Se você ainda não tem uma conta no Etherscan, [cadastre-se para obter uma](https://etherscan.io/register). -Uma vez conectado, encontre seu nome de usuário na barra de navegação, passe o mouse em cima dele, e selecione o botão **My profile**. +Depois de fazer o login, encontre seu nome de usuário na barra de navegação, passe o mouse sobre ele e selecione o botão **My profile**. -Na página do seu perfil, você deve ver uma barra de navegação lateral. Da barra de navegação lateral, selecione **API Keys**. Em seguida, pressione o botão "Add" para criar uma nova chave API, nomeie seu app **hello-world**e pressione o botão **Create New API Key**. +Na página do seu perfil, você deverá ver uma barra de navegação lateral. Na barra de navegação lateral, selecione **API Keys**. Em seguida, pressione o botão "Add" para criar uma nova chave de API, nomeie seu aplicativo **hello-world** e pressione o botão **Create New API Key**. -Sua nova chave API deve aparecer na tabela de chaves API. Copie a chave API na sua área de transferência. +Sua nova chave de API deve aparecer na tabela de chaves de API. Copie a chave de API para sua área de transferência. -Agora nós precisamos adicionar a chave API Etherscan no seu arquivo `.env`. +Em seguida, precisamos adicionar a chave de API do Etherscan ao nosso arquivo `.env`. -Depois de adicionar isso, seu arquivo `.env` deve se parecer com isso: +Depois de adicioná-la, seu arquivo `.env` deve ter a seguinte aparência: ```javascript -API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key" -PUBLIC_KEY = "your-public-account-address" -PRIVATE_KEY = "your-private-account-address" -CONTRACT_ADDRESS = "your-contract-address" -ETHERSCAN_API_KEY = "your-etherscan-key" +API_URL = "https://eth-goerli.alchemyapi.io/v2/sua-chave-de-api" +PUBLIC_KEY = "seu-endereco-de-conta-publica" +PRIVATE_KEY = "seu-endereco-de-conta-privada" +CONTRACT_ADDRESS = "seu-endereco-de-contrato" +ETHERSCAN_API_KEY = "sua-chave-etherscan" ``` -### Contratos inteligentes implantados pelo Hardhat {#hardhat-deployed-smart-contracts} +### Contratos inteligentes implantados com Hardhat {#hardhat-deployed-smart-contracts} #### Instale o hardhat-etherscan {#install-hardhat-etherscan} -Publicar o seu contrato no Etherscan usando Hardhat é uma tarefa direta. Você primeiro precisa instalar o plugin `hardhat-etherscan` para começar. `hardhat-etherscan` verificará automaticamente o código-fonte do contrato inteligente e da ABI no Etherscan. Para adicionar isso, no diretório `hello-world` rode: +Publicar seu contrato no Etherscan usando o Hardhat é simples. Você precisará primeiro instalar o plugin `hardhat-etherscan` para começar. `hardhat-etherscan` verificará automaticamente o código-fonte do contrato inteligente e a ABI no Etherscan. Para adicionar isso, no diretório `hello-world`, execute: ```text npm install --save-dev @nomiclabs/hardhat-etherscan ``` -Uma vez instalado, inclua o seguinte comando no topo do seu `hardhat.config.js`, e adicione as opções de configuração Etherscan: +Uma vez instalado, inclua a seguinte declaração no topo do seu `hardhat.config.js` e adicione as opções de configuração do Etherscan: ```javascript // hardhat.config.js @@ -630,8 +633,8 @@ module.exports = { }, }, etherscan: { - // Your API key for Etherscan - // Obtain one at https://etherscan.io/ + // Sua chave de API para o Etherscan + // Obtenha uma em https://etherscan.io/ apiKey: ETHERSCAN_API_KEY, }, } @@ -639,91 +642,91 @@ module.exports = { #### Verifique seu contrato inteligente no Etherscan {#verify-your-smart-contract-on-etherscan} -Certifique-se que todos os arquivos foram salvos e todas as variáveis `.env` estão corretamente configuradas. +Certifique-se de que todos os arquivos estão salvos e todas as variáveis `.env` estão configuradas corretamente. -Rode a tarefa `verify`, passando o endereço do contrato, e a rede onde ele foi implantado: +Execute a tarefa `verify`, passando o endereço do contrato e a rede onde ele está implantado: ```text -npx hardhat verify --network goerli DEPLOYED_CONTRACT_ADDRESS 'Hello World!' +npx hardhat verify --network goerli ENDERECO_DO_CONTRATO_IMPLANTADO 'Hello World!' ``` -Certifique-se que `DEPLOYED_CONTRACT_ADDRESS` é o endereço do seu contrato inteligente implantado na rede de teste Goerli. Além disso, o argumento final (`'Hello World!'`) tem de ser o mesmo valor de string usado [durante o passo de implantação na parte 1](#write-our-deploy-script). +Certifique-se de que `DEPLOYED_CONTRACT_ADDRESS` é o endereço do seu contrato inteligente implantado na rede de teste Goerli. Além disso, o argumento final (`'Hello World!'`) deve ser o mesmo valor de string usado [durante a etapa de implantação na parte 1](#write-our-deploy-script). -Se tudo der certo, você verá a seguinte mensagem no seu terminal: +Se tudo correr bem, você verá a seguinte mensagem no seu terminal: ```text -Successfully submitted source code for contract -contracts/HelloWorld.sol:HelloWorld at 0xdeployed-contract-address -for verification on Etherscan. Waiting for verification result... +Código-fonte enviado com sucesso para o contrato +contracts/HelloWorld.sol:HelloWorld em 0xendereco-do-contrato-implantado +para verificação no Etherscan. Aguardando resultado da verificação... -Successfully verified contract HelloWorld on Etherscan. -https://goerli.etherscan.io/address/#contracts +Contrato HelloWorld verificado com sucesso no Etherscan. +https://goerli.etherscan.io/address/#contracts ``` Parabéns! O código do seu contrato inteligente está no Etherscan! -### Cheque seu contrato inteligente no Etherscan! {#check-out-your-smart-contract-on-etherscan} +### Confira seu contrato inteligente no Etherscan! {#check-out-your-smart-contract-on-etherscan} -Quando você navegar para o link fornecido no seu terminal, você deve ser capaz de ver o código do seu contrato inteligente e ABI publicados no Etherscan! +Ao navegar para o link fornecido no seu terminal, você poderá ver o código do seu contrato inteligente e a ABI publicados no Etherscan! -**Parabéns, você conseguiu, campeão! Agora qualquer um pode chamar ou escrever no seu contrato inteligente! Nós mal conseguimos esperar o que você vai construir em seguida!** +**Uhuuuu - você conseguiu, campeão! Agora qualquer pessoa pode chamar ou escrever em seu contrato inteligente! Mal podemos esperar para ver o que você construirá em seguida!** -## Parte 4 - Integrando seu contrato inteligente com o front-end {#part-4-integrating-your-smart-contract-with-the-frontend} +## Parte 4 - Integrando seu contrato inteligente com o frontend {#part-4-integrating-your-smart-contract-with-the-frontend} -No fim deste tutorial você saberá como: +Ao final deste tutorial, você saberá como: -- Conectar uma carteira MetaMask no seu dapp +- Conectar uma carteira MetaMask ao seu dapp - Ler dados do seu contrato inteligente usando a API [Alchemy Web3](https://docs.alchemy.com/alchemy/documentation/alchemy-web3) -- Assinar transações Ethereum usando MetaMask +- Assinar transações Ethereum usando o MetaMask -Para este dapp, estaremos usando [React](https://reactjs.org/) como nosso framework de front-end; entretanto, é importante notar que nós não gastaremos muito tempo explicando seus fundamentos, já que estaremos principalmente focados em trazer funcionalidade Web3 para o nosso projeto. +Para este dapp, usaremos o [React](https://react.dev/) como nosso framework de frontend; no entanto, é importante notar que não gastaremos muito tempo explicando seus fundamentos, pois estaremos focados principalmente em trazer funcionalidades da Web3 para o nosso projeto. -Como um pré-requisito, você deve ter um nível iniciante de entendimento de React. Caso contrário, recomendamos concluir o tutorial oficial [Introdução ao React](https://reactjs.org/tutorial/tutorial.html). +Como pré-requisito, você deve ter um nível de entendimento de iniciante em React. Caso contrário, recomendamos concluir o [tutorial oficial de Introdução ao React](https://react.dev/learn). -### Clonar os arquivos iniciais {#clone-the-starter-files} +### Clone os arquivos iniciais {#clone-the-starter-files} -Primeiro, vá até o [repositório GitHub hello-world-part-four](https://github.com/alchemyplatform/hello-world-part-four-tutorial) para obter os arquivos iniciais para esse projeto e clone o repositório no seu computador local. +Primeiro, vá para o [repositório GitHub hello-world-part-four](https://github.com/alchemyplatform/hello-world-part-four-tutorial) para obter os arquivos iniciais deste projeto e clone este repositório em sua máquina local. -Abra o repositório clonado localmente. Note que ele contém duas pastas: `starter-files` e `completed`. +Abra o repositório clonado localmente. Observe que ele contém duas pastas: `starter-files` e `completed`. -- `starter-files`- **nós trabalharemos neste diretório**, nós conectaremos a UI à nossa carteira Ethereum e o contrato inteligente que nós publicamos no Etherscan na [Parte 3](#part-3). -- `completed` contém o tutorial inteiro completado e deve ser somente usado como referência se você estiver empacado. +- `starter-files`- **trabalharemos neste diretório**, conectaremos a UI à sua carteira Ethereum e ao contrato inteligente que publicamos no Etherscan na [Parte 3](#part-3). +- `completed` contém todo o tutorial concluído e deve ser usado apenas como referência se você ficar preso. -Em seguida, abra sua cópia de `starter-files` no seu editor de código favorito, e então navegue na pasta `src`. +Em seguida, abra sua cópia de `starter-files` no seu editor de código favorito e navegue até a pasta `src`. -Todo o código que vamos escrever será exibido na pasta `src`. Nós estaremos editando o componente `HelloWorld.js` e os arquivos JavaScript `util/interact.js` para dar ao seu projeto funcionalidade Web3. +Todo o código que escrevermos ficará na pasta `src`. Editaremos o componente `HelloWorld.js` e os arquivos JavaScript `util/interact.js` para dar ao nosso projeto a funcionalidade da Web3. -### Cheque os arquivos iniciais {#check-out-the-starter-files} +### Confira os arquivos iniciais {#check-out-the-starter-files} -Antes de começar a codificar, vamos explorar o que nos é fornecido nos arquivos iniciais. +Antes de começarmos a codificar, vamos explorar o que nos é fornecido nos arquivos iniciais. -#### Tenha seu projeto React em execução {#get-your-react-project-running} +#### Coloque seu projeto react para funcionar {#get-your-react-project-running} Vamos começar executando o projeto React em nosso navegador. A beleza do React é que uma vez que nosso projeto esteja sendo executado no nosso navegador, qualquer alteração que salvarmos será atualizada ao vivo em nosso navegador. -Para fazer com que o projeto funcione, navegue até o diretório raiz da pasta `starter-files`, e execute`npm install` no seu terminal para instalar as dependências do projeto: +Para iniciar o projeto, navegue para o diretório raiz da pasta `starter-files` e execute `npm install` no seu terminal para instalar as dependências do projeto: ```bash cd starter-files npm install ``` -Uma vez terminada a instalação, execute `npm start` em seu terminal: +Assim que a instalação for concluída, execute `npm start` em seu terminal: ```bash npm start ``` -Ao fazê-lo, deve abrir [http://localhost:3000/](http://localhost:3000/) no seu navegador, onde você verá o front-end do nosso projeto. Ele deve consistir em um campo \ (um lugar para atualizar a mensagem armazenada no seu contrato inteligente\), um botão “Conectar Carteira”, e um botão “Atualizar”. +Isso deve abrir [http://localhost:3000/](http://localhost:3000/) no seu navegador, onde você verá o frontend do nosso projeto. Ele deve consistir em um campo (um local para atualizar a mensagem armazenada em seu contrato inteligente), um botão "Conectar Carteira" e um botão "Atualizar". -Se você tentar clicar em qualquer dos botões você notará que eles não funcionam — isso porque ainda precisamos programar a funcionalidade deles. +Se você tentar clicar em qualquer um dos botões, notará que eles não funcionam — isso ocorre porque ainda precisamos programar sua funcionalidade. #### O componente `HelloWorld.js` {#the-helloworld-js-component} -Vamos voltar à pasta `src` no nosso editor e abrir o arquivo `HelloWorld.js`. É muito importante que entendamos tudo neste arquivo, pois é o principal componente do React no qual vamos trabalhar. +Vamos voltar para a pasta `src` em nosso editor e abrir o arquivo `HelloWorld.js`. É muito importante que entendamos tudo neste arquivo, pois é o principal componente do React no qual vamos trabalhar. -No começo deste arquivo você irá notar que nós temos diversas declarações importantes que são necessárias para termos nosso projeto rodando, incluindo a biblioteca React, os hooks useEffect e UseState, alguns itens do `./util/interact.js` (nós os descreveremos em mais detalhes em breve!), e o logo Alchemy. +No topo deste arquivo, você notará que temos várias declarações de importação necessárias para fazer nosso projeto funcionar, incluindo a biblioteca React, os hooks useEffect e useState, alguns itens do `./util/interact.js` (descreveremos em mais detalhes em breve!) e o logotipo da Alchemy. ```javascript // HelloWorld.js @@ -741,56 +744,56 @@ import { import alchemylogo from "./alchemylogo.svg" ``` -Em seguida, temos nossas variáveis de estado que serão atualizadas após eventos específicos. +Em seguida, temos nossas variáveis de estado que atualizaremos após eventos específicos. ```javascript // HelloWorld.js -//State variables +//Variáveis de estado const [walletAddress, setWallet] = useState("") const [status, setStatus] = useState("") -const [message, setMessage] = useState("No connection to the network.") +const [message, setMessage] = useState("Sem conexão com a rede.") const [newMessage, setNewMessage] = useState("") ``` Veja aqui o que cada uma das variáveis representa: - `walletAddress` - uma string que armazena o endereço da carteira do usuário -- `status` uma string que armazena uma mensagem útil que guia o usuário em como interagir com o dapp +- `status`- uma string que armazena uma mensagem útil que guia o usuário sobre como interagir com o dapp - `message` - uma string que armazena a mensagem atual no contrato inteligente -- `newMessage` -uma string que armazena a nova mensagem que será escrita no contrato inteligente +- `newMessage` - uma string que armazena a nova mensagem que será escrita no contrato inteligente -Depois das variáveis de estado, você verá cinco funções não implementadas: `useEffect` ,`addSmartContractListener`, `addWalletListener` , `connectWalletPressed`, e `onUpdatePressed`. Nós explicaremos o que elas fazem abaixo: +Após as variáveis de estado, você verá cinco funções não implementadas: `useEffect` ,`addSmartContractListener`, `addWalletListener` , `connectWalletPressed` e `onUpdatePressed`. Explicaremos o que elas fazem abaixo: ```javascript // HelloWorld.js -//called only once +//chamado apenas uma vez useEffect(async () => { - //TODO: implement + //TODO: implementar }, []) function addSmartContractListener() { - //TODO: implement + //TODO: implementar } function addWalletListener() { - //TODO: implement + //TODO: implementar } const connectWalletPressed = async () => { - //TODO: implement + //TODO: implementar } const onUpdatePressed = async () => { - //TODO: implement + //TODO: implementar } ``` -- [`useEffect`](https://reactjs.org/docs/hooks-effect.html)- isto é um hook React hook que é chamado depois que o seu componente é renderizado. Por ele ter um array vazio `[]` prop passada por ele \(veja linha 4\), ele só será chamado na _primeira_ renderização do componente. Aqui nós vamos carregar a mensagem atual armazenada no nosso contrato inteligente, chamar nosso contrato inteligente e listeners da carteira, e atualizar nos UI para refletir se a carteira já está conectada. -- `addSmartContractListener`- esta função configura um listener que irá aguardar o evento `UpdatedMessages` do nosso contrato HelloWorld e atualizar nossa UI quando a mensagem é alterada em nosso contrato inteligente. -- `addWalletListener`- esta função configura um listener que detecta mudanças no estado da carteira MetaMask do usuário, como quando o usuário desconecta sua carteira ou muda endereços. -- `connectWalletPressed`- esta função será chamada para conectar a carteira MetaMask do usuário no nosso dapp. +- [`useEffect`](https://legacy.reactjs.org/docs/hooks-effect.html)- este é um hook do React que é chamado após a renderização do seu componente. Como ele tem um prop de array vazio `[]` passado para ele (veja a linha 4), ele só será chamado na _primeira_ renderização do componente. Aqui, carregaremos a mensagem atual armazenada em nosso contrato inteligente, chamaremos nossos ouvintes de contrato inteligente e de carteira e atualizaremos nossa interface do usuário para refletir se uma carteira já está conectada. +- `addSmartContractListener` - esta função configura um ouvinte que observará o evento `UpdatedMessages` do nosso contrato HelloWorld e atualizará nossa interface do usuário quando a mensagem for alterada em nosso contrato inteligente. +- `addWalletListener` - esta função configura um ouvinte que detecta alterações no estado da carteira MetaMask do usuário, como quando o usuário desconecta sua carteira ou troca de endereços. +- `connectWalletPressed`- esta função será chamada para conectar a carteira MetaMask do usuário ao nosso dapp. - `onUpdatePressed` - essa função será chamada quando o usuário quiser atualizar a mensagem armazenada no contrato inteligente. Perto do final desse arquivo, temos a interface de usuário do nosso componente. @@ -798,64 +801,65 @@ Perto do final desse arquivo, temos a interface de usuário do nosso componente. ```javascript // HelloWorld.js -//the UI of our component +//a UI do nosso componente return (
-

Current Message:

+

Mensagem Atual:

{message}

-

New Message:

+

Nova Mensagem:

setNewMessage(e.target.value)} value={newMessage} />

{status}

-
-
+ + + ) ``` -Se você procurar com cuidado no código, você notará quando nós usamos nossas várias variáveis de estado na nossa UI: +Se você examinar este código com atenção, notará onde usamos nossas várias variáveis de estado em nossa interface do usuário: -- Nas linhas 6 a 12, se a carteira do usuário estiver conectada \(ou seja. `walletAddress.length > 0`\), mostraremos uma versão truncada da `walletAddress` do usuário no botão com a ID "walletButton;", caso contrário, ele simplesmente dirá "Connect Wallet." -- Na linha 17, nós mostramos a mensagem atual armazenada no contrato inteligente, que é capturada na string `message`. -- Nas linhas 23-26, nós usamos um [componente controlado](https://reactjs.org/docs/forms.html#controlled-components) para atualizar nossa variável de estado `newMessage` quando a entrada no campo texto muda. +- Nas linhas 6-12, se a carteira do usuário estiver conectada (ou seja, `walletAddress.length > 0`), exibimos uma versão truncada do `walletAddress` do usuário no botão com o ID "walletButton;" caso contrário, ele simplesmente diz "Conectar Carteira". +- Na linha 17, exibimos a mensagem atual armazenada no contrato inteligente, que é capturada na string `message`. +- Nas linhas 23-26, usamos um [componente controlado](https://legacy.reactjs.org/docs/forms.html#controlled-components) para atualizar nossa variável de estado `newMessage` quando a entrada no campo de texto muda. -Em adição às nossas variáveis de estado, você também verá que as funções `connectWalletPressed` e `onUpdatePressed` são chamadas quando os botões com IDs `publishButton` e `walletButton` são respectivamente clicados. +Além de nossas variáveis de estado, você também verá que as funções `connectWalletPressed` e `onUpdatePressed` são chamadas quando os botões com os IDs `publishButton` e `walletButton` são clicados, respectivamente. -Finalmente, vamos endereçar onde esse componente `HelloWorld.js` será adicionado. +Finalmente, vamos abordar onde este componente `HelloWorld.js` é adicionado. -Se você for ao arquivo `App.js`, que é o componente principal do React, que atua como um contêiner para todos os outros componentes, você verá que o nosso componente `HelloWorld.js` é injetado na linha 7. +Se você for ao arquivo `App.js`, que é o componente principal do React que atua como um contêiner para todos os outros componentes, você verá que nosso componente `HelloWorld.js` é injetado na linha 7. -Finalmente, mas não menos importante, vamos checar mais um arquivo fornecido para você, o arquivo `interact.js`. +Por último, mas não menos importante, vamos conferir mais um arquivo fornecido a você, o arquivo `interact.js`. #### O arquivo `interact.js` {#the-interact-js-file} -Como queremos respeitar o paradigma [M-V-C](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller), queremos um arquivo separado que contém todas as nossas funções para gerenciar a lógica, dados e regras do nosso dapp, para então conseguirmos exportar essas funções para o nosso front-end \(nosso componente `HelloWorld.js` component\). +Como queremos seguir o paradigma [M-V-C](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller), queremos um arquivo separado que contenha todas as nossas funções para gerenciar a lógica, os dados e as regras do nosso dapp e, em seguida, exportar essas funções para o nosso frontend (nosso componente `HelloWorld.js`). -👆🏽Esta é a exata finalidade do nosso arquivo `interact.js`! +👆🏽Este é o propósito exato do nosso arquivo `interact.js`! -Navegue para a pasta `util` no seu diretório `src`, e você notará que nós incluimos um arquivo chamado `interact.js` que irá conter todas as nossas interações com o contrato inteligente, funções de carteira, e variáveis. +Navegue até a pasta `util` em seu diretório `src` e você notará que incluímos um arquivo chamado `interact.js` que conterá todas as nossas funções e variáveis de interação com o contrato inteligente e a carteira. ```javascript // interact.js @@ -871,55 +875,55 @@ const getCurrentWalletConnected = async () => {} export const updateMessage = async (message) => {} ``` -Você pode notar no topo do arquivo que nós transformamos o objeto `helloWorldContract` em um comentário. Mais tarde neste tutorial nós vamos descomentar este objeto e instanciar nosso contrato inteligente nesta variável, que irá então exportar no nosso componente `HelloWorld.js`. +Você notará no topo do arquivo que comentamos o objeto `helloWorldContract`. Mais tarde neste tutorial, descomentaremos este objeto e instanciaremos nosso contrato inteligente nesta variável, que então exportaremos para nosso componente `HelloWorld.js`. -As quatro funções não implementadas depois do nosso objeto `helloWorldContract` fazem o seguinte: +As quatro funções não implementadas após nosso objeto `helloWorldContract` fazem o seguinte: -- `loadCurrentMessage`: esta função manipula a lógica de carregamento da mensagem atual armazenada no contrato inteligente. Ela fará uma chamada _read_ para o contrato inteligente Olá, Mundo usando a [API Web3 da Alchemy](https://github.com/alchemyplatform/alchemy-web3). -- `connectWallet`: essa função conectará a MetaMask do usuário ao nosso dapp. -- `getCurrentWalletConnected` - essa função irá checar se uma conta Ethereum já está conectada no nosso dapp no carregamento da página e atualização da nossa UI devidamente. -- `updateMessage` - esta função atualizará a mensagem armazenada no contrato inteligente. Ela fará uma chamada _write_ para o contrato inteligente Hello World, para que a carteira do usuário MetaMask tenha que assinar uma transação Ethereum para atualizar a mensagem. +- `loadCurrentMessage` - esta função lida com a lógica de carregar a mensagem atual armazenada no contrato inteligente. Ela fará uma chamada de _leitura_ para o contrato inteligente Hello World usando a [API Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3). +- `connectWallet` - esta função conectará a MetaMask do usuário ao nosso dapp. +- `getCurrentWalletConnected` - esta função verificará se uma conta Ethereum já está conectada ao nosso dapp ao carregar a página e atualizará nossa interface do usuário de acordo. +- `updateMessage` - esta função atualizará a mensagem armazenada no contrato inteligente. Ela fará uma chamada de _escrita_ para o contrato inteligente Hello World, então a carteira MetaMask do usuário terá que assinar uma transação Ethereum para atualizar a mensagem. -Agora que você entende no que estamos trabalhando, vamos entender como ler do nosso contrato inteligente! +Agora que entendemos com o que estamos trabalhando, vamos descobrir como ler do nosso contrato inteligente! -### Passo 3: Leia do seu Contrato Inteligente {#step-3-read-from-your-smart-contract} +### Passo 3: Leia do seu contrato inteligente {#step-3-read-from-your-smart-contract} -Para ler do seu contrato inteligente, você irá precisar configurar com sucesso: +Para ler do seu contrato inteligente, você precisará configurar com sucesso: -- Uma conexão API com a cadeia Ethereum -- Uma instância carregada para o seu contrato inteligente -- Uma função para chamar para a sua função de contrato inteligente -- Um ouvinte para observar as atualizações quando os dados de contrato inteligente que você está lendo mudem +- Uma conexão de API com a cadeia Ethereum +- Uma instância carregada do seu contrato inteligente +- Uma função para chamar a função do seu contrato inteligente +- Um ouvinte para observar as atualizações quando os dados que você está lendo do contrato inteligente mudarem -Isto pode parecer que são muitos passos, mas não se preocupe! Nós vamos acompanhá-lo como fazer cada um deles passo a passo! :\) +Isso pode parecer muitos passos, mas não se preocupe! Vamos guiá-lo passo a passo sobre como fazer cada um deles! :\) -#### Estabeleça uma conexão API com a cadeia Ethereum {#establish-an-api-connection-to-the-ethereum-chain} +#### Estabeleça uma conexão de API com a cadeia Ethereum {#establish-an-api-connection-to-the-ethereum-chain} -Você se lembra como na Parte 2 deste tutorial usamos a nossa chave [Alchemy Web3 para ler do nosso contrato inteligente](https://docs.alchemy.com/alchemy/tutorials/hello-world-smart-contract/interacting-with-a-smart-contract#step-1-install-web3-library)? Você também irá precisar de uma chave Alchemy Web3 em seu dapp para ler da cadeia. +Então, lembra como na Parte 2 deste tutorial, usamos nossa [chave Web3 da Alchemy para ler do nosso contrato inteligente](https://docs.alchemy.com/alchemy/tutorials/hello-world-smart-contract/interacting-with-a-smart-contract#step-1-install-web3-library)? Você também precisará de uma chave Web3 da Alchemy em seu dapp para ler da cadeia. -Se você ainda não tem, primeiro instale [Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3) navegando até o diretório raiz do seu `starter-files` e executando o seguinte em seu terminal: +Se você ainda não tiver, primeiro instale o [Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3) navegando até o diretório raiz dos seus `starter-files` e executando o seguinte no seu terminal: ```text -yarn add @alch/alchemy-web3 +npm install @alch/alchemy-web3 ``` -[Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3) é um invólucro em torno do [Web3.js](https://docs.web3js.org/), fornecendo métodos aprimorados da API e outros benefícios cruciais para tornar a sua vida de desenvolvedor da Web3 mais fácil. Ele foi projetado para exigir uma configuração mínima, para que você possa começar a usá-la no seu aplicativo imediatamente! +O [Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3) é um wrapper em torno do [Web3.js](https://docs.web3js.org/), fornecendo métodos de API aprimorados e outros benefícios cruciais para facilitar sua vida como desenvolvedor web3. Ele foi projetado para exigir uma configuração mínima, para que você possa começar a usá-la no seu aplicativo imediatamente! -Então, instale o pacote [dotenv](https://www.npmjs.com/package/dotenv) no seu diretório do projeto, para termos um lugar seguro para armazenar nossa chave API depois de pegarmos ela. +Em seguida, instale o pacote [dotenv](https://www.npmjs.com/package/dotenv) no diretório do seu projeto, para termos um local seguro para armazenar nossa chave de API depois de buscá-la. ```text npm install dotenv --save ``` -Para o nosso dapp, **nós usaremos nossa chave API Websockets** ao invés de nossa chave API HTTP, já que nos garante configurar um listener que detecta quando a mensagem, armazenada no contrato inteligente, muda. +Para nosso dapp, **usaremos nossa chave de API Websockets** em vez da nossa chave de API HTTP, pois ela nos permitirá configurar um ouvinte que detecta quando a mensagem armazenada no contrato inteligente muda. -Uma vez que você tem a chave API, crie um arquivo `.env` no seu diretório raiz e adicione sua url Alchemy Websockets a ele. Depois disso, seu arquivo `.env` deve se parecer com isso: +Depois de ter sua chave de API, crie um arquivo `.env` no seu diretório raiz e adicione sua URL de Websockets da Alchemy a ele. Depois disso, seu arquivo `.env` deve ter a seguinte aparência: ```javascript -REACT_APP_ALCHEMY_KEY = wss://eth-goerli.ws.alchemyapi.io/v2/ +REACT_APP_ALCHEMY_KEY = wss://eth-goerli.ws.alchemyapi.io/v2/ ``` -Agora estamos prontos para configurar nosso ponto de extremidade Web3 da Alchemy no nosso dapp! Vamos voltar para o nosso `interact.js`, que é aninhado dentro da nossa pasta `util` e adicionar o seguinte código no topo do arquivo: +Agora, estamos prontos para configurar nosso ponto de extremidade Alchemy Web3 em nosso dapp! Vamos voltar ao nosso `interact.js`, que está aninhado dentro da nossa pasta `util`, e adicionar o seguinte código no topo do arquivo: ```javascript // interact.js @@ -932,23 +936,23 @@ const web3 = createAlchemyWeb3(alchemyKey) //export const helloWorldContract; ``` -Acima, nós primeiro importamos a chave Alchemy do nosso arquivo `.env` e então passamos nosso `alchemyKey` para `createAlchemyWeb3` estabelecer nosso endpoint Alchemy Web3. +Acima, primeiro importamos a chave da Alchemy do nosso arquivo `.env` e depois passamos nossa `alchemyKey` para `createAlchemyWeb3` para estabelecer nosso ponto de extremidade Alchemy Web3. -Com este endpoint pronto, é hora de carregar nosso contrato inteligente! +Com este ponto de extremidade pronto, é hora de carregar nosso contrato inteligente! -#### Carregando o seu contrato inteligente Hello World {#loading-your-hello-world-smart-contract} +#### Carregando seu contrato inteligente Hello World {#loading-your-hello-world-smart-contract} -Para carregar o seu contrato inteligente Hello World, você precisará do seu endereço de contrato e ABI, ambos os quais podem ser encontrados no Etherscan se você completou a [Parte 3 deste tutorial.](/developers/tutorials/hello-world-smart-contract-fullstack/#part-3-publish-your-smart-contract-to-etherscan-part-3-publish-your-smart-contract-to-etherscan) +Para carregar seu contrato inteligente Hello World, você precisará do endereço do contrato e da ABI, ambos podem ser encontrados no Etherscan se você concluiu a [Parte 3 deste tutorial.](/developers/tutorials/hello-world-smart-contract-fullstack/#part-3-publish-your-smart-contract-to-etherscan-part-3-publish-your-smart-contract-to-etherscan) #### Como obter a ABI do seu contrato no Etherscan {#how-to-get-your-contract-abi-from-etherscan} -Se você pulou a Parte 3 deste tutorial, você pode usar o contrato Olá, Mundo com o endereço [0x6f3f635A9762B47954229Ea479b4541eAF402A6A](https://goerli.etherscan.io/address/0x6f3f635a9762b47954229ea479b4541eaf402a6a#code). Sua ABI pode ser encontrada [aqui](https://goerli.etherscan.io/address/0x6f3f635a9762b47954229ea479b4541eaf402a6a#code). +Se você pulou a Parte 3 deste tutorial, pode usar o contrato HelloWorld com o endereço [0x6f3f635A9762B47954229Ea479b4541eAF402A6A](https://goerli.etherscan.io/address/0x6f3f635a9762b47954229ea479b4541eaf402a6a#code). Sua ABI pode ser encontrada [aqui](https://goerli.etherscan.io/address/0x6f3f635a9762b47954229ea479b4541eaf402a6a#code). -A ABI de um contrato é necessária para especificar qual função um contrato irá invocar, assim como garantir que a função irá retornar dados no formato que você está esperando. Uma vez que nós copiamos nosso contrato ABI, vamos salvá-lo como um arquivo JSON chamado `contract-abi.json` no seu diretório `src`. +A ABI de um contrato é necessária para especificar qual função um contrato invocará, bem como para garantir que a função retorne dados no formato que você espera. Depois de copiar a ABI do nosso contrato, vamos salvá-la como um arquivo JSON chamado `contract-abi.json` em seu diretório `src`. -O seu contract-abi.json deve ser armazenado na sua pasta src. +Seu contract-abi.json deve ser armazenado na sua pasta src. -Armados com nosso endereço de contrato, ABI, e endpoint Alchemy Web3, nós podemos usar o [método do contrato](https://docs.web3js.org/api/web3-eth-contract/class/Contract) para carregar uma instância do nosso contrato inteligente. Importe a ABI do seu contrato no arquivo `interact.js` e adicione o seu endereço de contrato. +Armados com o endereço do nosso contrato, ABI e o ponto de extremidade da Alchemy Web3, podemos usar o [método de contrato](https://docs.web3js.org/api/web3-eth-contract/class/Contract) para carregar uma instância do nosso contrato inteligente. Importe a ABI do seu contrato no arquivo `interact.js` e adicione o endereço do seu contrato. ```javascript // interact.js @@ -957,7 +961,7 @@ const contractABI = require("../contract-abi.json") const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A" ``` -Nós podemos agora finalmente descomentar nossa variável `helloWorldContract`, e carregar o contrato inteligente usando nosso endpoint AlchemyWeb3: +Agora podemos finalmente descomentar nossa variável `helloWorldContract` e carregar o contrato inteligente usando nosso ponto de extremidade AlchemyWeb3: ```javascript // interact.js @@ -967,7 +971,7 @@ export const helloWorldContract = new web3.eth.Contract( ) ``` -Para recapitular, as primeiras 12 linhas do seu `interact.js` deve agora se parecer com isso: +Para recapitular, as primeiras 12 linhas do seu `interact.js` devem ter a seguinte aparência: ```javascript // interact.js @@ -986,11 +990,11 @@ export const helloWorldContract = new web3.eth.Contract( ) ``` -Agora que nós temos nosso contrato carregado, nós podemos implementar nossa função `loadCurrentMessage`! +Agora que nosso contrato está carregado, podemos implementar nossa função `loadCurrentMessage`! -#### Implementando `loadCurrentMessage` no nosso arquivo `interact.js` {#implementing-loadCurrentMessage-in-your-interact-js-file} +#### Implementando `loadCurrentMessage` no seu arquivo `interact.js` {#implementing-loadCurrentMessage-in-your-interact-js-file} -Esta função é super simples. Nós vamos fazer uma simples chamada async web3 para ler do nosso contrato. Nossa função irá retornar a mensagem armazenada no contrato inteligente: +Esta função é super simples. Faremos uma chamada assíncrona simples da web3 para ler do nosso contrato. Nossa função retornará a mensagem armazenada no contrato inteligente: Atualize o `loadCurrentMessage` no seu arquivo `interact.js` para o seguinte: @@ -1003,60 +1007,60 @@ export const loadCurrentMessage = async () => { } ``` -Já que nós queremos exibir este contrato inteligente na nossa UI, vamos atualizar a função `useEffect` no nosso componente `HelloWorld.js` com o seguinte: +Como queremos exibir este contrato inteligente em nossa interface do usuário, vamos atualizar a função `useEffect` em nosso componente `HelloWorld.js` para o seguinte: ```javascript // HelloWorld.js -//called only once +//chamado apenas uma vez useEffect(async () => { const message = await loadCurrentMessage() setMessage(message) }, []) ``` -Note que nós somente queremos nosso `loadCurrentMessage` ser chamado uma vez durante a primeira renderização do componente. Logo implementaremos `addSmartContractListener` para atualizar automaticamente a interface do usuário depois que a mensagem no contrato inteligente mudar. +Observe que só queremos que nosso `loadCurrentMessage` seja chamado uma vez durante a primeira renderização do componente. Em breve, implementaremos o `addSmartContractListener` para atualizar automaticamente a interface do usuário após a alteração da mensagem no contrato inteligente. -Antes que nós mergulhemos no nosso listener, vamos checar o que nós temos até aqui! Salve seus arquivos `HelloWorld.js` e `interact.js`, e então vá para [http://localhost:3000/](http://localhost:3000/) +Antes de mergulharmos em nosso ouvinte, vamos conferir o que temos até agora! Salve seus arquivos `HelloWorld.js` e `interact.js` e vá para [http://localhost:3000/](http://localhost:3000/) -Você notará que a mensagem atual não diz mais "No connection to the network." Ao invés disso, ela reflete a mensagem armazenada no contrato inteligente. Ótimo! +Você notará que a mensagem atual não diz mais "Sem conexão com a rede". Em vez disso, ela reflete a mensagem armazenada no contrato inteligente. Incrível! -#### Sua UI poderia agora refletir a mensagem armazenada no contrato inteligente {#your-UI-should-now-reflect-the-message-stored-in-the-smart-contract} +#### Sua interface do usuário agora deve refletir a mensagem armazenada no contrato inteligente {#your-UI-should-now-reflect-the-message-stored-in-the-smart-contract} -Agora falando daquele listener... +Agora, falando daquele ouvinte... -#### Implementar `addSmartContractListener` {#implement-addsmartcontractlistener} +#### Implemente `addSmartContractListener` {#implement-addsmartcontractlistener} -Se você voltar para pensar no arquivo `HelloWorld.sol` que escrevemos na [Parte 1 desta série de tutoriais](https://docs.alchemy.com/alchemy/tutorials/hello-world-smart-contract#step-10-write-our-contract), você se lembrará que há um evento de contrato inteligente chamado `UpdatedMessages` que é emitido depois da função `update` do nosso contrato inteligente ser invocada \(ver linhas 9 e 27\): +Se você se lembrar do arquivo `HelloWorld.sol` que escrevemos na [Parte 1 desta série de tutoriais](https://docs.alchemy.com/alchemy/tutorials/hello-world-smart-contract#step-10-write-our-contract), lembrará que há um evento de contrato inteligente chamado `UpdatedMessages` que é emitido após a invocação da função `update` do nosso contrato inteligente (veja as linhas 9 e 27): ```javascript // HelloWorld.sol -// Specifies the version of Solidity, using semantic versioning. -// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma +// Especifica a versão do Solidity, usando versionamento semântico. +// Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma pragma solidity ^0.7.3; -// Defines a contract named `HelloWorld`. -// Um contrato é uma coleção de funções e dados (seu estado). Uma vez implantado, um contrato reside em um endereço específico na blockchain Ethereum. Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html +// Define um contrato chamado `HelloWorld`. +// Um contrato é uma coleção de funções e dados (seu estado). Depois de implantado, um contrato reside em um endereço específico na blockchain Ethereum. Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html contract HelloWorld { - //Emitted when update function is called - //Smart contract events are a way for your contract to communicate that something happened on the blockchain to your app front-end, which can be 'listening' for certain events and take action when they happen. + //Emitido quando a função de atualização é chamada + //Os eventos de contratos inteligentes são uma forma de o seu contrato comunicar que algo aconteceu na blockchain para o front-end do seu aplicativo, que pode estar 'ouvindo' certos eventos e agir quando eles acontecem. event UpdatedMessages(string oldStr, string newStr); - // Declares a state variable `message` of type `string`. - // Variáveis de estado são variáveis cujos valores são permanentemente armazenados no armazenamento do contrato. The keyword `public` makes variables accessible from outside a contract and creates a function that other contracts or clients can call to access the value. + // Declara uma variável de estado `message` do tipo `string`. + // As variáveis de estado são variáveis cujos valores são permanentemente armazenados no armazenamento do contrato. A palavra-chave `public` torna as variáveis acessíveis de fora de um contrato e cria uma função que outros contratos ou clientes podem chamar para acessar o valor. string public message; - // Similar to many class-based object-oriented languages, a constructor is a special function that is only executed upon contract creation. - // Os construtores são usados para inicializar os dados do contrato. Learn more:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors + // Semelhante a muitas linguagens orientadas a objetos baseadas em classes, um construtor é uma função especial que só é executada na criação do contrato. + // Os construtores são usados para inicializar os dados do contrato. Saiba mais:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors constructor(string memory initMessage) { - // Accepts a string argument `initMessage` and sets the value into the contract's `message` storage variable). + // Aceita um argumento de string `initMessage` e define o valor na variável de armazenamento `message` do contrato. message = initMessage; } - // A public function that accepts a string argument and updates the `message` storage variable. + // Uma função pública que aceita um argumento de string e atualiza a variável de armazenamento `message`. function update(string memory newMessage) public { string memory oldMsg = message; message = newMessage; @@ -1065,11 +1069,11 @@ contract HelloWorld { } ``` -Eventos de contratos inteligentes são uma maneira do seu contrato comunicar que alguma coisa aconteceu \(ou seja, houve um _event_\) na blockchain no seu aplicativo de front-end, que pode “escutar” eventos específicos e tomar uma ação quando eles acontecem. +Eventos de contratos inteligentes são uma forma de o seu contrato comunicar que algo aconteceu (ou seja, houve um _evento_) na blockchain para seu aplicativo de front-end, que pode estar 'ouvindo' eventos específicos e tomar uma ação quando eles acontecem. -A função `addSmartContractListener` escutará especificamente o evento `UpdatedMessages` do nosso contrato inteligente Olá, Mundo e atualizar nossa interface do usuário para mostrar a nova mensagem. +A função `addSmartContractListener` irá ouvir especificamente o evento `UpdatedMessages` do nosso contrato inteligente Hello World e atualizará nossa interface do usuário para exibir a nova mensagem. -Modifique `addSmartContractListener` da seguinte maneira: +Modifique `addSmartContractListener` para o seguinte: ```javascript // HelloWorld.js @@ -1081,18 +1085,18 @@ function addSmartContractListener() { } else { setMessage(data.returnValues[1]) setNewMessage("") - setStatus("🎉 Your message has been updated!") + setStatus("🎉 Sua mensagem foi atualizada!") } }) } ``` -Vamos quebrar em partes o que acontece quando o listener detecta um evento: +Vamos detalhar o que acontece quando o ouvinte detecta um evento: -- Se um erro ocorre quando o evento é emitido, ele será refletido na UI via nossa variável de estado `status`. -- Caso contrário, nós usaremos o objeto `data` retornado. O `data.returnValues` é uma array indexada no zero onde o primeiro elemento da array armazena a mensagem anterior e o segundo elemento armazena o atualizado. Ao todo, em um evento bem-sucedido, iremos configurar nossa cadeia de caracteres `message` com a mensagem atualizada, limpar a cadeia de caracteres `newMessage` e atualizar nossa variável de estado `status` para refletir que uma nova mensagem foi publicada no nosso contrato inteligente. +- Se ocorrer um erro quando o evento for emitido, ele será refletido na interface do usuário por meio de nossa variável de estado `status`. +- Caso contrário, usaremos o objeto `data` retornado. O `data.returnValues` é um array indexado em zero onde o primeiro elemento no array armazena a mensagem anterior e o segundo elemento armazena a atualizada. No total, em um evento bem-sucedido, definiremos nossa string `message` para a mensagem atualizada, limparemos a string `newMessage` e atualizaremos nossa variável de estado `status` para refletir que uma nova mensagem foi publicada em nosso contrato inteligente. -Finalmente, vamos chamar nosso listener em nossa função `useEffect` para que seja inicializada na primeira renderização do componente `HelloWorld.js`. Tudo junto, sua função `useEffect` deve se parecer com: +Finalmente, vamos chamar nosso ouvinte em nossa função `useEffect` para que ele seja inicializado na primeira renderização do componente `HelloWorld.js`. No total, sua função `useEffect` deve ter a seguinte aparência: ```javascript // HelloWorld.js @@ -1104,43 +1108,43 @@ useEffect(async () => { }, []) ``` -Agora que nós somos capazes de ler do nosso contrato inteligente, seria ótimo descobrir como escrever nele também! Entretanto, para escrever no nosso dapp, nós precisamos primeiro uma carteira Ethereum conectada nele. +Agora que podemos ler do nosso contrato inteligente, seria ótimo descobrir como escrever nele também! No entanto, para escrever em nosso dapp, primeiro devemos ter uma carteira Ethereum conectada a ele. -Então, em seguida vamos configurar nossa carteira Ethereum \(MetaMask\) e então conectá-la ao nosso dapp! +Então, a seguir, abordaremos a configuração de nossa carteira Ethereum (MetaMask) e, em seguida, a conexão dela ao nosso dapp! -### Passo 4: Configurar sua carteira Ethereum {#step-4-set-up-your-ethereum-wallet} +### Passo 4: Configure sua carteira Ethereum {#step-4-set-up-your-ethereum-wallet} -Para escrever qualquer coisa na cadeia Ethereum, usuários devem assinar transações usando as chaves privadas das suas carteiras virtuais. Para este tutorial, usaremos o [MetaMask](https://metamask.io/), uma carteira virtual no navegador usada para gerenciar o seu endereço de conta do Ethereum, pois ele torna esta assinatura de transação superfácil para o usuário final. +Para escrever qualquer coisa na cadeia Ethereum, os usuários devem assinar transações usando as chaves privadas de suas carteiras virtuais. Para este tutorial, usaremos o [MetaMask](https://metamask.io/), uma carteira virtual no navegador usada para gerenciar o endereço da sua conta Ethereum, pois torna a assinatura de transações superfácil para o usuário final. -Se você quiser entender mais sobre como as transações no Ethereum funcionam, confira [esta página](/developers/docs/transactions/) na Fundação Ethereum. +Se quiser entender mais sobre como as transações na Ethereum funcionam, confira [esta página](/developers/docs/transactions/) da Ethereum Foundation. -#### Baixar MetaMask {#download-metamask} +#### Baixe o MetaMask {#download-metamask} -Você pode baixar e criar uma conta MetaMask gratuitamente [neste link](https://metamask.io/download). Ao criar uma conta, ou mesmo se você já tiver uma conta, certifique-se de mudar para "Goerli Test Network” na parte superior direita \(para não lidarmos com dinheiro real\). +Você pode baixar e criar uma conta MetaMask gratuitamente [aqui](https://metamask.io/download). Ao criar uma conta, ou se você já tiver uma, certifique-se de mudar para a “Rede de Teste Goerli” no canto superior direito (para não lidarmos com dinheiro real). -#### Etapa: Adicionar Faucet ether {#add-ether-from-a-faucet} +#### Adicione ether de uma Faucet {#add-ether-from-a-faucet} -Para assinar a transação no blockchain Ethereum, nós precisamos de alguns Eth falsos. Para obter Eth você pode ir em[FaucETH](https://fauceth.komputing.org) e entrar seu endereço de conta Goerli, clicar em “Request funds”, e então selecionar “Ethereum Testnet Goerli” no menu, e finalmente clicar no botão "Request funds" novamente. Em seguida, você deve ver Eth em sua conta Metamask! +Para assinar uma transação na blockchain Ethereum, precisaremos de um pouco de Eth falso. Para obter Eth, você pode ir para a [FaucETH](https://fauceth.komputing.org) e inserir o endereço da sua conta Goerli, clicar em “Solicitar fundos”, selecionar “Rede de Teste Ethereum Goerli” no menu suspenso e, finalmente, clicar no botão “Solicitar fundos” novamente. Em seguida, você deve ver Eth em sua conta MetaMask! -#### Cheque seu Saldo {#check-your-balance} +#### Verifique seu saldo {#check-your-balance} -Para verificar novamente que tem saldo, vamos fazer uma solicitação através da ferramenta [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) fornecida pelo [compositor da Alchemy](https://composer.alchemyapi.io?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D). Ela mostrará a quantidade de Eth na sua carteira. Depois de inserir o endereço da sua conta da MetaMask e clicar em "Send Request", você verá uma resposta como esta: +Para verificar novamente se nosso saldo está lá, vamos fazer uma solicitação [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) usando a [ferramenta de composição da Alchemy](https://composer.alchemyapi.io/?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D). Ela mostrará a quantidade de Eth na sua carteira. Depois de inserir o endereço da sua conta da MetaMask e clicar em "Send Request", você verá uma resposta como esta: ```text {"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"} ``` -**NOTA:** Este resultado está em wei, não em ETH. Lembre-se de que "Wei" é a menor unidade de ether. A conversão de wei para eth é: 1 eth = 10¹⁸ wei. Então, se convertemos 0xde0b6b3a7640000 para decimal, temos 1\*10¹⁸ wei, que é igual a 1 eth. +**OBSERVAÇÃO:** Este resultado está em wei, não em eth. Lembre-se de que "Wei" é a menor unidade de ether. A conversão de wei para eth é: 1 eth = 10¹⁸ wei. Então, se convertemos 0xde0b6b3a7640000 para decimal, temos 1\*10¹⁸ wei, que é igual a 1 eth. Ufa! Nosso dinheiro falso está todo lá! 🤑 -### Passo 5: Conecte o MetaMask na sua UI {#step-5-connect-metamask-to-your-UI} +### Passo 5: Conecte o MetaMask à sua interface do usuário {#step-5-connect-metamask-to-your-UI} Agora que nossa carteira MetaMask está configurada, vamos conectar nosso dapp a ela! -#### Função `connectWallet` {#the-connectWallet-function} +#### A função `connectWallet` {#the-connectWallet-function} -No nosso arquivo `interact.js`, vamos implementar a função `connectWallet`, a qual podemos então chamar no nosso componente `HelloWorld.js`. +Em nosso arquivo `interact.js`, vamos implementar a função `connectWallet`, que podemos chamar em nosso componente `HelloWorld.js`. Vamos modificar `connectWallet` para o seguinte: @@ -1154,7 +1158,7 @@ export const connectWallet = async () => { method: "eth_requestAccounts", }) const obj = { - status: "👆🏽 Write a message in the text-field above.", + status: "👆🏽 Escreva uma mensagem no campo de texto acima.", address: addressArray[0], } return obj @@ -1172,8 +1176,7 @@ export const connectWallet = async () => {

{" "} 🦊 - You must install MetaMask, a virtual Ethereum wallet, in your - browser. + Você deve instalar o MetaMask, uma carteira virtual Ethereum, no seu navegador.

@@ -1185,24 +1188,24 @@ export const connectWallet = async () => { Então, o que esse bloco gigante de código faz exatamente? -Bem, primeiro, ele checar se a `window.ethereum` está habilitada no seu navegador. +Bem, primeiro, ele verifica se o `window.ethereum` está habilitado no seu navegador. -`window.ethereum` é uma API global injetada pela MetaMask e outros provedores de carteira que permitem que sites solicitem contas Ethereum dos usuários. Se aprovado, ele pode ler dados dos blockchains que o usuário está conectado, e sugerir que o usuário assine mensagens e transações. Confira a [documentação da MetaMask](https://docs.metamask.io/guide/ethereum-provider.html#table-of-contents) para obter mais informações! +`window.ethereum` é uma API global injetada pelo MetaMask e outros provedores de carteira que permite que sites solicitem as contas Ethereum dos usuários. Se aprovado, ele pode ler dados das blockchains às quais o usuário está conectado e sugerir que o usuário assine mensagens e transações. Confira a [documentação do MetaMask](https://docs.metamask.io/guide/ethereum-provider.html#table-of-contents) para mais informações! -Se `window.ethereum` _não está_ presente, então isso significa que o MetaMask não está instalado. Isso resulta em um objeto JSON sendo retornado, onde o `endereço` retornado é uma string vazia, e o `status` do objeto JSX repassa que o usuário deve instalar o MetaMask. +Se o `window.ethereum` _não estiver_ presente, isso significa que o MetaMask não está instalado. Isso resulta no retorno de um objeto JSON, onde o `address` retornado é uma string vazia, e o objeto JSX `status` informa que o usuário deve instalar o MetaMask. -Agora se `window.ethereum` _estiver_ presente, e é aí que as coisas ficam interessantes. +Agora, se o `window.ethereum` _estiver_ presente, é aí que as coisas ficam interessantes. -Usando um laço try/catch, nós vamos tentar conectar ao MetaMask chamando[`window.ethereum.request({ method: "eth_requestAccounts" });`](https://docs.metamask.io/guide/rpc-api.html#eth-requestaccounts). Chamando esta função o MetaMask irá abrir no navegador, onde o usuário será solicitado a conectar sua carteira ao seu dapp. +Usando um loop try/catch, tentaremos nos conectar ao MetaMask chamando [`window.ethereum.request({ method: \"eth_requestAccounts\" });`](https://docs.metamask.io/guide/rpc-api.html#eth-requestaccounts). Chamando esta função o MetaMask irá abrir no navegador, onde o usuário será solicitado a conectar sua carteira ao seu dapp. -- Se o usuário escolher conectar, `method: "eth_requestAccounts"` irá retornar uma array que contém todos os endereços de contas de usuário que conectaram ao dapp. No total, nossa função `connectWallet` retornará um objeto JSON que contém o _primeiro_ `address` desta matriz \(ver linha 9\) e uma mensagem `status` que pede que o usuário escreva uma mensagem para o contrato inteligente. -- Se o usuário rejeitar a conexão, então o objeto JSON vai conter uma string vazia para o `address` retornado e uma mensagem de `status` que reflete que o usuário rejeitou a conexão. +- Se o usuário optar por conectar, `method: "eth_requestAccounts"` retornará um array que contém todos os endereços de conta do usuário conectados ao dapp. No total, nossa função `connectWallet` retornará um objeto JSON que contém o _primeiro_ `address` neste array (veja a linha 9) e uma mensagem de `status` que solicita ao usuário que escreva uma mensagem para o contrato inteligente. +- Se o usuário rejeitar a conexão, o objeto JSON conterá uma string vazia para o `address` retornado e uma mensagem de `status` que reflete que o usuário rejeitou a conexão. -Agora que nós escrevemos esta função `connectWallet`, o próximo passo é chamar ele para o nosso componente `HelloWorld.js`. +Agora que escrevemos esta função `connectWallet`, o próximo passo é chamá-la em nosso componente `HelloWorld.js`. #### Adicione a função `connectWallet` ao seu componente de interface do usuário `HelloWorld.js` {#add-the-connectWallet-function-to-your-HelloWorld-js-ui-component} -Navegue para a função `connectWalletPressed` em `HelloWorld.js`, e atualize-o para o seguinte: +Navegue para a função `connectWalletPressed` em `HelloWorld.js` e atualize-a para o seguinte: ```javascript // HelloWorld.js @@ -1214,25 +1217,25 @@ const connectWalletPressed = async () => { } ``` -Observe como a maior parte das nossas funcionalidades está abstraída do nosso componente `HelloWorld.js` do arquivo `interact.js`? É assim que respeitamos o paradigma M-V-C! +Observe como a maior parte de nossa funcionalidade está abstraída de nosso componente `HelloWorld.js` do arquivo `interact.js`? É assim que respeitamos o paradigma M-V-C! -Em `connectWalletPressed`, simplesmente fazemos uma chamada de espera (await) para a função `connectWallet`, importada, e usando sua resposta, nós atualizaremos nossas variáveis `status` e `walletAddress` através de seus state hooks. +Em `connectWalletPressed`, nós simplesmente fazemos uma chamada `await` para a nossa função `connectWallet` importada e, usando sua resposta, atualizamos nossas variáveis `status` e `walletAddress` através de seus hooks de estado. -Agora, vamos salvar os dois arquivos `HelloWorld.js` e `interact.js` e testar nossa UI até agora. +Agora, vamos salvar ambos os arquivos (`HelloWorld.js` e `interact.js`) e testar nossa interface do usuário até agora. -Abra seu navegador na página [http://localhost:3000/](http://localhost:3000/) e clique no botão “Connect Wallet” na parte superior direita da página. +Abra seu navegador na página [http://localhost:3000/](http://localhost:3000/) e pressione o botão "Conectar Carteira" no canto superior direito da página. Se você tiver o MetaMask instalado, você será solicitado a conectar sua carteira ao seu dapp. Aceite o convite para se conectar. -Observe que o botão de carteira agora mostra que o seu endereço está conectado! Ótimo!!🔥 +Você deve ver que o botão da carteira agora reflete que seu endereço está conectado! Demais! 🔥 -Em seguida, tente atualizar a página... isso é estranho. Nosso botão de carteira está nos pedindo para conectar o MetaMask, mesmo que já esteja conectado... +Em seguida, tente atualizar a página... que estranho. Nosso botão de carteira está nos pedindo para conectar o MetaMask, mesmo que já esteja conectado... -Entretanto, não tenha medo! Nós podemos endereçar (entendeu?) facilmente isso implementando `getCurrentWalletConnected`, o qual irá checar se um endereço já está conectado no nosso dapp e atualizar nossa UI de acordo! +No entanto, não tema! Podemos facilmente resolver isso (entendeu?) implementando `getCurrentWalletConnected`, que verificará se um endereço já está conectado ao nosso dapp e atualizará nossa interface do usuário de acordo! #### A função `getCurrentWalletConnected` {#the-getcurrentwalletconnected-function} -Atualize a sua função `getCurrentWalletConnected` no arquivo `interact.js` como mostrado abaixo: +Atualize sua função `getCurrentWalletConnected` no arquivo `interact.js` para o seguinte: ```javascript // interact.js @@ -1246,12 +1249,12 @@ export const getCurrentWalletConnected = async () => { if (addressArray.length > 0) { return { address: addressArray[0], - status: "👆🏽 Write a message in the text-field above.", + status: "👆🏽 Escreva uma mensagem no campo de texto acima.", } } else { return { address: "", - status: "🦊 Connect to MetaMask using the top right button.", + status: "🦊 Conecte-se ao MetaMask usando o botão superior direito.", } } } catch (err) { @@ -1268,8 +1271,7 @@ export const getCurrentWalletConnected = async () => {

{" "} 🦊 - You must install MetaMask, a virtual Ethereum wallet, in your - browser. + Você deve instalar o MetaMask, uma carteira virtual Ethereum, no seu navegador.

@@ -1279,11 +1281,11 @@ export const getCurrentWalletConnected = async () => { } ``` -Este código é _muito_ similar à função `connectWallet` que nós acabamos de escrever no passo anterior. +Este código é _muito_ semelhante à função `connectWallet` que acabamos de escrever na etapa anterior. -A diferença principal é que, em vez de chamar o método `eth_requestAccounts`, que abre o MetaMask para o usuário conectar sua carteira, aqui chamamos o método `eth_accounts`, que simplesmente retorna uma matriz que contém os endereços MetaMask atualmente conectados ao nosso dapp. +A principal diferença é que, em vez de chamar o método `eth_requestAccounts`, que abre o MetaMask para o usuário conectar sua carteira, aqui chamamos o método `eth_accounts`, que simplesmente retorna uma matriz contendo os endereços do MetaMask atualmente conectados ao nosso dapp. -Para ver esta função em ação, vamos chamar nossa função `useEffect` do nosso componente `HelloWorld.js`: +Para ver esta função em ação, vamos chamá-la em nossa função `useEffect` do nosso componente `HelloWorld.js`: ```javascript // HelloWorld.js @@ -1299,17 +1301,17 @@ useEffect(async () => { }, []) ``` -Note que nós usamos a resposta da nossa chamada a `getCurrentWalletConnected` para atualizar nossa `walletAddress` e nossa variável de estado `status`. +Observe que usamos a resposta da nossa chamada para `getCurrentWalletConnected` para atualizar nossas variáveis de estado `walletAddress` e `status`. -Agora que você adicionou este código, tente atualizar a janela do navegador. +Agora que você adicionou este código, vamos tentar atualizar a janela do nosso navegador. -Ótimo!!!! O botão deve dizer que você está conectado e mostrar uma visualização do endereço de sua carteira conectada - mesmo depois de atualizar! +Ótimoooo! O botão deve dizer que você está conectado e mostrar uma visualização do endereço de sua carteira conectada - mesmo depois de atualizar! #### Implemente `addWalletListener` {#implement-addwalletlistener} O passo final na configuração da nossa carteira dapp é implementar o ouvinte de carteira, para que nossa interface atualize quando o estado mudar, como quando o usuário desconecta ou troca de contas. -No seu arquivo `HelloWorld.js`, modifique a sua função `addWalletListener` para o seguinte: +No seu arquivo `HelloWorld.js`, modifique sua função `addWalletListener` para o seguinte: ```javascript // HelloWorld.js @@ -1319,10 +1321,10 @@ function addWalletListener() { window.ethereum.on("accountsChanged", (accounts) => { if (accounts.length > 0) { setWallet(accounts[0]) - setStatus("👆🏽 Write a message in the text-field above.") + setStatus("👆🏽 Escreva uma mensagem no campo de texto acima.") } else { setWallet("") - setStatus("🦊 Connect to MetaMask using the top right button.") + setStatus("🦊 Conecte-se ao MetaMask usando o botão superior direito.") } }) } else { @@ -1330,7 +1332,7 @@ function addWalletListener() {

{" "} 🦊 - You must install MetaMask, a virtual Ethereum wallet, in your browser. + Você deve instalar o MetaMask, uma carteira virtual Ethereum, no seu navegador.

) @@ -1338,13 +1340,13 @@ function addWalletListener() { } ``` -Eu aposto que você nem mesmo precisou da nossa ajuda para entender o que está acontecendo aqui neste ponto, mas por finalidade de clareza, vamos quebrá-lo em partes: +Aposto que você nem precisa da nossa ajuda para entender o que está acontecendo aqui neste ponto, mas, para fins de completude, vamos detalhar rapidamente: -- Primeiro, nossa função verifica se o `window.ethereum` está habilitado no seu navegador \(ex. MetaMask instalado\). - - Caso contrário, nós simplesmente configuramos a variável de estado `status` para uma JSX string que solicita o usuário instalar a MetaMask. - - Se estiver habilitado, configuramos o ouvinte `window.ethereum.on("accountsChanged")` na linha 3 que houve mudança de estado na carteira MetaMask, inclusive quando o usuário conecta uma conta adicional ao dapp, troca de conta ou desconecta uma conta. Se houver pelo menos uma conta conectada, a variável de estado `walletAddress` é atualizada como a primeira conta no array `accounts` retornada pelo ouvinte. Caso contrário, `walletAddress` é definida como uma string vazia. +- Primeiro, nossa função verifica se o `window.ethereum` está ativado (ou seja, se o MetaMask está instalado). + - Se não estiver, simplesmente definimos nossa variável de estado `status` como uma string JSX que solicita ao usuário que instale o MetaMask. + - Se estiver habilitado, configuramos o listener `window.ethereum.on("accountsChanged")` na linha 3 que escuta por mudanças de estado na carteira MetaMask, que incluem quando o usuário conecta uma conta adicional ao dapp, troca de contas ou desconecta uma conta. Se houver pelo menos uma conta conectada, a variável de estado `walletAddress` é atualizada como a primeira conta no array `accounts` retornado pelo listener. Caso contrário, o `walletAddress` é definido como uma string vazia. -Por último, mas não menos importante, nós devemos chamá-la em nossa função `useEffect`: +Por último, mas não menos importante, devemos chamá-la em nossa função `useEffect`: ```javascript // HelloWorld.js @@ -1362,23 +1364,23 @@ useEffect(async () => { }, []) ``` -E é isso! Concluímos com sucesso a programação de toda a nossa carteira! Agora, a nossa última tarefa: atualizar a mensagem armazenada no nosso contrato inteligente! +E é isso! Concluímos com sucesso a programação de toda a funcionalidade da nossa carteira! Agora para nossa última tarefa: atualizar a mensagem armazenada em nosso contrato inteligente! ### Passo 6: Implemente a função `updateMessage` {#step-6-implement-the-updateMessage-function} -Tudo bem, nós chegamos ao trecho caseiro! No `updateMessage` do seu arquivo `interact.js`, façamos o seguinte: +Tudo bem, pessoal, chegamos à reta final! Na `updateMessage` do seu arquivo `interact.js`, faremos o seguinte: -1. Certifique-se que a mensagem que nós queremos publicar no nosso contrato inteligente é válida -2. Assine nossa transação usando MetaMask -3. Chame esta função do nosso componente de frontend `HelloWorld.js` +1. Certificar-se de que a mensagem que desejamos publicar em nosso contrato inteligente é válida +2. Assinar nossa transação usando o MetaMask +3. Chamar esta função do nosso componente de frontend `HelloWorld.js` -Isso não vai demorar muito; vamos terminar este dapp! +Isso não levará muito tempo; vamos terminar este dapp! -#### Manipulação de erros de script {#input-error-handling} +#### Tratamento de erros de entrada {#input-error-handling} -Naturalmente, faz sentido ter alguns tipos de gerencialmente de erros de entrada no início da função. +Naturalmente, faz sentido ter algum tipo de tratamento de erro de entrada no início da função. -Queremos que nossa função retorne rapidamente. Se não houver uma extensão MetaMask instalada, não haverá carteiras conectadas \(ou seja, o `address` transmitido é uma cadeira de caracteres vazia\) ou a `message` será uma cadeira de caracteres vazia. Vamos adicionar o seguinte gerencialmente de erro em `updateMessage`: +Queremos que nossa função retorne mais cedo se não houver extensão MetaMask instalada, se não houver carteira conectada (ou seja, o `address` passado é uma string vazia) ou se a `message` for uma string vazia. Vamos adicionar o seguinte tratamento de erro a `updateMessage`: ```javascript // interact.js @@ -1387,35 +1389,35 @@ export const updateMessage = async (address, message) => { if (!window.ethereum || address === null) { return { status: - "💡 Connect your MetaMask wallet to update the message on the blockchain.", + "💡 Conecte sua carteira MetaMask para atualizar a mensagem na blockchain.", } } if (message.trim() === "") { return { - status: "❌ Your message cannot be an empty string.", + status: "❌ Sua mensagem não pode ser uma string vazia.", } } } ``` -Agora que ele tem o devido gerenciamento de erro de entrada, é hora de assinar a transação via MetaMask! +Agora que temos o tratamento de erro de entrada adequado, é hora de assinar a transação via MetaMask! -#### Assinando a nossa transação {#signing-our-transaction} +#### Assinando nossa transação {#signing-our-transaction} -Se você já está confortável com as transações tradicionais Web3 do Ethereum, o código que vamos escrever em seguida será bastante familiar. Abaixo, nosso código de manipulação de erro de entrada, adicione o seguinte a `updateMessage`: +Se você já está confortável com transações Ethereum da web3 tradicional, o código que escreveremos a seguir será muito familiar. Abaixo do seu código de tratamento de erro de entrada, adicione o seguinte a `updateMessage`: ```javascript // interact.js -//set up transaction parameters +//configurar parâmetros da transação const transactionParameters = { - to: contractAddress, // Required except during contract publications. - from: address, // must match user's active address. + to: contractAddress, // Obrigatório, exceto durante publicações de contrato. + from: address, // deve corresponder ao endereço ativo do usuário. data: helloWorldContract.methods.update(message).encodeABI(), } -//sign the transaction +//assinar a transação try { const txHash = await window.ethereum.request({ method: "eth_sendTransaction", @@ -1426,11 +1428,10 @@ try { ✅{" "} - View the status of your transaction on Etherscan! + Veja o status da sua transação no Etherscan!
- ℹ️ Once the transaction is verified by the network, the message will be - updated automatically. + ℹ️ Assim que a transação for verificada pela rede, a mensagem será atualizada automaticamente.
), } @@ -1441,47 +1442,47 @@ try { } ``` -Vamos quebrar em partes o que está acontecendo. Primeiro, configuramos nossos parâmetros de transações, em que: +Vamos detalhar o que está acontecendo. Primeiro, configuramos nossos parâmetros de transações, onde: -- `to` especificar o endereço do destinatário \(nosso contrato inteligente\) -- `from` especifica o signatário da transação, a variável `address` que transmitimos para a nossa função -- `data` contém a chamada para o método `update` do nosso contrato inteligente Olá, Mundo, recebendo nossa variável de cadeia de caracteres `message` como entrada +- `to` especifica o endereço do destinatário (nosso contrato inteligente) +- `from` especifica o signatário da transação, a variável `address` que passamos para nossa função +- `data` contém a chamada para o método `update` do nosso contrato inteligente Hello World, recebendo nossa variável de string `message` como entrada -Então, nós fazemos uma chamada await, `window.ethereum.request`, onde nós pedimos ao MetaMask para assinar a transação. Observe que nas linhas 11 e 12, estamos especificando nosso método eth `eth_sendTransaction` e passando os nossos `transactionParameters`. +Então, fazemos uma chamada de espera, `window.ethereum.request`, onde pedimos ao MetaMask para assinar a transação. Observe que, nas linhas 11 e 12, estamos especificando nosso método eth, `eth_sendTransaction`, e passando nossos `transactionParameters`. Neste ponto, a MetaMask irá abrir no navegador e pedirá que o usuário assine ou rejeite a transação. -- Se a transação tiver sucesso, a função retornará um objeto JSON no qual a cadeia de caracteres JSX `status` pede ao usuário para verificar o Etherscan para mais informações sobre suas transações. -- Se a transação falha, a função irá retornar um objeto JSON onde a string `status` retransmite a mensagem de erro. +- Se a transação for bem-sucedida, a função retornará um objeto JSON onde a string JSX `status` solicita ao usuário que verifique o Etherscan para mais informações sobre sua transação. +- Se a transação falhar, a função retornará um objeto JSON onde a string `status` transmite a mensagem de erro. -Tudo junto, nossa função `updateMessage` deve se parecer com isso: +No total, nossa função `updateMessage` deve ter a seguinte aparência: ```javascript // interact.js export const updateMessage = async (address, message) => { - //input error handling + //tratamento de erro de entrada if (!window.ethereum || address === null) { return { status: - "💡 Connect your MetaMask wallet to update the message on the blockchain.", + "💡 Conecte sua carteira MetaMask para atualizar a mensagem na blockchain.", } } if (message.trim() === "") { return { - status: "❌ Your message cannot be an empty string.", + status: "❌ Sua mensagem não pode ser uma string vazia.", } } - //set up transaction parameters + //configurar parâmetros da transação const transactionParameters = { - to: contractAddress, // Required except during contract publications. - from: address, // must match user's active address. + to: contractAddress, // Obrigatório, exceto durante publicações de contrato. + from: address, // deve corresponder ao endereço ativo do usuário. data: helloWorldContract.methods.update(message).encodeABI(), } - //sign the transaction + //assinar a transação try { const txHash = await window.ethereum.request({ method: "eth_sendTransaction", @@ -1492,11 +1493,10 @@ export const updateMessage = async (address, message) => { ✅{" "} - View the status of your transaction on Etherscan! + Veja o status da sua transação no Etherscan!
- ℹ️ Once the transaction is verified by the network, the message will - be updated automatically. + ℹ️ Assim que a transação for verificada pela rede, a mensagem será atualizada automaticamente.
), } @@ -1508,11 +1508,11 @@ export const updateMessage = async (address, message) => { } ``` -Por último, mas não menos importante, nós precisamos conectar nossa função `updateMessage` ao componente `HelloWorld.js`. +Por último, mas não menos importante, precisamos conectar nossa função `updateMessage` ao nosso componente `HelloWorld.js`. -#### Conecte `updateMessage` ao front-end `HelloWorld.js` {#connect-updatemessage-to-the-helloworld-js-frontend} +#### Conecte `updateMessage` ao frontend `HelloWorld.js` {#connect-updatemessage-to-the-helloworld-js-frontend} -Nossa função `onUpdatePressed` deve fazer uma chamada await para a função `updateMessage` importada e modificar a variável de estado `status` para refletir se a nossa transação teve sucesso ou falhou: +Nossa função `onUpdatePressed` deve fazer uma chamada de espera para a função `updateMessage` importada e modificar a variável de estado `status` para refletir se nossa transação foi bem-sucedida ou falhou: ```javascript // HelloWorld.js @@ -1523,18 +1523,18 @@ const onUpdatePressed = async () => { } ``` -É super limpo e simples. E advinhe... SEU DAPP ESTÁ COMPLETO!!! +É super limpo e simples. E adivinhe só... SEU DAPP ESTÁ COMPLETO!!! -Vá em frente e teste com o botão **Update**! +Vá em frente e teste o botão **Atualizar**! -### Faça o seu próprio dapp customizado {#make-your-own-custom-dapp} +### Crie seu próprio dapp personalizado {#make-your-own-custom-dapp} -Ebaaaaa, você chegou até o fim deste tutorial! Para recapitular, você aprendeu como: +Uhuuu, você chegou ao final do tutorial! Para recapitular, você aprendeu como: -- Conectar a carteira MetaMask no seu projeto dapp +- Conectar uma carteira MetaMask ao seu projeto de dapp - Ler dados do seu contrato inteligente usando a API [Alchemy Web3](https://docs.alchemy.com/alchemy/documentation/alchemy-web3) -- Assinar transações Ethereum usando MetaMask +- Assinar transações Ethereum usando o MetaMask -Agora você está totalmente equipado para aplicar suas habilidades deste tutorial para construir seu próprio projeto dapp customizado! Como sempre, se você tiver questões, não hesite em nos contatar para pedir ajuda no[Discord da Alchemy](https://discord.gg/gWuC7zB). 🧙‍♂️ +Agora você está totalmente equipado para aplicar as habilidades deste tutorial para construir seu próprio projeto de dapp personalizado! Como sempre, se tiver alguma dúvida, não hesite em nos contatar para obter ajuda no [Discord da Alchemy](https://discord.gg/gWuC7zB). 🧙‍♂️ -Uma vez que você terminou este tutorial, nos diga como foi sua experiência ou se você tem alguma opinião, nos marcando no Twitter [@alchemyplatform](https://twitter.com/AlchemyPlatform)! +Depois de concluir este tutorial, conte-nos como foi sua experiência ou se você tem algum feedback, marcando-nos no Twitter [@alchemyplatform](https://twitter.com/AlchemyPlatform)! diff --git a/public/content/translations/pt-br/developers/tutorials/hello-world-smart-contract/index.md b/public/content/translations/pt-br/developers/tutorials/hello-world-smart-contract/index.md index 540ba1314d8..2621a803c53 100644 --- a/public/content/translations/pt-br/developers/tutorials/hello-world-smart-contract/index.md +++ b/public/content/translations/pt-br/developers/tutorials/hello-world-smart-contract/index.md @@ -1,90 +1,86 @@ --- title: Contrato inteligente "Hello World" para iniciantes -description: Tutorial introdutório sobre como escrever e implementar um contrato inteligente simples no Ethereum. +description: "Tutorial introdutório sobre como escrever e implantar um contrato inteligente simples no Ethereum." author: "elanh" tags: - - "solidity" - - "hardhat" - - "alchemy" - - "contratos inteligentes" - - "implementação" + [ + "Solidity", + "Hardhat", + "Alchemy", + "smart contracts", + "implantação" + ] skill: beginner lang: pt-br published: 2021-03-31 --- -Se você é novo no desenvolvimento de blockchain e não sabe por onde começar, ou se apenas deseja entender como implementar ou interagir com contratos inteligentes, este guia é para você. Vamos criar e implantar um contrato inteligente simples na rede de teste Goerli usando uma carteira virtual [MetaMask](https://metamask.io/), [Solidity](https://docs.soliditylang.org/en/v0.8.0/), [Hardhat](https://hardhat.org/) e [Alchemy](https://alchemyapi.io/eth) (não se preocupe se você ainda não entendeu o que isso significa, nós explicaremos). +Se você é novo no desenvolvimento de blockchain e não sabe por onde começar, ou se apenas deseja entender como implantar ou interagir com contratos inteligentes, este guia é para você. Vamos criar e implantar um contrato inteligente simples na rede de teste Sepolia usando uma carteira virtual [MetaMask](https://metamask.io/), [Solidity](https://docs.soliditylang.org/en/v0.8.0/), [Hardhat](https://hardhat.org/) e [Alchemy](https://www.alchemy.com/eth) (não se preocupe se você ainda não entendeu o que isso significa, nós explicaremos). -> **Atenção** -> -> Aviso de descontinuidade -> -> Para este guia inteiro, a rede de teste Goerli está sendo usada para criação e implantação de contratos inteligentes. Entretanto, por favor note que a Ethereum Foundation anunciou que a [Goerli será descontinuada em breve](https://www.alchemy.com/blog/goerli-faucet-deprecation). -> -> Nós recomendamos você usar a [Sepolia](https://www.alchemy.com/overviews/sepolia-testnet) e [faucets Sepolia](https://sepoliafaucet.com/) para este tutorial. +Na [parte 2](https://docs.alchemy.com/docs/interacting-with-a-smart-contract) deste tutorial, vamos ver como podemos interagir com nosso contrato inteligente depois de implantado aqui, e na [parte 3](https://www.alchemy.com/docs/submitting-your-smart-contract-to-etherscan) vamos cobrir como publicá-lo no Etherscan. -Na [parte 2](https://docs.alchemy.com/docs/interacting-with-a-smart-contract) deste tutorial, veremos como podemos interagir com nosso contrato inteligente, assim que for implantado aqui, e na [parte 3](https://docs.alchemy.com/docs/submitting-your-smart-contract-to-etherscan), abordaremos como publicá-lo no Etherscan. +Se você tiver alguma dúvida, sinta-se à vontade para entrar em contato no [Discord da Alchemy](https://discord.gg/gWuC7zB)! -Caso surjam perguntas em qualquer momento, sinta-se à vontade para falar no Discord da [Alchemy](https://discord.gg/gWuC7zB)! +## Etapa 1: Conectar-se à rede Ethereum {#step-1} -## Passo 1: Conecte-se à rede de Ethereum {#step-1} +Existem muitas maneiras de fazer solicitações para a cadeia Ethereum. Para simplificar, usaremos uma conta gratuita no Alchemy, uma plataforma de desenvolvimento de blockchain e API que nos permite comunicar com a cadeia Ethereum sem ter que executar nossos próprios nós. A plataforma também possui ferramentas de desenvolvedor para monitoramento e análise das quais tiraremos proveito neste tutorial para entender o que está acontecendo nos bastidores na implantação do nosso contrato inteligente. Se você ainda não tem uma conta da Alchemy, [pode se inscrever gratuitamente aqui](https://dashboard.alchemy.com/signup). -Existem muitas maneiras de fazer solicitações à cadeia de Ethereum. Por simplicidade, usaremos uma conta gratuita na Alchemy, uma API e plataforma de desenvolvedores de blockchain, a qual permite nos comunicar com a cadeia de Ethereum sem ter que executar nossos próprios nós. A plataforma também possui ferramentas de desenvolvedor para monitorar e analisar; ferramentas das quais vamos tirar proveito neste tutorial, para entender o que está acontecendo nos bastidores da implantação de nosso contrato inteligente. Se ainda não tiver uma conta na Alchemy, você pode se cadastrar gratuitamente [neste link](https://dashboard.alchemyapi.io/signup). +## Etapa 2: Criar seu aplicativo (e chave de API) {#step-2} -## Passo 2: Crie seu aplicativo (e chave de API) {#step-2} +Assim que criar uma conta na Alchemy, você pode gerar uma chave de API criando um "app". Isso nos permitirá fazer solicitações à rede de teste Sepolia. Se você não está familiarizado com redes de teste, confira [esta página](/developers/docs/networks/). -Assim que você criar uma conta na Alchemy, você pode gerar uma chave de API criando um app. Isso nos permitirá fazer solicitações na rede de teste Goerli. Se não estiver familiarizado com as redes de teste, confira [esta página](/developers/docs/networks/). +1. Navegue até a página "Create new app" em seu Painel de Controle da Alchemy, selecionando "Select an app" na barra de navegação e clicando em "Create new app" -1. Navegue até a pagina "Create App" na sua "Dashboard da Alchemy", indo na aba de "Apps" na barra de navegação e clicando em “Create App” +![Hello world criar aplicativo](./hello-world-create-app.png) -![Criar um aplicativo Hello World](./hello-world-create-app.png) +2. Dê um nome ao seu aplicativo, como “Hello World”, ofereça uma breve descrição e escolha um caso de uso, por exemplo, "Infra & Tooling." Em seguida, pesquise por "Ethereum" e selecione a rede. -2. Nomeie seu aplicativo “Hello World”, ofereça uma breve descrição, selecione “Staging” para o ambiente (usado para seu aplicativo de contabilidade) e escolha “Goerli” para sua rede. +![visualização de criação de aplicativo hello world](./create-app-view-hello-world.png) -![criar uma visualização do app hello world](./create-app-view-hello-world.png) +3. Clique em "Next" para prosseguir, depois em “Create app” e pronto! Seu aplicativo deve aparecer no menu suspenso da barra de navegação, com uma chave de API disponível para cópia. -3. Clique em "Criar app" e pronto! Seu app deve aparecer na tabela abaixo. +## Etapa 3: Criar uma conta Ethereum (endereço) {#step-3} -## Passo 3: Crie uma conta (endereço) de Ethereum {#step-3} +Precisamos de uma conta Ethereum para enviar e receber transações. Para este tutorial, usaremos uma carteira virtual no navegador, a MetaMask, para gerenciar o endereço da sua conta Ethereum. Mais sobre [transações](/developers/docs/transactions/). -Precisamos de uma conta de Ethereum para enviar e receber transações. Para este tutorial, usaremos uma carteira virtual no navegador, a MetaMask, para gerenciar o endereço da sua conta Ethereum. Mais sobre [transações](/developers/docs/transactions/). +Você pode baixar o MetaMask e criar uma conta Ethereum gratuitamente [aqui](https://metamask.io/download). Ao criar uma conta, ou se você já tiver uma, certifique-se de mudar para a rede de teste "Sepolia" usando o menu suspenso de rede (para que não estejamos lidando com dinheiro de verdade). -Você pode baixar e criar uma conta MetaMask gratuitamente [neste link](https://metamask.io/download). Quando você estiver criando uma conta, ou se já tiver uma conta, certifique-se de mudar para a “Rede de teste Goerli”, no canto superior direito (para que não estejamos lidando com dinheiro real). +Se você não vir a Sepolia listada, vá ao menu, depois em Advanced e role para baixo para ativar a opção "Show test networks". No menu de seleção de rede, escolha a aba "Custom" para encontrar uma lista de redes de teste e selecione "Sepolia." -![exemplo metamask ropsten](./metamask-ropsten-example.png) +![exemplo metamask sepolia](./metamask-sepolia-example.png) -## Passo 4: Adicione ether de um faucet {#step-4} +## Etapa 4: Adicionar ether de um faucet {#step-4} -Para implantar nosso contrato inteligente na rede de teste, precisaremos de algum Eth falso. Para obter Eth, você pode acessar a [torneira Goerli](https://goerlifaucet.com/), fazer login na sua conta Alchemy, inserir o endereço da carteira e clicar em "Send Me Eth." Pode levar algum tempo para receber seu Eth falso devido ao tráfego de rede. (Enquanto escrevia isto, levou cerca de 30 minutos) Você deve ver Eth em sua conta Metamask logo depois! +Para implantar nosso contrato inteligente na rede de teste, precisaremos de um pouco de ETH falso. Para obter Sepolia ETH, você pode ir para os [detalhes da rede Sepolia](/developers/docs/networks/#sepolia) para ver uma lista de vários faucets. Se um não funcionar, tente outro, pois eles podem, às vezes, ficar sem fundos. Pode levar algum tempo para receber seu ETH falso devido ao tráfego da rede. Você deverá ver o ETH em sua conta MetaMask logo em seguida! -## Passo 5: Verifique seu saldo {#step-5} +## Etapa 5: Verificar seu saldo {#step-5} -Para verificar novamente que temos saldo, vamos fazer uma solicitação através da ferramenta [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) fornecida pelo [compositor da Alchemy](https://composer.alchemyapi.io?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D). Ele mostrará a quantidade de ETH em nossa carteira. Depois de inserir o endereço da sua conta da MetaMask e clicar em "Send Request", você verá uma resposta como esta: +Para verificar se nosso saldo está lá, vamos fazer uma solicitação [eth_getBalance](/developers/docs/apis/json-rpc/#eth_getbalance) usando a [ferramenta composer da Alchemy](https://sandbox.alchemy.com/?network=ETH_SEPOLIA&method=eth_getBalance&body.id=1&body.jsonrpc=2.0&body.method=eth_getBalance&body.params%5B0%5D=&body.params%5B1%5D=latest). Ele mostrará a quantidade de ETH em nossa carteira. Depois de inserir o endereço da sua conta da MetaMask e clicar em "Send Request", você verá uma resposta como esta: ```json { "jsonrpc": "2.0", "id": 0, "result": "0x2B5E3AF16B1880000" } ``` -> **OBSERVAÇÃO:** este resultado é em wei não em ETH. Lembre-se de que "Wei" é a menor unidade de ether. A conversão de wei para ETH é 1 ETH = 1018 wei. Desta maneira, se convertermos 0x2B5E3AF16B1880000 em decimal obteremos 5\*10¹⁸, o que equivale a 5 ETH. +> **OBSERVAÇÃO:** Este resultado está em wei, não em ETH. Lembre-se de que "Wei" é a menor unidade de ether. A conversão de wei para ETH é: 1 eth = 1018 wei. Então, se convertermos 0x2B5E3AF16B1880000 para decimal, teremos 5\*10¹⁸, o que equivale a 5 ETH. > -> Ufa! Nosso dinheiro de imitação está todo aí . +> Ufa! Nosso dinheiro falso está todo lá . -## Passo 6: Inicialize nosso projeto {#step-6} +## Etapa 6: Inicializar nosso projeto {#step-6} -Primeiramente, precisaremos criar uma pasta para o nosso projeto. Navegue até sua linha de comando e digite: +Primeiro, precisamos criar uma pasta para o nosso projeto. Navegue até sua linha de comando e digite: ``` mkdir hello-world cd hello-world ``` -Agora que estamos dentro da pasta do nosso projeto, vamos usar o comando `npm init `para inicializar o projeto. Se você ainda não tiver o npm instalado, siga [estas instruções](https://docs.alchemyapi.io/alchemy/guides/alchemy-for-macs#1-install-nodejs-and-npm). Também vamos precisar do node.js, então baixe-o também! +Agora que estamos dentro da pasta do nosso projeto, usaremos o `npm init` para inicializar o projeto. Se você ainda não tiver o npm instalado, siga [estas instruções](https://docs.alchemyapi.io/alchemy/guides/alchemy-for-macs#1-install-nodejs-and-npm) (também precisaremos do Node.js, então baixe-o também!). ``` npm init ``` -Não importa muito como você responde às questões sobre a instalação. A modo de referência, aqui está o que nós fizemos: +Não importa muito como você responde às perguntas da instalação, aqui está como fizemos para referência: ``` package name: (hello-world) @@ -104,30 +100,30 @@ About to write to /Users/.../.../.../hello-world/package.json: "description": "hello world smart contract", "main": "index.js", "scripts": { - "test": "echo \\"Error: no test specified\\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" } ``` -Aprove o package.json e estaremos prontos para começar! +Aprove o package.json e estamos prontos! -## Etapa 7: Faça o download do [Hardhat](https://hardhat.org/getting-started/#overview) {#step-7} +## Etapa 7: Baixar o [Hardhat](https://hardhat.org/getting-started/#overview) {#step-7} Hardhat é um ambiente de desenvolvimento para compilar, implementar, testar e depurar seu software de Ethereum. Ele ajuda os desenvolvedores na criação de contratos inteligentes e dapps localmente antes de implantar na cadeia real. -Dentro de nosso projeto `hello-world` execute: +Dentro do nosso projeto `hello-world`, execute: ``` npm install --save-dev hardhat ``` -Para mais detalhes, confira esta página sobre as [instruções de instalação](https://hardhat.org/getting-started/#overview). +Confira esta página para mais detalhes sobre as [instruções de instalação](https://hardhat.org/getting-started/#overview). -## Passo 8: Crie um projeto Hardhat {#step-8} +## Etapa 8: Criar projeto Hardhat {#step-8} -Dentro da nossa pasta do projeto, execute: +Dentro da nossa pasta de projeto, execute: ``` npx hardhat @@ -147,70 +143,70 @@ Você deve então ver uma mensagem de boas-vindas e a opção de selecionar o qu 👷 Welcome to Hardhat v2.0.11 👷‍? -O que você deseja fazer? … +What do you want to do? … Create a sample project ❯ Create an empty hardhat.config.js Quit ``` -Isso vai gerar um arquivo `hardhat.config.js` onde especificaremos todas as configurações para o nosso projeto (no passo 13). +Isso gerará um arquivo `hardhat.config.js` para nós, que é onde especificaremos toda a configuração do nosso projeto (na etapa 13). -## Passo 9: Adicione pastas do projeto {#step-9} +## Etapa 9: Adicionar pastas do projeto {#step-9} -Para manter nosso projeto organizado vamos criar duas pastas novas. Navegue até o diretório raiz do seu projeto na sua linha de comando e digite: +Para manter nosso projeto organizado, criaremos duas novas pastas. Navegue até o diretório raiz do seu projeto na sua linha de comando e digite: ``` mkdir contracts mkdir scripts ``` -- `contracts/` é onde nós vamos manter o arquivo de código do contrato inteligente "hello world" -- `scripts/` é onde nós vamos manter scripts para implantar e interagir com nosso contrato +- `contracts/` é onde manteremos nosso arquivo de código do contrato inteligente hello world +- `scripts/` é onde manteremos os scripts para implantar e interagir com nosso contrato -## Passo 10: Escreva nosso contrato {#step-10} +## Etapa 10: Escrever nosso contrato {#step-10} -Você pode estar se perguntando, quando é que nós vamos escrever códigos? Bem, aqui estamos, no passo 10. +Você pode estar se perguntando, quando diabos vamos escrever código?? Bem, aqui estamos, na etapa 10. -Abra o projeto hello-world em seu editor favorito (nós preferimos o [VSCode](https://code.visualstudio.com/)). Os contratos inteligentes são escritos em uma linguagem chamada Solidity, que usaremos para escrever nosso contrato inteligente HelloWorld.sol +Abra o projeto hello-world em seu editor favorito (nós gostamos do [VSCode](https://code.visualstudio.com/)). Os contratos inteligentes são escritos em uma linguagem chamada Solidity, que é o que usaremos para escrever nosso contrato inteligente HelloWorld.sol.‌ -1. Navegue até a pasta "contracts" e crie um novo arquivo chamado HelloWorld.sol -2. Veja abaixo uma amostra de contrato inteligente "Hello World" da Ethereum Foundation, que usaremos neste tutorial. Copie e cole os itens abaixo em seu arquivo HelloWorld.sol e não se esqueça de ler os comentários para entender o que este contrato faz: +1. Navegue até a pasta “contracts” e crie um novo arquivo chamado HelloWorld.sol +2. Abaixo está um exemplo de contrato inteligente Hello World da Ethereum Foundation que usaremos neste tutorial. Copie e cole o conteúdo abaixo em seu arquivo HelloWorld.sol e certifique-se de ler os comentários para entender o que este contrato faz: ```solidity -// Especifica a versão do Solidity usando a versão semântica. -// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma +// Especifica a versão do Solidity, usando o versionamento semântico. +// Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma pragma solidity ^0.7.0; -// Defines a contract named `HelloWorld`. -// Um contrato é uma coleção de funções e dados (seu estado). Uma vez implantado, um contrato reside em um endereço específico na blockchain Ethereum. Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html +// Define um contrato chamado `HelloWorld`. +// Um contrato é uma coleção de funções e dados (seu estado). Uma vez implantado, um contrato reside em um endereço específico na blockchain Ethereum. Saiba mais: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html contract HelloWorld { - // Declares a state variable `message` of type `string`. - // Variáveis de estado são variáveis cujos valores são permanentemente armazenados no armazenamento do contrato. The keyword `public` makes variables accessible from outside a contract and creates a function that other contracts or clients can call to access the value. + // Declara uma variável de estado `message` do tipo `string`. + // As variáveis de estado são variáveis cujos valores são armazenados permanentemente no armazenamento do contrato. A palavra-chave `public` torna as variáveis acessíveis de fora de um contrato e cria uma função que outros contratos ou clientes podem chamar para acessar o valor. string public message; - // Similar to many class-based object-oriented languages, a constructor is a special function that is only executed upon contract creation. - // Os construtores são usados para inicializar os dados do contrato. Learn more:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors + // Semelhante a muitas linguagens orientadas a objetos baseadas em classes, um construtor é uma função especial que só é executada na criação do contrato. + // Os construtores são usados para inicializar os dados do contrato. Saiba mais:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors constructor(string memory initMessage) { - // Accepts a string argument `initMessage` and sets the value into the contract's `message` storage variable). + // Aceita um argumento de string `initMessage` e define o valor na variável de armazenamento `message` do contrato). message = initMessage; } - // A public function that accepts a string argument and updates the `message` storage variable. + // Uma função pública que aceita um argumento de string e atualiza a variável de armazenamento `message`. function update(string memory newMessage) public { message = newMessage; } } ``` -Este é um contrato inteligente muito simples, que armazena uma mensagem ao ser criado e pode ser atualizado através da função `update`. +Este é um contrato inteligente super simples que armazena uma mensagem na criação e pode ser atualizado chamando a função `update`. -## Passo 11: Vincule Metamask e Alchemy a seu projeto {#step-11} +## Etapa 11: Conectar o MetaMask e o Alchemy ao seu projeto {#step-11} -Nós já criamos uma carteira Metamask, uma conta Alchemy e já escrevemos nosso contrato inteligente. Agora é hora de vincularmos os três. +Nós criamos uma carteira MetaMask, uma conta da Alchemy e escrevemos nosso contrato inteligente. Agora é hora de conectar os três. -Toda transação enviada da sua carteira virtual requer uma assinatura, usando sua chave privada única. Para fornecer essa permissão ao nosso programa, nós podemos armazenar com segurança nossa chave privada (e a chave Alchemy API) em um arquivo de ambiente. +Toda transação enviada da sua carteira virtual requer uma assinatura, usando sua chave privada única. Para fornecer esta permissão a nosso programa, podemos armazenar nossa chave privada (e a chave Alchemy API) em um arquivo de ambiente. > Para saber mais sobre o envio de transações, confira [este tutorial](/developers/tutorials/sending-transactions-using-web3-and-alchemy/) sobre o envio de transações usando web3. @@ -220,49 +216,49 @@ Primeiro, instale o pacote dotenv na pasta do seu projeto: npm install dotenv --save ``` -Depois, crie um arquivo `.env` no diretório raiz do seu projeto e adicione sua chave Metamask privada e o URL da API HTTP Alchemy nele. +Em seguida, crie um arquivo `.env` no diretório raiz do nosso projeto e adicione sua chave privada do MetaMask e o URL da API HTTP da Alchemy a ele. -- Siga [estas instruções](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key) para exportar sua chave privada -- Veja abaixo como obter o URL da API HTTP Alchemy +- Siga [estas instruções](https://support.metamask.io/configure/accounts/how-to-export-an-accounts-private-key/) para exportar sua chave privada +- Veja abaixo para obter o URL da API HTTP da Alchemy -![obter chave da alchemy api](./get-alchemy-api-key.gif) +![obter chave de api da alchemy](./get-alchemy-api-key.png) -Copiar o URL da Alchemy API +Copiar URL da API da Alchemy -Seu arquivo `.env` ficará assim: +Seu `.env` deve ficar assim: ``` -API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key" -PRIVATE_KEY = "your-metamask-private-key" +API_URL = "https://eth-sepolia.g.alchemy.com/v2/sua-chave-de-api" +PRIVATE_KEY = "sua-chave-privada-metamask" ``` -Para realmente vinculá-los a nosso código, vamos fazer referência a essas variáveis em nosso arquivo `hardhat.config.js` no passo 13. +Para realmente conectar isso ao nosso código, faremos referência a essas variáveis em nosso arquivo `hardhat.config.js` na etapa 13. -No faça commit do .env! Por favor, tenha certeza de nunca compartilhar ou expor seu arquivo .env com ninguém, pois estará comprometendo suas partes secretas ao fazê-lo. Se estiver usando um controle de versão, adicione seu .env ao arquivo gitignore +Não faça commit do .env! Por favor, certifique-se de nunca compartilhar ou expor seu arquivo .env com ninguém, pois você está comprometendo seus segredos ao fazer isso. Se você estiver usando controle de versão, adicione seu .env a um arquivo gitignore. -## Passo 12: Instale o Ethers.js {#step-12-install-ethersjs} +## Etapa 12: Instalar o Ethers.js {#step-12-install-ethersjs} -Ethers.js é uma biblioteca que facilita a interação e o envio de solicitações ao Ethereum ao incorporar [métodos padrões JSON-RPC](/developers/docs/apis/json-rpc/) a outros métodos mais amigáveis ao usuário. +Ethers.js é uma biblioteca que facilita a interação e a realização de solicitações à Ethereum, envolvendo os [métodos JSON-RPC padrão](/developers/docs/apis/json-rpc/) com métodos mais amigáveis ao usuário. -Hardhat torna muito fácil a integração de [plugins](https://hardhat.org/plugins/), para ferramentas adicionais e funcionalidades extendidas. Aproveitaremos o [plugin Ethers](https://hardhat.org/docs/plugins/official-plugins#hardhat-ethers) para implantação de contratos. ([Ethers.js](https://github.com/ethers-io/ethers.js/) tem alguns métodos de implantação de contratos bastante claros). +O Hardhat torna muito fácil a integração de [Plugins](https://hardhat.org/plugins/) para ferramentas adicionais e funcionalidades estendidas. Aproveitaremos o [plugin Ethers](https://hardhat.org/docs/plugins/official-plugins#hardhat-ethers) para a implantação de contratos ([Ethers.js](https://github.com/ethers-io/ethers.js/) has some super clean contract deployment methods). -No diretório do projeto, digite: +No diretório do seu projeto, digite: ``` npm install --save-dev @nomiclabs/hardhat-ethers "ethers@^5.0.0" ``` -Também vamos precisar de ethers em nosso `hardhat.config.js` no próximo passo. +Também vamos precisar do ethers em nosso `hardhat.config.js` na próxima etapa. -## Passo 13: Atualize o hardhat.config.js {#step-13-update-hardhatconfigjs} +## Etapa 13: Atualizar o hardhat.config.js {#step-13-update-hardhatconfigjs} -Até aqui, já adicionamos diversas dependências e plugins. Agora precisamos atualizar o `hardhat.config.js` para que nosso projeto reconheça todos eles. +Adicionamos várias dependências e plugins até agora. Agora precisamos atualizar o `hardhat.config.js` para que nosso projeto saiba sobre todos eles. Atualize seu `hardhat.config.js` para ficar assim: @@ -277,10 +273,10 @@ const { API_URL, PRIVATE_KEY } = process.env; */ module.exports = { solidity: "0.7.3", - defaultNetwork: "goerli", + defaultNetwork: "sepolia", networks: { hardhat: {}, - goerli: { + sepolia: { url: API_URL, accounts: [`0x${PRIVATE_KEY}`] } @@ -288,9 +284,9 @@ module.exports = { } ``` -## Passo 14: Compile nosso contrato {#step-14-compile-our-contracts} +## Etapa 14: Compilar nosso contrato {#step-14-compile-our-contracts} -Para ter certeza de que tudo está funcionando, vamos compilar nosso contrato. A tarefa `compile` é uma das tarefas integradas do Hardhat. +Para ter certeza de que tudo está funcionando, vamos compilar nosso contrato. A tarefa `compile` é uma das tarefas incorporadas do hardhat. Na linha de comando, execute: @@ -298,21 +294,21 @@ Na linha de comando, execute: npx hardhat compile ``` -Você pode receber o aviso `SPDX license identifier not provided in source file`, mas não há necessidade de se preocupar com isso. Esperemos que tudo mais esteja bem! Se não, você sempre pode enviar uma mensagem no [discord Alchemy](https://discord.gg/u72VCg3). +Você pode receber um aviso sobre `SPDX license identifier not provided in source file`, mas não precisa se preocupar com isso — esperamos que todo o resto pareça bom! Se não, você sempre pode enviar uma mensagem no [Discord da Alchemy](https://discord.gg/u72VCg3). -## Passo 15: Escreva nosso script de implantação {#step-15-write-our-deploy-scripts} +## Etapa 15: Escrever nosso script de implantação {#step-15-write-our-deploy-scripts} Agora que nosso contrato está escrito e nosso arquivo de configuração está pronto, é hora de escrever o script de implantação do contrato. -Navegue até a pasta `scripts/` e crie um novo arquivo chamado `deploy.js`, adicionando o seguinte conteúdo: +Navegue até a pasta `scripts/` e crie um novo arquivo chamado `deploy.js`, adicionando o seguinte conteúdo a ele: ``` async function main() { const HelloWorld = await ethers.getContractFactory("HelloWorld"); - // Start deployment, returning a promise that resolves to a contract object + // Inicia a implantação, retornando uma promessa que resolve para um objeto de contrato const hello_world = await HelloWorld.deploy("Hello World!"); - console.log("Contract deployed to address:", hello_world.address);} + console.log("Contrato implantado no endereço:", hello_world.address);} main() .then(() => process.exit(0)) @@ -322,48 +318,50 @@ main() }); ``` -A Hardhat fez um trabalho incrível ao explicar o que cada uma dessas linhas de código faz em seu [Tutorial sobre contratos](https://hardhat.org/tutorial/testing-contracts.html#writing-tests). Adotamos aqui as explicações deles. +A Hardhat faz um trabalho incrível explicando o que cada uma dessas linhas de código faz em seu [tutorial de Contratos](https://hardhat.org/tutorial/testing-contracts.html#writing-tests), nós adotamos as explicações deles aqui. ``` const HelloWorld = await ethers.getContractFactory("HelloWorld"); ``` -Uma `ContractFactory` em ethers.js é uma abstração usada para implantar novos contratos inteligentes, então, aqui, `HelloWorld` representa uma fábrica para instâncias do nosso contrato Hello World. Ao usar o plug-in `hardhat-ethers`, as instâncias `ContractFactory` e `Contract` são conectadas ao primeiro signatário por padrão. +Uma `ContractFactory` em ethers.js é uma abstração usada para implantar novos contratos inteligentes. Portanto, `HelloWorld` aqui é uma fábrica para instâncias do nosso contrato hello world. Ao usar o plugin `hardhat-ethers`, as instâncias `ContractFactory` e `Contract` são conectadas ao primeiro signatário por padrão. ``` const hello_world = await HelloWorld.deploy(); ``` -Ao chamar `deploy()` em uma `ContractFactory`, a implantação se iniciará e retornará uma `Promise` que se resolve em um `Contract`. Este é o objeto que tem um método para cada uma de nossas funções de contrato inteligente. +Chamar `deploy()` em uma `ContractFactory` iniciará a implantação e retornará uma `Promise` que resolve para um `Contrato`. Este é o objeto que tem um método para cada uma de nossas funções de contrato inteligente. -## Passo 16: Implante nosso contrato {#step-16-deploy-our-contract} +## Etapa 16: Implantar nosso contrato {#step-16-deploy-our-contract} -Finalmente estamos prontos para implantar o nosso contrato inteligente! Navegue até a linha de comando e digite: +Finalmente estamos prontos para implantar o nosso contrato inteligente! Navegue até a linha de comando e execute: ``` -npx hardhat run scripts/deploy.js --network goerli +npx hardhat run scripts/deploy.js --network sepolia ``` Você deverá ver algo assim: ``` -Contract deployed to address: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570 +Contrato implantado no endereço: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570 ``` -Se formos ao [etherscan da Goerli](https://goerli.etherscan.io/) e procurarmos nosso endereço de contrato, devemos ser capazes de ver que ele foi implantado com sucesso. A transação ficará parecida com isto: +Se formos ao [Etherscan da Sepolia](https://sepolia.etherscan.io/) e pesquisarmos o endereço do nosso contrato, poderemos ver que ele foi implantado com sucesso. A transação ficará parecida com isto: -![contrato etherscan](./etherscan-contract.png) +![contrato no etherscan](./etherscan-contract.png) -O endereço `From` deve corresponder ao endereço da sua conta Metamask, e o endereço "Para" vai dizer "Criação de contrato", mas se clicarmos na transação veremos o endereço do nosso contrato no campo `To`: +O endereço `From` deve corresponder ao endereço da sua conta MetaMask e o endereço To dirá “Contract Creation”, mas se clicarmos na transação, veremos o endereço do nosso contrato no campo `To`: -![transação etherscan](./etherscan-transaction.png) +![transação no etherscan](./etherscan-transaction.png) -Parabéns! Você acaba de implantar um contrato inteligente para a cadeia Ethereum 🎉 +Parabéns! Você acabou de implantar um contrato inteligente na cadeia Ethereum 🎉 -Para entender o que está acontecendo nos bastidores, vamos navegar até a guia Explorer no [painel do Alchemy](https://dashboard.alchemyapi.io/explorer). Se você tem vários aplicativos Alchemy, certifique-se de filtrar por app e selecionar “Hello World”. ![explorador hello world](./hello-world-explorer.png) +Para entender o que está acontecendo nos bastidores, vamos navegar para a guia Explorer em nosso [painel da Alchemy](https://dashboard.alchemyapi.io/explorer). Se você tiver vários aplicativos Alchemy, certifique-se de filtrar por aplicativo e selecionar “Hello World”. +![explorador hello world](./hello-world-explorer.png) -Aqui você verá um punhado de chamadas JSON-RPC que Hardhat/Ethers fizeram em segundo plano para nós quando chamamos a função `.deploy() `. Duas importantes chamadas aqui são [`eth_sendRawTransaction`](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_sendrawtransaction), que é o pedido para escrever de fato nosso contrato na cadeia Goerli, e [`eth_getTransactionByHash`](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_gettransactionbyhash) que é um pedido para ler informações sobre nossa transação dado o hash (um padrão típico em transações). Para saber mais sobre o envio de transações, confira este tutorial em [ sobre como enviar transações usando a Web3](/developers/tutorials/sending-transactions-using-web3-and-alchemy/) +Aqui você verá uma série de chamadas JSON-RPC que o Hardhat/Ethers fizeram nos bastidores para nós quando chamamos a função `.deploy()`. Duas chamadas importantes a serem destacadas aqui são [`eth_sendRawTransaction`](https://www.alchemy.com/docs/node/abstract/abstract-api-endpoints/eth-send-raw-transaction), que é a solicitação para realmente escrever nosso contrato na cadeia Sepolia, e [`eth_getTransactionByHash`](https://www.alchemy.com/docs/node/abstract/abstract-api-endpoints/eth-get-transaction-by-hash), que é uma solicitação para ler informações sobre nossa transação, dado o hash (um padrão típico ao lidar com +transações). Para saber mais sobre o envio de transações, confira este tutorial sobre [o envio de transações usando Web3](/developers/tutorials/sending-transactions-using-web3-and-alchemy/) -Isso é tudo para a parte 1 deste tutorial. Na parte 2, [interagiremos com nosso contrato inteligente](https://docs.alchemyapi.io/alchemy/tutorials/hello-world-smart-contract#part-2-interact-with-your-smart-contract) atualizando nossa mensagem inicial e, na parte 3, [publicaremos nosso contrato inteligente no Etherscan](https://docs.alchemyapi.io/alchemy/tutorials/hello-world-smart-contract#optional-part-3-publish-your-smart-contract-to-etherscan) para que todos aprendam como interagir com ele. +Isso é tudo para a parte 1 deste tutorial. Na parte 2, vamos [interagir com nosso contrato inteligente](https://www.alchemy.com/docs/interacting-with-a-smart-contract) atualizando nossa mensagem inicial e, na parte 3, vamos [publicar nosso contrato inteligente no Etherscan](https://www.alchemy.com/docs/submitting-your-smart-contract-to-etherscan) para que todos saibam como interagir com ele. -**Quer aprender mais sobre Alchemy? Confira nosso [site](https://alchemyapi.io/eth). Não quer perder nenhuma atualização? Assine o nosso boletim informativo [aqui](https://www.alchemyapi.io/newsletter)! Não se esqueça também de nos seguir no [Twitter](https://twitter.com/alchemyplatform) e participar do nosso [Discord](https://discord.com/invite/u72VCg3)**. +**Quer saber mais sobre o Alchemy? Confira nosso [site](https://www.alchemy.com/eth). Não quer perder nenhuma atualização? Assine nossa newsletter [aqui](https://www.alchemy.com/newsletter)! Não se esqueça de entrar também no nosso [Discord](https://discord.gg/u72VCg3).**. diff --git a/public/content/translations/pt-br/developers/tutorials/how-to-implement-an-erc721-market/index.md b/public/content/translations/pt-br/developers/tutorials/how-to-implement-an-erc721-market/index.md index dc2b696978c..39272d5c6f9 100644 --- a/public/content/translations/pt-br/developers/tutorials/how-to-implement-an-erc721-market/index.md +++ b/public/content/translations/pt-br/developers/tutorials/how-to-implement-an-erc721-market/index.md @@ -2,11 +2,7 @@ title: Como implementar um mercado ERC-721 description: Como colocar itens tokenizados para venda em um mercado descentralizado author: "Alberto Cuesta Cañada" -tags: - - "contratos inteligentes" - - "erc-721" - - "solidez" - - "tokens" +tags: [ "smart contracts", "erc-721", "Solidity", "tokens" ] skill: intermediate lang: pt-br published: 2020-03-19 @@ -26,13 +22,13 @@ Com a blockchain, esses mercados estão definidos para mudar mais uma vez, deixe O modelo de negócio de um conselho de classificações públicas da blockchain precisará ser diferente do da Ebay e da empresa. -Primeiro, há [o ângulo de descentralização](/developers/docs/web2-vs-web3/). Plataformas existentes precisam manter seus próprios servidores. Uma plataforma descentralizada é mantida por seus usuários, então o custo de executar a plataforma principal cai para zero para o proprietário da plataforma. +Primeiro, há [a perspectiva da descentralização](/developers/docs/web2-vs-web3/). Plataformas existentes precisam manter seus próprios servidores. Uma plataforma descentralizada é mantida por seus usuários, então o custo de executar a plataforma principal cai para zero para o proprietário da plataforma. -Em seguida, há o front-end, o site ou a interface que dá acesso à plataforma. Aqui há muitas opções. Os proprietários da plataforma podem restringir o acesso e forçar todos a usar a interface, carregando uma taxa. Os proprietários da plataforma também podem decidir abrir o acesso (Poder para as Pessoas!) e deixar qualquer pessoa construir interfaces na plataforma. Ou os proprietários poderiam decidir qualquer abordagem no meio desses extremos. +Em seguida, há o front-end, o site ou a interface que dá acesso à plataforma. Aqui há muitas opções. Os proprietários da plataforma podem restringir o acesso e forçar todos a usar a interface, carregando uma taxa. Os proprietários da plataforma também podem decidir abrir o acesso (Poder para o povo!) e permitir que qualquer pessoa crie interfaces para a plataforma. Ou os proprietários poderiam decidir qualquer abordagem no meio desses extremos. _Os líderes empresariais com mais visão do que eu saberão bem como monetizar isso. Tudo o que entendo é que isto é diferente do status quo e é, provavelmente, lucrativo._ -Além disso, há o ponto relativo à automação e aos pagamentos. Algumas coisas podem ser [efetivamente tokenizadas](https://hackernoon.com/tokenization-of-digital-assets-g0ffk3v8s?ref=hackernoon.com) e negociadas em um quadro de classificações. Ativos tokenizados são facilmente transferidos em uma blockchain. Métodos de pagamento altamente complexos podem ser facilmente implementados em uma blockchain. +Além disso, há o ponto relativo à automação e aos pagamentos. Algumas coisas podem ser [tokenizadas de forma muito eficaz](https://hackernoon.com/tokenization-of-digital-assets-g0ffk3v8s?ref=hackernoon.com) e negociadas em um quadro de classificados. Ativos tokenizados são facilmente transferidos em uma blockchain. Métodos de pagamento altamente complexos podem ser facilmente implementados em uma blockchain. Sinto uma oportunidade de negócios aqui. Um quadro de classificados sem custos correntes pode ser facilmente implementado, com caminhos de pagamento complexos incluídos em cada transação. Tenho certeza de que alguém vai ter uma ideia sobre em que usar isso. @@ -40,9 +36,9 @@ Estou feliz construindo. Vamos dar uma olhada no código. ## Implementação {#implementation} -Há algum tempo iniciamos um [repositório de código aberto](https://github.com/HQ20/contracts?ref=hackernoon.com) com implementações de exemplos de casos de negócios e outros brindes, dê uma olhada. +Há algum tempo, iniciamos um [repositório de código aberto](https://github.com/HQ20/contracts?ref=hackernoon.com) com exemplos de implementação de casos de negócio e outras coisinhas, por favor, dê uma olhada. -O código para este [Ethereum Classifieds Board](https://github.com/HQ20/contracts/tree/master/contracts/classifieds?ref=hackernoon.com) está lá, por favor, use e abuse dele. Apenas esteja ciente de que o código não foi auditado e de que você precisa fazer a sua própria diligência antes de deixar o dinheiro entrar. +O código para este [Quadro de Classificados do Ethereum](https://github.com/HQ20/contracts/tree/master/contracts/classifieds?ref=hackernoon.com) está lá, por favor, use e abuse dele. Apenas esteja ciente de que o código não foi auditado e de que você precisa fazer a sua própria diligência antes de deixar o dinheiro entrar. Os fundamentos do conselho não são complexos. Todos os anúncios no board serão apenas uma construção com alguns campos: @@ -67,9 +63,9 @@ Usando um mapeamento significa apenas que temos que criar um id para cada anúnc Em seguida, a questão de quais são os itens com que lidamos, e qual é esta moeda que é usada para pagar a transação. -Para os itens, vamos apenas pedir que eles implementem a interface [ERC-721](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/IERC721.sol?ref=hackernoon.com), que realmente é apenas uma maneira de representar itens do mundo real em uma blockchain, embora [funcione melhor com os recursos digitais](https://hackernoon.com/tokenization-of-digital-assets-g0ffk3v8s?ref=hackernoon.com). Vamos especificar o nosso próprio contrato ERC721 no construtor, significa que todos os ativos do nosso quadro de classificados precisam ter sido tokenizados previamente. +Para os itens, vamos apenas pedir que eles implementem a interface [ERC-721](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/IERC721.sol?ref=hackernoon.com), que na verdade é apenas uma forma de representar itens do mundo real em uma blockchain, embora [funcione melhor com ativos digitais](https://hackernoon.com/tokenization-of-digital-assets-g0ffk3v8s?ref=hackernoon.com). Vamos especificar o nosso próprio contrato ERC721 no construtor, significa que todos os ativos do nosso quadro de classificados precisam ter sido tokenizados previamente. -Quanto aos pagamentos, vamos fazer algo semelhante. A maioria dos projetos blockchain definem suas próprias criptomoedas [ERC-20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol?ref=hackernoon.com). Outros preferem usar um mainstream como a DAI. Neste quadro de classificações, você só precisa decidir em construção qual será a sua moeda. Fácil. +Quanto aos pagamentos, vamos fazer algo semelhante. A maioria dos projetos de blockchain define sua própria criptomoeda [ERC-20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol?ref=hackernoon.com). Outros preferem usar um mainstream como a DAI. Neste quadro de classificações, você só precisa decidir em construção qual será a sua moeda. Fácil. ```solidity constructor ( @@ -127,16 +123,16 @@ function cancelTrade(uint256 _trade) Trade memory trade = trades[_trade]; require( msg.sender == trade.poster, - "Trade can be cancelled only by poster." + "A negociação só pode ser cancelada pelo anunciante." ); - require(trade.status == "Open", "Trade is not Open."); + require(trade.status == "Open", "A negociação não está aberta."); itemToken.transferFrom(address(this), trade.poster, trade.item); trades[_trade].status = "Cancelled"; emit TradeStatusChange(_trade, "Cancelled"); } ``` -É isso. Você chegou ao fim da implementação. É bastante surpreendente como alguns conceitos de negócios se tornam compactos quando são expressados em código, e este é um desses casos. Verifique o contrato completo [no nosso repositório](https://github.com/HQ20/contracts/blob/master/contracts/classifieds/Classifieds.sol). +É isso. Você chegou ao fim da implementação. É bastante surpreendente como alguns conceitos de negócios se tornam compactos quando são expressados em código, e este é um desses casos. Confira o contrato completo [em nosso repositório](https://github.com/HQ20/contracts/blob/master/contracts/classifieds/Classifieds.sol). ## Conclusão {#conclusion} @@ -146,4 +142,4 @@ Também acontece de as seções de classificados serem uma ferramenta fácil de Neste artigo, tentei fazer uma ponte entre a realidade comercial de um conselho de administração clássico com a implementação tecnológica. Este conhecimento deve ajudá-lo a criar uma visão e um roteiro para a implementação, se você tiver as habilidades certas. -Como sempre, se você for construir algo divertido e gostaria de alguns conselhos, por favor [envie-me uma mensagem](https://albertocuesta.es/)! Fico sempre feliz em ajudar. +Como sempre, se você pretende construir algo divertido e gostaria de algum conselho, por favor [me envie uma mensagem](https://albertocuesta.es/)! Fico sempre feliz em ajudar. diff --git a/public/content/translations/pt-br/developers/tutorials/how-to-mint-an-nft/index.md b/public/content/translations/pt-br/developers/tutorials/how-to-mint-an-nft/index.md index 94593c6e630..a26f6ef7125 100644 --- a/public/content/translations/pt-br/developers/tutorials/how-to-mint-an-nft/index.md +++ b/public/content/translations/pt-br/developers/tutorials/how-to-mint-an-nft/index.md @@ -1,33 +1,31 @@ --- -title: Como criar um NFT (Segunda parte da série de tutoriais sobre NFT) -description: Este tutorial descreve como criar um NFT na blockchain Ethereum usando nosso contrato inteligente e Web3. +title: "Como Cunhar um NFT (Parte 2/3 da Série de Tutoriais sobre NFT)" +description: Este tutorial descreve como cunhar um NFT na blockchain Ethereum usando nosso contrato inteligente e Web3. author: "Sumi Mudgil" -tags: - - "ERC-721" - - "alchemy" - - "solidity" - - "contratos inteligentes" +tags: [ "ERC-721", "Alchemy", "Solidity", "smart contracts" ] skill: beginner lang: pt-br published: 2021-04-22 --- -[Beeple](https://www.nytimes.com/2021/03/11/arts/design/nft-auction-christies-beeple.html): 69 milhões de doláres [3LAU](https://www.forbes.com/sites/abrambrown/2021/03/03/3lau-nft-nonfungible-tokens-justin-blau/?sh=5f72ef64643b): 11 milhões de doláres [Grimes](https://www.theguardian.com/music/2021/mar/02/grimes-sells-digital-art-collection-non-fungible-tokens): 6 milhões de doláres +[Beeple](https://www.nytimes.com/2021/03/11/arts/design/nft-auction-christies-beeple.html): $69 Milhões +[3LAU](https://www.forbes.com/sites/abrambrown/2021/03/03/3lau-nft-nonfungible-tokens-justin-blau/?sh=5f72ef64643b): $11 Milhões +[Grimes](https://www.theguardian.com/music/2021/mar/02/grimes-sells-digital-art-collection-non-fungible-tokens): $6 Milhões -All of them minted their NFTs using Alchemy’s powerful API. Neste tutorial, vamos te ensinar a fazer o mesmo em < 10 minutos. +Todos eles cunharam seus NFTs usando a poderosa API da Alchemy. Neste tutorial, vamos te ensinar a fazer o mesmo em \<10 minutos. -"Cunhar um NFT" é o ato de publicar uma instância única do seu token ERC-721 na blockchain. Usando nosso contrato inteligente da [Parte 1 desta série de tutoriais NFT](/developers/tutorials/how-to-write-and-deploy-an-nft/), vamos usar nossas habilidades Web3 e criar um NFT. No final deste tutorial, você será capaz de cunhar tantos NFTs quanto seu coração (e sua carteira) desejar! +“Cunhar um NFT” é o ato de publicar uma instância única de seu token ERC-721 na blockchain. Usando nosso contrato inteligente da [Parte 1 desta série de tutoriais sobre NFT](/developers/tutorials/how-to-write-and-deploy-an-nft/), vamos usar nossas habilidades de Web3 e cunhar um NFT. No final deste tutorial, você será capaz de cunhar tantos NFTs quanto seu coração (e sua carteira) desejar! Vamos começar! -## Etapa 1: Instalar a Web3 {#install-web3} +## Etapa 1: Instalar o Web3 {#install-web3} -Se você seguiu o primeiro tutorial sobre a criação do seu contrato inteligente NFT, você já tem experiência usando a Ethers.js. Web3 é semelhante a Ethers, uma vez que é uma biblioteca usada para facilitar a criação de solicitações para a blockchain Ethereum. Neste tutorial, usaremos a [Alchemy Web3](https://docs.alchemyapi.io/alchemy/documentation/alchemy-web3), que é uma biblioteca Web3 aprimorada que oferece novas tentativas automáticas e um suporte WebSocket sólido. +Se você seguiu o primeiro tutorial sobre a criação do seu contrato inteligente NFT, você já tem experiência usando a Ethers.js. Web3 é semelhante ao Ethers, pois é uma biblioteca usada para facilitar a criação de solicitações para a blockchain Ethereum. Neste tutorial, usaremos o [Alchemy Web3](https://docs.alchemyapi.io/alchemy/documentation/alchemy-web3), que é uma biblioteca Web3 aprimorada que oferece novas tentativas automáticas e suporte robusto a WebSocket. -No diretório inicial do seu projeto execute: +No diretório inicial do seu projeto, execute: ``` -yarn add @alch/alchemy-web3 +npm install @alch/alchemy-web3 ``` ## Etapa 2: Criar um arquivo `mint-nft.js` {#create-mintnftjs} @@ -41,83 +39,83 @@ const { createAlchemyWeb3 } = require("@alch/alchemy-web3") const web3 = createAlchemyWeb3(API_URL) ``` -## Etapa 3: Conseguir sua ABI de contrato {#contract-abi} +## Etapa 3: Obter a ABI do seu contrato {#contract-abi} -Nossa ABI (Interface binária de aplicativo) de contrato é a interface para interagir com nosso contrato inteligente. Você pode aprender mais sobre ABIs de contratos [aqui](https://docs.alchemyapi.io/alchemy/guides/eth_getlogs#what-are-ab-is). O Hardhat automaticamente gera uma ABI para nós e a salva no arquivo `MyNFT.json`. Para usar isso, precisaremos distribuir o conteúdo adicionando as seguintes linhas de código ao nosso arquivo `mint-nft.js`: +A ABI (Application Binary Interface) do nosso contrato é a interface para interagir com o nosso contrato inteligente. Você pode saber mais sobre ABIs de Contrato [aqui](https://docs.alchemyapi.io/alchemy/guides/eth_getlogs#what-are-ab-is). O Hardhat gera automaticamente uma ABI para nós e a salva no arquivo `MyNFT.json`. Para usar isso, precisaremos analisar o conteúdo, adicionando as seguintes linhas de código ao nosso arquivo `mint-nft.js`: ```js const contract = require("../artifacts/contracts/MyNFT.sol/MyNFT.json") ``` -Se quiser ver a ABI, pode imprimi-la no console: +Se quiser ver a ABI, você pode imprimi-la no seu console: ```js console.log(JSON.stringify(contract.abi)) ``` -Para executar o `mint-nft.js` e ver seu ABI impresso no console, navegue até seu terminal e execute: +Para executar o `mint-nft.js` e ver sua ABI impressa no console, navegue até seu terminal e execute: ```js node scripts/mint-nft.js ``` -## Etapa 4: Configurar os metadados para seu NFT usando IPFS {#config-meta} +## Etapa 4: Configurar os metadados do seu NFT usando o IPFS {#config-meta} -Se você se lembra do nosso tutorial na Parte 1, nossa função do contrato inteligente `mintNFT` assume um parâmetro tokenURI que deve resolver em um documento JSON, descrevendo os metadados do NFT, o que realmente dá vida ao NFT, permitindo que ele tenha propriedades configuráveis, tais como: nome, descrição, imagem e outros atributos. +Se você se lembra do nosso tutorial da Parte 1, nossa função de contrato inteligente `mintNFT` recebe um parâmetro tokenURI que deve ser resolvido em um documento JSON que descreve os metadados do NFT — que é o que realmente dá vida ao NFT, permitindo que ele tenha propriedades configuráveis, como nome, descrição, imagem e outros atributos. -> _Interplanetary File System (IPFS) é um protocolo descentralizado e uma rede peer-to-peer para armazenar e compartilhar dados em um sistema de arquivos distribuído._ +> _O Interplanetary File System (IPFS) é um protocolo descentralizado e uma rede ponto a ponto para armazenar e compartilhar dados em um sistema de arquivos distribuído._ -Usaremos o Pinata, uma API IPFS e um kit de ferramentas práticos, para armazenar nossos ativos e metadados NFT para garantir que nosso NFT seja realmente descentralizado. Se você não tem uma conta em Pinata, cadastre-se [aqui](https://app.pinata.cloud) gratuitamente e conclua as etapas de confirmação de seu e-mail. +Usaremos o Pinata, uma API e um kit de ferramentas IPFS convenientes, para armazenar o ativo e os metadados do nosso NFT para garantir que nosso NFT seja verdadeiramente descentralizado. Se você não tiver uma conta no Pinata, crie uma conta gratuita [aqui](https://app.pinata.cloud) e siga as etapas para verificar seu e-mail. -Assim que você tiver criado sua conta: +Assim que tiver criado uma conta: -- Navegue até a página "Files" e clique no botão azul "Upload" no canto superior esquerdo da página. +- Navegue até a página “Arquivos” e clique no botão azul "Fazer Upload" no canto superior esquerdo da página. -- Faça o upload de uma imagem no Pinata — este será o recurso de imagem para o seu NFT. Sinta-se à vontade para nomear o ativo da forma que quiser +- Faça o upload de uma imagem para o Pinata — esta será a imagem do seu NFT. Sinta-se à vontade para nomear o ativo como quiser -- Após o upload, você verá as informações do arquivo na tabela da página "Arquivos". Você também verá a coluna CID. Você pode copiar o CID clicando no botão de cópia ao lado dele. Você pode ver seu ‘upload’ em: `https://gateway.pinata.cloud/ipfs/`. Você pode encontrar a imagem que usamos no IPFS [aqui](https://gateway.pinata.cloud/ipfs/QmZdd5KYdCFApWn7eTZJ1qgJu18urJrP9Yh1TZcZrZxxB5), por exemplo. +- Após o upload, você verá as informações do arquivo na tabela na página "Arquivos". Você também verá uma coluna CID. Você pode copiar o CID clicando no botão de cópia ao lado dele. Você pode visualizar seu upload em: `https://gateway.pinata.cloud/ipfs/`. Por exemplo, você pode encontrar a imagem que usamos no IPFS [aqui](https://gateway.pinata.cloud/ipfs/QmZdd5KYdCFApWn7eTZJ1qgJu18urJrP9Yh1TZcZrZxxB5). -Para os que aprendem de maneira mais visual, os passos acima são resumidos aqui: +Para aqueles que aprendem melhor visualmente, as etapas acima estão resumidas aqui: -![Como fazer o upload de sua imagem para Pinata](./instructionsPinata.gif) +![Como fazer o upload da sua imagem para o Pinata](./instructionsPinata.gif) -Agora, nós queremos enviar mais um documento para o Pinata. Mas antes, precisamos criá-lo! +Agora, vamos querer fazer o upload de mais um documento para o Pinata. Mas antes disso, precisamos criá-lo! -Em seu diretório raiz, faça um novo arquivo chamado `nft-metadata.json` e adicione o seguinte código json: +No seu diretório raiz, crie um novo arquivo chamado `nft-metadata.json` e adicione o seguinte código json: ```json { "attributes": [ { - "trait_type": "Breed", + "trait_type": "Raça", "value": "Maltipoo" }, { - "trait_type": "Eye color", + "trait_type": "Cor dos olhos", "value": "Mocha" } ], - "description": "The world's most adorable and sensitive pup.", + "description": "O cachorrinho mais adorável e sensível do mundo.", "image": "ipfs://QmWmvTJmJU3pozR9ZHFmQC2DNDwi2XJtf3QGyYiiagFSWb", "name": "Ramses" } ``` -Sinta-se à vontade para mudar os dados no json. Você pode remover ou adicionar na seção de atributos. O mais importante é se certificar de que o campo de imagem aponta para a localização da sua imagem IPFS — caso contrário, seu NFT incluirá uma foto de um cachorro (bem bonito, por sinal). +Sinta-se à vontade para alterar os dados no json. Você pode remover ou adicionar itens à seção de atributos. O mais importante é se certificar de que o campo da imagem aponte para a localização da sua imagem IPFS — caso contrário, seu NFT incluirá a foto de um (muito fofo!) cachorro. -Uma vez terminada a edição do arquivo JSON, salve-o e faça o upload para o Pinata, seguindo os mesmos passos que fizemos para o upload da imagem. +Quando terminar de editar o arquivo JSON, salve-o e faça o upload para o Pinata, seguindo os mesmos passos que fizemos para o upload da imagem. -![Como fazer o upload de seu nft-metadata.json para Pinata](./uploadPinata.gif) +![Como fazer o upload do seu nft-metadata.json para o Pinata](./uploadPinata.gif) -## Etapa 5: Criar uma instância de seu contrato {#instance-contract} +## Etapa 5: Criar uma instância do seu contrato {#instance-contract} -Agora, para interagir com o nosso contrato, precisamos criar uma instância dele em nosso código. Para fazer isso, precisaremos do nosso endereço de contrato, obtido na implantação ou no [Etherscan](https://sepolia.etherscan.io/), procurando o endereço que você usou para implantar o contrato. +Agora, para interagir com o nosso contrato, precisamos criar uma instância dele em nosso código. Para fazer isso, precisaremos do endereço do nosso contrato, que podemos obter na implantação ou no [Blockscout](https://eth-sepolia.blockscout.com/), pesquisando o endereço que você usou para implantar o contrato. -![Veja o seu endereço de contrato no Etherscan](./view-contract-etherscan.png) +![Veja o endereço do seu contrato no Etherscan](./view-contract-etherscan.png) -No exemplo acima, o endereço do contrato é 0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778. +No exemplo acima, o endereço do nosso contrato é 0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778. -Em seguida, usaremos o [método do contrato](https://docs.web3js.org/api/web3-eth-contract/class/Contract) Web3 para criar nosso contrato usando a ABI e o endereço. Em seu arquivo `mint-nft.js`, adicione o seguinte: +A seguir, usaremos o [método de contrato](https://docs.web3js.org/api/web3-eth-contract/class/Contract) do Web3 para criar nosso contrato usando a ABI e o endereço. No seu arquivo `mint-nft.js`, adicione o seguinte: ```js const contractAddress = "0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778" @@ -125,11 +123,11 @@ const contractAddress = "0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778" const nftContract = new web3.eth.Contract(contract.abi, contractAddress) ``` -## Etapa 6: Atualize o arquivo `.env` {#update-env} +## Etapa 6: Atualizar o arquivo `.env` {#update-env} -Agora, para criar e enviar transações para a cadeia Ethereum, usaremos seu endereço de conta Ethereum para obter o nonce da conta (explicaremos abaixo). +Agora, para criar e enviar transações para a rede Ethereum, usaremos o endereço da sua conta pública do Ethereum para obter o nonce da conta (explicaremos abaixo). -Adicione sua chave pública ao seu arquivo `.env` — se você concluiu a parte 1 do tutorial, nosso arquivo `.env` deve ficar assim: +Adicione sua chave pública ao seu arquivo `.env` — se você concluiu a parte 1 do tutorial, nosso arquivo `.env` deve estar assim agora: ```js API_URL = "https://eth-sepolia.g.alchemy.com/v2/your-api-key" @@ -139,25 +137,25 @@ PUBLIC_KEY = "your-public-account-address" ## Etapa 7: Criar sua transação {#create-txn} -Primeiro, vamos definir a função nomeada `mintNFT(tokenData)` e criar nossa transação através do seguinte: +Primeiro, vamos definir uma função chamada `mintNFT(tokenData)` e criar nossa transação fazendo o seguinte: -1. Pegue a _PRIVATE_KEY_ e a _PUBLIC_KEY_ do arquivo `.env`. +1. Obtenha suas _PRIVATE_KEY_ e _PUBLIC_KEY_ do arquivo `.env`. -1. Em seguida, precisaremos descobrir qual é o nonce da conta. A especificação nonce é usada para acompanhar o número de transações enviadas a partir do seu endereço — que precisamos para fins de segurança e evitar [ataques de replay](https://docs.alchemyapi.io/resources/blockchain-glossary#account-nonce). Para obter o número de transações enviadas a partir do seu endereço, usamos [getTransactionCount](https://docs.alchemyapi.io/documentation/alchemy-api-reference/json-rpc#eth_gettransactioncount). +2. Em seguida, precisaremos descobrir qual é o nonce da conta. A especificação nonce é usada para acompanhar o número de transações enviadas a partir do seu endereço — o que precisamos para fins de segurança e para prevenir [ataques de replay](https://docs.alchemyapi.io/resources/blockchain-glossary#account-nonce). Para obter o número de transações enviadas a partir do seu endereço, usamos o [getTransactionCount](https://docs.alchemyapi.io/documentation/alchemy-api-reference/json-rpc#eth_gettransactioncount). -1. Finalmente, vamos configurar nossa transação com as seguintes informações: +3. Finalmente, vamos configurar nossa transação com as seguintes informações: -- `'from': PUBLIC_KEY`: a origem da nossa transação é nosso endereço público +- `'from': PUBLIC_KEY` — A origem da nossa transação é o nosso endereço público -- `'to': contractAddress`: o contrato com o qual queremos interagir e ao qual enviar a transação +- `'to': contractAddress` — O contrato com o qual desejamos interagir e para o qual enviar a transação - `'nonce': nonce` — O nonce da conta com o número de transações enviadas do nosso endereço -- `'gas': estimatedGas`: o gás estimado necessário para completar a transação +- `'gas': estimatedGas` — O gás estimado necessário para concluir a transação -- `'data': nftContract.methods.mintNFT(PUBLIC_KEY, md).encodeABI()`: o cálculo que queremos realizar nesta transação que, neste caso, é cunhar um NFT +- `'data': nftContract.methods.mintNFT(PUBLIC_KEY, md).encodeABI()` — A computação que desejamos realizar nesta transação, que neste caso é cunhar um NFT -Seu arquivo `mint-nft.js` deverá ficar assim: +Seu arquivo `mint-nft.js` deve estar assim agora: ```js require('dotenv').config(); @@ -173,9 +171,9 @@ Seu arquivo `mint-nft.js` deverá ficar assim: const nftContract = new web3.eth.Contract(contract.abi, contractAddress); async function mintNFT(tokenURI) { - const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, 'latest'); //get latest nonce + const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, 'latest'); //obter o nonce mais recente - //the transaction + //a transação const tx = { 'from': PUBLIC_KEY, 'to': contractAddress, @@ -190,7 +188,7 @@ Seu arquivo `mint-nft.js` deverá ficar assim: Agora que criamos a nossa transação, precisamos assiná-la para poder enviá-la. É aqui que usaremos nossa chave privada. -`web3.eth.sendSignedTransaction` nos dará o hash da transação, que podemos usar para ter certeza de que nossa transação foi minerada e não foi descartada pela rede. Você vai notar na seção de assinatura de transações que adicionamos alguma verificação de erro para saber se nossa transação foi processada com sucesso. +`web3.eth.sendSignedTransaction` nos dará o hash da transação, que podemos usar para garantir que nossa transação foi minerada e não foi descartada pela rede. Você notará que, na seção de assinatura da transação, adicionamos uma verificação de erros para que saibamos se a nossa transação foi concluída com sucesso. ```js require("dotenv").config() @@ -206,9 +204,9 @@ const contractAddress = "0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778" const nftContract = new web3.eth.Contract(contract.abi, contractAddress) async function mintNFT(tokenURI) { - const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, "latest") //get latest nonce + const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, "latest") //obter o nonce mais recente - //the transaction + //a transação const tx = { from: PUBLIC_KEY, to: contractAddress, @@ -225,13 +223,13 @@ async function mintNFT(tokenURI) { function (err, hash) { if (!err) { console.log( - "The hash of your transaction is: ", + "O hash de sua transação é: ", hash, - "\nCheck Alchemy's Mempool to view the status of your transaction!" + "\nVerifique o Mempool da Alchemy para ver o status da sua transação!" ) } else { console.log( - "Something went wrong when submitting your transaction:", + "Algo deu errado ao enviar sua transação:", err ) } @@ -239,24 +237,24 @@ async function mintNFT(tokenURI) { ) }) .catch((err) => { - console.log(" Promise failed:", err) + console.log(" Falha na promessa:", err) }) } ``` -## Etapa 9: Chame `mintNFT` e execute o nó `mint-nft.js` {#call-mintnft-fn} +## Etapa 9: Chamar `mintNFT` e executar node `mint-nft.js` {#call-mintnft-fn} -Lembra do `metadata.json` que você carregou no Pinata? Obtenha o seu hashcode no Pinata e transmita o seguinte como parâmetro para a função `mintNFT` `https://gateway.pinata.cloud/ipfs/` +Lembra do arquivo `metadata.json` que você enviou para o Pinata? Obtenha seu hashcode do Pinata e passe o seguinte como parâmetro para a função `mintNFT`: `https://gateway.pinata.cloud/ipfs/` Veja como obter o hashcode: -![Como obter seu hashcode de metadados do nft no Pinata](./metadataPinata.gif)_Como obter seu hashcode de metadados do nft no Pinata_ +![Como obter o hashcode dos metadados do seu nft no Pinata](./metadataPinata.gif)_Como obter o hashcode dos metadados do seu nft no Pinata_ -> Verifique se o hashcode que você copiou se vincula ao **metadata.json** ao carregar `https://gateway.pinata.cloud/ipfs/` em uma janela separada. A página deve parecer semelhante à imagem abaixo: +> Verifique se o hashcode que você copiou leva ao seu **metadata.json** carregando `https://gateway.pinata.cloud/ipfs/` em uma janela separada. A página deve ser parecida com a captura de tela abaixo: ![Sua página deve exibir os metadados json](./metadataJSON.png)_Sua página deve exibir os metadados json_ -O código deve parecer com isso: +No total, seu código deve se parecer com isto: ```js require("dotenv").config() @@ -272,9 +270,9 @@ const contractAddress = "0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778" const nftContract = new web3.eth.Contract(contract.abi, contractAddress) async function mintNFT(tokenURI) { - const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, "latest") //get latest nonce + const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, "latest") //obter o nonce mais recente - //the transaction + //a transação const tx = { from: PUBLIC_KEY, to: contractAddress, @@ -291,13 +289,13 @@ async function mintNFT(tokenURI) { function (err, hash) { if (!err) { console.log( - "The hash of your transaction is: ", + "O hash de sua transação é: ", hash, - "\nCheck Alchemy's Mempool to view the status of your transaction!" + "\nVerifique o Mempool da Alchemy para ver o status da sua transação!" ) } else { console.log( - "Something went wrong when submitting your transaction:", + "Algo deu errado ao enviar sua transação:", err ) } @@ -305,7 +303,7 @@ async function mintNFT(tokenURI) { ) }) .catch((err) => { - console.log("Promise failed:", err) + console.log("Falha na promessa:", err) }) } @@ -314,16 +312,18 @@ mintNFT("ipfs://QmYueiuRNmL4MiA2GwtVMm6ZagknXnSpQnB3z2gWbz36hP") Agora, execute `node scripts/mint-nft.js` para implantar seu NFT. Depois de alguns segundos, você deverá ver uma resposta como essa no seu terminal: - O hash de sua transação é: 0x301791fdf492001fcd9d5e5b12f3aa1bbbea9a88ed24993a8ab2cdae2d06e1e8 + ``` + O hash da sua transação é: 0x301791fdf492001fcd9d5e5b12f3aa1bbbea9a88ed24993a8ab2cdae2d06e1e8 - Verifique o Mempool da Alquemy para ver o estado da sua transação! + Verifique o Mempool da Alchemy para ver o status da sua transação! + ``` -Em seguida, acesse a [mempool (área de espera) da Alchemy](https://dashboard.alchemyapi.io/mempool) para ver o estado da sua transação (se pendente, minerada ou recusada pela rede). Se a sua transação se perdeu, também é útil verificar no [Sepolia Etherscan](https://sepolia.etherscan.io/) e procurar o hash da transação. +Em seguida, visite o [mempool da Alchemy](https://dashboard.alchemyapi.io/mempool) para ver o status da sua transação (se está pendente, minerada ou foi descartada pela rede). Se sua transação for descartada, também é útil verificar o [Blockscout](https://eth-sepolia.blockscout.com/) e pesquisar pelo hash da sua transação. -![Veja seu hash de transação NFT no Etherscan](./view-nft-etherscan.png)_Veja seu hash de transação NFT no Etherscan_ +![Veja o hash da transação do seu NFT no Etherscan](./view-nft-etherscan.png)_Veja o hash da transação do seu NFT no Etherscan_ -E pronto! Você agora implantou E cunhou um NFT na blockchain Ethereum +E é isso! Você implantou E cunhou um NFT na blockchain Ethereum -Using the `mint-nft.js` you can mint as many NFTs as your heart (and wallet) desires! Apenas certifique-se de transmitir um novo tokenURI descrevendo os metadados do NFT (caso contrário, você acaba criando um monte de identificações idênticas, com IDs diferentes). +Usando o `mint-nft.js`, você pode cunhar quantos NFTs seu coração (e sua carteira) desejar! Apenas certifique-se de passar um novo tokenURI descrevendo os metadados do NFT (caso contrário, você acabará criando um monte de NFTs idênticos com IDs diferentes). -Provavelmente você gostaria de poder exibir seu NFT na sua carteira — então certifique-se de conferir [Parte 3: Como ver seu NFT na sua carteira](/developers/tutorials/how-to-view-nft-in-metamask/)! +Provavelmente, você gostaria de poder exibir seu NFT em sua carteira — então não deixe de conferir a [Parte 3: Como visualizar seu NFT em sua carteira](/developers/tutorials/how-to-view-nft-in-metamask/)! diff --git a/public/content/translations/pt-br/developers/tutorials/how-to-mock-solidity-contracts-for-testing/index.md b/public/content/translations/pt-br/developers/tutorials/how-to-mock-solidity-contracts-for-testing/index.md index 02f4bea1fb4..75db3d8bbfa 100644 --- a/public/content/translations/pt-br/developers/tutorials/how-to-mock-solidity-contracts-for-testing/index.md +++ b/public/content/translations/pt-br/developers/tutorials/how-to-mock-solidity-contracts-for-testing/index.md @@ -1,30 +1,26 @@ --- title: Como simular contratos inteligentes em Solidity para teste -description: Por que você deve aproveitar os seus contratos ao testar +description: "Por que você deve aproveitar os seus contratos ao testar" author: Markus Waas lang: pt-br -tags: - - "solidez" - - "contratos inteligentes" - - "testando" - - "simulando" +tags: [ "Solidity", "smart contracts", "testando", "simulando" ] skill: intermediate published: 2020-05-02 source: soliditydeveloper.com sourceUrl: https://soliditydeveloper.com/mocking-contracts --- -[Mock de objetos ](https://wikipedia.org/wiki/Mock_object) são um padrão de design comum na programação orientada a objetos. Vindo da velha palavra francesa "mocquer" com o significado de "diversão de", evoluiu para a "imitação de algo real", que é na realidade, o que estamos fazendo na programação. Por favor, só se divirta de seus contratos inteligentes se você quiser, mas faça o mock deles sempre que puder. Isso torna sua vida mais fácil. +[Objetos mock](https://wikipedia.org/wiki/Mock_object) são um padrão de design comum na programação orientada a objetos. Vindo da velha palavra francesa "mocquer" com o significado de "diversão de", evoluiu para a "imitação de algo real", que é na realidade, o que estamos fazendo na programação. Por favor, só se divirta de seus contratos inteligentes se você quiser, mas faça o mock deles sempre que puder. Isso torna sua vida mais fácil. -## Testes de unidade de contratos com simulações {#unit-testing-contracts-with-mocks} +## Teste de unidade de contratos com mocks {#unit-testing-contracts-with-mocks} -Simular um contrato (mocking) significa essencialmente criar uma segunda versão desse contrato que se comporta de maneira muito semelhante ao original, mas de uma maneira que pode ser facilmente controlada pelo desenvolvedor. Muitas vezes, você acaba com contratos complexos nos quais você só quer [fazer testes de unidade de pequenas partes do contrato](/developers/docs/smart-contracts/testing/). O problema é: e se o teste desta pequena parte exigir um estado de contrato muito específico que seja difícil de alcançar? +Simular um contrato (mocking) significa essencialmente criar uma segunda versão desse contrato que se comporta de maneira muito semelhante ao original, mas de uma maneira que pode ser facilmente controlada pelo desenvolvedor. Muitas vezes, você acaba com contratos complexos nos quais só quer [fazer o teste de unidade de pequenas partes do contrato](/developers/docs/smart-contracts/testing/). O problema é: e se o teste desta pequena parte exigir um estado de contrato muito específico que seja difícil de alcançar? Você poderia escrever uma lógica de configuração de testes complexa toda vez que apresentasse o contrato no estado necessário ou você escreveria uma simulação (mock, em inglês). Simular um contrato é fácil com herança. Basta criar um segundo contrato mock que herda do original. Agora você pode substituir funções de seu mock. Vejamos com um exemplo. -## Exemplo: ERC20 Privado {#example-private-erc20} +## Exemplo: Private ERC20 {#example-private-erc20} -Usamos um exemplo de contrato ERC-20 que tem um tempo privado inicial. O proprietário pode gerenciar usuários privados e apenas esses terão permissão para receber tokens no início. Uma vez que um certo tempo tenha passado, todos poderão utilizar os tokens. Se você estiver curioso, estamos usando o hook (código modificado) [`_beforeTokenTransfer`](https://docs.openzeppelin.com/contracts/5.x/extending-contracts#using-hooks) dos novos contratos OpenZeppelin v3. +Usamos um exemplo de contrato ERC-20 que tem um tempo privado inicial. O proprietário pode gerenciar usuários privados e apenas esses terão permissão para receber tokens no início. Uma vez que um certo tempo tenha passado, todos poderão utilizar os tokens. Se tiver curiosidade, estamos usando o hook [`_beforeTokenTransfer`](https://docs.openzeppelin.com/contracts/5.x/extending-contracts#using-hooks) dos novos contratos v3 da OpenZeppelin. ```solidity pragma solidity ^0.6.0; @@ -51,7 +47,7 @@ contract PrivateERC20 is ERC20, Ownable { function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override { super._beforeTokenTransfer(from, to, amount); - require(_validRecipient(to), "PrivateERC20: invalid recipient"); + require(_validRecipient(to), "PrivateERC20: destinatário inválido"); } function _validRecipient(address to) private view returns (bool) { @@ -90,17 +86,17 @@ Você receberá uma das seguintes mensagens de erro: - `PrivateERC20Mock.sol: TypeError: Overriding function is missing "override" specifier.` - `PrivateERC20.sol: TypeError: Trying to override non-virtual function. Did you forget to add "virtual"?.` -Como estamos usando a nova versão 0.6 do Solidity, temos que adicionar a palavra-chave `virtual` para funções que podem ser sobrescritas e substituídas pela função substituta. Então vamos adicioná-los para ambas as funções `isPublic`. +Como estamos usando a nova versão 0.6 do Solidity, temos que adicionar a palavra-chave `virtual` para funções que podem ser sobrescritas e `override` para a função de sobrescrita. Então, vamos adicioná-los a ambas as funções `isPublic`. -Agora você pode usar `PrivateERC20Mock` nos seus testes de unidade. Quando você quiser testar o comportamento durante o tempo de uso privado, use `setIsPublic(false)` e, da mesma forma, `setIsPublic(true)` para testar o tempo de uso público. É claro que em nosso exemplo, poderíamos usar simplesmente [auxiliares de tempo](https://docs.openzeppelin.com/test-helpers/0.5/api#increase) para alterar os tempos de acordo também. Mas a ideia de mocking deve estar clara agora e você pode imaginar cenários em que não é tão fácil quanto simplesmente avançar no tempo. +Agora, em seus testes de unidade, você pode usar o `PrivateERC20Mock`. Quando você quiser testar o comportamento durante o tempo de uso privado, use `setIsPublic(false)` e, da mesma forma, `setIsPublic(true)` para testar o tempo de uso público. Claro que, em nosso exemplo, também poderíamos usar [auxiliares de tempo](https://docs.openzeppelin.com/test-helpers/0.5/api#increase) para alterar os horários de acordo. Mas a ideia de mocking deve estar clara agora e você pode imaginar cenários em que não é tão fácil quanto simplesmente avançar no tempo. -## Mocking em muitos contratos {#mocking-many-contracts} +## Fazendo mock de muitos contratos {#mocking-many-contracts} -Pode ficar confuso se você tiver que criar outro contrato para cada mock. Se isso incomoda você, dê uma olhada na biblioteca [MockContract](https://github.com/gnosis/mock-contract). Ele permite que você sobrescreva e modifique comportamentos de contratos em tempo real. No entanto, ele só funciona para chamadas mocking para outro contrato, portanto, não funcionaria para o nosso exemplo. +Pode ficar confuso se você tiver que criar outro contrato para cada mock. Se isso o incomoda, você pode dar uma olhada na biblioteca [MockContract](https://github.com/gnosis/mock-contract). Ele permite que você sobrescreva e modifique comportamentos de contratos em tempo real. No entanto, ele só funciona para chamadas mocking para outro contrato, portanto, não funcionaria para o nosso exemplo. -## Mocking podem ser ainda mais poderosas {#mocking-can-be-even-more-powerful} +## O mocking pode ser ainda mais poderoso {#mocking-can-be-even-more-powerful} Os poderes de mocking não terminam aí. -- Adicionando funções: sobrescrever uma função específica é útil, mas apenas acrescentar funções adicionais também poderá ser. Um bom exemplo para tokens é ter apenas uma função adicional `mint` para permitir que qualquer usuário obtenha novos tokens gratuitamente. +- Adicionando funções: sobrescrever uma função específica é útil, mas apenas acrescentar funções adicionais também poderá ser. Um bom exemplo para tokens é simplesmente ter uma função `mint` adicional para permitir que qualquer usuário obtenha novos tokens gratuitamente. - Uso em testnets: ao implantar e testar seus contratos em testnets juntamente com seu Dapp, considere usar uma versão mock. Evite sobrescrever funções, a menos que você realmente precise. Afinal, você quer testar a lógica real. Mas adicionar, por exemplo, uma função de redefinição pode ser útil que simplesmente redefine o estado do contrato para o início, sem necessidade de nova implantação. Obviamente, você não gostaria de ter isso em um contrato na mainnet (rede principal). diff --git a/public/content/translations/pt-br/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/index.md b/public/content/translations/pt-br/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/index.md index 3cb13dcff28..8c54fb967c0 100644 --- a/public/content/translations/pt-br/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/index.md +++ b/public/content/translations/pt-br/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/index.md @@ -4,31 +4,33 @@ description: Como usar o Echidna para testar automaticamente contratos inteligen author: "Trailofbits" lang: pt-br tags: - - "solidez" - - "smart contracts" - - "segurança" - - "testando" - - "fuzzing" + [ + "Solidity", + "smart contracts", + "segurança", + "testando", + "fuzzing" + ] skill: advanced published: 2020-04-10 -source: Construindo contratos seguros +source: Building secure contracts sourceUrl: https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/echidna --- ## Instalação {#installation} -Echidna pode ser instalado através do docker ou usando o binário pré-compilado. +O Echidna pode ser instalado através do docker ou usando o binário pré-compilado. -### Echidna com docker {#echidna-through-docker} +### Echidna através do docker {#echidna-through-docker} ```bash docker pull trailofbits/eth-security-toolbox docker run -it -v "$PWD":/home/training trailofbits/eth-security-toolbox ``` -_O último comando roda a eth-security-toolbox em um docker que tem acesso ao seu diretório atual. Você pode alterar os arquivos do seu host e executar as ferramentas nos arquivos através do docker_ +_O último comando executa o eth-security-toolbox em um docker que tem acesso ao seu diretório atual. Você pode alterar os arquivos do seu host e executar as ferramentas nos arquivos do docker_ -Dentro do docker, execute : +Dentro do docker, execute: ```bash solc-select 0.5.11 @@ -39,33 +41,33 @@ cd /home/training [https://github.com/crytic/echidna/releases/tag/v1.4.0.0](https://github.com/crytic/echidna/releases/tag/v1.4.0.0) -## Introdução a fuzzing baseado em propriedade {#introduction-to-property-based-fuzzing} +## Introdução ao fuzzing baseado em propriedade {#introduction-to-property-based-fuzzing} -Echidna é um fuzzer baseado em propriedades, descrevemos em nossos posts anteriores ([1](https://blog.trailofbits.com/2018/03/09/echidna-a-smart-fuzzer-for-ethereum/), [2](https://blog.trailofbits.com/2018/05/03/state-machine-testing-with-echidna/), [3](https://blog.trailofbits.com/2020/03/30/an-echidna-for-all-seasons/)). +O Echidna é um fuzzer baseado em propriedade, que descrevemos em nossas postagens de blog anteriores ([1](https://blog.trailofbits.com/2018/03/09/echidna-a-smart-fuzzer-for-ethereum/), [2](https://blog.trailofbits.com/2018/05/03/state-machine-testing-with-echidna/), [3](https://blog.trailofbits.com/2020/03/30/an-echidna-for-all-seasons/)). ### Fuzzing {#fuzzing} -[Fuzzing](https://wikipedia.org/wiki/Fuzzing) é uma técnica bem conhecida na comunidade de segurança. It consists of generating inputs that are more or less random to find bugs in the program. Fuzzers por software tradicional (como [AFL](http://lcamtuf.coredump.cx/afl/) ou [LibFuzzer](https://llvm.org/docs/LibFuzzer.html)) são conhecidos por serem ferramentas eficientes para encontrar bugs. +[Fuzzing](https://wikipedia.org/wiki/Fuzzing) é uma técnica bem conhecida na comunidade de segurança. Consiste em gerar entradas que são mais ou menos aleatórias para encontrar bugs no programa. Fuzzers para software tradicional (como [AFL](http://lcamtuf.coredump.cx/afl/) ou [LibFuzzer](https://llvm.org/docs/LibFuzzer.html)) são conhecidos por serem ferramentas eficientes para encontrar bugs. -Além da geração aleatória de entradas, há muitas técnicas e estratégias para gerar bons inputs, incluindo: +Além da geração puramente aleatória de entradas, existem muitas técnicas e estratégias para gerar boas entradas, incluindo: -- Obtenha feedback de cada execução e geração de guias usando-o. Por exemplo, se uma entrada recém-gerada leva à descoberta de um novo caminho, ele pode fazer sentido para gerar novas entradas fechadas a ele. -- Geração da entrada respeitando uma restrição estrutural. Por exemplo, se a sua entrada contiver um cabeçalho com uma soma de verificação, fará sentido deixar o difusor gerar uma entrada validando a soma de verificação. -- Usando entradas conhecidas para gerar novas entradas: se você tem acesso a um grande conjunto de dados de entrada válida, seu difusor pode gerar novas entradas a partir deles, ao invés de começar sua geração do zero. Eles geralmente são chamados de _seeds_. +- Obter feedback de cada execução e usá-lo para guiar a geração. Por exemplo, se uma entrada recém-gerada levar à descoberta de um novo caminho, pode fazer sentido gerar novas entradas próximas a ela. +- Gerar a entrada respeitando uma restrição estrutural. Por exemplo, se sua entrada contiver um cabeçalho com um checksum, fará sentido deixar que o fuzzer gere uma entrada que valide o checksum. +- Usar entradas conhecidas para gerar novas entradas: se você tiver acesso a um grande conjunto de dados de entrada válida, seu fuzzer pode gerar novas entradas a partir deles, em vez de iniciar sua geração do zero. Normalmente, são chamadas de _seeds_. ### Fuzzing baseado em propriedade {#property-based-fuzzing} -Echidna pertence a uma família específica de fuzzer: fuzzing baseada em propriedades fortemente inspirada pelo [QuickCheck](https://wikipedia.org/wiki/QuickCheck). Em contraste com o fuzzing clássico que tentará encontrar falhas, Echidna tentará quebrar invariantes definidos pelo usuário. +O Echidna pertence a uma família específica de fuzzer: fuzzing baseado em propriedade, fortemente inspirado pelo [QuickCheck](https://wikipedia.org/wiki/QuickCheck). Em contraste com o fuzzer clássico, que tentará encontrar falhas, o Echidna tentará quebrar invariantes definidos pelo usuário. -Nos contratos inteligentes, invariantes são funções Solidity, que podem representar qualquer estado incorreto ou inválido que o contrato possa alcançar, incluindo: +Em contratos inteligentes, as invariantes são funções do Solidity que podem representar qualquer estado incorreto ou inválido que o contrato possa alcançar, incluindo: -- Controle de acesso incorreto: quem ataca tornou-se o proprietário do contrato. -- Máquina de estado incorreta: os tokens podem ser transferidos enquanto o contrato é pausado. -- Aritmética incorreta: o usuário pode passar abaixo do saldo e obter tokens gratuitos ilimitados. +- Controle de acesso incorreto: o invasor tornou-se o proprietário do contrato. +- Máquina de estado incorreta: os tokens podem ser transferidos enquanto o contrato está pausado. +- Aritmética incorreta: o usuário pode causar um underflow em seu saldo e obter tokens gratuitos ilimitados. -### Testando uma propriedade com Echidna {#testing-a-property-with-echidna} +### Testando uma propriedade com o Echidna {#testing-a-property-with-echidna} -Veremos como testar um contrato inteligente com o Echidna. O alvo é o seguinte contrato inteligente [`exemplo.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/token.sol): +Veremos como testar um contrato inteligente com o Echidna. O alvo é o seguinte contrato inteligente [`token.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/token.sol): ```solidity contract Token{ @@ -83,26 +85,26 @@ contract Token{ } ``` -Assumiremos que esse token deve ter as seguintes propriedades: +Vamos supor que este token deva ter as seguintes propriedades: -- Qualquer um pode ter no máximo 1000 tokens +- Qualquer pessoa pode ter no máximo 1.000 tokens - O token não pode ser transferido (não é um token ERC20) -### Escrever uma propriedade {#write-a-property} +### Escreva uma propriedade {#write-a-property} -Propriedades do Echidna são funções de Solidity. Uma propriedade deve: +As propriedades do Echidna são funções do Solidity. Uma propriedade deve: -- Ter nenhum argumento -- Retornar `verdadeiro` se for bem sucedido -- Tenha seu nome começando com `echidna` +- Não ter argumentos +- Retornar `true` se for bem-sucedida +- Ter seu nome começando com `echidna` -Echidna irá: +O Echidna irá: -- Gera automaticamente transações arbitrárias para testar a propriedade. -- Relata quaisquer transações que levem uma propriedade para retornar `` falso ou lançar um erro. -- Descartar efeito lateral ao chamar uma propriedade (ou seja, se a propriedade altera uma variável de estado, ela é descartada após o teste) +- Gerar automaticamente transações arbitrárias para testar a propriedade. +- Relatar quaisquer transações que levem uma propriedade a retornar `false` ou a lançar um erro. +- Descartar o efeito colateral ao chamar uma propriedade (ou seja, se a propriedade alterar uma variável de estado, ela será descartada após o teste) -A propriedade a seguir verifica que o "caller" não possui mais do que 1000 tokens: +A propriedade a seguir verifica se o chamador não tem mais de 1.000 tokens: ```solidity function echidna_balance_under_1000() public view returns(bool){ @@ -120,36 +122,36 @@ contract TestToken is Token{ } ``` -[`token.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/token.sol) implementa a propriedade e herda do token. +O [`token.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/token.sol) implementa a propriedade e herda do token. ### Iniciar um contrato {#initiate-a-contract} -Echidna precisa de um [constructor](/developers/docs/smart-contracts/anatomy/#constructor-functions) sem argumento. Se seu contrato precisa de uma inicialização específica, você precisa fazê-lo no construtor. +O Echidna precisa de um [construtor](/developers/docs/smart-contracts/anatomy/#constructor-functions) sem argumentos. Se seu contrato precisar de uma inicialização específica, você precisará fazê-la no construtor. -Há alguns endereços específicos no Echidna: +Existem alguns endereços específicos no Echidna: -- `0x00a329c0648769A73afAc7F9381E08FB43dBEA72` que chama o constructor. -- `0x10000`, `0x20000`, e `0x00a329C0648769a73afAC7F9381e08fb43DBEA70` que aleatoriamente chama as outras funções. +- `0x00a329c0648769A73afAc7F9381E08FB43dBEA72`, que chama o construtor. +- `0x10000`, `0x20000` e `0x00a329C0648769a73afAC7F9381e08fb43DBEA70`, que chamam aleatoriamente as outras funções. -Nós não precisamos de nenhuma inicialização específica em nosso exemplo atual, como resultado, nosso construtor está vazio. +Não precisamos de nenhuma inicialização específica em nosso exemplo atual, como resultado, nosso construtor está vazio. -### Executando Echidna {#run-echidna} +### Executar o Echidna {#run-echidna} -Echidna foi lançado com: +O Echidna é iniciado com: ```bash echidna-test contract.sol ``` -Se o contract.sol contém múltiplos contratos, você pode especificar o alvo: +Se contract.sol contiver vários contratos, você pode especificar o alvo: ```bash echidna-test contract.sol --contract MyContract ``` -### Resumo: Testando uma propriedade {#summary-testing-a-property} +### Resumo: testando uma propriedade {#summary-testing-a-property} -O seguinte resumo é a execução de Echidna no nosso exemplo: +O texto a seguir resume a execução do Echidna em nosso exemplo: ```solidity contract TestToken is Token{ @@ -164,19 +166,20 @@ contract TestToken is Token{ echidna-test testtoken.sol --contract TestToken ... -echidna_balance_under_1000: failed!💥 - Call sequence, shrinking (1205/5000): +echidna_balance_under_1000: falhou!💥 + Sequência de chamadas, encolhendo (1205/5000): airdrop() backdoor() ... ``` -Echidna descobriu que a propriedade é violada se `backdoor` é chamada. +O Echidna descobriu que a propriedade é violada se `backdoor` for chamado. ## Filtrando funções para chamar durante uma campanha de fuzzing {#filtering-functions-to-call-during-a-fuzzing-campaign} -Veremos como filtrar as funções a serem "fuzzed". O alvo é o seguinte contrato inteligente: +Veremos como filtrar as funções que sofrerão fuzzing. +O alvo é o seguinte contrato inteligente: ```solidity contract C { @@ -227,56 +230,60 @@ contract C { } ``` -Este pequeno exemplo força Echidna a encontrar uma determinada sequência de transações para alterar uma variável de estado. Isso é difícil para um fuzzer (é recomendado usar uma ferramenta de execução simbólica como [Manticore](https://github.com/trailofbits/manticore)). Podemos executar o Echidna para verificar isto: +Este pequeno exemplo força o Echidna a encontrar uma determinada sequência de transações para alterar uma variável de estado. +Isso é difícil para um fuzzer (recomenda-se usar uma ferramenta de execução simbólica como o [Manticore](https://github.com/trailofbits/manticore)). +Podemos executar o Echidna para verificar isso: ```bash echidna-test multi.sol ... -echidna_state4: passed! 🎉 +echidna_state4: passou! 🎉 Seed: -3684648582249875403 ``` -### Filtrando funções {#filtering-functions} +### Funções de filtragem {#filtering-functions} -Echidna tem problemas para encontrar a sequência correta para testar esse contrato, porque as duas funções de redefinição (`reset1` e `reset2`) definirão todas as variáveis de estado como `false`. No entanto, podemos usar um recurso especial Echidna para ou para a lista negra redefinir a função ou apenas para a lista branca `f`, `g`, `h` e `i` funções. +O Echidna tem dificuldade em encontrar a sequência correta para testar este contrato porque as duas funções de redefinição (`reset1` e `reset2`) definirão todas as variáveis de estado como `false`. +No entanto, podemos usar um recurso especial do Echidna para adicionar as funções de redefinição à lista de bloqueio ou para adicionar apenas as funções `f`, `g`, +`h` e `i` à lista de permissões. -Para funções da lista negra, podemos usar esse arquivo de configuração: +Para adicionar funções à lista de bloqueio, podemos usar este arquivo de configuração: ```yaml filterBlacklist: true filterFunctions: ["reset1", "reset2"] ``` -Outra abordagem para as funções de filtro é listar as funções na lista branca. Para fazer isso, podemos usar este arquivo de configuração: +Outra abordagem para filtrar funções é listar as funções permitidas. Para fazer isso, podemos usar este arquivo de configuração: ```yaml filterBlacklist: false filterFunctions: ["f", "g", "h", "i"] ``` -- `filterBlacklist` é `verdadeiro` por padrão. -- A filtragem será executada apenas por nome (sem parâmetros). Se você tiver `f()` e `f(uint256)`, o filtro `"f"` corresponderá a ambas as funções. +- `filterBlacklist` é `true` por padrão. +- A filtragem será realizada apenas por nome (sem parâmetros). Se você tiver `f()` e `f(uint256)`, o filtro `"f"` corresponderá a ambas as funções. -### Executar Echidna {#run-echidna-1} +### Executar o Echidna {#run-echidna-1} -Para executar Echidna com um arquivo de configuração `blacklist.yaml`: +Para executar o Echidna com um arquivo de configuração `blacklist.yaml`: ```bash echidna-test multi.sol --config blacklist.yaml ... -echidna_state4: failed!💥 - Call sequence: +echidna_state4: falhou!💥 + Sequência de chamadas: f(12) g(8) h(42) i() ``` -Echidna vai encontrar a sequência de transações para falsificar a propriedade quase de forma mesquinha. +O Echidna encontrará a sequência de transações para falsear a propriedade quase imediatamente. -### Resumo: Filtrando funções {#summary-filtering-functions} +### Resumo: funções de filtragem {#summary-filtering-functions} -Echidna pode ser chamada na lista negra ou na lista branca durante uma campanha de fuzzing: +O Echidna pode adicionar funções a uma lista de bloqueio ou a uma lista de permissões para chamar durante uma campanha de fuzzing usando: ```yaml filterBlacklist: true @@ -288,11 +295,11 @@ echidna-test contract.sol --config config.yaml ... ``` -Echidna inicia uma campanha de fuzzing em qualquer blacklist `f1`, `f2` e `f3` ou apenas chamando a eles, de acordo com o valor do booleano `filterBlacklist`. +O Echidna inicia uma campanha de fuzzing adicionando `f1`, `f2` e `f3` à lista de bloqueio ou chamando apenas essas funções, de acordo com o valor do booleano `filterBlacklist`. -## Como testar a asserção de Solidity com Echidna {#how-to-test-soliditys-assert-with-echidna} +## Como testar a asserção do Solidity com o Echidna {#how-to-test-soliditys-assert-with-echidna} -Neste breve tutorial, vamos mostrar como usar o Echidna para testar a verificação de asserção em contratos. Vamos supor que tenhamos um contrato como este: +Neste breve tutorial, vamos mostrar como usar o Echidna para testar a verificação de asserções em contratos. Vamos supor que tenhamos um contrato como este: ```solidity contract Incrementor { @@ -307,9 +314,10 @@ contract Incrementor { } ``` -### Escreva uma asserção {#write-an-assertion} +### Escrever uma asserção {#write-an-assertion} -Queremos ter certeza de que `tmp` é menor ou igual a `contador` depois de retornar a sua diferença. Nós poderíamos escrever uma propriedade de Echidna, mas precisaremos armazenar o valor de `tmp` em algum lugar. Em vez disso, poderíamos usar uma asserção como esta: +Queremos ter certeza de que `tmp` é menor ou igual a `counter` depois de retornar sua diferença. Poderíamos escrever uma +propriedade do Echidna, mas precisaríamos armazenar o valor `tmp` em algum lugar. Em vez disso, poderíamos usar uma asserção como esta: ```solidity contract Incrementor { @@ -324,15 +332,15 @@ contract Incrementor { } ``` -### Executando Echidna {#run-echidna-2} +### Executar o Echidna {#run-echidna-2} -Para habilitar o teste de falha de asserção, crie um arquivo de configuração [Echidna](https://github.com/crytic/echidna/wiki/Config) `config.yaml`: +Para habilitar o teste de falha de asserção, crie um [arquivo de configuração do Echidna](https://github.com/crytic/echidna/wiki/Config) `config.yaml`: ```yaml checkAsserts: true ``` -Quando executamos este contrato em Echidna, obtemos os resultados esperados: +Quando executamos este contrato no Echidna, obtemos os resultados esperados: ```bash echidna-test assert.sol --config config.yaml @@ -346,11 +354,11 @@ assertion in inc: failed!💥 Seed: 1806480648350826486 ``` -Como você pode ver, Echidna relata algumas falhas de afirmação na função `inc`. Adicionar mais de uma asserção por função é possível, mas Echidna não pode dizer qual afirmação falhou. +Como você pode ver, o Echidna relata alguma falha de asserção na função `inc`. Adicionar mais de uma asserção por função é possível, mas o Echidna não consegue dizer qual asserção falhou. ### Quando e como usar asserções {#when-and-how-use-assertions} -As asserções podem ser usadas como alternativas às propriedades explícitas, se as condições a serem verificadas estão diretamente relacionadas com o uso correto de alguma operação `f`. Adicionar asserções após algum código forçará que a verificação ocorra imediatamente após sua execução: +As asserções podem ser usadas como alternativas a propriedades explícitas, especialmente se as condições a serem verificadas estiverem diretamente relacionadas ao uso correto de alguma operação `f`. Adicionar asserções após algum código garantirá que a verificação ocorra imediatamente após sua execução: ```solidity function f(..) public { @@ -362,7 +370,7 @@ function f(..) public { ``` -Pelo contrário, usando uma propriedade Echidna explícita irá executar transações aleatoriamente e não há maneira fácil de aplicar exatamente quando elas serão verificadas. Ainda é possível fazer esta solução alternativa: +Pelo contrário, o uso de uma propriedade explícita do Echidna executará transações aleatoriamente e não há uma maneira fácil de forçar exatamente quando ela será verificada. Ainda é possível fazer esta solução alternativa: ```solidity function echidna_assert_after_f() public returns (bool) { @@ -371,22 +379,22 @@ function echidna_assert_after_f() public returns (bool) { } ``` -Entretanto, existem alguns problemas: %\{issues}: +No entanto, há alguns problemas: -- Ele falha se `f` é declarado como `interno` ou `externo`. +- Falha se `f` for declarada como `internal` ou `external`. - Não está claro quais argumentos devem ser usados para chamar `f`. -- Se `f` reverter, a propriedade irá falhar. +- Se `f` reverter, a propriedade falhará. -Em geral, recomendamos seguir a recomendação de [John Regehr](https://blog.regehr.org/archives/1091) sobre como usar asserções: +Em geral, recomendamos seguir a [recomendação de John Regehr](https://blog.regehr.org/archives/1091) sobre como usar asserções: -- Não force qualquer efeito colateral durante a verificação de asserção. Por exemplo: `assert(ChangeStateAndReturn() == 1)` +- Não force nenhum efeito colateral durante a verificação de asserção. Por exemplo: `assert(ChangeStateAndReturn() == 1)` - Não faça asserções óbvias. Por exemplo, `assert(var >= 0)` onde `var` é declarado como `uint`. -Finalmente, **não use** `require` em vez de `assert`, já que Echidna não será capaz de detectá-lo (mas o contrato será revertido mesmo assim). +Finalmente, **não use** `require` em vez de `assert`, pois o Echidna não será capaz de detectá-lo (mas o contrato será revertido de qualquer maneira). -### Resumo: checando a asserção {#summary-assertion-checking} +### Resumo: verificação de asserção {#summary-assertion-checking} -O seguinte resumo é a execução de Echidna no nosso exemplo: +O texto a seguir resume a execução do Echidna em nosso exemplo: ```solidity contract Incrementor { @@ -413,11 +421,11 @@ assertion in inc: failed!💥 Seed: 1806480648350826486 ``` -Echidna percebeu que a asserção em `inc` pode falhar se essa função é chamada várias vezes com argumentos grandes. +O Echidna descobriu que a asserção em `inc` pode falhar se essa função for chamada várias vezes com argumentos grandes. -## Coletando e modificando um corpus Echidna {#collecting-and-modifying-an-echidna-corpus} +## Coletando e modificando um corpus do Echidna {#collecting-and-modifying-an-echidna-corpus} -Veremos como coletar e usar um corpus de transações com Echidna. O alvo é o seguinte contrato inteligente [`exemplo.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/magic.sol): +Veremos como coletar e usar um corpus de transações com o Echidna. O alvo é o seguinte contrato inteligente [`magic.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/magic.sol): ```solidity contract C { @@ -437,41 +445,44 @@ contract C { } ``` -Este pequeno exemplo força Echidna a encontrar uma determinada sequência de transações para alterar uma variável de estado. Isso é difícil para um fuzzer (é recomendado usar uma ferramenta de execução simbólica como [Manticore](https://github.com/trailofbits/manticore)). Podemos executar o Echidna para verificar isto: +Este pequeno exemplo força o Echidna a encontrar determinados valores para alterar uma variável de estado. Isso é difícil para um fuzzer +(recomenda-se usar uma ferramenta de execução simbólica como o [Manticore](https://github.com/trailofbits/manticore)). +Podemos executar o Echidna para verificar isso: ```bash echidna-test magic.sol ... -echidna_magic_values: passed! 🎉 +echidna_magic_values: passou! 🎉 Seed: 2221503356319272685 ``` -No entanto, ainda podemos usar o Echidna para coletar corpus na condução desta campanha de fuzzing. +No entanto, ainda podemos usar o Echidna para coletar o corpus ao executar esta campanha de fuzzing. ### Coletando um corpus {#collecting-a-corpus} -Para habilitar a coleção de corpus, crie um diretório corpus: +Para habilitar a coleta de corpus, crie um diretório de corpus: ```bash mkdir corpus-magic ``` -E um [arquivo de configuração Echidna](https://github.com/crytic/echidna/wiki/Config) `config.yaml`: +E um [arquivo de configuração do Echidna](https://github.com/crytic/echidna/wiki/Config) `config.yaml`: ```yaml coverage: true corpusDir: "corpus-magic" ``` -Agora podemos rodar nossa ferramenta e checar o corpus coletado: +Agora podemos executar nossa ferramenta e verificar o corpus coletado: ```bash echidna-test magic.sol --config config.yaml ``` -Echidna ainda não conseguiu encontrar os valores mágicos corretos, mas podemos olhar para o corpus que ele coletou. Por exemplo, um desses arquivos foi: +O Echidna ainda não consegue encontrar os valores mágicos corretos, mas podemos dar uma olhada no corpus que ele coletou. +Por exemplo, um desses arquivos era: ```json [ @@ -516,17 +527,18 @@ Echidna ainda não conseguiu encontrar os valores mágicos corretos, mas podemos ] ``` -Claramente, esse input não causará falha em nossa propriedade. No entanto, no próximo passo, veremos como modificá-lo nesse sentido. +Claramente, essa entrada não acionará a falha em nossa propriedade. No entanto, na próxima etapa, veremos como modificá-lo para isso. ### Semeando um corpus {#seeding-a-corpus} -Echidna precisa de ajuda para lidar com a função `mágica`. Vamos copiar e modificar a entrada para usar os parâmetros adequados para ele: +O Echidna precisa de ajuda para lidar com a função `magic`. Vamos copiar e modificar a entrada para usar parâmetros +adequados para ela: ```bash cp corpus/2712688662897926208.txt corpus/new.txt ``` -Nós iremos modificar `new.txt` para chamar `mágica(42,129,333,0)`. Agora, podemos reexecutar o Echidna: +Modificaremos o `new.txt` para chamar `magic(42,129,333,0)`. Agora, podemos executar novamente o Echidna: ```bash echidna-test magic.sol --config config.yaml @@ -542,11 +554,11 @@ Seed: -7293830866560616537 ``` -Desta vez, constatou que a propriedade é violada imediatamente. +Desta vez, descobriu que a propriedade é violada imediatamente. -## Localizando transações com alto consumo de gas {#finding-transactions-with-high-gas-consumption} +## Encontrando transações com alto consumo de gás {#finding-transactions-with-high-gas-consumption} -Veremos como encontrar as transações com alto consumo de gas com o Echidna. O alvo é o seguinte contrato inteligente: +Veremos como encontrar as transações com alto consumo de gás com o Echidna. O alvo é o seguinte contrato inteligente: ```solidity contract C { @@ -571,21 +583,22 @@ contract C { } ``` -Aqui `caro` pode ter um grande consumo de gas. +Aqui, `expensive` pode ter um grande consumo de gás. -Atualmente, Echidna sempre precisa de uma propriedade para testar: aqui `echidna_test` sempre retorna `true`. Podemos executar o Echidna para verificar isto: +Atualmente, o Echidna sempre precisa de uma propriedade para testar: aqui, `echidna_test` sempre retorna `true`. +Podemos executar o Echidna para verificar isso: ``` echidna-test gas.sol ... -echidna_test: passed! 🎉 +echidna_test: passou! 🎉 Seed: 2320549945714142710 ``` -### Medição do consumo de gas {#measuring-gas-consumption} +### Medindo o consumo de gás {#measuring-gas-consumption} -Para habilitar o consumo de gas com Echidna, crie um arquivo de configuração `config.yaml`: +Para habilitar o consumo de gás com o Echidna, crie um arquivo de configuração `config.yaml`: ```yaml estimateGas: true @@ -598,9 +611,9 @@ seqLen: 2 estimateGas: true ``` -### Executando Echidna {#run-echidna-3} +### Executar o Echidna {#run-echidna-3} -Assim que tivermos o arquivo de configuração criado, poderemos executar o Echidna assim: +Depois que o arquivo de configuração for criado, podemos executar o Echidna desta forma: ```bash echidna-test gas.sol --config config.yaml @@ -617,12 +630,14 @@ Seed: -325611019680165325 ``` -- O gas mostrado é um cálculo fornecido por [HEVM](https://github.com/dapphub/dapptools/tree/master/src/hevm#hevm-). +- O gás mostrado é uma estimativa fornecida pelo [HEVM](https://github.com/dapphub/dapptools/tree/master/src/hevm#hevm-). -### Filtrando Chamadas com Redução de Gas {#filtering-out-gas-reducing-calls} +### Filtrando chamadas que reduzem o gás {#filtering-out-gas-reducing-calls} -O tutorial sobre **funções de filtragem para chamar durante uma campanha de difusão** acima mostra como remover algumas funções de seu teste. -Isso pode ser fundamental para obter uma estimativa de gas precisa. Considere o seguinte exemplo: +O tutorial sobre **como filtrar funções a serem chamadas durante uma campanha de fuzzing**, acima, mostra como +remover algumas funções do seu teste. +Isso pode ser crítico para obter uma estimativa de gás precisa. +Considere o seguinte exemplo: ```solidity contract C { @@ -648,7 +663,7 @@ contract C { } ``` -Se Echidna pode chamar todas as funções, ele não encontrará facilmente transações com alto custo de gas: +Se o Echidna puder chamar todas as funções, ele não encontrará facilmente transações com alto custo de gás: ``` echidna-test pushpop.sol --config config.yaml @@ -662,7 +677,8 @@ clear used a maximum of 35916 gas push used a maximum of 40839 gas ``` -Isso porque o custo depende do tamanho dos `addrs` e chamadas aleatórias tendem a deixar o array quase vazio. Lista negra `pop` e `limpa`, no entanto, nos dá resultados muito melhores: +Isso porque o custo depende do tamanho de `addrs` e chamadas aleatórias tendem a deixar o array quase vazio. +Isso ocorre porque o custo depende do tamanho de `addrs` e as chamadas aleatórias tendem a deixar o array quase vazio. Adicionar `pop` e `clear` à lista de bloqueio, no entanto, nos dá resultados muito melhores: ```yaml filterBlacklist: true @@ -677,9 +693,9 @@ push used a maximum of 40839 gas check used a maximum of 1484472 gas ``` -### Localizando transações com alto consumo de gás {#summary-finding-transactions-with-high-gas-consumption} +### Resumo: encontrando transações com alto consumo de gás {#summary-finding-transactions-with-high-gas-consumption} -Echidna pode encontrar transações com alto consumo de gás usando a opção de configuração `estimateGas`: +O Echidna pode encontrar transações com alto consumo de gás usando a opção de configuração `estimateGas`: ```yaml estimateGas: true @@ -690,4 +706,4 @@ echidna-test contract.sol --config config.yaml ... ``` -Echidna irá relatar uma sequência com o consumo máximo de gas para cada função, uma vez terminada a campanha de fuzzing. +O Echidna relatará uma sequência com o consumo máximo de gás para cada função, uma vez que a campanha de fuzzing tenha terminado. diff --git a/public/content/translations/pt-br/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/index.md b/public/content/translations/pt-br/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/index.md index 3382b47b034..c24bd70e257 100644 --- a/public/content/translations/pt-br/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/index.md +++ b/public/content/translations/pt-br/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/index.md @@ -1,17 +1,19 @@ --- title: Como usar o Manticore para encontrar bugs em contratos inteligentes -description: Como usar o Manticore para encontrar bugs automaticamente em contratos inteligentes +description: Como usar o Manticore para encontrar bugs em contratos inteligentes automaticamente author: Trailofbits lang: pt-br tags: - - "solidez" - - "smart contracts" - - "segurança" - - "testando" - - "verificação formal" + [ + "Solidity", + "smart contracts", + "segurança", + "testando", + "verificação formal" + ] skill: advanced published: 2020-01-13 -source: Construindo contratos seguros +source: Building secure contracts sourceUrl: https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/manticore --- @@ -19,16 +21,16 @@ O objetivo deste tutorial é mostrar como usar o Manticore para encontrar bugs e ## Instalação {#installation} -Manticore requer >= python 3.6. Pode ser instalado pelo pip ou usando o docker. +Manticore requer >= python 3.6. Pode ser instalado via pip ou usando o docker. -### Manticore através do Docker {#manticore-through-docker} +### Manticore via docker {#manticore-through-docker} ```bash docker pull trailofbits/eth-security-toolbox docker run -it -v "$PWD":/home/training trailofbits/eth-security-toolbox ``` -_O último comando roda a eth-security-toolbox em um docker que tem acesso ao seu diretório atual. Você pode alterar os arquivos do seu host e executar as ferramentas nos arquivos através do docker_ +_O último comando executa o eth-security-toolbox em um docker que tem acesso ao seu diretório atual. Você pode alterar os arquivos do seu host e executar as ferramentas nos arquivos do docker_ Dentro do docker, execute: @@ -37,7 +39,7 @@ solc-select 0.5.11 cd /home/trufflecon/ ``` -### Manticore através do pip {#manticore-through-pip} +### Manticore via pip {#manticore-through-pip} ```bash pip3 install --user manticore @@ -55,18 +57,18 @@ python3 script.py ## Introdução à execução simbólica dinâmica {#introduction-to-dynamic-symbolic-execution} -### Execução Simbólica Dinâmica em uma Nutshell {#dynamic-symbolic-execution-in-a-nutshell} +### Execução Simbólica Dinâmica em poucas palavras {#dynamic-symbolic-execution-in-a-nutshell} -A execução simbólica dinâmica (DSE) é uma técnica de análise de programa que explora um espaço de estado com um alto grau de consciência semântica. Esta técnica baseia-se na descoberta de "caminhos do programa", representados como fórmulas matemáticas chamadas de `predicados de caminho`. Conceitualmente, esta técnica opera em predicados de caminho em dois passos: +A execução simbólica dinâmica (DSE) é uma técnica de análise de programa que explora um espaço de estado com um alto grau de consciência semântica. Esta técnica é baseada na descoberta de "caminhos de programa", representados como fórmulas matemáticas chamadas de `predicados de caminho`. Conceitualmente, esta técnica opera em predicados de caminho em duas etapas: -1. Eles são construídos usando restrições na entrada de dados do programa. -2. Eles são usados para gerar entradas no programa que farão com que os caminhos associados sejam executados. +1. Eles são construídos usando restrições na entrada do programa. +2. Eles são usados para gerar entradas de programa que farão com que os caminhos associados sejam executados. -Esta abordagem não produz falsos positivos no sentido de que todos os estados identificados do programa podem ser acionados durante a execução concreta. Por exemplo, se a análise encontrar um integer overflow, é certo que será reproduzível. +Esta abordagem não produz falsos positivos, no sentido de que todos os estados de programa identificados podem ser acionados durante a execução concreta. Por exemplo, se a análise encontrar um integer overflow, é garantido que será reproduzível. -### Exemplo de Predicado do Caminho {#path-predicate-example} +### Exemplo de Predicado de Caminho {#path-predicate-example} -Para se ter uma idéia de como o DSE funciona, considere o seguinte exemplo: +Para ter uma ideia de como o DSE funciona, considere o seguinte exemplo: ```solidity function f(uint a){ @@ -78,37 +80,37 @@ function f(uint a){ } ``` -Como `f()` contém dois caminhos, uma DSE construirá dois caminhos diferentes atribuídos: +Como `f()` contém dois caminhos, um DSE construirá dois predicados de caminho diferentes: - Caminho 1: `a == 65` - Caminho 2: `Not (a == 65)` -Cada caminho atribuido é uma fórmula matemática que pode ser dada a uma chamada [SMT solver](https://wikipedia.org/wiki/Satisfiability_modulo_theories), que tentará resolver a equação. Para o `Caminho 1`, o solver dirá que o caminho pode ser explorado com `a = 65`. Para o `Caminho 2`, o solver pode dar para `a` qualquer valor diferente de 65, por exemplo, `a = 0`. +Cada predicado de caminho é uma fórmula matemática que pode ser fornecida a um chamado [solucionador SMT](https://wikipedia.org/wiki/Satisfiability_modulo_theories), que tentará resolver a equação. Para o `Caminho 1`, o solucionador dirá que o caminho pode ser explorado com `a = 65`. Para o `Caminho 2`, o solucionador pode atribuir a `a` qualquer valor diferente de 65, por exemplo `a = 0`. ### Verificando propriedades {#verifying-properties} -A Manticore permite um controle total sobre toda a execução de cada caminho. Como resultado, permite que você adicione restrições arbitrárias a quase qualquer coisa. Este controle permite a criação de propriedades no contrato. +O Manticore permite controle total sobre toda a execução de cada caminho. Como resultado, ele permite que você adicione restrições arbitrárias a quase tudo. Este controle permite a criação de propriedades no contrato. Considere o seguinte exemplo: ```solidity function unsafe_add(uint a, uint b) returns(uint c){ - c = a + b; // no overflow protection + c = a + b; // sem proteção contra overflow return c; } ``` -Aqui há apenas um caminho para explorar na função: +Aqui, há apenas um caminho a ser explorado na função: - Caminho 1: `c = a + b` -Usando o Manticore, você pode verificar se há overflow, e adicionar restrições à previsão do caminho: +Usando o Manticore, você pode verificar se há overflow e adicionar restrições ao predicado de caminho: - `c = a + b AND (c < a OR c < b)` -Se é possível encontrar uma avaliação de `um` e `b` para a qual o caminho predicado acima é viável, significa que encontrou um transbordamento ("overflow"). Por exemplo, o solver pode gerar a entrada `a = 10 , b = MAXUINT256`. +Se for possível encontrar uma valoração de `a` e `b` para a qual o predicado de caminho acima seja viável, significa que você encontrou um overflow. Por exemplo, o solucionador pode gerar a entrada `a = 10, b = MAXUINT256`. -Se você considerar uma versão fixa: +Se você considerar uma versão corrigida: ```solidity function safe_add(uint a, uint b) returns(uint c){ @@ -119,17 +121,17 @@ function safe_add(uint a, uint b) returns(uint c){ } ``` -A fórmula associada com verificação de overflow seria: +A fórmula associada com a verificação de overflow seria: - `c = a + b AND (c >= a) AND (c=>b) AND (c < a OR c < b)` -Esta fórmula não pode ser resolvida; em outras palavras, esta é uma **prova** que em `safe_add`, `c` irá sempre aumentar. +Esta fórmula não pode ser resolvida; em outras palavras, esta é uma **prova** de que em `safe_add`, `c` sempre aumentará. -DSE é assim uma ferramenta poderosa, que pode verificar restrições arbitrárias no seu código. +O DSE é, portanto, uma ferramenta poderosa que pode verificar restrições arbitrárias em seu código. -## Executando sob Manticore {#running-under-manticore} +## Executando no Manticore {#running-under-manticore} -Veremos como explorar um contrato inteligente com a API Manticore. O alvo é o seguinte contrato inteligente [`exemplo.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example.sol): +Veremos como explorar um contrato inteligente com a API do Manticore. O alvo é o seguinte contrato inteligente [`example.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example.sol): ```solidity pragma solidity >=0.4.24 <0.6.0; @@ -143,15 +145,15 @@ contract Simple { } ``` -### Executar uma exploração independente {#run-a-standalone-exploration} +### Execute uma exploração autônoma {#run-a-standalone-exploration} -Você pode executar a Manticore diretamente no contrato inteligente pelo seguinte comando (`projeto` pode ser um Arquivo Solidity, ou um diretório de projeto): +Você pode executar o Manticore diretamente no contrato inteligente com o seguinte comando (`project` pode ser um arquivo Solidity ou um diretório de projeto): ```bash $ manticore project ``` -Você obterá a saída de casos de teste como este (a ordem pode mudar): +Você receberá a saída de casos de teste como este (a ordem pode mudar): ``` ... @@ -166,51 +168,54 @@ Você obterá a saída de casos de teste como este (a ordem pode mudar): ... ``` -Sem informações adicionais, Manticore explorará o contrato com novas transações simbólicas até que não explore novos caminhos do contrato. Manticore não executa novas transações após uma falha (por exemplo: após um reversão). +Sem informações adicionais, o Manticore explorará o contrato com novas transações +simbólicas até que não explore novos caminhos no contrato. O Manticore não executa novas transações após uma que falhou (ex: após uma reversão). -Manticore irá gerar as informações em um diretório `mcore_*`. Entre outros, você encontrará nesse diretório: +O Manticore produzirá a informação em um diretório `mcore_*`. Entre outras coisas, você encontrará neste diretório: - `global.summary`: cobertura e avisos do compilador -- `test_XXXXX.summary`: cobertura, última instrução, saldos de conta por caso de teste +- `test_XXXXX.summary`: cobertura, última instrução, saldos da conta por caso de teste - `test_XXXXX.tx`: lista detalhada de transações por caso de teste -Aqui, Manticore encontrou 7 casos de teste, que correspondem à (a ordem do nome do arquivo pode mudar): +Aqui o Manticore encontra 7 casos de teste, que correspondem a (a ordem do nome do arquivo pode mudar): -| | Transação 0 | Transação 1 | Transação 2 | Resultado | -|:--------------------:|:-------------------:|:----------------------:| ---------------------- |:---------:| -| **test_00000000.tx** | Criação de contrato | f(!=65) | f(!=65) | STOP | -| **test_00000001.tx** | Criação de contrato | função de contingência | | REVERT | -| **test_00000002.tx** | Criação de contrato | | | RETURN | -| **test_00000003.tx** | Criação de contrato | f(65) | | REVERT | -| **test_00000004.tx** | Criação de contrato | f(!=65) | | STOP | -| **test_00000005.tx** | Criação de contrato | f(!=65) | f(65) | REVERT | -| **test_00000006.tx** | Criação de contrato | f(!=65) | função de contingência | REVERT | +| | Transação 0 | Transação 1 | Transação 2 | Resultado | +| :-------------------------------------------------------: | :-----------------: | :------------------------: | -------------------------- | :-------: | +| **test_00000000.tx** | Criação de contrato | f(!=65) | f(!=65) | STOP | +| **test_00000001.tx** | Criação de contrato | função de fallback | | REVERT | +| **test_00000002.tx** | Criação de contrato | | | RETURN | +| **test_00000003.tx** | Criação de contrato | f(65) | | REVERT | +| **test_00000004.tx** | Criação de contrato | f(!=65) | | STOP | +| **test_00000005.tx** | Criação de contrato | f(!=65) | f(65) | REVERT | +| **test_00000006.tx** | Criação de contrato | f(!=65) | função de fallback | REVERT | _Resumo da exploração f(!=65) denota f chamado com qualquer valor diferente de 65._ -Como você pode perceber, Manticore gera um caso de teste único para cada transação bem sucedida ou revertida. +Como você pode perceber, o Manticore gera um caso de teste único para cada transação bem-sucedida ou revertida. -Use a flag `--quick-mode` se você quiser uma exploração rápida de código (ele desativa detectores de bugs, cálculo de gas, ...) +Use a flag `--quick-mode` se você quiser uma exploração rápida de código (ela desativa detectores de bugs, computação de gás, ...) -### Manipule um contrato inteligente através da API {#manipulate-a-smart-contract-through-the-api} +### Manipular um contrato inteligente através da API {#manipulate-a-smart-contract-through-the-api} -Esta seção descreve detalhes sobre como manipular um contrato inteligente através da API Manticore Python. Você pode criar um novo arquivo com a extensão python `*. y` e escreva o código necessário adicionando os comandos da API (básicos dos quais serão descritos abaixo) neste arquivo e então execute-o com o comando `$ python3 *. a`. Também você pode executar os comandos abaixo diretamente no console python, para executar o console use o comando `$ python3`. +Esta seção descreve em detalhes como manipular um contrato inteligente através da API Python do Manticore. Você pode criar um novo arquivo com a extensão python `*.py` e escrever o código necessário adicionando os comandos da API (cujos fundamentos serão descritos abaixo) neste arquivo e, em seguida, executá-lo com o comando `$ python3 *.py`. Você também pode executar os comandos abaixo diretamente no console do python; para executar o console, use o comando `$ python3`. ### Criando Contas {#creating-accounts} -A primeira coisa que você deve fazer é iniciar uma nova blockchain com os seguintes comandos: +A primeira coisa que você deve fazer é iniciar uma nova cadeia de blocos com os seguintes comandos: ```python from manticore.ethereum import ManticoreEVM + +m = ManticoreEVM() ``` -Uma conta de não-contrato é criada usando [m.create_account](https://manticore.readthedocs.io/en/latest/evm.html?highlight=create_account#manticore.ethereum.ManticoreEVM.create_account): +Uma conta que não seja de contrato é criada usando [m.create_account](https://manticore.readthedocs.io/en/latest/evm.html?highlight=create_account#manticore.ethereum.ManticoreEVM.create_account): ```python user_account = m.create_account(balance=1000) ``` -Um contrato de Solidity pode ser implantado usando [m.solidity_create_contract](https://manticore.readthedocs.io/en/latest/evm.html?highlight=solidity_create#manticore.ethereum.ManticoreEVM.create_contract): +Um contrato Solidity pode ser implantado usando [m.solidity_create_contract](https://manticore.readthedocs.io/en/latest/evm.html?highlight=solidity_create#manticore.ethereum.ManticoreEVM.create_contract): ```solidity source_code = ''' @@ -229,11 +234,11 @@ contract_account = m.solidity_create_contract(source_code, owner=user_account) #### Resumo {#summary} -- Você pode criar contas de usuário e contratos com [m.create_account](https://manticore.readthedocs.io/en/latest/evm.html?highlight=create_account#manticore.ethereum.ManticoreEVM.create_account) and [m.solidity_create_contract](https://manticore.readthedocs.io/en/latest/evm.html?highlight=solidity_create#manticore.ethereum.ManticoreEVM.create_contract). +- Você pode criar contas de usuário e de contrato com [m.create_account](https://manticore.readthedocs.io/en/latest/evm.html?highlight=create_account#manticore.ethereum.ManticoreEVM.create_account) e [m.solidity_create_contract](https://manticore.readthedocs.io/en/latest/evm.html?highlight=solidity_create#manticore.ethereum.ManticoreEVM.create_contract). ### Executando transações {#executing-transactions} -Manticore suporta dois tipos de transação: +O Manticore suporta dois tipos de transação: - Transação bruta: todas as funções são exploradas - Transação nomeada: apenas uma função é explorada @@ -249,10 +254,10 @@ m.transaction(caller=user_account, value=value) ``` -O chamador, o endereço, os dados ou o valor da transação pode ser concreto ou simbólico: +O chamador, o endereço, os dados ou o valor da transação podem ser concretos ou simbólicos: -- [m.make_symbollic_value](https://manticore.readthedocs.io/en/latest/evm.html?highlight=make_symbolic_value#manticore.ethereum.ManticoreEVM.make_symbolic_value) cria um valor simbólico. -- [m.make_symbollic_value](https://manticore.readthedocs.io/en/latest/evm.html?highlight=make_symbolic_buffer#manticore.ethereum.ManticoreEVM.make_symbolic_buffer) cria um valor simbólico "byte array". +- [m.make_symbolic_value](https://manticore.readthedocs.io/en/latest/evm.html?highlight=make_symbolic_value#manticore.ethereum.ManticoreEVM.make_symbolic_value) cria um valor simbólico. +- [m.make_symbolic_buffer(size)](https://manticore.readthedocs.io/en/latest/evm.html?highlight=make_symbolic_buffer#manticore.ethereum.ManticoreEVM.make_symbolic_buffer) cria uma matriz de bytes simbólica. Por exemplo: @@ -262,43 +267,44 @@ symbolic_data = m.make_symbolic_buffer(320) m.transaction(caller=user_account, address=contract_address, data=symbolic_data, - value=symbolic_value + value=symbolic_value) ``` -Se os dados forem simbólicos, Manticore irá explorar todas as funções do contrato durante a execução da transação. Será útil ver a explicação de Função de Fallback nas [Mãos do CTF Ethernaut](https://blog.trailofbits.com/2017/11/06/hands-on-the-ethernaut-ctf/), artigo para entender como a seleção de função funciona. +Se os dados forem simbólicos, o Manticore explorará todas as funções do contrato durante a execução da transação. Será útil ver a explicação da Função de Fallback no artigo [Hands on the Ethernaut CTF](https://blog.trailofbits.com/2017/11/06/hands-on-the-ethernaut-ctf/) para entender como a seleção de funções funciona. #### Transação nomeada {#named-transaction} -Funções podem ser executadas através de seu nome. Para executar `f(uint var)` com um valor simbólico, do user_account, e com 0 ether, use: +As funções podem ser executadas pelo nome. +Para executar `f(uint var)` com um valor simbólico, de user_account, e com 0 ether, use: ```python symbolic_var = m.make_symbolic_value() contract_account.f(symbolic_var, caller=user_account, value=0) ``` -Se `valor` da transação não for especificado, ela é 0 por padrão. +Se o `value` da transação não for especificado, ele será 0 por padrão. #### Resumo {#summary-1} -- Os argumentos de uma transação podem ser concretos ou simbólicos -- Uma transação bruta irá explorar todas as funções -- A função pode ser chamada pelo nome +- Argumentos de uma transação podem ser concretos ou simbólicos +- Uma transação bruta explorará todas as funções +- A função pode ser chamada pelo seu nome ### Espaço de trabalho {#workspace} `m.workspace` é o diretório usado como diretório de saída para todos os arquivos gerados: ```python -print("Results are in {}".format(m.workspace)) +print("Os resultados estão em {}".format(m.workspace)) ``` -### Terminar a Exploração {#terminate-the-exploration} +### Encerrar a exploração {#terminate-the-exploration} -Para parar a exploração, use [m.finalize()](https://manticore.readthedocs.io/en/latest/evm.html?highlight=finalize#manticore.ethereum.ManticoreEVM.finalize). Nenhuma transação adicional deve ser enviada quando este método for chamado e a Manticore gerar casos de teste para cada caminho explorado. +Para parar a exploração, use [m.finalize()](https://manticore.readthedocs.io/en/latest/evm.html?highlight=finalize#manticore.ethereum.ManticoreEVM.finalize). Nenhuma transação adicional deve ser enviada depois que este método for chamado e o Manticore gerará casos de teste para cada caminho explorado. -### Resumo: Executando sob Manticore {#summary-running-under-manticore} +### Resumo: Executando no Manticore {#summary-running-under-manticore} -Juntando todos os passos anteriores, obtemos: +Juntando todas as etapas anteriores, obtemos: ```python from manticore.ethereum import ManticoreEVM @@ -314,15 +320,15 @@ contract_account = m.solidity_create_contract(source_code, owner=user_account) symbolic_var = m.make_symbolic_value() contract_account.f(symbolic_var) -print("Results are in {}".format(m.workspace)) -m.finalize() # stop the exploration +print("Os resultados estão em {}".format(m.workspace)) +m.finalize() # para a exploração ``` -Todo o código acima você pode encontrar no [`exemple_run.py`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example_run.py) +Todo o código acima pode ser encontrado em [`example_run.py`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example_run.py) -## Obtendo caminhos {#getting-throwing-paths} +## Obtendo caminhos que lançam exceções {#getting-throwing-paths} -Agora vamos gerar entradas específicas para os caminhos levantando uma exceção em `f()`. O alvo é ainda o seguinte contrato inteligente [`exemplo.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example.sol): +Agora, vamos gerar entradas específicas para os caminhos que levantam uma exceção em `f()`. O alvo ainda é o seguinte contrato inteligente [`example.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example.sol): ```solidity pragma solidity >=0.4.24 <0.6.0; @@ -335,38 +341,38 @@ contract Simple { } ``` -### Usando informações do estado {#using-state-information} +### Usando informações de estado {#using-state-information} -Cada caminho executado tem seu estado de blockchain. Um estado ou está pronto ou é morto, o que significa que atinge um caminho de THROW ou REVERT: +Cada caminho executado tem seu estado da cadeia de blocos. Um estado está pronto ou é encerrado, o que significa que ele atinge uma instrução THROW ou REVERT: - [m.ready_states](https://manticore.readthedocs.io/en/latest/states.html#accessing): a lista de estados que estão prontos (não executaram um REVERT/INVALID) -- [m.killed_states](https://manticore.readthedocs.io/en/latest/states.html#accessings): a lista de estados que estão mortos -- [m.all_states](https://manticore.readthedocs.io/en/latest/states.html#accessings): todos os estados +- [m.killed_states](https://manticore.readthedocs.io/en/latest/states.html#accessing): a lista de estados que são encerrados +- [m.all_states](https://manticore.readthedocs.io/en/latest/states.html#accessing): todos os estados ```python -for state in m.all_statees: - # faz algo com estado +for state in m.all_states: + # faça algo com o estado ``` -Você pode acessar informações de estado. Por exemplo: +Você pode acessar as informações de estado. Por exemplo: - `state.platform.get_balance(account.address)`: o saldo da conta - `state.platform.transactions`: a lista de transações - `state.platform.transactions[-1].return_data`: os dados retornados pela última transação -Os dados retornados pela última transação são um array, que pode ser convertido para um valor com ABI.deserialize, por exemplo: +Os dados retornados pela última transação são uma matriz, que pode ser convertida em um valor com ABI.deserialize, por exemplo: ```python data = state.platform.transactions[0].return_data data = ABI.deserialize("uint", data) ``` -### Como gerar caixa de teste {#how-to-generate-testcase} +### Como gerar um caso de teste {#how-to-generate-testcase} -Use [m.generate_testcase(state, name)](https://manticore.readthedocs.io/en/latest/evm.html?highlight=generate_testcase#manticore.ethereum.ManticoreEVM.generate_testcase) para gerar a caixa de teste: +Use [m.generate_testcase(state, name)](https://manticore.readthedocs.io/en/latest/evm.html?highlight=generate_testcase#manticore.ethereum.ManticoreEVM.generate_testcase) para gerar um caso de teste: ```python -m.generate_testcase(estado, 'BugFound') +m.generate_testcase(state, 'BugFound') ``` ### Resumo {#summary-2} @@ -374,10 +380,10 @@ m.generate_testcase(estado, 'BugFound') - Você pode iterar sobre o estado com m.all_states - `state.platform.get_balance(account.address)` retorna o saldo da conta - `state.platform.transactions` retorna a lista de transações -- `Transtion.return_data` são os dados retornados +- `transaction.return_data` são os dados retornados - `m.generate_testcase(state, name)` gera entradas para o estado -### Resumo: Obtendo o caminho de lançamento {#summary-getting-throwing-path} +### Resumo: Obtendo caminhos que lançam exceções {#summary-getting-throwing-path} ```python from manticore.ethereum import ManticoreEVM @@ -393,21 +399,23 @@ contract_account = m.solidity_create_contract(source_code, owner=user_account) symbolic_var = m.make_symbolic_value() contract_account.f(symbolic_var) -## Verificando se a execução termina com um REVERT ou INVALID +## Verifique se uma execução termina com um REVERT ou INVALID + for state in m.terminated_states: last_tx = state.platform.transactions[-1] if last_tx.result in ['REVERT', 'INVALID']: - print('Throw found {}'.format(m.workspace)) + print('Exceção encontrada {}'.format(m.workspace)) m.generate_testcase(state, 'ThrowFound') ``` -Todo o código acima você pode encontrar no [`exemple_run.py`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example_run.py) +Todo o código acima pode ser encontrado em [`example_run.py`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example_run.py) -_Note que poderíamos ter gerado um script muito mais simples, como todos os estados retornados por terminated_state REVERT ou INVALID no seu resultado: este exemplo foi destinado apenas para demonstrar como manipular a API._ +_Observe que poderíamos ter gerado um script muito mais simples, pois todos os estados retornados por terminated_state têm REVERT ou INVALID em seu resultado: este exemplo teve como objetivo apenas demonstrar como manipular a API._ -## Adicionar Restrições {#adding-constraints} +## Adicionando restrições {#adding-constraints} -Veremos como restringir a exploração. Vamos fazer a suposição de que a documentação de `f()` que afirma que a função nunca é chamada com `a == 65`, então qualquer erro com `a == 65` não é um bug de verdade. O alvo é o seguinte contrato inteligente [`exemplo.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example.sol): +Veremos como restringir a exploração. Vamos assumir que a +documentação de `f()` afirma que a função nunca é chamada com `a == 65`, então qualquer bug com `a == 65` não é um bug real. O alvo ainda é o seguinte contrato inteligente [`example.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example.sol): ```solidity pragma solidity >=0.4.24 <0.6.0; @@ -422,22 +430,22 @@ contract Simple { ### Operadores {#operators} -O módulo [Operadores](https://github.com/trailofbits/manticore/blob/master/manticore/core/smtlib/operators.py) facilita a manipulação de restrições, entre outras que fornece: +O módulo [Operators](https://github.com/trailofbits/manticore/blob/master/manticore/core/smtlib/operators.py) facilita a manipulação de restrições, entre outras coisas, ele fornece: -- Operadores.AND, -- Operadores.OR, -- Operators.UGT (não assinado maior que), -- Operators.UGE (não assinado maior ou igual a), -- Operators.UGT (não assinado menor que), -- Operators.ULE (menor que ou igual a). +- Operators.AND, +- Operators.OR, +- Operators.UGT (maior que sem sinal), +- Operators.UGE (maior ou igual que sem sinal), +- Operators.ULT (menor que sem sinal), +- Operators.ULE (menor ou igual que sem sinal). -Para importar o módulo use o seguinte: +Para importar o módulo, use o seguinte: ```python from manticore.core.smtlib import Operators ``` -`Operators.CONCAT` é usado para concatenar uma matriz a um valor. Por exemplo, o return_data de uma transação precisa ser alterado para um valor a ser verificado contra outro valor: +`Operators.CONCAT` é usado para concatenar uma matriz a um valor. Por exemplo, o return_data de uma transação precisa ser alterado para um valor para ser verificado em relação a outro valor: ```python last_return = Operators.CONCAT(256, *last_return) @@ -449,7 +457,8 @@ Você pode usar restrições globalmente ou para um estado específico. #### Restrição global {#state-constraint} -Use `m.constrain(constraint)` para adicionar um constraint ("restrição") global. Por exemplo, você pode chamar um contrato de um endereço simbólico e restringir este endereço para serem valores específicos: +Use `m.constrain(constraint)` para adicionar uma restrição global. +Por exemplo, você pode chamar um contrato a partir de um endereço simbólico e restringir esse endereço a valores específicos: ```python symbolic_address = m.make_symbolic_value() @@ -462,21 +471,23 @@ m.transaction(caller=user_account, #### Restrição de estado {#state-constraint} -Use o estado de [. onstrain(restrição)](https://manticore.readthedocs.io/en/latest/states.html?highlight=StateBase#manticore.core.state.StateBase.constrain) para adicionar uma restrição a um estado específico. Ele pode ser usado para restringir o estado após sua exploração para verificar alguma propriedade nele. +Use [state.constrain(constraint)](https://manticore.readthedocs.io/en/latest/states.html?highlight=StateBase#manticore.core.state.StateBase.constrain) para adicionar uma restrição a um estado específico. +Pode ser usado para restringir o estado após sua exploração para verificar alguma propriedade nele. -### Verificando a constraint ("restrição") {#checking-constraint} +### Verificando a restrição {#checking-constraint} -Use `solver.check(state.constraints)` para saber se uma restrição ainda é viável. Por exemplo, o seguinte irá restringir o simbolic_valor para ser diferente do 65 e verificar se o estado ainda é viável: +Use `solver.check(state.constraints)` para saber se uma restrição ainda é viável. +Por exemplo, o seguinte irá restringir o symbolic_value a ser diferente de 65 e verificar se o estado ainda é viável: ```python state.constrain(symbolic_var != 65) if solver.check(state.constraints): - # estado é viável + # o estado é viável ``` -### Resumo: Adicionando constraints ("restrições") {#summary-adding-constraints} +### Resumo: Adicionando restrições {#summary-adding-constraints} -Adicionando constraints ("restrições") ao código anterior, obtemos: +Adicionando restrição ao código anterior, obtemos: ```python from manticore.ethereum import ManticoreEVM @@ -497,18 +508,19 @@ contract_account.f(symbolic_var) no_bug_found = True -## Verificar se a execução termina com um REVERT ou INVALID +## Verifique se uma execução termina com um REVERT ou INVALID + for state in m.terminated_states: last_tx = state.platform.transactions[-1] if last_tx.result in ['REVERT', 'INVALID']: - # we do not consider the path were a == 65 + # não consideramos o caminho onde a == 65 condition = symbolic_var != 65 if m.generate_testcase(state, name="BugFound", only_if=condition): - print(f'Bug found, results are in {m.workspace}') + print(f'Bug encontrado, os resultados estão em {m.workspace}') no_bug_found = False if no_bug_found: - print(f'No bug found') + print(f'Nenhum bug encontrado') ``` -Todo o código acima você pode encontrar no [`exemple_run.py`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example_run.py) +Todo o código acima pode ser encontrado em [`example_run.py`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/manticore/examples/example_run.py) diff --git a/public/content/translations/pt-br/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/index.md b/public/content/translations/pt-br/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/index.md index b9ac9dc2118..80af4439b10 100644 --- a/public/content/translations/pt-br/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/index.md +++ b/public/content/translations/pt-br/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/index.md @@ -1,17 +1,12 @@ --- -title: Como utilizar o Slither para encontrar bugs nos contratos inteligentes +title: Como usar o Slither para encontrar bugs em contratos inteligentes description: Como usar o Slither para encontrar automaticamente bugs em contratos inteligentes author: Trailofbits lang: pt-br -tags: - - "solidity" - - "smart contracts" - - "segurança" - - "testando" - - "análise estática" +tags: [ "Solidity", "smart contracts", "segurança", "testando" ] skill: advanced published: 2020-06-09 -source: Construindo contratos seguros +source: Building secure contracts sourceUrl: https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/slither --- @@ -26,7 +21,7 @@ O objetivo deste tutorial é mostrar como usar o Slither para localizar automati ## Instalação {#installation} -O Slither requer a versão 3.6 do Python ou superior. Pode ser instalado pelo pip ou usando o docker. +O Slither requer a versão 3.6 do Python ou superior. Pode ser instalado via pip ou usando o docker. Slither via pip: @@ -34,14 +29,14 @@ Slither via pip: pip3 install --user slither-analyzer ``` -Slither através de docker: +Slither via docker: ```bash docker pull trailofbits/eth-security-toolbox docker run -it -v "$PWD":/home/trufflecon trailofbits/eth-security-toolbox ``` -_O último comando roda a eth-security-toolbox em um docker que tem acesso ao seu diretório atual. Você pode alterar os arquivos do seu host e executar as ferramentas nos arquivos através do docker_ +_O último comando executa o eth-security-toolbox em um docker que tem acesso ao seu diretório atual. Você pode alterar os arquivos do seu host e executar as ferramentas nos arquivos do docker_ Dentro do docker, execute: @@ -60,23 +55,23 @@ python3 script.py ### Linha de comando {#command-line} -**Linha de comando versus scripts definidos pelo usuário.** O Slither vem com um conjunto de detectores predefinidos que encontram muitos bugs comuns. Chamar o Slither na linha de comando irá executar todos os detectores. Nenhum conhecimento detalhado da análise estática é necessária: +**Linha de comando versus scripts definidos pelo usuário.** O Slither vem com um conjunto de detectores predefinidos que encontram muitos bugs comuns. Chamar o Slither pela linha de comando executará todos os detectores, não é necessário conhecimento detalhado de análise estática: ```bash slither project_paths ``` -Além de detectadores, o Slither possui recursos de revisão de código através de suas [printers](https://github.com/crytic/slither#printers) e [ferramentas](https://github.com/crytic/slither#tools). +Além dos detectores, o Slither tem recursos de revisão de código por meio de seus [printers](https://github.com/crytic/slither#printers) e [ferramentas](https://github.com/crytic/slither#tools). -Use [crytic.io](https://github.com/crytic) para obter acesso a detectadores privados e integração GitHub. +Use o [crytic.io](https://github.com/crytic) para obter acesso a detectores privados e integração com o GitHub. ## Análise estática {#static-analysis} -Os recursos e design do framework estático de análise do Slither foram descritos nos posts de blog ([1](https://blog.trailofbits.com/2018/10/19/slither-a-solidity-static-analysis-framework/)), [2](https://blog.trailofbits.com/2019/05/27/slither-the-leading-static-analyzer-for-smart-contracts/)) e em um [documento acadêmico](https://github.com/trailofbits/publications/blob/master/papers/wetseb19.pdf). +As capacidades e o design da estrutura de análise estática Slither foram descritos em posts de blog ([1](https://blog.trailofbits.com/2018/10/19/slither-a-solidity-static-analysis-framework/), [2](https://blog.trailofbits.com/2019/05/27/slither-the-leading-static-analyzer-for-smart-contracts/)) e em um [artigo acadêmico](https://github.com/trailofbits/publications/blob/master/papers/wetseb19.pdf). -A análise estática existe em diferentes "flavors". Você provavelmente percebe que compiladores como [clang](https://clang-analyzer.llvm.org/) e [gcc](https://lwn.net/Articles/806099/) dependem destas técnicas de pesquisa, mas também sustenta ([Infer](https://fbinfer.com/), [CodeClimate](https://codeclimate.com/), [FindBugs](http://findbugs.sourceforge.net/) e ferramentas baseadas em métodos formais como [Frama-C](https://frama-c.com/) e [Polyspace](https://www.mathworks.com/products/polyspace.html). +A análise estática existe em diferentes "sabores". Você provavelmente percebe que compiladores como [clang](https://clang-analyzer.llvm.org/) e [gcc](https://lwn.net/Articles/806099/) dependem dessas técnicas de pesquisa, mas elas também são a base para ([Infer](https://fbinfer.com/), [CodeClimate](https://codeclimate.com/), [FindBugs](http://findbugs.sourceforge.net/)) e ferramentas baseadas em métodos formais como [Frama-C](https://frama-c.com/) e [Polyspace](https://www.mathworks.com/products/polyspace.html). -Nós não analisaremos exaustivamente técnicas de análise estática e pesquisador aqui. Em vez disso, vamos focar no que é necessário para entender como o Slither funciona para que você possa usá-lo de forma mais eficiente para encontrar bugs e entender códigos. +Não faremos uma revisão exaustiva das técnicas de análise estática e dos pesquisadores aqui. Em vez disso, vamos nos concentrar no que é necessário para entender como o Slither funciona para que você possa usá-lo com mais eficácia para encontrar bugs e entender o código. - [Representação de código](#code-representation) - [Análise de código](#analysis) @@ -84,13 +79,13 @@ Nós não analisaremos exaustivamente técnicas de análise estática e pesquisa ### Representação de código {#code-representation} -Em contraste com uma análise dinâmica, que justifica um único caminho de execução, razões de análise estática sobre todos os caminhos ao mesmo tempo. Para isso, ele depende de uma representação diferente do código. As duas mais comuns são a árvore de sintaxe abstrata (AST) e o gráfico de fluxo de controle (CFG). +Em contraste com uma análise dinâmica, que analisa um único caminho de execução, a análise estática analisa todos os caminhos de uma só vez. Para isso, ela se baseia em uma representação de código diferente. As duas mais comuns são a árvore de sintaxe abstrata (AST) e o grafo de fluxo de controle (CFG). -### Árvores de sintaxe abstratas (AST) {#abstract-syntax-trees-ast} +### Árvores de Sintaxe Abstrata (AST) {#abstract-syntax-trees-ast} -AST é usado toda vez que o compilador analisa o código. É provavelmente a estrutura mais básica sobre a qual se pode efetuar a análise estática. +As ASTs são usadas sempre que o compilador analisa o código. É provavelmente a estrutura mais básica sobre a qual a análise estática pode ser realizada. -Em poucas palavras, a AST é uma árvore estruturada onde, normalmente, cada folha contém uma variável ou uma constante e os nós internos são operações ou operações de fluxo de controle. Considere o seguinte código: +Em resumo, uma AST é uma árvore estruturada onde, geralmente, cada folha contém uma variável ou uma constante, e os nós internos são operandos ou operações de fluxo de controle. Considere o seguinte código: ```solidity function safeAdd(uint a, uint b) pure internal returns(uint){ @@ -101,15 +96,15 @@ function safeAdd(uint a, uint b) pure internal returns(uint){ } ``` -O AST correspondente é mostrado em: +A AST correspondente é mostrada em: ![AST](./ast.png) -O Slither usa o AST exportado pelo solc. +O Slither usa a AST exportada pelo solc. -Enquanto for simples construir, o AST é uma estrutura aninhada. Por vezes, esta não é a mais simples de analisar. Por exemplo, para identificar as operações usadas pela expressão `a + b <= a`,, primeiro você deve analisar `<=` e, em seguida, `+`. Uma abordagem comum é usar o chamado padrão de visitantes, que navega pela árvore recursivamente. O Slither contém um visitante genérico em [`ExpressionVisitor`](https://github.com/crytic/slither/blob/master/slither/visitors/expression/expression.py). +Embora seja simples de construir, a AST é uma estrutura aninhada. Às vezes, essa não é a forma mais direta de analisar. Por exemplo, para identificar as operações usadas pela expressão `a + b <= a`, você deve primeiro analisar `<=` e depois `+`. Uma abordagem comum é usar o chamado padrão de visitante, que navega pela árvore recursivamente. O Slither contém um visitante genérico em [`ExpressionVisitor`](https://github.com/crytic/slither/blob/master/slither/visitors/expression/expression.py). -O código a seguir usa `ExpressionVisitor` para detectar se a expressão contém uma adição: +O código a seguir usa o `ExpressionVisitor` para detectar se a expressão contém uma adição: ```python from slither.visitors.expression.expression import ExpressionVisitor @@ -128,39 +123,39 @@ visitor = HasAddition(expression) # expression is the expression to be tested print(f'The expression {expression} has a addition: {visitor.result()}') ``` -### Controlar Gráfico de Fluxos (CFG) {#control-flow-graph-cfg} +### Grafo de Fluxo de Controle (CFG) {#control-flow-graph-cfg} -A segunda representação de código mais comum é o gráfico de fluxo de controle (CFG). Como seu nome sugere, é uma representação baseada em gráficos que expõe todos os caminhos de execução. Cada nó contém uma ou várias instruções. Bordas no gráfico representam as operações de fluxo de controle (se/então/outra vez, loop, etc). O nosso exemplo anterior é o do CFG: +A segunda representação de código mais comum é o grafo de fluxo de controle (CFG). Como o nome sugere, é uma representação baseada em grafo que expõe todos os caminhos de execução. Cada nó contém uma ou várias instruções. As arestas no grafo representam as operações de fluxo de controle (if/then/else, loop, etc). O CFG do nosso exemplo anterior é: ![CFG](./cfg.png) -O CFG é a representação que está por cima da qual se constrói a maioria das análises. +O CFG é a representação sobre a qual a maioria das análises é construída. -Existem muitas outras representações de código. Cada representação tem vantagens e desvantagens de acordo com a análise que você deseja realizar. +Existem muitas outras representações de código. Cada representação tem vantagens e desvantagens, dependendo da análise que você deseja realizar. ### Análise {#analysis} -O tipo mais simples de análises que você pode realizar com o Slither são análises sintáticas. +O tipo mais simples de análise que você pode realizar com o Slither é a análise sintática. -### Análises de sintaxe {#syntax-analysis} +### Análise de sintaxe {#syntax-analysis} -O Slither pode navegar através dos diferentes componentes do código e sua representação para encontrar inconsistências e falhas usando uma abordagem semelhante a padrões de correspondência. +O Slither pode navegar pelos diferentes componentes do código e sua representação para encontrar inconsistências e falhas usando uma abordagem do tipo correspondência de padrões. Por exemplo, os seguintes detectores procuram por problemas relacionados à sintaxe: -- [State variable shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing): itera sobre todas as variáveis de estado e verifica se tem alguma variável "shadow" de um contrato herdado ([state.py#L51-L62](https://github.com/crytic/slither/blob/0441338e055ab7151b30ca69258561a5a793f8ba/slither/detectors/shadowing/state.py#L51-L62)) +- [Sombreamento de variável de estado](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing): itera sobre todas as variáveis de estado e verifica se alguma sombreia uma variável de um contrato herdado ([state.py#L51-L62](https://github.com/crytic/slither/blob/0441338e055ab7151b30ca69258561a5a793f8ba/slither/detectors/shadowing/state.py#L51-L62)) -- [Interface ERC20 incorreta](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface): procurar por assinaturas de função ERC20 incorretas ([incorrect_erc20_interface.py#L34-L55](https://github.com/crytic/slither/blob/0441338e055ab7151b30ca69258561a5a793f8ba/slither/detectors/erc/incorrect_erc20_interface.py#L34-L55)) +- [Interface ERC20 incorreta](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface): procura por assinaturas de função ERC20 incorretas ([incorrect_erc20_interface.py#L34-L55](https://github.com/crytic/slither/blob/0441338e055ab7151b30ca69258561a5a793f8ba/slither/detectors/erc/incorrect_erc20_interface.py#L34-L55)) ### Análise semântica {#semantic-analysis} -Em contraste com a análise de sintaxe, uma análise semântica vai aprofundar e analisar o "significado" do código. Esta família inclui vários tipos de análises. Conduzem a resultados mais poderosos e úteis, mas são também mais complexos de escrever. +Em contraste com a análise de sintaxe, uma análise semântica irá mais a fundo e analisará o "significado" do código. Esta família inclui alguns tipos abrangentes de análises. Elas levam a resultados mais poderosos e úteis, mas também são mais complexas de escrever. -Análises semânticas são usadas para detecções de vulnerabilidades mais avançadas. +As análises semânticas são usadas para as detecções de vulnerabilidades mais avançadas. #### Análise de dependência de dados {#fixed-point-computation} -Uma variável `variable_a` diz ser dependente de dados `variable_b` se houver um caminho para o qual o valor de `variable_a` seja influenciado pela `variable_b`. +Diz-se que uma variável `variable_a` tem dependência de dados de `variable_b` se houver um caminho no qual o valor de `variable_a` é influenciado por `variable_b`. No código a seguir, `variable_a` depende de `variable_b`: @@ -169,13 +164,13 @@ No código a seguir, `variable_a` depende de `variable_b`: variable_a = variable_b + 1; ``` -O Slither vem com capacidades embutidas de [dependência de dados,](https://github.com/crytic/slither/wiki/data-dependency) graças à sua representação intermediária (discutida em uma seção posterior). +O Slither vem com recursos integrados de [dependência de dados](https://github.com/crytic/slither/wiki/data-dependency), graças à sua representação intermediária (discutida em uma seção posterior). -Um exemplo de uso de dependência de dados pode ser encontrado em ["dangerous strict equality detector"](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities). Aqui o Slither procurará por uma comparação rigorosa de igualdade com um valor perigoso ([incorrect_strict_equality. y#L86-L87](https://github.com/crytic/slither/blob/6d86220a53603476f9567c3358524ea4db07fb25/slither/detectors/statements/incorrect_strict_equality.py#L86-L87)), e informará o usuário que deve usar `>=` ou `<=` ao invés de `==`para evitar um invasor para prender o contrato. Entre outros, o detector considerará como perigoso o valor de retorno de uma chamada para o `balanceOf(endereço)` ([incorrect_strict_equality. y#L63-L64](https://github.com/crytic/slither/blob/6d86220a53603476f9567c3358524ea4db07fb25/slither/detectors/statements/incorrect_strict_equality.py#L63-L64)), e usará o mecanismo de dependência de dados para rastrear seu uso. +Um exemplo de uso de dependência de dados pode ser encontrado no [detector de igualdades estritas perigosas](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities). Aqui, o Slither procurará por uma comparação de igualdade estrita com um valor perigoso ([incorrect_strict_equality.py#L86-L87](https://github.com/crytic/slither/blob/6d86220a53603476f9567c3358524ea4db07fb25/slither/detectors/statements/incorrect_strict_equality.py#L86-L87)), e informará ao usuário que deve usar `>=` ou `<=` em vez de `==`, para evitar que um invasor prenda o contrato em uma armadilha. Entre outras coisas, o detector considerará perigoso o valor de retorno de uma chamada para `balanceOf(address)` ([incorrect_strict_equality.py#L63-L64](https://github.com/crytic/slither/blob/6d86220a53603476f9567c3358524ea4db07fb25/slither/detectors/statements/incorrect_strict_equality.py#L63-L64)) e usará o mecanismo de dependência de dados para rastrear seu uso. -#### Cálculo de ponto fixo {#fixed-point-computation} +#### Computação de ponto fixo {#fixed-point-computation} -Se a sua análise navegar através do CFG e seguir as bordas, é provável que você veja os nós já visitados. Por exemplo, se um loop é apresentado como mostrado abaixo: +Se sua análise navegar pelo CFG e seguir as arestas, você provavelmente verá nós já visitados. Por exemplo, se um loop for apresentado como mostrado abaixo: ```solidity for(uint i; i < range; ++){ @@ -183,23 +178,23 @@ for(uint i; i < range; ++){ } ``` -A sua análise terá de saber quando parar. Existem duas estratégias principais aqui: (1) iterar em cada nó um número finito de vezes, (2) calcular um chamado _fixpoint_. Um ponto de acesso basicamente significa que a análise deste nó não fornece nenhuma informação significativa. +Sua análise precisará saber quando parar. Existem duas estratégias principais aqui: (1) iterar em cada nó um número finito de vezes, (2) computar um chamado _ponto fixo_. Um ponto fixo basicamente significa que analisar este nó não fornece nenhuma informação significativa. -Um exemplo de fixpoint usado pode ser encontrado nos detectadores de reentrância: Slither explora os nós, e procurar por chamadas externas, escrever e ler para armazenar. Uma vez que chegou a um ponto de correção ("fixpoint") ([reentrancy.py#L125-L131](https://github.com/crytic/slither/blob/master/slither/detectors/reentrancy/reentrancy.py#L125-L131)), interrompe a exploração e analisa os resultados para ver se uma reentrância está presente, através de diferentes padrões de reentrada ([reentrancy_benign. y](https://github.com/crytic/slither/blob/b275bcc824b1b932310cf03b6bfb1a1fef0ebae1/slither/detectors/reentrancy/reentrancy_benign.py), [reentrancy_read_before_write.py](https://github.com/crytic/slither/blob/b275bcc824b1b932310cf03b6bfb1a1fef0ebae1/slither/detectors/reentrancy/reentrancy_read_before_write.py), [reentrancy_eth.py](https://github.com/crytic/slither/blob/b275bcc824b1b932310cf03b6bfb1a1fef0ebae1/slither/detectors/reentrancy/reentrancy_eth.py)). +Um exemplo de uso de ponto fixo pode ser encontrado nos detectores de reentrância: o Slither explora os nós e procura por chamadas externas, escrita e leitura no armazenamento. Depois de atingir um ponto fixo ([reentrancy.py#L125-L131](https://github.com/crytic/slither/blob/master/slither/detectors/reentrancy/reentrancy.py#L125-L131)), ele interrompe a exploração e analisa os resultados para ver se há uma reentrância, por meio de diferentes padrões de reentrância ([reentrancy_benign.py](https://github.com/crytic/slither/blob/b275bcc824b1b932310cf03b6bfb1a1fef0ebae1/slither/detectors/reentrancy/reentrancy_benign.py), [reentrancy_read_before_write.py](https://github.com/crytic/slither/blob/b275bcc824b1b932310cf03b6bfb1a1fef0ebae1/slither/detectors/reentrancy/reentrancy_read_before_write.py), [reentrancy_eth.py](https://github.com/crytic/slither/blob/b275bcc824b1b932310cf03b6bfb1a1fef0ebae1/slither/detectors/reentrancy/reentrancy_eth.py)). -Escrever análises usando um cálculo de ponto fixo eficiente requer um bom entendimento de como a análise propaga sua informação. +Escrever análises usando computação de ponto fixo eficiente requer uma boa compreensão de como a análise propaga suas informações. ### Representação intermediária {#intermediate-representation} -Uma representação intermediária (IR) é uma linguagem que deve ser mais acessível à análise estática do que a original. Slither traduz Solidity para seu próprio IR: [SlithIR](https://github.com/crytic/slither/wiki/SlithIR). +Uma representação intermediária (RI) é uma linguagem destinada a ser mais adequada à análise estática do que a original. O Slither traduz Solidity para sua própria RI: [SlithIR](https://github.com/crytic/slither/wiki/SlithIR). -Compreender o SlithIR não é necessário se você quiser apenas escrever verificações básicas. No entanto, será útil se você planejar escrever análises semânticas avançadas. As [SlithIR](https://github.com/crytic/slither/wiki/Printer-documentation#slithir) e [SSA](https://github.com/crytic/slither/wiki/Printer-documentation#slithir-ssa)printers irão ajudá-lo a entender como o código é traduzido. +Entender o SlithIR não é necessário se você quiser apenas escrever verificações básicas. No entanto, será útil se você planeja escrever análises semânticas avançadas. Os printers [SlithIR](https://github.com/crytic/slither/wiki/Printer-documentation#slithir) e [SSA](https://github.com/crytic/slither/wiki/Printer-documentation#slithir-ssa) ajudarão você a entender como o código é traduzido. -## API Básica {#api-basics} +## Conceitos básicos da API {#api-basics} -Slither tem uma API que permite explorar os atributos básicos do contrato e suas funções. +O Slither tem uma API que permite explorar atributos básicos do contrato e suas funções. -Carregando um codebase: +Para carregar uma base de código: ```python from slither import Slither @@ -209,30 +204,30 @@ slither = Slither('/path/to/project') ### Explorando contratos e funções {#exploring-contracts-and-functions} -Um objeto `Slither` contém: +Um objeto `Slither` tem: -- contracts`contracts (list(Contract)`: lista de contratos +- `contracts (list(Contract)`: lista de contratos - `contracts_derived (list(Contract)`: lista de contratos que não são herdados por outro contrato (subconjunto de contratos) -- `get_contract_from_name (str)`: Retorna um contrato a partir de seu nome +- `get_contract_from_name (str)`: retorna um contrato a partir do seu nome -Um objeto `Slither` contém: +Um objeto `Contract` tem: -- `name (str)`: Nome do contrato -- `functions (list(Function))`: Lista de funções -- `modifiers (list(Modifier))`: Lista de funções -- `all_functions_called (list(Função/Modificador))`: Lista de todas as funções internas acessíveis pelo contrato -- `herança (lista(contrato))`: Lista de contratos herdados -- `get_function_from_signature (str)`: Retorna uma função a partir de sua assinatura -- `get_function_from_signature (str)`: Retorna uma função a partir de sua assinatura -- `get_contract_from_name (str)`: Retorna um contrato a partir de seu nome +- `name (str)`: nome do contrato +- `functions (list(Function))`: lista de funções +- `modifiers (list(Modifier))`: lista de modificadores +- `all_functions_called (list(Function/Modifier))`: lista de todas as funções internas alcançáveis pelo contrato +- `inheritance (list(Contract))`: lista de contratos herdados +- `get_function_from_signature (str)`: retorna uma função a partir de sua assinatura +- `get_modifier_from_signature (str)`: retorna um modificador a partir de sua assinatura +- `get_state_variable_from_name (str)`: retorna uma StateVariable a partir do seu nome -Um objeto `Function` ou `Modifier` têm: +Um objeto `Function` ou `Modifier` tem: -- `name (str)`: Nome da função +- `name (str)`: nome da função - `contract (contract)`: o contrato onde a função é declarada -- `nodes (list(Node))`: Lista dos nós que compõem o CFG da função/modificador -- `entry_point (Node)`: Ponto de entrada do CFG -- `variables_read (list(variável))`: Lista de variáveis lidas -- `variables_written (list(variável))`: Lista de variáveis escritas -- `state_variables_read (list(StateVariable))`: Lista de variáveis de estado lidas (subconjunto de variáveis lidas) -- `state_variables_written (list(StateVariable))`: Lista de variáveis de estado escritas (subconjunto de variáveis escritas) +- `nodes (list(Node))`: lista dos nós que compõem o CFG da função/modificador +- `entry_point (Node)`: ponto de entrada do CFG +- `variables_read (list(Variable))`: lista de variáveis lidas +- `variables_written (list(Variable))`: lista de variáveis escritas +- `state_variables_read (list(StateVariable))`: lista de variáveis de estado lidas (subconjunto de `variables_read`) +- `state_variables_written (list(StateVariable))`: lista de variáveis de estado escritas (subconjunto de `variables_written`) diff --git a/public/content/translations/pt-br/developers/tutorials/how-to-use-tellor-as-your-oracle/index.md b/public/content/translations/pt-br/developers/tutorials/how-to-use-tellor-as-your-oracle/index.md index 2dae6657637..05931fb052a 100644 --- a/public/content/translations/pt-br/developers/tutorials/how-to-use-tellor-as-your-oracle/index.md +++ b/public/content/translations/pt-br/developers/tutorials/how-to-use-tellor-as-your-oracle/index.md @@ -1,53 +1,50 @@ --- -title: Como configurar Tellor como seu Oráculo -description: Um guia para começar a integrar o oráculo Tellor ao seu protocolo +title: "Como configurar o Tellor como seu Oráculo" +description: "Um guia para começar a integrar o oráculo Tellor ao seu protocolo" author: "Tellor" lang: pt-br -tags: - - "solidity" - - "contratos inteligentes" - - "oráculos" -skill: intermediate +tags: [ "Solidity", "smart contracts", "oráculos" ] +skill: beginner published: 2021-06-29 -source: Documentação Tellor +source: Tellor Docs sourceUrl: https://docs.tellor.io/tellor/ --- -Pop Quiz: Seu protocolo está quase pronto, mas precisa de um oráculo para obter acesso aos dados off-chain... O que você faz? +Pop Quiz: seu protocolo está quase pronto, mas precisa de um oráculo para ter acesso a dados fora da cadeia... O que você faz? -## (Soft) Pré-requisitos {#soft-prerequisites} +## (Pré-requisitos básicos) {#soft-prerequisites} -Esse texto tem como objetivo tornar o acesso a um conjunto de dados através do uso de um oráculo o mais simples e direto possível. Dito isso, estamos assumindo o seguinte sobre seu nível de habilidade de codificação para focar no aspecto do oráculo. +Esta publicação visa tornar o acesso a uma fonte de dados de oráculo o mais simples e direto possível. Dito isso, estamos assumindo o seguinte sobre o seu nível de habilidade de programação para focar no aspecto do oráculo. Suposições: -- você pode navegar em um terminal +- você consegue navegar em um terminal - você tem o npm instalado - você sabe como usar o npm para gerenciar dependências -Tellor é um oráculo vivo e de código aberto pronto para implementação. Este guia para iniciantes está aqui para mostrar a facilidade com que se pode começar a trabalhar com Tellor, fornecendo ao seu projeto um oráculo totalmente descentralizado e resistente à censura. +Tellor é um oráculo ativo e de código aberto pronto para implementação. Este guia para iniciantes está aqui para mostrar a facilidade com que se pode começar a trabalhar com o Tellor, fornecendo ao seu projeto um oráculo totalmente descentralizado e resistente à censura. ## Visão geral {#overview} -Tellor é um sistema de oráculo onde as partes podem solicitar o valor de um ponto de dados off-chain (por exemplo, BTC/USD) e os repórteres (nós ou participantes) competem para adicionar esse valor a um banco de dados on-chain, acessível por todos os contratos inteligentes do Ethereum. As entradas para este banco de dados são asseguradas por uma rede de repórteres participantes. Tellor utiliza mecanismos de incentivo cripto-econômico, recompensando envios de dados honestos por repórteres e punindo maus atores por meio da emissão do token Tellor, Tributos (TRB) e um mecanismo de disputa. +Tellor é um sistema de oráculo onde as partes podem solicitar o valor de um ponto de dados fora da cadeia (p. ex., BTC/USD) e os relatores competem para adicionar esse valor a um banco de dados em cadeia, acessível a todos os contratos inteligentes da Ethereum. As entradas para este banco de dados são protegidas por uma rede de relatores em staking. O Tellor utiliza mecanismos de incentivo criptoeconômicos, recompensando os envios de dados honestos por relatores e punindo os agentes mal-intencionados através da emissão do token do Tellor, Tributes (TRB), e de um mecanismo de disputa. -Neste tutorial, nós iremos ver: +Neste tutorial, abordaremos: -- Configurar o kit de ferramentas inicial, que você precisará para começar a trabalhar. -- Percorra por um exemplo simples. -- Listar os endereços de teste das redes as quais você pode testar o Tellor atualmente. +- Configurar o kit de ferramentas inicial que você precisará para começar a usar. +- Analisar um exemplo simples. +- Listar os endereços de redes de teste nas quais você pode testar o Tellor atualmente. ## UsingTellor {#usingtellor} -A primeira coisa que você vai querer fazer é instalar as ferramentas básicas necessárias para usar o Tellor como seu oráculo. Use [este pacote](https://github.com/tellor-io/usingtellor) para instalar os contratos de usuário do Tellor: +A primeira coisa que você vai querer fazer é instalar as ferramentas básicas necessárias para usar o Tellor como seu oráculo. Use [este pacote](https://github.com/tellor-io/usingtellor) para instalar os Contratos de Usuário do Tellor: `npm install usingtellor` Uma vez instalado, isso permitirá que seus contratos herdem as funções do contrato 'UsingTellor'. -Excelente! Agora que você tem as ferramentas prontas, vamos passar por um simples exercício onde recuperamos o preço do bitcoin: +Ótimo! Agora que você tem as ferramentas prontas, vamos fazer um exercício simples em que recuperamos o preço do bitcoin: -### Exemplo BTC/USD {#btcusd-example} +### Exemplo de BTC/USD {#btcusd-example} Herde o contrato UsingTellor, passando o endereço do Tellor como um argumento do construtor: @@ -59,7 +56,7 @@ import "usingtellor/contracts/UsingTellor.sol"; contract PriceContract is UsingTellor { uint256 public btcPrice; - //This Contract now has access to all functions in UsingTellor + //Este contrato agora tem acesso a todas as funções em UsingTellor constructor(address payable _tellorAddress) UsingTellor(_tellorAddress) public {} @@ -77,8 +74,8 @@ function setBtcPrice() public { } ``` -Para uma lista completa de endereços de contrato, consulte [aqui](https://docs.tellor.io/tellor/the-basics/contracts-reference). +Para obter uma lista completa de endereços de contrato, consulte [aqui](https://docs.tellor.io/tellor/the-basics/contracts-reference). -Para facilidade de uso, o repositório UsingTellor vem com uma versão do contrato [Tellor Playground](https://github.com/tellor-io/TellorPlayground) para facilitar a integração. Consulte [aqui](https://github.com/tellor-io/sampleUsingTellor#tellor-playground) para obter uma lista de funções úteis. +Para facilitar o uso, o repositório UsingTellor vem com uma versão do contrato [Tellor Playground](https://github.com/tellor-io/TellorPlayground) para uma integração mais fácil. Veja [aqui](https://github.com/tellor-io/sampleUsingTellor#tellor-playground) uma lista de funções úteis. -Para uma implementação mais robusta do oráculo Tellor, confira a lista completa de funções, disponíveis [aqui](https://github.com/tellor-io/usingtellor/blob/master/README.md). +Para uma implementação mais robusta do oráculo Tellor, confira a lista completa de funções disponíveis [aqui](https://github.com/tellor-io/usingtellor/blob/master/README.md). diff --git a/public/content/translations/pt-br/developers/tutorials/how-to-view-nft-in-metamask/index.md b/public/content/translations/pt-br/developers/tutorials/how-to-view-nft-in-metamask/index.md index 3171780741b..b24bdeed295 100644 --- a/public/content/translations/pt-br/developers/tutorials/how-to-view-nft-in-metamask/index.md +++ b/public/content/translations/pt-br/developers/tutorials/how-to-view-nft-in-metamask/index.md @@ -1,36 +1,33 @@ --- -title: Como ver seu NFT na sua carteira (Parte 3/3 da série de tutorial sobre NFT) -description: This tutorial describes how to view an existing NFT on MetaMask! +title: "Como visualizar seu NFT na sua carteira (Parte 3/3 da série de tutoriais de NFT)" +description: Este tutorial descreve como visualizar um NFT existente no MetaMask! author: "Sumi Mudgil" -tags: - - "ERC-721" - - "Alchemy" - - "Solidity" -skill: intermediate +tags: [ "ERC-721", "Alchemy", "Solidity" ] +skill: beginner lang: pt-br published: 2021-04-22 --- -Este tutorial é a Parte 3/3 das séries de Tutorial de NFT, onde vemos nosso NFT recentemente cunhado. No entanto, você pode usar o tutorial geral para qualquer token ERC-721 usando MetaMask, inclusive na rede principal ou em qualquer rede de teste. Se você quiser aprender como cunhar seu próprio NFT no Ethereum, confira a [Parte 1 sobre Como Escrever implantar um contrato inteligente de NFT](/developers/tutorials/how-to-write-and-deploy-an-nft)! +Este tutorial é a Parte 3/3 da série de tutoriais sobre NFT, onde visualizamos nosso NFT recém-mintado. No entanto, você pode usar o tutorial geral para qualquer token ERC-721 usando o MetaMask, inclusive na Mainnet ou em qualquer rede de teste. Se quiser aprender a mintar seu próprio NFT na Ethereum, confira a [Parte 1 sobre Como Escrever e Implantar um Contrato Inteligente de NFT](/developers/tutorials/how-to-write-and-deploy-an-nft)! -Parabéns! Você chegou à parte mais curta e simples da nossa série de tutoriais de NFT: como visualizar seu NFT recém-cunhado em uma carteira virtual. Assim como nas duas partes anteriores, também usaremos o MetaMask aqui. +Parabéns! Você chegou à parte mais curta e simples da nossa série de tutoriais de NFT: como visualizar seu NFT recém-mintado em uma carteira virtual. Usaremos o MetaMask para este exemplo, pois foi o que usamos nas duas partes anteriores. -Como pré-requisito, você já deve ter MetaMask instalado no celular e deve incluir a conta para a qual você cunhou seu NFT. Você pode obter o aplicativo gratuitamente no [iOS](https://apps.apple.com/us/app/metamask-blockchain-wallet/id1438144202) ou [Android](https://play.google.com/store/apps/details?id=io.metamask&hl=en_US&gl=US). +Como pré-requisito, você já deve ter o MetaMask instalado no celular, e ele deve incluir a conta na qual você mintou seu NFT — você pode obter o aplicativo gratuitamente para [iOS](https://apps.apple.com/us/app/metamask-blockchain-wallet/id1438144202) ou [Android](https://play.google.com/store/apps/details?id=io.metamask&hl=en_US&gl=US). ## Passo 1: Defina sua rede para Sepolia {#set-network-to-sepolia} -No topo do aplicativo, pressione o botão "Wallet". Em seguida, você será solicitado a selecionar uma rede. Como nosso NFT foi cunhado na rede Sepolia, você deverá selecionar Sepolia como sua rede. +Na parte superior do aplicativo, pressione o botão “Carteira”, após o qual você será solicitado a selecionar uma rede. Como nosso NFT foi mintado na rede Sepolia, você deverá selecionar Sepolia como sua rede. -![Como definir Sepolia como sua rede no MetaMask Mobile](./goerliMetamask.gif) +![Como definir a Sepolia como sua rede no MetaMask Mobile](./goerliMetamask.gif) -## Passo 2: Adicionar o seu colecionável ao MetaMask {#add-nft-to-metamask} +## Passo 2: Adicionar seu colecionável ao MetaMask {#add-nft-to-metamask} -Quando estiver na rede Sepolia, selecione a guia “Colecionáveis” à direita e adicione o endereço do contrato inteligente NFT e o ID do token ERC-721 do seu NFT - o qual você poderá encontrar no Etherscan com base no hash da transação do seu NFT implantado na Parte II do nosso tutorial. +Assim que estiver na rede Sepolia, selecione a aba “Colecionáveis” à direita e adicione o endereço do contrato inteligente e o ID do token ERC-721 do seu NFT — que você deve conseguir encontrar no Etherscan com base no hash da transação do seu NFT implantado na Parte II do nosso tutorial. -![Como encontrar seu hash de transação e o ID do token ERC-721](./findNFTEtherscan.png) +![Como encontrar o hash da sua transação e o ID do token ERC-721](./findNFTEtherscan.png) -Talvez você precise atualizar algumas vezes para visualizar seu NFT — mas ele estará lá ! +Talvez seja preciso atualizar algumas vezes para visualizar seu NFT — mas ele estará lá ! -![Como enviar seu NFT para a MetaMask](./findNFTMetamask.gif) +![Como fazer o upload do seu NFT para o MetaMask](./findNFTMetamask.gif) -Parabéns! Você cunhou um NFT com sucesso e agora pode visualizá-lo! Mal podemos esperar para ver como você vai conquistar o mundo NFT! +Parabéns! Você mintou um NFT com sucesso e agora pode visualizá-lo! Mal podemos esperar para ver como você vai conquistar o mundo dos NFTs! diff --git a/public/content/translations/pt-br/developers/tutorials/how-to-write-and-deploy-an-nft/index.md b/public/content/translations/pt-br/developers/tutorials/how-to-write-and-deploy-an-nft/index.md index 2d6d8c017c4..3112d45b539 100644 --- a/public/content/translations/pt-br/developers/tutorials/how-to-write-and-deploy-an-nft/index.md +++ b/public/content/translations/pt-br/developers/tutorials/how-to-write-and-deploy-an-nft/index.md @@ -1,36 +1,32 @@ --- -title: Como escrever e implantar um NFT (Primeira parte da série de tutoriais sobre NFT) -description: Este tutorial é a parte 1 de uma série sobre NFTs que o guiará passo a passo sobre como escrever e implantar um contrato inteligente não fungível (token ERC-721) usando Ethereum e o sistema de arquivos do Inter Planetary (IPFS). +title: "Como Escrever e Implantar um NFT (Parte 1/3 da Série de Tutoriais sobre NFT)" +description: "Este tutorial é a parte 1 de uma série sobre NFTs que o guiará passo a passo sobre como escrever e implantar um contrato inteligente não fungível (token ERC-721) usando Ethereum e o sistema de arquivos do Inter Planetary (IPFS)." author: "Sumi Mudgil" -tags: - - "ERC-721" - - "Alchemy" - - "Solidity" - - "contratos inteligentes" -skill: intermediate +tags: [ "ERC-721", "Alchemy", "Solidity", "smart contracts" ] +skill: beginner lang: pt-br published: 2021-04-22 --- Com os NFTs trazendo a blockchain aos olhos do público, agora é uma excelente oportunidade para entender a tendência publicando seu próprio contrato NFT (ERC-721 Token) na blockchain Ethereum! -A Alchemy tem muito orgulho por estar no espaço NFT com os maiores nomes incluindo Makersplace (recentemente atingiu a marca de 69 milhões de doláres em vendas de artes digitais), Dapper Labs (criadores do NBA Top Shot e Crypto Kitties), OpenSea (o maior mercado de NFT do mundo), Zora, Super Rare, NFTfi, Foundation, Enjin, Origin Protocol, Immutable e muito mais. +A Alchemy se orgulha imensamente de impulsionar os maiores nomes no espaço de NFT, incluindo a Makersplace (que recentemente estabeleceu um recorde de venda de arte digital na Christie's por 69 milhões de dólares), Dapper Labs (criadores do NBA Top Shot & Crypto Kitties), OpenSea (o maior marketplace de NFT do mundo), Zora, Super Rare, NFTfi, Foundation, Enjin, Origin Protocol, Immutable e muito mais. -Neste tutorial, nós vamos criar e implantar um contrato inteligente ERC-721 na rede de teste Sepolia usando [MetaMask](https://metamask.io/), [Solidity](https://docs.soliditylang.org/en/v0.8.0/), [Hardhat](https://hardhat.org/), [Pinata](https://pinata.cloud/) e [Alquimia](https://alchemy.com/signup/eth) (não se preocupe caso não entender o que tudo isso significa — explicaremos tudo!). +Neste tutorial, vamos percorrer a criação e implantação de um contrato inteligente ERC-721 na rede de teste Sepolia usando [MetaMask](https://metamask.io/), [Solidity](https://docs.soliditylang.org/en/v0.8.0/), [Hardhat](https://hardhat.org/), [Pinata](https://pinata.cloud/) e [Alchemy](https://alchemy.com/signup/eth) (não se preocupe se você ainda não entende o que tudo isso significa — nós explicaremos!). Na parte 2 deste tutorial, veremos como podemos usar nosso contrato inteligente para gerar NFT, e na Parte 3, explicaremos como ver seu NFT no MetaMask. -E claro, se você tiver dúvidas a qualquer momento, acesso o [Alchemy Discord](https://discord.gg/gWuC7zB) ou visite a página de [Documentação sobre a API NFT da Alchemy](https://docs.alchemy.com/alchemy/enhanced-apis/nft-api)! +E, claro, se você tiver dúvidas a qualquer momento, não hesite em nos contatar no [Discord da Alchemy](https://discord.gg/gWuC7zB) ou visite a [documentação da API de NFT da Alchemy](https://docs.alchemy.com/alchemy/enhanced-apis/nft-api)! -## Etapa 1: Se conectar à rede Ethereum {#connect-to-ethereum} +## Etapa 1: Conecte-se à rede Ethereum {#connect-to-ethereum} -Existem várias maneiras de fazer solicitações para a blockchain Ethereum, mas para facilitar as coisas, usaremos uma conta gratuita na [Alchemy](https://alchemy.com/signup/eth), uma plataforma e API de desenvolvedores de blockchain que nos permite nos comunicar com a cadeia Ethereum sem ter que executar os nossos próprios nós. +Há várias maneiras de fazer solicitações para a blockchain Ethereum, mas, para facilitar, usaremos uma conta gratuita na [Alchemy](https://alchemy.com/signup/eth), uma plataforma de desenvolvimento de blockchain e API que nos permite comunicar com a blockchain Ethereum sem ter que executar nossos próprios nós. -Neste tutorial, também aproveitaremos as ferramentas de desenvolvedor da Alchemy para fins de monitoramento e análise, para entender o que está acontecendo nos bastidores da nossa implantação de contrato inteligente. Se você ainda não tiver uma conta da Alchemy, inscreva-se gratuitamente [aqui](https://alchemy.com/signup/eth). +Neste tutorial, também aproveitaremos as ferramentas de desenvolvedor da Alchemy para fins de monitoramento e análise, para entender o que está acontecendo nos bastidores da nossa implantação de contrato inteligente. Se você ainda não tem uma conta na Alchemy, pode se inscrever gratuitamente [aqui](https://alchemy.com/signup/eth). -## Etapa 2: Criar seu aplicativo (e chave de API) {#make-api-key} +## Etapa 2: Crie seu aplicativo (e chave de API) {#make-api-key} -Assim que criar uma conta na Alchemy, você pode gerar uma chave de API criando um "app". Isso nos permitirá fazer solicitações à rede de teste Sepolia. Confira [este guia](https://docs.alchemyapi.io/guides/choosing-a-network) se você está curioso para aprender mais sobre as redes de teste. +Assim que criar uma conta na Alchemy, você pode gerar uma chave de API criando um "app". Isso nos permitirá fazer solicitações à rede de teste Sepolia. Confira [este guia](https://docs.alchemyapi.io/guides/choosing-a-network) se tiver curiosidade em aprender mais sobre redes de teste. 1. Vá até a página "Create App" no painel da Alchemy, passe o mouse sobre a palavra "Apps" na barra de navegação e clique em "Create App" @@ -42,84 +38,97 @@ Assim que criar uma conta na Alchemy, você pode gerar uma chave de API criando 3. Clique em "Create App", e é isso e tudo! Seu app deveria aparecer na tabela abaixo. -## Etapa 3: Criar uma conta Ethereum (endereço) {#create-eth-address} +## Etapa 3: Crie uma conta Ethereum (endereço) {#create-eth-address} -Precisamos de uma conta Ethereum para enviar e receber transações. Para este tutorial, usaremos uma carteira virtual no navegador, a MetaMask, para gerenciar o endereço da sua conta Ethereum. Se você quiser entender mais sobre como as transações no Ethereum funcionam, confira [esta página](/developers/docs/transactions/) na Fundação Ethereum. +Precisamos de uma conta Ethereum para enviar e receber transações. Para este tutorial, usaremos uma carteira virtual no navegador, a MetaMask, para gerenciar o endereço da sua conta Ethereum. Se quiser entender mais sobre como as transações na Ethereum funcionam, confira [esta página](/developers/docs/transactions/) da Ethereum Foundation. -Você pode baixar e criar uma conta MetaMask gratuitamente [neste link](https://metamask.io/download). Quando você estiver criando uma conta, ou se você já tiver uma, certifique-se de mudar para a “Sepolia Test Network” no canto superior direito (para que não lidemos com dinheiro real). +Você pode baixar e criar uma conta MetaMask gratuitamente [aqui](https://metamask.io/download). Quando você estiver criando uma conta, ou se você já tiver uma, certifique-se de mudar para a “Sepolia Test Network” no canto superior direito (para que não lidemos com dinheiro real). ![Defina Sepolia como sua rede](./metamask-goerli.png) -## Etapa 4: Adicionar ether de um faucet {#step-4-add-ether-from-a-faucet} +## Etapa 4: Adicione ether de um Faucet {#step-4-add-ether-from-a-faucet} -Para implementar nosso contrato inteligente na rede de teste, precisaremos de alguns ETHs de imitação. Para obter ETH, você pode acessar a [Torneira da Sepolia](https://sepoliafaucet.com/) hospedada pela Alchemy, fazer login, inserir o endereço da sua conta e clicar em "Enviar-me ETH". Você deveria ver o ETH na sua conta MetaMask logo depois! +Para implementar nosso contrato inteligente na rede de teste, precisaremos de alguns ETHs de imitação. Para obter ETH, você pode ir para o [Sepolia Faucet](https://sepoliafaucet.com/) hospedado pela Alchemy, fazer login, inserir o endereço da sua conta e clicar em “Envie-me ETH”. Você deveria ver o ETH na sua conta MetaMask logo depois! -## Etapa 5: Verificar seu saldo {#check-balance} +## Etapa 5: Verifique seu saldo {#check-balance} -Para verificar novamente que temos saldo, vamos fazer uma solicitação através da ferramenta [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) fornecida pelo [compositor da Alchemy](https://composer.alchemyapi.io?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D). Ele mostrará a quantidade de ETH em nossa carteira. Depois de inserir o endereço da sua conta da MetaMask e clicar em "Send Request", você verá uma resposta como esta: +Para conferir nosso saldo, vamos fazer uma solicitação [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) usando a [ferramenta de composição da Alchemy](https://composer.alchemyapi.io?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D). Ele mostrará a quantidade de ETH em nossa carteira. Depois de inserir o endereço da sua conta da MetaMask e clicar em "Send Request", você verá uma resposta como esta: + ``` `{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"}` + ``` -> **Nota** Este resultado está em wei, não em ETH. Lembre-se de que o wei é a menor unidade do ether. A conversão de wei para ETH é 1 eth = 1018 wei. Então, se convertemos 0xde0b6b3a7640000 para decimal, temos 1\*1018 wei, que é igual a 1 ETH. +> **Observação**: este resultado está em wei, não em ETH. Lembre-se de que "Wei" é a menor unidade de ether. A conversão de wei para ETH é 1 eth = 1018 wei. Então, se convertemos 0xde0b6b3a7640000 para decimal, temos 1\*1018 wei, que é igual a 1 ETH. Ufa! O nosso dinheiro falso está todo lá. -## Etapa 6: Dar início a nosso projeto {#initialize-project} +## Etapa 6: Inicialize nosso projeto {#initialize-project} Primeiro, precisamos criar uma pasta para o nosso projeto. Navegue até sua linha de comando e digite: + ``` mkdir my-nft cd my-nft + ``` -Agora que estamos dentro da pasta do nosso projeto, vamos usar npm init para inicializá-lo. Se você ainda não tiver o npm instalado, siga [estas instruções](https://docs.alchemyapi.io/alchemy/guides/alchemy-for-macs#1-install-nodejs-and-npm) (nós também vamos precisar do [Node.js](https://nodejs.org/en/download/), então baixe isso também!). +Agora que estamos dentro da pasta do nosso projeto, vamos usar npm init para inicializá-lo. Se você ainda não tem o npm instalado, siga [estas instruções](https://docs.alchemyapi.io/alchemy/guides/alchemy-for-macs#1-install-nodejs-and-npm) (também vamos precisar do [Node.js](https://nodejs.org/en/download/), então baixe-o também!). + ``` npm init + ``` Não importa realmente como você responde às questões de instalação; aqui está o que utilizamos de referência: + ```json - package name: (my-nft) - version: (1.0.0) - description: My first NFT! - entry point: (index.js) - test command: - git repository: - keywords: - author: - license: (ISC) - About to write to /Users/thesuperb1/Desktop/my-nft/package.json: + nome do pacote: (my-nft) + versão: (1.0.0) + descrição: Meu primeiro NFT! + ponto de entrada: (index.js) + comando de teste: + repositório git: + palavras-chave: + autor: + licença: (ISC) + Prestes a escrever em /Users/thesuperb1/Desktop/my-nft/package.json: { "name": "my-nft", "version": "1.0.0", - "description": "My first NFT!", + "description": "Meu primeiro NFT!", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Erro: nenhum teste especificado\" && exit 1" }, "author": "", "license": "ISC" } ``` + Aprove o package.json e estamos prontos para começar! -## Etapa 7: Instalar o [Hardhat](https://hardhat.org/getting-started/#overview) {#install-hardhat} +## Etapa 7: Instale o [Hardhat](https://hardhat.org/getting-started/#overview) {#install-hardhat} Hardhat é um ambiente de desenvolvimento para compilar, implementar, testar e depurar seu software de Ethereum. Ele ajuda os desenvolvedores na criação de contratos inteligentes e dapps localmente antes de implantar na cadeia real. Dentro do nosso projeto my-nft execute: + ``` npm install --save-dev hardhat + ``` -Para mais detalhes, confira esta página sobre as [instruções de instalação](https://hardhat.org/getting-started/#overview). +Confira esta página para mais detalhes sobre as [instruções de instalação](https://hardhat.org/getting-started/#overview). -## Etapa 8: Criar o projeto Hardhat {#create-hardhat-project} +## Etapa 8: Crie um projeto Hardhat {#create-hardhat-project} Dentro da nossa pasta de projeto, execute: + ``` npx hardhat + ``` Você deve então ver uma mensagem de boas-vindas e a opção de selecionar o que quer fazer. Selecione "criar uma hardhat.config.js vazia": + ``` 888 888 888 888 888 888 888 888 888 888 888 888 888 888 888 @@ -128,37 +137,40 @@ Você deve então ver uma mensagem de boas-vindas e a opção de selecionar o qu 888 888 .d888888 888 888 888 888 888 .d888888 888 888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. 888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - 👷 Welcome to Hardhat v2.0.11 👷‍ - ? O que você deseja fazer? … - Create a sample project - ❯ Create an empty hardhat.config.js - Quit + 👷 Bem-vindo ao Hardhat v2.0.11 👷‍ + ? O que você quer fazer? … + Criar um projeto de exemplo + ❯ Criar um hardhat.config.js vazio + Sair + ``` Isso vai gerar um arquivo hardhat.config.js, no qual especificaremos todas as configurações para o nosso projeto (no passo 13). -## Etapa 9: Adicionar as pastas do projeto {#add-project-folders} +## Etapa 9: Adicione pastas ao projeto {#add-project-folders} Para manter a organização do nosso projeto, vamos criar duas novas pastas. Navegue até o diretório raiz do seu projeto na sua linha de comando e digite: + ``` mkdir contracts mkdir scripts + ``` - contracts/ é onde manteremos o nosso código de contrato inteligente para o NFT - scripts/ é onde manteremos scripts para implantar e interagir com nosso contrato inteligente -## Etapa 10: Escrever nosso contrato {#write-contract} +## Etapa 10: Escreva nosso contrato {#write-contract} -Agora que nosso ambiente de trabalho está configurado, iremos para a parte mais emocionante: _escrever nosso contrato de código inteligente!_ +Agora que nosso ambiente está configurado, vamos para a parte mais empolgante: _escrever o código do nosso contrato inteligente!_ -Abra o projeto my-nft no seu editor favorito (nós gostamos do [VSCode](https://code.visualstudio.com/)). Os contratos inteligentes são escritos em uma linguagem chamada Solidity, que usaremos para escrever nosso contrato inteligente MyNFT.sol. +Abra o projeto my-nft em seu editor favorito (gostamos do [VSCode](https://code.visualstudio.com/)). Os contratos inteligentes são escritos em uma linguagem chamada Solidity, que usaremos para escrever nosso contrato inteligente MyNFT.sol. -1. Navegue até a pasta de `contracts` e crie um novo arquivo chamado MyNFT.sol +1. Navegue para a pasta `contracts` e crie um novo arquivo chamado MyNFT.sol -2. Abaixo está o nosso código de contrato inteligente NFT, nossa base para a implementação do ERC-721 da biblioteca [OpenZeppelin](https://docs.openzeppelin.com/contracts/3.x/erc721). Copie e cole o conteúdo abaixo no seu arquivo MyNFT.sol. +2. Abaixo está nosso código de contrato inteligente NFT, que baseamos na implementação ERC-721 da biblioteca [OpenZeppelin](https://docs.openzeppelin.com/contracts/3.x/erc721). Copie e cole o conteúdo abaixo no seu arquivo MyNFT.sol. ```solidity - //Contract based on [https://docs.openzeppelin.com/contracts/3.x/erc721](https://docs.openzeppelin.com/contracts/3.x/erc721) + //Contrato baseado em [https://docs.openzeppelin.com/contracts/3.x/erc721](https://docs.openzeppelin.com/contracts/3.x/erc721) // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; @@ -188,31 +200,31 @@ Abra o projeto my-nft no seu editor favorito (nós gostamos do [VSCode](https:// } ``` -3. Como estamos herdando classes da biblioteca de contratos OpenZeppelin, na linha de comando execute `npm install @openzeppelin/contracts` para instalar a biblioteca em nossa pasta. +3. Como estamos herdando classes da biblioteca de contratos OpenZeppelin, na sua linha de comando execute `npm install @openzeppelin/contracts^4.0.0` para instalar a biblioteca em nossa pasta. -Então, o que esse código _faz_ exatamente? Vamos por partes, linha por linha. +Então, o que este código _faz_ exatamente? Vamos por partes, linha por linha. -No topo do nosso contrato inteligente, importamos três [classes de contrato inteligente OpenZeppelin](https://openzeppelin.com/): +No topo do nosso contrato inteligente, importamos três classes de contrato inteligente [OpenZeppelin](https://openzeppelin.com/): -- @openzeppelin/contracts/token/ERC721/ERC721.sol contém a implementação do padrão ERC-721, que nosso contrato inteligente NFT herdará. (Para ser um NFT válido, seu contrato inteligente deve implementar todos os métodos do padrão ERC-721.) Para saber mais sobre as funções herdadas do ERC-721, confira a definição da interface [aqui](https://eips.ethereum.org/EIPS/eip-721). +- @openzeppelin/contracts/token/ERC721/ERC721.sol contém a implementação do padrão ERC-721, que nosso contrato inteligente NFT herdará. (Para ser um NFT válido, seu contrato inteligente deve implementar todos os métodos do padrão ERC-721.) Para saber mais sobre as funções ERC-721 herdadas, confira a definição da interface [aqui](https://eips.ethereum.org/EIPS/eip-721). - @openzeppelin/contracts/utils/Counters.sol fornece contadores que só podem ser incrementados ou diminuídos por um. Nosso contrato inteligente usa um contador para acompanhar o número total de NFTs impressos e definir o ID exclusivo em nosso novo NFT. (Cada NFT cunhado usando um contrato inteligente deve ter um ID único – aqui nosso ID exclusivo é determinado pelo número total de NFTs existentes. Por exemplo, o primeiro NFT que cunhamos com o nosso contrato inteligente tem um ID igual a "1," nosso segundo NFT tem um ID igual a "2," etc.) -- @openzeppelin/contratos/access/Ownable.sol configura [controle de acesso](https://docs.openzeppelin.com/contracts/3.x/access-control) em nosso contrato inteligente, então apenas o proprietário do contrato inteligente (você) pode 'cunhar' NFTs. (Observação, incluir controle de acesso é inteiramente uma preferência. Se você quer que qualquer pessoa consiga gerar um NFT usando seu contrato inteligente, remove a palavra "Ownable" na linha 10 e "onlyOwner" na linha 17.) +- @openzeppelin/contracts/access/Ownable.sol configura o [controle de acesso](https://docs.openzeppelin.com/contracts/3.x/access-control) em nosso contrato inteligente, de modo que apenas o proprietário do contrato inteligente (você) pode cunhar NFTs. (Observação, incluir controle de acesso é inteiramente uma preferência. Se você quer que qualquer pessoa consiga gerar um NFT usando seu contrato inteligente, remove a palavra "Ownable" na linha 10 e "onlyOwner" na linha 17.) -Depois de seguir nossas instruções de importação, temos o nosso contrato inteligente de NFT, que é surpreendentemente curto – contém apenas um contador, um construtor e uma única função! Isso se deve aos nossos contratos OpenZeppelin herdados, que implementam a maioria dos métodos de que precisamos para criar um NFT, tal como `ownerOf`, que retorna o proprietário do NFT, e `transferFrom`, que transfere a propriedade do NFT de uma conta para outra. +Depois de seguir nossas instruções de importação, temos o nosso contrato inteligente de NFT, que é surpreendentemente curto – contém apenas um contador, um construtor e uma única função! Isso é graças aos nossos contratos OpenZeppelin herdados, que implementam a maioria dos métodos que precisamos para criar um NFT, como `ownerOf`, que retorna o proprietário do NFT, e `transferFrom`, que transfere a propriedade do NFT de uma conta para outra. No nosso construtor ERC-721, você notará que transmitimos duas cadeias de caracteres: "MyNFT" e "NFT" A primeira variável é o nome do contrato inteligente e a segunda é símbolo dele. Você pode nomear cada uma dessas variáveis como quiser! -Finalmente, temos nossa função `mintNFT(destinatário de endereço, string memory tokenURI)`, que nos permite cunhar um NFT! Você vai notar que essa função recebe duas variáveis: +Finalmente, temos nossa função `mintNFT(address recipient, string memory tokenURI)` que nos permite cunhar um NFT! Você vai notar que essa função recebe duas variáveis: -- `address recipient` especifica o endereço que receberá o seu NFT recém-cunhado +- `address recipient` especifica o endereço que receberá seu NFT recém-cunhado -- `string memory tokenURI` é uma string que deve ser resolvida em um documento JSON que descreve os metadados do NFT. Os metadados de um NFT são o que realmente o torna realidade, permitindo que tenha propriedades configuráveis, como um nome, descrição, imagem e outros atributos. Na parte 2 deste tutorial, descreveremos como configurar este metadado. +- `string memory tokenURI` é uma string que deve ser resolvida para um documento JSON que descreve os metadados do NFT. Os metadados de um NFT são o que realmente o torna realidade, permitindo que tenha propriedades configuráveis, como um nome, descrição, imagem e outros atributos. Na parte 2 deste tutorial, descreveremos como configurar este metadado. -`mintNFT` chama alguns métodos da biblioteca ERC-721 herdada, e retorna um número que representa a ID do NFT recém-cunhado. +`mintNFT` chama alguns métodos da biblioteca ERC-721 herdada e, por fim, retorna um número que representa o ID do NFT recém-cunhado. -## Etapa 11: Vincular as contas MetaMask e Alchemy a seu projeto {#connect-metamask-and-alchemy} +## Etapa 11: Conecte o MetaMask e a Alchemy ao seu projeto {#connect-metamask-and-alchemy} Agora que criamos uma carteira MetaMask, uma conta Alchemy, e escrevemos o nosso contrato inteligente, é hora de vincular os três. @@ -222,38 +234,44 @@ Para saber mais sobre o envio de transações, confira [este tutorial](/develope Primeiro, instale o pacote dotenv na pasta do seu projeto: + ``` npm install dotenv --save + ``` -Então crie um arquivo `.env` no diretório raiz do nosso projeto e adicione sua chave privada do MetaMask e sua URL HTTP da API Alchemy a ele. +Em seguida, crie um arquivo `.env` no diretório raiz do nosso projeto e adicione sua chave privada do MetaMask e o URL da API HTTP da Alchemy a ele. - Siga [estas instruções](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key) para exportar sua chave privada do MetaMask - Veja abaixo como obter o URL da API HTTP Alchemy e copiá-la para a área de transferência -![Copie o URL da API Alchemy](./copy-alchemy-api-url.gif) +![Copie a URL da sua API da Alchemy](./copy-alchemy-api-url.gif) -Seu arquivo `.env` ficará assim: +Seu `.env` deve agora se parecer com isto: - API_URL="https://eth-sepolia.g.alchemy.com/v2/your-api-key" - PRIVATE_KEY="your-metamask-private-key" + ``` + API_URL="https://eth-sepolia.g.alchemy.com/v2/sua-chave-de-api" + PRIVATE_KEY="sua-chave-privada-metamask" + ``` Para realmente conectá-las ao nosso código, referenciaremos essas variáveis em nosso arquivo hardhat.config.js na etapa 13. -## Etapa 12: Instalar o Ethers.js {#install-ethers} +## Etapa 12: Instale o Ethers.js {#install-ethers} -Ethers.js é uma biblioteca que facilita a interação e o envio de solicitações ao Ethereum ao incorporar [métodos padrões JSON-RPC](/developers/docs/apis/json-rpc/) a outros métodos mais amigáveis ao usuário. +Ethers.js é uma biblioteca que facilita a interação e a realização de solicitações à Ethereum, envolvendo os [métodos JSON-RPC padrão](/developers/docs/apis/json-rpc/) com métodos mais amigáveis ao usuário. -Hardhat torna muito fácil a integração de [plugins](https://hardhat.org/plugins/), para ferramentas adicionais e funcionalidades extendidas. Aproveitaremos o [plugin Ethers](https://hardhat.org/docs/plugins/official-plugins#hardhat-ethers) para implantação de contratos. ([Ethers.js](https://github.com/ethers-io/ethers.js/) tem alguns métodos de implantação de contratos bastante claros). +O Hardhat torna muito fácil a integração de [Plugins](https://hardhat.org/plugins/) para ferramentas adicionais e funcionalidades estendidas. Aproveitaremos o [plugin Ethers](https://hardhat.org/docs/plugins/official-plugins#hardhat-ethers) para a implantação de contratos ([Ethers.js](https://github.com/ethers-io/ethers.js/) has some super clean contract deployment methods). -No diretório do projeto, digite: +No diretório do seu projeto, digite: + ``` npm install --save-dev @nomiclabs/hardhat-ethers ethers@^5.0.0 + ``` Também precisaremos de ethers em nosso hardhat.config.js na próxima etapa. -## Etapa 13: Atualizar hardhat.config.js {#update-hardhat-config} +## Etapa 13: Atualize o hardhat.config.js {#update-hardhat-config} Até aqui, já adicionamos diversas dependências e plugins. Agora precisamos atualizar o hardhat.config.js para que nosso projeto reconheça todos eles. @@ -279,30 +297,32 @@ Atualize seu hardhat.config.js para ficar assim: } ``` -## Etapa 14: Compilar nosso contrato {#compile-contract} +## Etapa 14: Compile nosso contrato {#compile-contract} Para ter certeza de que tudo está funcionando, vamos compilar nosso contrato. A tarefa de compilação é uma das tarefas integradas do Hardhat. Na linha de comando, execute: + ``` npx hardhat compile + ``` -Você pode receber o aviso do identificador de licença SPDX não fornecido no arquivo fonte, mas não há necessidade de se preocupar com isso. Esperemos que tudo mais esteja bem! Se não, você sempre pode enviar uma mensagem no [discord Alchemy](https://discord.gg/u72VCg3). +Você pode receber o aviso do identificador de licença SPDX não fornecido no arquivo fonte, mas não há necessidade de se preocupar com isso. Esperemos que tudo mais esteja bem! Se não, você sempre pode enviar uma mensagem no [Discord da Alchemy](https://discord.gg/u72VCg3). -## Etapa 15: Escrever nosso script de implantação {#write-deploy} +## Etapa 15: Escreva nosso script de implantação {#write-deploy} Agora que nosso contrato está escrito e nosso arquivo de configuração está pronto, é hora de escrever o script de implantação do contrato. -Navegue até a pasta `scripts/` e crie um novo arquivo chamado `deploy.js`, adicionando o seguinte conteúdo: +Navegue até a pasta `scripts/` e crie um novo arquivo chamado `deploy.js`, adicionando o seguinte conteúdo a ele: ```js async function main() { const MyNFT = await ethers.getContractFactory("MyNFT") - // Start deployment, returning a promise that resolves to a contract object + // Inicia a implantação, retornando uma promessa que se resolve em um objeto de contrato const myNFT = await MyNFT.deploy() await myNFT.deployed() - console.log("Contract deployed to address:", myNFT.address) + console.log("Contrato implantado para o endereço:", myNFT.address) } main() @@ -313,40 +333,48 @@ main() }) ``` -A Hardhat fez um trabalho incrível ao explicar o que cada uma dessas linhas de código faz em seu [Tutorial sobre contratos](https://hardhat.org/tutorial/testing-contracts.html#writing-tests). Adotamos aqui as explicações deles. +A Hardhat faz um trabalho incrível explicando o que cada uma dessas linhas de código faz em seu [tutorial de Contratos](https://hardhat.org/tutorial/testing-contracts.html#writing-tests), nós adotamos as explicações deles aqui. + ``` const MyNFT = await ethers.getContractFactory("MyNFT"); + ``` Uma ContractFactory em ethers.js é uma abstração usada para implantar novos contratos inteligentes, então a MyNFT aqui representa uma fábrica para instâncias do nosso contrato NFT. Ao usar o plug-in hardhat-ethers, as instâncias ContractFactory e Contract são conectadas ao primeiro signatário por padrão. + ``` const myNFT = await MyNFT.deploy(); + ``` Ao chamar deploy() em uma ContractFactory, a implantação se iniciará e retornará uma Promise que se resolve em um Contract. Este é o objeto que tem um método para cada uma de nossas funções de contrato inteligente. -## Etapa 16: Implantar nosso contrato {#deploy-contract} +## Etapa 16: Implante nosso contrato {#deploy-contract} Finalmente estamos prontos para implantar o nosso contrato inteligente! Navegue de volta para a raiz do diretório do seu projeto e, na linha de comando, execute: + ``` npx hardhat --network sepo lia run scripts/deploy.js + ``` Você deverá ver algo assim: + ``` Contrato implantado no endereço: 0x4C5266cCc4b3F426965d2f51b6D910325a0E7650 + ``` -Se nós formos ao [Sepolia etherscan](https://sepolia.etherscan.io/) e procurarmos o endereço do nosso contrato, poderemos ver que ele foi implantado com sucesso. Se você não puder ver o endereço imediatamente, por favor, aguarde um momento, pois pode levar algum tempo. A transação ficará parecida com isto: +Se formos ao [Etherscan da Sepolia](https://sepolia.etherscan.io/) e pesquisarmos o endereço do nosso contrato, poderemos ver que ele foi implantado com sucesso. Se você não puder ver o endereço imediatamente, por favor, aguarde um momento, pois pode levar algum tempo. A transação ficará parecida com isto: -![Veja o seu endereço de transação no Etherscan](./etherscan-sepoila-contract-creation.png) +![Veja o endereço da sua transação no Etherscan](./etherscan-sepoila-contract-creation.png) -O endereço do remetente (From) deve corresponder ao seu endereço da conta MetaMask e o endereço do destinatário (To) deve dizer "Contract Creation". Se clicarmos na transação, veremos o nosso endereço de contrato no campo "To": +O endereço do remetente (From) deve corresponder ao endereço da sua conta MetaMask e o endereço do destinatário (To) indicará “Criação de Contrato”. Se clicarmos na transação, veremos o nosso endereço de contrato no campo "To": -![Veja o seu endereço de contrato no Etherscan](./etherscan-sepolia-tx-details.png) +![Veja o endereço do seu contrato no Etherscan](./etherscan-sepolia-tx-details.png) Sim! Você acabou de implantar seu contrato inteligente NFT na cadeia Ethereum (testnet)! -Para entender o que está acontecendo nos bastidores, vamos navegar até a guia Explorer no [painel do Alchemy](https://dashboard.alchemyapi.io/explorer). Se você tem vários aplicativos Alchemy certifique-se de filtrar por app e selecionar "MyNFT". +Para entender o que está acontecendo nos bastidores, vamos navegar para a guia Explorer em nosso [painel da Alchemy](https://dashboard.alchemyapi.io/explorer). Se você tem vários aplicativos Alchemy, certifique-se de filtrar por app e selecionar "MyNFT". -![Exibir chamadas feitas "em segundo plano" com o Explorer Dashboard do Alquimia](./alchemy-explorer-goerli.png) +![Veja as chamadas feitas “nos bastidores” com o painel do Explorer da Alchemy](./alchemy-explorer-goerli.png) -Aqui você verá um punhado de chamadas JSON-RPC que Hardhat/Ethers fizeram em segundo plano para nós quando chamamos a função .deploy() . Dois importantes pontos a destacar aqui são [eth_sendRawTransaction](/developers/docs/apis/json-rpc/#eth_sendrawtransaction), que é a solicitação para realmente escrever nosso contrato inteligente na cadeia Sepolia, e [eth_getTransactionByHash](/developers/docs/apis/json-rpc/#eth_gettransactionbyhash), que é uma solicitação para ler informações sobre nossa transação dado o hash (um padrão típico ao enviar transações). Para saber mais sobre o envio de transações, confira [este tutorial](/developers/tutorials/sending-transactions-using-web3-and-alchemy/) sobre como enviar transações usando a web3. +Aqui você verá um punhado de chamadas JSON-RPC que Hardhat/Ethers fizeram em segundo plano para nós quando chamamos a função .deploy() . Dois pontos importantes a serem mencionados aqui são [eth_sendRawTransaction](/developers/docs/apis/json-rpc/#eth_sendrawtransaction), que é a solicitação para realmente escrever nosso contrato inteligente na blockchain Sepolia, e [eth_getTransactionByHash](/developers/docs/apis/json-rpc/#eth_gettransactionbyhash), que é uma solicitação para ler informações sobre nossa transação, dado o hash (um padrão típico ao enviar transações). Para saber mais sobre o envio de transações, confira este tutorial sobre o [envio de transações usando Web3](/developers/tutorials/sending-transactions-using-web3-and-alchemy/). -Isso é tudo para a Parte 1 deste tutorial. Na [Parte 2, interagiremos com o nosso contrato inteligente cunhando um NFT](/developers/tutorials/how-to-mint-an-nft/), e na [Parte 3, mostraremos como ver o seu NFT na sua carteira Ethereum](/developers/tutorials/how-to-view-nft-in-metamask/)! +Isso é tudo para a Parte 1 deste tutorial. Na [Parte 2, vamos interagir de fato com nosso contrato inteligente cunhando um NFT](/developers/tutorials/how-to-mint-an-nft/), e na [Parte 3, mostraremos como visualizar seu NFT em sua carteira Ethereum](/developers/tutorials/how-to-view-nft-in-metamask/)! diff --git a/public/content/translations/pt-br/developers/tutorials/interact-with-other-contracts-from-solidity/index.md b/public/content/translations/pt-br/developers/tutorials/interact-with-other-contracts-from-solidity/index.md index 53c8a1a6b79..bc125e0b684 100644 --- a/public/content/translations/pt-br/developers/tutorials/interact-with-other-contracts-from-solidity/index.md +++ b/public/content/translations/pt-br/developers/tutorials/interact-with-other-contracts-from-solidity/index.md @@ -3,11 +3,13 @@ title: Interaja com outros contratos de Solidity description: Como implantar um contrato inteligente a partir de um contrato existente e interagir com ele author: "jdourlens" tags: - - "contratos Inteligentes" - - "solidity" - - "remix" - - "implementação" - - "componibilidade" + [ + "smart contracts", + "Solidity", + "Remix", + "implantação", + "componibilidade" + ] skill: advanced lang: pt-br published: 2020-04-05 @@ -16,9 +18,9 @@ sourceUrl: https://ethereumdev.io/interact-with-other-contracts-from-solidity/ address: "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE" --- -Nos tutoriais anteriores, aprendemos muito [como publicar seu primeiro contrato inteligente](/developers/tutorials/deploying-your-first-smart-contract/) e adicionar alguns recursos a ele, como [controlar o acesso com modificadores](https://ethereumdev.io/organize-your-code-and-control-access-to-your-smart-contract-with-modifiers/) ou [manipulação de erros no Solidity](https://ethereumdev.io/handle-errors-in-solidity-with-require-and-revert/). Neste tutorial, aprenderemos como implantar um contrato inteligente a partir de um contrato existente e interagir com ele. +Nos tutoriais anteriores, aprendemos muito sobre [como implantar seu primeiro contrato inteligente](/developers/tutorials/deploying-your-first-smart-contract/) e adicionar alguns recursos a ele, como [controle de acesso com modificadores](https://ethereumdev.io/organize-your-code-and-control-access-to-your-smart-contract-with-modifiers/) ou [tratamento de erros no Solidity](https://ethereumdev.io/handle-errors-in-solidity-with-require-and-revert/). Neste tutorial, aprenderemos como implantar um contrato inteligente a partir de um contrato existente e interagir com ele. -Faremos um contrato que permite a qualquer pessoa ter seu próprio contrato inteligente`Counter`, criando uma fábrica para ele. Seu nome será `CounterFactory`. De início, aqui está o código do nosso primeiro contrato inteligente `Counter`: +Faremos um contrato que permite a qualquer pessoa ter seu próprio contrato inteligente `Counter`, criando uma fábrica para ele. Seu nome será `CounterFactory`. Primeiro, aqui está o código do nosso contrato inteligente `Counter` inicial: ```solidity pragma solidity 0.5.17; @@ -31,12 +33,12 @@ contract Counter { modifier onlyOwner(address caller) { - require(caller == _owner, "You're not the owner of the contract"); + require(caller == _owner, "Você não é o proprietário do contrato"); _; } modifier onlyFactory() { - require(msg.sender == _factory, "You need to use the factory"); + require(msg.sender == _factory, "Você precisa usar a fábrica"); _; } @@ -56,19 +58,19 @@ contract Counter { } ``` -Note que modificamos ligeiramente o código do contrato para manter um controle do endereço da fábrica e do endereço do proprietário. Quando você chamar um código de contrato de outro contrato, o msg.sender irá consultar o endereço da nossa fábrica de contratos. Este é **um ponto muito importante para entender** como usar um contrato para interagir com outros contratos é uma prática comum. Você deve, portanto, cuidar de quem é o remetente em casos complexos. +Observe que modificamos ligeiramente o código do contrato para manter um registro do endereço da fábrica e do endereço do proprietário do contrato. Quando você chama o código de um contrato a partir de outro, o `msg.sender` se referirá ao endereço da nossa fábrica de contratos. Este é **um ponto muito importante a ser entendido**, pois usar um contrato para interagir com outros é uma prática comum. Portanto, você deve ter cuidado com quem é o remetente em casos complexos. -Para isso também adicionamos um modificador de `onlyFactory` que certifica-se de que a função de mudança de estado só pode ser chamada pela fábrica que passará o chamador original como um parâmetro. +Para isso, também adicionamos um modificador `onlyFactory` que garante que a função que altera o estado só possa ser chamada pela fábrica, que passará o chamador original como um parâmetro. -Dentro de nossa nova `CounterFactory` que gerenciará todos os outros Counters, adicionaremos um mapeamento que associará o proprietário ao endereço de seu contrato: +Dentro de nossa nova `CounterFactory`, que gerenciará todos os outros `Counters`, adicionaremos um mapeamento que associará um proprietário ao endereço de seu contrato `Counter`: ```solidity mapping(address => Counter) _counters; ``` -Na Ethereum, o mapeamento é equivalente a objetos em Javascript. Eles permitem mapear uma chave do tipo A para um valor do tipo B. Neste caso, mapeamos o endereço de um proprietário com a instância de seu Counter. +No Ethereum, mapeamentos são o equivalente a objetos em JavaScript; eles permitem mapear uma chave do tipo A para um valor do tipo B. Nesse caso, mapeamos o endereço de um proprietário com a instância de seu `Counter`. -Instanciar um novo Counter para alguém ficará assim: +Instanciar um novo `Counter` para alguém ficará assim: ```solidity function createCounter() public { @@ -77,9 +79,9 @@ Instanciar um novo Counter para alguém ficará assim: } ``` -Primeiro, verificamos se a pessoa já possui um Counter. Se ele não tem um Counter, instanciamos um novo Counter, passando seu endereço para o construtor `Counter` e atribuímos a instância recém-criada para o mapeamento. +Primeiro, verificamos se a pessoa já possui um `Counter`. Se a pessoa não possuir um `Counter`, nós instanciamos um novo, passando o endereço dela para o construtor `Counter`, e atribuímos a instância recém-criada ao mapeamento. -Para obter a contagem de um Counter específico, fica assim: +Para obter a contagem de um `Counter` específico, o código será assim: ```solidity function getCount(address account) public view returns (uint256) { @@ -92,9 +94,9 @@ function getMyCount() public view returns (uint256) { } ``` -A primeira função verifica se o contrato do Counter existe para um determinado endereço e, em seguida, chama o método `getCount` a partir da instância. A segunda função: `getMyCount` é apenas um breve fim para passar a função msg.sender diretamente para a função `getCount`. +A primeira função verifica se o contrato `Counter` existe para um determinado endereço e, em seguida, chama o método `getCount` da instância. A segunda função, `getMyCount`, é apenas um atalho para passar o `msg.sender` diretamente para a função `getCount`. -A função `increment` é bastante parecida, mas passa o remetente da transação original para o contrato `Counter`: +A função `increment` é bem parecida, mas passa o remetente da transação original para o contrato `Counter`: ```solidity function increment() public { @@ -103,9 +105,9 @@ function increment() public { } ``` -Observe que, se for chamado várias vezes, nosso contador poderá ser vítima de um transbordamento ("overflow"). Você deve usar a [biblioteca SafeMath](https://ethereumdev.io/using-safe-math-library-to-prevent-from-overflows/) tanto quanto possível para se proteger deste possível caso. +Observe que, se chamada muitas vezes, nosso contador poderia ser vítima de um estouro (overflow). Você deve usar a [biblioteca SafeMath](https://ethereumdev.io/using-safe-math-library-to-prevent-from-overflows/) o máximo possível para se proteger desse possível caso. -Para implantar nosso contrato, você precisará fornecer tanto o código da `CounterFactory` quanto o `Counter`. Ao implantar, por exemplo, em Remix, você precisará selecionar a CounterFactory. +Para implantar nosso contrato, você precisará fornecer tanto o código da `CounterFactory` quanto o do `Counter`. Ao implantar, por exemplo, no Remix, você precisará selecionar `CounterFactory`. Aqui está o código completo: @@ -120,12 +122,12 @@ contract Counter { modifier onlyOwner(address caller) { - require(caller == _owner, "You're not the owner of the contract"); + require(caller == _owner, "Você não é o proprietário do contrato"); _; } modifier onlyFactory() { - require(msg.sender == _factory, "You need to use the factory"); + require(msg.sender == _factory, "Você precisa usar a fábrica"); _; } @@ -170,8 +172,8 @@ contract CounterFactory { } ``` -Depois de compilar, na seção de implante de Remix, você selecionará a fábrica a ser implantada: +Após a compilação, na seção de implantação do Remix, você selecionará a fábrica a ser implantada: ![Selecionando a fábrica a ser implantada no Remix](./counterfactory-deploy.png) -Então você pode brincar com sua fábrica de contrato e verificar a mudança de valor. Se você prefere chamar o contrato inteligente a partir de um endereço diferente, altere o endereço na Conta selecionada do Remix. +Então você pode experimentar sua fábrica de contratos e verificar a alteração de valor. Se você quiser chamar o contrato inteligente de um endereço diferente, precisará alterar o endereço no seletor de Contas do Remix. diff --git a/public/content/translations/pt-br/developers/tutorials/ipfs-decentralized-ui/index.md b/public/content/translations/pt-br/developers/tutorials/ipfs-decentralized-ui/index.md new file mode 100644 index 00000000000..8e08c7c603a --- /dev/null +++ b/public/content/translations/pt-br/developers/tutorials/ipfs-decentralized-ui/index.md @@ -0,0 +1,73 @@ +--- +title: "IPFS para interfaces de usuário descentralizadas" +description: "Este tutorial ensina o leitor a usar o IPFS para armazenar a interface do usuário para um dapp. Embora os dados e a lógica de negócios do aplicativo sejam descentralizados, sem uma interface de usuário resistente à censura, os usuários podem perder o acesso a ele de qualquer maneira." +author: Ori Pomerantz +tags: [ "ipfs" ] +skill: beginner +lang: pt-br +published: 2024-06-29 +--- + +Você escreveu um novo dapp incrível. Você até escreveu uma [interface de usuário](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/) para ele. Mas agora você tem medo de que alguém tente censurá-lo, derrubando sua interface de usuário, que é apenas um servidor na nuvem. Neste tutorial, você aprende a evitar a censura colocando sua interface de usuário no **[sistema de arquivos interplanetário (IPFS)](https://ipfs.tech/developers/)** para que qualquer pessoa interessada possa fixá-lo em um servidor para acesso futuro. + +Você pode usar um serviço de terceiros, como o [Fleek](https://resources.fleek.xyz/docs/), para fazer todo o trabalho. Este tutorial é para pessoas que querem fazer o suficiente para entender o que estão fazendo, mesmo que dê mais trabalho. + +## Começando localmente {#getting-started-locally} + +Existem vários [provedores IPFS de terceiros](https://docs.ipfs.tech/how-to/work-with-pinning-services/#use-a-third-party-pinning-service), mas é melhor começar executando o IPFS localmente para testes. + +1. Instale a [interface de usuário do IPFS](https://docs.ipfs.tech/install/ipfs-desktop/#install-instructions). + +2. Crie um diretório com seu site. Se você estiver usando o [Vite](https://vite.dev/), use este comando: + + ```sh + pnpm vite build + ``` + +3. No IPFS Desktop, clique em **Importar > Pasta** e selecione o diretório que você criou na etapa anterior. + +4. Selecione a pasta que você acabou de carregar e clique em **Renomear**. Dê a ele um nome mais significativo. + +5. Selecione-o novamente e clique em **Compartilhar link**. Copie a URL para a área de transferência. O link será semelhante a `https://ipfs.io/ipfs/QmaCuQ7yN6iyBjLmLGe8YiFuCwnePoKfVu6ue8vLBsLJQJ`. + +6. Clique em **Status**. Expanda a guia **Avançado** para ver o endereço do gateway. Por exemplo, no meu sistema, o endereço é `http://127.0.0.1:8080`. + +7. Combine o caminho da etapa do link com o endereço do gateway para encontrar seu endereço. Por exemplo, para o exemplo acima, a URL é `http://127.0.0.1:8080/ipfs/QmaCuQ7yN6iyBjLmLGe8YiFuCwnePoKfVu6ue8vLBsLJQJ`. Abra essa URL em um navegador para ver seu site. + +## Fazendo upload {#uploading} + +Então agora você pode usar o IPFS para servir arquivos localmente, o que não é muito emocionante. O próximo passo é torná-los disponíveis para o mundo quando você estiver offline. + +Existem vários [serviços de fixação](https://docs.ipfs.tech/concepts/persistence/#pinning-services) bem conhecidos. Escolha um deles. Qualquer que seja o serviço que você usar, você precisa criar uma conta e fornecer a ela o **identificador de conteúdo (CID)** no seu IPFS desktop. + +Pessoalmente, achei o [4EVERLAND](https://docs.4everland.org/storage/4ever-pin/guides) o mais fácil de usar. Aqui estão as instruções para isso: + +1. Navegue até [o painel](https://dashboard.4everland.org/overview) e faça login com sua carteira. + +2. Na barra lateral esquerda, clique em **Armazenamento > 4EVER Pin**. + +3. Clique em **Carregar > CID Selecionado**. Dê um nome ao seu conteúdo e forneça o CID do IPFS desktop. Atualmente, um CID é uma string que começa com `Qm` seguida por 44 letras e dígitos que representam um hash [codificado em base-58](https://medium.com/bootdotdev/base64-vs-base58-encoding-c25553ff4524), como `QmaCuQ7yN6iyBjLmLGe8YiFuCwnePoKfVu6ue8vLBsLJQJ`, mas [isso provavelmente mudará](https://docs.ipfs.tech/concepts/content-addressing/#version-1-v1). + +4. O status inicial é **Na fila**. Recarregue até que mude para **Fixado**. + +5. Clique no seu CID para obter o link. Você pode ver meu aplicativo [aqui](https://bafybeifqka2odrne5b6l5guthqvbxu4pujko2i6rx2zslvr3qxs6u5o7im.ipfs.dweb.link/). + +6. Você pode precisar ativar sua conta para mantê-lo fixado por mais de um mês. A ativação da conta custa cerca de US$ 1. Se você fechou, saia e faça login novamente para ser solicitado a ativar novamente. + +## Usando do IPFS {#using-from-ipfs} + +Neste ponto, você tem um link para um gateway centralizado que serve seu conteúdo IPFS. Em resumo, sua interface de usuário pode ser um pouco mais segura, mas ainda não é resistente à censura. Para uma real resistência à censura, os usuários precisam usar o IPFS [diretamente de um navegador](https://docs.ipfs.tech/install/ipfs-companion/#prerequisites). + +Depois de instalá-lo (e com o IPFS desktop funcionando), você pode ir para [/ipfs/``](https://any.site/ipfs/bafybeifqka2odrne5b6l5guthqvbxu4pujko2i6rx2zslvr3qxs6u5o7im) em qualquer site e obterá esse conteúdo, servido de maneira descentralizada. + +## Desvantagens {#drawbacks} + +Você não pode excluir arquivos IPFS de forma confiável, então, enquanto estiver modificando sua interface de usuário, provavelmente é melhor deixá-la centralizada ou usar o [sistema de nomes interplanetário (IPNS)](https://docs.ipfs.tech/concepts/ipns/#mutability-in-ipfs), um sistema que fornece mutabilidade sobre o IPFS. Claro, qualquer coisa que seja mutável pode ser censurada, no caso do IPNS, pressionando a pessoa com a chave privada à qual corresponde. + +Além disso, alguns pacotes têm problemas com o IPFS, então se o seu site for muito complicado, essa pode não ser uma boa solução. E, claro, qualquer coisa que dependa da integração do servidor não pode ser descentralizada apenas por ter o lado do cliente no IPFS. + +## Conclusão {#conclusion} + +Assim como o Ethereum permite que você descentralize o banco de dados e os aspectos da lógica de negócios do seu dapp, o IPFS permite que você descentralize a interface do usuário. Isso permite que você elimine mais um vetor de ataque contra o seu dapp. + +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). diff --git a/public/content/translations/pt-br/developers/tutorials/kickstart-your-dapp-frontend-development-with-create-eth-app/index.md b/public/content/translations/pt-br/developers/tutorials/kickstart-your-dapp-frontend-development-with-create-eth-app/index.md new file mode 100644 index 00000000000..f3c3769e3f8 --- /dev/null +++ b/public/content/translations/pt-br/developers/tutorials/kickstart-your-dapp-frontend-development-with-create-eth-app/index.md @@ -0,0 +1,111 @@ +--- +title: "Dê o pontapé inicial no desenvolvimento do frontend do seu dapp com o create-eth-app" +description: "Uma visão geral de como usar o create-eth-app e seus recursos" +author: "Markus Waas" +tags: + [ + "front-end", + "JavaScript", + "ethers.js", + "the graph", + "defi" + ] +skill: beginner +lang: pt-br +published: 2020-04-27 +source: soliditydeveloper.com +sourceUrl: https://soliditydeveloper.com/create-eth-app +--- + +Na última vez, vimos [o panorama geral do Solidity](https://soliditydeveloper.com/solidity-overview-2020) e já mencionamos o [create-eth-app](https://github.com/PaulRBerg/create-eth-app). Agora você descobrirá como usá-lo, quais recursos estão integrados e ideias adicionais sobre como expandi-lo. Iniciado por Paul Razvan Berg, o fundador do [Sablier](http://sablier.com/), este aplicativo dará o pontapé inicial no seu desenvolvimento de frontend e vem com várias integrações opcionais para você escolher. + +## Instalação {#installation} + +A instalação requer o Yarn 0.25 ou superior (`npm install yarn --global`). É tão simples quanto executar: + +```bash +yarn create eth-app my-eth-app +cd my-eth-app +yarn react-app:start +``` + +Ele usa o [create-react-app](https://github.com/facebook/create-react-app) por baixo dos panos. Para ver seu app, abra `http://localhost:3000/`. Quando estiver pronto para implantar em produção, crie um pacote minificado com `yarn build`. Uma maneira fácil de hospedar isso seria o [Netlify](https://www.netlify.com/). Você pode criar um repositório no GitHub, adicioná-lo ao Netlify, configurar o comando de build e pronto! Seu app será hospedado e poderá ser usado por todos. E tudo isso gratuitamente. + +## Recursos {#features} + +### React e create-react-app {#react--create-react-app} + +Primeiramente, o coração do app: o React e todos os recursos adicionais que vêm com o _create-react-app_. Usar apenas isso é uma ótima opção se você não quiser integrar o Ethereum. O próprio [React](https://react.dev/) torna a criação de UIs interativas muito fácil. Pode não ser tão amigável para iniciantes quanto o [Vue](https://vuejs.org/), mas ainda é o mais utilizado, tem mais recursos e, o mais importante, milhares de bibliotecas adicionais para escolher. O _create-react-app_ também torna muito fácil começar a usá-lo e inclui: + +- Suporte às sintaxes React, JSX, ES6, TypeScript e Flow. +- Recursos de linguagem além do ES6, como o operador de propagação de objeto. +- CSS com prefixo automático, para que você não precise de `-webkit-` ou outros prefixos. +- Um executor de testes unitários rápido e interativo com suporte integrado para relatórios de cobertura. +- Um servidor de desenvolvimento em tempo real que avisa sobre erros comuns. +- Um script de build para empacotar JS, CSS e imagens para produção, com hashes e sourcemaps. + +O _create-eth-app_ em particular faz uso dos novos [efeitos de hooks](https://legacy.reactjs.org/docs/hooks-effect.html). Um método para escrever os chamados componentes funcionais, que são poderosos, mas muito pequenos. Veja a seção abaixo sobre o Apollo para saber como eles são usados no _create-eth-app_. + +### Yarn Workspaces {#yarn-workspaces} + +Os [Yarn Workspaces](https://classic.yarnpkg.com/en/docs/workspaces/) permitem que você tenha vários pacotes, mas com a capacidade de gerenciá-los todos a partir da pasta raiz e instalar as dependências de todos de uma vez usando `yarn install`. Isso faz sentido especialmente para pacotes adicionais menores, como o gerenciamento de endereços/ABIs de contratos inteligentes (as informações sobre onde você implantou quais contratos inteligentes e como se comunicar com eles) ou a integração do graph, ambos parte do `create-eth-app`. + +### ethers.js {#ethersjs} + +Embora o [Web3](https://docs.web3js.org/) ainda seja o mais usado, o [ethers.js](https://docs.ethers.io/) tem ganhado muito mais força como alternativa no último ano e é o que está integrado no _create-eth-app_. Você pode trabalhar com ele, alterá-lo para Web3 ou considerar a atualização para o [ethers.js v5](https://docs.ethers.org/v5/), que está quase saindo da versão beta. + +### The Graph {#the-graph} + +[GraphQL](https://graphql.org/) é uma forma alternativa de lidar com dados em comparação com uma [API Restful](https://restfulapi.net/). Eles têm várias vantagens sobre as APIs Restful, especialmente para dados descentralizados da cadeia de blocos. Se você estiver interessado no raciocínio por trás disso, dê uma olhada em [GraphQL Will Power the Decentralized Web](https://medium.com/graphprotocol/graphql-will-power-the-decentralized-web-d7443a69c69a). + +Normalmente, você buscaria dados diretamente do seu contrato inteligente. Quer ler o horário da última negociação? Basta chamar `MyContract.methods.latestTradeTime().call()`, que busca os dados de um nó do Ethereum para o seu dapp. Mas e se você precisar de centenas de pontos de dados diferentes? Isso resultaria em centenas de buscas de dados no nó, cada uma exigindo um [RTT](https://wikipedia.org/wiki/Round-trip_delay_time), tornando seu dapp lento e ineficiente. Uma solução alternativa pode ser uma função de chamada de busca dentro do seu contrato que retorna múltiplos dados de uma vez. No entanto, isso nem sempre é o ideal. + +E você também pode se interessar por dados históricos. Você quer saber não apenas o horário da última negociação, mas os horários de todas as negociações que você mesmo já fez. Use o pacote subgraph do _create-eth-app_, leia a [documentação](https://thegraph.com/docs/en/subgraphs/developing/creating/starting-your-subgraph) e adapte-o aos seus próprios contratos. Se você estiver procurando por contratos inteligentes populares, pode ser que já exista um subgraph. Confira o [explorador de subgraphs](https://thegraph.com/explorer/). + +Depois de ter um subgraph, ele permite que você escreva uma consulta simples em seu dapp que recupera todos os dados importantes da cadeia de blocos, incluindo os históricos que você precisa, com apenas uma busca necessária. + +### Apollo {#apollo} + +Graças à integração do [Apollo Boost](https://www.apollographql.com/docs/react/get-started/), você pode integrar facilmente o graph em seu dapp React. Especialmente ao usar [React hooks e Apollo](https://www.apollographql.com/blog/apollo-client-now-with-react-hooks), buscar dados é tão simples quanto escrever uma única consulta GraphQL em seu componente: + +```js +const { loading, error, data } = useQuery(myGraphQlQuery) + +React.useEffect(() => { + if (!loading && !error && data) { + console.log({ data }) + } +}, [loading, error, data]) +``` + +## Modelos {#templates} + +Além disso, você pode escolher entre vários modelos diferentes. Até agora, você pode usar uma integração com Aave, Compound, UniSwap ou sablier. Todos eles adicionam endereços de contratos inteligentes de serviços importantes, juntamente com integrações de subgraphs pré-fabricadas. Basta adicionar o modelo ao comando de criação, como `yarn create eth-app my-eth-app --with-template aave`. + +### Aave {#aave} + +O [Aave](https://aave.com/) é um mercado descentralizado de empréstimo de dinheiro. Os depositantes fornecem liquidez ao mercado para obter uma renda passiva, enquanto os mutuários podem pegar emprestado usando garantias. Uma característica única do Aave são os [empréstimos-relâmpago (flash loans)](https://aave.com/docs/developers/flash-loans), que permitem que você pegue dinheiro emprestado sem qualquer garantia, desde que devolva o empréstimo em uma única transação. Isso pode ser útil, por exemplo, para lhe dar um dinheiro extra em negociações de arbitragem. + +Os tokens negociados que rendem juros são chamados de _aTokens_. + +Ao optar por integrar o Aave com o _create-eth-app_, você obterá uma [integração de subgraph](https://docs.aave.com/developers/getting-started/using-graphql). O Aave usa o The Graph e já fornece vários subgraphs prontos para uso na [Ropsten](https://thegraph.com/explorer/subgraph/aave/protocol-ropsten) e na [Rede Principal (Mainnet)](https://thegraph.com/explorer/subgraph/aave/protocol) em formato [bruto (raw)](https://thegraph.com/explorer/subgraph/aave/protocol-raw) ou [formatado (formatted)](https://thegraph.com/explorer/subgraph/aave/protocol). + +![Meme de Empréstimo-Relâmpago (Flash Loan) da Aave – \"Éééé, se eu pudesse manter meu empréstimo-relâmpago por mais de 1 transação, seria ótimo\"](./flashloan-meme.png) + +### Compound {#compound} + +O [Compound](https://compound.finance/) é semelhante ao Aave. A integração já inclui o novo [Compound v2 Subgraph](https://medium.com/graphprotocol/https-medium-com-graphprotocol-compound-v2-subgraph-highlight-a5f38f094195). Os tokens que rendem juros aqui são, surpreendentemente, chamados de _cTokens_. + +### Uniswap {#uniswap} + +A [Uniswap](https://uniswap.exchange/) é uma corretora descentralizada (DEX). Os provedores de liquidez podem ganhar taxas fornecendo os tokens ou ether necessários para ambos os lados de uma negociação. É amplamente utilizada e, portanto, tem uma das maiores liquidez para uma gama muito ampla de tokens. Você pode integrá-la facilmente em seu dapp para, por exemplo, permitir que os usuários façam o swap de seus ETH por DAI. + +Infelizmente, no momento em que este artigo foi escrito, a integração é apenas para a Uniswap v1 e não para a [versão v2 recém-lançada](https://uniswap.org/blog/uniswap-v2/). + +### Sablier {#sablier} + +O [Sablier](https://sablier.com/) permite que os usuários façam pagamentos de dinheiro por streaming. Em vez de um único dia de pagamento, você recebe seu dinheiro constantemente, sem necessidade de administração adicional após a configuração inicial. A integração inclui seu [próprio subgraph](https://thegraph.com/explorer/subgraph/sablierhq/sablier). + +## O que vem a seguir? {#whats-next} + +Se você tiver dúvidas sobre o _create-eth-app_, acesse o [servidor da comunidade Sablier](https://discord.gg/bsS8T47), onde você pode entrar em contato com os autores do _create-eth-app_. Como próximos passos, você pode querer integrar um framework de UI como o [Material UI](https://mui.com/material-ui/), escrever consultas GraphQL para os dados que você realmente precisa e configurar a implantação. diff --git a/public/content/translations/pt-br/developers/tutorials/kickstart-your-dapp-frontend-development-wth-create-eth-app/index.md b/public/content/translations/pt-br/developers/tutorials/kickstart-your-dapp-frontend-development-wth-create-eth-app/index.md index d697c1f2039..aad9f84f3f3 100644 --- a/public/content/translations/pt-br/developers/tutorials/kickstart-your-dapp-frontend-development-wth-create-eth-app/index.md +++ b/public/content/translations/pt-br/developers/tutorials/kickstart-your-dapp-frontend-development-wth-create-eth-app/index.md @@ -1,6 +1,6 @@ --- title: Comece a desenvolver o front-end do seu dapp usando create-eth-app -description: Uma visão geral de como criar um aplicativo eth-app e seus recursos +description: "Uma visão geral de como criar um aplicativo eth-app e seus recursos" author: "Markus Waas" tags: - "create-eth-app" diff --git a/public/content/translations/pt-br/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md b/public/content/translations/pt-br/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md index 0457b9e3218..848360459d4 100644 --- a/public/content/translations/pt-br/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md +++ b/public/content/translations/pt-br/developers/tutorials/learn-foundational-ethereum-topics-with-sql/index.md @@ -1,39 +1,36 @@ --- -title: Aprenda Tópicos fundamentais de Ethereum com SQL -description: Este tutorial ajuda os leitores a entender os conceitos fundamentais de Ethereum, incluindo transações, blocos e gas, consultando dados on-chain com linguagem de consulta estruturada (SQL). +title: "Aprenda Tópicos Fundamentais do Ethereum com SQL" +description: "Este tutorial ajuda os leitores a entenderem os conceitos fundamentais do Ethereum, incluindo transações, blocos e gás, consultando dados em cadeia com a Linguagem de Consulta Estruturada (SQL)." author: "Paul Apivat" -tags: - - "SQL" - - "Querying" - - "Transações" -skill: intermediate +tags: [ "SQL", "Consulta", "Transações" ] +skill: beginner lang: pt-br published: 2021-05-11 source: paulapivat.com sourceUrl: https://paulapivat.com/post/query_ethereum/ --- -Muitos tutorias da Ethereum são direcionadas para desenvolvedores, mas há uma falta de recursos educacionais para analistas de dados ou pessoas que desejam ver dados on-chain sem executar um cliente ou um nó. +Muitos tutoriais do Ethereum são direcionados a desenvolvedores, mas há uma falta de recursos educacionais para analistas de dados ou para pessoas que desejam ver dados em cadeia sem executar um cliente ou um nó. -Esse tutorial ajuda os leitores a entenderem os conceitos fundamentais da Ethereum, incluindo transações, blocos e gás, consultando dados on-chain com a linguagem SQL por meio de uma interface fornecida por [Dune Analytics](https://dune.xyz/home). +Este tutorial ajuda os leitores a entenderem os conceitos fundamentais do Ethereum, incluindo transações, blocos e gás, consultando dados em cadeia com a linguagem de consulta estruturada (SQL) por meio de uma interface fornecida pela [Dune Analytics](https://dune.com/). -Dados on-chain podem nos ajudar a compreender a rede Ethereum como uma economia para capacidade computacional, e deve servir como base para entender os desafios enfrentados pela Ethereum hoje (por exemplo, o aumento dos preços do gas) e, o mais importante, discussões sobre soluções de escalabilidade. +Dados em cadeia podem nos ajudar a compreender o Ethereum, a rede, e como uma economia para poder computacional. Eles devem servir como base para entender os desafios que o Ethereum enfrenta hoje (ou seja, o aumento dos preços do gás) e, mais importante, as discussões sobre soluções de escalabilidade. ### Transações {#transactions} -A jornada do usuário no Ethereum começa com a inicialização de uma conta controlada ou uma entidade com saldo ETH. Há duas categorias de contas: controlada pelo usuário ou um contrato inteligente (veja em: [ethereum.org](/developers/docs/accounts/)). +A jornada de um usuário no Ethereum começa com a inicialização de uma conta controlada pelo usuário ou uma entidade com saldo de ETH. Existem dois tipos de conta: controlada pelo usuário ou um contrato inteligente (consulte [ethereum.org](/developers/docs/accounts/)). -Qualquer conta pode ser visualizada em um explorador de bloco como a [Etherscan](https://etherscan.io/). Exploradores de bloco são um portal para os dados da Ethereum. Eles exibem, em tempo real, dados em blocos, transações, mineiradores, contas, e outras atividades on-chain (veja [aqui](/developers/docs/data-and-analytics/block-explorers/)). +Qualquer conta pode ser visualizada em um explorador de blocos como o [Etherscan](https://etherscan.io/) ou o [Blockscout](https://eth.blockscout.com/). Os exploradores de blocos são um portal para os dados do Ethereum. Eles exibem, em tempo real, dados sobre blocos, transações, mineradores, contas e outras atividades em cadeia (veja [aqui](/developers/docs/data-and-analytics/block-explorers/)). -No entanto, um usuário pode desejar consultar um dado diretamente para reconciliar as informações fornecidas por exploradores de bloco externos. O [Dune Analytics](https://duneanalytics.com/) fornece esse recurso para qualquer pessoa com algum conhecimento em SQL. +No entanto, um usuário pode querer consultar os dados diretamente para reconciliar as informações fornecidas por exploradores de blocos externos. O [Dune Analytics](https://dune.com/) oferece essa capacidade a qualquer pessoa com algum conhecimento de SQL. -Como referência, a conta de contrato inteligente da Fundação Ethereum (EF) pode ser visualizada na [Etherscan](https://etherscan.io/address/0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae). +Para referência, a conta de contrato inteligente da Ethereum Foundation (EF) pode ser visualizada no [Blockscout](https://eth.blockscout.com/address/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe). -Uma coisa a ser observada é que todas as contas, incluindo as EF's, têm um endereço público que pode ser utilizado para enviar e receber transações. +Uma coisa a se notar é que todas as contas, incluindo a da EF, têm um endereço público que pode ser usado para enviar e receber transações. -O saldo da conta na Etherscan inclui transações regulare e transações internas. As transações internas, apesar do nome, não são _realmente_ transações que alteram o estado da cadeia. Elas são transferências de valores iniciadas pela execução de um contrato ([fonte](https://ethereum.stackexchange.com/questions/3417/how-to-get-contract-internal-transactions)). Visto que as transações internas não têm assinatura, elas **não** são incluídas na blockchain e não podem ser consultadas com o Dune Analytics. +O saldo da conta no Etherscan compreende transações regulares e transações internas. Transações internas, apesar do nome, não são transações _reais_ que mudam o estado da cadeia. São transferências de valor iniciadas pela execução de um contrato ([fonte](https://ethereum.stackexchange.com/questions/3417/how-to-get-contract-internal-transactions)). Como as transações internas não têm assinatura, elas **não** são incluídas na blockchain e não podem ser consultadas com o Dune Analytics. -Portanto, este tutorial irá focar em transações regulares. Isso pode ser consultado como: +Portanto, este tutorial se concentrará em transações regulares. Isso pode ser consultado da seguinte forma: ```sql WITH temp_table AS ( @@ -61,33 +58,33 @@ SELECT FROM temp_table ``` -Isso irá gerar as mesmas informações fornecidas na página de transações do Etherscan. Para você comparar, aqui estão duas fontes: +Isso resultará na mesma informação fornecida na página de transações do Etherscan. Para comparação, aqui estão as duas fontes: #### Etherscan {#etherscan} -![](./etherscan_view.png) +![Captura de tela da visualização do explorador de transações Etherscan](./etherscan_view.png) -[Visualizar página de contratos de EF's no Etherscan.](https://etherscan.io/address/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe) +[Página do contrato da EF no Blockscout.](https://eth.blockscout.com/address/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe) #### Dune Analytics {#dune-analytics} -![](./dune_view.png) +![Captura de tela de um painel de consulta do Dune Analytics](./dune_view.png) -Você pode encontrar o painel [aqui](https://duneanalytics.com/paulapivat/Learn-Ethereum). Clique na tabela para visualizar a consulta (veja também acima). +Você pode encontrar o painel [aqui](https://dune.com/paulapivat/Learn-Ethereum). Clique na tabela para ver a consulta (veja também acima). -### Decompondo Transações {#breaking_down_transactions} +### Analisando as Transações {#breaking_down_transactions} Uma transação enviada inclui várias informações, incluindo ([fonte](/developers/docs/transactions/)): -- **Destinatário**: O endereço de recebimento (chamado como "para") -- **Assinatura**: Enquanto as chaves privadas de um remetente assinam uma transação, o que podemos consultar com o SQL é o endereço público de um remetente ("de"). -- **Valor**: Esta é a quantidade de ETH transferido (veja a coluna `ether`). -- **Dados**: Estes são dados arbitrários misturados (veja a coluna `dados`). -- **gasLimit**: a quantidade máxima de gas que pode ser consumida pela transação. As unidades de gas representam etapas computacionais -- **maxPriorityFeePerGas**: a quantidade máxima de gas a ser incluída como dica para o minerador -- **maxFeePerGas** - a quantidade máxima de gas disposta a ser paga pela transação (incluindo baseFeePerGas e maxPriorityFeePerGas) +- **Destinatário**: O endereço de recebimento (consultado como "to") +- **Assinatura**: Embora as chaves privadas de um remetente assinem uma transação, o que podemos consultar com SQL é o endereço público de um remetente ("from"). +- **Valor**: Esta é a quantidade de ETH transferida (veja a coluna `ether`). +- **Dados**: São dados arbitrários que sofreram hash (consulte a coluna `data`) +- **gasLimit** – a quantidade máxima de unidades de gás que podem ser consumidas pela transação. As unidades de gás representam etapas computacionais +- **maxPriorityFeePerGas** - a quantidade máxima de gás a ser incluída como gorjeta para o minerador +- **maxFeePerGas** - a quantidade máxima de gás que se está disposto a pagar pela transação (incluindo baseFeePerGas e maxPriorityFeePerGas) -Podemos consultar essas informações específicas sobre transações no endereço público da Fundação Ethereum: +Podemos consultar estas informações específicas para transações para o endereço público da Ethereum Foundation: ```sql SELECT @@ -106,15 +103,15 @@ ORDER BY block_time DESC ### Blocos {#blocks} -Cada transação irá alterar o estado da máquina virtual da Ethereum ([EVM](/developers/docs/evm/)) ([fonte](/developers/docs/transactions/)). As transações são transmitidas à rede para serem verificadas e incluídas em um bloco. Cada transação está associada a um número de bloco. Para ver os dados, nós podemos consultar um número de bloco específico: 12396854 (o bloco mais recente entre as transações da Fundação Ethereum a partir desta escrita, 11/05/21). +Cada transação mudará o estado da máquina virtual ethereum ([EVM](/developers/docs/evm/)) ([fonte](/developers/docs/transactions/)). As transações são transmitidas para a rede para serem verificadas e incluídas em um bloco. Cada transação está associada a um número de bloco. Para ver os dados, podemos consultar um número de bloco específico: 12396854 (o bloco mais recente entre as transações da Ethereum Foundation no momento da redação deste artigo, em 11/05/21). -Além disso, quando consultarmos os próximos dois blocos, podemos observar que cada bloco contém o hash do bloco anterior (i.., hash pai), ilustrando como a blockchain é formada. +Além disso, quando consultamos os dois blocos seguintes, podemos ver que cada bloco contém o hash do bloco anterior (ou seja, o hash pai), ilustrando como a blockchain é formada. -Cada bloco contém uma referência ao bloco pai. Isso é mostrado abaixo entre as colunas `hash` e `parent_hash` (fonte[](/developers/docs/blocks/)): +Cada bloco contém uma referência ao seu bloco pai. Isso é mostrado abaixo entre as colunas `hash` e `parent_hash` ([fonte](/developers/docs/blocks/)): ![parent_hash](./parent_hash.png) -Aqui está a [consulta](https://duneanalytics.com/queries/44856/88292) no Dune Analytics: +Aqui está a [consulta](https://dune.com/queries/44856/88292) no Dune Analytics: ```sql SELECT @@ -128,18 +125,18 @@ WHERE "number" = 12396854 OR "number" = 12396855 OR "number" = 12396856 LIMIT 10 ``` -Podemos examinar um bloco consultando o horário, o número de bloco, a dificuldade (quantidade de computação necessária), o hash, o hash pai e a nonce. +Podemos examinar um bloco consultando o tempo, o número do bloco, a dificuldade, o hash, o hash pai e o nonce. -A única coisa que esta consulta não cobre é a _lista de transações_ que requer uma consulta separada abaixo e _raiz do estado_. Um nó completo ou de arquivamento irá armazenar todas as transações e transições de estado, permitindo que os clientes consultem o estado da cadeia a qualquer momento. Como isso requer um grande espaço de armazenamento, nós podemos separar os dados em cadeia dos dados de estado: +A única coisa que esta consulta não cobre é a _lista de transações_, que requer uma consulta separada abaixo, e a _raiz do estado_. Um nó completo ou de arquivamento armazenará todas as transações e transições de estado, permitindo que os clientes consultem o estado da cadeia a qualquer momento. Como isso exige um grande espaço de armazenamento, podemos separar os dados da cadeia dos dados de estado: -- Dados em cadeia (lista de blocos, transações) +- Dados da cadeia (lista de blocos, transações) - Dados de estado (resultado da transição de estado de cada transação) -A raiz de estado cai na última e são _ dados implícitos_ (não armazenados na cadeia), enquanto os dados em cadeia são explícitos e armazenados na própria cadeia ([fonte](https://ethereum.stackexchange.com/questions/359/where-is-the-state-data-stored)). +A raiz do estado se enquadra no último e são dados _implícitos_ (não armazenados em cadeia), enquanto os dados da cadeia são explícitos e armazenados na própria cadeia ([fonte](https://ethereum.stackexchange.com/questions/359/where-is-the-state-data-stored)). -Para este tutorial, estaremos focando em dados on-chain que _podem_ ser consultados com SQL via Dune Analytics. +Neste tutorial, vamos nos concentrar nos dados em cadeia que _podem_ ser consultados com SQL via Dune Analytics. -Como mencionado acima, cada bloco contém uma lista de transações, podemos consultar isso filtrando por um bloco específico. Vamos tentar o bloco mais recente, 12396854: +Conforme indicado acima, cada bloco contém uma lista de transações. Podemos consultar isso filtrando por um bloco específico. Vamos tentar o bloco mais recente, 12396854: ```sql SELECT * FROM ethereum."transactions" @@ -147,13 +144,13 @@ WHERE block_number = 12396854 ORDER BY block_time DESC` ``` -Segue o SQL output no Dune: +Aqui está a saída SQL no Dune: ![](./list_of_txn.png) -Este único bloco sendo adicionado à cadeia altera o estado da máquina virtual Ethereum ([EVM](/developers/docs/evm/)). Dezenas, às vezes centenas, de transações são verificadas de uma só vez. Neste caso específico, foram incluídas 222 transações. +Este único bloco adicionado à cadeia altera o estado da máquina virtual ethereum ([EVM](/developers/docs/evm/)). Dezenas, às vezes centenas, de transações são verificadas de uma só vez. Neste caso específico, 222 transações foram incluídas. -Para ver quantas foram realmente bem-sucedidas, nós adicionaríamos outro filtro para contar transações bem-sucedidas: +Para ver quantas foram realmente bem-sucedidas, adicionaríamos outro filtro para contar as transações bem-sucedidas: ```sql WITH temp_table AS ( @@ -166,26 +163,26 @@ SELECT FROM temp_table ``` -Para o bloco 12396854, do total de 222 transações, 204 foram verificadas com sucesso: +Para o bloco 12396854, de um total de 222 transações, 204 foram verificadas com sucesso: ![](./successful_txn.png) -As solicitações de transações ocorrem dezenas de vezes por segundo, mas os blocos são confirmados aproximadamente uma vez a cada 15 segundos ([source](/developers/docs/blocks/)). +As solicitações de transação ocorrem dezenas de vezes por segundo, mas os blocos são consolidados aproximadamente uma vez a cada 15 segundos ([fonte](/developers/docs/blocks/)). -Para ver que há um bloco produzido aproximadamente a cada 15 segundos, poderíamos pegar o número de segundos em um dia (86400) por 15, para obter um número médio estimado de blocos por dia (~ 5760). +Para ver que um bloco é produzido aproximadamente a cada 15 segundos, poderíamos pegar o número de segundos em um dia (86400) e dividi-lo por 15 para obter um número médio estimado de blocos por dia (~ 5760). -O gráfico de blocos Ethereum produzidos por dia (2016 - presente) é: +O gráfico de blocos do Ethereum produzidos por dia (2016 - presente) é: ![](./daily_blocks.png) -O número médio de blocos produzidos diariamente durante esse período de tempo é de aproximadamente ~5.874: +O número médio de blocos produzidos diariamente durante este período é de aproximadamente 5.874: ![](./avg_daily_blocks.png) As consultas são: ```sql -# query to visualize number of blocks produced daily since 2016 +# consulta para visualizar o número de blocos produzidos diariamente desde 2016 SELECT DATE_TRUNC('day', time) AS dt, @@ -194,7 +191,7 @@ FROM ethereum."blocks" GROUP BY dt OFFSET 1 -# average number of blocks produced per day +# número médio de blocos produzidos por dia WITH temp_table AS ( SELECT @@ -209,13 +206,13 @@ SELECT FROM temp_table ``` -O número médio de blocos produzidos por dia desde 2016 está um pouco acima desse número em 5.874. Alternativamente, dividindo 86400 segundos por 5874 blocos médios resultam em 14,7 segundos ou aproximadamente um bloco a cada 15 segundos. +O número médio de blocos produzidos por dia desde 2016 é ligeiramente superior a esse número, em 5.874. Alternativamente, dividir 86400 segundos por uma média de 5874 blocos resulta em 14,7 segundos ou aproximadamente um bloco a cada 15 segundos. ### Gás {#gas} -Blocos são limitados em tamanho. O tamanho máximo do bloco é dinâmico e varia de acordo com a demanda de rede entre 12.500.000 e 25.000.000 unidades. Limites são necessários para evitar que, blocos de tamanho arbitrariamente grandes coloquem tensão em nós completos, em termos de espaço em disco e requisitos de velocidade ([source](/developers/docs/blocks/)). +Os blocos têm um tamanho limitado. O tamanho máximo do bloco é dinâmico e varia de acordo com a demanda da rede entre 12.500.000 e 25.000.000 unidades. São necessários limites para evitar que blocos de tamanho arbitrariamente grande sobrecarreguem os nós completos em termos de espaço em disco e requisitos de velocidade ([fonte](/developers/docs/blocks/)). -Uma maneira de conceitualizar o limite de gas do bloco é pensar nele como o **suprimento** de espaço de bloco disponível para as transações em lote. O limite de gas do bloco pode ser consultado e visualizado a partir de 2016 até o presente dia: +Uma forma de conceituar o limite de gás do bloco é pensar nele como a **oferta** de espaço de bloco disponível para transações em lote. O limite de gás do bloco pode ser consultado e visualizado de 2016 até os dias atuais: ![](./avg_gas_limit.png) @@ -228,7 +225,7 @@ GROUP BY dt OFFSET 1 ``` -Depois, há o gas real usado diariamente para pagar pela computação realizada na cadeia Ethereum (ou seja, enviar transações, chamar um contrato inteligente, cunhar um NFT). Esta é a **demanda** por espaço de bloco disponível no Ethereum: +Depois, há o gás real usado diariamente para pagar pela computação feita na cadeia Ethereum (ou seja, enviar transações, chamar um contrato inteligente, mintar um NFT). Esta é a **demanda** por espaço de bloco disponível no Ethereum: ![](./daily_gas_used.png) @@ -241,17 +238,17 @@ GROUP BY dt OFFSET 1 ``` -Também podemos justapor esses dois gráficos para ver como a **demanda e oferta** se alinham: +Também podemos justapor estes dois gráficos para ver como a **demanda e a oferta** se alinham: ![gas_demand_supply](./gas_demand_supply.png) -Portanto, podemos entender os preços do gas em função da demanda por espaço no bloco Ethereum, dada a oferta disponível. +Portanto, podemos entender os preços do gás como uma função da demanda por espaço de bloco do Ethereum, dada a oferta disponível. -Finalmente, podemos querer consultar os preços médios diários do gas para a cadeia Ethereum, no entanto, fazê-lo resultará em um tempo de consulta especialmente longo, então, filtraremos a nossa consulta pela quantidade média de gas paga por transação pela Fundação Ethereum. +Finalmente, podemos querer consultar os preços médios diários do gás para a cadeia Ethereum. No entanto, isso resultará em um tempo de consulta especialmente longo, por isso filtraremos nossa consulta para a quantidade média de gás paga por transação pela Ethereum Foundation. ![](./ef_daily_gas.png) -Podemos ver os preços do gas pagos por todas as transações feitas para o endereço da Ethereum Foundation ao longo dos anos. Aqui está a consulta: +Podemos ver os preços do gás pagos por todas as transações feitas para o endereço da Ethereum Foundation ao longo dos anos. Aqui está a consulta: ```sql SELECT @@ -265,8 +262,8 @@ ORDER BY block_time DESC ### Resumo {#summary} -Com este tutorial, entendemos os conceitos fundamentais do Ethereum e como a blockchain do Ethereum funciona consultando e obtendo uma ideia dos dados on-chain. +Com este tutorial, entendemos os conceitos fundamentais do Ethereum e como a blockchain do Ethereum funciona, consultando e tendo uma noção dos dados em cadeia. -O painel que contém todo o código usado neste tutorial pode ser encontrado [aqui](https://duneanalytics.com/paulapivat/Learn-Ethereum). +O painel que contém todo o código usado neste tutorial pode ser encontrado [aqui](https://dune.com/paulapivat/Learn-Ethereum). -Para mais uso de dados para explorar a web3 [siga-me no Twitter](https://twitter.com/paulapivat). +Para mais usos de dados para explorar a web3, [encontre-me no Twitter](https://twitter.com/paulapivat). diff --git a/public/content/translations/pt-br/developers/tutorials/logging-events-smart-contracts/index.md b/public/content/translations/pt-br/developers/tutorials/logging-events-smart-contracts/index.md index d74031cc9e8..1286acb2a7f 100644 --- a/public/content/translations/pt-br/developers/tutorials/logging-events-smart-contracts/index.md +++ b/public/content/translations/pt-br/developers/tutorials/logging-events-smart-contracts/index.md @@ -1,12 +1,8 @@ --- title: Registrando dados de contratos inteligentes com eventos -description: Uma introdução aos eventos de contrato inteligentes e como você pode usá-los para registrar os dados +description: "Uma introdução aos eventos de contrato inteligente e como você pode usá-los para registrar dados" author: "jdourlens" -tags: - - "contratos inteligentes" - - "remix" - - "solidity" - - "eventos" +tags: [ "smart contracts", "Remix", "Solidity", "eventos" ] skill: intermediate lang: pt-br published: 2020-04-03 @@ -15,19 +11,19 @@ sourceUrl: https://ethereumdev.io/logging-data-with-events/ address: "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE" --- -No Solidity, [eventos](/developers/docs/smart-contracts/anatomy/#events-and-logs) são sinais enviados que os contratos inteligentes podem disparar. Dapps, ou qualquer coisa conectada à API Ethereum JSON-RPC, podem reconhecer esses eventos e agir em conformidade. Um evento também pode ser indexado para que o histórico de eventos seja pesquisável posteriormente. +Em Solidity, [eventos](/developers/docs/smart-contracts/anatomy/#events-and-logs) são sinais despachados que os contratos inteligentes podem disparar. Dapps, ou qualquer coisa conectada à API JSON-RPC do Ethereum, podem escutar esses eventos e agir de acordo. Um evento também pode ser indexado para que o histórico de eventos seja pesquisável posteriormente. ## Eventos {#events} -O evento mais comum na blockchain Ethereum no momento da redação deste artigo é o evento Transfer, que é emitido por tokens ERC20 quando alguém transfere tokens. +O evento mais comum na blockchain Ethereum, no momento em que este artigo foi escrito, é o evento Transfer, emitido por tokens ERC20 quando alguém transfere tokens. ```solidity event Transfer(address indexed from, address indexed to, uint256 value); ``` -A assinatura do evento é declarada dentro do código do contrato e pode ser emitida com a palavra-chave de emissão. Por exemplo, os registros de eventos de transferência que enviaram a transferência (_from_), para quem foram transferidos (_to_) e quantos tokens foram transferidos (_value_). +A assinatura do evento é declarada dentro do código do contrato e pode ser emitida com a palavra-chave emit. Por exemplo, o evento de transferência registra quem enviou a transferência (_from_), para quem (_to_) e quantos tokens foram transferidos (_value_). -Se voltarmos ao nosso contrato inteligente Contador e decidirmos registrar toda vez que o valor for alterado. Como este contrato não é para ser usado, mas serve como uma base para a construção de outro contrato, estendendo-o: é chamado de contrato abstrato. No caso de nosso exemplo de contador, ele ficaria assim: +Se voltarmos ao nosso contrato inteligente Counter e decidirmos registrar toda vez que o valor é alterado. Como este contrato não se destina a ser implantado, mas a servir como base para a construção de outro contrato estendendo-o: ele é chamado de contrato abstrato. No caso do nosso exemplo de contador, ficaria assim: ```solidity pragma solidity 0.5.17; @@ -36,16 +32,16 @@ contract Counter { event ValueChanged(uint oldValue, uint256 newValue); - // Private variable of type unsigned int to keep the number of counts + // Variável privada do tipo inteiro não assinado para manter o número de contagens uint256 private count = 0; - // Function that increments our counter + // Função que incrementa nosso contador function increment() public { count += 1; emit ValueChanged(count - 1, count); } - // Getter to get the count value + // Getter para obter o valor da contagem function getCount() public view returns (uint256) { return count; } @@ -55,12 +51,12 @@ contract Counter { Observe que: -- **Linha 5**: declaramos nosso evento e o que ele contém, o valor antigo e o novo valor. +- **Linha 5**: declaramos nosso evento e o que ele contém: o valor antigo e o novo valor. - **Linha 13**: Quando incrementamos nossa variável de contagem, emitimos o evento. -Se implementarmos o contrato e chamarmos a função de incremento, veremos que o Remix será exibido automaticamente se você clicar na nova transação dentro de um array de logs nomeados. +Se implantarmos o contrato agora e chamarmos a função de incremento, veremos que o Remix o exibirá automaticamente se você clicar na nova transação dentro de um array chamado logs. -![Captura de tela Remix](./remix-screenshot.png) +![Captura de tela do Remix](./remix-screenshot.png) -Os logs são muito úteis para depurar seus contratos inteligentes, mas também são importantes se você criar aplicativos usados por diferentes pessoas e tornar mais fácil fazer análises para rastrear e entender como seu contrato inteligente é usado. Os registros gerados pelas transações são exibidos em exploradores de blocos populares e você também pode, por exemplo, usá-los para criar 'scripts' fora da cadeia para ver eventos específicos e agir quando eles ocorrerem. +Os logs são muito úteis para depurar seus contratos inteligentes, mas também são importantes se você constrói aplicações usadas por pessoas diferentes, o que facilita a análise para rastrear e entender como seu contrato inteligente é usado. Os logs gerados pelas transações são exibidos nos exploradores de bloco populares e você também pode, por exemplo, usá-los para criar scripts fora da cadeia para escutar eventos específicos e agir quando eles ocorrerem. diff --git a/public/content/translations/pt-br/developers/tutorials/merkle-proofs-for-offline-data-integrity/index.md b/public/content/translations/pt-br/developers/tutorials/merkle-proofs-for-offline-data-integrity/index.md index 791dfeb56ef..2829bc1edc4 100644 --- a/public/content/translations/pt-br/developers/tutorials/merkle-proofs-for-offline-data-integrity/index.md +++ b/public/content/translations/pt-br/developers/tutorials/merkle-proofs-for-offline-data-integrity/index.md @@ -1,9 +1,8 @@ --- title: Provas de Merkle para integridade de dados offline -description: Assegurar a integridade dos dados na cadeia para os dados armazenados, sobretudo, fora da cadeia +description: "Garantindo a integridade dos dados na cadeia para dados que são armazenados, em sua maioria, fora da cadeia" author: Ori Pomerantz -tags: - - "armazenamento" +tags: [ "armazenamento" ] skill: advanced lang: pt-br published: 2021-12-30 @@ -11,21 +10,23 @@ published: 2021-12-30 ## Introdução {#introduction} -Idealmente, gostaríamos de guardar tudo no armazenamento do Ethereum, que é armazenado em milhares de computadores e conta com uma disponibilidade extremamente alta (os dados não podem ser censurados) e integridade (os dados não podem ser modificados de forma não autorizada), sabendo que armazenar uma palavra de 32 bytes normalmente custa 20.000 gás. No momento em que estou escrevendo isto, o custo é equivalente a $6,60. A 21 centavos por byte, isso é bastante caro para muitas utilizações. +Idealmente, gostaríamos de guardar tudo no armazenamento do Ethereum, que é armazenado em milhares de computadores e conta com uma disponibilidade extremamente alta (os dados não podem ser censurados) e integridade (os dados não podem ser modificados de forma não autorizada), sabendo que armazenar uma palavra de 32 bytes normalmente custa 20.000 gás. No momento em que estou escrevendo isto, o custo +é equivalente a $6,60. A 21 centavos por byte, isso é bastante caro para muitas utilizações. -Para resolver esse problema, o ecossistema do Ethereum desenvolveu [muitas formas alternativas de armazenar dados de forma descentralizada](/developers/docs/storage/). Geralmente, elas envolvem um equilíbrio entre a disponibilidade e o preço. No entanto, a integridade é geralmente assegurada. +Para resolver esse problema, o ecossistema da Ethereum desenvolveu [muitas maneiras alternativas de armazenar dados de forma descentralizada](/developers/docs/storage/). Geralmente, elas envolvem um equilíbrio entre a disponibilidade e o preço. No entanto, a integridade é geralmente assegurada. -Neste artigo, você aprenderá **como** garantir a integridade dos dados sem armazenar os dados na blockchain, usando [ provas de Merkle](https://computersciencewiki.org/index.php/Merkle_proof). +Neste artigo, você aprenderá **como** garantir a integridade dos dados sem armazenar os dados na blockchain, usando +[provas de Merkle](https://computersciencewiki.org/index.php/Merkle_proof). ## Como isso funciona? {#how-does-it-work} -Em teoria, poderíamos apenas armazenar o hash dos dados na cadeia e enviar todos os dados em transações que precisam deles. No entanto, isso ainda é demasiado caro. Um byte de dados para uma transação custa cerca de 16 gás, atualmente cerca de meio centavo ou cerca de $5 por kilobyte. A $5.000 por megabyte, isso ainda é muito caro para várias utilizações, mesmo sem o custo adicional de hashing de dados. +Em teoria, poderíamos apenas armazenar o hash dos dados na cadeia e enviar todos os dados em transações que o exigem. No entanto, isso ainda é demasiado caro. Um byte de dados para uma transação custa cerca de 16 gás, atualmente cerca de meio centavo ou cerca de $5 por kilobyte. A $5.000 por megabyte, isso ainda é muito caro para várias utilizações, mesmo sem o custo adicional de hashing de dados. A solução é fazer hash repetidamente de diferentes subconjuntos dos dados. Para os dados que você não precisa enviar, você pode apenas enviar um hash. Você pode fazer isso usando uma árvore de Merkle, uma estrutura de dados de árvore em que cada nó é um hash dos nós abaixo: -![Árvores de Merkle](tree.png) +![Árvore de Merkle](tree.png) -O hash raiz é a única parte que precisa ser armazenada na cadeia. Para comprovar um determinado valor, forneça todos os hashes que precisam ser combinados com ele para obter a raiz. Por exemplo, para provar `C` você fornece `D`, `(H-B)`, e `H(E-H)`. +O hash raiz é a única parte que precisa ser armazenada na cadeia. Para comprovar um determinado valor, forneça todos os hashes que precisam ser combinados com ele para obter a raiz. Por exemplo, para provar `C`, você fornece `D`, `H(A-B)` e `H(E-H)`. ![Prova do valor de C](proof-c.png) @@ -33,11 +34,11 @@ O hash raiz é a única parte que precisa ser armazenada na cadeia. Para comprov [O código de exemplo é fornecido aqui](https://github.com/qbzzt/merkle-proofs-for-offline-data-integrity). -### Código fora da cadeia {#off-chain-code} +### Código fora da cadeia {#offchain-code} -Neste artigo, usamos JavaScript para os cálculos fora da cadeia. A maioria dos aplicativos descentralizados tem seu componente off-chain em JavaScript. +Neste artigo, usamos JavaScript para os cálculos fora da cadeia. A maioria dos aplicativos descentralizados tem seu componente fora da cadeia em JavaScript. -#### Criando a raiz Merkle {#creating-the-merkle-root} +#### Criando a raiz de Merkle {#creating-the-merkle-root} Primeiro, precisamos fornecer a raiz Merkle à cadeia. @@ -45,61 +46,64 @@ Primeiro, precisamos fornecer a raiz Merkle à cadeia. const ethers = require("ethers") ``` -[Usamos a função hash do pacote ethers](https://docs.ethers.io/v5/api/utils/hashing/#utils-keccak256). +[Usamos a função de hash do pacote ethers](https://docs.ethers.io/v5/api/utils/hashing/#utils-keccak256). ```javascript -// The raw data whose integrity we have to verify. The first two bytes a -// are a user identifier, and the last two bytes the amount of tokens the -// user owns at present. +// Os dados brutos cuja integridade temos que verificar. Os primeiros dois bytes a +// são um identificador de usuário, e os dois últimos bytes a quantidade de tokens que o +// usuário possui no momento. const dataArray = [ 0x0bad0010, 0x60a70020, 0xbeef0030, 0xdead0040, 0xca110050, 0x0e660060, 0xface0070, 0xbad00080, 0x060d0091, ] ``` -Codificar cada entrada em um único inteiro de 256 bits resulta em um código menos legível que o JSON, por exemplo. No entanto, isso significa um processamento significativamente menor para recuperar os dados contidos no contrato, portanto, custos de gás muito menores. [Você pode ler o JSON na cadeia](https://github.com/chrisdotn/jsmnSol), porém, isso é uma má ideia e evite fazer isso se puder. +Codificar cada entrada em um único inteiro de 256 bits resulta em um código menos legível que o JSON, por exemplo. No entanto, isso significa um processamento significativamente menor para recuperar os dados contidos no contrato, portanto, custos de gás muito menores. [Você pode ler JSON na cadeia](https://github.com/chrisdotn/jsmnSol), mas é uma má ideia se for evitável. ```javascript -// The array of hash values, as BigInts +// A matriz de valores de hash, como BigInts const hashArray = dataArray ``` Nesse caso, para começar, nossos dados têm um valor 256 bits. Portanto, não é necessário qualquer tipo de processamento. Se usarmos uma estrutura de dados mais complicada, como cadeias de caracteres, precisamos ter certeza de que fazemos primeiro o hash dos dados para obter uma matriz de hashes. Observe que isso também é devido ao fato de não nos importarmos se usuários conhecem as informações de outros usuários. Caso contrário, teríamos tido que fazer um hash, para que o usuário 1 não saiba o valor para o usuário 0, ao usuário 2 que não saberá o valor para o usuário 3, etc. ```javascript -// Convert between the string the hash function expects and the -// BigInt we use everywhere else. +// Converte entre a string que a função de hash espera e o +// BigInt que usamos em todos os outros lugares. const hash = (x) => BigInt(ethers.utils.keccak256("0x" + x.toString(16).padStart(64, 0))) ``` -A função hash de ethers espera obter uma cadeia de caracteres em JavaScript com um número hexadecimal, como `0x60A7`, e responde com outra cadeia de caracteres com a mesma estrutura. No entanto, para o resto do código, é mais fácil usar `BigInt`, então convertemos em uma cadeia de caracteres hexadecimal e de volta novamente. +A função de hash ethers espera obter uma string JavaScript com um número hexadecimal, como `0x60A7`, e responde com outra string com a mesma estrutura. No entanto, para o resto do código, é mais fácil usar `BigInt`, então convertemos para uma string hexadecimal e de volta novamente. ```javascript -// Symmetrical hash of a pair so we won't care if the order is reversed. +// Hash simétrico de um par para que não nos importemos se a ordem for invertida. const pairHash = (a, b) => hash(hash(a) ^ hash(b)) ``` -Essa função é simétrica (hash de um [xor](https://en.wikipedia.org/wiki/Exclusive_or) b). Isto significa que quando verificamos a prova de Merkle, não precisamos nos preocupar se devemos colocar o valor da prova antes ou depois do valor calculado. A verificação da prova de Merkle é feita na cadeia, portanto, quanto menos precisarmos fazer lá, melhor. +Esta função é simétrica (hash de um [xor](https://en.wikipedia.org/wiki/Exclusive_or) b). Isto significa que quando verificamos a prova de Merkle, não precisamos nos preocupar se devemos colocar o valor da prova antes ou depois do valor calculado. A verificação da prova de Merkle é feita na cadeia, portanto, quanto menos precisarmos fazer lá, melhor. -Atenção: A criptografia é mais difícil do que parece. A versão inicial deste artigo tinha a função hash `hash(a^b)`. Essa foi uma **má** ideia, porque significava que se você conhecesse os valores legítimos de `a` e de `b`, você poderia usar `b' = a^b^a'` para provar qualquer valor `a'` desejado. Com essa função, você teria que calcular `b'`, de forma que `hash(a') ^ hash(b')` fosse igual a um valor conhecido (o próximo branch a caminho da raiz), o que é muito mais difícil. +Atenção: A criptografia é mais difícil do que parece. +A versão inicial deste artigo tinha a função de hash `hash(a^b)`. +Essa foi uma **má** ideia, porque significava que se você conhecesse os valores legítimos de `a` e `b`, você poderia usar `b' = a^b^a'` para provar qualquer valor `a'` desejado. +Com esta função, você teria que calcular `b'` de tal forma que `hash(a') ^ hash(b')` seja igual a um valor conhecido (o próximo ramo a caminho da raiz), o que é muito mais difícil. ```javascript -// The value to denote that a certain branch is empty, doesn't -// have a value +// O valor para denotar que um determinado ramo está vazio, não +// tem um valor const empty = 0n ``` Quando o número de valores não é uma potência inteira de dois, precisamos lidar com branches vazios. O programa faz isso colocando zero como espaço reservado. -![Árvore de Merkle com branches faltando](merkle-empty-hash.png) +![Árvore de Merkle com ramos ausentes](merkle-empty-hash.png) ```javascript -// Calculate one level up the tree of a hash array by taking the hash of -// each pair in sequence +// Calcula um nível acima na árvore de uma matriz de hash, obtendo o hash de +// cada par em sequência const oneLevelUp = (inputArray) => { var result = [] - var inp = [...inputArray] // To avoid over writing the input // Add an empty value if necessary (we need all the leaves to be // paired) + var inp = [...inputArray] // Para evitar sobrescrever a entrada // Adicione um valor vazio se necessário (precisamos que todas as folhas sejam // pareadas) if (inp.length % 2 === 1) inp.push(empty) @@ -110,13 +114,13 @@ const oneLevelUp = (inputArray) => { } // oneLevelUp ``` -Esta função “escala” um nível na árvore de Merkle, fazendo hash dos pares de valores na camada atual. Observe que esta não é a implementação mais eficiente. Poderíamos ter evitado copiar a entrada e apenas adicionar `hashEmpty` quando apropriado no loop, mas este código é otimizado para melhorar a legibilidade. +Esta função “escala” um nível na árvore de Merkle, fazendo hash dos pares de valores na camada atual. Observe que esta não é a implementação mais eficiente, poderíamos ter evitado copiar a entrada e apenas adicionado `hashEmpty` quando apropriado no loop, mas este código é otimizado para legibilidade. ```javascript const getMerkleRoot = (inputArray) => { var result - result = [...inputArray] // Climb up the tree until there is only one value, that is the // root. // // If a layer has an odd number of entries the // code in oneLevelUp adds an empty value, so if we have, for example, // 10 leaves we'll have 5 branches in the second layer, 3 // branches in the third, 2 in the fourth and the root is the fifth + result = [...inputArray] // Sobe na árvore até que haja apenas um valor, que é a // raiz. // // Se uma camada tem um número ímpar de entradas, o // código em oneLevelUp adiciona um valor vazio, então se tivermos, por exemplo, // 10 folhas, teremos 5 ramos na segunda camada, 3 // ramos na terceira, 2 na quarta e a raiz é a quinta while (result.length > 1) result = oneLevelUp(result) @@ -131,41 +135,41 @@ Para obter a raiz, suba até que haja apenas um valor restante. Uma prova de Merkle é o conjunto de valores a fazer hash junto com o valor que está sendo provado para recuperar a raiz de Merkle. O valor a provar está frequentemente disponível a partir de outros dados, então eu prefiro fornecê-lo separadamente do que como parte do código. ```javascript -// A merkle proof consists of the value of the list of entries to -// hash with. Because we use a symmetrical hash function, we don't -// need the item's location to verify the proof, only to create it +// Uma prova de merkle consiste no valor da lista de entradas para +// fazer o hash. Como usamos uma função de hash simétrica, não +// precisamos da localização do item para verificar a prova, apenas para criá-la const getMerkleProof = (inputArray, n) => {     var result = [], currentLayer = [...inputArray], currentN = n -    // Until we reach the top +    // Até chegarmos ao topo     while (currentLayer.length > 1) { -        // No odd length layers +        // Nenhuma camada de comprimento ímpar         if (currentLayer.length % 2)             currentLayer.push(empty)         result.push(currentN % 2 -               // If currentN is odd, add with the value before it to the proof +               // Se currentN for ímpar, adicione o valor anterior a ele à prova             ? currentLayer[currentN-1] -               // If it is even, add the value after it +               // Se for par, adicione o valor depois dele             : currentLayer[currentN+1]) ``` -Fazemos o hash `(v[0],v[1])`, `(v[2],v[3])`, etc. Portanto, para valores pares, precisamos do próximo e, para valores ímpares, precisamos do anterior. +Fazemos o hash de `(v[0],v[1])`, `(v[2],v[3])`, etc. Portanto, para valores pares, precisamos do próximo e, para valores ímpares, precisamos do anterior. ```javascript -        // Move to the next layer up +        // Move para a próxima camada acima         currentN = Math.floor(currentN/2)         currentLayer = oneLevelUp(currentLayer) -    }   // while currentLayer.length > 1 +    }   // enquanto currentLayer.length > 1     return result }   // getMerkleProof ``` -### Código on-chain {#on-chain-code} +### Código na cadeia {#onchain-code} -Por fim, temos o código que verifica a prova. O código on-chain é escrito em [Solidity](https://docs.soliditylang.org/en/v0.8.11/). A otimização é aqui muito mais importante, porque o gás é relativamente caro. +Por fim, temos o código que verifica a prova. O código na cadeia é escrito em [Solidity](https://docs.soliditylang.org/en/v0.8.11/). A otimização é aqui muito mais importante, porque o gás é relativamente caro. ```solidity //SPDX-License-Identifier: Public Domain @@ -174,7 +178,7 @@ pragma solidity ^0.8.0; import "hardhat/console.sol"; ``` -Escrevi isso usando o [ambiente de desenvolvimento de hardware](https://hardhat.org/), que nos permite ter [saída do console do Solidity](https://hardhat.org/docs/cookbook/debug-logs) em desenvolvimento. +Escrevi isso usando o [ambiente de desenvolvimento Hardhat](https://hardhat.org/), que nos permite ter uma [saída de console do Solidity](https://hardhat.org/docs/cookbook/debug-logs) durante o desenvolvimento. ```solidity @@ -185,15 +189,15 @@ contract MerkleProof {       return merkleRoot;     } -    // Extremely insecure, in production code access to -    // this function MUST BE strictly limited, probably to an -    // owner +    // Extremamente inseguro, em código de produção, o acesso a +    // esta função DEVE SER estritamente limitado, provavelmente a um +    // proprietário     function setRoot(uint _merkleRoot) external {       merkleRoot = _merkleRoot;     }   // setRoot ``` -Configure e obtenha funções para a raiz de Merkle. Deixar que todo mundo atualize a raiz de Merkle é uma _ideia extremamente má_ em um sistema de produção. Aqui, faço isso por uma questão de simplicidade no código de exemplo. **Não faça isso em um sistema no qual a integridade de dados realmente importa**. +Configure e obtenha funções para a raiz de Merkle. Permitir que todos atualizem a raiz de Merkle é uma _péssima ideia_ em um sistema de produção. Aqui, faço isso por uma questão de simplicidade no código de exemplo. **Não faça isso em um sistema onde a integridade dos dados realmente importa**. ```solidity     function hash(uint _a) internal pure returns(uint) { @@ -205,12 +209,12 @@ Configure e obtenha funções para a raiz de Merkle. Deixar que todo mundo atual     } ``` -Essa função gera um par de hashes. Ela é simplesmente a tradução do Solidity do código em JavaScript para `hash` e `pairHash`. +Essa função gera um par de hashes. É apenas a tradução em Solidity do código JavaScript para `hash` e `pairHash`. -**Observação:** Este é outro caso de otimização para facilidade de leitura. Baseado em [a definição da função](https://www.tutorialspoint.com/solidity/solidity_cryptographic_functions.htm), é possível armazenar os dados como um valor de [`bytes32`](https://docs.soliditylang.org/en/v0.5.3/types.html#fixed-size-byte-arrays) e evitar as conversões. +**Observação:** este é outro caso de otimização para legibilidade. Com base na [definição da função](https://www.tutorialspoint.com/solidity/solidity_cryptographic_functions.htm), pode ser possível armazenar os dados como um valor [`bytes32`](https://docs.soliditylang.org/en/v0.5.3/types.html#fixed-size-byte-arrays) e evitar as conversões. ```solidity -    // Verify a Merkle proof +    // Verifica uma prova de Merkle     function verifyProof(uint _value, uint[] calldata _proof)         public view returns (bool) {       uint temp = _value; @@ -226,16 +230,18 @@ Essa função gera um par de hashes. Ela é simplesmente a tradução do Solidit }  // MarkleProof ``` -Na notação matemática, a verificação pela prova de Merkle tem esta aparência: `H(proof_n, H(proof_n-1, H(proof_n-2, ... H(prova_1, H(prova_0, valor)...)))`. Este código implementa-o. +Em notação matemática, a verificação da prova de Merkle se parece com isto: `H(proof_n, H(proof_n-1, H(proof_n-2, ...` `H(proof_1, H(proof_0, value))...)))`. Este código implementa-o. -## Provas de Merkle e rollups não se misturam {#merkle-proofs-and-rollups} +## Provas de Merkle e rollups não combinam {#merkle-proofs-and-rollups} As provas de Merkle não funcionam bem com [rollups](/developers/docs/scaling/#rollups). O motivo é que os rollups escrevem todos os dados da transação no L1, mas são processadas no L2. O custo para enviar uma prova de Merkle com uma média de transação a 638 gás por camada (atualmente, um byte nos dados de chamadas custa 16 gás se não for zero, e 4 se for zero). Se temos 1024 palavras de dados, uma prova de Merkle requer dez camadas, ou um total de 6380 gás. -Procurando um exemplo no [Optimism](https://public-grafana.optimism.io/d/9hkhMxn7z/public-dashboard?orgId=1&refresh=5m), escrever custos de gás L1 custa cerca de 100 gwei e escrever custos de gás L2 custa 0,001 gwei (esse é o preço normal, que pode aumentar com o congestionamento). Portanto, pelo custo de um gás L1 podemos gastar cem mil gás no processamento L2. Supondo que não sobrescrevamos o armazenamento, isso significa que podemos escrever cerca de cinco palavras para armazenamento na L2 pelo preço de um gás L1. Para uma única prova de Merkle, podemos escrever todas as 1024 palavras para armazenamento (assumindo que elas podem ser calculadas em cadeia para começar, em vez de serem fornecidos em uma transação) e ainda restam a maior parte do gás. +Olhando, por exemplo, para o [Optimism](https://public-grafana.optimism.io/d/9hkhMxn7z/public-dashboard?orgId=1&refresh=5m), escrever na L1 custa cerca de 100 gwei de gás e na L2 custa 0,001 gwei de gás (este é o preço normal, pode aumentar com o congestionamento). Portanto, pelo custo de um gás L1 podemos gastar cem mil gás no processamento L2. Supondo que não sobrescrevamos o armazenamento, isso significa que podemos escrever cerca de cinco palavras para armazenamento na L2 pelo preço de um gás L1. Para uma única prova de Merkle, podemos escrever todas as 1024 palavras no armazenamento (supondo que elas possam ser calculadas na cadeia para começar, em vez de serem fornecidas em uma transação) e ainda ter a maior parte do gás restante. ## Conclusão {#conclusion} Na vida real, você pode nunca implementar Merkle por conta própria. Existem bibliotecas conhecidas e auditadas que você pode usar e, de um modo geral, é melhor não implementar primitivos criptográficos por conta própria. Mas espero que agora você compreenda melhor as provas de Merkle e que possa decidir quando é que vale a pena utilizar. -Observe que, enquanto as provas de Merkle preservam a _integridade_, elas não preservam a disponibilidade __. Saber que mais ninguém pode tomar seus ativos é uma pequena consolação se o armazenamento de dados decidir impedir o acesso e você não pode construir uma Merkle para acessá-los também. Portanto, as árvores de Merkle são melhor usadas com algum tipo de armazenamento descentralizado, como IPFS. +Observe que, embora as provas de Merkle preservem a _integridade_, elas não preservam a _disponibilidade_. Saber que mais ninguém pode tomar seus ativos é uma pequena consolação se o armazenamento de dados decidir impedir o acesso e você não pode construir uma Merkle para acessá-los também. Portanto, as árvores de Merkle são melhor usadas com algum tipo de armazenamento descentralizado, como IPFS. + +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). diff --git a/public/content/translations/pt-br/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md b/public/content/translations/pt-br/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md index 0eeaaa39d5d..8c0b48d93f2 100644 --- a/public/content/translations/pt-br/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md +++ b/public/content/translations/pt-br/developers/tutorials/monitoring-geth-with-influxdb-and-grafana/index.md @@ -1,26 +1,24 @@ --- title: Monitorando o Geth com InfluxDB e Grafana -description: -author: "Mário Havel" -tags: - - "clientes" - - "nós" +description: "Configure o monitoramento para seu nó Geth usando InfluxDB e Grafana para acompanhar o desempenho e identificar problemas." +author: "Mario Havel" +tags: [ "clientes", "nós" ] skill: intermediate lang: pt-br published: 2021-01-13 --- -Esse tutorial ajudará você a configurar o monitoramento do seu Geth para você poder entender melhor o seu desempenho e identificar possíveis problemas. +Este tutorial irá ajudá-lo a configurar o monitoramento do seu nó Geth para que você possa entender melhor seu desempenho e identificar possíveis problemas. -## Pré-Requisitos {#prerequisites} +## Pré-requisitos {#prerequisites} -- Você já deveria estar executando uma instância de Geth. -- A maioria dos passos e exemplos são para o ambiente Linux, o conhecimento básico sobre terminais será útil. -- Confira este vídeo da visão geral da suíte de métricas do Geth: [Monitoring an Ethereum infrastructure by Péter Szilágyi](https://www.youtube.com/watch?v=cOBab8IJMYI). +- Você já deve estar executando uma instância do Geth. +- A maioria das etapas e exemplos é para o ambiente Linux, portanto, conhecimento básico de terminal será útil. +- Confira esta visão geral em vídeo do conjunto de métricas do Geth: [Monitoring an Ethereum infrastructure por Péter Szilágyi](https://www.youtube.com/watch?v=cOBab8IJMYI). -## Stack de monitoramento {#monitoring-stack} +## Pilha de monitoramento {#monitoring-stack} -Um cliente Ethereum coleta muitos dados que podem ser lidos na forma de uma base de dados cronológica. Para facilitar o monitoramento, você pode inserir isso em um software de visualização de dados. Existem múltiplas opções disponíveis: +Um cliente Ethereum coleta muitos dados que podem ser lidos na forma de um banco de dados cronológico. Para facilitar o monitoramento, você pode fornecer esses dados para um software de visualização de dados. Há várias opções disponíveis: - [Prometheus](https://prometheus.io/) (modelo pull) - [InfluxDB](https://www.influxdata.com/get-influxdb/) (modelo push) @@ -29,13 +27,14 @@ Um cliente Ethereum coleta muitos dados que podem ser lidos na forma de uma base - [Datadog](https://www.datadoghq.com/) - [Chronograf](https://www.influxdata.com/time-series-platform/chronograf/) -Também há o [Geth Prometheus Exporter](https://github.com/hunterlong/gethexporter), uma opção pré-configurada com InfluxDB e Grafana. +Há também o [Geth Prometheus Exporter](https://github.com/hunterlong/gethexporter), uma opção pré-configurada com InfluxDB e Grafana. -Neste tutorial, nós configuramos seu cliente Geth para enviar dados para o InfluxDB para criar um banco de dados e o Grafana para criar um gráfico de visualização dos dados. Fazer isso manualmente ajudará você a entender melhor o processo, alterá-lo e fazer deploy em diferentes ambientes. +Neste tutorial, vamos configurar seu cliente Geth para enviar dados para o InfluxDB a fim de criar um banco de dados e para o Grafana a fim de criar uma visualização gráfica dos dados. Fazer isso manualmente o ajudará a entender melhor o processo, alterá-lo e implantá-lo em diferentes ambientes. ## Configurando o InfluxDB {#setting-up-influxdb} -Primeiro, vamos baixar e instalar o InfluxDB. Várias opções de download podem ser encontradas na [página de release do Influxdata](https://portal.influxdata.com/downloads/). Escolha o que mais se adequa ao seu ambiente. Você também pode instalá-lo a partir de um [repositório](https://repos.influxdata.com/). Por exemplo, em uma distribuição baseada em Debian: +Primeiro, vamos baixar e instalar o InfluxDB. Várias opções de download podem ser encontradas na [página de lançamentos do Influxdata](https://portal.influxdata.com/downloads/). Escolha a que melhor se adapta ao seu ambiente. +Você também pode instalá-lo a partir de um [repositório](https://repos.influxdata.com/). Por exemplo, em uma distribuição baseada em Debian: ``` curl -tlsv1.3 --proto =https -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add @@ -48,7 +47,8 @@ sudo systemctl start influxdb sudo apt install influxdb-client ``` -Após instalar o InfluxDB com sucesso, certifique-se de que ele está sendo executado em segundo plano. Por padrão, ele é acessível em `localhost:8086`. Antes de usar o cliente `influx` você tem que criar um novo usuário com privilégios de administrador. Este usuário servirá para gerenciamento de alto nível, criando bancos de dados e usuários. +Após instalar o InfluxDB com sucesso, certifique-se de que ele está sendo executado em segundo plano. Por padrão, ele pode ser acessado em `localhost:8086`. +Antes de usar o cliente `influx`, você deve criar um novo usuário com privilégios de administrador. Este usuário servirá para o gerenciamento de alto nível, criação de bancos de dados e usuários. ``` curl -XPOST "http://localhost:8086/query" --data-urlencode "q=CREATE USER username WITH PASSWORD 'password' WITH ALL PRIVILEGES" @@ -60,7 +60,7 @@ Agora você pode usar o cliente influx para entrar no [shell do InfluxDB](https: influx -username 'username' -password 'password' ``` -Comunificando diretamente com o InfluxDB em seu shell, você pode criar banco de dados e usuário para métricas do geth. +Comunicando-se diretamente com o InfluxDB em seu shell, você pode criar um banco de dados e um usuário para as métricas do Geth. ``` create database geth @@ -74,25 +74,26 @@ show databases show users ``` -Saia do Shell InfluxDB. +Saia do shell do InfluxDB. ``` exit ``` -O InfluxDB está rodando e configurado para armazenar métricas do Geth. +O InfluxDB está em execução e configurado para armazenar as métricas do Geth. ## Preparando o Geth {#preparing-geth} -Depois de configurar o banco de dados, precisamos habilitar a coleção de métricas no Geth. Preste atenção em `METRICS AND STATS OPTIONS` com `geth --help`. Várias opções podem ser encontradas lá, neste caso queremos que o Geth envie dados para o InfluxDB. A configuração básica especifica o endpoint onde o InfluxDB é acessível e a autenticação para o banco de dados. +Após configurar o banco de dados, precisamos habilitar a coleta de métricas no Geth. Preste atenção em `METRICS AND STATS OPTIONS` em `geth --help`. Várias opções podem ser encontradas lá. Neste caso, queremos que o Geth envie dados para o InfluxDB. +A configuração básica especifica o endpoint onde o InfluxDB pode ser acessado e a autenticação para o banco de dados. ``` geth --metrics --metrics.influxdb --metrics.influxdb.endpoint "http://0.0.0.0:8086" --metrics.influxdb.username "geth" --metrics.influxdb.password "chosenpassword" ``` -Estas flags podem ser anexadas a um comando que inicie o cliente ou salvas no arquivo de configuração. +Essas flags podem ser anexadas a um comando que inicia o cliente ou salvas no arquivo de configuração. -Você pode verificar que o Geth está fazendo push de dados com sucesso, por exemplo, listando as métricas no banco de dados. Saia do shell do InfluxDB: +Você pode verificar se o Geth está enviando dados com sucesso, por exemplo, listando as métricas no banco de dados. No shell do InfluxDB: ``` use geth @@ -101,7 +102,8 @@ show measurements ## Configurando o Grafana {#setting-up-grafana} -O próximo passo é instalar o Grafana que interpretará os dados graficamente. Siga o processo de instalação do seu ambiente na documentação do Grafana. Certifique-se de instalar a versão OSS se você não quiser o contrário. Etapas de instalação de exemplo para distribuições Debian usando o repositório: +A próxima etapa é instalar o Grafana, que interpretará os dados graficamente. Siga o processo de instalação para o seu ambiente na documentação do Grafana. Certifique-se de instalar a versão OSS, a menos que queira de outra forma. +Exemplo de etapas de instalação para distribuições Debian usando o repositório: ``` curl -tlsv1.3 --proto =https -sL https://packages.grafana.com/gpg.key | sudo apt-key add - @@ -112,36 +114,38 @@ sudo systemctl enable grafana-server sudo systemctl start grafana-server ``` -Quando você estiver rodando o Grafana, ele deve ser acessível em `localhost:3000`. Use seu navegador preferido para acessar esta URL e, em seguida, faça login com as credenciais padrão (usuário: `admin` e senha: `admin`). Quando solicitado, altere a senha padrão e salve. +Quando o Grafana estiver em execução, ele deverá estar acessível em `localhost:3000`. +Use seu navegador preferido para acessar este caminho e faça login com as credenciais padrão (usuário: `admin` e senha: `admin`). Quando solicitado, altere a senha padrão e salve. -![](./grafana1.png) +![Captura de tela do painel Grafana para monitoramento Geth (painel 1)](./grafana1.png) -Você vai ser redirecionado para a página principal do Grafana. Primeiro, configure seu source data. Clique no ícone de configuração na barra esquerda e selecione "Data sources". +Você será redirecionado para a página inicial do Grafana. Primeiro, configure sua fonte de dados. Clique no ícone de configuração na barra esquerda e selecione "Fontes de dados". -![](./grafana2.png) +![Captura de tela do painel Grafana para monitoramento Geth (painel 2)](./grafana2.png) -Ainda não existem data sources criados, clique em "Add data source" para definir um. +Ainda não há nenhuma fonte de dados criada. Clique em "Adicionar fonte de dados" para definir uma. -![](./grafana3.png) +![Captura de tela do painel Grafana para monitoramento Geth (painel 3)](./grafana3.png) Para esta configuração, selecione "InfluxDB" e prossiga. -![](./grafana4.png) +![Captura de tela do painel Grafana para monitoramento Geth (painel 4)](./grafana4.png) -A configuração do data source é bem simples se você estiver rodando ferramentas na mesma máquina. Você precisa configurar o endereço e os detalhes do InfluxDB para acessar o banco de dados. Consulte a imagem abaixo. +A configuração da fonte de dados é bastante simples se você estiver executando as ferramentas na mesma máquina. Você precisa definir o endereço do InfluxDB e os detalhes para acessar o banco de dados. Consulte a imagem abaixo. -![](./grafana5.png) +![Captura de tela do painel Grafana para monitoramento Geth (painel 5)](./grafana5.png) -Se tudo estiver completo e o InfluxDB estiver acessível, clique em "Save and test" e aguarde a confirmação aparecer. +Se tudo estiver correto e o InfluxDB estiver acessível, clique em "Salvar e testar" e aguarde o surgimento da confirmação. -![](./grafana6.png) +![Captura de tela do painel Grafana para monitoramento Geth (painel 6)](./grafana6.png) -O Grafana está agora configurado para ler dados do InfluxDB. Agora você precisa criar um painel que o interprete e o exiba. As propriedades dos Dashboards são codificadas em arquivos JSON que podem ser criados por qualquer um e podem ser facilmente importados. Na barra esquerda, clique em "Create and Import". +O Grafana agora está configurado para ler dados do InfluxDB. Agora você precisa criar um dashboard que irá interpretá-los e exibi-los. As propriedades dos dashboards são codificadas em arquivos JSON que podem ser criados por qualquer pessoa e facilmente importados. Na barra à esquerda, clique em "Criar e importar". -![](./grafana7.png) +![Captura de tela do painel Grafana para monitoramento Geth (painel 7)](./grafana7.png) -Para um dashboard de monitoramento do Geth, copie o ID [deste dashboard](https://grafana.com/grafana/dashboards/13877/) e cole-o em "Import page" no Grafana. Depois de salvar o dashboard, ele deve ficar assim: +Para um dashboard de monitoramento do Geth, copie o ID [deste dashboard](https://grafana.com/grafana/dashboards/13877/) e cole-o na "Página de importação" do Grafana. Depois de salvar o dashboard, ele deve ter a seguinte aparência: -![](./grafana8.png) +![Captura de tela do painel Grafana para monitoramento Geth (painel 8)](./grafana8.png) -Você pode modificar seus dashboards. Cada dashboard pode ser editado, movido, removido ou adicionado. Você pode alterar suas configurações. É com você! Para saber mais sobre como os dashboards funcionam, consulte a [documentação do Grafana](https://grafana.com/docs/grafana/latest/dashboards/). Você também pode estar interessado sobre [Notificações / Alertas](https://grafana.com/docs/grafana/latest/alerting/). Isso permite configurar notificações de alerta para quando as métricas alcançarem certos valores. Vários canais de comunicação são suportados. +Você pode modificar seus dashboards. Cada painel pode ser editado, movido, removido ou adicionado. Você pode alterar suas configurações. A decisão é sua! Para saber mais sobre como os dashboards funcionam, consulte a [documentação do Grafana](https://grafana.com/docs/grafana/latest/dashboards/). +Você também pode se interessar por [Alertas](https://grafana.com/docs/grafana/latest/alerting/). Isso permite que você configure notificações de alerta para quando as métricas atingirem determinados valores. Vários canais de comunicação são suportados. diff --git a/public/content/translations/pt-br/developers/tutorials/nft-minter/index.md b/public/content/translations/pt-br/developers/tutorials/nft-minter/index.md index 7915b9561ce..1e531af54cb 100644 --- a/public/content/translations/pt-br/developers/tutorials/nft-minter/index.md +++ b/public/content/translations/pt-br/developers/tutorials/nft-minter/index.md @@ -1,14 +1,16 @@ --- -title: Tutorial de criação de uma NFT -description: Neste tutorial, você irá construir um minter NFT e, também, aprender a como criar um full stack dapp conectando seu contrato inteligente a um React frontend usando MetaMask e ferramentas Web3. +title: "Tutorial de criação de uma NFT" +description: "Neste tutorial, você irá construir um minter NFT e, também, aprender a como criar um full stack dapp conectando seu contrato inteligente a um React frontend usando MetaMask e ferramentas Web3." author: "smudgil" tags: - - "solidity" - - "NFT" - - "alchemy" - - "contratos inteligentes" - - "front-end" - - "Pinata" + [ + "Solidity", + "NFT", + "Alchemy", + "smart contracts", + "front-end", + "Pinata" + ] skill: intermediate lang: pt-br published: 2021-10-06 @@ -22,11 +24,11 @@ Ao criar um minter NFT — uma simples UI onde você pode inserir um link para s - Chamar métodos de contrato inteligentes no seu frontend - Assine transações usando MetaMask -Neste tutorial, usaremos o [React](https://reactjs.org/) como nossa estrutura de frontend. Como este tutorial está focado principalmente no desenvolvimento da Web3, nós não passaremos muito tempo detalhando os fundamentos do React. Em vez disso, nós focaremos em trazer funcionalidade para o nosso projeto. +Neste tutorial, usaremos o [React](https://react.dev/) como nossa estrutura de frontend. Como este tutorial está focado principalmente no desenvolvimento da Web3, nós não passaremos muito tempo detalhando os fundamentos do React. Em vez disso, nós focaremos em trazer funcionalidade para o nosso projeto. -Como pré-requisito, você deve ter uma compreensão mínima do React – saber como funcionam componentes, props, useState/useEffect e chamadas de funções básicas. Se você nunca ouviu falar de nenhum desses termos antes, você pode querer conferir este [Intro to React tutorial](https://reactjs.org/tutorial/tutorial.html). Para os que apreciam mais visualidade, é altamente recomendável esta excelente série de vídeos [Full Modern React Tutorial](https://www.youtube.com/playlist?list=PL4cUxeGkcC9gZD-TvwTutorialfod2gaISzfRiP9d) por Net Ninja. +Como pré-requisito, você deve ter uma compreensão mínima do React – saber como funcionam componentes, props, useState/useEffect e chamadas de funções básicas. Se você nunca ouviu falar de nenhum desses termos antes, talvez queira conferir este [tutorial de Introdução ao React](https://react.dev/learn/tutorial-tic-tac-toe). Para os alunos mais visuais, recomendamos fortemente esta excelente série de vídeos [Full Modern React Tutorial](https://www.youtube.com/playlist?list=PL4cUxeGkcC9gZD-Tvwfod2gaISzfRiP9d) do Net Ninja. -E se você ainda não fez, você definitivamente precisará criar uma conta Alchemy para concluir este tutorial, bem como construir qualquer coisa no blockchain. Inscreva-se para uma conta gratuita [aqui](https://alchemy.com/). +E se você ainda não fez, você definitivamente precisará criar uma conta Alchemy para concluir este tutorial, bem como construir qualquer coisa no blockchain. Cadastre-se para uma conta gratuita [aqui](https://alchemy.com/). Sem mais delongas, vamos começar! @@ -34,51 +36,51 @@ Sem mais delongas, vamos começar! Antes de começarmos a olhar para qualquer código, é importante entender como funciona fazer uma NFT. Envolve duas etapas: -### Publicar um contrato inteligente da NFT no blockchain Ethereum {#publish-nft} +### Publique um contrato inteligente de NFT na blockchain da Ethereum {#publish-nft} A maior diferença entre os dois padrões de contrato inteligente NFT é que o ERC-1155 é um padrão multi-token e inclui a funcionalidade de lote, enquanto o ERC-721 é um padrão de token único, portanto, suporta apenas a transferência de um token por vez. -### Chamar a função mint {#minting-function} +### Chame a função de mintagem {#minting-function} -Normalmente, esta função mint requer que você passe duas variáveis como parâmetros, primeiro o destinatário `recipient`, que especifica o endereço que receberá a sua NFT recém-mintada, e segundo o `tokenURI` da NFT, uma string que indica a um documento JSON que descreve os metadados da NFT. +Normalmente, esta função de mintagem exige que você passe duas variáveis como parâmetros: primeiro o `recipient`, que especifica o endereço que receberá seu NFT recém-mintado, e segundo o `tokenURI` do NFT, uma string que resolve para um documento JSON descrevendo os metadados do NFT. -Os metadados de uma NFT são o que realmente a torna realidade, permitindo que tenha propriedades configuráveis, como um nome, descrição, imagem (ou diferentes ativos digitais), e outros atributos. Aqui está [um exemplo de um tokenURI](https://gateway.pinata.cloud/ipfs/QmSvBcb4tjdFpajGJhbFAWeK3JAxCdNQLQtr6ZdiSi42V2), que contém os metadados de uma NFT. +Os metadados de uma NFT são o que realmente a torna realidade, permitindo que tenha propriedades configuráveis, como um nome, descrição, imagem (ou diferentes ativos digitais), e outros atributos. Aqui está [um exemplo de um tokenURI](https://gateway.pinata.cloud/ipfs/QmSvBcb4tjdFpajGJhbFAWeK3JAxCdNQLQtr6ZdiSi42V2), que contém os metadados de um NFT. Neste tutorial, vamos nos concentrar na parte 2, chamando a função mint de contrato inteligente de uma NFT existente usando nossa interface do React. -[Aqui está um link](https://ropsten.etherscan.io/address/0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE) para o contrato inteligente NFT ERC-721 que vamos chamar neste tutorial. Se você gostaria de saber como o fizemos, é altamente recomendável que você veja nosso outro tutorial, ["Como criar uma NFT"](https://docs.alchemyapi.io/alchemy/tutorials/how-to-create-an-nft). +[Aqui está um link](https://ropsten.etherscan.io/address/0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE) para o contrato inteligente de NFT ERC-721 que chamaremos neste tutorial. Se você quiser saber como o fizemos, recomendamos que confira nosso outro tutorial, ["Como Criar um NFT"](https://www.alchemy.com/docs/how-to-create-an-nft). Legal, agora que entendemos como fazer uma NFT funcionar, vamos clonar nossos arquivos iniciais! -## Clonar os arquivos iniciais {#clone-the-starter-files} +## Clone os arquivos iniciais {#clone-the-starter-files} -Primeiro, vá para o [repositório GitHub do nft-minter-tutorial](https://github.com/alchemyplatform/nft-minter-tutorial) para obter os arquivos iniciais para este projeto. Clone este repositório para o seu ambiente local.= +Primeiro, acesse o [repositório do GitHub nft-minter-tutorial](https://github.com/alchemyplatform/nft-minter-tutorial) para obter os arquivos iniciais deste projeto. Clone este repositório para o seu ambiente local. -Quando você abrir este repositório clonado `nft-minter-tutorial`, irá notar que ele contém duas pastas: `minter-starter-files` e `nft-minter`. +Ao abrir este repositório `nft-minter-tutorial` clonado, você notará que ele contém duas pastas: `minter-starter-files` e `nft-minter`. -- `minter-starter-files` contém os arquivos iniciais (essencialmente a interface do React) para este projeto. Neste tutorial, **trabalharemos nesse diretório**, enquanto você aprende a dar vida a sua interface do usuário, conectando-a à sua carteira Ethereum e a um contrato inteligente de NFT. -- `nft-minter` contém o tutorial completo e serve para você como uma **referência** **se você ficar preso.** +- `minter-starter-files` contém os arquivos iniciais (essencialmente a UI do React) para este projeto. Neste tutorial, **estaremos trabalhando neste diretório**, à medida que você aprende como dar vida a esta UI, conectando-a à sua carteira Ethereum e a um contrato inteligente de NFT. +- `nft-minter` contém o tutorial completo e está lá para você como uma **referência** **caso você trave.** -Em seguida, abra sua cópia de `minter-starter-files` no seu editor de código e navegue para a pasta `src`. +Em seguida, abra sua cópia de `minter-starter-files` em seu editor de código e navegue até a pasta `src`. -Todo o código que vamos escrever será exibido na pasta `src`. Vamos editar o componente `Minter.js` e escrever arquivos javascript adicionais para dar funcionalidades Web3 ao nosso projeto. +Todo o código que escrevermos ficará na pasta `src`. Estaremos editando o componente `Minter.js` e escrevendo arquivos javascript adicionais para dar ao nosso projeto a funcionalidade Web3. ## Passo 2: Confira nossos arquivos iniciais {#step-2-check-out-our-starter-files} Antes de começarmos a codificar, é importante verificar o que já está fornecido para nós nos arquivos iniciais. -### Tenha seu projeto React em execução {#get-your-react-project-running} +### Coloque seu projeto react para funcionar {#get-your-react-project-running} Vamos começar executando o projeto React em nosso navegador. A beleza do React é que uma vez que nosso projeto esteja sendo executado no nosso navegador, qualquer alteração que salvarmos será atualizada ao vivo em nosso navegador. -Para fazer com que o projeto funcione, navegue até o diretório raiz da pasta `minter-starter-files`, e execute`npm install` no seu terminal para instalar as dependências do projeto: +Para colocar o projeto para funcionar, navegue até o diretório raiz da pasta `minter-starter-files` e execute `npm install` em seu terminal para instalar as dependências do projeto: ```bash cd minter-starter-files npm install ``` -Uma vez terminada a instalação, execute `npm start` em seu terminal: +Assim que a instalação for concluída, execute `npm start` em seu terminal: ```bash npm start @@ -90,14 +92,14 @@ Se você tentar clicar nos botões "Connectar Wallet" ou "Mint NFT", você notar ### O componente Minter.js {#minter-js} -**NOTA:** Certifique-se de estar na pasta `minter-starter-files` e não na pasta `nft-minter`! +**OBSERVAÇÃO:** Certifique-se de que você está na pasta `minter-starter-files` e não na pasta `nft-minter`! -Vamos voltar à pasta `src` no nosso editor e abrir o arquivo `Minter.js`. É muito importante que entendamos tudo neste arquivo, pois é o principal componente do React no qual vamos trabalhar. +Vamos voltar para a pasta `src` em nosso editor e abrir o arquivo `Minter.js`. É muito importante que entendamos tudo neste arquivo, pois é o principal componente do React no qual vamos trabalhar. No topo do nosso arquivo, temos nossas variáveis de estado que serão atualizadas após eventos específicos. ```javascript -//State variables +//Variáveis de estado const [walletAddress, setWallet] = useState("") const [status, setStatus] = useState("") const [name, setName] = useState("") @@ -105,93 +107,93 @@ const [description, setDescription] = useState("") const [url, setURL] = useState("") ``` -Nunca ouviu falar de variáveis de estado do React ou State Hooks? Confira [está](https://reactjs.org/docs/hooks-state.html) documentação. +Nunca ouviu falar de variáveis de estado do React ou State Hooks? Confira [esta](https://legacy.reactjs.org/docs/hooks-state.html) documentação. Veja aqui o que cada uma das variáveis representa: - `walletAddress` - uma string que armazena o endereço da carteira do usuário -- `status` - uma string que contém uma mensagem a ser exibida na parte inferior da interface do usuário -- `name` - uma string que armazena o nome da NFT -- `descrição` - uma string que armazena a descrição da NFT -- `url` - uma string que é um link para o ativo digital da NFT +- `status` - uma string que contém uma mensagem para exibir na parte inferior da UI +- `name` - uma string que armazena o nome do NFT +- `description` - uma string que armazena a descrição do NFT +- `url` - uma string que é um link para o ativo digital do NFT -Após as variáveis de estado, você verá três funções não implementadas: `useEffect`, `connectWalletPressed`, e `onMintPressed`. Você irá notar que todas essas funções são `async`, isso é porque iremos fazer chamadas assíncronas da API nelas! Os nomes delas são relacionadas com sua funcionalidade: +Após as variáveis de estado, você verá três funções não implementadas: `useEffect`, `connectWalletPressed` e `onMintPressed`. Você notará que todas essas funções são `async`, porque faremos chamadas de API assíncronas nelas! Os nomes delas são relacionadas com sua funcionalidade: ```javascript useEffect(async () => { - //TODO: implement + //TODO: implementar }, []) const connectWalletPressed = async () => { - //TODO: implement + //TODO: implementar } const onMintPressed = async () => { - //TODO: implement + //TODO: implementar } ``` -- [`useEffect`](https://reactjs.org/docs/hooks-effect.html) - este é um React Hook que é chamado depois que seu componente é renderizado. Porque ele tem uma array vazia `[]` "prop" passada para ela (veja a linha 3), ela só será chamada na _primeira_ renderização do componente. Aqui vamos chamar nosso ouvinte de carteira e outra função de carteira para atualizar nossa interface de usuário para refletir se uma carteira já está conectada. +- [`useEffect`](https://legacy.reactjs.org/docs/hooks-effect.html) - este é um hook do React que é chamado depois que seu componente é renderizado. Como ele tem uma `prop` de array vazio `[]` passada para ele (veja a linha 3), ele só será chamado na _primeira_ renderização do componente. Aqui vamos chamar nosso ouvinte de carteira e outra função de carteira para atualizar nossa interface de usuário para refletir se uma carteira já está conectada. - `connectWalletPressed` - esta função será chamada para conectar a carteira MetaMask do usuário ao nosso dapp. -- `onMintPressed` - esta função será chamada para mintar a NFT do usuário. +- `onMintPressed` - esta função será chamada para mintar o NFT do usuário. -Perto do final desse arquivo, temos a interface de usuário do nosso componente. Se você escanear este código com cuidado, notará que atualizamos nossa `url`, `name`, e `description` variáveis de estado quando a entrada em seus campos de texto correspondentes muda. +Perto do final desse arquivo, temos a interface de usuário do nosso componente. Se você analisar este código com atenção, notará que atualizamos nossas variáveis de estado `url`, `name` e `description` quando a entrada em seus campos de texto correspondentes muda. -Você também verá que `connectWalletPressed` e `onMintPressed` são chamadas quando os botões com IDs `mintButton` e `walletButton` são clicados respectivamente. +Você também verá que `connectWalletPressed` e `onMintPressed` são chamadas quando os botões com os IDs `mintButton` e `walletButton` são clicados, respectivamente. ```javascript -//the UI of our component +//a UI do nosso componente return (


-

🧙‍♂️ Alchemy NFT Minter

+

🧙‍♂️ Mintador de NFT da Alchemy

- Simply add your asset's link, name, and description, then press "Mint." + Basta adicionar o link, nome e descrição do seu ativo e, em seguida, pressione "Mintar".

-

🖼 Link to asset:

+

🖼 Link para o ativo:

setURL(event.target.value)} /> -

🤔 Name:

+

🤔 Nome:

setName(event.target.value)} /> -

✍️ Description:

+

✍️ Descrição:

setDescription(event.target.value)} />

{status}

-
+ ) ``` Finalmente, vamos endereçar onde esse componente Minter será adicionado. -Se você for ao arquivo `App.js`, que é o componente principal do React que atua como um contêiner para todos os outros componentes, você verá que nosso componente Minter é injetado na linha 7. +Se você for ao arquivo `App.js`, que é o componente principal no React que atua como um contêiner para todos os outros componentes, você verá que nosso componente Minter é injetado na linha 7. -**Neste tutorial, vamos apenas editar o arquivo `Minter.js` e adicionar arquivos em nossa pasta `src`.** +**Neste tutorial, editaremos apenas o arquivo `Minter.js` e adicionaremos arquivos em nossa pasta `src`.** Agora que entendemos com o que estamos trabalhando, vamos configurar a nossa carteira Ethereum! @@ -199,41 +201,41 @@ Agora que entendemos com o que estamos trabalhando, vamos configurar a nossa car Para que os usuários possam interagir com o seu contrato inteligente, eles precisarão conectar a sua carteira Ethereum ao seu dapp. -### Baixar MetaMask {#download-metamask} +### Baixe o MetaMask {#download-metamask} -Para este tutorial, usaremos uma carteira virtual no navegador, a MetaMask, para gerenciar o endereço da sua conta Ethereum. Se você quiser entender mais sobre como as transações no Ethereum funcionam, confira [esta página](/developers/docs/transactions/) na Fundação Ethereum. +Para este tutorial, usaremos uma carteira virtual no navegador, a MetaMask, para gerenciar o endereço da sua conta Ethereum. Se você quiser entender mais sobre como as transações na Ethereum funcionam, confira [esta página](/developers/docs/transactions/). -Você pode baixar e criar uma conta MetaMask gratuitamente [neste link](https://metamask.io/download). Quando estiver criando uma conta, ou se já tiver uma, certifique-se de mudar para a "Ropsten Test Network", no canto superior direito (para não precisar lidar com dinheiro de verdade\). +Você pode baixar e criar uma conta MetaMask gratuitamente [aqui](https://metamask.io/download). Quando estiver criando uma conta, ou se já tiver uma, certifique-se de mudar para a "Ropsten Test Network", no canto superior direito (para não precisar lidar com dinheiro de verdade\). -### Etapa: Adicionar Faucet ether {#add-ether-from-faucet} +### Adicione ether de um Faucet {#add-ether-from-faucet} -Para mintar as nossas NFT (ou assinar quaisquer transações no blockchain Ethereum), precisaremos de alguns Eth falsos. Para obter Eth você pode ir para o [faucet da Ropsten](https://faucet.ropsten.be/), inserir seu endereço de conta Ropsten e clicar em "Send Ropsten Eth." Em seguida, você deve ver Eth em sua conta Metamask! +Para mintar as nossas NFT (ou assinar quaisquer transações no blockchain Ethereum), precisaremos de alguns Eth falsos. Para obter Eth, você pode ir ao [Ropsten faucet](https://faucet.ropsten.be/) e inserir o endereço da sua conta Ropsten, depois clicar em “Send Ropsten Eth.” Em seguida, você deve ver Eth em sua conta MetaMask! -### Conferir o seu saldo {#check-your-balance} +### Verifique seu saldo {#check-your-balance} -Para verificar novamente que tem saldo, vamos fazer uma solicitação através da ferramenta [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) fornecida pelo [compositor da Alchemy](https://composer.alchemyapi.io?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D). Ela mostrará a quantidade de Eth na sua carteira. Depois de inserir o endereço da sua conta da MetaMask e clicar em "Send Request", você verá uma resposta como esta: +Para verificar novamente se nosso saldo está lá, vamos fazer uma solicitação [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) usando a [ferramenta de composição da Alchemy](https://composer.alchemyapi.io/?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D). Ela mostrará a quantidade de Eth na sua carteira. Depois de inserir o endereço da sua conta da MetaMask e clicar em "Send Request", você verá uma resposta como esta: ```text {"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"} ``` -**NOTA:** Este resultado está em wei, não em ETH. Lembre-se de que "Wei" é a menor unidade de ether. A conversão de wei para eth é: 1 eth = 10¹⁸ wei. Então, se convertemos 0xde0b6b3a7640000 para decimal, temos 1\*10¹⁸ wei, que é igual a 1 eth. +**OBSERVAÇÃO:** Este resultado está em wei, não em eth. Lembre-se de que "Wei" é a menor unidade de ether. A conversão de wei para eth é: 1 eth = 10¹⁸ wei. Então, se convertemos 0xde0b6b3a7640000 para decimal, temos 1\*10¹⁸ wei, que é igual a 1 eth. Ufa! Nosso dinheiro falso está todo lá! -## Conecte o MetaMask à sua interface {#connect-metamask-to-your-UI} +## Conecte o MetaMask à sua UI {#connect-metamask-to-your-UI} Agora que nossa carteira MetaMask está configurada, vamos conectar nosso dapp a ela! -Como queremos prescrever conforme o paradigma [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller), vamos criar um arquivo separado que contém nossas funções para gerenciar a lógica, dados e regras de nosso dapp, e então passar essas funções para nosso frontend (nosso componente Minter.js). +Como queremos aderir ao paradigma [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller), vamos criar um arquivo separado que contém nossas funções para gerenciar a lógica, os dados e as regras do nosso dapp e, em seguida, passar essas funções para o nosso frontend (nosso componente Minter.js). -### Função `connectWallet` {#connect-wallet-function} +### A função `connectWallet` {#connect-wallet-function} -Para fazer isso, vamos criar uma nova pasta chamada `utils` em seu diretório `src` e adicionar um arquivo chamado `interact.js` dentro dele, que conterá todas as funções de nossa carteira e da interação com o contrato inteligente. +Para fazer isso, vamos criar uma nova pasta chamada `utils` em seu diretório `src` e adicionar um arquivo chamado `interact.js` dentro dela, que conterá todas as nossas funções de interação com a carteira e o contrato inteligente. -No nosso arquivo `interact.js`, vamos escrever uma função `connectWallet`, que então importar e chamará nosso componente `Minter.js`. +Em nosso arquivo `interact.js`, escreveremos uma função `connectWallet`, que então importaremos e chamaremos em nosso componente `Minter.js`. -No seu arquivo`interact.js`, adicione o seguinte +No seu arquivo `interact.js`, adicione o seguinte ```javascript export const connectWallet = async () => { @@ -243,7 +245,7 @@ export const connectWallet = async () => { method: "eth_requestAccounts", }) const obj = { - status: "👆🏽 Write a message in the text-field above.", + status: "👆🏽 Escreva uma mensagem no campo de texto acima.", address: addressArray[0], } return obj @@ -261,8 +263,7 @@ export const connectWallet = async () => {

{" "} 🦊 - You must install MetaMask, a virtual Ethereum wallet, in your - browser. + Você deve instalar o MetaMask, uma carteira virtual Ethereum, em seu navegador.

@@ -274,26 +275,26 @@ export const connectWallet = async () => { Vamos dividir o que este código faz: -Primeiro, nossa função verifica se o `window.ethereum` está habilitado no seu navegador. +Primeiro, nossa função verifica se o `window.ethereum` está ativado em seu navegador. -`window.ethereum` é uma API global injetada pela MetaMask e outros provedores de carteira que permitem que sites solicitem contas Ethereum dos usuários. Se aprovada, ela pode ler dados das blockchains ao qual o usuário está conectado e sugerir que o usuário assine mensagens e transações. Confira a [documentação da MetaMask](https://docs.metamask.io/guide/ethereum-provider.html#table-of-contents) para obter mais informações! +`window.ethereum` é uma API global injetada pelo MetaMask e outros provedores de carteira que permite que sites solicitem as contas Ethereum dos usuários. Se aprovada, ela pode ler dados das blockchains ao qual o usuário está conectado e sugerir que o usuário assine mensagens e transações. Confira a [documentação do MetaMask](https://docs.metamask.io/guide/ethereum-provider.html#table-of-contents) para mais informações! -Se `window.ethereum` _não está_ presente, então isso significa que o MetaMask não está instalado. Isso resulta em um objeto JSON sendo retornado, onde o `endereço` retornado é uma string vazia, e o `status` do objeto JSX repassa que o usuário deve instalar o MetaMask. +Se o `window.ethereum` _não estiver_ presente, isso significa que o MetaMask não está instalado. Isso resulta no retorno de um objeto JSON, onde o `address` retornado é uma string vazia, e o objeto JSX `status` informa que o usuário deve instalar o MetaMask. -**A maioria das funções que escrevermos retornarão objetos JSON que podemos usar para atualizar nossas variáveis de estado e interface de usuário.** +**A maioria das funções que escrevermos retornará objetos JSON que podemos usar para atualizar nossas variáveis de estado e UI.** -Agora se `window.ethereum` _estiver_ presente, e é aí que as coisas ficam interessantes. +Agora, se o `window.ethereum` _estiver_ presente, é aí que as coisas ficam interessantes. -Usando um loop de try/catch, tentaremos nos conectar a MetaMask chamando`[window.ethereum.request({ method: "eth_requestAccounts" });](https://docs.metamask.io/guide/rpc-api.html#eth-requestaccounts)`. Chamando esta função o MetaMask irá abrir no navegador, onde o usuário será solicitado a conectar sua carteira ao seu dapp. +Usando um loop try/catch, tentaremos nos conectar ao MetaMask chamando [`window.ethereum.request({ method: \"eth_requestAccounts\" });`](https://docs.metamask.io/guide/rpc-api.html#eth-requestaccounts). Chamando esta função o MetaMask irá abrir no navegador, onde o usuário será solicitado a conectar sua carteira ao seu dapp. -- Se o usuário escolher conectar-se, `método: "eth_requestAccounts"` retornará um array que contém todos os endereços de conta do usuário que estão conectados ao dapp. No total, nossa função `connectWallet` retornará um objeto JSON que contém o _primeiro_ `address` desta matriz \(ver linha 9\) e uma mensagem `status` que pede que o usuário escreva uma mensagem para o contrato inteligente. -- Se o usuário rejeitar a conexão, então o objeto JSON vai conter uma string vazia para o `address` retornado e uma mensagem de `status` que reflete que o usuário rejeitou a conexão. +- Se o usuário optar por se conectar, o `method: \"eth_requestAccounts\"` retornará um array que contém todos os endereços de conta do usuário que estão conectados ao dapp. No total, nossa função `connectWallet` retornará um objeto JSON que contém o _primeiro_ `address` neste array (veja a linha 9) e uma mensagem de `status` que solicita ao usuário que escreva uma mensagem para o contrato inteligente. +- Se o usuário rejeitar a conexão, o objeto JSON conterá uma string vazia para o `address` retornado e uma mensagem de `status` que reflete que o usuário rejeitou a conexão. -### Adicionar função connectWallet ao seu componente UI Minter.js {#add-connect-wallet} +### Adicione a função connectWallet ao seu Componente de UI Minter.js {#add-connect-wallet} -Agora que escrevemos esta função `connectWallet`, vamos conectá-la ao nosso componente `Minter.js.`. +Agora que escrevemos esta função `connectWallet`, vamos conectá-la ao nosso componente `Minter.js`. -Primeiro, teremos que importar nossa função para o arquivo `Minter.js` adicionando `import { connectWallet } from "./utils/interact.js";` para o topo do arquivo `Minter.js`. Suas primeiras 11 linhas de `Minter.js` agora devem se parecer com isto: +Primeiro, teremos que importar nossa função para o nosso arquivo `Minter.js`, adicionando `import { connectWallet } from "./utils/interact.js";` no topo do arquivo `Minter.js`. Suas primeiras 11 linhas de `Minter.js` agora devem se parecer com isto: ```javascript import { useEffect, useState } from "react"; @@ -301,7 +302,7 @@ import { connectWallet } from "./utils/interact.js"; const Minter = (props) => { - //State variables + //Variáveis de estado const [walletAddress, setWallet] = useState(""); const [status, setStatus] = useState(""); const [name, setName] = useState(""); @@ -319,9 +320,9 @@ const connectWalletPressed = async () => { } ``` -Observe como a maior parte das nossas funcionalidades está abstraída do nosso componente `Minter.js` do arquivo `interact.js`? É assim que respeitamos o paradigma M-V-C! +Observe como a maior parte da nossa funcionalidade é abstraída do nosso componente `Minter.js` a partir do arquivo `interact.js`? É assim que respeitamos o paradigma M-V-C! -Em `connectWalletPressed`, simplesmente fazemos uma chamada de espera (await) para a função `connectWallet`, importada, e usando sua resposta, nós atualizaremos nossas variáveis `status` e `walletAddress` através de seus state hooks. +Em `connectWalletPressed`, nós simplesmente fazemos uma chamada `await` para a nossa função `connectWallet` importada e, usando sua resposta, atualizamos nossas variáveis `status` e `walletAddress` através de seus hooks de estado. Agora, vamos salvar os dois arquivos `Minter.js` e `interact.js` e testar nossa UI até agora. @@ -331,13 +332,13 @@ Se você tiver o MetaMask instalado, você será solicitado a conectar sua carte Você verá que o botão da carteira agora reflete que seu endereço está conectado. -Em seguida, tente atualizar a página... isso é estranho. Nosso botão de carteira está nos pedindo para conectar o MetaMask, mesmo que já esteja conectado... +Em seguida, tente atualizar a página... que estranho. Nosso botão de carteira está nos pedindo para conectar o MetaMask, mesmo que já esteja conectado... -Mas não se preocupe! Nós podemos facilmente corrigir isso implementando uma função chamada `getCurrentWalletConnected`, que irá verificar se um endereço já está conectado ao nosso dapp e atualizará nossa interface do usuário adequadamente! +Mas não se preocupe! Podemos corrigir isso facilmente implementando uma função chamada `getCurrentWalletConnected`, que verificará se um endereço já está conectado ao nosso dapp e atualizará nossa UI de acordo! -### Função getCurrentWalletConnected {#get-current-wallet} +### A função getCurrentWalletConnected {#get-current-wallet} -Em seu arquivo `interact.js`, adicione a função`getCurrentWalletConnected`: +No seu arquivo `interact.js`, adicione a seguinte função `getCurrentWalletConnected`: ```javascript export const getCurrentWalletConnected = async () => { @@ -349,12 +350,12 @@ export const getCurrentWalletConnected = async () => { if (addressArray.length > 0) { return { address: addressArray[0], - status: "👆🏽 Write a message in the text-field above.", + status: "👆🏽 Escreva uma mensagem no campo de texto acima.", } } else { return { address: "", - status: "🦊 Connect to MetaMask using the top right button.", + status: "🦊 Conecte-se ao MetaMask usando o botão no canto superior direito.", } } } catch (err) { @@ -371,8 +372,7 @@ export const getCurrentWalletConnected = async () => {

{" "} 🦊 - You must install MetaMask, a virtual Ethereum wallet, in your - browser. + Você deve instalar o MetaMask, uma carteira virtual Ethereum, em seu navegador.

@@ -382,23 +382,23 @@ export const getCurrentWalletConnected = async () => { } ``` -Este código é _muito_ semelhante à função `connectWallet` que acabamos de escrever. +Este código é _muito_ semelhante à função `connectWallet` que escrevemos anteriormente. -A diferença principal é que, em vez de chamar o método `eth_requestAccounts`, que abre o MetaMask para o usuário conectar sua carteira, aqui chamamos o método `eth_accounts`, que simplesmente retorna uma matriz que contém os endereços MetaMask atualmente conectados ao nosso dapp. +A principal diferença é que, em vez de chamar o método `eth_requestAccounts`, que abre o MetaMask para o usuário conectar sua carteira, aqui chamamos o método `eth_accounts`, que simplesmente retorna uma matriz contendo os endereços do MetaMask atualmente conectados ao nosso dapp. Para ver essa função em ação, vamos chamá-la na função `useEffect` do nosso componente `Minter.js`. -Como fizemos para `connectWallet`, devemos importar essa função do nosso arquivo `interact.js` para o `Minter.js`, assim: +Como fizemos para `connectWallet`, devemos importar essa função do nosso arquivo `interact.js` para o nosso arquivo `Minter.js` da seguinte forma: ```javascript import { useEffect, useState } from "react" import { connectWallet, - getCurrentWalletConnected, //import here + getCurrentWalletConnected, //importar aqui } from "./utils/interact.js" ``` -Agora, simplesmente a chamamos em nossa função `useEffect`: +Agora, nós simplesmente a chamamos em nossa função `useEffect`: ```javascript useEffect(async () => { @@ -408,15 +408,15 @@ useEffect(async () => { }, []) ``` -Note que nós usamos a resposta da nossa chamada a `getCurrentWalletConnected` para atualizar nossa `walletAddress` e nossa variável de estado `status`. +Observe que usamos a resposta da nossa chamada para `getCurrentWalletConnected` para atualizar nossas variáveis de estado `walletAddress` e `status`. Depois de adicionar este código, tente atualizar a janela do navegador. O botão deve dizer que você está conectado e mostrar uma visualização do endereço de sua carteira conectada - mesmo depois de atualizar! -### Implementar addWalletListener {#implement-add-wallet-listener} +### Implemente addWalletListener {#implement-add-wallet-listener} O passo final na configuração da nossa carteira dapp é implementar o ouvinte de carteira, para que nossa interface atualize quando o estado mudar, como quando o usuário desconecta ou troca de contas. -No seu arquivo `Minter.js`, adicione a função `addWalletListener` que se parece com o seguinte: +No seu arquivo `Minter.js`, adicione uma função `addWalletListener` que se pareça com o seguinte: ```javascript function addWalletListener() { @@ -424,10 +424,10 @@ function addWalletListener() { window.ethereum.on("accountsChanged", (accounts) => { if (accounts.length > 0) { setWallet(accounts[0]) - setStatus("👆🏽 Write a message in the text-field above.") + setStatus("👆🏽 Escreva uma mensagem no campo de texto acima.") } else { setWallet("") - setStatus("🦊 Connect to MetaMask using the top right button.") + setStatus("🦊 Conecte-se ao MetaMask usando o botão superior direito.") } }) } else { @@ -435,7 +435,7 @@ function addWalletListener() {

{" "} 🦊 - You must install MetaMask, a virtual Ethereum wallet, in your browser. + Você deve instalar o MetaMask, uma carteira virtual Ethereum, em seu navegador.

) @@ -445,9 +445,9 @@ function addWalletListener() { Vamos dividir rapidamente o que está acontecendo aqui: -- Primeiro, nossa função verifica se o `window.ethereum` está habilitado no seu navegador \(ex. MetaMask instalado\). - - Caso contrário, nós simplesmente configuramos a variável de estado `status` para uma JSX string que solicita o usuário instalar a MetaMask. - - Se estiver habilitado, configuramos o ouvinte `window.ethereum.on("accountsChanged")` na linha 3 que houve mudança de estado na carteira MetaMask, inclusive quando o usuário conecta uma conta adicional ao dapp, troca de conta ou desconecta uma conta. Se houver pelo menos uma conta conectada, a variável de estado `walletAddress` é atualizada como a primeira conta no array `accounts` retornada pelo ouvinte. Caso contrário, `walletAddress` é definida como uma string vazia. +- Primeiro, nossa função verifica se o `window.ethereum` está ativado (ou seja, se o MetaMask está instalado). + - Se não estiver, simplesmente definimos nossa variável de estado `status` como uma string JSX que solicita ao usuário que instale o MetaMask. + - Se estiver habilitado, configuramos o listener `window.ethereum.on("accountsChanged")` na linha 3 que escuta por mudanças de estado na carteira MetaMask, que incluem quando o usuário conecta uma conta adicional ao dapp, troca de contas ou desconecta uma conta. Se houver pelo menos uma conta conectada, a variável de estado `walletAddress` é atualizada como a primeira conta no array `accounts` retornado pelo listener. Caso contrário, o `walletAddress` é definido como uma string vazia. Finalmente, nós devemos chamá-la em nossa função `useEffect`: @@ -463,11 +463,11 @@ useEffect(async () => { E Voila! Concluímos a programação de toda a funcionalidade da nossa carteira! Agora que a nossa carteira está pronta, vamos descobrir como mintar nossa NFT! -## Metadados NFT 101 {#nft-metadata-101} +## Metadados de NFT 101 {#nft-metadata-101} Lembra dos metadados da NFT que acabamos de falar no Passo 0 deste tutorial - ele dá vida a uma NFT, permitindo que tenha propriedades, como um ativo digital, nome, descrição e outros atributos. -Vamos precisar configurar esse metadado como um objeto JSON e amarzena-lo, para que possamos passa-lo como parâmetro `tokenURI` quando chamarmos a função `mintNFT` do nosso contrato inteligente. +Vamos precisar configurar esses metadados como um objeto JSON e armazená-lo, para que possamos passá-lo como o parâmetro `tokenURI` ao chamar a função `mintNFT` do nosso contrato inteligente. No campo texto "Link to Asset", "Name", "Description" inclui as diferentes propriedades dos metadados de nosso NFT. Nós vamos formatar estes metadados como um objeto JSON, mas há algumas opções para onde podemos armazenar este objeto JSON: @@ -475,39 +475,39 @@ No campo texto "Link to Asset", "Name", "Description" inclui as diferentes propr - Nós poderíamos armazená-lo em um servidor centralizado, como AWS ou Firebase. Mas isso iria contra nossa ética de descentralização. - Poderíamos usar o IPFS, um protocolo descentralizado e uma rede peer-to-peer para armazenar e compartilhar dados em um sistema de arquivos distribuído. Como este protocolo é descentralizado e gratuito, essa é a melhor opção! -Para armazenar nossos metadados no IPFS, vamos usar [Pinata](https://pinata.cloud/), uma conveniente API IPFS e um conjunto de ferramentas. Na próxima etapa, vamos explicar exatamente como fazer isso! +Para armazenar nossos metadados no IPFS, usaremos o [Pinata](https://pinata.cloud/), uma API e um kit de ferramentas IPFS convenientes. Na próxima etapa, vamos explicar exatamente como fazer isso! ## Use o Pinata para fixar seus metadados no IPFS {#use-pinata-to-pin-your-metadata-to-IPFS} -Se você não tem uma conta no [Pinata](https://pinata.cloud/), cadastre-se [aqui](https://pinata.cloud/) gratuitamente e conclua as etapas de confirmação do seu e-mail e conta. +Se você não tiver uma conta no [Pinata](https://pinata.cloud/), cadastre-se para obter uma conta gratuita [aqui](https://app.pinata.cloud/auth/signup) e conclua as etapas para verificar seu e-mail e conta. -### Crie sua chave API do Pinata {#create-pinata-api-key} +### Crie sua chave de API do Pinata {#create-pinata-api-key} -Navegue para a página[https://pinata.cloud/keys](https://pinata.cloud/keys), então selecione o botão "New Key" no topo da página, defina o Admin widget como ativado, e nomeie sua chave. +Navegue até a página [https://pinata.cloud/keys](https://pinata.cloud/keys), selecione o botão "Nova Chave" na parte superior, defina o widget Admin como ativado e nomeie sua chave. Será mostrado a você um pop-up com as informações da sua API. Certifique-se de colocar isto num lugar seguro. Agora que a nossa chave está configurada, vamos adicioná-la ao nosso projeto para que possamos usá-la. -### Criar o arquivo .env {#create-a-env} +### Crie um arquivo .env {#create-a-env} Podemos armazenar com segurança nossa chave e segredo do Pinata em um arquivo de ambiente. Vamos instalar o [pacote dotenv](https://www.npmjs.com/package/dotenv) no diretório do seu projeto. -Abra uma nova aba no seu terminal \(separado do terminal executando o local host\) e certifique-se de estar na pasta `minter-starter-files`, então execute o seguinte comando no seu terminal: +Abra uma nova aba em seu terminal (separada da que está executando o host local) e certifique-se de estar na pasta `minter-starter-files`. Em seguida, execute o seguinte comando em seu terminal: ```text npm install dotenv --save ``` -Em seguida, crie um arquivo `.env` no diretório raiz dos seus `minter-starter-files` inserindo o seguinte na sua linha de comando: +Em seguida, crie um arquivo `.env` no diretório raiz de seus `minter-starter-files` inserindo o seguinte na sua linha de comando: ```javascript vim.env ``` -Isto abrirá seu arquivo `.env` no formato vim \(um editor de texto\). Para salvar, aperte "esc" + ":" + "q" no seu teclado nesta ordem. +Isso abrirá seu arquivo `.env` no vim (um editor de texto). Para salvar, aperte "esc" + ":" + "q" no seu teclado nesta ordem. -Em seguida, no VSCode, navegue até o seu arquivo `.env` e adicione sua chave de API Pinata e sua API secreta, assim: +Em seguida, no VSCode, navegue até o seu arquivo .env e adicione sua chave de API e segredo de API da Pinata a ele, da seguinte forma: ```text REACT_APP_PINATA_KEY = @@ -516,11 +516,11 @@ REACT_APP_PINATA_SECRET = Salve o arquivo e então você estará pronto para começar a escrever a função de enviar seus metadados JSON para IPFS! -### Implementar pinJSONToIPFS {#pin-json-to-ipfs} +### Implemente pinJSONToIPFS {#pin-json-to-ipfs} -Felizmente para nós, a Pinata tem uma API [especificamente para carregar dados JSON para o IPFS](https://docs.pinata.cloud/api-reference/endpoint/ipfs/pin-json-to-ipfs#pin-json) e um JavaScript conveniente com axios de exemplo que podemos usar, com algumas pequenas modificações. +Felizmente para nós, a Pinata tem uma [API especificamente para carregar dados JSON para o IPFS](https://docs.pinata.cloud/api-reference/endpoint/ipfs/pin-json-to-ipfs#pin-json) e um exemplo conveniente em JavaScript com axios que podemos usar, com algumas pequenas modificações. -Na sua pasta `utils`, vamos criar outro arquivo chamado `pinata.js` e então importar nossa chave Pinata do arquivo .env assim: +Na sua pasta `utils`, vamos criar outro arquivo chamado `pinata.js` e então importar nosso segredo e chave do Pinata do arquivo .env da seguinte forma: ```javascript require("dotenv").config() @@ -539,7 +539,7 @@ const axios = require("axios") export const pinJSONToIPFS = async (JSONBody) => { const url = `https://api.pinata.cloud/pinning/pinJSONToIPFS` - //making axios POST request to Pinata ⬇️ + //fazendo a requisição axios POST para o Pinata ⬇️ return axios .post(url, JSONBody, { headers: { @@ -566,30 +566,30 @@ export const pinJSONToIPFS = async (JSONBody) => { Então, o que esse código faz exatamente? -Primeiro, importa [axios](https://www.npmjs.com/package/axios), a um cliente HTTP baseado em promessas para o navegador e node.js, que utilizaremos para fazer um pedido a Pinata. +Primeiro, ele importa o [axios](https://www.npmjs.com/package/axios), um cliente HTTP baseado em promessas para o navegador e node.js, que usaremos para fazer uma requisição para o Pinata. -Em seguida, temos nossa função assíncrona `pinJSONToIPFS`, que recebe um `JSONBody` como sua entrada e a chave e senha do API Pinata em seu cabeçalho, tudo para fazer uma solicitação POST para sua API `pinJSONToIPFS`. +Em seguida, temos nossa função assíncrona `pinJSONToIPFS`, que recebe um `JSONBody` como entrada e a chave e segredo da API da Pinata em seu cabeçalho, tudo para fazer uma requisição POST para sua API `pinJSONToIPFS`. -- Se esta solicitação POST for bem sucedida, então nossa função retorna um objeto JSON com o valor booleano `sucess` como verdadeiro e a `pinataUrl` onde nossos metadados foram fixados. Nós usaremos a `pinataUrl` retornada, como entrada na `tokenURI` para a função mint do nosso contrato inteligente. -- Se esta solicitação POST falhar, então, nossa função retorna um objeto JSON com o booleano `success` como falso e uma `message` que transmite nosso erro. +- Se esta requisição POST for bem-sucedida, nossa função retornará um objeto JSON com o booleano `success` como verdadeiro e o `pinataUrl` onde nossos metadados foram fixados. Usaremos este `pinataUrl` retornado como a entrada `tokenURI` para a função de mintagem do nosso contrato inteligente. +- Se esta solicitação de post falhar, nossa função retornará um objeto JSON com o booleano de `success` como falso e uma string `message` que transmite nosso erro. -Assim como na nossa função `connectWallet`retorna tipos, estamos retornando objetos JSON para que possamos usar seus parâmetros para atualizar nossas variáveis de estado e nossa interface de usuário. +Assim como nos tipos de retorno da nossa função `connectWallet`, estamos retornando objetos JSON para que possamos usar seus parâmetros para atualizar nossas variáveis de estado e a UI. -## Carregar seu contrato inteligente {#load-your-smart-contract} +## Carregue seu contrato inteligente {#load-your-smart-contract} -Agora que temos uma maneira de enviar nossos metadados NFT para IPFS através de nossa função de `pinJSONToIPFS`, vamos precisar de uma forma de carregar uma instância do nosso contrato inteligente para que possamos chamar a função `mintNFT`. +Agora que temos uma maneira de enviar nossos metadados de NFT para o IPFS através de nossa função `pinJSONToIPFS`, vamos precisar de uma forma de carregar uma instância do nosso contrato inteligente para que possamos chamar sua função `mintNFT`. -Como mencionado anteriormente, neste tutorial usaremos [este é um contrato inteligente NFT existente](https://ropsten.etherscan.io/address/0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE); no entanto, se você quer aprender como o fizemos ou como fazer um você mesmo, é altamente recomendável que você confira nosso outro tutorial, ["Como criar uma NFT.](https://docs.alchemyapi.io/alchemy/tutorials/how-to-create-an-nft). +Como mencionamos anteriormente, neste tutorial usaremos [este contrato inteligente de NFT existente](https://ropsten.etherscan.io/address/0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE); no entanto, se você quiser aprender como o fizemos ou criar um você mesmo, recomendamos fortemente que você confira nosso outro tutorial, ["Como Criar um NFT."](https://www.alchemy.com/docs/how-to-create-an-nft). -### O contrato ABI {#contract-abi} +### A ABI do contrato {#contract-abi} -Se você examinar de perto nossos arquivos, você notará que no nosso diretório `src`, há um arquivo `contract-abi.json`. Um ABI é necessário para especificar qual função um contrato irá invocar, como também garantir que a função retornará dados no formato que você espera. +Se você examinou nossos arquivos de perto, deve ter notado que em nosso diretório `src`, há um arquivo `contract-abi.json`. Um ABI é necessário para especificar qual função um contrato irá invocar, como também garantir que a função retornará dados no formato que você espera. Também precisaremos de uma chave API Alchemy e da API Alchemy Web3 para conectar ao blockchain Ethereum e carregar o nosso contrato inteligente. -### Crie a sua chave API Alchemy {#create-alchemy-api} +### Crie sua chave de API da Alchemy {#create-alchemy-api} -Se ainda não tiver uma conta na Alchemy, você pode se cadastrar gratuitamente [neste link](https://alchemy.com/?a=eth-org-nft-minter) +Se você ainda não tem uma conta na Alchemy, [inscreva-se gratuitamente aqui.](https://alchemy.com/?a=eth-org-nft-minter) Assim que criar uma conta na Alchemy, você pode gerar uma chave de API criando um "app". Isso nos permitirá fazer solicitações à rede de testes Ropsten. @@ -609,18 +609,18 @@ REACT_APP_PINATA_SECRET = REACT_APP_ALCHEMY_KEY = https://eth-ropsten.alchemyapi.io/v2/ ``` -Agora que temos nosso contrato ABI e nossa chave API do Alchemy, estamos prontos para carregar o nosso contrato inteligente usando [Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3). +Agora que temos nossa ABI de contrato e nossa chave de API da Alchemy, estamos prontos para carregar nosso contrato inteligente usando o [Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3). -### Configure seu Alchemy Web3 endpoint e contrato {#setup-alchemy-endpoint} +### Configure seu endpoint e contrato do Alchemy Web3 {#setup-alchemy-endpoint} -Primeiro, se você ainda não tiver, você precisará instalar [Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3) navegando até o diretório home: `nft-minter-tutorial` no terminal: +Primeiro, se você ainda não o tiver, precisará instalar o [Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3) navegando até o diretório inicial: `nft-minter-tutorial` no terminal: ```text cd .. -yarn add @alch/alchemy-web3 +npm install @alch/alchemy-web3 ``` -Em seguida, voltaremos para o nosso arquivo `interact.js`. No topo do arquivo, adicione o seguinte código para importar a chave de Alchemy do seu arquivo .env e configure seu Alchemy Web3 endpoint: +Em seguida, vamos voltar ao nosso arquivo `interact.js`. No topo do arquivo, adicione o seguinte código para importar a chave de Alchemy do seu arquivo .env e configure seu Alchemy Web3 endpoint: ```javascript require("dotenv").config() @@ -629,7 +629,7 @@ const { createAlchemyWeb3 } = require("@alch/alchemy-web3") const web3 = createAlchemyWeb3(alchemyKey) ``` -[Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3) é um invólucro em torno do [Web3.js](https://docs.web3js.org/), fornecendo métodos aprimorados da API e outros benefícios cruciais para tornar a sua vida de desenvolvedor da Web3 mais fácil. Ele foi projetado para exigir uma configuração mínima, para que você possa começar a usá-la no seu aplicativo imediatamente! +O [Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3) é um wrapper em torno do [Web3.js](https://docs.web3js.org/), fornecendo métodos de API aprimorados e outros benefícios cruciais para facilitar sua vida como desenvolvedor web3. Ele foi projetado para exigir uma configuração mínima, para que você possa começar a usá-la no seu aplicativo imediatamente! Em seguida, vamos adicionar nosso contrato ABI e endereço do contrato ao nosso arquivo. @@ -645,83 +645,83 @@ const contractAddress = "0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE" Assim que tivermos ambas as coisas, estaremos prontos para começar a codificar a nossa função "mint"! -## Implementar a função mintNFT {#implement-the-mintnft-function} +## Implemente a função mintNFT {#implement-the-mintnft-function} -Dentro do seu arquivo `interact.js`, vamos definir nossa função, `mintNFT`, que deliberadamente vai criar nossa NFT. +Dentro do seu arquivo `interact.js`, vamos definir nossa função, `mintNFT`, que, de forma homônima, irá mintar nosso NFT. Porque vamos fazer numerosas chamadas assíncronas \(para o Pinata fixar nossos metadados para IPFS, Alchemy Web3 para carregar o nosso contrato inteligente, e MetaMask para assinar nossas transações\), nossa função também será assíncrona. -As três entradas para nossa função serão a `url` do nosso ativo digital, `name`e `description`. Adicione a seguinte assinatura da função abaixo da função `connectWallet`: +As três entradas para nossa função serão a `url` do nosso ativo digital, o `name` e a `description`. Adicione a seguinte assinatura da função abaixo da função `connectWallet`: ```javascript export const mintNFT = async (url, name, description) => {} ``` -### Manipulação de erros de script {#input-error-handling} +### Tratamento de erros de entrada {#input-error-handling} Naturalmente, faz sentido ter algum tipo de tratamento de erro de entrada no início da função, então vamos sair desta função se nossos parâmetros de entrada não estiverem corretos. Dentro da nossa função, vamos adicionar o seguinte código: ```javascript export const mintNFT = async (url, name, description) => { - //error handling + //tratamento de erros if (url.trim() == "" || name.trim() == "" || description.trim() == "") { return { success: false, - status: "❗Please make sure all fields are completed before minting.", + status: "❗Certifique-se de que todos os campos estão preenchidos antes de mintar.", } } } ``` -Essencialmente, se algum dos parâmetros de entrada for uma string vazia, então retornamos um objeto JSON onde o valor booleano `success` é falso, e a string `status` repassa que todos os campos na nossa UI precisam estar completos. +Essencialmente, se algum dos parâmetros de entrada for uma string vazia, retornamos um objeto JSON onde o booleano `success` é falso, e a string `status` informa que todos os campos em nossa UI devem ser preenchidos. -### Carregar os metadados para o IPFS {#upload-metadata-to-ipfs} +### Envie os metadados para o IPFS {#upload-metadata-to-ipfs} -Assim que soubermos que nossos metadados estão formatados corretamente, o próximo passo é envolvê-lo em um objeto JSON e enviá-lo para IPFS através do `pinJSONToIPFS` que escrevemos! +Assim que soubermos que nossos metadados estão formatados corretamente, o próximo passo é envolvê-lo em um objeto JSON e enviá-lo para o IPFS através do `pinJSONToIPFS` que escrevemos! -Para fazer isso, precisamos primeiro importar a função `pinJSONToIPFS` para nosso arquivo `interact.js`. No topo do `interact.js`, vamos adicionar: +Para fazer isso, primeiro precisamos importar a função `pinJSONToIPFS` para nosso arquivo `interact.js`. No topo do `interact.js`, vamos adicionar: ```javascript import { pinJSONToIPFS } from "./pinata.js" ``` -Lembre-se que `pinJSONToIPFS` recebe um corpo JSON. Então, antes de fazer a chamada, precisaremos formatar a nossa `url`, `name`e `description` parâmetros em um objeto JSON. +Lembre-se que o `pinJSONToIPFS` recebe um corpo JSON. Então, antes de fazer uma chamada para ele, precisaremos formatar nossos parâmetros `url`, `name` e `description` em um objeto JSON. -Vamos atualizar nosso código para criar um objeto JSON chamado `metadada` e então fazer uma chamada para `pinJSONToIPFS` com este parâmetro `metadada`: +Vamos atualizar nosso código para criar um objeto JSON chamado `metadata` e então fazer uma chamada para `pinJSONToIPFS` com este parâmetro `metadata`: ```javascript export const mintNFT = async (url, name, description) => { - //error handling + //tratamento de erros if (url.trim() == "" || name.trim() == "" || description.trim() == "") { return { success: false, - status: "❗Please make sure all fields are completed before minting.", + status: "❗Certifique-se de que todos os campos estão preenchidos antes de mintar.", } } - //make metadata + //criar metadados const metadata = new Object() metadata.name = name metadata.image = url metadata.description = description - //make pinata call + //fazer chamada ao pinata const pinataResponse = await pinJSONToIPFS(metadata) if (!pinataResponse.success) { return { success: false, - status: "😢 Something went wrong while uploading your tokenURI.", + status: "😢 Algo deu errado durante o upload do seu tokenURI.", } } const tokenURI = pinataResponse.pinataUrl } ``` -Note, nós armazenamos a resposta de nossa chamada para `pinJSONToIPFS(metadada)` no objeto `pinataResponse`. Então, analisamos esse objeto para quaisquer erros. +Observe que armazenamos a resposta da nossa chamada para `pinJSONToIPFS(metadata)` no objeto `pinataResponse`. Então, analisamos esse objeto para quaisquer erros. -Se houver um erro, nós retornamos um objeto JSON onde o `sucess` booleano é falso e nossa string `status` relata que nossa chamada falhou. Caso contrário, nós extraímos a `pinataURL` da `pinataResponse` e armazenamos como nossa variável `tokenURI`. +Se houver um erro, retornamos um objeto JSON onde o booleano `success` é falso e nossa string `status` informa que nossa chamada falhou. Caso contrário, extraímos o `pinataURL` da `pinataResponse` e o armazenamos como nossa variável `tokenURI`. -Agora é hora de carregar o nosso contrato inteligente usando a API da Alchemy Web3 que inicializamos no topo do nosso arquivo. Adicione a seguinte linha de código na parte inferior da função `mintNFT` para definir o contrato na `window.contract` variável global: +Agora é hora de carregar o nosso contrato inteligente usando a API da Alchemy Web3 que inicializamos no topo do nosso arquivo. Adicione a seguinte linha de código na parte inferior da função `mintNFT` para definir o contrato na variável global `window.contract`: ```javascript window.contract = await new web3.eth.Contract(contractABI, contractAddress) @@ -730,16 +730,16 @@ window.contract = await new web3.eth.Contract(contractABI, contractAddress) A última coisa a adicionar em nossa função `mintNFT` é a nossa transação Ethereum: ```javascript -//set up your Ethereum transaction +//configure sua transação Ethereum const transactionParameters = { - to: contractAddress, // Required except during contract publications. - from: window.ethereum.selectedAddress, // must match user's active address. + to: contractAddress, // Obrigatório, exceto durante a publicação de contratos. + from: window.ethereum.selectedAddress, // deve corresponder ao endereço ativo do usuário. data: window.contract.methods .mintNFT(window.ethereum.selectedAddress, tokenURI) - .encodeABI(), //make call to NFT smart contract + .encodeABI(), //faz uma chamada para o contrato inteligente de NFT } -//sign the transaction via MetaMask +//assine a transação via MetaMask try { const txHash = await window.ethereum.request({ method: "eth_sendTransaction", @@ -748,13 +748,13 @@ try { return { success: true, status: - "✅ Check out your transaction on Etherscan: https://ropsten.etherscan.io/tx/" + + "✅ Confira sua transação no Etherscan: https://ropsten.etherscan.io/tx/" + txHash, } } catch (error) { return { success: false, - status: "😥 Something went wrong: " + error.message, + status: "😥 Algo deu errado: " + error.message, } } ``` @@ -762,54 +762,54 @@ try { Se você já está familiarizado com as transações na Ethereum, perceberá que a estrutura é bem parecida com a que você já viu. - Primeiro, nós configuramos nossos parâmetros de transações. - - `to` especificar o endereço do destinatário \(nosso contrato inteligente\) - - `from` especifica o signatário da transação \(o endereço conectado ao MetaMask: `window.ethereum.selectedAddress`\) - - `data` contém a chamada para nosso contrato inteligente do método `mintNFT`, que recebe nossa `tokenURI` e o endereço da carteira do usuário, `window.ethereum.selectedAddress` como entradas -- Então, faremos uma chamada para, `window.ethereum.request,` onde pedimos ao MetaMask para assinar a transação. Note que nessa solicitação, estamos especificando nosso método eth \(eth_SentTransaction\) e passando em nossos `transactionParameters`. Neste ponto, a MetaMask irá abrir no navegador e pedirá que o usuário assine ou rejeite a transação. - - Se a transação for bem-sucedida, a função retornará um objeto JSON onde o booleano `success` é definido como verdadeiro e a string `status` pede que o usuário verifique o Etherscan para obter mais informações sobre sua transação. - - Se a transação falhar, a função retornará um objeto JSON onde o booleano `success` é definido como falso, `status` string retransmite a mensagem de erro. + - `to` especifica o endereço do destinatário (nosso contrato inteligente) + - `from` especifica o assinante da transação (o endereço conectado do usuário ao MetaMask: `window.ethereum.selectedAddress`) + - `data` contém a chamada para o nosso método `mintNFT` de contrato inteligente, que recebe o nosso `tokenURI` e o endereço da carteira do usuário, `window.ethereum.selectedAddress`, como entradas +- Então, fazemos uma chamada de `await`, `window.ethereum.request`, onde pedimos ao MetaMask para assinar a transação. Observe que, nesta solicitação, estamos especificando nosso método eth (`eth_SentTransaction`) e passando nossos `transactionParameters`. Neste ponto, a MetaMask irá abrir no navegador e pedirá que o usuário assine ou rejeite a transação. + - Se a transação for bem-sucedida, a função retornará um objeto JSON onde o booleano `success` é definido como verdadeiro e a string `status` solicita que o usuário verifique o Etherscan para obter mais informações sobre sua transação. + - Se a transação falhar, a função retornará um objeto JSON onde o booleano `success` é definido como falso, e a string `status` retransmite a mensagem de erro. -Ao todo, nossa função `mintNFT` deve-se parecer com isto: +No total, nossa função `mintNFT` deve se parecer com isto: ```javascript export const mintNFT = async (url, name, description) => { - //error handling + //tratamento de erros if (url.trim() == "" || name.trim() == "" || description.trim() == "") { return { success: false, - status: "❗Please make sure all fields are completed before minting.", + status: "❗Certifique-se de que todos os campos estão preenchidos antes de mintar.", } } - //make metadata + //criar metadados const metadata = new Object() metadata.name = name metadata.image = url metadata.description = description - //pinata pin request + //solicitação de fixação do pinata const pinataResponse = await pinJSONToIPFS(metadata) if (!pinataResponse.success) { return { success: false, - status: "😢 Something went wrong while uploading your tokenURI.", + status: "😢 Algo deu errado durante o upload do seu tokenURI.", } } const tokenURI = pinataResponse.pinataUrl - //load smart contract + //carregar contrato inteligente window.contract = await new web3.eth.Contract(contractABI, contractAddress) //loadContract(); - //set up your Ethereum transaction + //configure sua transação Ethereum const transactionParameters = { - to: contractAddress, // Required except during contract publications. - from: window.ethereum.selectedAddress, // must match user's active address. + to: contractAddress, // Obrigatório, exceto durante a publicação de contratos. + from: window.ethereum.selectedAddress, // deve corresponder ao endereço ativo do usuário. data: window.contract.methods .mintNFT(window.ethereum.selectedAddress, tokenURI) - .encodeABI(), //make call to NFT smart contract + .encodeABI(), //faz uma chamada para o contrato inteligente de NFT } - //sign transaction via MetaMask + //assinar transação via MetaMask try { const txHash = await window.ethereum.request({ method: "eth_sendTransaction", @@ -818,23 +818,23 @@ export const mintNFT = async (url, name, description) => { return { success: true, status: - "✅ Check out your transaction on Etherscan: https://ropsten.etherscan.io/tx/" + + "✅ Confira sua transação no Etherscan: https://ropsten.etherscan.io/tx/" + txHash, } } catch (error) { return { success: false, - status: "😥 Something went wrong: " + error.message, + status: "😥 Algo deu errado: " + error.message, } } } ``` -Essa é uma função gigante! Agora, só precisamos conectar nossa função `mintNFT` com nosso componente `Minter.js`... +Essa é uma função gigante! Agora, só precisamos conectar nossa função `mintNFT` ao nosso componente `Minter.js`... -## Conectando mintNFT ao nosso frontend Minter.js {#connect-our-frontend} +## Conecte o mintNFT ao nosso frontend Minter.js {#connect-our-frontend} -Abra o seu arquivo `Minter.js` e atualize `import { connectWallet, getCurrentWalletConnected } from "./utils/interact.js";` a linha em cima deve ser: +Abra seu arquivo `Minter.js` e atualize a linha `import { connectWallet, getCurrentWalletConnected } from "./utils/interact.js";` no topo para ser: ```javascript import { @@ -844,7 +844,7 @@ import { } from "./utils/interact.js" ``` -Finalmente, implemente a função `onMintPressed` para fazer a chamada(await call) para a função `mintNFT`importada e atualize a variável de estado `status` para refletir se nossa transação foi bem-sucedida ou falhou: +Finalmente, implemente a função `onMintPressed` para fazer a chamada `await` para a sua função `mintNFT` importada e atualize a variável de estado `status` para refletir se nossa transação foi bem-sucedida ou falhou: ```javascript const onMintPressed = async () => { @@ -853,13 +853,13 @@ const onMintPressed = async () => { } ``` -## Implante seu NFT a um site ao vivo {#deploy-your-NFT} +## Implante seu NFT em um site ativo {#deploy-your-NFT} -Pronto para deixar seu projeto ao vivo para que usuários interajam? Confira [este tutorial](https://docs.alchemy.com/alchemy/tutorials/nft-minter/how-do-i-deploy-nfts-online) para implantar seu Minter em um site ao vivo. +Pronto para deixar seu projeto ao vivo para que usuários interajam? Confira [este tutorial](https://docs.alchemy.com/alchemy/tutorials/nft-minter/how-do-i-deploy-nfts-online) para implantar seu Mintador em um site ativo. Um último passo... -## Leve o mundo blockchain numa enxurrada {#take-the-blockchain-world-by-storm} +## Conquiste o mundo da blockchain {#take-the-blockchain-world-by-storm} Só uma brincadeira, você chegou ao fim do tutorial! @@ -869,6 +869,6 @@ Para recapitular, construindo um minter NFT, você aprendeu com sucesso como: - Chamar métodos de contrato inteligentes no seu frontend - Assine transações usando MetaMask -Provavelmente você gostaria de poder exibir seu NFT na sua carteira — então certifique-se de conferir [ a parte Como ver seu NFT na sua carteira](https://docs.alchemyapi.io/alchemy/tutorials/how-to-write-and-deploy-a-nft-smart-contract/how-to-view-your-nft-in-your-wallet)! +Presumivelmente, você gostaria de poder exibir os NFTs mintados através do seu dapp em sua carteira — então, certifique-se de conferir nosso rápido tutorial [Como Visualizar seu NFT em sua Carteira](https://www.alchemy.com/docs/how-to-view-your-nft-in-your-mobile-wallet)! -E, como sempre, se você tiver alguma dúvida, estamos aqui para ajudar no [Alchemy Discord](https://discord.gg/gWuC7zB). Mal podemos esperar para ver como você aplicará os conceitos deste tutorial em seus projetos futuros! +E, como sempre, se você tiver alguma dúvida, estamos aqui para ajudar no [Discord da Alchemy](https://discord.gg/gWuC7zB). Mal podemos esperar para ver como você aplicará os conceitos deste tutorial em seus projetos futuros! diff --git a/public/content/translations/pt-br/developers/tutorials/optimism-std-bridge-annotated-code/index.md b/public/content/translations/pt-br/developers/tutorials/optimism-std-bridge-annotated-code/index.md index 563bb7c50e7..e6259320790 100644 --- a/public/content/translations/pt-br/developers/tutorials/optimism-std-bridge-annotated-code/index.md +++ b/public/content/translations/pt-br/developers/tutorials/optimism-std-bridge-annotated-code/index.md @@ -1,84 +1,89 @@ --- -title: "Passo a passo do contrato de ponte padrão da Optimism" -description: Como funciona a ponte padrão para a Optimism? Porque funciona desta maneira? +title: "Passo a passo do contrato da ponte padrão do Optimism" +description: "Como funciona a ponte padrão para o Optimism? Por que funciona desta maneira?" author: Ori Pomerantz -tags: - - "solidity" - - "ponte" - - "camada 2" +tags: [ "Solidity", "ponte", "camada 2" ] skill: intermediate published: 2022-03-30 lang: pt-br --- -[Optimism](https://www.optimism.io/) é uma [ Optimistic Rollup](/developers/docs/scaling/optimistic-rollups/). Optimistic rollups podem processar transações por um preço muito inferior ao Ethereum Mainnet (também conhecido como layer 1 ou L1) porque as transações são processadas apenas por alguns nós, em vez de cada nó na rede. Ao mesmo tempo, os dados são todos escritos em L1, de modo que tudo pode ser provado e reconstruído com todas as garantias de integridade e disponibilidade da rede principal. +[Optimism](https://www.optimism.io/) é um [Optimistic Rollup](/developers/docs/scaling/optimistic-rollups/). +Os optimistic rollups podem processar transações por um preço muito mais baixo do que a Rede Principal da Ethereum (também conhecida como camada 1 ou L1), porque as transações são processadas apenas por alguns nós, em vez de por todos os nós na rede. +Ao mesmo tempo, todos os dados são escritos na L1, para que tudo possa ser provado e reconstruído com todas as garantias de integridade e disponibilidade da Rede Principal. -Para usar ativos L1 na Optimism (ou qualquer outra L2), os ativos precisam ser [enviados pela ponte](/bridges/#prerequisites). Uma maneira de conseguir isso é os usuários bloquearem ativos (ETH e [tokens ERC-20](/developers/docs/standards/tokens/erc-20/) são os mais comuns) na L1, e receber ativos equivalentes para usar na L2. Por fim, quem for que acabe com eles, talvez queira enviá-los de volta para a L1. Ao fazer isso, os ativos são queimados na L2 e, em seguida, liberados para o usuário na L1. +Para usar ativos da L1 no Optimism (ou em qualquer outra L2), os ativos precisam ser [transferidos por ponte](/bridges/#prerequisites). +Uma maneira de conseguir isso é os usuários bloquearem ativos (ETH e [tokens ERC-20](/developers/docs/standards/tokens/erc-20/) são os mais comuns) na L1 e receberem ativos equivalentes para usar na L2. +Eventualmente, quem quer que acabe com eles pode querer transferi-los por ponte de volta para a L1. +Ao fazer isso, os ativos são queimados na L2 e então liberados de volta para o usuário na L1. -É assim que a [ponte padrão Optimism](https://docs.optimism.io/app-developers/bridging/standard-bridge) funciona. Neste artigo, passamos pelo código-fonte para essa ponte para ver como ele funciona e estudá-lo como um exemplo de código Solidity bem escrito. +É assim que a [ponte padrão do Optimism](https://docs.optimism.io/app-developers/bridging/standard-bridge) funciona. +Neste artigo, analisamos o código-fonte dessa ponte para ver como ela funciona e estudá-la como um exemplo de código Solidity bem escrito. -## Fluxo de controle {#control-flows} +## Fluxos de controle {#control-flows} A ponte tem dois fluxos principais: -- Depósito (de L1 a L2) -- Saque de (L2 para L1) +- Depósito (da L1 para a L2) +- Retirada (da L2 para a L1) -### Fluxo de depósitos {#deposit-flow} +### Fluxo de depósito {#deposit-flow} #### Camada 1 {#deposit-flow-layer-1} -1. Se depositar um ERC-20, o depositante dá à ponte uma permissão para gastar o valor que está sendo depositado -2. O depositor chama a ponte L1(`depositERC20`, `depositERC20To`, `depositETH`, ou `depositETHTo`) -3. A ponte L1 toma posse do ativo que está na ponte - - ETH: O ativo é transferido pelo depositante como parte da chamada - - ERC-20: O ativo é transferido pela ponte para si mesmo usando a permissão fornecida pelo depositante -4. A ponte L1 usa o mecanismo de mensagem entre domínios para chamar `finalizeDeposit` na ponte L2 +1. Ao depositar um ERC-20, o depositante concede à ponte uma autorização para gastar o valor que está sendo depositado +2. O depositante chama a ponte da L1 (`depositERC20`, `depositERC20To`, `depositETH` ou `depositETHTo`) +3. A ponte da L1 toma posse do ativo transferido pela ponte + - ETH: o ativo é transferido pelo depositante como parte da chamada + - ERC-20: o ativo é transferido pela ponte para si mesma usando a autorização fornecida pelo depositante +4. A ponte da L1 usa o mecanismo de mensagens entre domínios para chamar `finalizeDeposit` na ponte da L2 #### Camada 2 {#deposit-flow-layer-2} -5. A ponte L2 verifica que a chamada do `finalizeDeposit` é legítima: - - Se veio do contrato de mensagem entre domínios - - Era originalmente da ponte em L1 -6. A ponte L2 checa se o contrato do token ERC-20 na L2 é o correto: - - O contrato L2 reporta que sua contraparte L1 é a mesma de onde vieram os tokens da L1 - - O contrato L2 reporta que suporta a interface correta ([usando ERC-165](https://eips.ethereum.org/EIPS/eip-165)). -7. Se o contrato L2 é o correto, chame-o para cunhar o número apropriado de tokens para o endereço apropriado. Se não, comece o processo de retirada para permitir o usuário reclamar os tokens no L1. +5. A ponte da L2 verifica se a chamada para `finalizeDeposit` é legítima: + - Veio do contrato de mensagens entre domínios + - Era originalmente da ponte na L1 +6. A ponte da L2 verifica se o contrato do token ERC-20 na L2 é o correto: + - O contrato da L2 informa que sua contraparte da L1 é a mesma de onde os tokens vieram na L1 + - O contrato da L2 informa que suporta a interface correta ([usando ERC-165](https://eips.ethereum.org/EIPS/eip-165)). +7. Se o contrato da L2 for o correto, chame-o para cunhar o número apropriado de tokens para o endereço apropriado. Caso contrário, inicie um processo de retirada para permitir que o usuário resgate os tokens na L1. ### Fluxo de retirada {#withdrawal-flow} -#### Camada 2 {#withdrawl-flow-layer-2} +#### Camada 2 {#withdrawal-flow-layer-2} -1. O sacador chama a ponte L2 (`withdraw` ou `withdrawTo`) -2. A ponte L2 queima o número apropriado de tokens pertencentes a `msg.sender` -3. A ponte L2 usa o mecanismo de mensagens entre domínios para chamar `finalizeETHWithdrawal` ou `finalizeERC20Withdrawal` na ponte L1 +1. O sacador chama a ponte da L2 (`withdraw` ou `withdrawTo`) +2. A ponte da L2 queima o número apropriado de tokens pertencentes a `msg.sender` +3. A ponte da L2 usa o mecanismo de mensagens entre domínios para chamar `finalizeETHWithdrawal` ou `finalizeERC20Withdrawal` na ponte da L1 -#### Camada 1 {#withdrawl-flow-layer-1} +#### Camada 1 {#withdrawal-flow-layer-1} -4. A ponte L1 verifica a chamada a `finalizeETHWithdrawal` ou `finalizeERC20Withdrawal` é legitima: - - Veio de um mecanismo de mensagens entre domínios - - Foi originada da ponte no L2 -5. A ponte L1 transfere o ativo apropriado (ETH ou ERC-20) para o endereço apropriado +4. A ponte da L1 verifica se a chamada para `finalizeETHWithdrawal` ou `finalizeERC20Withdrawal` é legítima: + - Veio do mecanismo de mensagens entre domínios + - Foi originada da ponte na L2 +5. A ponte da L1 transfere o ativo apropriado (ETH ou ERC-20) para o endereço apropriado -## Código Camada 1 {#layer-1-code} +## Código da Camada 1 {#layer-1-code} -Este é o código que roda na L1, a Rede Principal do Ethereum. +Este é o código que é executado na L1, a Rede Principal da Ethereum. ### IL1ERC20Bridge {#IL1ERC20Bridge} -[Esta interface é definida aqui](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/IL1ERC20Bridge.sol). Ela inclui funções e definições exigidas para realizar a ponte de tokens ERC-20. +[Esta interface é definida aqui](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/IL1ERC20Bridge.sol). +Ela inclui funções e definições necessárias para a transferência de tokens ERC-20 por ponte. ```solidity // SPDX-License-Identifier: MIT ``` -[Maioria do código da Optimism é lançada sob a licença MIT](https://help.optimism.io/hc/en-us/articles/4411908707995-What-software-license-does-Optimism-use-). +[A maior parte do código do Optimism é lançada sob a licença MIT](https://help.optimism.io/hc/en-us/articles/4411908707995-What-software-license-does-Optimism-use-). ```solidity pragma solidity >0.5.0 <0.9.0; ``` -Neste momento, a última versão do Solidity é 0.8.12. Até versão 0.9.0 ser lançada, nós não sabemos se este código é compatível com ele ou não. +No momento em que este artigo foi escrito, a versão mais recente do Solidity era a 0.8.12. +Até que a versão 0.9.0 seja lançada, não sabemos se este código é compatível com ela ou não. ```solidity /** @@ -86,20 +91,23 @@ Neste momento, a última versão do Solidity é 0.8.12. Até versão 0.9.0 ser l */ interface IL1ERC20Bridge { /********** - * Events * + * Eventos * **********/ event ERC20DepositInitiated( ``` -Na terminologia de ponte Optimism _deposit_ significa transferência de L2 para L2, e _withdrawal_ significa uma transferência de L2 para L1. +Na terminologia de ponte do Optimism, _deposit_ (depósito) significa transferência da L1 para a L2, e _withdrawal_ (retirada) significa uma transferência da L2 para a L1. ```solidity address indexed _l1Token, address indexed _l2Token, ``` -Na maioria dos casos o endereço de um ERC-20 na L1 não é o mesmo endereço do equivalente ERC-20 na L2. [Você pode ver a lista de endereços de tokens aqui](https://static.optimism.io/optimism.tokenlist.json). O endereço com `chainId` 1 está na L1 (Mainnet) e o endereço com `chainId` 10 está na L2 (Optimism). Os outros dois valores `chainId` são para a rede de testes Kovan (42) e a rede de testes Optimistic Kovan (69). +Na maioria dos casos, o endereço de um ERC-20 na L1 não é o mesmo que o endereço do ERC-20 equivalente na L2. +[Você pode ver a lista de endereços de token aqui](https://static.optimism.io/optimism.tokenlist.json). +O endereço com `chainId` 1 está na L1 (Rede Principal) e o endereço com `chainId` 10 está na L2 (Optimism). +Os outros dois valores de `chainId` são para a rede de teste Kovan (42) e a rede de teste Optimistic Kovan (69). ```solidity address indexed _from, @@ -109,7 +117,7 @@ Na maioria dos casos o endereço de um ERC-20 na L1 não é o mesmo endereço do ); ``` -É possível adicionar notas para transferências, caso no qual elas são adicionadas para os eventos que as reportam. +É possível adicionar anotações às transferências, e nesse caso, elas são adicionadas aos eventos que as relatam. ```solidity event ERC20WithdrawalFinalized( @@ -122,33 +130,35 @@ Na maioria dos casos o endereço de um ERC-20 na L1 não é o mesmo endereço do ); ``` -O mesmo contrato de ponte manipula transferências em ambas as direções. No caso da ponte L1, isto significa inicialização de depósitos e finalização de retiradas. +O mesmo contrato de ponte lida com transferências em ambas as direções. +No caso da ponte da L1, isso significa a inicialização de depósitos e a finalização de retiradas. ```solidity /******************** - * Public Functions * + * Funções Públicas * ********************/ /** - * @dev get the address of the corresponding L2 bridge contract. - * @return Address of the corresponding L2 bridge contract. + * @dev obtém o endereço do contrato da ponte da L2 correspondente. + * @return Endereço do contrato da ponte da L2 correspondente. */ function l2TokenBridge() external returns (address); ``` -Esta função não é realmente necessária, porque na L2 ela é um contrato pré-implantado, então ela está sempre no endereço `0x4200000000000000000000000000000000000010`. Ela está aqui por simetria com a ponte L2, porque o endereço da ponte L1 _não_ é trivial de saber. +Esta função não é realmente necessária, porque na L2 ela é um contrato pré-implantado, então está sempre no endereço `0x4200000000000000000000000000000000000010`. +Ela está aqui por simetria com a ponte da L2, porque o endereço da ponte da L1 _não_ é trivial de saber. ```solidity /** - * @dev deposit an amount of the ERC20 to the caller's balance on L2. - * @param _l1Token Address of the L1 ERC20 we are depositing - * @param _l2Token Address of the L1 respective L2 ERC20 - * @param _amount Amount of the ERC20 to deposit - * @param _l2Gas Gas limit required to complete the deposit on L2. - * @param _data Optional data to forward to L2. This data is provided - * solely as a convenience for external contracts. Aside from enforcing a maximum - * length, these contracts provide no guarantees about its content. + * @dev deposita uma quantia do ERC20 no saldo do chamador na L2. + * @param _l1Token Endereço do ERC20 da L1 que estamos depositando + * @param _l2Token Endereço do respectivo ERC20 da L2 + * @param _amount Quantia do ERC20 a ser depositada + * @param _l2Gas Limite de gás necessário para completar o depósito na L2. + * @param _data Dados opcionais para encaminhar para a L2. Estes dados são fornecidos + * apenas como uma conveniência para contratos externos. Além de impor um comprimento + * máximo, estes contratos não fornecem garantias sobre seu conteúdo. */ function depositERC20( address _l1Token, @@ -159,19 +169,21 @@ Esta função não é realmente necessária, porque na L2 ela é um contrato pr ) external; ``` -O parâmetro `_l2Gas` é a quantidade de gas L2 que a transação tem permissão de gastar. [Até um certo (alto) limite, isto é grátis](https://community.optimism.io/docs/developers/bridge/messaging/#for-l1-%E2%87%92-l2-transactions-2), portanto a menos que o contrato ERC-20 faça algo realmente estranho quando cunhando, isto não deveria ser um problema. Esta função cuida do cenário comum, onde um usuário faz a ponte dos ativos para o mesmo endereço em uma blockchain diferente. +O parâmetro `_l2Gas` é a quantidade de gás da L2 que a transação pode gastar. +[Até um certo limite (alto), isso é gratuito](https://community.optimism.io/docs/developers/bridge/messaging/#for-l1-%E2%87%92-l2-transactions-2), então, a menos que o contrato ERC-20 faça algo muito estranho durante a cunhagem, não deve ser um problema. +Esta função cuida do cenário comum, em que um usuário transfere ativos por ponte para o mesmo endereço em uma blockchain diferente. ```solidity /** - * @dev deposit an amount of ERC20 to a recipient's balance on L2. - * @param _l1Token Address of the L1 ERC20 we are depositing - * @param _l2Token Address of the L1 respective L2 ERC20 - * @param _to L2 address to credit the withdrawal to. - * @param _amount Amount of the ERC20 to deposit. - * @param _l2Gas Gas limit required to complete the deposit on L2. - * @param _data Optional data to forward to L2. This data is provided - * solely as a convenience for external contracts. Aside from enforcing a maximum - * length, these contracts provide no guarantees about its content. + * @dev deposita uma quantia de ERC20 no saldo de um destinatário na L2. + * @param _l1Token Endereço do ERC20 da L1 que estamos depositando + * @param _l2Token Endereço do respectivo ERC20 da L2 + * @param _to endereço da L2 para creditar a retirada. + * @param _amount Quantia do ERC20 a ser depositada. + * @param _l2Gas Limite de gás necessário para completar o depósito na L2. + * @param _data Dados opcionais para encaminhar para a L2. Estes dados são fornecidos + * apenas como uma conveniência para contratos externos. Além de impor um comprimento + * máximo, estes contratos não fornecem garantias sobre seu conteúdo. */ function depositERC20To( address _l1Token, @@ -183,26 +195,26 @@ O parâmetro `_l2Gas` é a quantidade de gas L2 que a transação tem permissão ) external; ``` -Esta função é quase idêntica a `depositERC20`, mas ela deixa você enviar o ERC-20 para diferentes endereços. +Esta função é quase idêntica a `depositERC20`, mas permite que você envie o ERC-20 para um endereço diferente. ```solidity /************************* - * Cross-chain Functions * + * Funções entre cadeias * *************************/ /** - * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the - * L1 ERC20 token. - * This call will fail if the initialized withdrawal from L2 has not been finalized. + * @dev Completa uma retirada da L2 para a L1 e credita fundos no saldo do destinatário do + * token ERC20 da L1. + * Esta chamada falhará se a retirada iniciada da L2 não tiver sido finalizada. * - * @param _l1Token Address of L1 token to finalizeWithdrawal for. - * @param _l2Token Address of L2 token where withdrawal was initiated. - * @param _from L2 address initiating the transfer. - * @param _to L1 address to credit the withdrawal to. - * @param _amount Amount of the ERC20 to deposit. - * @param _data Data provided by the sender on L2. This data is provided - * solely as a convenience for external contracts. Aside from enforcing a maximum - * length, these contracts provide no guarantees about its content. + * @param _l1Token Endereço do token da L1 para o qual finalizeWithdrawal será executado. + * @param _l2Token Endereço do token da L2 onde a retirada foi iniciada. + * @param _from Endereço da L2 que iniciou a transferência. + * @param _to Endereço da L1 para creditar a retirada. + * @param _amount Quantia do ERC20 a ser depositada. + * @param _data Dados fornecidos pelo remetente na L2. Estes dados são fornecidos + * apenas como uma conveniência para contratos externos. Além de impor um comprimento + * máximo, estes contratos não fornecem garantias sobre seu conteúdo. */ function finalizeERC20Withdrawal( address _l1Token, @@ -215,16 +227,20 @@ Esta função é quase idêntica a `depositERC20`, mas ela deixa você enviar o } ``` -Saques (e outras mensagens de L2 para L1) na Optimism é um processo em duas etapas: +As retiradas (e outras mensagens da L2 para a L1) no Optimism são um processo de duas etapas: -1. Uma transação inicial no L2. -2. Uma transação de finalização ou de reclamação na L1. Esta transação precisa acontecer depois do [período de desafio de falha](https://community.optimism.io/docs/how-optimism-works/#fault-proofs) para a transação L2 terminar. +1. Uma transação de iniciação na L2. +2. Uma transação de finalização ou de resgate na L1. + Essa transação precisa acontecer após o término do [período de contestação de falhas](https://community.optimism.io/docs/how-optimism-works/#fault-proofs) para a transação da L2. ### IL1StandardBridge {#il1standardbridge} -[Esta interface é definida aqui](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/IL1StandardBridge.sol). Este arquivo contém definições de evento e função para ETH. Estas definições são muito similares com aquelas definidas em `IL1ERC20Bridge` acima para ERC-20. +[Esta interface é definida aqui](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/IL1StandardBridge.sol). +Este arquivo contém definições de evento e função para ETH. +Essas definições são muito semelhantes às definidas em `IL1ERC20Bridge` acima para ERC-20. -A ponte interface é dividida entre dois arquivos, porque alguns tokens ERC-20 requerem processamento customizado e não podem ser manipulados pela ponte padrão. Dessa maneira a ponte customizada que manipula este token pode implementar `IL1ERC20Bridge` e não ter que também fazer a ponte ETH. +A interface da ponte é dividida em dois arquivos porque alguns tokens ERC-20 exigem processamento personalizado e não podem ser tratados pela ponte padrão. +Dessa forma, a ponte personalizada que lida com esse token pode implementar `IL1ERC20Bridge` e não precisar também transferir ETH por ponte. ```solidity // SPDX-License-Identifier: MIT @@ -237,7 +253,7 @@ import "./IL1ERC20Bridge.sol"; */ interface IL1StandardBridge is IL1ERC20Bridge { /********** - * Events * + * Eventos * **********/ event ETHDepositInitiated( address indexed _from, @@ -247,7 +263,8 @@ interface IL1StandardBridge is IL1ERC20Bridge { ); ``` -Este evento é praticamente idêntico à versão ERC-20 (`ERC20DepositInitiated`), exceto por não ter os endereços de token L1 e L2. O mesmo é verdade para outros eventos e funções. +Este evento é quase idêntico à versão ERC-20 (`ERC20DepositInitiated`), exceto que não tem os endereços de token da L1 e da L2. +O mesmo se aplica aos outros eventos e funções. ```solidity event ETHWithdrawalFinalized( @@ -257,11 +274,11 @@ Este evento é praticamente idêntico à versão ERC-20 (`ERC20DepositInitiated` ); /******************** - * Public Functions * + * Funções Públicas * ********************/ /** - * @dev Deposit an amount of the ETH to the caller's balance on L2. + * @dev Deposita uma quantia de ETH no saldo do chamador na L2. . . . @@ -269,7 +286,7 @@ Este evento é praticamente idêntico à versão ERC-20 (`ERC20DepositInitiated` function depositETH(uint32 _l2Gas, bytes calldata _data) external payable; /** - * @dev Deposit an amount of ETH to a recipient's balance on L2. + * @dev Deposita uma quantia de ETH no saldo de um destinatário na L2. . . . @@ -281,13 +298,13 @@ Este evento é praticamente idêntico à versão ERC-20 (`ERC20DepositInitiated` ) external payable; /************************* - * Cross-chain Functions * + * Funções entre cadeias * *************************/ /** - * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the - * L1 ETH token. Since only the xDomainMessenger can call this function, it will never be called - * before the withdrawal is finalized. + * @dev Completa uma retirada da L2 para a L1 e credita os fundos no saldo do destinatário do + * token ETH da L1. Como apenas o xDomainMessenger pode chamar esta função, ela nunca será chamada + * antes da finalização da retirada. . . . @@ -303,83 +320,87 @@ Este evento é praticamente idêntico à versão ERC-20 (`ERC20DepositInitiated` ### CrossDomainEnabled {#crossdomainenabled} -[Este contrato](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/bridge/CrossDomainEnabled.sol) é herdado por ambas pontes ([L1](#the-l1-bridge-contract) e [L2](#the-l2-bridge-contract)) para enviar mensagens para a outra camada. +[Este contrato](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/bridge/CrossDomainEnabled.sol) é herdado por ambas as pontes ([L1](#the-l1-bridge-contract) e [L2](#the-l2-bridge-contract)) para enviar mensagens para a outra camada. ```solidity // SPDX-License-Identifier: MIT pragma solidity >0.5.0 <0.9.0; -/* Interface Imports */ +/* Importações de Interface */ import { ICrossDomainMessenger } from "./ICrossDomainMessenger.sol"; ``` -[Esta interface](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/bridge/ICrossDomainMessenger.sol) mostra ao contrato como enviar mensagens para a outra camada, usando o mensageiro entre domínios. Este mensageiro entre domínios é todo um outro sistema, e merece um artigo próprio, que espero escrever no futuro. +[Esta interface](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/bridge/ICrossDomainMessenger.sol) informa ao contrato como enviar mensagens para a outra camada, usando o mensageiro entre domínios. +Este mensageiro entre domínios é um sistema completamente diferente, e merece seu próprio artigo, que espero escrever no futuro. ```solidity /** * @title CrossDomainEnabled - * @dev Helper contract for contracts performing cross-domain communications + * @dev Contrato auxiliar para contratos que realizam comunicações entre domínios * - * Compiler used: defined by inheriting contract + * Compilador usado: definido pelo contrato herdado */ contract CrossDomainEnabled { /************* - * Variables * + * Variáveis * *************/ - // Messenger contract used to send and receive messages from the other domain. + // Contrato de mensageiro usado para enviar e receber mensagens do outro domínio. address public messenger; /*************** - * Constructor * + * Construtor * ***************/ /** - * @param _messenger Address of the CrossDomainMessenger on the current layer. + * @param _messenger Endereço do CrossDomainMessenger na camada atual. */ constructor(address _messenger) { messenger = _messenger; } ``` -O único parâmetro que o contrato precisa saber é o endereço do mensageiro entre domínios nessa camada. Este parâmetro é configurado uma vez, no construtor, e nunca muda. +O único parâmetro que o contrato precisa saber é o endereço do mensageiro entre domínios nessa camada. +Este parâmetro é definido uma vez, no construtor, e nunca muda. ```solidity /********************** - * Function Modifiers * + * Modificadores de Função * **********************/ /** - * Enforces that the modified function is only callable by a specific cross-domain account. - * @param _sourceDomainAccount The only account on the originating domain which is - * authenticated to call this function. + * Garante que a função modificada só pode ser chamada por uma conta específica de outro domínio. + * @param _sourceDomainAccount A única conta no domínio de origem que está + * autenticada para chamar esta função. */ modifier onlyFromCrossDomainAccount(address _sourceDomainAccount) { ``` -O mensageiro entre domínios é acessível por qualquer contrato na blockchain onde estiver rodando (seja Ethereum mainnet ou Optimism). Mas nós precisamos da ponte em cada lado para _apenas_ confiar em certas mensagens se eles vierem da ponte do outro lado. +O sistema de mensagens entre domínios é acessível por qualquer contrato na blockchain em que está sendo executado (seja a Rede Principal da Ethereum ou o Optimism). +Mas precisamos que a ponte de cada lado confie _apenas_ em certas mensagens se elas vierem da ponte do outro lado. ```solidity require( msg.sender == address(getCrossDomainMessenger()), - "OVM_XCHAIN: messenger contract unauthenticated" + "OVM_XCHAIN: contrato de mensageiro não autenticado" ); ``` -Somente mensagens do mensageiro entre domínios apropriado (`messenger`, como você vê abaixo) pode ser confiado. +Apenas mensagens do mensageiro entre domínios apropriado (`messenger`, como você verá abaixo) são confiáveis. ```solidity require( getCrossDomainMessenger().xDomainMessageSender() == _sourceDomainAccount, - "OVM_XCHAIN: wrong sender of cross-domain message" + "OVM_XCHAIN: remetente incorreto da mensagem entre domínios" ); ``` -A maneira que o mensageiro entre domínios fornece o endereço que enviou uma mensagem com a outra camada é [a função `.xDomainMessageSender()`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol#L122-L128). Enquanto ele for chamado na transação que foi iniciada pela mensagem, ele pode fornecer esta informação. +A forma como o mensageiro entre domínios fornece o endereço que enviou uma mensagem para a outra camada é através da [função `.xDomainMessageSender()`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol#L122-L128). +Desde que seja chamada na transação que foi iniciada pela mensagem, ela pode fornecer esta informação. -Nós precisamos nos certificar que a mensagem que nós recebemos veio da outra ponte. +Precisamos ter certeza de que a mensagem que recebemos veio da outra ponte. ```solidity @@ -387,29 +408,30 @@ Nós precisamos nos certificar que a mensagem que nós recebemos veio da outra p } /********************** - * Internal Functions * + * Funções Internas * **********************/ /** - * Gets the messenger, usually from storage. This function is exposed in case a child contract - * needs to override. - * @return The address of the cross-domain messenger contract which should be used. + * Obtém o mensageiro, geralmente do armazenamento. Esta função é exposta caso um contrato filho + * precise substituí-la. + * @return O endereço do contrato do mensageiro entre domínios que deve ser usado. */ function getCrossDomainMessenger() internal virtual returns (ICrossDomainMessenger) { return ICrossDomainMessenger(messenger); } ``` -Esta função retorna o mensageiro entre domínios. Nós usamos uma função ao invés da variável `messenger` para permitir contratos que herdam deste para usar um algoritmo para especificar qual mensageiro entre domínios usar. +Esta função retorna o mensageiro entre domínios. +Usamos uma função em vez da variável `messenger` para permitir que contratos que herdam deste usem um algoritmo para especificar qual mensageiro entre domínios usar. ```solidity /** - * Sends a message to an account on another domain - * @param _crossDomainTarget The intended recipient on the destination domain - * @param _message The data to send to the target (usually calldata to a function with + * Envia uma mensagem para uma conta em outro domínio + * @param _crossDomainTarget O destinatário pretendido no domínio de destino + * @param _message Os dados a serem enviados para o destino (geralmente calldata para uma função com * `onlyFromCrossDomainAccount()`) - * @param _gasLimit The gasLimit for the receipt of the message on the target domain. + * @param _gasLimit O gasLimit para o recebimento da mensagem no domínio de destino. */ function sendCrossDomainMessage( address _crossDomainTarget, @@ -417,17 +439,18 @@ Esta função retorna o mensageiro entre domínios. Nós usamos uma função ao bytes memory _message ``` -Finalmente, a função que envia a mensagem para a outra camada. +Finalmente, a função que envia uma mensagem para a outra camada. ```solidity ) internal { // slither-disable-next-line reentrancy-events, reentrancy-benign ``` -[Slither](https://github.com/crytic/slither)é um analisador estático que a Optimism roda em cada contrato para procurar por vulnerabilidades e outros problemas em potencial. Nesse caso, as seguintes linhas disparam duas vulnerabilidades: +[Slither](https://github.com/crytic/slither) é um analisador estático que o Optimism executa em cada contrato para procurar por vulnerabilidades e outros problemas em potencial. +Nesse caso, a linha seguinte aciona duas vulnerabilidades: 1. [Eventos de reentrância](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3) -2. [Reentrância Benigna](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2) +2. [Reentrância benigna](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2) ```solidity getCrossDomainMessenger().sendMessage(_crossDomainTarget, _message, _gasLimit); @@ -435,9 +458,9 @@ Finalmente, a função que envia a mensagem para a outra camada. } ``` -Neste caso nós não estamos preocupados sobre reentrância. Nós sabemos que `getCrossDomainMessenger()` returna um endereço confiável, mesmo se Slither não tem como saber isso. +Neste caso, não estamos preocupados com a reentrância, pois sabemos que `getCrossDomainMessenger()` retorna um endereço confiável, mesmo que o Slither não tenha como saber disso. -### O contrato da ponte L1 {#the-l1-bridge-contract} +### O contrato da ponte da L1 {#the-l1-bridge-contract} [O código-fonte para este contrato está aqui](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/L1StandardBridge.sol). @@ -446,10 +469,11 @@ Neste caso nós não estamos preocupados sobre reentrância. Nós sabemos que `g pragma solidity ^0.8.9; ``` -A interface pode ser parte de outros contratos, então eles têm de suportar uma larga faixa de versões de Solidity. Mas a ponte por ela mesma é o nosso contrato, e nós podemos ser estritos sobre qual versão Solidity ela usa. +As interfaces podem fazer parte de outros contratos, por isso precisam suportar uma ampla gama de versões do Solidity. +Mas a ponte em si é nosso contrato, e podemos ser rigorosos sobre qual versão do Solidity ela usa. ```solidity -/* Interface Imports */ +/* Importações de Interface */ import { IL1StandardBridge } from "./IL1StandardBridge.sol"; import { IL1ERC20Bridge } from "./IL1ERC20Bridge.sol"; ``` @@ -460,118 +484,134 @@ import { IL1ERC20Bridge } from "./IL1ERC20Bridge.sol"; import { IL2ERC20Bridge } from "../../L2/messaging/IL2ERC20Bridge.sol"; ``` -[Esta interface](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol) nos deixa criar mensagens para controlar a ponte padrão em L2. +[Esta interface](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol) nos permite criar mensagens para controlar a ponte padrão na L2. ```solidity import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; ``` -[Esta interface](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol) nos deixa controlar contratos ERC-20. [Você pode ler mais sobre ela aqui](/developers/tutorials/erc20-annotated-code/#the-interface). +[Esta interface](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol) nos permite controlar contratos ERC-20. +[Você pode ler mais sobre isso aqui](/developers/tutorials/erc20-annotated-code/#the-interface). ```solidity -/* Library Imports */ +/* Importações de Biblioteca */ import { CrossDomainEnabled } from "../../libraries/bridge/CrossDomainEnabled.sol"; ``` -[Como explicado acima](#crossdomainenabled), este contrato é usado para mensageria entre camadas. +[Como explicado acima](#crossdomainenabled), este contrato é usado para mensagens entre camadas. ```solidity import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol"; ``` -[`Lib_PredeployAddresses`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/constants/Lib_PredeployAddresses.sol) tem os endereços dos contratos L2 que sempre tem o mesmo endereço. Isto inclui a ponte padrão em L2. +`Lib_PredeployAddresses` (https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/constants/Lib_PredeployAddresses.sol) tem os endereços para os contratos da L2 que sempre têm o mesmo endereço. Isso inclui a ponte padrão na L2. ```solidity import { Address } from "@openzeppelin/contracts/utils/Address.sol"; ``` -[Utilitários de endereços OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol). Ele é usado para distinguir entre endereços de contrato e aqueles pertencentes a contas de propriedade externa (EOA). +[Utilitários de Endereço do OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol). É usado para distinguir entre endereços de contrato e aqueles pertencentes a contas de propriedade externa (EOA). -Note que isto não é a solução perfeita, porque não há como distinguir entre chamadas diretas e chamadas feitas de um construtor de contrato, mas pelo menos isto nos deixa identificar e evitar alguns erros comuns de usuário. +Note que esta não é uma solução perfeita, porque não há como distinguir entre chamadas diretas e chamadas feitas a partir do construtor de um contrato, mas pelo menos isso nos permite identificar e prevenir alguns erros comuns de usuários. ```solidity import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; ``` -[O padrão ERC-20 ](https://eips.ethereum.org/EIPS/eip-20) suporta duas maneiras para um contrato reportar falha: +[O padrão ERC-20](https://eips.ethereum.org/EIPS/eip-20) suporta duas maneiras para um contrato relatar falhas: -1. Revert -2. Return `false` +1. Reverter +2. Retornar `false` -Gerenciar ambos casos faria nosso código mais complicado, então ao invés disso, usamos [OpenZeppelin `SafeERC20`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol), que garante [ que todas as falhas resultem num revert](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol#L96). +Lidar com ambos os casos tornaria nosso código mais complicado, então, em vez disso, usamos o [`SafeERC20` do OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol), que garante que [todas as falhas resultem em uma reversão](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol#L96). ```solidity /** * @title L1StandardBridge - * @dev The L1 ETH and ERC20 Bridge is a contract which stores deposited L1 funds and standard - * tokens that are in use on L2. It synchronizes a corresponding L2 Bridge, informing it of deposits - * and listening to it for newly finalized withdrawals. + * @dev A Ponte de ETH e ERC20 da L1 é um contrato que armazena fundos depositados da L1 e tokens padrão + * que estão em uso na L2. Ela sincroniza uma Ponte da L2 correspondente, informando-a sobre depósitos + * e escutando-a para novas retiradas finalizadas. * */ contract L1StandardBridge is IL1StandardBridge, CrossDomainEnabled { using SafeERC20 for IERC20; ``` -Esta linha é como especificamos para usar o wrapper `SafeERC20` cada vez que nós usamos a interface `IERC20`. +Esta linha é como especificamos o uso do wrapper `SafeERC20` toda vez que usamos a interface `IERC20`. ```solidity /******************************** - * External Contract References * + * Referências de Contratos Externos * ********************************/ address public l2TokenBridge; ``` -O endereço de [L2StandardBridge](#the-l2-bridge-contract). +O endereço do [L2StandardBridge](#the-l2-bridge-contract). ```solidity - // Maps L1 token to L2 token to balance of the L1 token deposited + // Mapeia o token da L1 para o token da L2 para o saldo do token da L1 depositado mapping(address => mapping(address => uint256)) public deposits; ``` -Um [mapeamento](https://www.tutorialspoint.com/solidity/solidity_mappings.htm) em dobro como este é a maneira de você definir uma [array esparsa bi-dimensional](https://en.wikipedia.org/wiki/Sparse_matrix). Valores nesta estrutura de dados são identificados como `deposit[L1 token addr][L2 token addr]`. O valor padrão é zero. Somente células que são configuradas para um valor diferente são escritas no storage. +Um [mapeamento](https://www.tutorialspoint.com/solidity/solidity_mappings.htm) duplo como este é a maneira de definir uma [matriz esparsa bidimensional](https://en.wikipedia.org/wiki/Sparse_matrix). +Os valores nesta estrutura de dados são identificados como `deposit[L1 token addr][L2 token addr]`. +O valor padrão é zero. +Apenas as células que são definidas com um valor diferente são escritas no armazenamento. ```solidity /*************** - * Constructor * + * Construtor * ***************/ - // This contract lives behind a proxy, so the constructor parameters will go unused. + // Este contrato vive por trás de um proxy, então os parâmetros do construtor não serão utilizados. constructor() CrossDomainEnabled(address(0)) {} ``` -Para querer ser capaz de atualizar este contrato sem ter que copiar todas as variáveis no storage. Para fazer isso, nós usamos um [`Proxy`](https://docs.openzeppelin.com/contracts/3.x/api/proxy), um contrato que usa [`delegatecall`](https://solidity-by-example.org/delegatecall/) para transferir chamadas para um contato separado cujo endereço é armazenado pelo contrato proxy (quando você atualiza, você diz ao proxy para mudar o endereço). Quando você usa `delegatecall` o storage permanece com o valor do contrato _chamador_, então os valores de todas as variáveis de estado do contrato não são afetadas. +Para poder atualizar este contrato sem ter que copiar todas as variáveis no armazenamento. +Para fazer isso, usamos um [`Proxy`](https://docs.openzeppelin.com/contracts/3.x/api/proxy), um contrato que usa [`delegatecall`](https://solidity-by-example.org/delegatecall/) para transferir chamadas para um contrato separado cujo endereço é armazenado pelo contrato proxy (quando você atualiza, você diz ao proxy para mudar esse endereço). +Quando você usa `delegatecall`, o armazenamento permanece o armazenamento do contrato _chamador_, então os valores de todas as variáveis de estado do contrato não são afetados. -Um efeito deste padrão é que o storage do contrato que é _chamado_ pelo `delegatecall` não é usado, e portanto os valores do construtor passados para ele não importam. Esta é a razão pela qual nós podemos fornecer um valor sem sentido para o construtor `CrossDomainEnabled`. É também a razão que a inicialização abaixo é separada do construtor. +Um efeito deste padrão é que o armazenamento do contrato que é o _chamado_ de `delegatecall` não é usado e, portanto, os valores do construtor passados para ele não importam. +Esta é a razão pela qual podemos fornecer um valor sem sentido para o construtor `CrossDomainEnabled`. +É também a razão pela qual a inicialização abaixo é separada do construtor. ```solidity /****************** - * Initialization * + * Inicialização * ******************/ /** - * @param _l1messenger L1 Messenger address being used for cross-chain communications. - * @param _l2TokenBridge L2 standard bridge address. + * @param _l1messenger Endereço do Mensageiro da L1 sendo usado para comunicações entre cadeias. + * @param _l2TokenBridge Endereço da ponte padrão da L2. */ // slither-disable-next-line external-function ``` -Este [teste Slither](https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-external) identifica funções que não são chamadas do código do contrato e poderiam portanto serem declaradas `external` ao invés de `public`. As funções de custo de gas `external` podem ser menores, porque elas podem ser fornecidas com parâmetros no calldata. Funções declaradas `public` têm de ser acessíveis de dentro do contrato. Contratos não podem modificar seus próprios calldata, então os parâmetros têm que estar na memória. Quando esta função é chamada externamente, é necessário copiar o calldata para a memória, que custa gas. Nesse caso a função é chamada somente uma vez, então a ineficiência não importa para nós. +Este [teste do Slither](https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-external) identifica funções que não são chamadas do código do contrato e que, portanto, poderiam ser declaradas `external` em vez de `public`. +O custo de gás de funções `external` pode ser menor, porque elas podem receber parâmetros no calldata. +Funções declaradas como `public` precisam ser acessíveis de dentro do contrato. +Contratos não podem modificar seu próprio calldata, então os parâmetros precisam estar na memória. +Quando tal função é chamada externamente, é necessário copiar o calldata para a memória, o que custa gás. +Neste caso, a função é chamada apenas uma vez, então a ineficiência não importa para nós. ```solidity function initialize(address _l1messenger, address _l2TokenBridge) public { - require(messenger == address(0), "Contract has already been initialized."); + require(messenger == address(0), "O contrato já foi inicializado."); ``` -A função `initialize` deve ser chamada só uma vez. Se o endereço do mensageiro entre domínios L1 ou se a ponte do token L2 mudam, nós criamos um novo proxy e uma nova ponte que chama ele. Isto é improvável de acontecer, exceto quando o sistema inteiro é atualizado, uma ocorrência muito rara. +A função `initialize` deve ser chamada apenas uma vez. +Se o endereço do mensageiro entre domínios da L1 ou da ponte de token da L2 mudar, criamos um novo proxy e uma nova ponte que o chama. +Isso é improvável de acontecer, exceto quando todo o sistema é atualizado, uma ocorrência muito rara. -Note que esta função não tem nenhum mecanismo que restringe _quem_ pode chamá-la. Isto significa que em teoria um atacante poderia esperar até que nós implantassemos o proxy e a primeira versão da ponte e então [front-run](https://solidity-by-example.org/hacks/front-running/)para pegar a função `initialize` antes que o usuário legítimo o faça. Mas há dois métodos para evitar isso: +Note que esta função não tem nenhum mecanismo que restringe _quem_ pode chamá-la. +Isso significa que, em teoria, um invasor poderia esperar até que implantemos o proxy e a primeira versão da ponte e, em seguida, usar [front-run](https://solidity-by-example.org/hacks/front-running/) para chegar à função `initialize` antes que o usuário legítimo o faça. Mas há dois métodos para evitar isso: -1. Se o contrato for implantado não diretamente por um EOA mas [em uma transação que tem outro contrato criando eles,](https://medium.com/upstate-interactive/creating-a-contract-with-a-smart-contract-bdb67c5c8595) o processo inteiro pode ser atômico, e finalizar antes que qualquer outra transação seja executada. -2. Se a chamada legítima para `initialize` falhar, é sempre possível ignorar o proxy recém-criado e fazer a ponte para criar outros novos. +1. Se os contratos forem implantados não diretamente por uma EOA, mas [em uma transação que tem outro contrato para criá-los](https://medium.com/upstate-interactive/creating-a-contract-with-a-smart-contract-bdb67c5c8595), todo o processo pode ser atômico e terminar antes que qualquer outra transação seja executada. +2. Se a chamada legítima para `initialize` falhar, é sempre possível ignorar o proxy e a ponte recém-criados e criar novos. ```solidity messenger = _l1messenger; @@ -579,20 +619,20 @@ Note que esta função não tem nenhum mecanismo que restringe _quem_ pode cham } ``` -Estes são dois parâmetros que a ponte precisa conhecer. +Estes são os dois parâmetros que a ponte precisa conhecer. ```solidity /************** - * Depositing * + * Depósito * **************/ - /** @dev Modifier requiring sender to be EOA. This check could be bypassed by a malicious - * contract via initcode, but it takes care of the user error we want to avoid. + /** @dev Modificador que exige que o remetente seja uma EOA. Esta verificação poderia ser contornada por um + * contrato malicioso via initcode, mas cuida do erro de usuário que queremos evitar. */ modifier onlyEOA() { - // Used to stop deposits from contracts (avoid accidentally lost tokens) - require(!Address.isContract(msg.sender), "Account not EOA"); + // Usado para impedir depósitos de contratos (evita a perda acidental de tokens) + require(!Address.isContract(msg.sender), "Conta não é EOA"); _; } ``` @@ -601,17 +641,18 @@ Estes são dois parâmetros que a ponte precisa conhecer. ```solidity /** - * @dev This function can be called with no data - * to deposit an amount of ETH to the caller's balance on L2. - * Since the receive function doesn't take data, a conservative - * default amount is forwarded to L2. + * @dev Esta função pode ser chamada sem dados + * para depositar uma quantia de ETH no saldo do chamador na L2. + * Como a função receive não aceita dados, uma quantia + * padrão conservadora é encaminhada para a L2. */ receive() external payable onlyEOA { _initiateETHDeposit(msg.sender, msg.sender, 200_000, bytes("")); } ``` -A função existe para finalidade de testes. Note que ela não aparece nas definições de interface - não é para uso corrente. +A função existe para finalidade de testes. +Note que ela não aparece nas definições de interface - não é para uso corrente. ```solidity /** @@ -633,18 +674,18 @@ A função existe para finalidade de testes. Note que ela não aparece nas defin } ``` -Estas duas funções são wrappers em volta do `_initiateETHDeposit`, a função que manipula o depósito do ETH real. +Estas duas funções são wrappers em volta do `_initiateETHDeposit`, a função que lida com o depósito real de ETH. ```solidity /** - * @dev Performs the logic for deposits by storing the ETH and informing the L2 ETH Gateway of - * the deposit. - * @param _from Account to pull the deposit from on L1. - * @param _to Account to give the deposit to on L2. - * @param _l2Gas Gas limit required to complete the deposit on L2. - * @param _data Optional data to forward to L2. This data is provided - * solely as a convenience for external contracts. Aside from enforcing a maximum - * length, these contracts provide no guarantees about its content. + * @dev Executa a lógica para depósitos armazenando o ETH e informando o Gateway de ETH da L2 sobre + * o depósito. + * @param _from Conta da qual o depósito será retirado na L1. + * @param _to Conta para a qual o depósito será creditado na L2. + * @param _l2Gas Limite de gás necessário para completar o depósito na L2. + * @param _data Dados opcionais para encaminhar para a L2. Estes dados são fornecidos + * apenas como uma conveniência para contratos externos. Além de impor um comprimento + * máximo, estes contratos não fornecem garantias sobre seu conteúdo. */ function _initiateETHDeposit( address _from, @@ -652,11 +693,14 @@ Estas duas funções são wrappers em volta do `_initiateETHDeposit`, a função uint32 _l2Gas, bytes memory _data ) internal { - // Construct calldata for finalizeDeposit call + // Constrói o calldata para a chamada finalizeDeposit bytes memory message = abi.encodeWithSelector( ``` -A maneira que mensagens entre domínios trabalham é que o contrato de destino é chamado com a mensagem como o seu calldata. Contratos Solidity sempre interpretam seu calldata de acordo com [a especificação ABI](https://docs.soliditylang.org/en/v0.8.12/abi-spec.html). A função Solidity [`abi.encodeWithSelector`](https://docs.soliditylang.org/en/v0.8.12/units-and-global-variables.html#abi-encoding-and-decoding-functions) cria este calldata. +A maneira como as mensagens entre domínios funcionam é que o contrato de destino é chamado com a mensagem como seu calldata. +Os contratos Solidity sempre interpretam seu calldata de acordo com +[as especificações da ABI](https://docs.soliditylang.org/en/v0.8.12/abi-spec.html). +A função do Solidity [`abi.encodeWithSelector`](https://docs.soliditylang.org/en/v0.8.12/units-and-global-variables.html#abi-encoding-and-decoding-functions) cria esse calldata. ```solidity IL2ERC20Bridge.finalizeDeposit.selector, @@ -669,24 +713,24 @@ A maneira que mensagens entre domínios trabalham é que o contrato de destino ); ``` -A mensagem aqui é chamar [a função `finalizeDeposit`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/L2StandardBridge.sol#L141-L148) com estes parâmetros: +A mensagem aqui é para chamar [a função `finalizeDeposit`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/L2StandardBridge.sol#L141-L148) com estes parâmetros: -| Parâmetro | Valores | Significado | -| ----------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| \_l1Token | address(0) | Valor especial para o ETH (que não é um token ERC-20) na L1 | -| \_l2Token | Lib_PredeployAddresses.OVM_ETH | O contrato L2 que gerencia ETH na Optimism, `0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000` (este contrato é apenas para uso interno da Optimism) | -| \_from | \_from | Os endereços na L1 que enviam o ETH | -| \_to | \_to | O endereço na L2 que recebe o ETH | -| amount | msg.value | Quantidade de wei enviado (que já foi enviado para a ponte) | -| \_data | \_data | Dados adicionais para anexar ao depósito | +| Parâmetro | Valor | Significado | +| ------------------------------- | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| \_l1Token | address(0) | Valor especial para representar ETH (que não é um token ERC-20) na L1 | +| \_l2Token | Lib_PredeployAddresses.OVM_ETH | O contrato da L2 que gerencia ETH no Optimism, `0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000` (este contrato é para uso interno do Optimism apenas) | +| \_from | \_from | O endereço na L1 que envia o ETH | +| \_to | \_to | O endereço na L2 que recebe o ETH | +| quantidade | msg.value | Quantidade de wei enviado (que já foi enviado para a ponte) | +| \_data | \_data | Dados adicionais para anexar ao depósito | ```solidity - // Send calldata into L2 + // Envia o calldata para a L2 // slither-disable-next-line reentrancy-events sendCrossDomainMessage(l2TokenBridge, _l2Gas, message); ``` -Enviar a mensagem através de mensageiro entre domínios. +Envia a mensagem através do mensageiro entre domínios. ```solidity // slither-disable-next-line reentrancy-events @@ -694,16 +738,16 @@ Enviar a mensagem através de mensageiro entre domínios. } ``` -Emitir um evento para informar qualquer aplicação descentralizada que escuta esta transferência. +Emite um evento para informar qualquer aplicativo descentralizado que escuta esta transferência. ```solidity /** * @inheritdoc IL1ERC20Bridge */ function depositERC20( - . - . - . + . + . + . ) external virtual onlyEOA { _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, msg.sender, _amount, _l2Gas, _data); } @@ -712,9 +756,9 @@ Emitir um evento para informar qualquer aplicação descentralizada que escuta e * @inheritdoc IL1ERC20Bridge */ function depositERC20To( - . - . - . + . + . + . ) external virtual { _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, _to, _amount, _l2Gas, _data); } @@ -724,18 +768,18 @@ Estas duas funções são wrappers em volta do `_initiateERC20Deposit`, a funç ```solidity /** - * @dev Performs the logic for deposits by informing the L2 Deposited Token - * contract of the deposit and calling a handler to lock the L1 funds. (e.g., transferFrom) + * @dev Executa a lógica para depósitos, informando o contrato do Token Depositado da L2 + * sobre o depósito e chamando um manipulador para bloquear os fundos da L1. (ex: transferFrom) * - * @param _l1Token Address of the L1 ERC20 we are depositing - * @param _l2Token Address of the L1 respective L2 ERC20 - * @param _from Account to pull the deposit from on L1 - * @param _to Account to give the deposit to on L2 - * @param _amount Amount of the ERC20 to deposit. - * @param _l2Gas Gas limit required to complete the deposit on L2. - * @param _data Optional data to forward to L2. This data is provided - * solely as a convenience for external contracts. Aside from enforcing a maximum - * length, these contracts provide no guarantees about its content. + * @param _l1Token Endereço do ERC20 da L1 que estamos depositando + * @param _l2Token Endereço do respectivo ERC20 da L2 + * @param _from Conta da qual o depósito será retirado na L1 + * @param _to Conta para a qual o depósito será creditado na L2 + * @param _amount Quantia do ERC20 a ser depositada. + * @param _l2Gas Limite de gás necessário para completar o depósito na L2. + * @param _data Dados opcionais para encaminhar para a L2. Estes dados são fornecidos + * apenas como uma conveniência para contratos externos. Além de impor um comprimento + * máximo, estes contratos não fornecem garantias sobre seu conteúdo. */ function _initiateERC20Deposit( address _l1Token, @@ -748,26 +792,29 @@ Estas duas funções são wrappers em volta do `_initiateERC20Deposit`, a funç ) internal { ``` -Esta função é similiar a `_initiateETHDeposit` acima, com algumas poucas diferenças importantes. A primeira diferença é que esta função recebe o endereço de token e a quantia a transferir como parâmetros. No caso do ETH, a chamada para a ponte já inclui a transferência do ativo para a conta da ponte (`msg.value`). +Esta função é semelhante a `_initiateETHDeposit` acima, com algumas diferenças importantes. +A primeira diferença é que esta função recebe os endereços de token e a quantia a ser transferida como parâmetros. +No caso do ETH, a chamada para a ponte já inclui a transferência do ativo para a conta da ponte (`msg.value`). ```solidity - // When a deposit is initiated on L1, the L1 Bridge transfers the funds to itself for future - // withdrawals. safeTransferFrom also checks if the contract has code, so this will fail if - // _from is an EOA or address(0). + // Quando um depósito é iniciado na L1, a Ponte da L1 transfere os fundos para si mesma para futuras + // retiradas. safeTransferFrom também verifica se o contrato tem código, então isso falhará se + // _from for uma EOA ou address(0). // slither-disable-next-line reentrancy-events, reentrancy-benign IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount); ``` -Transferências de tokens ERC-20 seguem um processo diferente do ETH: +As transferências de token ERC-20 seguem um processo diferente do ETH: -1. O usuário (`_from`) dá uma permissão para a ponte para transferir os tokens apropriados. +1. O usuário (`_from`) concede uma autorização à ponte para transferir os tokens apropriados. 2. O usuário chama a ponte com o endereço do contrato do token, a quantia, etc. -3. A ponte transfere os tokens (para ela mesmo) como parte do processo de depósito. +3. A ponte transfere os tokens (para si mesma) como parte do processo de depósito. -O primeiro passo pode acontecer em uma transação separada das últimas duas. Entretanto, front-running não é um problema porque as duas funções que chamam `_initiateERC20Deposit` (`depositERC20` e `depositERC20To`) somente chamam essa função com `msg.sender` como parâmetro `_from`. +O primeiro passo pode acontecer em uma transação separada dos dois últimos. +No entanto, o front-running não é um problema porque as duas funções que chamam `_initiateERC20Deposit` (`depositERC20` e `depositERC20To`) só chamam esta função com `msg.sender` como o parâmetro `_from`. ```solidity - // Construct calldata for _l2Token.finalizeDeposit(_to, _amount) + // Constrói o calldata para _l2Token.finalizeDeposit(_to, _amount) bytes memory message = abi.encodeWithSelector( IL2ERC20Bridge.finalizeDeposit.selector, _l1Token, @@ -778,7 +825,7 @@ O primeiro passo pode acontecer em uma transação separada das últimas duas. E _data ); - // Send calldata into L2 + // Envia o calldata para a L2 // slither-disable-next-line reentrancy-events, reentrancy-benign sendCrossDomainMessage(l2TokenBridge, _l2Gas, message); @@ -786,7 +833,8 @@ O primeiro passo pode acontecer em uma transação separada das últimas duas. E deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] + _amount; ``` -Adicione a quantia depositada de tokens para a estrutura de dados `deposits`. Pode haver múltiplos endereços em L2 que correspondam ao mesmo token ERC-20 L1, portanto não é suficiente usar saldo de ponte de token ERC-20 L1 para rastrear os depósitos. +Adiciona a quantia depositada de tokens à estrutura de dados `deposits`. +Pode haver múltiplos endereços na L2 que correspondem ao mesmo token ERC-20 da L1, então não é suficiente usar o saldo da ponte do token ERC-20 da L1 para rastrear os depósitos. ```solidity @@ -795,7 +843,7 @@ Adicione a quantia depositada de tokens para a estrutura de dados `deposits`. Po } /************************* - * Cross-chain Functions * + * Funções entre cadeias * *************************/ /** @@ -808,29 +856,30 @@ Adicione a quantia depositada de tokens para a estrutura de dados `deposits`. Po bytes calldata _data ``` -A ponte L2 envia uma mensagem para o mensageiro entre domínios L2 que causa o mensageiro entre domínios L1 chamar esta função (uma vez que a [transação que finaliza a mensagem](https://community.optimism.io/docs/developers/bridge/messaging/#fees-for-l2-%E2%87%92-l1-transactions) é submetida no L1, claro). +A ponte da L2 envia uma mensagem para o mensageiro entre domínios da L2, o que faz com que o mensageiro entre domínios da L1 chame esta função (uma vez que a [transação que finaliza a mensagem](https://community.optimism.io/docs/developers/bridge/messaging/#fees-for-l2-%E2%87%92-l1-transactions) seja enviada na L1, é claro). ```solidity ) external onlyFromCrossDomainAccount(l2TokenBridge) { ``` -Certifique-se que isto é uma mensagem _legítima_, vinda do mensageiro entre domínios e originada com o token da ponte L2. Esta função é usada para retirar ETH da ponte, então nós temos que nos certificar que é somente chamada pelo chamador autorizado. +Certifique-se de que esta é uma mensagem _legítima_, vinda do mensageiro entre domínios e originada na ponte de tokens da L2. +Esta função é usada para retirar ETH da ponte, então temos que ter certeza de que ela só é chamada pelo chamador autorizado. ```solidity // slither-disable-next-line reentrancy-events (bool success, ) = _to.call{ value: _amount }(new bytes(0)); ``` -A maneira de transferir ETH é chamar o recebedor com a quantia de wei no `msg.value`. +A maneira de transferir ETH é chamar o destinatário com a quantia de wei no `msg.value`. ```solidity - require(success, "TransferHelper::safeTransferETH: ETH transfer failed"); + require(success, "TransferHelper::safeTransferETH: falha na transferência de ETH"); // slither-disable-next-line reentrancy-events emit ETHWithdrawalFinalized(_from, _to, _amount, _data); ``` -Emitir um evento sobre o saque. +Emite um evento sobre a retirada. ```solidity } @@ -848,17 +897,17 @@ Emitir um evento sobre o saque. ) external onlyFromCrossDomainAccount(l2TokenBridge) { ``` -Esta função é similar a `finalizeETHWithdrawal` acima, com as mudanças necessárias para os tokens ERC-20. +Esta função é semelhante a `finalizeETHWithdrawal` acima, com as alterações necessárias para tokens ERC-20. ```solidity deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] - _amount; ``` -Atualiza a estrutura de dados`deposits`. +Atualiza a estrutura de dados `deposits`. ```solidity - // When a withdrawal is finalized on L1, the L1 Bridge transfers the funds to the withdrawer + // Quando uma retirada é finalizada na L1, a Ponte da L1 transfere os fundos para o sacador // slither-disable-next-line reentrancy-events IERC20(_l1Token).safeTransfer(_to, _amount); @@ -868,28 +917,35 @@ Atualiza a estrutura de dados`deposits`. /***************************** - * Temporary - Migrating ETH * + * Temporário - Migrando ETH * *****************************/ /** - * @dev Adds ETH balance to the account. This is meant to allow for ETH - * to be migrated from an old gateway to a new gateway. - * NOTE: This is left for one upgrade only so we are able to receive the migrated ETH from the - * old contract + * @dev Adiciona saldo de ETH à conta. Isso serve para permitir que o ETH + * seja migrado de um gateway antigo para um novo gateway. + * OBS: Isso é deixado para apenas uma atualização, para que possamos receber o ETH migrado do + * contrato antigo */ function donateETH() external payable {} } ``` -Houve uma implementação anterior dessa ponte. Quando nos movemos da implementação para esta ponte, tivemos que mover todos os ativos. Tokens ERC-20 podem serem simplesmente movidos. Entretanto, para transferir ETH para um contrato, você precisa da aprovação do contrato, que é o que `donateETH` nos fornece. +Havia uma implementação anterior da ponte. +Quando mudamos da implementação anterior para esta, tivemos que mover todos os ativos. +Os tokens ERC-20 podem simplesmente ser movidos. +No entanto, para transferir ETH para um contrato, você precisa da aprovação desse contrato, que é o que `donateETH` nos fornece. ## Tokens ERC-20 na L2 {#erc-20-tokens-on-l2} -Para um token ERC-20 servir na ponte padrão, ele precisa permitir que a ponte padrão, e _somente_ a ponte padrão, cunhe token. Isto é necessário porque as pontes precisam garantir que o número de tokens circulando na Optimism é igual ao número de tokens travados dentro do contrato da ponte L1. Se houver tokens demais na L2, alguns usuários ficarão incapazes de usar a ponte de volta para os seus ativos para a L1. Ao invés de uma ponte confiável, nós iriamos essencialmente recriar [reserva fracionária bancária](https://www.investopedia.com/terms/f/fractionalreservebanking.asp). Se houver tokens demais em L1, alguns desses tokens estaria travados dentro do contrato da ponte para sempre, porque não há maneira de liberá-los sem queimar tokens L2. +Para um token ERC-20 se encaixar na ponte padrão, ele precisa permitir que a ponte padrão, e _apenas_ a ponte padrão, cunhe o token. +Isso é necessário porque as pontes precisam garantir que o número de tokens circulando no Optimism seja igual ao número de tokens bloqueados dentro do contrato da ponte da L1. +Se houver muitos tokens na L2, alguns usuários não conseguirão transferir seus ativos de volta para a L1 por meio da ponte. +Em vez de uma ponte confiável, estaríamos essencialmente recriando o [sistema de reservas fracionárias](https://www.investopedia.com/terms/f/fractionalreservebanking.asp). +Se houver tokens demais na L1, alguns desses tokens ficariam bloqueados dentro do contrato da ponte para sempre, porque não há como liberá-los sem queimar tokens da L2. ### IL2StandardERC20 {#il2standarderc20} -Cada token ERC-20 na L2 que usa a ponte padrão precisa fornecer [esta interface](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/standards/IL2StandardERC20.sol), que tem as funções e eventos que a ponte padrão necessita. +Todo token ERC-20 na L2 que usa a ponte padrão precisa fornecer [esta interface](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/standards/IL2StandardERC20.sol), que tem as funções e eventos de que a ponte padrão precisa. ```solidity // SPDX-License-Identifier: MIT @@ -898,20 +954,24 @@ pragma solidity ^0.8.9; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; ``` -[A interface padrão ERC-20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol) não inclui as funções `mint` e `burn`. Estes métodos não são necessários pelo [padrão ERC-20](https://eips.ethereum.org/EIPS/eip-20), que não deixa especificado os mecanismos para criar e destruir tokens. +[A interface padrão ERC-20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol) não inclui as funções `mint` e `burn`. +Esses métodos não são exigidos pelo [padrão ERC-20](https://eips.ethereum.org/EIPS/eip-20), que não especifica os mecanismos para criar e destruir tokens. ```solidity import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; ``` -[A interface ERC-165 ](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/IERC165.sol)é usada para especificar que funções um contrato fornece. [Você pode ler o padrão aqui](https://eips.ethereum.org/EIPS/eip-165). +[A interface ERC-165](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/IERC165.sol) é usada para especificar quais funções um contrato fornece. +[Você pode ler o padrão aqui](https://eips.ethereum.org/EIPS/eip-165). ```solidity interface IL2StandardERC20 is IERC20, IERC165 { function l1Token() external returns (address); ``` -Esta função fornece o endereço do token L1 que usa a ponte para este contrato. Note que nós não temos uma função similar na direção oposta. Nós precisamos ser capazes de usar a ponte para qualquer token L1, independente se o suporte L2 foi planejado quando foi implementado ou não. +Esta função fornece o endereço do token da L1 que é transferido por ponte para este contrato. +Observe que não temos uma função semelhante na direção oposta. +Precisamos ser capazes de transferir por ponte qualquer token da L1, independentemente de o suporte à L2 ter sido planejado quando ele foi implementado ou não. ```solidity @@ -924,11 +984,13 @@ Esta função fornece o endereço do token L1 que usa a ponte para este contrato } ``` -Funções e eventos para cunhar (criar) e queimar (destruir) tokens. A ponte deveria ser a única entidade que pode rodar estas funções para garantir que o número de tokens esteja correto (igual ao número de tokens travados na L1). +Funções e eventos para cunhar (criar) e queimar (destruir) tokens. +A ponte deve ser a única entidade que pode executar essas funções para garantir que o número de tokens esteja correto (igual ao número de tokens bloqueados na L1). ### L2StandardERC20 {#L2StandardERC20} -[Essa é a nossa implementação da interface `IL2StandardERC20`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/standards/L2StandardERC20.sol). A não ser que você precise de algum tipo de lógica customizada, você deveria usar esta. +[Esta é a nossa implementação da interface `IL2StandardERC20`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/standards/L2StandardERC20.sol). +A menos que você precise de algum tipo de lógica personalizada, você deve usar esta. ```solidity // SPDX-License-Identifier: MIT @@ -937,7 +999,8 @@ pragma solidity ^0.8.9; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; ``` -[O contrato ERC-20 OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol). A Optimism não acredita em reinventar a roda, especialmente quando a roda é bem auditada e precisa ser estimada o suficiente para manter ativos. +[O contrato ERC-20 do OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol). +O Optimism não acredita em reinventar a roda, especialmente quando a roda é bem auditada e precisa ser confiável o suficiente para guardar ativos. ```solidity import "./IL2StandardERC20.sol"; @@ -947,15 +1010,15 @@ contract L2StandardERC20 is IL2StandardERC20, ERC20 { address public l2Bridge; ``` -Há dois parâmetros de configuração adicionais que nós precisamos, e um ERC-20 normalmente não precisa. +Estes são os dois parâmetros de configuração adicionais que exigimos e que um ERC-20 normalmente não exige. ```solidity /** - * @param _l2Bridge Address of the L2 standard bridge. - * @param _l1Token Address of the corresponding L1 token. - * @param _name ERC20 name. - * @param _symbol ERC20 symbol. + * @param _l2Bridge Endereço da ponte padrão da L2. + * @param _l1Token Endereço do token correspondente da L1. + * @param _name Nome do ERC20. + * @param _symbol Símbolo do ERC20. */ constructor( address _l2Bridge, @@ -968,12 +1031,12 @@ Há dois parâmetros de configuração adicionais que nós precisamos, e um ERC- } ``` -Primeiro chame o construtor do contrato que nós herdamos (`ERC20(_name, _symbol)`) e então configure suas próprias variáveis. +Primeiro chame o construtor do contrato que herdamos (`ERC20(_name, _symbol)`) e depois defina nossas próprias variáveis. ```solidity modifier onlyL2Bridge() { - require(msg.sender == l2Bridge, "Only L2 Bridge can mint and burn"); + require(msg.sender == l2Bridge, "Apenas a Ponte da L2 pode cunhar e queimar"); _; } @@ -988,11 +1051,12 @@ Primeiro chame o construtor do contrato que nós herdamos (`ERC20(_name, _symbol } ``` -Essa é a maneira que o[ERC-165](https://eips.ethereum.org/EIPS/eip-165) funciona. Cada interface é um número de funções suportadas, como identificadas no [ou exclusivo](https://en.wikipedia.org/wiki/Exclusive_or) dos [seletores de funções ABI](https://docs.soliditylang.org/en/v0.8.12/abi-spec.html#function-selector) destas funções. +É assim que o [ERC-165](https://eips.ethereum.org/EIPS/eip-165) funciona. +Cada interface é um número de funções suportadas e é identificada como o [ou exclusivo](https://en.wikipedia.org/wiki/Exclusive_or) dos [seletores de função da ABI](https://docs.soliditylang.org/en/v0.8.12/abi-spec.html#function-selector) dessas funções. -A ponte L2 usa ERC-165 como checagem de sanidade para garantir que o contrato ERC-20 para o qual ela envia ativos é um `IL2StandardERC20`. +A ponte da L2 usa o ERC-165 como uma verificação de sanidade para garantir que o contrato ERC-20 para o qual envia ativos é um `IL2StandardERC20`. -**Note:** Não há nada para evitar contratos trapaceiros de fornecer falsas respostas para `supportsInterface`, portanto isto é um mecanismo de checagem de sanidade, _não_ um mecanismo de segurança. +**Observação:** Não há nada que impeça um contrato mal-intencionado de fornecer respostas falsas para `supportsInterface`, portanto, este é um mecanismo de verificação de sanidade, _não_ um mecanismo de segurança. ```solidity // slither-disable-next-line external-function @@ -1011,66 +1075,73 @@ A ponte L2 usa ERC-165 como checagem de sanidade para garantir que o contrato ER } ``` -Somente a ponte L2 pode cunhar e queimar ativos. +Apenas a ponte da L2 pode cunhar e queimar ativos. -`_mint` e `_burn` são na verdade definidos no [contrato ERC-20 OpenZeppelin](/developers/tutorials/erc20-annotated-code/#the-_mint-and-_burn-functions-_mint-and-_burn). Este contrato só não os expõem externamente, porque as condições para cunhar e queimar tokens são tão variadas como o número de maneiras de usar ERC-20. +`_mint` e `_burn` são, na verdade, definidos no [contrato ERC-20 da OpenZeppelin](/developers/tutorials/erc20-annotated-code/#the-_mint-and-_burn-functions-_mint-and-_burn). +Aquele contrato simplesmente não os expõe externamente, porque as condições para cunhar e queimar tokens são tão variadas quanto o número de maneiras de usar o ERC-20. -## Código da ponte L2 {#l2-bridge-code} +## Código da Ponte da L2 {#l2-bridge-code} -Este é o código que roda na ponte na Optimism. [A fonte deste contrato é aqui](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/L2StandardBridge.sol). +Este é o código que executa a ponte no Optimism. +[A fonte para este contrato está aqui](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/L2StandardBridge.sol). ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.9; -/* Interface Imports */ +/* Importações de Interface */ import { IL1StandardBridge } from "../../L1/messaging/IL1StandardBridge.sol"; import { IL1ERC20Bridge } from "../../L1/messaging/IL1ERC20Bridge.sol"; import { IL2ERC20Bridge } from "./IL2ERC20Bridge.sol"; ``` -A interface [IL2ERC20Bridge](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol) é muito similar ao [equivalente L1](#IL1ERC20Bridge) que nós vimos acima. Há duas diferenças significantes: +A interface [IL2ERC20Bridge](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol) é muito semelhante ao [equivalente da L1](#IL1ERC20Bridge) que vimos acima. +Há duas diferenças significativas: -1. Na L1 você inicia depósitos e finaliza retiradas. Aqui você inicia retiradas e finaliza depósitos. -2. Na L1 é necessário distinguir entre ETH e tokens ERC-20. Na L2 nós podemos usar as mesmas funções para ambos os casos porque internamente saldos ETH na Optimism são manipulados por um token ERC-20 com o endereço [0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000](https://optimistic.etherscan.io/address/0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000). +1. Na L1, você inicia depósitos e finaliza retiradas. + Aqui, você inicia retiradas e finaliza depósitos. +2. Na L1, é necessário distinguir entre tokens ETH e ERC-20. + Na L2, podemos usar as mesmas funções para ambos, porque internamente os saldos de ETH no Optimism são tratados como um token ERC-20 com o endereço [0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000](https://explorer.optimism.io/address/0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000). ```solidity -/* Library Imports */ +/* Importações de Biblioteca */ import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import { CrossDomainEnabled } from "../../libraries/bridge/CrossDomainEnabled.sol"; import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol"; -/* Contract Imports */ +/* Importações de Contrato */ import { IL2StandardERC20 } from "../../standards/IL2StandardERC20.sol"; /** * @title L2StandardBridge - * @dev The L2 Standard bridge is a contract which works together with the L1 Standard bridge to - * enable ETH and ERC20 transitions between L1 and L2. - * This contract acts as a minter for new tokens when it hears about deposits into the L1 Standard - * bridge. - * This contract also acts as a burner of the tokens intended for withdrawal, informing the L1 - * bridge to release L1 funds. + * @dev A ponte Padrão da L2 é um contrato que funciona em conjunto com a ponte Padrão da L1 para + * permitir transições de ETH e ERC20 entre L1 e L2. + * Este contrato atua como um cunhador para novos tokens quando ouve sobre depósitos na Ponte Padrão + * da L1. + * Este contrato também atua como um queimador dos tokens destinados à retirada, informando à ponte + * da L1 para liberar fundos da L1. */ contract L2StandardBridge is IL2ERC20Bridge, CrossDomainEnabled { /******************************** - * External Contract References * + * Referências de Contratos Externos * ********************************/ address public l1TokenBridge; ``` -Acompanhe o endereço da ponte L1. Observe que, em contraste com o equivalente L1, aqui _precisamos_ desta variável. O endereço da ponte L1 não é conhecido antecipadamente. +Acompanhe o endereço da ponte da L1. +Observe que, em contraste com o equivalente da L1, aqui _precisamos_ desta variável. +O endereço da ponte da L1 não é conhecido antecipadamente. ```solidity /*************** - * Constructor * + * Construtor * ***************/ /** - * @param _l2CrossDomainMessenger Cross-domain messenger used by this contract. - * @param _l1TokenBridge Address of the L1 bridge deployed to the main chain. + * @param _l2CrossDomainMessenger Mensageiro entre domínios usado por este contrato. + * @param _l1TokenBridge Endereço da ponte da L1 implantada na cadeia principal. */ constructor(address _l2CrossDomainMessenger, address _l1TokenBridge) CrossDomainEnabled(_l2CrossDomainMessenger) @@ -1079,7 +1150,7 @@ Acompanhe o endereço da ponte L1. Observe que, em contraste com o equivalente L } /*************** - * Withdrawing * + * Retirada * ***************/ /** @@ -1108,21 +1179,23 @@ Acompanhe o endereço da ponte L1. Observe que, em contraste com o equivalente L } ``` -Estas duas funções iniciam retiradas. Observe que não há necessidade de especificar o endereço do token L1. Espera-se que os tokens L2 nos digam o endereço do equivalente L1. +Estas duas funções iniciam as retiradas. +Observe que não há necessidade de especificar o endereço do token da L1. +Espera-se que os tokens da L2 nos digam o endereço do equivalente da L1. ```solidity /** - * @dev Performs the logic for withdrawals by burning the token and informing - * the L1 token Gateway of the withdrawal. - * @param _l2Token Address of L2 token where withdrawal is initiated. - * @param _from Account to pull the withdrawal from on L2. - * @param _to Account to give the withdrawal to on L1. - * @param _amount Amount of the token to withdraw. - * @param _l1Gas Unused, but included for potential forward compatibility considerations. - * @param _data Optional data to forward to L1. This data is provided - * solely as a convenience for external contracts. Aside from enforcing a maximum - * length, these contracts provide no guarantees about its content. + * @dev Executa a lógica para retiradas, queimando o token e informando + * o Gateway de Token da L1 sobre a retirada. + * @param _l2Token Endereço do token da L2 onde a retirada é iniciada. + * @param _from Conta da qual a retirada será retirada na L2. + * @param _to Conta para a qual a retirada será creditada na L1. + * @param _amount Quantidade do token a ser retirado. + * @param _l1Gas Não utilizado, mas incluído para possíveis considerações de compatibilidade futura. + * @param _data Dados opcionais para encaminhar para a L1. Estes dados são fornecidos + * apenas como uma conveniência para contratos externos. Além de impor um comprimento + * máximo, estes contratos não fornecem garantias sobre seu conteúdo. */ function _initiateWithdrawal( address _l2Token, @@ -1132,17 +1205,17 @@ Estas duas funções iniciam retiradas. Observe que não há necessidade de espe uint32 _l1Gas, bytes calldata _data ) internal { - // When a withdrawal is initiated, we burn the withdrawer's funds to prevent subsequent L2 - // usage + // Quando uma retirada é iniciada, nós queimamos os fundos do sacador para evitar o uso subsequente na L2 + // // slither-disable-next-line reentrancy-events IL2StandardERC20(_l2Token).burn(msg.sender, _amount); ``` -Observe que _não_ estamos contando com o parâmetro `_from`, mas com o `msg.sender` que é muito mais difícil de falsificar (impossível, até onde eu sei). +Observe que não estamos confiando no parâmetro `_from`, mas em `msg.sender`, que é muito mais difícil de falsificar (impossível, até onde eu sei). ```solidity - // Construct calldata for l1TokenBridge.finalizeERC20Withdrawal(_to, _amount) + // Constrói o calldata para l1TokenBridge.finalizeERC20Withdrawal(_to, _amount) // slither-disable-next-line reentrancy-events address l1Token = IL2StandardERC20(_l2Token).l1Token(); bytes memory message; @@ -1150,7 +1223,7 @@ Observe que _não_ estamos contando com o parâmetro `_from`, mas com o `msg.sen if (_l2Token == Lib_PredeployAddresses.OVM_ETH) { ``` -Na L1 é necessário distinguir entre ETH e ERC-20. +Na L1, é necessário distinguir entre ETH e ERC-20. ```solidity message = abi.encodeWithSelector( @@ -1172,7 +1245,7 @@ Na L1 é necessário distinguir entre ETH e ERC-20. ); } - // Send message up to L1 bridge + // Envia a mensagem para a ponte da L1 // slither-disable-next-line reentrancy-events sendCrossDomainMessage(l1TokenBridge, _l1Gas, message); @@ -1181,7 +1254,7 @@ Na L1 é necessário distinguir entre ETH e ERC-20. } /************************************ - * Cross-chain Function: Depositing * + * Função entre cadeias: Depósito * ************************************/ /** @@ -1202,11 +1275,12 @@ Essa função é chamada pelo `L1StandardBridge`. ) external virtual onlyFromCrossDomainAccount(l1TokenBridge) { ``` -Certifique-se que a origem da mensagem é legítima. Isso é importante porque a função chama `_mint` e poderia ser usada para dar tokens que não foram cobertos pelos tokens que a ponte tem na L1. +Certifique-se de que a origem da mensagem é legítima. +Isso é importante porque a função chama `_mint` e poderia ser usada para dar tokens que não são cobertos pelos tokens que a ponte possui na L1. ```solidity - // Check the target token is compliant and - // verify the deposited token on L1 matches the L2 deposited token representation here + // Verifica se o token de destino é compatível e + // verifica se o token depositado na L1 corresponde à representação do token depositado na L2 aqui if ( // slither-disable-next-line reentrancy-events ERC165Checker.supportsInterface(_l2Token, 0x1d1d8b63) && @@ -1216,11 +1290,11 @@ Certifique-se que a origem da mensagem é legítima. Isso é importante porque a Verificações de sanidade: 1. A interface correta é suportada -2. O endereço L1 do contrato ERC-20 L2 bate com a fonte L1 dos tokens +2. O endereço L1 do contrato ERC-20 da L2 corresponde à origem dos tokens na L1 ```solidity ) { - // When a deposit is finalized, we credit the account on L2 with the same amount of + // Quando um depósito é finalizado, creditamos na conta da L2 a mesma quantidade de // tokens. // slither-disable-next-line reentrancy-events IL2StandardERC20(_l2Token).mint(_to, _amount); @@ -1228,37 +1302,38 @@ Verificações de sanidade: emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); ``` -Se a checagem de sanidade passar, finalize o depósito: +Se a verificação de sanidade passar, finalize o depósito: -1. Cunhe os tokens -2. Emita o evento apropriado +1. Cunhar os tokens +2. Emitir o evento apropriado ```solidity } else { - // Either the L2 token which is being deposited-into disagrees about the correct address - // of its L1 token, or does not support the correct interface. - // This should only happen if there is a malicious L2 token, or if a user somehow - // specified the wrong L2 token address to deposit into. - // In either case, we stop the process here and construct a withdrawal - // message so that users can get their funds out in some cases. - // There is no way to prevent malicious token contracts altogether, but this does limit - // user error and mitigate some forms of malicious contract behavior. + // Ou o token da L2 que está sendo depositado discorda sobre o endereço correto + // de seu token da L1, ou não suporta a interface correta. + // Isso só deve acontecer se houver um token malicioso na L2, ou se um usuário de alguma forma + // especificou o endereço errado do token da L2 para depositar. + // Em ambos os casos, paramos o processo aqui e construímos uma mensagem de retirada + // para que os usuários possam retirar seus fundos em alguns casos. + // Não há como evitar contratos de token maliciosos completamente, mas isso limita + // o erro do usuário e mitiga algumas formas de comportamento de contrato malicioso. ``` -Se um usuário fez um erro detectável usando o endereço de token L2 errado, nós queremos cancelar o depósito e retornar os tokens na L1. A única maneira que nós podemos fazer isso de L2 é enviar uma mensagem que irá ter que esperar pelo período de desafio de falha, mas isto é muito melhor para o usuário que perder seus tokens permanentemente. +Se um usuário cometeu um erro detectável usando o endereço de token da L2 errado, queremos cancelar o depósito e retornar os tokens na L1. +A única maneira de fazer isso a partir da L2 é enviar uma mensagem que terá que esperar o período de contestação de falhas, mas isso é muito melhor para o usuário do que perder os tokens permanentemente. ```solidity bytes memory message = abi.encodeWithSelector( IL1ERC20Bridge.finalizeERC20Withdrawal.selector, _l1Token, _l2Token, - _to, // switched the _to and _from here to bounce back the deposit to the sender + _to, // trocou o _to e o _from aqui para devolver o depósito ao remetente _from, _amount, _data ); - // Send message up to L1 bridge + // Envia a mensagem para a ponte da L1 // slither-disable-next-line reentrancy-events sendCrossDomainMessage(l1TokenBridge, 0, message); // slither-disable-next-line reentrancy-events @@ -1270,8 +1345,13 @@ Se um usuário fez um erro detectável usando o endereço de token L2 errado, n ## Conclusão {#conclusion} -A ponte padrão é o mecanismo mais flexível para transferência de ativos. Porém, por ser genérico não é sempre o mecanismo mais fácil de usar. Especialmente para retiradas, a maioria dos usuários prefere usar [pontes de terceiros](https://optimism.io/apps#bridge) a esperar o período de desafio e também não precisar de uma prova de Merkle para finalizar a retirada. +A ponte padrão é o mecanismo mais flexível para transferência de ativos. +Porém, por ser genérico não é sempre o mecanismo mais fácil de usar. +Especialmente para retiradas, a maioria dos usuários prefere usar [pontes de terceiros](https://optimism.io/apps#bridge) que não esperam o período de desafio e não exigem uma prova de Merkle para finalizar a retirada. + +Estas pontes tipicamente funcionam tendo ativos na L1, que elas fornecem imediatamente por uma taxa pequena (geralmente menor que o custo de gás para uma retirada de uma ponte padrão). +Quando a ponte (ou as pessoas que a administram) antecipa a falta de ativos da L1, ela transfere ativos suficientes da L2. Como estes são saques muito grandes, o custo do saque é amortizado por uma grande quantia e é um percentual muito menor. -Estas pontes tipicamente funcionam tendo ativos na L1, que elas fornecem imediatamente por uma taxa pequena (geralmente menor que o custo de gas para uma retirada de uma ponte padrão). Quando a ponte (ou as pessoas que a administram) antecipa a falta de ativos L1, ela transfere ativos suficientes da L2. Como estes são saques muito grandes, o custo do saque é amortizado por uma larga quantia e é um percentual muito menor. +Esperamos que este artigo tenha ajudado você a entender mais sobre como a camada 2 funciona e como escrever um código Solidity claro e seguro. -Esperamos que este artigo tenha ajudado você a entender mais sobre como a camada 2 funciona, e como escrever um código Solidity claro e seguro. +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). diff --git a/public/content/translations/pt-br/developers/tutorials/reverse-engineering-a-contract/index.md b/public/content/translations/pt-br/developers/tutorials/reverse-engineering-a-contract/index.md index 8c95b9ec979..2e7be918d57 100644 --- a/public/content/translations/pt-br/developers/tutorials/reverse-engineering-a-contract/index.md +++ b/public/content/translations/pt-br/developers/tutorials/reverse-engineering-a-contract/index.md @@ -1,309 +1,307 @@ --- -title: "Engenharia reversa de um contrato" -description: Como entender um contrato quando você não tem o código-fonte +title: "Engenharia Reversa de um Contrato" +description: "Como entender um contrato quando você não tem o código-fonte" author: Ori Pomerantz lang: pt-br -tags: - - "evm" - - "códigos de operação" +tags: [ "evm", "códigos de operação" ] skill: advanced published: 2021-12-30 --- ## Introdução {#introduction} -_Não há segredos no blockchain_. Tudo o que acontece é consistente, verificável e está disponível publicamente. O ideal é que os contratos [tenham seu código-fonte publicado e verificado na Etherscan](https://etherscan.io/address/0xb8901acb165ed027e32754e0ffe830802919727f#code). No entanto, [nem sempre isso acontece](https://etherscan.io/address/0x2510c039cc3b061d79e564b38836da87e31b342f#code). Neste artigo, você aprenderá a usar engenharia reversa em contratos analisando um contrato sem código-fonte, [`0x2510c039cc3b061d79e564b38836da87e31b342f`](https://etherscan.io/address/0x2510c039cc3b061d79e564b38836da87e31b342f). +_Não há segredos no blockchain, tudo o que acontece é consistente, verificável e está disponível publicamente._ Idealmente, [os contratos devem ter seu código-fonte publicado e verificado no Etherscan](https://etherscan.io/address/0xb8901acb165ed027e32754e0ffe830802919727f#code). No entanto, [nem sempre é o caso](https://etherscan.io/address/0x2510c039cc3b061d79e564b38836da87e31b342f#code). Neste artigo, você aprenderá como fazer engenharia reversa de contratos analisando um contrato sem código-fonte, [`0x2510c039cc3b061d79e564b38836da87e31b342f`](https://etherscan.io/address/0x2510c039cc3b061d79e564b38836da87e31b342f). -Existem compiladores reversos, mas eles nem sempre produzem [resultados utilizáveis](https://etherscan.io/bytecode-decompiler?a=0x2510c039cc3b061d79e564b38836da87e31b342f). Neste artigo, você aprenderá como usar engenharia reversa manualmente e entender um contrato dos [opcodes](https://github.com/wolflo/evm-opcodes), além de interpretar os resultados de um descompilador. +Existem compiladores reversos, mas eles nem sempre produzem [resultados utilizáveis](https://etherscan.io/bytecode-decompiler?a=0x2510c039cc3b061d79e564b38836da87e31b342f). Neste artigo, você aprenderá a fazer engenharia reversa manualmente e a entender um contrato a partir dos [códigos de operação](https://github.com/wolflo/evm-opcodes), bem como a interpretar os resultados de um descompilador. -Para entender este artigo, é preciso saber o básico de EVM e pelo menos estar um pouco familiarizado com a montagem de EVM. [Você pode ler sobre estes tópicos aqui](https://medium.com/mycrypto/the-ethereum-virtual-machine-how-does-it-work-9abac2b7c9e). +Para entender este artigo, você já deve saber o básico da EVM e estar pelo menos um pouco familiarizado com a linguagem de montagem da EVM. [Você pode ler sobre esses tópicos aqui](https://medium.com/mycrypto/the-ethereum-virtual-machine-how-does-it-work-9abac2b7c9e). -## Preparar o Código Executável {#prepare-the-executable-code} +## Preparar o código executável {#prepare-the-executable-code} -Você pode obter os opcodes acessando o contrato no Etherscan clicando na guia **Contrato** e depois em **Alternar para a Visualização de Opcodes**. Você poderá visualizar um opcode por linha. +Você pode obter os códigos de operação indo para o Etherscan para o contrato, clicando na guia **Contrato** e depois em **Mudar para Visualização de Opcodes**. Você obterá uma visualização de um código de operação por linha. -![Visualização do Opcode no Etherscan](opcode-view.png) +![Visualização de código de operação do Etherscan](opcode-view.png) -Para entender os saltos, no entanto, você precisa saber onde no código cada opcode está localizado. Uma maneira de fazer isso é abrir uma planilha do Google e colar os opcodes na coluna C. [Você pode pular as seguintes etapas ao fazer uma cópia desta planilha já preparada](https://docs.google.com/spreadsheets/d/1tKmTJiNjUwHbW64wCKOSJxHjmh0bAUapt6btUYE7kDA/edit?usp=sharing). +Para entender os saltos, no entanto, você precisa saber onde no código cada código de operação está localizado. Para fazer isso, uma maneira é abrir uma planilha do Google e colar os códigos de operação na coluna C. [Você pode pular as etapas a seguir fazendo uma cópia desta planilha já preparada](https://docs.google.com/spreadsheets/d/1tKmTJiNjUwHbW64wCKOSJxHjmh0bAUapt6btUYE7kDA/edit?usp=sharing). -O próximo passo é obter os locais de código corretos para que possamos entender os saltos. Colocaremos o tamanho do opcode na coluna B e o local (em hexadecimal) na coluna A. Digite esta função na célula `B1` e então copie e cole para o resto da coluna B, até o final do código. Depois de fazer isso, você pode ocultar a coluna B. +O próximo passo é obter os locais corretos do código para que possamos entender os saltos. Colocaremos o tamanho do código de operação na coluna B e o local (em hexadecimal) na coluna A. Digite esta função na célula `B1` e depois copie e cole no resto da coluna B, até o final do código. Depois de fazer isso, você pode ocultar a coluna B. ``` =1+IF(REGEXMATCH(C1,"PUSH"),REGEXEXTRACT(C1,"PUSH(\d+)"),0) ``` -Primeiro essa função adiciona um byte no opcode em si e depois procura por `PUSH`. Opcodes de push são especiais porque eles precisam ter bytes adicionais para o valor que está sendo enviado. Se o opcode é um `PUSH`, extraímos o número de bytes e adicionamos isso. +Primeiro, esta função adiciona um byte para o próprio código de operação e, em seguida, procura por `PUSH`. Os códigos de operação de push são especiais porque precisam ter bytes adicionais para o valor que está sendo inserido. Se o código de operação for um `PUSH`, extraímos o número de bytes e o adicionamos. -Em `A1` coloque o primeiro offset (descolamento de bits), para zero. Depois, em `A2`, insira esta função e copie e cole novamente para o resto da coluna A: +Em `A1`, coloque o primeiro deslocamento, zero. Depois, em `A2`, insira esta função e copie e cole novamente para o resto da coluna A: ``` =dec2hex(hex2dec(A1)+B1) ``` -Nós precisamos desta função, para nos dar o valor hexadecimal, porque os valores que são enviados antes dos saltos (`JUMP` e `JUMPI`) são dados a nós em hexadecimal. +Precisamos desta função para nos dar o valor hexadecimal, porque os valores que são inseridos antes dos saltos (`JUMP` e `JUMPI`) são nos dados em hexadecimal. -## O Ponto de Entrada (0x00) {#the-entry-point-0x00} +## O ponto de entrada (0x00) {#the-entry-point-0x00} -Os contratos são sempre executados a partir do primeiro byte. Essa é a parte inicial do código: +Os contratos são sempre executados a partir do primeiro byte. Esta é a parte inicial do código: -| Deslocamento | Código de Operação | Montante (depois do opcode) | -| ------------:| ------------------ | --------------------------- | -| 0 | PUSH1 0x80 | 0x80 | -| 2 | PUSH1 0x40 | 0x40, 0x80 | -| 4 | MSTORE | Vazio | -| 5 | PUSH1 0x04 | 0x04 | -| 7 | CALLDATASIZE | CALLDATASIZE 0x04 | -| 8 | LT | CALLDATASIZE\<4 | -| 9 | PUSH2 0x005e | 0x5E CALLDATASIZE\<4 | -| C | JUMPI | Vazio | +| Deslocamento | Código de Operação | Pilha (após o código de operação) | +| -----------: | ------------------ | ---------------------------------------------------- | +| 0 | PUSH1 0x80 | 0x80 | +| 2 | PUSH1 0x40 | 0x40, 0x80 | +| 4 | MSTORE | Vazio | +| 5 | PUSH1 0x04 | 0x04 | +| 7 | CALLDATASIZE | CALLDATASIZE 0x04 | +| 8 | LT | CALLDATASIZE\<4 | +| 9 | PUSH2 0x005e | 0x5E CALLDATASIZE\<4 | +| C | JUMPI | Vazio | -Esse código faz duas coisas: +Este código faz duas coisas: -1. Escreva 0x80 como um valor de 32 bytes para locais da memória 0x40-0x5F (0x80 é armazenado em 0x5F, e 0x40-0x5E são todos zeros). -2. Leia o tamanho dos dados de chamada. Normalmente, os dados de chamada para um contrato Ethereum seguem [a ABI (interface binária do aplicativo)](https://docs.soliditylang.org/en/v0.8.10/abi-spec.html), o qual requer no mínimo quatro bytes para o seletor de função. Se o tamanho dos dados da chamada for menor que quatro, pule para 0x5E. +1. Escreve 0x80 como um valor de 32 bytes para os locais de memória 0x40-0x5F (0x80 é armazenado em 0x5F e 0x40-0x5E são todos zeros). +2. Lê o tamanho dos dados de chamada. Normalmente, os dados de chamada para um contrato Ethereum seguem [a ABI (interface binária de aplicativo)](https://docs.soliditylang.org/en/v0.8.10/abi-spec.html), que no mínimo requer quatro bytes para o seletor de função. Se o tamanho dos dados da chamada for menor que quatro, salta para 0x5E. ![Fluxograma para esta parte](flowchart-entry.png) -### O controlador em 0x5E (para dados de chamada não ABI) {#the-handler-at-0x5e-for-non-abi-call-data} +### O manipulador em 0x5E (para dados de chamada não ABI) {#the-handler-at-0x5e-for-non-abi-call-data} | Deslocamento | Código de Operação | -| ------------:| ------------------ | +| -----------: | ------------------ | | 5E | JUMPDEST | | 5F | CALLDATASIZE | | 60 | PUSH2 0x007c | | 63 | JUMPI | -Este trecho começa com um `JUMPDEST`. Os programas EVM (Máquina Virtual Ethereum) lançam uma exceção se você pular para um opcode que não for `JUMPDEST`. Então, ele examina o CALLDATASIZE e, se for "verdadeiro" (ou seja, não for zero), pula para 0x7C. Veremos isso abaixo. +Este trecho começa com um `JUMPDEST`. Programas EVM (máquina virtual Ethereum) lançam uma exceção se você saltar para um código de operação que não seja `JUMPDEST`. Em seguida, ele analisa o CALLDATASIZE e, se for "verdadeiro" (ou seja, diferente de zero), salta para 0x7C. Veremos isso abaixo. -| Deslocamento | Código de Operação | Montante (depois do opcode) | -| ------------:| ------------------ | ----------------------------------------------------------------------------- | -| 64 | CALLVALUE | [Wei](/glossary/#wei) fornecido pela chamada. Chamado `msg.value` no Solidity | -| 65 | PUSH1 0x06 | 6 CALLVALUE | -| 67 | PUSH1 0x00 | 0 6 CALLVALUE | -| 69 | DUP3 | CALLVALUE 0 6 CALLVALUE | -| 6A | DUP3 | 6 CALLVALUE 0 6 CALLVALUE | -| 6B | SLOAD | Storage[6] CALLVALUE 0 6 CALLVALUE | +| Deslocamento | Código de Operação | Pilha (após o código de operação) | +| -----------: | ------------------ | ------------------------------------------------------------------------------------------------ | +| 64 | CALLVALUE | [Wei](/glossary/#wei) fornecido pela chamada. Chamado de `msg.value` no Solidity | +| 65 | PUSH1 0x06 | 6 CALLVALUE | +| 67 | PUSH1 0x00 | 0 6 CALLVALUE | +| 69 | DUP3 | CALLVALUE 0 6 CALLVALUE | +| 6A | DUP3 | 6 CALLVALUE 0 6 CALLVALUE | +| 6B | SLOAD | Storage[6] CALLVALUE 0 6 CALLVALUE | -Portanto, quando não há dados de chamada, nós lemos o valor de Storage[6]. Ainda não sabemos que valor é esse, mas podemos buscar as transações que o contrato recebeu sem nenhum dado de chamada. Transações que apenas transferem ETH sem nenhum dado de chamada (e, portanto, nenhum método) têm no Etherscan o método `Transfer`. De fato, [a primeira transação que o contrato recebeu](https://etherscan.io/tx/0xeec75287a583c36bcc7ca87685ab41603494516a0f5986d18de96c8e630762e7) é uma transferência. +Então, quando não há dados de chamada, lemos o valor de Storage[6]. Ainda não sabemos qual é esse valor, mas podemos procurar transações que o contrato recebeu sem dados de chamada. As transações que apenas transferem ETH sem quaisquer dados de chamada (e, portanto, sem método) têm no Etherscan o método `Transfer`. Na verdade, [a primeira transação que o contrato recebeu](https://etherscan.io/tx/0xeec75287a583c36bcc7ca87685ab41603494516a0f5986d18de96c8e630762e7) é uma transferência. -Se nós olharmos nessa transação e clicarmos em **Clique para ver mais**, veremos que os dados da chamada, chamados de dados de entrada, estão de fato vazios (`0x`). Observe também que o valor é 1.559 ETH, que será relevante mais tarde. +Se olharmos nessa transação e clicarmos em **Clique para ver mais**, vemos que os dados da chamada, chamados de dados de entrada, estão de fato vazios (`0x`). Observe também que o valor é 1,559 ETH, o que será relevante mais tarde. ![Os dados da chamada estão vazios](calldata-empty.png) -Em seguida, clique na guia o **Estado** e expanda o contrato que estamos fazendo engenharia reversa (0x2510...). Você pode ver que `Storage[6]` (armazenamento) mudou durante a transação e, se você alterar Hex para **Número**, verá que se tornou 1.559.000.000.000.000.000, o valor transferido em wei (adicionei as vírgulas para maior clareza), que corresponde ao próximo valor do contrato. +Em seguida, clique na guia **Estado** e expanda o contrato do qual estamos fazendo engenharia reversa (0x2510...). Você pode ver que `Storage[6]` mudou durante a transação, e se você mudar de Hex para **Número**, verá que se tornou 1.559.000.000.000.000.000, o valor transferido em wei (adicionei os pontos para maior clareza), correspondendo ao próximo valor do contrato. -![A mudança no Armazenamento[6]](storage6.png) +![A mudança em Storage[6]](storage6.png) -Se observarmos as mudanças de estado causadas por [outras transações de `Transfer` (transferência) do mesmo período](https://etherscan.io/tx/0xf708d306de39c422472f43cb975d97b66fd5d6a6863db627067167cbf93d84d1#statechange), vemos que `Storage[6]` rastreou o valor do contrato por um tempo. Por enquanto, vamos chamá-lo de `Value*` (valor). O asterisco (`*`) nos lembra que não _sabemos_ o que esta variável faz, ainda, mas não pode ser apenas para rastrear o valor do contrato porque não há necessidade de usar armazenamento, o que é muito caro, quando você pode obter o saldo de suas contas usando `ADDRESS BALANCE`. O primeiro opcode envia o próprio endereço do contrato. O segundo lê o endereço no topo da pilha e o substitui com o saldo desse endereço. - -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | --------------------------------------------- | -| 6C | PUSH2 0x0075 | 0x75 Value\* CALLVALUE 0 6 CALLVALUE | -| 6F | SWAP2 | CALLVALUE Value\* 0x75 0 6 CALLVALUE | -| 70 | SWAP1 | Value\* CALLVALUE 0x75 0 6 CALLVALUE | -| 71 | PUSH2 0x01a7 | 0x01A7 Value\* CALLVALUE 0x75 0 6 CALLVALUE | -| 74 | JUMP | | - -Nós continuaremos a rastrear esse código no destino do salto (desvio). - -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ------------------------------------------------------------- | -| 1A7 | JUMPDEST | Value\* CALLVALUE 0x75 0 6 CALLVALUE | -| 1A8 | PUSH1 0x00 | 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | -| 1AA | DUP3 | CALLVALUE 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | -| 1AB | NOT | 2^256-CALLVALUE-1 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | - -O `NOT` é bit a bit, portanto, ele inverte o valor de cada bit no valor da chamada. - -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ------------------------------------------------------------------------------- | -| 1AC | DUP3 | Value\* 2^256-CALLVALUE-1 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | -| 1AD | GT | Value\*>2^256-CALLVALUE-1 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | -| 1AE | ISZERO | Value\*\<=2^256-CALLVALUE-1 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | -| 1AF | PUSH2 0x01df | 0x01DF Value\*\<=2^256-CALLVALUE-1 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | -| 1B2 | JUMPI | | - -Nós pulamos se `Value*` (o valor) for menor que 2^256-CALLVALUE-1 ou igual a ele. Isso parece lógico para evitar vazamento (overflow). E, de fato, vemos que depois de algumas operações sem sentido (escrever na memória que está prestes a ser excluída, por exemplo) no deslocamento 0x01DE, o contrato é revertido se o vazamento for detectado, o que é um comportamento normal. - -Note que esse vazamento é extremamente improvável, porque exigiria que o valor da chamada mais o `Value*` fosse comparável a 2^256 wei, em torno de 10^59 ETH. [O suprimento total de ETH, no momento desta redação, é inferior a duzentos milhões](https://etherscan.io/stat/supply). +Se olharmos nas mudanças de estado causadas por [outras transações de `Transfer` do mesmo período](https://etherscan.io/tx/0xf708d306de39c422472f43cb975d97b66fd5d6a6863db627067167cbf93d84d1#statechange), vemos que `Storage[6]` rastreou o valor do contrato por um tempo. Por enquanto, vamos chamá-lo de `Valor*`. O asterisco (`*`) nos lembra que ainda não _sabemos_ o que essa variável faz, mas não pode ser apenas para rastrear o valor do contrato porque não há necessidade de usar o armazenamento, que é muito caro, quando você pode obter o saldo de suas contas usando `ADDRESS BALANCE`. O primeiro código de operação insere o próprio endereço do contrato. O segundo lê o endereço no topo da pilha e o substitui pelo saldo desse endereço. | Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ------------------------------------------- | -| 1DF | JUMPDEST | 0x00 Value\* CALLVALUE 0x75 0 6 CALLVALUE | -| 1E0 | POP | Value\* CALLVALUE 0x75 0 6 CALLVALUE | -| 1E1 | ADD | Value\*+CALLVALUE 0x75 0 6 CALLVALUE | -| 1E2 | SWAP1 | 0x75 Value\*+CALLVALUE 0 6 CALLVALUE | -| 1E3 | JUMP | | +| -----------: | ------------------ | ------------------------------------------- | +| 6C | PUSH2 0x0075 | 0x75 Valor\* CALLVALUE 0 6 CALLVALUE | +| 6F | SWAP2 | CALLVALUE Valor\* 0x75 0 6 CALLVALUE | +| 70 | SWAP1 | Valor\* CALLVALUE 0x75 0 6 CALLVALUE | +| 71 | PUSH2 0x01a7 | 0x01A7 Valor\* CALLVALUE 0x75 0 6 CALLVALUE | +| 74 | JUMP | | + +Continuaremos a rastrear este código no destino do salto. + +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | ----------------------------------------------------------- | +| 1A7 | JUMPDEST | Valor\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1A8 | PUSH1 0x00 | 0x00 Valor\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1AA | DUP3 | CALLVALUE 0x00 Valor\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1AB | NOT | 2^256-CALLVALUE-1 0x00 Valor\* CALLVALUE 0x75 0 6 CALLVALUE | + +O `NOT` é bit a bit, então ele inverte o valor de cada bit no valor da chamada. + +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | ------------------------------------------------------------------------------------------------------ | +| 1AC | DUP3 | Valor\* 2^256-CALLVALUE-1 0x00 Valor\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1AD | GT | Valor\*>2^256-CALLVALUE-1 0x00 Valor\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1AE | ISZERO | Valor\*\<=2^256-CALLVALUE-1 0x00 Valor\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1AF | PUSH2 0x01df | 0x01DF Valor\*\<=2^256-CALLVALUE-1 0x00 Valor\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1B2 | JUMPI | | + +Saltamos se `Valor*` for menor ou igual a 2^256-CALLVALUE-1. Isso parece uma lógica para evitar overflow. E, de fato, vemos que, após algumas operações sem sentido (escrever na memória que está prestes a ser excluída, por exemplo), no deslocamento 0x01DE, o contrato reverte se o overflow for detectado, o que é um comportamento normal. + +Note que tal overflow é extremamente improvável, porque exigiria que o valor da chamada mais `Valor*` fosse comparável a 2^256 wei, cerca de 10^59 ETH. [O fornecimento total de ETH, no momento da escrita, é inferior a duzentos milhões](https://etherscan.io/stat/supply). + +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | ----------------------------------------- | +| 1DF | JUMPDEST | 0x00 Valor\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1E0 | POP | Valor\* CALLVALUE 0x75 0 6 CALLVALUE | +| 1E1 | ADD | Valor\*+CALLVALUE 0x75 0 6 CALLVALUE | +| 1E2 | SWAP1 | 0x75 Valor\*+CALLVALUE 0 6 CALLVALUE | +| 1E3 | JUMP | | + +Se chegamos aqui, obtemos `Valor* + CALLVALUE` e saltamos para o deslocamento 0x75. -Se chegamos aqui, pegue `Value* + CALLVALUE` e salte para o offset 0x75. - -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | --------------------------------- | -| 75 | JUMPDEST | Value\*+CALLVALUE 0 6 CALLVALUE | -| 76 | SWAP1 | 0 Value\*+CALLVALUE 6 CALLVALUE | -| 77 | SWAP2 | 6 Value\*+CALLVALUE 0 CALLVALUE | -| 78 | SSTORE | 0 CALLVALUE | +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | ------------------------------- | +| 75 | JUMPDEST | Valor\*+CALLVALUE 0 6 CALLVALUE | +| 76 | SWAP1 | 0 Valor\*+CALLVALUE 6 CALLVALUE | +| 77 | SWAP2 | 6 Valor\*+CALLVALUE 0 CALLVALUE | +| 78 | SSTORE | 0 CALLVALUE | -Se nós chegarmos aqui (o que requer que os dados da chamada estejam vazios), adicionamos o `Value*` ao valor da chamada. Isso é consistente com o que dizemos que as transações de `Transfer` fazem. +Se chegarmos aqui (o que exige que os dados da chamada estejam vazios), adicionamos o valor da chamada a `Valor*`. Isso é consistente com o que dizemos que as transações de `Transfer` fazem. | Deslocamento | Código de Operação | -| ------------:| ------------------ | +| -----------: | ------------------ | | 79 | POP | | 7A | POP | | 7B | STOP | Finalmente, limpe a pilha (o que não é necessário) e sinalize o fim bem-sucedido da transação. -Para simplificar tudo, aqui está um fluxograma para o código inicial. +Para resumir tudo, aqui está um fluxograma para o código inicial. ![Fluxograma do ponto de entrada](flowchart-entry.png) -## O Controlador em 0x7C {#the-handler-at-0x7c} +## O manipulador em 0x7C {#the-handler-at-0x7c} -Eu propositalmente não coloquei no cabeçalho o que esse controlador faz. O propósito não é ensinar como esse contrato específico funciona, mas como fazer engenharia reversa de contratos. Você irá aprender o que ele faz da mesma forma que eu, seguindo o código. +Eu propositalmente não coloquei no título o que este manipulador faz. O objetivo não é ensinar como este contrato específico funciona, mas como fazer engenharia reversa de contratos. Você aprenderá o que ele faz da mesma maneira que eu, seguindo o código. -Nós chegamos aqui a partir de vários locais: +Chegamos aqui de vários lugares: -- Se houver dados de chamada de 1, 2 ou 3 bytes (a partir do deslocamento 0x63) -- Se a assinatura do método for desconhecida (dos offsets 0x42 e 0x5D) +- Se houver dados de chamada de 1, 2 ou 3 bytes (do deslocamento 0x63) +- Se a assinatura do método for desconhecida (dos deslocamentos 0x42 e 0x5D) -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | -------------------- | -| 7C | JUMPDEST | | -| 7D | PUSH1 0x00 | 0x00 | -| 7F | PUSH2 0x009d | 0x9D 0x00 | -| 82 | PUSH1 0x03 | 0x03 0x9D 0x00 | +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | ------------------------------------------------------------------------ | +| 7C | JUMPDEST | | +| 7D | PUSH1 0x00 | 0x00 | +| 7F | PUSH2 0x009d | 0x9D 0x00 | +| 82 | PUSH1 0x03 | 0x03 0x9D 0x00 | | 84 | SLOAD | Storage[3] 0x9D 0x00 | -Esta é outra célula de armazenamento, que não poderia encontrar em nenhuma transação, portanto, é mais difícil saber o que significa. O código abaixo deixará isso mais claro. +Esta é outra célula de armazenamento, uma que não consegui encontrar em nenhuma transação, então é mais difícil saber o que significa. O código abaixo tornará isso mais claro. -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------------------------------------- | ------------------------------- | +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | 85 | PUSH20 0xffffffffffffffffffffffffffffffffffffffff | 0xff....ff Storage[3] 0x9D 0x00 | -| 9A | AND | Storage[3]-as-address 0x9D 0x00 | +| 9A | AND | Storage[3]-como-endereço 0x9D 0x00 | -Esses opcodes truncam o valor que lemos do Armazenamento[3] para 160 bits, o tamanho de um endereço Ethereum. +Esses códigos de operação truncam o valor que lemos de Storage[3] para 160 bits, o comprimento de um endereço Ethereum. -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ------------------------------- | -| 9B | SWAP1 | 0x9D Storage[3]-as-address 0x00 | -| 9C | JUMP | Storage[3]-as-address 0x00 | +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | -------------------------------------------------------------------------------------- | +| 9B | SWAP1 | 0x9D Storage[3]-como-endereço 0x00 | +| 9C | JUMP | Storage[3]-como-endereço 0x00 | -Este salto é supérfluo, pois estamos indo para o próximo opcode. Esse código não é tão eficiente em relação ao consumo de gás quanto ele poderia ser. +Este salto é supérfluo, já que estamos indo para o próximo código de operação. Este código não é tão eficiente em termos de gás quanto poderia ser. -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ------------------------------- | -| 9D | JUMPDEST | Storage[3]-as-address 0x00 | -| 9E | SWAP1 | 0x00 Storage[3]-as-address | -| 9F | POP | Storage[3]-as-address | -| A0 | PUSH1 0x40 | 0x40 Storage[3]-as-address | -| A2 | MLOAD | Mem[0x40] Storage[3]-as-address | - -Bem no início do código, definimos Mem[0x40] como 0x80. Se procurarmos 0x40 posteriormente, veremos que nós não o alteramos - então podemos assumir que é 0x80. - -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ------------------------------------------------- | -| A3 | CALLDATASIZE | CALLDATASIZE 0x80 Storage[3]-as-address | -| A4 | PUSH1 0x00 | 0x00 CALLDATASIZE 0x80 Storage[3]-as-address | -| A6 | DUP3 | 0x80 0x00 CALLDATASIZE 0x80 Storage[3]-as-address | -| A7 | CALLDATACOPY | 0x80 Storage[3]-as-address | - -Copie todos os dados da chamada para a memória, começando por 0x80. - -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | -------------------------------------------------------------------------------- | -| A8 | PUSH1 0x00 | 0x00 0x80 Storage[3]-as-address | -| AA | DUP1 | 0x00 0x00 0x80 Storage[3]-as-address | -| AB | CALLDATASIZE | CALLDATASIZE 0x00 0x00 0x80 Storage[3]-as-address | -| AC | DUP4 | 0x80 CALLDATASIZE 0x00 0x00 0x80 Storage[3]-as-address | -| AD | DUP6 | Storage[3]-as-address 0x80 CALLDATASIZE 0x00 0x00 0x80 Storage[3]-as-address | -| AE | GAS | GAS Storage[3]-as-address 0x80 CALLDATASIZE 0x00 0x00 0x80 Storage[3]-as-address | -| AF | DELEGATE_CALL | | - -Agora as coisas estão muito mais claras. Este contrato pode atuar como um [proxy](https://blog.openzeppelin.com/proxy-patterns/), chamando o endereço no Armazenamento[3] para fazer o trabalho real. `DELEGATE_CALL` chama um contrato separado, mas permanece no mesmo armazenamento. Isto significa que o contrato delegado, aquele para o qual somos proxy, acessa o mesmo espaço de armazenamento. Os parâmetros para a chamada são: - -- _Gas_: Todo o gas restante -- _Endereço chamado_: Armazenamento[3] como endereço -- _Dados da chamada_: Os bytes CALLDATASIZE começando em 0x80, que é onde colocamos os dados originais da chamada -- _Dados de retorno_: Nenhum (0x00 - 0x00) Nós vamos obter os dados de retorno por outros meios (veja abaixo) - -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | --------------------------------------------------------------------------------------------- | -| B0 | RETURNDATASIZE | RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | -| B1 | DUP1 | RETURNDATASIZE RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | -| B2 | PUSH1 0x00 | 0x00 RETURNDATASIZE RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | -| B4 | DUP5 | 0x80 0x00 RETURNDATASIZE RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | -| B5 | RETURNDATACOPY | RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ | +| 9D | JUMPDEST | Storage[3]-como-endereço 0x00 | +| 9E | SWAP1 | 0x00 Storage[3]-como-endereço | +| 9F | POP | Storage[3]-como-endereço | +| A0 | PUSH1 0x40 | 0x40 Storage[3]-como-endereço | +| A2 | MLOAD | Mem[0x40] Storage[3]-como-endereço | + +Bem no início do código, definimos Mem[0x40] como 0x80. Se procurarmos por 0x40 mais tarde, veremos que não o alteramos - então podemos assumir que é 0x80. + +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | -------------------------------------------------------------------------------------------------------- | +| A3 | CALLDATASIZE | CALLDATASIZE 0x80 Storage[3]-como-endereço | +| A4 | PUSH1 0x00 | 0x00 CALLDATASIZE 0x80 Storage[3]-como-endereço | +| A6 | DUP3 | 0x80 0x00 CALLDATASIZE 0x80 Storage[3]-como-endereço | +| A7 | CALLDATACOPY | 0x80 Storage[3]-como-endereço | + +Copie todos os dados da chamada para a memória, começando em 0x80. + +| Deslocamento | Código de Operação | Pilha | +| -----------: | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| A8 | PUSH1 0x00 | 0x00 0x80 Storage[3]-como-endereço | +| AA | DUP1 | 0x00 0x00 0x80 Storage[3]-como-endereço | +| AB | CALLDATASIZE | CALLDATASIZE 0x00 0x00 0x80 Storage[3]-como-endereço | +| AC | DUP4 | 0x80 CALLDATASIZE 0x00 0x00 0x80 Storage[3]-como-endereço | +| AD | DUP6 | Storage[3]-como-endereço 0x80 CALLDATASIZE 0x00 0x00 0x80 Storage[3]-como-endereço | +| AE | GAS | GAS Storage[3]-como-endereço 0x80 CALLDATASIZE 0x00 0x00 0x80 Storage[3]-como-endereço | +| AF | DELEGATE_CALL | | + +Agora as coisas estão muito mais claras. Este contrato pode atuar como um [proxy](https://blog.openzeppelin.com/proxy-patterns/), chamando o endereço em Storage[3] para fazer o trabalho real. `DELEGATE_CALL` chama um contrato separado, mas permanece no mesmo armazenamento. Isso significa que o contrato delegado, para o qual somos um proxy, acessa o mesmo espaço de armazenamento. Os parâmetros para a chamada são: + +- _Gás_: todo o gás restante +- _Endereço chamado_: Storage[3]-como-endereço +- _Dados de chamada_: Os bytes CALLDATASIZE começando em 0x80, que é onde colocamos os dados de chamada originais +- _Dados de retorno_: Nenhum (0x00 - 0x00) Obteremos os dados de retorno por outros meios (veja abaixo) + +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| B0 | RETURNDATASIZE | RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | +| B1 | DUP1 | RETURNDATASIZE RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | +| B2 | PUSH1 0x00 | 0x00 RETURNDATASIZE RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | +| B4 | DUP5 | 0x80 0x00 RETURNDATASIZE RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | +| B5 | RETURNDATACOPY | RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | Aqui copiamos todos os dados de retorno para o buffer de memória começando em 0x80. -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ---------------------------------------------------------------------------------------------------------------------------- | -| B6 | DUP2 | (((call success/failure))) RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | -| B7 | DUP1 | (((call success/failure))) (((call success/failure))) RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | -| B8 | ISZERO | (((did the call fail))) (((call success/failure))) RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | -| B9 | PUSH2 0x00c0 | 0xC0 (((did the call fail))) (((call success/failure))) RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | -| BC | JUMPI | (((call success/failure))) RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | -| BD | DUP2 | RETURNDATASIZE (((call success/failure))) RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | -| BE | DUP5 | 0x80 RETURNDATASIZE (((call success/failure))) RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | -| BF | RETURN | | +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| B6 | DUP2 | (((sucesso/falha da chamada))) RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | +| B7 | DUP1 | (((sucesso/falha da chamada))) (((sucesso/falha da chamada))) RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | +| B8 | ISZERO | (((a chamada falhou))) (((sucesso/falha da chamada))) RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | +| B9 | PUSH2 0x00c0 | 0xC0 (((a chamada falhou))) (((sucesso/falha da chamada))) RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | +| BC | JUMPI | (((sucesso/falha da chamada))) RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | +| BD | DUP2 | RETURNDATASIZE (((sucesso/falha da chamada))) RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | +| BE | DUP5 | 0x80 RETURNDATASIZE (((sucesso/falha da chamada))) RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | +| BF | RETURN | | -Então, após a chamada, nós copiamos os dados de retorno para o buffer 0x80 - 0x80+RETURNDATASIZE e, se a chamada for bem-sucedida, nós então fazemos o `RETURN` com exatamente este buffer. +Então, após a chamada, copiamos os dados de retorno para o buffer 0x80 - 0x80+RETURNDATASIZE e, se a chamada for bem-sucedida, fazemos um `RETURN` com exatamente esse buffer. -### DELEGATECALL falhou {#delegatecall-failed} +### DELEGATECALL Falhou {#delegatecall-failed} -Se chegarmos aqui, para 0xC0, significa que o contrato que chamamos foi revertido. Como somos apenas um proxy para esse contrato, queremos retornar os mesmos dados e também reverter. +Se chegarmos aqui, em 0xC0, significa que o contrato que chamamos reverteu. Como somos apenas um proxy para esse contrato, queremos retornar os mesmos dados e também reverter. -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ------------------------------------------------------------------------------------------------------------------- | -| C0 | JUMPDEST | (((call success/failure))) RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | -| C1 | DUP2 | RETURNDATASIZE (((call success/failure))) RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | -| C2 | DUP5 | 0x80 RETURNDATASIZE (((call success/failure))) RETURNDATASIZE (((call success/failure))) 0x80 Storage[3]-as-address | -| C3 | REVERT | | +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| C0 | JUMPDEST | (((sucesso/falha da chamada))) RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | +| C1 | DUP2 | RETURNDATASIZE (((sucesso/falha da chamada))) RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | +| C2 | DUP5 | 0x80 RETURNDATASIZE (((sucesso/falha da chamada))) RETURNDATASIZE (((sucesso/falha da chamada))) 0x80 Storage[3]-como-endereço | +| C3 | REVERT | | -Portanto, fazemos o `REVERT` com o mesmo buffer que usamos para o `RETURN` anteriormente: 0x80 - 0x80+RETURNDATASIZE +Portanto, fazemos `REVERT` com o mesmo buffer que usamos para `RETURN` anteriormente: 0x80 - 0x80+RETURNDATASIZE -![Fluxograma de chamada ao proxy](flowchart-proxy.png) +![Fluxograma de chamada para proxy](flowchart-proxy.png) -## Chamadas da ABI {#abi-calls} +## Chamadas ABI {#abi-calls} -Se o tamanho dos dados da chamada for quatro bytes ou mais, pode ser uma chamada ABI válida. +Se o tamanho dos dados da chamada for de quatro bytes ou mais, pode ser uma chamada ABI válida. -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ------------------------------------------------- | -| D | PUSH1 0x00 | 0x00 | -| F | CALLDATALOAD | (((First word (256 bits) of the call data))) | -| 10 | PUSH1 0xe0 | 0xE0 (((First word (256 bits) of the call data))) | -| 12 | SHR | (((first 32 bits (4 bytes) of the call data))) | +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | +| D | PUSH1 0x00 | 0x00 | +| F | CALLDATALOAD | (((Primeira palavra (256 bits) dos dados da chamada))) | +| 10 | PUSH1 0xe0 | 0xE0 (((Primeira palavra (256 bits) dos dados da chamada))) | +| 12 | SHR | (((primeiros 32 bits (4 bytes) dos dados de chamada))) | -O Etherscan nos conta que `1C` é um opcode desconhecido, porque [ele foi adicionado depois que o Etherscan escreveu essa funcionalidade](https://eips.ethereum.org/EIPS/eip-145) e eles não o atualizaram. An [up to date opcode table](https://github.com/wolflo/evm-opcodes) shows us that this is shift right +O Etherscan nos diz que `1C` é um código de operação desconhecido, porque [foi adicionado depois que o Etherscan escreveu este recurso](https://eips.ethereum.org/EIPS/eip-145) e eles não o atualizaram. Uma [tabela de códigos de operação atualizada](https://github.com/wolflo/evm-opcodes) nos mostra que isso é um deslocamento para a direita -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | -------------------------------------------------------------------------------------------------------- | -| 13 | DUP1 | (((first 32 bits (4 bytes) of the call data))) (((first 32 bits (4 bytes) of the call data))) | -| 14 | PUSH4 0x3cd8045e | 0x3CD8045E (((first 32 bits (4 bytes) of the call data))) (((first 32 bits (4 bytes) of the call data))) | -| 19 | GT | 0x3CD8045E>first-32-bits-of-the-call-data (((first 32 bits (4 bytes) of the call data))) | -| 1A | PUSH2 0x0043 | 0x43 0x3CD8045E>first-32-bits-of-the-call-data (((first 32 bits (4 bytes) of the call data))) | -| 1D | JUMPI | (((first 32 bits (4 bytes) of the call data))) | +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 13 | DUP1 | (((primeiros 32 bits (4 bytes) dos dados de chamada))) (((primeiros 32 bits (4 bytes) dos dados de chamada))) | +| 14 | PUSH4 0x3cd8045e | 0x3CD8045E (((primeiros 32 bits (4 bytes) dos dados de chamada))) (((primeiros 32 bits (4 bytes) dos dados de chamada))) | +| 19 | GT | 0x3CD8045E>primeiros-32-bits-dos-dados-de-chamada (((primeiros 32 bits (4 bytes) dos dados de chamada))) | +| 1A | PUSH2 0x0043 | 0x43 0x3CD8045E>primeiros-32-bits-dos-dados-de-chamada (((primeiros 32 bits (4 bytes) dos dados de chamada))) | +| 1D | JUMPI | (((primeiros 32 bits (4 bytes) dos dados de chamada))) | -Ao dividir os testes de correspondência da assinatura do método em dois, dessa forma, economiza metade dos testes, em média. O código que segue imediatamente e o código em 0x43 seguem o mesmo padrão: `DUP1` os primeiros 32 bits dos dados da chamada, `PUSH4 (((method signature>`, executa `EQ` para verificar a igualdade e, então, fazer o `JUMPI` se a assinatura do método corresponder. Aqui estão as assinaturas de método, seus endereços e, se conhecido [a definição de método correspondente](https://www.4byte.directory/): +Dividir os testes de correspondência da assinatura do método em dois, dessa forma, economiza metade dos testes, em média. O código que se segue imediatamente e o código em 0x43 seguem o mesmo padrão: `DUP1` os primeiros 32 bits dos dados da chamada, `PUSH4 (((assinatura do método`, executa `EQ` para verificar a igualdade e, em seguida, `JUMPI` se a assinatura do método corresponder. Aqui estão as assinaturas do método, seus endereços e, se conhecida, [a definição do método correspondente](https://www.4byte.directory/): -| Método | Assinatura do método | Deslocamento por salto | -| -------------------------------------------------------------------------------------- | -------------------- | ---------------------- | -| [splitter()](https://www.4byte.directory/signatures/?bytes4_signature=0x3cd8045e) | 0x3cd8045e | 0x0103 | -| ??? | 0x81e580d3 | 0x0138 | -| [currentWindow()](https://www.4byte.directory/signatures/?bytes4_signature=0xba0bafb4) | 0xba0bafb4 | 0x0158 | -| ??? | 0x1f135823 | 0x00C4 | -| [merkleRoot()](https://www.4byte.directory/signatures/?bytes4_signature=0x2eb4a7ab) | 0x2eb4a7ab | 0x00ED | +| Método | Assinatura do método | Deslocamento para saltar | +| --------------------------------------------------------------------------------------------------------- | -------------------- | ------------------------ | +| [splitter()](https://www.4byte.directory/signatures/?bytes4_signature=0x3cd8045e) | 0x3cd8045e | 0x0103 | +| ??? | 0x81e580d3 | 0x0138 | +| [currentWindow()](https://www.4byte.directory/signatures/?bytes4_signature=0xba0bafb4) | 0xba0bafb4 | 0x0158 | +| ??? | 0x1f135823 | 0x00C4 | +| [merkleRoot()](https://www.4byte.directory/signatures/?bytes4_signature=0x2eb4a7ab) | 0x2eb4a7ab | 0x00ED | -Se nenhuma combinação for encontrada, o código pula para [o controlador do proxy em 0x7C](#the-handler-at-0x7c), na esperança de que o contrato para o qual somos um proxy tenha uma correspondência. +Se nenhuma correspondência for encontrada, o código salta para [o manipulador de proxy em 0x7C](#the-handler-at-0x7c), na esperança de que o contrato para o qual somos um proxy tenha uma correspondência. ![Fluxograma de chamadas ABI](flowchart-abi.png) ## splitter() {#splitter} | Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ----------------------------- | +| -----------: | ------------------ | ----------------------------- | | 103 | JUMPDEST | | | 104 | CALLVALUE | CALLVALUE | | 105 | DUP1 | CALLVALUE CALLVALUE | @@ -314,38 +312,38 @@ Se nenhuma combinação for encontrada, o código pula para [o controlador do pr | 10D | DUP1 | 0x00 0x00 CALLVALUE | | 10E | REVERT | | -A primeira coisa que esta função faz é verificar que a chamada não enviou nenhum ETH. Esta função não é [`payable`](https://solidity-by-example.org/payable/) pagável. Se alguém nos enviou ETH, isso deve ser um erro, e queremos fazer o `REVERT` para evitar ter esse ETH que eles não possam recuperá-lo. - -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------------------------------------- | --------------------------------------------------------------------------- | -| 10F | JUMPDEST | | -| 110 | POP | | -| 111 | PUSH1 0x03 | 0x03 | -| 113 | SLOAD | (((Storage[3] a.k.a the contract for which we are a proxy))) | -| 114 | PUSH1 0x40 | 0x40 (((Storage[3] a.k.a the contract for which we are a proxy))) | -| 116 | MLOAD | 0x80 (((Storage[3] a.k.a the contract for which we are a proxy))) | -| 117 | PUSH20 0xffffffffffffffffffffffffffffffffffffffff | 0xFF...FF 0x80 (((Storage[3] a.k.a the contract for which we are a proxy))) | -| 12C | SWAP1 | 0x80 0xFF...FF (((Storage[3] a.k.a the contract for which we are a proxy))) | -| 12D | SWAP2 | (((Storage[3] a.k.a the contract for which we are a proxy))) 0xFF...FF 0x80 | -| 12E | AND | ProxyAddr 0x80 | -| 12F | DUP2 | 0x80 ProxyAddr 0x80 | -| 130 | MSTORE | 0x80 | +A primeira coisa que esta função faz é verificar se a chamada não enviou nenhum ETH. Esta função não é [`payable`](https://solidity-by-example.org/payable/). Se alguém nos enviou ETH, deve ter sido um erro, e queremos fazer um `REVERT` para evitar que esse ETH fique onde eles não possam recuperá-lo. + +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 10F | JUMPDEST | | +| 110 | POP | | +| 111 | PUSH1 0x03 | 0x03 | +| 113 | SLOAD | (((Storage[3] ou seja, o contrato para o qual somos um proxy))) | +| 114 | PUSH1 0x40 | 0x40 (((Storage[3] ou seja, o contrato para o qual somos um proxy))) | +| 116 | MLOAD | 0x80 (((Storage[3] ou seja, o contrato para o qual somos um proxy))) | +| 117 | PUSH20 0xffffffffffffffffffffffffffffffffffffffff | 0xFF...FF 0x80 (((Storage[3] ou seja, o contrato para o qual somos um proxy))) | +| 12C | SWAP1 | 0x80 0xFF...FF (((Storage[3] ou seja, o contrato para o qual somos um proxy))) | +| 12D | SWAP2 | (((Storage[3] ou seja, o contrato para o qual somos um proxy))) 0xFF...FF 0x80 | +| 12E | AND | EndereçoProxy 0x80 | +| 12F | DUP2 | 0x80 EndereçoProxy 0x80 | +| 130 | MSTORE | 0x80 | E 0x80 agora contém o endereço do proxy | Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | --------- | +| -----------: | ------------------ | --------- | | 131 | PUSH1 0x20 | 0x20 0x80 | | 133 | ADD | 0xA0 | | 134 | PUSH2 0x00e4 | 0xE4 0xA0 | | 137 | JUMP | 0xA0 | -### O código E4 {#the-e4-code} +### O Código E4 {#the-e4-code} -Essa é a primeira vez que vemos essas linhas, mas elas são compartilhadas com outros métodos (veja abaixo). Então, vamos chamar o valor na pilha de X, e lembre-se que em `splitter()` o valor desse X é 0xA0. +Essa é a primeira vez que vemos essas linhas, mas elas são compartilhadas com outros métodos (veja abaixo). Então, vamos chamar o valor na pilha de X e apenas lembrar que em `splitter()` o valor desse X é 0xA0. | Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ----------- | +| -----------: | ------------------ | ----------- | | E4 | JUMPDEST | X | | E5 | PUSH1 0x40 | 0x40 X | | E7 | MLOAD | 0x80 X | @@ -355,30 +353,30 @@ Essa é a primeira vez que vemos essas linhas, mas elas são compartilhadas com | EB | SWAP1 | 0x80 X-0x80 | | EC | RETURN | | -Portanto, esse código recebe um ponteiro de memória no montante (X) e faz com que o contrato faça o `RETURN` com um buffer que é 0x80 - X. +Portanto, esse código recebe um ponteiro de memória na pilha (X) e faz com que o contrato retorne (`RETURN`) com um buffer que é 0x80 - X. -No caso do `splitter()`, isto retorna o endereço do qual somos um proxy. O `RETURN` devolve o buffer em 0x80-0x9F, que é onde escrevemos esses dados (offset 0x130 acima). +No caso do `splitter()`, isso retorna o endereço para o qual somos um proxy. `RETURN` retorna o buffer em 0x80-0x9F, que é onde escrevemos esses dados (deslocamento 0x130 acima). ## currentWindow() {#currentwindow} -O código nos deslocamentos 0x158-0x163 é idêntico ao que vimos em 0x103-0x10E em `splitter()` (que não seja o destino `JUMPI`), então sabemos que `currentWindow()` também não é `payable` (pagável). +O código nos deslocamentos 0x158-0x163 é idêntico ao que vimos em 0x103-0x10E em `splitter()` (além do destino de `JUMPI`), então sabemos que `currentWindow()` também não é `payable`. -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | -------------------- | -| 164 | JUMPDEST | | -| 165 | POP | | -| 166 | PUSH2 0x00da | 0xDA | -| 169 | PUSH1 0x01 | 0x01 0xDA | +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | ------------------------------------------------------------------------ | +| 164 | JUMPDEST | | +| 165 | POP | | +| 166 | PUSH2 0x00da | 0xDA | +| 169 | PUSH1 0x01 | 0x01 0xDA | | 16B | SLOAD | Storage[1] 0xDA | | 16C | DUP2 | 0xDA Storage[1] 0xDA | | 16D | JUMP | Storage[1] 0xDA | ### O código DA {#the-da-code} -Esse código também é compartilhado com outros métodos. Então, chamaremos o valor na pilha de Y e lembre-se de que em `currentWindow()` o valor desse Y é o Armazenamento[1]. +Esse código também é compartilhado com outros métodos. Então, chamaremos o valor na pilha de Y e lembre-se de que em `currentWindow()` o valor desse Y é Storage[1]. | Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ---------------- | +| -----------: | ------------------ | ---------------- | | DA | JUMPDEST | Y 0xDA | | DB | PUSH1 0x40 | 0x40 Y 0xDA | | DD | MLOAD | 0x80 Y 0xDA | @@ -386,107 +384,107 @@ Esse código também é compartilhado com outros métodos. Então, chamaremos o | DF | DUP2 | 0x80 Y 0x80 0xDA | | E0 | MSTORE | 0x80 0xDA | -Escreva Y em 0x80-0x9F. +Escreve Y em 0x80-0x9F. | Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | -------------- | +| -----------: | ------------------ | -------------- | | E1 | PUSH1 0x20 | 0x20 0x80 0xDA | | E3 | ADD | 0xA0 0xDA | -E o resto já está explicado conforme [acima](#the-e4-code). Portanto, salte para 0xDA, escreva no topo da pilha (Y) para 0x80-0x9F e retorne esse valor. No caso de `currentWindow()`, retorne o Armazenamento[1]. +E o resto já foi explicado [acima](#the-e4-code). Portanto, saltos para 0xDA escrevem o valor do topo da pilha (Y) em 0x80-0x9F e retornam esse valor. No caso de `currentWindow()`, ele retorna Storage[1]. ## merkleRoot() {#merkleroot} -O código nos deslocamentos 0xED-0xF8 é idêntico ao que vimos em 0x103-0x10E em `splitter()` (além do alvo `JUMPI`), então sabemos `merkleRoot()` também não é `payable`. +O código nos deslocamentos 0xED-0xF8 é idêntico ao que vimos em 0x103-0x10E em `splitter()` (além do destino de `JUMPI`), então sabemos que `merkleRoot()` também não é `payable`. -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | -------------------- | -| F9 | JUMPDEST | | -| FA | POP | | -| FB | PUSH2 0x00da | 0xDA | -| FE | PUSH1 0x00 | 0x00 0xDA | +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | ------------------------------------------------------------------------ | +| F9 | JUMPDEST | | +| FA | POP | | +| FB | PUSH2 0x00da | 0xDA | +| FE | PUSH1 0x00 | 0x00 0xDA | | 100 | SLOAD | Storage[0] 0xDA | | 101 | DUP2 | 0xDA Storage[0] 0xDA | | 102 | JUMP | Storage[0] 0xDA | -O que acontece após o salto [já descobrimos](#the-da-code). Portanto, `merkleRoot()` retorna o Armazenamento[0]. +O que acontece após o salto [já descobrimos](#the-da-code). Portanto, `merkleRoot()` retorna Storage[0]. ## 0x81e580d3 {#0x81e580d3} -O código nos deslocamentos 0x138-0x143 é idêntico ao que vimos em 0x103-0x10E em `splitter()` (além do alvo `JUMPI`), então sabemos que esta função também é não `payable`. - -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ------------------------------------------------------------ | -| 144 | JUMPDEST | | -| 145 | POP | | -| 146 | PUSH2 0x00da | 0xDA | -| 149 | PUSH2 0x0153 | 0x0153 0xDA | -| 14C | CALLDATASIZE | CALLDATASIZE 0x0153 0xDA | -| 14D | PUSH1 0x04 | 0x04 CALLDATASIZE 0x0153 0xDA | -| 14F | PUSH2 0x018f | 0x018F 0x04 CALLDATASIZE 0x0153 0xDA | -| 152 | JUMP | 0x04 CALLDATASIZE 0x0153 0xDA | -| 18F | JUMPDEST | 0x04 CALLDATASIZE 0x0153 0xDA | -| 190 | PUSH1 0x00 | 0x00 0x04 CALLDATASIZE 0x0153 0xDA | -| 192 | PUSH1 0x20 | 0x20 0x00 0x04 CALLDATASIZE 0x0153 0xDA | -| 194 | DUP3 | 0x04 0x20 0x00 0x04 CALLDATASIZE 0x0153 0xDA | -| 195 | DUP5 | CALLDATASIZE 0x04 0x20 0x00 0x04 CALLDATASIZE 0x0153 0xDA | -| 196 | SUB | CALLDATASIZE-4 0x20 0x00 0x04 CALLDATASIZE 0x0153 0xDA | -| 197 | SLT | CALLDATASIZE-4\<32 0x00 0x04 CALLDATASIZE 0x0153 0xDA | -| 198 | ISZERO | CALLDATASIZE-4>=32 0x00 0x04 CALLDATASIZE 0x0153 0xDA | -| 199 | PUSH2 0x01a0 | 0x01A0 CALLDATASIZE-4>=32 0x00 0x04 CALLDATASIZE 0x0153 0xDA | -| 19C | JUMPI | 0x00 0x04 CALLDATASIZE 0x0153 0xDA | - -Parece que esta função leva ao menos 32 bytes (uma palavra) de dados da chamada. +O código nos deslocamentos 0x138-0x143 é idêntico ao que vimos em 0x103-0x10E em `splitter()` (além do destino de `JUMPI`), então sabemos que esta função também não é `payable`. + +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | ------------------------------------------------------------------------------- | +| 144 | JUMPDEST | | +| 145 | POP | | +| 146 | PUSH2 0x00da | 0xDA | +| 149 | PUSH2 0x0153 | 0x0153 0xDA | +| 14C | CALLDATASIZE | CALLDATASIZE 0x0153 0xDA | +| 14D | PUSH1 0x04 | 0x04 CALLDATASIZE 0x0153 0xDA | +| 14F | PUSH2 0x018f | 0x018F 0x04 CALLDATASIZE 0x0153 0xDA | +| 152 | JUMP | 0x04 CALLDATASIZE 0x0153 0xDA | +| 18F | JUMPDEST | 0x04 CALLDATASIZE 0x0153 0xDA | +| 190 | PUSH1 0x00 | 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 192 | PUSH1 0x20 | 0x20 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 194 | DUP3 | 0x04 0x20 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 195 | DUP5 | CALLDATASIZE 0x04 0x20 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 196 | SUB | CALLDATASIZE-4 0x20 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 197 | SLT | CALLDATASIZE-4\<32 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 198 | ISZERO | CALLDATASIZE-4>=32 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 199 | PUSH2 0x01a0 | 0x01A0 CALLDATASIZE-4>=32 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 19C | JUMPI | 0x00 0x04 CALLDATASIZE 0x0153 0xDA | + +Parece que esta função leva pelo menos 32 bytes (uma palavra) de dados de chamada. | Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | -------------------------------------------- | +| -----------: | ------------------ | -------------------------------------------- | | 19D | DUP1 | 0x00 0x00 0x04 CALLDATASIZE 0x0153 0xDA | | 19E | DUP2 | 0x00 0x00 0x00 0x04 CALLDATASIZE 0x0153 0xDA | | 19F | REVERT | | Se não obtiver os dados da chamada, a transação é revertida sem nenhum dado de retorno. -Vamos ver o que acontece se a função _obtiver_ os dados de chamada necessários. +Vamos ver o que acontece se a função _receber_ os dados de chamada de que precisa. -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ---------------------------------------- | -| 1A0 | JUMPDEST | 0x00 0x04 CALLDATASIZE 0x0153 0xDA | -| 1A1 | POP | 0x04 CALLDATASIZE 0x0153 0xDA | +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | ----------------------------------------------------------- | +| 1A0 | JUMPDEST | 0x00 0x04 CALLDATASIZE 0x0153 0xDA | +| 1A1 | POP | 0x04 CALLDATASIZE 0x0153 0xDA | | 1A2 | CALLDATALOAD | calldataload(4) CALLDATASIZE 0x0153 0xDA | `calldataload(4)` é a primeira palavra dos dados da chamada _após_ a assinatura do método -| Deslocamento | Código de Operação | Pilha | -| ------------:| ------------------ | ---------------------------------------------------------------------------- | -| 1A3 | SWAP2 | 0x0153 CALLDATASIZE calldataload(4) 0xDA | -| 1A4 | SWAP1 | CALLDATASIZE 0x0153 calldataload(4) 0xDA | -| 1A5 | POP | 0x0153 calldataload(4) 0xDA | -| 1A6 | JUMP | calldataload(4) 0xDA | -| 153 | JUMPDEST | calldataload(4) 0xDA | -| 154 | PUSH2 0x016e | 0x016E calldataload(4) 0xDA | -| 157 | JUMP | calldataload(4) 0xDA | -| 16E | JUMPDEST | calldataload(4) 0xDA | -| 16F | PUSH1 0x04 | 0x04 calldataload(4) 0xDA | -| 171 | DUP2 | calldataload(4) 0x04 calldataload(4) 0xDA | -| 172 | DUP2 | 0x04 calldataload(4) 0x04 calldataload(4) 0xDA | -| 173 | SLOAD | Storage[4] calldataload(4) 0x04 calldataload(4) 0xDA | -| 174 | DUP2 | calldataload(4) Storage[4] calldataload(4) 0x04 calldataload(4) 0xDA | +| Deslocamento | Código de Operação | Pilha | +| -----------: | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1A3 | SWAP2 | 0x0153 CALLDATASIZE calldataload(4) 0xDA | +| 1A4 | SWAP1 | CALLDATASIZE 0x0153 calldataload(4) 0xDA | +| 1A5 | POP | 0x0153 calldataload(4) 0xDA | +| 1A6 | JUMP | calldataload(4) 0xDA | +| 153 | JUMPDEST | calldataload(4) 0xDA | +| 154 | PUSH2 0x016e | 0x016E calldataload(4) 0xDA | +| 157 | JUMP | calldataload(4) 0xDA | +| 16E | JUMPDEST | calldataload(4) 0xDA | +| 16F | PUSH1 0x04 | 0x04 calldataload(4) 0xDA | +| 171 | DUP2 | calldataload(4) 0x04 calldataload(4) 0xDA | +| 172 | DUP2 | 0x04 calldataload(4) 0x04 calldataload(4) 0xDA | +| 173 | SLOAD | Storage[4] calldataload(4) 0x04 calldataload(4) 0xDA | +| 174 | DUP2 | calldataload(4) Storage[4] calldataload(4) 0x04 calldataload(4) 0xDA | | 175 | LT | calldataload(4)\)`, e outro é `isClaimed()`, então parece como um contrato airdrop. Em vez de passar pelo restante opcode por opcode, podemos [tentar o descompilador](https://etherscan.io/bytecode-decompiler?a=0x2f81e57ff4f4d83b40a9f719fd892d8e806e0761), que produz resultados uteis para três funções deste contrato. A engenharia reversa dos outros é deixada como um exercício para o leitor. +Um dos métodos restantes é `claim()`, e outro é `isClaimed()`, então parece um contrato de airdrop. Em vez de passar pelo restante código de operação por código de operação, podemos [tentar o descompilador](https://etherscan.io/bytecode-decompiler?a=0x2f81e57ff4f4d83b40a9f719fd892d8e806e0761), que produz resultados úteis para três funções deste contrato. A engenharia reversa dos outros é deixada como um exercício para o leitor. ### scaleAmountByPercentage {#scaleamountbypercentage} @@ -592,13 +590,13 @@ def unknown8ffb5c97(uint256 _param1, uint256 _param2) payable: return (_param1 * _param2 / 100 * 10^6) ``` -O primeiro `require` testa que os dados da chamada tenham, além dos quatro bytes da assinatura da função, ao menos 64 bytes, suficientes para os dois parâmetros. Do contrário, obviamente, há algo errado. +O primeiro `require` testa que os dados da chamada tenham, além dos quatro bytes da assinatura da função, pelo menos 64 bytes, suficientes para os dois parâmetros. Do contrário, obviamente, há algo errado. -A instrução `if` da sentença parece verificar que `_param1` não é zero e que `_param1 * _param2` não é negativo. Provavelmente, isso é para evitar casos de desvios. +A instrução `if` parece verificar se `_param1` não é zero e se `_param1 * _param2` não é negativo. Provavelmente, isso é para evitar casos de wrap around (retorno). -Finalmente, a função retorna um valor em escala. +Finalmente, a função retorna um valor escalado. -### Reivindicação {#claim} +### claim {#claim} O código que o descompilador cria é complexo, e nem todo ele é relevante para nós. Vou pular algumas partes para focar nas linhas que acredito fornecerem informações úteis @@ -608,21 +606,21 @@ def unknown2e7ba6ef(uint256 _param1, uint256 _param2, uint256 _param3, array _pa require _param2 == addr(_param2) ... if currentWindow <= _param1: - revert with 0, 'cannot claim for a future window' + revert with 0, 'não é possível reivindicar para uma janela futura' ``` Vemos aqui duas coisas importantes: - `_param2`, embora esteja declarado como um `uint256`, é na verdade um endereço -- `_param1` é a janela que está sendo reivindicada, o qual tem de ser `currentWindow` ou a anterior. +- `_param1` é a janela que está sendo reivindicada, que tem que ser `currentWindow` ou anterior. ```python ... if stor5[_claimWindow][addr(_claimFor)]: - revert with 0, 'Account already claimed the given window' + revert with 0, 'A conta já reivindicou a janela fornecida' ``` -Ou seja, agora sabemos que Armazenamento[5] é uma matriz de janelas e endereços e se o endereço reivindicou a recompensa por essa janela. +Então, agora sabemos que Storage[5] é uma matriz de janelas e endereços, e se o endereço reivindicou a recompensa por essa janela. ```python ... @@ -639,10 +637,10 @@ Ou seja, agora sabemos que Armazenamento[5] é uma matriz de janelas e endereço s = sha3(mem[_66 + 32 len mem[_66]]) continue if unknown2eb4a7ab != s: - revert with 0, 'Invalid proof' + revert with 0, 'Prova inválida' ``` -Sabemos que `unknown2eb4a7ab` é na verdade a função `merkleRoot()`, então este código parece estar verificando um [prova de merkle](https://medium.com/crypto-0-nite/merkle-proofs-explained-6dd429623dc5). Isso significa que `_param4` é uma prova de merkle. +Sabemos que `unknown2eb4a7ab` é, na verdade, a função `merkleRoot()`, então este código parece estar verificando uma [prova de Merkle](https://medium.com/crypto-0-nite/merkle-proofs-explained-6dd429623dc5). Isso significa que `_param4` é uma prova de Merkle. ```python call addr(_param2) with: @@ -650,7 +648,7 @@ Sabemos que `unknown2eb4a7ab` é na verdade a função `merkleRoot()`, então es gas 30000 wei ``` -É assim que um contrato transfere seu próprio ETH para outro endereço (de contrato ou de propriedade externa). Ele o chama com um valor que é a quantidade a ser transferida. Logo, parece que isso é um airdrop do ETH. +É assim que um contrato transfere seu próprio ETH para outro endereço (de contrato ou de propriedade externa). Ele o chama com um valor que é a quantidade a ser transferida. Logo, parece que isso é um airdrop de ETH. ```python if not return_data.size: @@ -660,22 +658,22 @@ Sabemos que `unknown2eb4a7ab` é na verdade a função `merkleRoot()`, então es value unknown81e580d3[_param1] * _param3 / 100 * 10^6 wei ``` -As duas linhas mais abaixo nos dizem que o Armazenamento[2] também é um contrato que chamamos. Se nós [olharmos a transação do construtor](https://etherscan.io/tx/0xa1ea0549fb349eb7d3aff90e1d6ce7469fdfdcd59a2fd9b8d1f5e420c0d05b58#statechange), veremos que este contrato é o [0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2](https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2), um contrato de Ether encapsulado [cujo código-fonte foi carregado no Etherscan](https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code). +As duas linhas inferiores nos dizem que Storage[2] também é um contrato que chamamos. Se [olharmos para a transação do construtor](https://etherscan.io/tx/0xa1ea0549fb349eb7d3aff90e1d6ce7469fdfdcd59a2fd9b8d1f5e420c0d05b58#statechange) vemos que este contrato é [0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2](https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2), um contrato de Wrapped Ether [cujo código-fonte foi carregado no Etherscan](https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code). -Assim, parece que os contratos tentam enviar ETH para `_param2`. Se puder fazer isso, ótimo. Se não, ele tenta enviar [WETH](https://weth.tkn.eth.limo/). Se `_param2` for uma conta de propriedade externa (EOA), então ele sempre pode receber ETH, mas os contratos podem se recusar a receber ETH. No entanto, WETH é ERC-20 e os contratos não podem se recusar a aceitar isso. +Assim, parece que os contratos tentam enviar ETH para `_param2`. Se puder fazer isso, ótimo. Caso contrário, ele tenta enviar [WETH](https://weth.tkn.eth.limo/). Se `_param2` for uma conta de propriedade externa (EOA), então ela sempre pode receber ETH, mas os contratos podem se recusar a receber ETH. No entanto, WETH é ERC-20 e os contratos não podem se recusar a aceitar isso. ```python ... log 0xdbd5389f: addr(_param2), unknown81e580d3[_param1] * _param3 / 100 * 10^6, bool(ext_call.success) ``` -No final da função, nós vemos uma entrada de log sendo gerada. [Veja as entradas de log geradas](https://etherscan.io/address/0x2510c039cc3b061d79e564b38836da87e31b342f#events) e filtre pelo tópico que começa com `0xdbd5...`. Se nós [clicarmos em uma das transações que gerou tal entrada](https://etherscan.io/tx/0xe7d3b7e00f645af17dfbbd010478ef4af235896c65b6548def1fe95b3b7d2274), veremos que realmente parece uma reivindicação - a conta enviou uma mensagem para o contrato, que estamos fazendo engenharia reversa e, em troca, recebemos ETH. +No final da função, vemos uma entrada de log sendo gerada. [Veja as entradas de log geradas](https://etherscan.io/address/0x2510c039cc3b061d79e564b38836da87e31b342f#events) e filtre pelo tópico que começa com `0xdbd5...`. Se [clicarmos em uma das transações que gerou tal entrada](https://etherscan.io/tx/0xe7d3b7e00f645af17dfbbd010478ef4af235896c65b6548def1fe95b3b7d2274), veremos que realmente parece uma reivindicação - a conta enviou uma mensagem para o contrato do qual estamos fazendo engenharia reversa e, em troca, recebeu ETH. ![Uma transação de reivindicação](claim-tx.png) ### 1e7df9d3 {#1e7df9d3} -Esta função é muito semelhante à [`claim`](#claim) (reinvidicação) acima. Ela também verifica uma prova de merkle, que tenta transferir ETH para o primeiro e produz o mesmo tipo de entrada de log. +Esta função é muito semelhante a `claim` acima. Ela também verifica uma prova de Merkle, tenta transferir ETH para o primeiro e produz o mesmo tipo de entrada de log. ```python def unknown1e7df9d3(uint256 _param1, uint256 _param2, array _param3) payable: @@ -693,7 +691,7 @@ def unknown1e7df9d3(uint256 _param1, uint256 _param2, array _param3) payable: mem[mem[64] + 32] = s + sha3(mem[(32 * _param3.length) + 160 len mem[(32 * _param3.length) + 128]]) ... if unknown2eb4a7ab != s: - revert with 0, 'Invalid proof' + revert with 0, 'Prova inválida' ... call addr(_param1) with: value s wei @@ -708,7 +706,7 @@ def unknown1e7df9d3(uint256 _param1, uint256 _param2, array _param3) payable: log 0xdbd5389f: addr(_param1), s, bool(ext_call.success) ``` -A principal diferença é que o primeiro parâmetro, a janela para retirada, não está lá. Em vez disso, há um loop em todas as janelas que podem ser reivindicadas. +A principal diferença é que o primeiro parâmetro, a janela para retirada, não está lá. Em vez disso, há um loop sobre todas as janelas que podem ser reivindicadas. ```python idx = 0 @@ -737,8 +735,10 @@ A principal diferença é que o primeiro parâmetro, a janela para retirada, nã continue ``` -Portanto, parece uma variante da `claim` que reivindica todas as janelas. +Portanto, parece uma variante de `claim` que reivindica todas as janelas. ## Conclusão {#conclusion} -A esta altura, você já deveria saber como entender os contratos cujo código-fonte não está disponível, usando os opcodes ou (quando funciona) o descompilador. Como é evidente na extensão deste artigo, a engenharia reversa de um contrato não é trivial, mas em um sistema em que a segurança é essencial, é uma habilidade importante ser capaz de verificar se os contratos funcionam como prometido. +Até agora você já deve saber como entender contratos cujo código-fonte não está disponível, usando os códigos de operação ou (quando funciona) o descompilador. Como é evidente pela extensão deste artigo, a engenharia reversa de um contrato não é trivial, mas em um sistema onde a segurança é essencial, é uma habilidade importante ser capaz de verificar se os contratos funcionam como prometido. + +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). diff --git a/public/content/translations/pt-br/developers/tutorials/run-node-raspberry-pi/index.md b/public/content/translations/pt-br/developers/tutorials/run-node-raspberry-pi/index.md index 71efde63434..08a5523288e 100644 --- a/public/content/translations/pt-br/developers/tutorials/run-node-raspberry-pi/index.md +++ b/public/content/translations/pt-br/developers/tutorials/run-node-raspberry-pi/index.md @@ -1,12 +1,14 @@ --- -title: Como transformar o Raspberry Pi 4 em um nó apenas instalando o cartão MicroSD -description: Piscar seu Raspberry Pi 4, plugar em um cabo ethernet, conectar o disco SSD e ligar o dispositivo para transformar o Raspberry Pi 4 em um nó Ethereum completo + validador +title: "Execute um nó Ethereum em um Raspberry Pi 4" +description: "Flasheie seu Raspberry Pi 4, conecte um cabo de ethernet, conecte o disco SSD e ligue o dispositivo para transformar o Raspberry Pi 4 em um nó Ethereum completo + validador" author: "EthereumOnArm" tags: - - "clientes" - - "camada de execução" - - "camada de consenso" - - "nós" + [ + "clientes", + "camada de execução", + "camada de consenso", + "nós" + ] lang: pt-br skill: intermediate published: 2022-06-10 @@ -14,34 +16,34 @@ source: Ethereum on ARM sourceUrl: https://ethereum-on-arm-documentation.readthedocs.io/en/latest/ --- -**A Ethereum on Arm é uma imagem personalizada de Linux que pode transformar um Raspberry Pi em um nó Ethereum.** +**O Ethereum on Arm é uma imagem Linux personalizada que pode transformar um Raspberry Pi em um nó Ethereum.** -Para usar Ethereum on Arm para transformar um Raspberry Pi em um nó Ethereum, recomenda-se o seguinte hardware: +Para usar o Ethereum on Arm para transformar um Raspberry Pi em um nó Ethereum, o seguinte hardware é recomendado: -- Raspberry 4 (modelo B 8 GB), placa mãe Odroid M1 ou Rock 5B (8 GB/16 GB RAM) -- Cartão MicroSD (mínimo 16 GB Classe 10) -- 2 TB SSD minimum USB 3.0 disk ou um SSD com USB para SATA case. +- Placa Raspberry 4 (modelo B 8GB), Odroid M1 ou Rock 5B (8GB/16GB de RAM) +- Cartão MicroSD (mínimo de 16 GB Classe 10) +- Disco SSD de no mínimo 2 TB com USB 3.0 ou um SSD com um case USB para SATA. - Fonte de alimentação -- Cabo da Ethernet +- Cabo de Ethernet - Encaminhamento de porta (consulte os clientes para obter mais informações) -- Uma case com dissipador de calor e cooler -- Teclado USB, Monitor e cabo HDMI (micro-HDMI) (Opcional) +- Um case com dissipador de calor e ventoinha +- Teclado USB, monitor e cabo HDMI (micro-HDMI) (Opcional) -## Por que executar Ethereum no ARM? {#why-run-ethereum-on-arm} +## Por que executar o Ethereum em ARM? {#why-run-ethereum-on-arm} -Os painéis ARM são computadores muito acessíveis, flexíveis e pequenos. Eles são boas escolhas para rodar os nós do Ethereum porque são baratos, configurados de forma que todos os recursos foquem em apenas um nó, tornando-os mais eficiente; eles consomem energia e são fisicamente menores, assim cabendo em qualquer casa. Também é muito fácil de rodar nós porque o cartão de memória do Raspberry Pi pode simplesmente ser ligado com uma imagem pré montada, sem precisar de download ou software de montagem. +As placas ARM são computadores pequenos, flexíveis e muito acessíveis. Elas são boas escolhas para executar nós Ethereum por serem baratas e configuráveis para que todos os seus recursos se concentrem apenas no nó, tornando-as eficientes. Consomem pouca energia e são fisicamente pequenas, cabendo discretamente em qualquer casa. Também é muito fácil iniciar nós, pois o MicroSD do Raspberry Pi pode simplesmente ser gravado com uma imagem pré-construída, sem a necessidade de baixar ou construir nenhum software. -## Como funciona? {#how-does-it-work} +## Como isso funciona? {#how-does-it-work} -O cartão de memória do Raspberry Pi já vem com uma imagem pré montada. Esta imagem contém tudo o que é necessário para executar um nó da Ethereum. Com um cartão flash, tudo o que o usuário precisa fazer é ligar o Raspberry Pi. Todos os processos necessários para executar o nó são iniciados automaticamente. Isso funciona porque o cartão de memória contém um sistema operacional baseado no Linux (OS) na qual os processos em nível de sistema rodam automaticamente e se tornam a unidade em um nó de Ethereum. +O cartão de memória do Raspberry Pi é gravado com uma imagem pré-construída. Esta imagem contém tudo o que é necessário para executar um nó da Ethereum. Com um cartão flasheado, tudo o que o usuário precisa fazer é ligar o Raspberry Pi. Todos os processos necessários para executar o nó são iniciados automaticamente. Isso funciona porque o cartão de memória contém um sistema operacional (SO) baseado em Linux, sobre o qual processos de nível de sistema são executados automaticamente que transformam a unidade em um nó Ethereum. -O Ethereum não pode rodar usando o popular Raspberry Pi Linux "Raspbian" porque o Raspbian ainda usa uma arquitetura de 32 bits que leva os Usuários do Ethereum a ter problemas com memória e o cliente de consenso não suporta binários de 32-bits. Para superar isso, a Ethereum on Arm migrou para um OS nativo de 64 bits chamado "Armbian". +O Ethereum não pode ser executado usando o popular SO Linux para Raspberry Pi "Raspbian", pois o Raspbian ainda usa uma arquitetura de 32 bits, o que leva os usuários do Ethereum a terem problemas de memória, e os clientes de consenso não suportam binários de 32 bits. Para superar isso, a equipe Ethereum on Arm migrou para um SO nativo de 64 bits chamado "Armbian". -**As imagens cuidam de todos os passos necessários**, desde configurar o ambiente e formatar o disco SSD até instalar e executar o “software” Ethereum, bem como iniciar a sincronização da blockchain. +**As imagens cuidam de todas as etapas necessárias**, desde a configuração do ambiente e a formatação do disco SSD até a instalação e execução do software Ethereum, bem como o início da sincronização da cadeia de blocos. -## Execução de acoplamento e clientes de consenso {#note-on-execution-and-consensus-clients} +## Nota sobre clientes de execução e de consenso {#note-on-execution-and-consensus-clients} -A imagem do Ethereum on Arm incluí uma execução pré construída e o cliente de consenso como serviços. Um nó Ethereum exige que ambos os clientes estejam sincronizados e executados. Você só precisa fazer o download, instalar a imagem flash e iniciar os serviços. A imagem é pré carregada com os seguintes clientes de execução: +A imagem do Ethereum on Arm inclui clientes de execução e de consenso pré-construídos como serviços. Um nó Ethereum exige que ambos os clientes estejam sincronizados e em execução. Você só precisa baixar e gravar a imagem e, em seguida, iniciar os serviços. A imagem é pré-carregada com os seguintes clientes de execução: - Geth - Nethermind @@ -54,61 +56,61 @@ e os seguintes clientes de consenso: - Prysm - Teku -Você deve escolher um de cada para executar - todos os clientes de execução são compatíveis com todos os clientes de consenso. Se você não selecionar explicitamente um cliente, o nó vai voltar aos seus padrões - Geth e Lighthouse - e executá-los automaticamente quando o quadro estiver ligado. Você precisa abrir a porta 30303 no seu roteador para o Geth Encontrar e conectar-se aos pares. +Você deve escolher um de cada para executar. Todos os clientes de execução são compatíveis com todos os clientes de consenso. Se você não selecionar explicitamente um cliente, o nó voltará aos padrões — Geth e Lighthouse — e os executará automaticamente quando a placa for ligada. Você precisa abrir a porta 30303 no seu roteador para que o Geth possa encontrar e se conectar aos pares. -## Baixando imagem {#downloading-the-image} +## Baixando a imagem {#downloading-the-image} -A imagem Ethereum Raspberry Pi 4 é uma imagem "plug and play" que vai instalar automaticamente e configurar ambos clientes de consenso e de execução, configurando-os para conversarem entre si e conectarem-se à rede Ethereum. Tudo o que o usuário precisa fazer é iniciar seus processos usando um simples comando. +A imagem Ethereum para Raspberry Pi 4 é uma imagem "plug and play" que instala e configura automaticamente os clientes de execução e de consenso, configurando-os para se comunicarem e se conectarem à rede Ethereum. Tudo o que o usuário precisa fazer é iniciar seus processos usando um comando simples. -Baixe a imagem do Raspberry Pi em [Ethereum no Arm](https://ethereumonarm-my.sharepoint.com/:u:/p/dlosada/Ec_VmUvr80VFjf3RYSU-NzkBmj2JOteDECj8Bibde929Gw?download=1) e verifique o hash SHA256: +Baixe a imagem do Raspberry Pi do [Ethereum on Arm](https://ethereumonarm-my.sharepoint.com/:u:/p/dlosada/Ec_VmUvr80VFjf3RYSU-NzkBmj2JOteDECj8Bibde929Gw?download=1) e verifique o hash SHA256: ```sh -# From directory containing the downloaded image +# Do diretório que contém a imagem baixada shasum -a 256 ethonarm_22.04.00.img.zip -# Hash should output: fb497e8f8a7388b62d6e1efbc406b9558bee7ef46ec7e53083630029c117444f +# A saída do hash deve ser: fb497e8f8a7388b62d6e1efbc406b9558bee7ef46ec7e53083630029c117444f ``` -Note que as imagens para as placas Rock 5B e Odroid M1 estão disponíveis no Ethereum-On-Arm [página de downloads](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/). +Observe que as imagens para as placas Rock 5B e Odroid M1 estão disponíveis na [página de downloads](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/quick-guide/download-and-install.html) do Ethereum-on-Arm. -## Instalando o MicroSD {#flashing-the-microsd} +## Gravando a imagem no MicroSD {#flashing-the-microsd} -O cartão MicroSD que vai ser usado no Raspberry Pi deve ser primeiro inserido em um desktop ou laptop para que seja instalado. Em seguida, os seguintes comandos do terminal instalarão a imagem baixada no cartão SD: +O cartão MicroSD que será usado para o Raspberry Pi deve primeiro ser inserido em um desktop ou laptop para que possa ser gravado. Em seguida, os seguintes comandos do terminal gravarão a imagem baixada no cartão SD: ```shell -# check the MicroSD card name +# verifique o nome do cartão MicroSD sudo fdisk -l >> sdxxx ``` -É muito importante se atentar ao nome correto pois o próximo comando inclui`dd` que apaga completamente o conteúdo existente do cartão antes de instalar a imagem dentro nele. Para continuar, navegue até o diretório que contém a imagem compactada: +É muito importante usar o nome correto, pois o próximo comando inclui `dd`, que apaga completamente o conteúdo existente do cartão antes de gravar a imagem nele. Para continuar, navegue até o diretório que contém a imagem compactada: ```shell -# unzip and flash image +# descompacte e grave a imagem unzip ethonarm_22.04.00.img.zip sudo dd bs=1M if=ethonarm_22.04.00.img of=/dev/ conv=fdatasync status=progress ``` -O cartão esta instalado, para que seja inserido no Raspberry Pi. +O cartão agora está gravado, então pode ser inserido no Raspberry Pi. ## Inicie o nó {#start-the-node} -Com o cartão SD inserido no Raspberry Pi, conecte o cabo Ethernet e SSD e então ligue o aparelho. O OS vai iniciar e automaticamente começará a executar as tarefas pré-configuradas que transformam o Raspberry Pi em um nó de Ethereum, incluindo a instalação e construção de um software cliente. Isso levará provavelmente 10-15 minutos. +Com o cartão SD inserido no Raspberry Pi, conecte o cabo de Ethernet e o SSD e, em seguida, ligue o dispositivo. O SO será inicializado e começará a executar automaticamente as tarefas pré-configuradas que transformam o Raspberry Pi em um nó Ethereum, incluindo a instalação e a criação do software do cliente. Isso provavelmente levará de 10 a 15 minutos. -Assim que tudo estiver instalado e configurado, faça login no dispositivo via uma conecção ssh ou usando o terminal diretamente se um monitor e teclado estiverem conectados à placa. Use a conta `ethereum` para logar, pois isso tem as permissões necessárioas para iniciar o nó. +Depois que tudo estiver instalado e configurado, faça login no dispositivo por meio de uma conexão ssh ou usando o terminal diretamente se um monitor e um teclado estiverem conectados à placa. Use a conta `ethereum` para fazer login, pois ela tem as permissões necessárias para iniciar o nó. ```shell Usuário: ethereum -Senha: Ethereum +Senha: ethereum ``` -O cliente de execução padrão, Geth, irá iniciar automaticamente. Você pode confirmar isso checando os logs usando o seguinte comando no terminal: +O cliente de execução padrão, Geth, iniciará automaticamente. Você pode confirmar isso verificando os logs com o seguinte comando de terminal: ```sh sudo journalctl -u geth -f ``` -O cliente de consenso precisa de ser iniciado explicitamente. Para fazer isso, primeiro abra a porta 9000 no seu roteador para que o farol possa encontrar e se conectar a pares. Então habilite e inicie o serviço de lighthouse: +O cliente de consenso precisa ser iniciado explicitamente. Para fazer isso, primeiro abra a porta 9000 no seu roteador para que o Lighthouse possa encontrar e se conectar aos pares. Em seguida, ative e inicie o serviço Lighthouse: ```sh sudo systemctl enable lighthouse-beacon @@ -121,15 +123,15 @@ Verifique o cliente usando os logs: sudo journalctl -u lighthouse-beacon ``` -Observe que o cliente de consenso irá sincronizar em alguns minutos porque ele usa a sincronização do ponto de controle. O cliente de execução vai levar mais tempo - Potencialmente algumas horas, e ele não vai executar até que o cliente de consenso termine de sincronizar (isso porque o cliente de execução precisa de um alvo para sincronizar, que o cliente de consenso sincronizado fornece). +Observe que o cliente de consenso será sincronizado em poucos minutos, pois ele usa a sincronização por checkpoint. O cliente de execução levará mais tempo (potencialmente várias horas) e não será iniciado até que o cliente de consenso termine a sincronização (isso ocorre porque o cliente de execução precisa de um alvo para sincronizar, que é fornecido pelo cliente de consenso já sincronizado). -Com os serviços Geth e Lighthouse sincronizados e rodando, seu Raspberry Pi agora é um nó de Ethereum! É mais comum interagir com a rede Ethereum utilizando o console Javascript do Geth, que pode ser anexado ao cliente Geth na porta 8545. Também é possível enviar comandos formatados como objetos JSON usando uma ferramenta de solicitação como o Curl. Veja mais em [Documentação Geth](https://geth.ethereum.org/). +Com os serviços Geth e Lighthouse em execução e sincronizados, seu Raspberry Pi agora é um nó Ethereum! É mais comum interagir com a rede Ethereum utilizando o console Javascript do Geth, que pode ser anexado ao cliente Geth na porta 8545. Também é possível enviar comandos formatados como objetos JSON usando uma ferramenta de solicitação como o Curl. Veja mais na [documentação do Geth](https://geth.ethereum.org/). -Geth é pré configurado para enviar relatórios pro painel Grafana, que pode ser visto no seu navegador. Usuários mais avançados podem querer usar este recurso para monitorar a saúde do seu nó navegando para `ipaddress.3000`, passing`usuário: admin` e `senha:ethereum`. +O Geth é pré-configurado para relatar métricas a um painel do Grafana que pode ser visualizado no navegador. Usuários mais avançados podem querer usar este recurso para monitorar a saúde de seu nó navegando para `ipaddress:3000`, passando `usuário: admin` e `senha: ethereum`. ## Validadores {#validators} -Um validador também pode ser opcionalmente adicionado ao cliente de consenso. O software validador permite seu nó de participar ativamente no consenso e fornece a rede com segurança criptoeconomica. Você será recompensado por este trabalho em ETH. Para rodar um validador, você precisa primeiro ter 32 ETH, que precisa ser depositado em um contrato de depósito. **Este é um termo de compromisso a longo prazo - ainda não é possível sacar este ETH!**. O depósito pode ser feito seguindo o passo a passo no [Launchpad](https://launchpad.ethereum.org/). Faça isso em um desktop/laptop, mas não gere chaves — isso pode ser feito diretamente no Raspberry Pi. +Um validador também pode ser adicionado opcionalmente ao cliente de consenso. O software do validador permite que seu nó participe ativamente do consenso e fornece segurança criptoeconômica à rede. Você é recompensado por este trabalho em ETH. Para executar um validador, você deve primeiro ter 32 ETH, que devem ser depositados no contrato de depósito. O depósito pode ser feito seguindo o guia passo a passo na [Plataforma de lançamento](https://launchpad.ethereum.org/). Faça isso em um desktop/laptop, mas não gere chaves — isso pode ser feito diretamente no Raspberry Pi. Abra um terminal no Raspberry Pi e execute o seguinte comando para gerar as chaves de depósito: @@ -139,32 +141,35 @@ sudo apt-get install staking-deposit-cli cd && deposit new-mnemonic --num_validators 1 ``` -Mantenha a frase mnemônica segura! O comando acima gerou dois arquivos no keystore: as chaves validadoras e um arquivo de dados de depósito. Os dados do depósito precisam ser carregados no launchpad, portanto, devem ser copiados do Raspberry Pi para o desktop/laptop. Isso pode ser feito usando uma conexão ssh ou qualquer outro método de copiar/colar. +(Ou baixe o [staking-deposit-cli](https://github.com/ethereum/staking-deposit-cli) para executar em uma máquina isolada (air-gapped) e execute o comando `deposit new-mnemnonic`) -Uma vez que o arquivo de dados do depósito estiver disponível no computador que executa o launchpad, ele pode ser arrastado e solto no `+` na tela do launchpad. Siga as instruções na tela para enviar uma transação para o contrato de depósito. +Mantenha a frase mnemônica segura! O comando acima gerou dois arquivos no keystore do nó: as chaves do validador e um arquivo de dados de depósito. Os dados de depósito precisam ser carregados na plataforma de lançamento, portanto, eles devem ser copiados do Raspberry Pi para o desktop/laptop. Isso pode ser feito usando uma conexão ssh ou qualquer outro método de copiar/colar. -De volta ao Raspberry Pi, um validador pode ser iniciado. Isso requer importar as chaves do validador, definir o endereço para coletar recompensas e, em seguida, iniciar o processo do validador pré-configurado. O exemplo abaixo é para o Lighthouse - instruções para outros clientes de consenso estão disponíveis na [Ethereum on Arm docs](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/): +Quando o arquivo de dados de depósito estiver disponível no computador que executa a plataforma de lançamento, ele poderá ser arrastado e solto no `+` na tela da plataforma de lançamento. Siga as instruções na tela para enviar uma transação para o contrato de depósito. + +De volta ao Raspberry Pi, um validador pode ser iniciado. Isso requer importar as chaves do validador, definir o endereço para coletar recompensas e, em seguida, iniciar o processo do validador pré-configurado. O exemplo abaixo é para o Lighthouse — as instruções para outros clientes de consenso estão disponíveis nos [documentos do Ethereum on Arm](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/): ```shell -# import the validator keys +# importe as chaves do validador lighthouse account validator import --directory=/home/ethereum/validator_keys -# set the reward address +# defina o endereço de recompensa sudo sed -i 's/' /etc/ethereum/lighthouse-validator.conf -# start the validator +# inicie o validador sudo systemctl start lighthouse-validator ``` -Parabéns, agora você tem um nó Ethereum completo e um validador rodando em um Raspberry Pi! +Parabéns, agora você tem um nó e validador Ethereum completos em execução em um Raspberry Pi! ## Mais detalhes {#more-details} -Esta página deu uma visão geral de como configurar um nó e validador Geth-Lighthouse usando Raspberry Pi. Instruções mais detalhadas estão disponíveis no [site Ethereum-on-Arm](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/). +Esta página deu uma visão geral de como configurar um nó e validador Geth-Lighthouse usando Raspberry Pi. Instruções mais detalhadas estão disponíveis no [site do Ethereum-on-Arm](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/index.html). -## Agradecemos o feedback {#feedback-appreciated} +## Agradecemos o seu feedback {#feedback-appreciated} -Sabemos que o Raspberry Pi tem uma enorme base de usuários, que pode ter um impacto muito positivo na saúde da rede Ethereum. Por favor, explore os detalhes deste tutorial, tente rodar em redes de teste, confira o Ethereum on Arm pelo GitHub, dê feedback, levante questões e pull requests e ajude a avançar a tecnologia e a documentação! +Sabemos que o Raspberry Pi tem uma enorme base de usuários, que pode ter um impacto muito positivo na saúde da rede Ethereum. +Por favor, aprofunde-se nos detalhes deste tutorial, tente executá-lo em redes de teste, confira o GitHub do Ethereum on Arm, dê seu feedback, relate problemas e envie pull requests para ajudar no avanço da tecnologia e da documentação! ## Referências {#references} @@ -178,7 +183,7 @@ Sabemos que o Raspberry Pi tem uma enorme base de usuários, que pode ter um imp 8. https://www.hyperledger.org/projects/besu 9. https://github.com/prysmaticlabs/prysm 10. https://lighthouse.sigmaprime.io -11. https://docs.ethswarm.org/ +11. https://ethersphere.github.io/swarm-home 12. https://raiden.network 13. https://ipfs.io 14. https://status.im diff --git a/public/content/translations/pt-br/developers/tutorials/scam-token-tricks/index.md b/public/content/translations/pt-br/developers/tutorials/scam-token-tricks/index.md new file mode 100644 index 00000000000..25354c9d166 --- /dev/null +++ b/public/content/translations/pt-br/developers/tutorials/scam-token-tricks/index.md @@ -0,0 +1,470 @@ +--- +title: "Alguns truques usados por tokens fraudulentos e como detectá-los" +description: "Neste tutorial, dissecamos um token fraudulento para ver alguns dos truques que os golpistas usam, como eles os implementam e como podemos detectá-los." +author: Ori Pomerantz +tags: + [ + "fraude", + "Solidity", + "erc-20", + "JavaScript", + "TypeScript" + ] +skill: intermediate +published: 2023-09-15 +lang: pt-br +--- + +Neste tutorial, dissecamos [um token fraudulento](https://etherscan.io/token/0xb047c8032b99841713b8e3872f06cf32beb27b82#code) para ver alguns dos truques que os golpistas usam e como eles os implementam. Ao final do tutorial, você terá uma visão mais abrangente dos contratos de token ERC-20, suas capacidades e por que o ceticismo é necessário. Então, olhamos para os eventos emitidos por esse token fraudulento e vemos como podemos identificar que ele não é legítimo automaticamente. + +## Tokens fraudulentos - o que são, por que as pessoas os criam e como evitá-los {#scam-tokens} + +Um dos usos mais comuns do Ethereum é a criação por um grupo de pessoas de um token negociável que, de certa forma, criam sua própria moeda. Entretanto, sempre onde há casos de uso legítimos que agregam valor, também haverá criminosos que tentam roubar esse valor. + +Você pode ler mais sobre este assunto [em outro lugar em ethereum.org](/guides/how-to-id-scam-tokens/) da perspectiva do usuário. Este tutorial foca em dissecar um token fraudulento para ver como é feito e como ele pode ser detectado. + +### Como eu sei que o wARB é uma fraude? {#warb-scam} + +O token que dissecamos é o [wARB](https://etherscan.io/token/0xb047c8032b99841713b8e3872f06cf32beb27b82#code), que finge ser equivalente ao [token ARB](https://etherscan.io/token/0xb50721bcf8d664c30412cfbc6cf7a15145234ad1) legítimo. + +A maneira mais fácil de saber qual é o token legítimo é olhar para a organização de origem, a [Arbitrum](https://arbitrum.foundation/). Os endereços legítimos são especificados [na documentação deles](https://docs.arbitrum.foundation/deployment-addresses#token). + +### Por que o código-fonte está disponível? {#why-source} + +Normalmente, esperaríamos que pessoas que tentam enganar outras fossem sigilosas e, de fato, muitos tokens fraudulentos não têm seu código disponível (por exemplo, [este](https://optimistic.etherscan.io/token/0x15992f382d8c46d667b10dc8456dc36651af1452#code) e [este](https://optimistic.etherscan.io/token/0x026b623eb4aada7de37ef25256854f9235207178#code)). + +No entanto, os tokens legítimos geralmente publicam seu código-fonte, então, para parecerem legítimos, os autores de tokens fraudulentos às vezes fazem o mesmo. O [wARB](https://etherscan.io/token/0xb047c8032b99841713b8e3872f06cf32beb27b82#code) é um desses tokens com código-fonte disponível, o que facilita o seu entendimento. + +Embora os implantadores de contratos possam escolher publicar ou não o código-fonte, eles _não podem_ publicar o código-fonte errado. O explorador de blocos compila o código-fonte fornecido de forma independente e, se não obtiver o mesmo bytecode exato, ele rejeita esse código-fonte. [Você pode ler mais sobre isso no site do Etherscan](https://etherscan.io/verifyContract). + +## Comparação com tokens ERC-20 legítimos {#compare-legit-erc20} + +Vamos comparar este token com tokens ERC-20 legítimos. Se você não está familiarizado com a forma como os tokens ERC-20 legítimos são normalmente escritos, [veja este tutorial](/developers/tutorials/erc20-annotated-code/). + +### Constantes para endereços privilegiados {#constants-for-privileged-addresses} + +Os contratos às vezes precisam de endereços privilegiados. Contratos projetados para uso a longo prazo permitem que alguns endereços privilegiados alterem esses endereços, por exemplo, para permitir o uso de um novo contrato multisig. Existem várias maneiras de fazer isso. + +O [contrato do token `HOP`](https://etherscan.io/address/0xc5102fe9359fd9a28f877a67e36b0f050d81a3cc#code) usa o padrão [`Ownable`](https://docs.openzeppelin.com/contracts/2.x/access-control#ownership-and-ownable). O endereço privilegiado é mantido no armazenamento, em um campo chamado `_owner` (veja o terceiro arquivo, `Ownable.sol`). + +```solidity +abstract contract Ownable is Context { + address private _owner; + . + . + . +} +``` + +O [contrato do token `ARB`](https://etherscan.io/address/0xad0c361ef902a7d9851ca7dcc85535da2d3c6fc7#code) não tem um endereço privilegiado diretamente. No entanto, ele não precisa de um. Ele está por trás de um [`proxy`](https://docs.openzeppelin.com/contracts/5.x/api/proxy) no [endereço `0xb50721bcf8d664c30412cfbc6cf7a15145234ad1`](https://etherscan.io/address/0xb50721bcf8d664c30412cfbc6cf7a15145234ad1#code). Esse contrato tem um endereço privilegiado (veja o quarto arquivo, `ERC1967Upgrade.sol`) que pode ser usado para atualizações. + +```solidity + /** + * @dev Armazena um novo endereço no slot de administrador do EIP1967. + */ + function _setAdmin(address newAdmin) private { + require(newAdmin != address(0), "ERC1967: new admin is the zero address"); + StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; + } +``` + +Em contraste, o contrato `wARB` tem um `contract_owner` codificado permanentemente. + +```solidity +contract WrappedArbitrum is Context, IERC20 { + . + . + . + address deployer = 0xB50721BCf8d664c30412Cfbc6cf7a15145234ad1; + address public contract_owner = 0xb40dE7b1beE84Ff2dc22B70a049A07A13a411A33; + . + . + . +} +``` + +[Este proprietário do contrato](https://etherscan.io/address/0xb40dE7b1beE84Ff2dc22B70a049A07A13a411A33) não é um contrato que poderia ser controlado por contas diferentes em momentos diferentes, mas uma [conta de propriedade externa](/developers/docs/accounts/#externally-owned-accounts-and-key-pairs). Isso significa que ele provavelmente foi projetado para uso a curto prazo por um indivíduo, em vez de uma solução de longo prazo para controlar um ERC-20 que permanecerá valioso. + +E, de fato, se olharmos no Etherscan, vemos que o golpista usou este contrato por apenas 12 horas ([primeira transação](https://etherscan.io/tx/0xf49136198c3f925fcb401870a669d43cecb537bde36eb8b41df77f06d5f6fbc2) até a [última transação](https://etherscan.io/tx/0xdfd6e717157354e64bbd5d6adf16761e5a5b3f914b1948d3545d39633244d47b)) durante o dia 19 de maio de 2023. + +### A função `_transfer` falsa {#the-fake-transfer-function} + +É padrão que as transferências reais aconteçam usando [uma função `_transfer` interna](/developers/tutorials/erc20-annotated-code/#the-_transfer-function-_transfer). + +No `wARB`, esta função parece quase legítima: + +```solidity + function _transfer(address sender, address recipient, uint256 amount) internal virtual{ + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); + _balances[recipient] = _balances[recipient].add(amount); + if (sender == contract_owner){ + sender = deployer; + } + emit Transfer(sender, recipient, amount); + } +``` + +A parte suspeita é: + +```solidity + if (sender == contract_owner){ + sender = deployer; + } + emit Transfer(sender, recipient, amount); +``` + +Se o proprietário do contrato envia tokens, por que o evento `Transfer` mostra que eles vêm do `deployer`? + +No entanto, há um problema mais importante. Quem chama esta função `_transfer`? Não pode ser chamada de fora, ela está marcada como `internal`. E o código que temos não inclui nenhuma chamada para `_transfer`. Claramente, está aqui como uma isca. + +```solidity + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _f_(_msgSender(), recipient, amount); + return true; + } + + function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { + _f_(sender, recipient, amount); + _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); + return true; + } +``` + +Quando olhamos para as funções que são chamadas para transferir tokens, `transfer` e `transferFrom`, vemos que elas chamam uma função completamente diferente, `_f_`. + +### A função `_f_` real {#the-real-f-function} + +```solidity + function _f_(address sender, address recipient, uint256 amount) internal _mod_(sender,recipient,amount) virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); + _balances[recipient] = _balances[recipient].add(amount); + if (sender == contract_owner){ + + sender = deployer; + } + emit Transfer(sender, recipient, amount); + } +``` + +Há duas bandeiras vermelhas em potencial nesta função. + +- O uso do [modificador de função](https://www.tutorialspoint.com/solidity/solidity_function_modifiers.htm) `_mod_`. No entanto, quando olhamos o código-fonte, vemos que `_mod_` é na verdade inofensivo. + + ```solidity + modifier _mod_(address sender, address recipient, uint256 amount){ + _; + } + ``` + +- O mesmo problema que vimos em `_transfer`, que é quando o `contract_owner` envia tokens, eles parecem vir do `deployer`. + +### A função de eventos falsos `dropNewTokens` {#the-fake-events-function-dropNewTokens} + +Agora chegamos a algo que parece uma fraude real. Editei um pouco a função para facilitar a leitura, mas é funcionalmente equivalente. + +```solidity +function dropNewTokens(address uPool, + address[] memory eReceiver, + uint256[] memory eAmounts) public auth() +``` + +Esta função tem o modificador `auth()`, o que significa que só pode ser chamada pelo proprietário do contrato. + +```solidity +modifier auth() { + require(msg.sender == contract_owner, "Not allowed to interact"); + _; +} +``` + +Essa restrição faz todo o sentido, porque não queremos que contas aleatórias distribuam tokens. No entanto, o resto da função é suspeito. + +```solidity +{ + for (uint256 i = 0; i < eReceiver.length; i++) { + emit Transfer(uPool, eReceiver[i], eAmounts[i]); + } +} +``` + +Uma função para transferir de uma conta de pool para uma matriz de receptores e uma matriz de valores faz todo o sentido. Existem muitos casos de uso em que você desejará distribuir tokens de uma única fonte para vários destinos, como folha de pagamento, airdrops, etc. É mais barato (em gás) fazer em uma única transação em vez de emitir várias transações, ou até mesmo chamar o ERC-20 várias vezes de um contrato diferente como parte da mesma transação. + +No entanto, `dropNewTokens` não faz isso. Ele emite [eventos `Transfer`](https://eips.ethereum.org/EIPS/eip-20#transfer-1), mas na verdade não transfere nenhum token. Não há razão legítima para confundir aplicações off-chain informando-as de uma transferência que não aconteceu de verdade. + +### A função de queima `Approve` {#the-burning-approve-function} + +Contratos ERC-20 devem ter [uma função `approve`](/developers/tutorials/erc20-annotated-code/#approve) para permissões e, de fato, nosso token fraudulento tem essa função, e ela está até correta. No entanto, como o Solidity descende do C, ele diferencia maiúsculas de minúsculas. "Approve" e "approve" são strings diferentes. + +Além disso, a funcionalidade não está relacionada a `approve`. + +```solidity + function Approve( + address[] memory holders) +``` + +Esta função é chamada com uma matriz de endereços para detentores do token. + +```solidity + public approver() { +``` + +O modificador `approver()` garante que apenas o `contract_owner` tenha permissão para chamar esta função (veja abaixo). + +```solidity + for (uint256 i = 0; i < holders.length; i++) { + uint256 amount = _balances[holders[i]]; + _beforeTokenTransfer(holders[i], 0x0000000000000000000000000000000000000001, amount); + _balances[holders[i]] = _balances[holders[i]].sub(amount, + "ERC20: burn amount exceeds balance"); + _balances[0x0000000000000000000000000000000000000001] = + _balances[0x0000000000000000000000000000000000000001].add(amount); + } + } + +``` + +Para cada endereço de detentor, a função move todo o saldo do detentor para o endereço `0x00...01`, efetivamente queimando-o (o `burn` real no padrão também altera o fornecimento total e transfere os tokens para `0x00...00`). Isso significa que o `contract_owner` pode remover os ativos de qualquer usuário. Isso não parece um recurso que você gostaria em um token de governança. + +### Problemas de qualidade do código {#code-quality-issues} + +Esses problemas de qualidade do código não _provam_ que este código é uma fraude, mas o tornam suspeito. Empresas organizadas como a Arbitrum geralmente não lançam códigos tão ruins. + +#### A função `mount` {#the-mount-function} + +Embora não seja especificado no [padrão](https://eips.ethereum.org/EIPS/eip-20), geralmente, a função que cria novos tokens é chamada de [`mint`](https://ethereum.org/el/developers/tutorials/erc20-annotated-code/#the-_mint-and-_burn-functions-_mint-and-_burn). + +Se olharmos no construtor do `wARB`, vemos que a função de cunhagem foi renomeada para `mount` por algum motivo e é chamada cinco vezes com um quinto do fornecimento inicial, em vez de uma vez para o valor total por eficiência. + +```solidity + constructor () public { + + _name = "Wrapped Arbitrum"; + _symbol = "wARB"; + _decimals = 18; + uint256 initialSupply = 1000000000000; + + mount(deployer, initialSupply*(10**18)/5); + mount(deployer, initialSupply*(10**18)/5); + mount(deployer, initialSupply*(10**18)/5); + mount(deployer, initialSupply*(10**18)/5); + mount(deployer, initialSupply*(10**18)/5); + } +``` + +A própria função `mount` também é suspeita. + +```solidity + function mount(address account, uint256 amount) public { + require(msg.sender == contract_owner, "ERC20: mint to the zero address"); +``` + +Olhando para o `require`, vemos que apenas o proprietário do contrato tem permissão para cunhar. Isso é legítimo. Mas a mensagem de erro deveria ser _apenas o proprietário tem permissão para cunhar_ ou algo parecido. Em vez disso, é o irrelevante _ERC20: cunhar para o endereço zero_. O teste correto para cunhagem para o endereço zero é `require(account != address(0), "")`, que o contrato nunca se preocupa em verificar. + +```solidity + _totalSupply = _totalSupply.add(amount); + _balances[contract_owner] = _balances[contract_owner].add(amount); + emit Transfer(address(0), account, amount); + } +``` + +Existem mais dois fatos suspeitos, diretamente relacionados à cunhagem: + +- Existe um parâmetro `account`, que é presumivelmente a conta que deve receber o valor cunhado. Mas o saldo que aumenta é na verdade o do `contract_owner`. + +- Embora o saldo aumentado pertença ao `contract_owner`, o evento emitido mostra uma transferência para `account`. + +### Por que tanto `auth` quanto `approver`? Por que o `mod` que não faz nada? {#why-both-autho-and-approver-why-the-mod-that-does-nothing} + +Este contrato contém três modificadores: `_mod_`, `auth` e `approver`. + +```solidity + modifier _mod_(address sender, address recipient, uint256 amount){ + _; + } +``` + +`_mod_` recebe três parâmetros e não faz nada com eles. Por que tê-lo? + +```solidity + modifier auth() { + require(msg.sender == contract_owner, "Not allowed to interact"); + _; + } + + modifier approver() { + require(msg.sender == contract_owner, "Not allowed to interact"); + _; + } +``` + +`auth` e `approver` fazem mais sentido, porque verificam se o contrato foi chamado pelo `contract_owner`. Esperaríamos que certas ações privilegiadas, como a cunhagem, fossem limitadas a essa conta. No entanto, qual é o sentido de ter duas funções separadas que fazem _precisamente a mesma coisa_? + +## O que podemos detectar automaticamente? {#what-can-we-detect-automatically} + +Podemos ver que o `wARB` é um token fraudulento olhando no Etherscan. No entanto, essa é uma solução centralizada. Em teoria, o Etherscan poderia ser subvertido ou hackeado. É melhor ser capaz de descobrir independentemente se um token é legítimo ou não. + +Existem alguns truques que podemos usar para identificar que um token ERC-20 é suspeito (seja uma fraude ou muito mal escrito), olhando para os eventos que eles emitem. + +## Eventos `Approval` suspeitos {#suspicious-approval-events} + +[Eventos de `Approval`](https://eips.ethereum.org/EIPS/eip-20#approval) devem ocorrer apenas com uma solicitação direta (em contraste com os [eventos de `Transfer`](https://eips.ethereum.org/EIPS/eip-20#transfer-1), que podem ocorrer como resultado de uma permissão). [Veja a documentação do Solidity](https://docs.soliditylang.org/en/v0.8.20/security-considerations.html#tx-origin) para uma explicação detalhada sobre este problema e por que as solicitações precisam ser diretas, em vez de mediadas por um contrato. + +Isso significa que os eventos `Approval` que aprovam o gasto de uma [conta de propriedade externa](/developers/docs/accounts/#types-of-account) devem vir de transações que se originam nessa conta e cujo destino é o contrato ERC-20. Qualquer outro tipo de aprovação de uma conta de propriedade externa é suspeito. + +Aqui está [um programa que identifica esse tipo de evento](https://github.com/qbzzt/20230915-scam-token-detection), usando [viem](https://viem.sh/) e [TypeScript](https://www.typescriptlang.org/docs/), uma variante do JavaScript com segurança de tipo. Para executá-lo: + +1. Copie `.env.example` para `.env`. +2. Edite `.env` para fornecer o URL para um nó da rede principal do Ethereum. +3. Execute `pnpm install` para instalar os pacotes necessários. +4. Execute `pnpm susApproval` para procurar aprovações suspeitas. + +Aqui está uma explicação linha por linha: + +```typescript +import { + Address, + TransactionReceipt, + createPublicClient, + http, + parseAbiItem, +} from "viem" +import { mainnet } from "viem/chains" +``` + +Importe definições de tipo, funções e a definição da cadeia de `viem`. + +```typescript +import { config } from "dotenv" +config() +``` + +Leia `.env` para obter o URL. + +```typescript +const client = createPublicClient({ + chain: mainnet, + transport: http(process.env.URL), +}) +``` + +Crie um cliente Viem. Só precisamos ler da blockchain, então este cliente não precisa de uma chave privada. + +```typescript +const testedAddress = "0xb047c8032b99841713b8e3872f06cf32beb27b82" +const fromBlock = 16859812n +const toBlock = 16873372n +``` + +O endereço do contrato ERC-20 suspeito e os blocos dentro dos quais procuraremos por eventos. Os provedores de nó normalmente limitam nossa capacidade de ler eventos porque a largura de banda pode ficar cara. Felizmente, o `wARB` não foi usado por um período de dezoito horas, então podemos procurar por todos os eventos (havia apenas 13 no total). + +```typescript +const approvalEvents = await client.getLogs({ + address: testedAddress, + fromBlock, + toBlock, + event: parseAbiItem( + "event Approval(address indexed _owner, address indexed _spender, uint256 _value)" + ), +}) +``` + +Esta é a maneira de solicitar informações de eventos ao Viem. Quando fornecemos a assinatura exata do evento, incluindo os nomes dos campos, ele analisa o evento para nós. + +```typescript +const isContract = async (addr: Address): boolean => + await client.getBytecode({ address: addr }) +``` + +Nosso algoritmo é aplicável apenas a contas de propriedade externa. Se houver algum bytecode retornado por `client.getBytecode`, isso significa que se trata de um contrato e devemos simplesmente pulá-lo. + +Se você nunca usou o TypeScript antes, a definição da função pode parecer um pouco estranha. Não apenas dizemos que o primeiro (e único) parâmetro é chamado `addr`, mas também que ele é do tipo `Address`. Da mesma forma, a parte `: boolean` diz ao TypeScript que o valor de retorno da função é um booleano. + +```typescript +const getEventTxn = async (ev: Event): TransactionReceipt => + await client.getTransactionReceipt({ hash: ev.transactionHash }) +``` + +Esta função obtém o recibo da transação de um evento. Precisamos do recibo para garantir que sabemos qual foi o destino da transação. + +```typescript +const suspiciousApprovalEvent = async (ev : Event) : (Event | null) => { +``` + +Esta é a função mais importante, a que realmente decide se um evento é suspeito ou não. O tipo de retorno, `(Event | null)`, informa ao TypeScript que esta função pode retornar um `Event` ou `null`. Retornamos `null` se o evento não for suspeito. + +```typescript +const owner = ev.args._owner +``` + +O Viem tem os nomes dos campos, então ele analisou o evento para nós. `_owner` é o proprietário dos tokens a serem gastos. + +```typescript +// Aprovações por contratos não são suspeitas +if (await isContract(owner)) return null +``` + +Se o proprietário for um contrato, presuma que essa aprovação não é suspeita. Para verificar se a aprovação de um contrato é suspeita ou não, precisaremos rastrear a execução completa da transação para ver se ela chegou ao contrato do proprietário e se esse contrato chamou o contrato ERC-20 diretamente. Isso consome muito mais recursos do que gostaríamos. + +```typescript +const txn = await getEventTxn(ev) +``` + +Se a aprovação vier de uma conta de propriedade externa, obtenha a transação que a causou. + +```typescript +// A aprovação é suspeita se vier de um proprietário de EOA que não é o `from` da transação +if (owner.toLowerCase() != txn.from.toLowerCase()) return ev +``` + +Não podemos simplesmente verificar a igualdade de strings porque os endereços são hexadecimais, então eles contêm letras. Às vezes, por exemplo em `txn.from`, essas letras são todas minúsculas. Em outros casos, como `ev.args._owner`, o endereço está em [maiúsculas e minúsculas misturadas para identificação de erros](https://eips.ethereum.org/EIPS/eip-55). + +Mas se a transação não for do proprietário, e esse proprietário for de propriedade externa, então temos uma transação suspeita. + +```typescript +// Também é suspeito se o destino da transação não for o contrato ERC-20 que estamos +// investigando +if (txn.to.toLowerCase() != testedAddress) return ev +``` + +Da mesma forma, se o endereço `to` da transação, o primeiro contrato chamado, não for o contrato ERC-20 sob investigação, então é suspeito. + +```typescript + // Se não houver motivo para suspeitar, retorne nulo. + return null +} +``` + +Se nenhuma das condições for verdadeira, o evento `Approval` não é suspeito. + +```typescript +const testPromises = approvalEvents.map((ev) => suspiciousApprovalEvent(ev)) +const testResults = (await Promise.all(testPromises)).filter((x) => x != null) + +console.log(testResults) +``` + +[Uma função `async`](https://www.w3schools.com/js/js_async.asp) retorna um objeto `Promise`. Com a sintaxe comum, `await x()`, esperamos que essa `Promise` seja cumprida antes de continuarmos o processamento. Isso é simples de programar e seguir, mas também é ineficiente. Enquanto esperamos que a `Promise` de um evento específico seja cumprida, já podemos começar a trabalhar no próximo evento. + +Aqui usamos [`map`](https://www.w3schools.com/jsref/jsref_map.asp) para criar uma matriz de objetos `Promise`. Em seguida, usamos [`Promise.all`](https://www.javascripttutorial.net/es6/javascript-promise-all/) para esperar que todas essas promessas sejam resolvidas. Em seguida, [`filter`](https://www.w3schools.com/jsref/jsref_filter.asp) esses resultados para remover os eventos não suspeitos. + +### Eventos `Transfer` suspeitos {#suspicious-transfer-events} + +Outra maneira possível de identificar tokens fraudulentos é ver se eles têm alguma transferência suspeita. Por exemplo, transferências de contas que não têm tantos tokens. Você pode ver [como implementar este teste](https://github.com/qbzzt/20230915-scam-token-detection/blob/main/susTransfer.ts), mas o `wARB` não tem este problema. + +## Conclusão {#conclusion} + +A detecção automatizada de fraudes ERC-20 sofre de [falsos negativos](https://en.wikipedia.org/wiki/False_positives_and_false_negatives#False_negative_error), porque uma fraude pode usar um contrato de token ERC-20 perfeitamente normal que simplesmente não representa nada real. Portanto, você deve sempre tentar _obter o endereço do token de uma fonte confiável_. + +A detecção automatizada pode ajudar em certos casos, como peças de DeFi, onde há muitos tokens e eles precisam ser tratados automaticamente. Mas como sempre [caveat emptor](https://www.investopedia.com/terms/c/caveatemptor.asp), faça sua própria pesquisa e incentive seus usuários a fazerem o mesmo. + +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). diff --git a/public/content/translations/pt-br/developers/tutorials/secret-state/index.md b/public/content/translations/pt-br/developers/tutorials/secret-state/index.md new file mode 100644 index 00000000000..8609bc79fed --- /dev/null +++ b/public/content/translations/pt-br/developers/tutorials/secret-state/index.md @@ -0,0 +1,740 @@ +--- +title: Usando conhecimento zero para um estado secreto +description: "Os jogos em cadeia são limitados porque não conseguem manter nenhuma informação oculta. Após ler este tutorial, o leitor será capaz de combinar provas de conhecimento zero e componentes de servidor para criar jogos verificáveis com um estado secreto, fora da cadeia, componente. A técnica para fazer isso será demonstrada com a criação de um jogo de campo minado." +author: Ori Pomerantz +tags: + [ + "servidor", + "fora da cadeia", + "centralizado", + "conhecimento zero", + "zokrates", + "mud" + ] +skill: advanced +lang: pt-br +published: 2025-03-15 +--- + +_Não há segredos na blockchain_. Tudo o que é publicado na cadeia de blocos é aberto para que todos leiam. Isso é necessário, porque a cadeia de blocos se baseia na capacidade de qualquer pessoa poder verificá-la. No entanto, os jogos geralmente dependem de um estado secreto. Por exemplo, o jogo de [campo minado](https://en.wikipedia.org/wiki/Minesweeper_\(video_game\)) não faz o menor sentido se você puder simplesmente acessar um explorador da cadeia de blocos e ver o mapa. + +A solução mais simples é usar um [componente de servidor](/developers/tutorials/server-components/) para manter o estado secreto. No entanto, a razão pela qual usamos a cadeia de blocos é para impedir que o desenvolvedor do jogo trapaceie. Precisamos garantir a honestidade do componente do servidor. O servidor pode fornecer um hash do estado e usar [provas de conhecimento zero](/zero-knowledge-proofs/#why-zero-knowledge-proofs-are-important) para provar que o estado usado para calcular o resultado de um movimento é o correto. + +Após ler este artigo, você saberá como criar este tipo de servidor que detém o estado secreto, um cliente para mostrar o estado e um componente em cadeia para comunicação entre os dois. As principais ferramentas que usaremos serão: + +| Ferramenta | Propósito | Verificado na versão | +| --------------------------------------------- | ---------------------------------------------------- | --------------------------------------: | +| [Zokrates](https://zokrates.github.io/) | Provas de conhecimento zero e sua verificação | 1.1.9 | +| [Typescript](https://www.typescriptlang.org/) | Linguagem de programação para o servidor e o cliente | 5.4.2 | +| [Node](https://nodejs.org/en) | Executando o servidor | 20.18.2 | +| [Viem](https://viem.sh/) | Comunicação com a cadeia de blocos | 2.9.20 | +| [MUD](https://mud.dev/) | Gerenciamento de dados em cadeia | 2.0.12 | +| [React](https://react.dev/) | Interface do usuário do cliente | 18.2.0 | +| [Vite](https://vitejs.dev/) | Servindo o código do cliente | 4.2.1 | + +## Exemplo de Campo Minado {#minesweeper} + +[Campo Minado](https://en.wikipedia.org/wiki/Minesweeper_\(video_game\)) é um jogo que inclui um mapa secreto com um campo minado. O jogador escolhe cavar em um local específico. Se esse local tiver uma mina, o jogo acaba. Caso contrário, o jogador obtém o número de minas nos oito quadrados ao redor daquele local. + +Esta aplicação é escrita usando [MUD](https://mud.dev/), uma estrutura que nos permite armazenar dados em cadeia usando um [banco de dados chave-valor](https://aws.amazon.com/nosql/key-value/) e sincronizar esses dados automaticamente com componentes fora da cadeia. Além da sincronização, o MUD facilita o controle de acesso e permite que outros usuários [estendam](https://mud.dev/guides/extending-a-world) nossa aplicação sem permissão. + +### Executando o exemplo de Campo Minado {#running-minesweeper-example} + +Para executar o exemplo do Campo Minado: + +1. Certifique-se de que você [tenha os pré-requisitos instalados](https://mud.dev/quickstart#prerequisites): [Node](https://mud.dev/quickstart#prerequisites), [Foundry](https://book.getfoundry.sh/getting-started/installation), [`git`](https://git-scm.com/downloads), [`pnpm`](https://git-scm.com/downloads) e [`mprocs`](https://github.com/pvolok/mprocs). + +2. Clone o repositório. + + ```sh copy + git clone https://github.com/qbzzt/20240901-secret-state.git + ``` + +3. Instale os pacotes. + + ```sh copy + cd 20240901-secret-state/ + pnpm install + npm install -g mprocs + ``` + + Se o Foundry foi instalado como parte do `pnpm install`, você precisa reiniciar o shell da linha de comando. + +4. Compile os contratos + + ```sh copy + cd packages/contracts + forge build + cd ../.. + ``` + +5. Inicie o programa (incluindo uma cadeia de blocos [anvil](https://book.getfoundry.sh/anvil/)) e aguarde. + + ```sh copy + mprocs + ``` + + Observe que a inicialização leva muito tempo. Para ver o progresso, primeiro use a seta para baixo para rolar até a guia _contracts_ para ver os contratos MUD sendo implantados. Quando você receber a mensagem _Waiting for file changes…_, os contratos serão implantados e o progresso adicional ocorrerá na guia _server_. Lá, você espera até receber a mensagem _Verifier address: 0x...._. + + Se esta etapa for bem-sucedida, você verá a tela `mprocs`, com os diferentes processos à esquerda e a saída do console para o processo atualmente selecionado à direita. + + ![A tela mprocs](./mprocs.png) + + Se houver um problema com `mprocs`, você pode executar os quatro processos manualmente, cada um em sua própria janela de linha de comando: + + - **Anvil** + + ```sh + cd packages/contracts + anvil --base-fee 0 --block-time 2 + ``` + + - **Contratos** + + ```sh + cd packages/contracts + pnpm mud dev-contracts --rpc http://127.0.0.1:8545 + ``` + + - **Servidor** + + ```sh + cd packages/server + pnpm start + ``` + + - **Cliente** + + ```sh + cd packages/client + pnpm run dev + ``` + +6. Agora você pode navegar para [o cliente](http://localhost:3000), clicar em **Novo Jogo** e começar a jogar. + +### Tabelas {#tables} + +Precisamos de [várias tabelas](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/mud.config.ts) em cadeia. + +- `Configuration`: esta tabela é um singleton, não tem chave e um único registro. É usada para manter informações de configuração do jogo: + - `height`: a altura de um campo minado + - `width`: a largura de um campo minado + - `numberOfBombs`: o número de bombas em cada campo minado + +- `VerifierAddress`: esta tabela também é um singleton. É usada para conter uma parte da configuração, o endereço do contrato do verificador (`verifier`). Poderíamos ter colocado essa informação na tabela `Configuration`, mas ela é definida por um componente diferente, o servidor, então é mais fácil colocá-la em uma tabela separada. + +- `PlayerGame`: a chave é o endereço do jogador. Os dados são: + + - `gameId`: valor de 32 bytes que é o hash do mapa em que o jogador está jogando (o identificador do jogo). + - `win`: um booleano que indica se o jogador ganhou o jogo. + - `lose`: um booleano que indica se o jogador perdeu o jogo. + - `digNumber`: o número de escavações bem-sucedidas no jogo. + +- `GamePlayer`: esta tabela contém o mapeamento inverso, do `gameId` para o endereço do jogador. + +- `Map`: a chave é uma tupla de três valores: + + - `gameId`: valor de 32 bytes que é o hash do mapa em que o jogador está jogando (o identificador do jogo). + - coordenada `x` + - coordenada `y` + + O valor é um único número. É 255 se uma bomba foi detectada. Caso contrário, é o número de bombas ao redor desse local mais um. Não podemos usar apenas o número de bombas, porque, por padrão, todo o armazenamento na EVM e todos os valores de linha no MUD são zero. Precisamos distinguir entre "o jogador ainda não cavou aqui" e "o jogador cavou aqui e descobriu que há zero bombas por perto". + +Além disso, a comunicação entre o cliente e o servidor ocorre por meio do componente em cadeia. Isso também é implementado usando tabelas. + +- `PendingGame`: solicitações não atendidas para iniciar um novo jogo. +- `PendingDig`: solicitações não atendidas para cavar em um local específico em um jogo específico. Esta é uma [tabela fora da cadeia](https://mud.dev/store/tables#types-of-tables), o que significa que não é gravada no armazenamento da EVM, é apenas legível fora da cadeia usando eventos. + +### Fluxos de execução e de dados {#execution-data-flows} + +Esses fluxos coordenam a execução entre o cliente, o componente em cadeia e o servidor. + +#### Inicialização {#initialization-flow} + +Quando você executa `mprocs`, estas etapas ocorrem: + +1. [`mprocs`](https://github.com/pvolok/mprocs) executa quatro componentes: + + - [Anvil](https://book.getfoundry.sh/anvil/), que executa uma cadeia de blocos local + - [Contracts](https://github.com/qbzzt/20240901-secret-state/tree/main/packages/contracts), que compila (se necessário) e implanta os contratos para o MUD + - [Client](https://github.com/qbzzt/20240901-secret-state/tree/main/packages/client), que executa o [Vite](https://vitejs.dev/) para servir a UI e o código do cliente para navegadores da web. + - [Server](https://github.com/qbzzt/20240901-secret-state/tree/main/packages/server), que executa as ações do servidor + +2. O pacote `contracts` implanta os contratos MUD e, em seguida, executa [o script `PostDeploy.s.sol`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/script/PostDeploy.s.sol). Este script define a configuração. O código do GitHub especifica [um campo minado de 10x5 com oito minas nele](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/script/PostDeploy.s.sol#L23). + +3. [O servidor](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts) começa por [configurar o MUD](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L6). Entre outras coisas, isso ativa a sincronização de dados, para que uma cópia das tabelas relevantes exista na memória do servidor. + +4. O servidor inscreve uma função para ser executada [quando a tabela `Configuration` muda](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L23). [Esta função](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L24-L168) é chamada depois que `PostDeploy.s.sol` é executado e modifica a tabela. + +5. Quando a função de inicialização do servidor tem a configuração, [ela chama `zkFunctions`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L34-L35) para inicializar [a parte de conhecimento zero do servidor](#using-zokrates-from-typescript). Isso não pode acontecer até que obtenhamos a configuração, porque as funções de conhecimento zero devem ter a largura e a altura do campo minado como constantes. + +6. Depois que a parte de conhecimento zero do servidor é inicializada, o próximo passo é [implantar o contrato de verificação de conhecimento zero na cadeia de blocos](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L42-L53) e definir o endereço do verificador no MUD. + +7. Finalmente, nos inscrevemos para atualizações para que vejamos quando um jogador solicita [iniciar um novo jogo](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L55-L71) ou [cavar em um jogo existente](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L73-L108). + +#### Novo jogo {#new-game-flow} + +Isto é o que acontece quando o jogador solicita um novo jogo. + +1. Se não houver nenhum jogo em andamento para este jogador, ou se houver um, mas com um gameId de zero, o cliente exibe um [botão de novo jogo](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L175). Quando o usuário pressiona este botão, o [React executa a função `newGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L96). + +2. [`newGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/mud/createSystemCalls.ts#L43-L46) é uma chamada `System`. No MUD, todas as chamadas são roteadas através do contrato `World` e, na maioria dos casos, você chama `__`. Nesse caso, a chamada é para `app__newGame`, que o MUD então roteia para [`newGame` em `GameSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L16-L22). + +3. A função em cadeia verifica se o jogador não tem um jogo em andamento e, se não houver, [adiciona a solicitação à tabela `PendingGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L21). + +4. O servidor detecta a alteração em `PendingGame` e [executa a função inscrita](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L55-L71). Essa função chama [`newGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L110-L114), que por sua vez chama [`createGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L116-L144). + +5. A primeira coisa que `createGame` faz é [criar um mapa aleatório com o número apropriado de minas](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L120-L135). Em seguida, ele chama [`makeMapBorders`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L147-L166) para criar um mapa com bordas em branco, o que é necessário para o Zokrates. Finalmente, `createGame` chama [`calculateMapHash`](#calculateMapHash) para obter o hash do mapa, que é usado como o ID do jogo. + +6. A função `newGame` adiciona o novo jogo a `gamesInProgress`. + +7. A última coisa que o servidor faz é chamar [`app__newGameResponse`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L38-L43), que está em cadeia. Esta função está em um `System` diferente, [`ServerSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol), para habilitar o controle de acesso. O controle de acesso é definido no [arquivo de configuração MUD](https://mud.dev/config), [`mud.config.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/mud.config.ts#L67-L72). + + A lista de acesso permite que apenas um único endereço chame o `System`. Isso restringe o acesso às funções do servidor a um único endereço, para que ninguém possa se passar pelo servidor. + +8. O componente em cadeia atualiza as tabelas relevantes: + + - Crie o jogo em `PlayerGame`. + - Defina o mapeamento reverso em `GamePlayer`. + - Remova a solicitação de `PendingGame`. + +9. O servidor identifica a alteração em `PendingGame`, mas não faz nada porque [`wantsGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L58-L60) é falso. + +10. No cliente, [`gameRecord`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L143-L148) é definido para a entrada `PlayerGame` para o endereço do jogador. Quando `PlayerGame` muda, `gameRecord` muda também. + +11. Se houver um valor em `gameRecord` e o jogo não tiver sido ganho ou perdido, o cliente [exibe o mapa](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L175-L190). + +#### Cavar {#dig-flow} + +1. O jogador [clica no botão da célula do mapa](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L188), que chama a [função `dig`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/mud/createSystemCalls.ts#L33-L36). Essa função chama [`dig` em cadeia](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L24-L32). + +2. O componente em cadeia [realiza uma série de verificações de sanidade](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L25-L30) e, se bem-sucedido, adiciona a solicitação de escavação a [`PendingDig`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L31). + +3. O servidor [detecta a alteração em `PendingDig`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L73). [Se for válido](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L75-L84), ele [chama o código de conhecimento zero](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L86-L95) (explicado abaixo) para gerar tanto o resultado quanto uma prova de que ele é válido. + +4. [O servidor](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L97-L107) chama [`digResponse`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L45-L64) em cadeia. + +5. `digResponse` faz duas coisas. Primeiro, ele verifica a [prova de conhecimento zero](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L47-L61). Então, se a prova for verificada, ele chama [`processDigResult`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L67-L86) para processar o resultado. + +6. `processDigResult` verifica se o jogo foi [perdido](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L76-L78) ou [ganho](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L83-L86) e [atualiza o `Map`, o mapa em cadeia](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L80). + +7. O cliente recebe as atualizações automaticamente e [atualiza o mapa exibido para o jogador](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L175-L190) e, se aplicável, informa ao jogador se é uma vitória ou uma derrota. + +## Usando Zokrates {#using-zokrates} + +Nos fluxos explicados acima, pulamos as partes de conhecimento zero, tratando-as como uma caixa preta. Agora vamos abri-la e ver como esse código é escrito. + +### Hashing do mapa {#hashing-map} + +Podemos usar [este código JavaScript](https://github.com/ZK-Plus/ICBC24_Tutorial_Compute-Offchain-Verify-onchain/tree/solutions/exercise) para implementar [Poseidon](https://www.poseidon-hash.info), a função de hash do Zokrates que usamos. No entanto, embora isso fosse mais rápido, também seria mais complicado do que simplesmente usar a função de hash do Zokrates para fazê-lo. Este é um tutorial e, portanto, o código é otimizado para simplicidade, não para desempenho. Portanto, precisamos de dois programas Zokrates diferentes, um para apenas calcular o hash de um mapa (`hash`) e outro para realmente criar uma prova de conhecimento zero do resultado da escavação em um local no mapa (`dig`). + +### A função de hash {#hash-function} + +Esta é a função que calcula o hash de um mapa. Vamos analisar este código linha por linha. + +``` +import "hashes/poseidon/poseidon.zok" as poseidon; +import "utils/pack/bool/pack128.zok" as pack128; +``` + +Essas duas linhas importam duas funções da [biblioteca padrão do Zokrates](https://zokrates.github.io/toolbox/stdlib.html). [A primeira função](https://github.com/Zokrates/ZoKrates/blob/latest/zokrates_stdlib/stdlib/hashes/poseidon/poseidon.zok) é um [hash Poseidon](https://www.poseidon-hash.info/). Ela recebe um array de elementos [`field`](https://zokrates.github.io/language/types.html#field) e retorna um `field`. + +O elemento de campo no Zokrates é normalmente menor que 256 bits, mas não por muito. Para simplificar o código, restringimos o mapa a até 512 bits e fazemos o hash de um array de quatro campos, e em cada campo usamos apenas 128 bits. [A função `pack128`](https://github.com/Zokrates/ZoKrates/blob/latest/zokrates_stdlib/stdlib/utils/pack/bool/pack128.zok) transforma um array de 128 bits em um `field` para este propósito. + +``` + def hashMap(bool[${width+2}][${height+2}] map) -> field { +``` + +Esta linha inicia uma definição de função. `hashMap` recebe um único parâmetro chamado `map`, um array `bool`(eano) bidimensional. O tamanho do mapa é `width+2` por `height+2` por razões que são [explicadas abaixo](#why-map-border). + +Podemos usar `${width+2}` e `${height+2}` porque os programas Zokrates são armazenados nesta aplicação como [template strings](https://www.w3schools.com/js/js_string_templates.asp). O código entre `${` e `}` é avaliado pelo JavaScript e, dessa forma, o programa pode ser usado para diferentes tamanhos de mapa. O parâmetro do mapa tem uma borda de um local de largura ao seu redor sem nenhuma bomba, que é a razão pela qual precisamos adicionar dois à largura e à altura. + +O valor de retorno é um `field` que contém o hash. + +``` + bool[512] mut map1d = [false; 512]; +``` + +O mapa é bidimensional. No entanto, a função `pack128` não funciona com arrays bidimensionais. Então, primeiro achatamos o mapa em um array de 512 bytes, usando `map1d`. Por padrão, as variáveis do Zokrates são constantes, mas precisamos atribuir valores a este array em um loop, então o definimos como [`mut`](https://zokrates.github.io/language/variables.html#mutability). + +Precisamos inicializar o array porque o Zokrates não tem `undefined`. A expressão `[false; 512]` significa [um array de 512 valores `false`](https://zokrates.github.io/language/types.html#declaration-and-initialization). + +``` + u32 mut counter = 0; +``` + +Também precisamos de um contador para distinguir entre os bits que já preenchemos em `map1d` e os que não preenchemos. + +``` + for u32 x in 0..${width+2} { +``` + +É assim que se declara um [loop `for`](https://zokrates.github.io/language/control_flow.html#for-loops) no Zokrates. Um loop `for` do Zokrates tem que ter limites fixos, porque embora pareça ser um loop, o compilador na verdade o "desenrola". A expressão `${width+2}` é uma constante em tempo de compilação porque `width` é definida pelo código TypeScript antes de chamar o compilador. + +``` + for u32 y in 0..${height+2} { + map1d[counter] = map[x][y]; + counter = counter+1; + } + } +``` + +Para cada local no mapa, coloque esse valor no array `map1d` e incremente o contador. + +``` + field[4] hashMe = [ + pack128(map1d[0..128]), + pack128(map1d[128..256]), + pack128(map1d[256..384]), + pack128(map1d[384..512]) + ]; +``` + +Usamos `pack128` para criar um array de quatro valores `field` a partir de `map1d`. No Zokrates, `array[a..b]` significa a fatia do array que começa em `a` e termina em `b-1`. + +``` + return poseidon(hashMe); +} +``` + +Use `poseidon` para converter este array em um hash. + +### O programa de hash {#hash-program} + +O servidor precisa chamar `hashMap` diretamente para criar identificadores de jogo. No entanto, Zokrates só pode chamar a função `main` em um programa para iniciar, então criamos um programa com uma `main` que chama a função de hash. + +``` +${hashFragment} + +def main(bool[${width+2}][${height+2}] map) -> field { + return hashMap(map); +} +``` + +### O programa dig {#dig-program} + +Este é o coração da parte de conhecimento zero da aplicação, onde produzimos as provas que são usadas para verificar os resultados da escavação. + +``` +${hashFragment} + +// O número de minas no local (x,y) +def map2mineCount(bool[${width+2}][${height+2}] map, u32 x, u32 y) -> u8 { + return if map[x+1][y+1] { 1 } else { 0 }; +} +``` + +#### Por que borda do mapa {#why-map-border} + +As provas de conhecimento zero usam [circuitos aritméticos](https://medium.com/web3studio/simple-explanations-of-arithmetic-circuits-and-zero-knowledge-proofs-806e59a79785), que não têm um equivalente fácil para uma declaração `if`. Em vez disso, eles usam o equivalente do [operador condicional](https://en.wikipedia.org/wiki/Ternary_conditional_operator). Se `a` pode ser zero ou um, você pode calcular `if a { b } else { c }` como `ab+(1-a)c`. + +Por causa disso, uma instrução `if` do Zokrates sempre avalia ambas as ramificações. Por exemplo, se você tiver este código: + +``` +bool[5] arr = [false; 5]; +u32 index=10; +return if index>4 { 0 } else { arr[index] } +``` + +Ele vai dar erro, porque precisa calcular `arr[10]`, mesmo que esse valor seja posteriormente multiplicado por zero. + +Esta é a razão pela qual precisamos de uma borda com uma casa de largura em todo o mapa. Precisamos calcular o número total de minas ao redor de um local, e isso significa que precisamos ver o local uma linha acima e abaixo, à esquerda e à direita, do local onde estamos cavando. O que significa que esses locais precisam existir no array do mapa que é fornecido ao Zokrates. + +``` +def main(private bool[${width+2}][${height+2}] map, u32 x, u32 y) -> (field, u8) { +``` + +Por padrão, as provas Zokrates incluem suas entradas. Não adianta saber que há cinco minas ao redor de um ponto, a menos que você saiba qual é o ponto (e você não pode simplesmente combiná-lo com sua solicitação, porque então o provador poderia usar valores diferentes e não lhe contar sobre isso). No entanto, precisamos manter o mapa em segredo, enquanto o fornecemos ao Zokrates. A solução é usar um parâmetro `private`, que _não_ é revelado pela prova. + +Isso abre outra via para abuso. O provador poderia usar as coordenadas corretas, mas criar um mapa com qualquer número de minas ao redor do local, e possivelmente no próprio local. Para evitar esse abuso, fazemos com que a prova de conhecimento zero inclua o hash do mapa, que é o identificador do jogo. + +``` + return (hashMap(map), +``` + +O valor de retorno aqui é uma tupla que inclui o array de hash do mapa, bem como o resultado da escavação. + +``` + if map2mineCount(map, x, y) > 0 { 0xFF } else { +``` + +Usamos 255 como um valor especial caso o próprio local tenha uma bomba. + +``` + map2mineCount(map, x-1, y-1) + map2mineCount(map, x, y-1) + map2mineCount(map, x+1, y-1) + + map2mineCount(map, x-1, y) + map2mineCount(map, x+1, y) + + map2mineCount(map, x-1, y+1) + map2mineCount(map, x, y+1) + map2mineCount(map, x+1, y+1) + } + ); +} +``` + +Se o jogador não atingiu uma mina, some as contagens de minas da área ao redor do local e retorne isso. + +### Usando Zokrates a partir do TypeScript {#using-zokrates-from-typescript} + +O Zokrates tem uma interface de linha de comando, mas neste programa nós o usamos no [código TypeScript](https://zokrates.github.io/toolbox/zokrates_js.html). + +A biblioteca que contém as definições do Zokrates é chamada [`zero-knowledge.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts). + +```typescript +import { initialize as zokratesInitialize } from "zokrates-js" +``` + +Importe as [ligações JavaScript do Zokrates](https://zokrates.github.io/toolbox/zokrates_js.html). Só precisamos da função [`initialize`](https://zokrates.github.io/toolbox/zokrates_js.html#initialize) porque ela retorna uma promessa que resolve para todas as definições do Zokrates. + +```typescript +export const zkFunctions = async (width: number, height: number) : Promise => { +``` + +Semelhante ao próprio Zokrates, também exportamos apenas uma função, que também é [assíncrona](https://www.w3schools.com/js/js_async.asp). Quando ela finalmente retorna, ela fornece várias funções, como veremos abaixo. + +```typescript +const zokrates = await zokratesInitialize() +``` + +Inicialize o Zokrates, obtenha tudo o que precisamos da biblioteca. + +```typescript +const hashFragment = ` + import "utils/pack/bool/pack128.zok" as pack128; + import "hashes/poseidon/poseidon.zok" as poseidon; + . + . + . + } + ` + +const hashProgram = ` + ${hashFragment} + . + . + . + ` + +const digProgram = ` + ${hashFragment} + . + . + . + ` +``` + +A seguir, temos a função de hash e dois programas Zokrates que vimos acima. + +```typescript +const digCompiled = zokrates.compile(digProgram) +const hashCompiled = zokrates.compile(hashProgram) +``` + +Aqui compilamos esses programas. + +```typescript +// Crie as chaves para a verificação de conhecimento zero. +// Em um sistema de produção, você desejaria usar uma cerimônia de configuração. +// (https://zokrates.github.io/toolbox/trusted_setup.html#initializing-a-phase-2-ceremony). +const keySetupResults = zokrates.setup(digCompiled.program, "") +const verifierKey = keySetupResults.vk +const proverKey = keySetupResults.pk +``` + +Em um sistema de produção, poderíamos usar uma [cerimônia de configuração](https://zokrates.github.io/toolbox/trusted_setup.html#initializing-a-phase-2-ceremony) mais complicada, mas isso é suficiente para uma demonstração. Não é um problema que os usuários possam conhecer a chave do provador - eles ainda não podem usá-la para provar coisas, a menos que sejam verdadeiras. Como especificamos a entropia (o segundo parâmetro, `""`), os resultados serão sempre os mesmos. + +**Observação:** a compilação de programas Zokrates e a criação de chaves são processos lentos. Não há necessidade de repeti-los sempre, apenas quando o tamanho do mapa muda. Em um sistema de produção, você os faria uma vez e depois armazenaria a saída. A única razão pela qual não estou fazendo isso aqui é por uma questão de simplicidade. + +#### `calculateMapHash` {#calculateMapHash} + +```typescript +const calculateMapHash = function (hashMe: boolean[][]): string { + return ( + "0x" + + BigInt(zokrates.computeWitness(hashCompiled, [hashMe]).output.slice(1, -1)) + .toString(16) + .padStart(64, "0") + ) +} +``` + +A função [`computeWitness`](https://zokrates.github.io/toolbox/zokrates_js.html#computewitnessartifacts-args-options) realmente executa o programa Zokrates. Ela retorna uma estrutura com dois campos: `output`, que é a saída do programa como uma string JSON, e `witness`, que é a informação necessária para criar a prova de conhecimento zero do resultado. Aqui só precisamos da saída. + +A saída é uma string no formato `"31337"`, um número decimal entre aspas. Mas a saída que precisamos para o `viem` é um número hexadecimal no formato `0x60A7`. Portanto, usamos `.slice(1,-1)` para remover as aspas e, em seguida, `BigInt` para transformar a string restante, que é um número decimal, em um [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt). `.toString(16)` converte este `BigInt` em uma string hexadecimal, e `"0x"+` adiciona o marcador para números hexadecimais. + +```typescript +// Escave e retorne uma prova de conhecimento zero do resultado +// (código do lado do servidor) +``` + +A prova de conhecimento zero inclui as entradas públicas (`x` e `y`) e os resultados (hash do mapa e número de bombas). + +```typescript + const zkDig = function(map: boolean[][], x: number, y: number) : any { + if (x<0 || x>=width || y<0 || y>=height) + throw new Error("Tentando cavar fora do mapa") +``` + +É um problema verificar se um índice está fora dos limites no Zokrates, então fazemos isso aqui. + +```typescript +const runResults = zokrates.computeWitness(digCompiled, [map, `${x}`, `${y}`]) +``` + +Execute o programa dig. + +```typescript + const proof = zokrates.generateProof( + digCompiled.program, + runResults.witness, + proverKey) + + return proof + } +``` + +Use [`generateProof`](https://zokrates.github.io/toolbox/zokrates_js.html#generateproofprogram-witness-provingkey-entropy) e retorne a prova. + +```typescript +const solidityVerifier = ` + // Tamanho do mapa: ${width} x ${height} + \n${zokrates.exportSolidityVerifier(verifierKey)} + ` +``` + +Um verificador Solidity, um contrato inteligente que podemos implantar na cadeia de blocos e usar para verificar as provas geradas por `digCompiled.program`. + +```typescript + return { + zkDig, + calculateMapHash, + solidityVerifier, + } +} +``` + +Finalmente, retorne tudo o que outro código possa precisar. + +## Testes de segurança {#security-tests} + +Os testes de segurança são importantes porque um bug de funcionalidade acabará por se revelar. Mas se a aplicação for insegura, é provável que isso permaneça oculto por muito tempo antes de ser revelado por alguém que trapaceia e obtém recursos que pertencem a outros. + +### Permissões {#permissions} + +Há uma entidade privilegiada neste jogo, o servidor. É o único usuário autorizado a chamar as funções em [`ServerSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol). Podemos usar [`cast`](https://book.getfoundry.sh/cast/) para verificar se as chamadas para funções permissionadas são permitidas apenas como a conta do servidor. + +[A chave privada do servidor está em `setupNetwork.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/mud/setupNetwork.ts#L52). + +1. No computador que executa o `anvil` (a cadeia de blocos), defina estas variáveis de ambiente. + + ```sh copy + WORLD_ADDRESS=0x8d8b6b8414e1e3dcfd4168561b9be6bd3bf6ec4b + UNAUTHORIZED_KEY=0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a + AUTHORIZED_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d + ``` + +2. Use `cast` para tentar definir o endereço do verificador como um endereço não autorizado. + + ```sh copy + cast send $WORLD_ADDRESS 'app__setVerifier(address)' `cast address-zero` --private-key $UNAUTHORIZED_KEY + ``` + + O `cast` não apenas relata uma falha, mas você também pode abrir as **Ferramentas de Desenvolvedor MUD** no jogo no navegador, clicar em **Tabelas** e selecionar **app\_\_VerifierAddress**. Veja que o endereço não é zero. + +3. Defina o endereço do verificador como o endereço do servidor. + + ```sh copy + cast send $WORLD_ADDRESS 'app__setVerifier(address)' `cast address-zero` --private-key $AUTHORIZED_KEY + ``` + + O endereço em **app\_\_VerifiedAddress** agora deve ser zero. + +Todas as funções MUD no mesmo `System` passam pelo mesmo controle de acesso, então considero este teste suficiente. Caso contrário, você pode verificar as outras funções em [`ServerSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol). + +### Abusos de conhecimento zero {#zero-knowledge-abuses} + +A matemática para verificar o Zokrates está além do escopo deste tutorial (e das minhas habilidades). No entanto, podemos executar várias verificações no código de conhecimento zero para verificar se, se não for feito corretamente, ele falha. Todos esses testes exigirão que alteremos [`zero-knowledge.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts) e reiniciemos toda a aplicação. Não é suficiente reiniciar o processo do servidor, porque isso coloca a aplicação em um estado impossível (o jogador tem um jogo em andamento, mas o jogo não está mais disponível para o servidor). + +#### Resposta errada {#wrong-answer} + +A possibilidade mais simples é fornecer a resposta errada na prova de conhecimento zero. Para fazer isso, entramos em `zkDig` e [modificamos a linha 91](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L91): + +```ts +proof.inputs[3] = "0x" + "1".padStart(64, "0") +``` + +Isso significa que sempre alegaremos que há uma bomba, independentemente da resposta correta. Tente jogar com esta versão e você verá na guia **servidor** da tela `pnpm dev` este erro: + +``` + cause: { + code: 3, + message: 'execution reverted: revert: Falha na verificação de conhecimento zero', + data: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000 +000000000000000000000000000000000000000000000000205a65726f206b6e6f776c6564676520766572696669636174696f6 +e206661696c' + }, +``` + +Portanto, esse tipo de trapaça falha. + +#### Prova errada {#wrong-proof} + +O que acontece se fornecermos as informações corretas, mas tivermos os dados de prova errados? Agora, substitua a linha 91 por: + +```ts +proof.proof = { + a: ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")], + b: [ + ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")], + ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")], + ], + c: ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")], +} +``` + +Ele ainda falha, mas agora falha sem motivo, porque acontece durante a chamada do verificador. + +### Como um usuário pode verificar o código de confiança zero? {#user-verify-zero-trust} + +Contratos inteligentes são relativamente fáceis de verificar. Normalmente, o desenvolvedor publica o código-fonte em um explorador de blocos, e o explorador de blocos verifica se o código-fonte compila para o código na [transação de implantação do contrato](/developers/docs/smart-contracts/deploying/). No caso dos `System`s MUD, isso é [um pouco mais complicado](https://mud.dev/cli/verify), mas não muito. + +Isso é mais difícil com conhecimento zero. O verificador inclui algumas constantes e executa alguns cálculos sobre elas. Isso não lhe diz o que está sendo provado. + +```solidity + function verifyingKey() pure internal returns (VerifyingKey memory vk) { + vk.alpha = Pairing.G1Point(uint256(0x0f43f4fe7b5c2326fed4ac6ed2f4003ab9ab4ea6f667c2bdd77afb068617ee16), uint256(0x25a77832283f9726935219b5f4678842cda465631e72dbb24708a97ba5d0ce6f)); + vk.beta = Pairing.G2Point([uint256(0x2cebd0fbd21aca01910581537b21ae4fed46bc0e524c055059aa164ba0a6b62b), uint256(0x18fd4a7bc386cf03a95af7163d5359165acc4e7961cb46519e6d9ee4a1e2b7e9)], [uint256(0x11449dee0199ef6d8eebfe43b548e875c69e7ce37705ee9a00c81fe52f11a009), uint256(0x066d0c83b32800d3f335bb9e8ed5e2924cf00e77e6ec28178592eac9898e1a00)]); +``` + +A solução, pelo menos até que os exploradores de blocos adicionem a verificação do Zokrates às suas interfaces de usuário, é que os desenvolvedores de aplicações disponibilizem os programas Zokrates, e que pelo menos alguns usuários os compilem com a chave de verificação apropriada. + +Para fazer isso: + +1. [Instale o Zokrates](https://zokrates.github.io/gettingstarted.html). + +2. Crie um arquivo, `dig.zok`, com o programa Zokrates. O código abaixo presume que você manteve o tamanho original do mapa, 10x5. + + ```zokrates + import "utils/pack/bool/pack128.zok" as pack128; + import "hashes/poseidon/poseidon.zok" as poseidon; + + def hashMap(bool[12][7] map) -> field { + bool[512] mut map1d = [false; 512]; + u32 mut counter = 0; + + for u32 x in 0..12 { + for u32 y in 0..7 { + map1d[counter] = map[x][y]; + counter = counter+1; + } + } + + field[4] hashMe = [ + pack128(map1d[0..128]), + pack128(map1d[128..256]), + pack128(map1d[256..384]), + pack128(map1d[384..512]) + ]; + + return poseidon(hashMe); + } + + + // O número de minas no local (x,y) + def map2mineCount(bool[12][7] map, u32 x, u32 y) -> u8 { + return if map[x+1][y+1] { 1 } else { 0 }; + } + + def main(private bool[12][7] map, u32 x, u32 y) -> (field, u8) { + return (hashMap(map) , + if map2mineCount(map, x, y) > 0 { 0xFF } else { + map2mineCount(map, x-1, y-1) + map2mineCount(map, x, y-1) + map2mineCount(map, x+1, y-1) + + map2mineCount(map, x-1, y) + map2mineCount(map, x+1, y) + + map2mineCount(map, x-1, y+1) + map2mineCount(map, x, y+1) + map2mineCount(map, x+1, y+1) + } + ); + } + ``` + +3. Compile o código Zokrates e crie a chave de verificação. A chave de verificação deve ser criada com a mesma entropia usada no servidor original, [neste caso, uma string vazia](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L67). + + ```sh copy + zokrates compile --input dig.zok + zokrates setup -e "" + ``` + +4. Crie o verificador Solidity por conta própria e verifique se ele é funcionalmente idêntico ao da cadeia de blocos (o servidor adiciona um comentário, mas isso não é importante). + + ```sh copy + zokrates export-verifier + diff verifier.sol ~/20240901-secret-state/packages/contracts/src/verifier.sol + ``` + +## Decisões de design {#design} + +Em qualquer aplicação suficientemente complexa, existem objetivos de design concorrentes que exigem trade-offs. Vamos analisar alguns dos trade-offs e por que a solução atual é preferível a outras opções. + +### Por que conhecimento zero {#why-zero-knowledge} + +Para o Campo Minado, você não precisa realmente de conhecimento zero. O servidor pode sempre manter o mapa e depois revelá-lo por completo quando o jogo terminar. Então, no final do jogo, o contrato inteligente pode calcular o hash do mapa, verificar se corresponde e, se não, penalizar o servidor ou desconsiderar o jogo completamente. + +Não usei essa solução mais simples porque ela só funciona para jogos curtos com um estado final bem definido. Quando um jogo é potencialmente infinito (como no caso dos [mundos autônomos](https://0xparc.org/blog/autonomous-worlds)), você precisa de uma solução que prove o estado _sem_ revelá-lo. + +Como um tutorial, este artigo precisava de um jogo curto que fosse fácil de entender, mas essa técnica é mais útil para jogos mais longos. + +### Por que Zokrates? {#why-zokrates} + +[Zokrates](https://zokrates.github.io/) não é a única biblioteca de conhecimento zero disponível, mas é semelhante a uma linguagem de programação normal e [imperativa](https://en.wikipedia.org/wiki/Imperative_programming) e suporta variáveis ​​booleanas. + +Para sua aplicação, com requisitos diferentes, você pode preferir usar [Circum](https://docs.circom.io/getting-started/installation/) ou [Cairo](https://www.cairo-lang.org/tutorials/getting-started-with-cairo/). + +### Quando compilar o Zokrates {#when-compile-zokrates} + +Neste programa, compilamos os programas Zokrates [toda vez que o servidor é iniciado](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L60-L61). Isso é claramente um desperdício de recursos, mas este é um tutorial, otimizado para simplicidade. + +Se eu estivesse escrevendo uma aplicação de nível de produção, verificaria se tenho um arquivo com os programas Zokrates compilados neste tamanho de campo minado e, se sim, usaria isso. O mesmo vale para implantar um contrato de verificador em cadeia. + +### Criando as chaves do verificador e do provador {#key-creation} + +A [criação de chaves](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L63-L69) é outro cálculo puro que não precisa ser feito mais de uma vez para um determinado tamanho de campo minado. Novamente, é feito apenas uma vez por uma questão de simplicidade. + +Além disso, poderíamos usar [uma cerimônia de configuração](https://zokrates.github.io/toolbox/trusted_setup.html#initializing-a-phase-2-ceremony). A vantagem de uma cerimônia de configuração é que você precisa da entropia ou de algum resultado intermediário de cada participante para trapacear na prova de conhecimento zero. Se pelo menos um participante da cerimônia for honesto e excluir essa informação, as provas de conhecimento zero estarão seguras contra certos ataques. No entanto, _não há mecanismo_ para verificar se a informação foi excluída de todos os lugares. Se as provas de conhecimento zero são de importância crítica, você vai querer participar da cerimônia de configuração. + +Aqui, contamos com [poderes perpétuos de tau](https://github.com/privacy-scaling-explorations/perpetualpowersoftau), que teve dezenas de participantes. Provavelmente é seguro o suficiente e muito mais simples. Também não adicionamos entropia durante a criação da chave, o que facilita para os usuários [verificarem a configuração de conhecimento zero](#user-verify-zero-trust). + +### Onde verificar {#where-verification} + +Podemos verificar as provas de conhecimento zero em cadeia (o que custa gás) ou no cliente (usando [`verify`](https://zokrates.github.io/toolbox/zokrates_js.html#verifyverificationkey-proof)). Eu escolhi a primeira, porque isso permite que você [verifique o verificador](#user-verify-zero-trust) uma vez e depois confie que ele não muda, desde que o endereço do contrato para ele permaneça o mesmo. Se a verificação fosse feita no cliente, você teria que verificar o código que recebe cada vez que baixa o cliente. + +Além disso, embora este jogo seja para um jogador, muitos jogos de cadeia de blocos são para vários jogadores. a verificação em cadeia significa que você só verifica a prova de conhecimento zero uma vez. Fazer isso no cliente exigiria que cada cliente verificasse independentemente. + +### Achatar o mapa em TypeScript ou Zokrates? {#where-flatten} + +Em geral, quando o processamento pode ser feito em TypeScript ou Zokrates, é melhor fazê-lo em TypeScript, que é muito mais rápido e não requer provas de conhecimento zero. Essa é a razão, por exemplo, pela qual não fornecemos ao Zokrates o hash e o fazemos verificar se está correto. O hashing deve ser feito dentro do Zokrates, mas a correspondência entre o hash retornado e o hash em cadeia pode ocorrer fora dele. + +No entanto, ainda [achatamos o mapa em Zokrates](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L15-L20), enquanto poderíamos tê-lo feito em TypeScript. A razão é que as outras opções são, na minha opinião, piores. + +- Forneça um array unidimensional de booleanos para o código Zokrates e use uma expressão como `x*(height+2)+y` para obter o mapa bidimensional. Isso tornaria [o código](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L44-L47) um pouco mais complicado, então decidi que o ganho de desempenho não vale a pena para um tutorial. + +- Envie ao Zokrates tanto o array unidimensional quanto o array bidimensional. No entanto, esta solução não nos traz nenhum ganho. O código Zokrates teria que verificar se o array unidimensional fornecido é realmente a representação correta do array bidimensional. Portanto, não haveria nenhum ganho de desempenho. + +- Achatar o array bidimensional em Zokrates. Esta é a opção mais simples, então eu a escolhi. + +### Onde armazenar mapas {#where-store-maps} + +Nesta aplicação, [`gamesInProgress`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L20) é simplesmente uma variável na memória. Isso significa que se o seu servidor parar de funcionar e precisar ser reiniciado, todas as informações armazenadas serão perdidas. Os jogadores não apenas não conseguem continuar o jogo, como também não conseguem iniciar um novo, porque o componente em cadeia pensa que eles ainda têm um jogo em andamento. + +Isso é claramente um mau design para um sistema de produção, no qual você armazenaria essa informação em um banco de dados. A única razão pela qual usei uma variável aqui é porque este é um tutorial e a simplicidade é a principal consideração. + +## Conclusão: Em que condições esta é a técnica apropriada? {#conclusion} + +Então, agora você sabe como escrever um jogo com um servidor que armazena um estado secreto que não pertence à cadeia. Mas em que casos você deve fazer isso? Existem duas considerações principais. + +- _Jogo de longa duração_: [Como mencionado acima](#why-zero-knowledge), em um jogo curto, você pode simplesmente publicar o estado quando o jogo terminar e ter tudo verificado então. Mas essa não é uma opção quando o jogo leva um tempo longo ou indefinido, e o estado precisa permanecer secreto. + +- _Alguma centralização aceitável_: As provas de conhecimento zero podem verificar a integridade, que uma entidade não está falsificando os resultados. O que elas não podem fazer é garantir que a entidade ainda estará disponível e responderá às mensagens. Em situações em que a disponibilidade também precisa ser descentralizada, as provas de conhecimento zero não são uma solução suficiente, e você precisa de [computação multipartidária](https://en.wikipedia.org/wiki/Secure_multi-party_computation). + +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). + +### Agradecimentos {#acknowledgements} + +- Alvaro Alonso leu um rascunho deste artigo e esclareceu alguns dos meus mal-entendidos sobre Zokrates. + +Quaisquer erros remanescentes são de minha responsabilidade. diff --git a/public/content/translations/pt-br/developers/tutorials/secure-development-workflow/index.md b/public/content/translations/pt-br/developers/tutorials/secure-development-workflow/index.md index 7caf23f4aca..5faabf18098 100644 --- a/public/content/translations/pt-br/developers/tutorials/secure-development-workflow/index.md +++ b/public/content/translations/pt-br/developers/tutorials/secure-development-workflow/index.md @@ -1,44 +1,41 @@ --- -title: Checklist de segurança para smart contracts +title: "Checklist de segurança para smart contracts" description: Um workflow sugerido para escrever smart contracts seguros author: "Trailofbits" -tags: - - "contratos inteligentes" - - "segurança" - - "solidity" +tags: [ "smart contracts", "segurança", "Solidity" ] skill: intermediate lang: pt-br published: 2020-09-07 -source: Construindo contratos seguros +source: Building secure contracts sourceUrl: https://github.com/crytic/building-secure-contracts/blob/master/development-guidelines/workflow.md --- -## Processo de desenvolvimento do contrato inteligente {#smart-contract-development-checklist} +## Lista de verificação de desenvolvimento de contrato inteligente {#smart-contract-development-checklist} Aqui temos um processo de alto nível que recomendamos seguir enquanto você escreve seus contratos inteligentes. Verificar problemas de segurança conhecidos: -- Reveja seus contratos com o [Slither](https://github.com/crytic/slither). Tem mais de 40 detectores internos para vulnerabilidades comuns. Execute em cada check-in com um novo código e certifique-se de que ele recebe um relatório limpo (ou use o modo de triagem para silenciar certos problemas). -- Reveja seus contratos com o [Crytic](https://crytic.io/). Ele verifica 50 problemas que o Slither não tem. O Crytic também pode ajudar sua equipe a se manter atualizada, resolvendo problemas de segurança facilmente nas solicitações de pull no GitHub. +- Revise seus contratos com [Slither](https://github.com/crytic/slither). Tem mais de 40 detectores internos para vulnerabilidades comuns. Execute em cada check-in com um novo código e certifique-se de que ele recebe um relatório limpo (ou use o modo de triagem para silenciar certos problemas). +- Revise seus contratos com [Crytic](https://crytic.io/). Ele verifica 50 problemas que o Slither não tem. O Crytic também pode ajudar sua equipe a se manter atualizada, resolvendo problemas de segurança facilmente nas solicitações de pull no GitHub. Considere as características especiais do seu contrato: -- Os seus contratos são atualizáveis? Verifique se há defeitos em seu código de capacidade de atualização com o [`slither-check-upgradeability`](https://github.com/crytic/slither/wiki/Upgradeability-Checks) ou [Crytic](https://blog.trailofbits.com/2020/06/12/upgradeable-contracts-made-safer-with-crytic/). Documentamos 17 situações em que as atualizações podem correr mal. -- Seus contratos pretendem estar em conformidade com os ERCs? Verifique com [`slither-check-erc`](https://github.com/crytic/slither/wiki/ERC-Conformance). Esta ferramenta identifica instantaneamente desvios de seis especificações comuns. -- Você faz integrações com tokens de outras empresas? Revise nossa [lista de verificação de integração de tokens](/developers/tutorials/token-integration-checklist/) antes de confiar em contratos externos. +- Os seus contratos são atualizáveis? Revise seu código de capacidade de atualização em busca de falhas com [`slither-check-upgradeability`](https://github.com/crytic/slither/wiki/Upgradeability-Checks) ou [Crytic](https://blog.trailofbits.com/2020/06/12/upgradeable-contracts-made-safer-with-crytic/). Documentamos 17 situações em que as atualizações podem correr mal. +- Seus contratos pretendem estar em conformidade com os ERCs? Verifique-os com [`slither-check-erc`](https://github.com/crytic/slither/wiki/ERC-Conformance). Esta ferramenta identifica instantaneamente desvios de seis especificações comuns. +- Você faz integrações com tokens de outras empresas? Revise nossa [lista de verificação de integração de token](/developers/tutorials/token-integration-checklist/) antes de depender de contratos externos. Visualmente inspecione recursos críticos de segurança com seu código: -- Analise o printer [inheritance-graph](https://github.com/trailofbits/slither/wiki/Printer-documentation#inheritance-graph) do Slither. Evite problemas de linearização de sombras e C3 involuntários. -- Analise o printer [inheritance-graph](https://github.com/trailofbits/slither/wiki/Printer-documentation#function-summary) do Slither. Reporta a visibilidade da função e os controles de acesso. -- Analise o printer [vars-and-auth](https://github.com/trailofbits/slither/wiki/Printer-documentation#variables-written-and-authorization) do Slither. Ele relata os controles de acesso às variáveis de estado. +- Revise o impressor [inheritance-graph](https://github.com/trailofbits/slither/wiki/Printer-documentation#inheritance-graph) do Slither. Evite problemas de linearização de sombras e C3 involuntários. +- Revise o impressor [function-summary](https://github.com/trailofbits/slither/wiki/Printer-documentation#function-summary) do Slither. Reporta a visibilidade da função e os controles de acesso. +- Revise o impressor [vars-and-auth](https://github.com/trailofbits/slither/wiki/Printer-documentation#variables-written-and-authorization) do Slither. Ele relata os controles de acesso às variáveis de estado. Propriedades de segurança críticas do documento e use geradores de testes automatizados para avaliá-las: -- Aprenda com [as propriedades de segurança de documentos para o seu código](/developers/tutorials/guide-to-smart-contract-security-tools/). É difícil no início, mas é a atividade mais importante para alcançar um bom resultado. Também é um pré-requisito para usar qualquer uma das técnicas avançadas neste tutorial. -- Defina as propriedades de segurança no Solidity, para usar com [Echidna](https://github.com/crytic/echidna) e [Manticore](https://manticore.readthedocs.io/en/latest/verifier.html). Concentre-se na sua máquina do estado, controles de acesso, operações aritméticas, interações externas e padrões de conformidade. -- Defina as propriedades de segurança com [API Python do Slither](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/). Concentre-se na herança, nas dependências variáveis, nos controles de acesso e em outras questões estruturais. +- Aprenda a [documentar as propriedades de segurança para o seu código](/developers/tutorials/guide-to-smart-contract-security-tools/). É difícil no início, mas é a atividade mais importante para alcançar um bom resultado. Também é um pré-requisito para usar qualquer uma das técnicas avançadas neste tutorial. +- Defina as propriedades de segurança em Solidity para uso com [Echidna](https://github.com/crytic/echidna) e [Manticore](https://manticore.readthedocs.io/en/latest/verifier.html). Concentre-se na sua máquina do estado, controles de acesso, operações aritméticas, interações externas e padrões de conformidade. +- Defina as propriedades de segurança com a [API Python do Slither](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/). Concentre-se na herança, nas dependências variáveis, nos controles de acesso e em outras questões estruturais. - Execute seus testes de propriedade em cada commit com [Crytic](https://crytic.io). Critica pode consumir e avaliar testes de propriedade de segurança para que todos na sua equipe possam facilmente ver que eles passam no GitHub. Os testes que falharam podem bloquear os commits. Finalmente, esteja atento a questões que as ferramentas automatizadas não conseguem facilmente encontrar: @@ -48,8 +45,8 @@ Finalmente, esteja atento a questões que as ferramentas automatizadas não cons - Operações criptográficas - Interações arriscadas com componentes externos de DeFi -## Pedir ajuda {#ask-for-help} +## Peça ajuda {#ask-for-help} -[Horário de escritório Ethereum](https://calendly.com/dan-trailofbits/office-hours) executa todas as terças da tarde. Essas sessões presenciais de uma hora são uma oportunidade para você nos fazer quaisquer perguntas que sobre segurança, solucionar problemas usando nossas ferramentas e obter comentários de especialistas sobre sua abordagem atual. Vamos ajudá-lo a trabalhar neste guia. +Os [horários de expediente do Ethereum](https://calendly.com/dan-trailofbits/office-hours) acontecem toda terça-feira à tarde. Essas sessões presenciais de uma hora são uma oportunidade para você nos fazer quaisquer perguntas que sobre segurança, solucionar problemas usando nossas ferramentas e obter comentários de especialistas sobre sua abordagem atual. Vamos ajudá-lo a trabalhar neste guia. Junte-se ao nosso Slack: [Empire Hacking](https://join.slack.com/t/empirehacking/shared_invite/zt-h97bbrj8-1jwuiU33nnzg67JcvIciUw). Sempre estaremos disponíveis nos canais #crytic e #ethereum caso tenha alguma dúvida. diff --git a/public/content/translations/pt-br/developers/tutorials/send-token-ethersjs/index.md b/public/content/translations/pt-br/developers/tutorials/send-token-ethersjs/index.md index f57529f2ef8..f35890853ce 100644 --- a/public/content/translations/pt-br/developers/tutorials/send-token-ethersjs/index.md +++ b/public/content/translations/pt-br/developers/tutorials/send-token-ethersjs/index.md @@ -1,11 +1,8 @@ --- -title: Envio de fichas usando ethers.js -description: Guia amigo para iniciantes enviarem tokens usando ethers.js. +title: Enviando Tokens Usando ethers.js +description: Guia para iniciantes sobre o envio de tokens usando ethers.js. author: Kim YongJun -tags: - - "ETHERS.JS" - - "ERC-20" - - "TOKENS" +tags: [ "ETHERS.JS", "ERC-20", "TOKENS" ] skill: beginner lang: pt-br published: 2021-04-06 @@ -13,32 +10,33 @@ published: 2021-04-06 ## Enviar Token usando ethers.js(5.0) {#send-token} -### Neste tutorial, você aprenderá {#you-learn-about} +### Neste tutorial, você aprenderá como {#you-learn-about} - Importar ethers.js -- Transferência de tokens -- Defina o preço do gás de acordo com a situação do tráfego de rede +- Transferir token +- Definir o preço do gás de acordo com a situação do tráfego da rede -### Iniciado {#to-get-started} +### Para começar {#to-get-started} -Para começar, primeiro devemos importar a biblioteca ethers.js para nossa javascript Incluir ethers.js(5.0) +Para começar, devemos primeiro importar a biblioteca ethers.js em nosso javascript +Incluir ethers.js(5.0) -### Instalando {#install-ethersjs} +### Instalação {#install-ethersjs} ```shell /home/ricmoo> npm install --save ethers ``` -ES6 no Navegador +ES6 no navegador ```html ``` -ES3(UMD) no Navegador +ES3(UMD) no navegador ```html ``` -Se você preferir instalar a biblioteca para usar em seu backend ou um projeto do frontend que usa build, você pode instalá-la usando o npm: +Se preferir instalar a biblioteca para usar no seu back-end ou em um projeto de front-end que use um processo de build, você pode instalá-la usando o npm: ```bash npm install web3 --save ``` -Em seguida, para importar o Web3.js em um script Node.js ou projeto front-end do Browserify, você pode usar a seguinte linha de JavaScript: +Em seguida, para importar o Web3.js em um script Node.js ou projeto de front-end do Browserify, você pode usar a seguinte linha de JavaScript: ```js const Web3 = require("web3") ``` -Agora que incluímos a biblioteca no projeto, precisamos inicializá-la. Seu projeto precisa ser capaz de se comunicar com a blockchain. A maioria das bibliotecas Ethereum se comunicam com um [nó](/developers/docs/nodes-and-clients/) através de chamadas RPC. Para iniciar nosso provedor Web3, nós criaremos uma instância Web3 passando como construtor a URL do provedor. Se você tiver uma instância de um nó ou [ganache executando no seu computador](https://ethereumdev.io/testing-your-smart-contract-with-existing-protocols-ganache-fork/) será parecido com isto: +Agora que incluímos a biblioteca no projeto, precisamos inicializá-la. Seu projeto precisa ser capaz de se comunicar com a blockchain. A maioria das bibliotecas Ethereum se comunica com um [nó](/developers/docs/nodes-and-clients/) por meio de chamadas RPC. Para iniciar nosso provedor Web3, vamos instanciar o Web3 passando a URL do provedor para o construtor. Se você tiver um nó ou uma [instância do ganache em execução em seu computador](https://ethereumdev.io/testing-your-smart-contract-with-existing-protocols-ganache-fork/), o código será parecido com este: ```js const web3 = new Web3("http://localhost:8545") ``` -Se você deseja acessar diretamente um nó hospedado, poderá encontrar opções em [nós como um serviço](/developers/docs/nodes-and-clients/nodes-as-a-service). +Se quiser acessar diretamente um nó hospedado, você pode encontrar opções em [nós como serviço](/developers/docs/nodes-and-clients/nodes-as-a-service). ```js const web3 = new Web3("https://cloudflare-eth.com") ``` -Para testar se configuramos corretamente nossa instância Web3, tentaremos recuperar o número do último bloco usando a função `getBlockNumber`. Esta função aceita uma chamada de callback como parâmetro e retorna o número do bloco como um inteiro. +Para testar se configuramos nossa instância do Web3 corretamente, vamos tentar recuperar o número do bloco mais recente usando a função `getBlockNumber`. Essa função aceita um callback como parâmetro e retorna o número do bloco como um inteiro. ```js var Web3 = require("web3") @@ -56,7 +54,7 @@ web3.eth.getBlockNumber(function (error, result) { }) ``` -Se você executar este programa, ele simplesmente imprimirá o bloco mais recente: o topo do blockchain. Você também pode usar chamadas de função `await/async` para evitar aninhar (encadear por identação) chamadas de callback em seu código: +Se você executar este programa, ele simplesmente imprimirá o número do bloco mais recente: o topo da blockchain. Você também pode usar chamadas de função `async/await` para evitar o aninhamento de callbacks em seu código: ```js async function getBlockNumber() { @@ -68,27 +66,27 @@ async function getBlockNumber() { getBlockNumber() ``` -Você pode ver todas as funções disponíveis da instância Web3 na [documentação oficial do web3.js](https://docs.web3js.org/). +Você pode ver todas as funções disponíveis na instância do Web3 na [documentação oficial do web3.js](https://docs.web3js.org/). -A maioria das bibliotecas Web3 são assíncronas porque em segundo plano a biblioteca faz chamadas JSON RPC para o nó que envia os resultados. +A maioria das bibliotecas Web3 é assíncrona porque, em segundo plano, a biblioteca faz chamadas JSON-RPC para o nó, que envia o resultado de volta. -Se você estiver trabalhando no navegador, algumas carteiras injetam diretamente uma instância Web3, e você deveria tentar usá-la sempre que possível, especialmente se planeja interagir com o endereço Ethereum do usuário para fazer transações. +Se você estiver trabalhando no navegador, algumas carteiras injetam diretamente uma instância do Web3, e você deve tentar usá-la sempre que possível, especialmente se planeja interagir com o endereço Ethereum do usuário para realizar transações. -Aqui está o trecho de código para detectar se uma carteira MetaMask está disponível e tentar habilitá-la se estiver. Isso permitirá mais tarde você ler o saldo do usuário e permitir-lhe-á validar as transações que gostaria de fazer na blockchain Ethereum: +Aqui está o trecho de código para detectar se uma carteira MetaMask está disponível e tentar habilitá-la, se for o caso. Isso permitirá que você leia o saldo do usuário e que ele valide as transações que você deseja que ele realize na blockchain da Ethereum: ```js if (window.ethereum != null) { state.web3 = new Web3(window.ethereum) try { - // Request account access if needed + // Solicita acesso à conta, se necessário await window.ethereum.enable() - // Accounts now exposed + // Contas agora expostas } catch (error) { - // User denied account access... + // O usuário negou o acesso à conta... } } ``` -Alternativas para web3.js como [Ethers.js](https://docs.ethers.io/) existem e também são comumente usadas. No próximo tutorial, veremos [como escutar facilmente novos blocos recebidos na blockchain e ver o que eles contêm](https://ethereumdev.io/listening-to-new-transactions-happening-on-the-blockchain/). +Existem alternativas ao web3.js, como o [Ethers.js](https://docs.ethers.io/), que também são comumente usadas. No próximo tutorial, veremos [como escutar facilmente os novos blocos que chegam na blockchain e ver o que eles contêm](https://ethereumdev.io/listening-to-new-transactions-happening-on-the-blockchain/). diff --git a/public/content/translations/pt-br/developers/tutorials/short-abi/index.md b/public/content/translations/pt-br/developers/tutorials/short-abi/index.md index 4ce396e010e..92a65ea54f3 100644 --- a/public/content/translations/pt-br/developers/tutorials/short-abi/index.md +++ b/public/content/translations/pt-br/developers/tutorials/short-abi/index.md @@ -1,85 +1,106 @@ --- -title: "ABIs curtos para otimização de dados de chamada" -description: Otimizando contratos inteligentes para Rollups Otimistas +title: "ABIs curtos para otimização de Calldata" +description: Otimizando contratos inteligentes para Optimistic Rollups author: Ori Pomerantz lang: pt-br -tags: - - "camada 2" +tags: [ "camada 2" ] skill: intermediate published: 2022-04-01 --- ## Introdução {#introduction} -Neste artigo, você aprenderá sobre [optimistic rollups](/developers/docs/scaling/optimistic-rollups), os custos das transações e como essa estrutura de custos diferente nos obriga a otimizar coisas diferentes do que fazemos na Ethereum Mainnet. Você também aprenderá como implementar essa otimização. +Neste artigo, você aprenderá sobre [optimistic rollups](/developers/docs/scaling/optimistic-rollups), o custo das transações neles, e como essa estrutura de custos diferente exige que otimizemos para coisas diferentes do que na Rede Principal do Ethereum. +Você também aprende como implementar essa otimização. ### Divulgação completa {#full-disclosure} -Eu sou funcionário em tempo integral da [Optimism](https://www.optimism.io/), então os exemplos neste artigo serão executados na Optimism. No entanto, a técnica explicada aqui deve funcionar para outras rollups também. +Sou funcionário em tempo integral da [Optimism](https://www.optimism.io/), então os exemplos deste artigo serão executados na Optimism. +No entanto, a técnica explicada aqui deve funcionar tão bem para outros rollups. ### Terminologia {#terminology} -Quando se discute rollups, o termo 'camada 1' (L1) é usado para a Mainnet, a rede Ethereum de produção. O termo 'camada 2' (L2) é usado para a rollup ou qualquer outro sistema que depende do L1 para segurança, mas faz a maior parte de seu processamento fora da cadeia +Ao discutir rollups, o termo 'camada 1' (L1) é usado para a Rede Principal, a rede de produção da Ethereum. +O termo 'camada 2' (L2) é usado para o rollup ou qualquer outro sistema que dependa da L1 para segurança, mas que faça a maior parte de seu processamento fora da cadeia. ## Como podemos reduzir ainda mais o custo das transações L2? {#how-can-we-further-reduce-the-cost-of-L2-transactions} -[Optimistic rollups](/developers/docs/scaling/optimistic-rollups) tem que preservar um registro de cada transação histórica para que qualquer pessoa possa passar por elas e verificar se o estado atual está correto. A forma mais barata de obter dados na Ethereum Mainnet é escrevê-los como calldata. Esta solução foi escolhida por ambos [Optimism](https://help.optimism.io/hc/en-us/articles/4413163242779-What-is-a-rollup-) e [Arbitrum](https://developer.offchainlabs.com/docs/rollup_basics#intro-to-rollups). +Os [Optimistic rollups](/developers/docs/scaling/optimistic-rollups) precisam preservar um registro de todas as transações históricas para que qualquer pessoa possa analisá-las e verificar se o estado atual está correto. +A forma mais barata de inserir dados na Rede Principal do Ethereum é gravá-los como calldata. +Esta solução foi escolhida tanto pela [Optimism](https://help.optimism.io/hc/en-us/articles/4413163242779-What-is-a-rollup-) quanto pela [Arbitrum](https://developer.offchainlabs.com/docs/rollup_basics#intro-to-rollups). ### Custo das transações L2 {#cost-of-l2-transactions} O custo das transações L2 é composto por dois componentes: 1. Processamento L2, que geralmente é extremamente barato -2. Armazenamento L1, vinculado aos custos de gas da Mainnet +2. Armazenamento L1, que está atrelado aos custos de gás da Rede Principal -No momento em que escrevo isso, no Optimism, o custo do gas L2 é de 0,001 [Gwei](/developers/docs/gas/#pre-london). O custo do gas na L1 é de aproximadamente 40 gwei. [Você pode ver os preços atuais aqui](https://public-grafana.optimism.io/d/9hkhMxn7z/public-dashboard?orgId=1&refresh=5m). +No momento em que escrevo isto, na Optimism o custo do gás L2 é de 0,001 [Gwei](/developers/docs/gas/#pre-london). +O custo do gás na L1, por outro lado, é de aproximadamente 40 gwei. +[Você pode ver os preços atuais aqui](https://public-grafana.optimism.io/d/9hkhMxn7z/public-dashboard?orgId=1&refresh=5m). -Um byte de dado da chamada custa, ou 4 gas (se for zero), ou 16 gas (se for qualquer outro valor). Uma das operações mais caras no EVM é escrever no storage. O custo máximo de escrever uma palavra de 32 bytes para armazenamento na L2 é de 22100 gas. Atualmente, isso é 22.1 gwei. Portanto, se nós pudermos salvar um único byte zero de calldata, poderemos gravar cerca de 200 bytes no armazenamento e ainda sairemos ganhando. +Um byte de calldata custa 4 de gás (se for zero) ou 16 de gás (se for qualquer outro valor). +Uma das operações mais caras na EVM é gravar no armazenamento. +O custo máximo para gravar uma palavra de 32 bytes no armazenamento em L2 é de 22.100 de gás. Atualmente, isso é 22.1 gwei. +Portanto, se conseguirmos economizar um único byte zero de calldata, poderemos gravar cerca de 200 bytes no armazenamento e ainda sair ganhando. -### O ABI {#the-abi} +### A ABI {#the-abi} -A grande maioria das transações acessa um contrato de uma conta de propriedade externa. A maioria dos contratos é escrita em Solidity e interpreta seu campo de dados de acordo com a [interface binária do aplicativo (ABI)](https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding). +A grande maioria das transações acessa um contrato de uma conta de propriedade externa. +A maioria dos contratos é escrita em Solidity e interpreta seu campo de dados de acordo com a [interface binária de aplicação (ABI)](https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding). -No entanto, a ABI foi projetada para L1, em que um byte de dados da chamada custa aproximadamente o mesmo que quatro operações aritméticas, não para L2, em que um byte de dados da chamada custa mais de mil operações aritméticas. Por exemplo, [aqui está uma transação de transferência ERC-20](https://kovan-optimistic.etherscan.io/tx/0x7ce4c144ebfce157b4de99d8ad53a352ae91b57b3fa06d8a1c79439df6bfa998). Os dados da chamada são divididos da seguinte forma: +No entanto, a ABI foi projetada para a L1, onde um byte de calldata custa aproximadamente o mesmo que quatro operações aritméticas, e não para a L2, onde um byte de calldata custa mais de mil operações aritméticas. +O calldata é dividido da seguinte forma: -| Seção | Comprimento | Bytes | Bytes gastos | Gas gasto | Bytes necessários | Gas necessário | -| ------------------- | -----------:| -----:| ------------:| ---------:| -----------------:| --------------:| -| Seletor de função | 4 | 0-3 | 3 | 48 | 1 | 16 | -| Zeros | 12 | 4-15 | 12 | 48 | 0 | 0 | -| Endereço de destino | 20 | 16-35 | 0 | 0 | 20 | 320 | -| Quantidade | 32 | 16-35 | 17 | 64 | 15 | 240 | -| Total | 68 | | | 576 | | 576 | +| Seção | Comprimento | Bytes | Bytes desperdiçados | Gás desperdiçado | Bytes necessários | Gás necessário | +| ------------------- | ----------: | ----: | ------------------: | ---------------: | ----------------: | -------------: | +| Seletor de função | 4 | 0-3 | 3 | 48 | 1 | 16 | +| Zeros | 12 | 4-15 | 12 | 48 | 0 | 0 | +| Endereço de destino | 20 | 16-35 | 0 | 0 | 20 | 320 | +| Quantidade | 32 | 36-67 | 17 | 64 | 15 | 240 | +| Total | 68 | | | 160 | | 576 | Explicação: -- **Seletor de funções**: O contrato tem menos de 256 funções, portanto podemos distingui-las com um único byte. Esses bytes são tipicamente diferentes de zero e, portanto, [custam dezesseis gás](https://eips.ethereum.org/EIPS/eip-2028). -- **Zeros**: Esses bytes são sempre zero porque um endereço de vinte bytes não requer uma palavra de trinta e dois bytes para usá-lo. Bytes que possuem zero custam quatro gas ([consulte o yellow paper](https://ethereum.github.io/yellowpaper/paper.pdf), Apêndice G, pág. 27, o valor para `G``txdatazero`). -- **Quantia**: Se nós assumirmos que neste contrato `decimais` são dezoito (o valor normal) e o valor máximo de tokens que nós transferimos será 1018, nós temos uma quantia máxima de 1036. 25615 > 1036, então quinze bytes são suficientes. +- **Seletor de função**: o contrato tem menos de 256 funções, então podemos distingui-las com um único byte. + Esses bytes normalmente não são zero e, portanto, [custam dezesseis de gás](https://eips.ethereum.org/EIPS/eip-2028). +- **Zeros**: esses bytes são sempre zero porque um endereço de vinte bytes não requer uma palavra de trinta e dois bytes para o conter. + Bytes que contêm zero custam quatro de gás ([consulte o yellow paper](https://ethereum.github.io/yellowpaper/paper.pdf), Apêndice G, + p. 27, o valor para `G``txdatazero`). +- **Quantidade**: se assumirmos que neste contrato `decimals` é dezoito (o valor normal) e a quantidade máxima de tokens que transferimos será 1018, obteremos uma quantidade máxima de 1036. + 25615 > 1036, então quinze bytes são suficientes. -Um gasto de 160 gas na L1 é normalmente insignificante. Uma transação custa pelo menos [21.000 gas](https://yakkomajuri.medium.com/blockchain-definition-of-the-week-ethereum-gas-2f976af774ed), então um extra de 0,8% não importa. Entretanto, na L2, as coisas são diferentes. Quase o custo inteiro da transação é escrevendo-o na L1. Em adição ao calldata da transação, há 109 bytes de cabeçalho de transação (endereço de destino, assinatura, etc.). O custo total é portanto `109*16+576+160=2480`, e nós estamos desperdiçando cerca de 6,5% disso. +Um desperdício de 160 de gás na L1 é normalmente insignificante. Uma transação custa pelo menos [21.000 de gás](https://yakkomajuri.medium.com/blockchain-definition-of-the-week-ethereum-gas-2f976af774ed), então 0,8% a mais não importa. +Entretanto, na L2, as coisas são diferentes. Quase todo o custo da transação é para gravá-la na L1. +Além do calldata da transação, há 109 bytes de cabeçalho da transação (endereço de destino, assinatura etc.). +O custo total é, portanto, `109*16+576+160=2480`, e estamos desperdiçando cerca de 6,5% disso. ## Reduzindo custos quando você não controla o destino {#reducing-costs-when-you-dont-control-the-destination} -Assumindo que você não tem controle sobre o contrato de destino, você pode ainda usar uma solução similar a [esta](https://github.com/qbzzt/ethereum.org-20220330-shortABI). Vamos passar pelos arquivos relevantes. +Assumindo que você não tenha controle sobre o contrato de destino, você ainda pode usar uma solução semelhante a [esta](https://github.com/qbzzt/ethereum.org-20220330-shortABI). +Vamos rever os arquivos relevantes. ### Token.sol {#token-sol} -[Este é o contrato destino](https://github.com/qbzzt/ethereum.org-20220330-shortABI/blob/master/contracts/Token.sol). É um contrato ERC-20 padrão, com um recurso adicional. Esta função `faucet` permite qualquer usuário obter algum token para usar. Ele faria o contrato de produção ERC-20 inútil, mas ele facilita a vida quando um ERC-20 existe somente para facilitar o teste. +[Este é o contrato de destino](https://github.com/qbzzt/ethereum.org-20220330-shortABI/blob/master/contracts/Token.sol). +É um contrato padrão ERC-20, com um recurso adicional. +Esta função `faucet` permite que qualquer usuário obtenha alguns tokens para usar. +Isso tornaria um contrato de produção ERC-20 inútil, mas facilita as coisas quando um ERC-20 existe apenas para facilitar os testes. ```solidity /** - * @dev Gives the caller 1000 tokens to play with + * @dev Fornece ao chamador 1000 tokens para usar */ function faucet() external { _mint(msg.sender, 1000); } // function faucet ``` -[Você pode ver um exemplo deste contrato sendo implantado aqui](https://kovan-optimistic.etherscan.io/address/0x950c753c0edbde44a74d3793db738a318e9c8ce8). - ### CalldataInterpreter.sol {#calldatainterpreter-sol} -[Este é o contrato que transações devem chamar com calldata menor](https://github.com/qbzzt/ethereum.org-20220330-shortABI/blob/master/contracts/CalldataInterpreter.sol). Vamos passar por ele linha a linha. +[Este é o contrato que as transações devem chamar com calldata mais curto](https://github.com/qbzzt/ethereum.org-20220330-shortABI/blob/master/contracts/CalldataInterpreter.sol). +Vamos analisá-lo linha por linha. ```solidity //SPDX-License-Identifier: Unlicense @@ -89,7 +110,7 @@ pragma solidity ^0.8.0; import { OrisUselessToken } from "./Token.sol"; ``` -Nós precisamos da função do token para saber como chamá-lo. +Precisamos da função do token para saber como chamá-la. ```solidity contract CalldataInterpreter { @@ -97,13 +118,13 @@ contract CalldataInterpreter { OrisUselessToken public immutable token; ``` -O endereço do token para o qual nós somos um proxy. +O endereço do token para o qual somos um proxy. ```solidity /** - * @dev Specify the token address - * @param tokenAddr_ ERC-20 contract address + * @dev Especifique o endereço do token + * @param tokenAddr_ Endereço do contrato ERC-20 */ constructor( address tokenAddr_ @@ -112,14 +133,14 @@ O endereço do token para o qual nós somos um proxy. } // constructor ``` -O endereço do token é o único parâmetro que nós precisamos especificar. +O endereço do token é o único parâmetro que precisamos especificar. ```solidity function calldataVal(uint startByte, uint length) private pure returns (uint) { ``` -Ler um valor do calldata. +Leia um valor do calldata. ```solidity uint _retVal; @@ -131,7 +152,9 @@ Ler um valor do calldata. "calldataVal trying to read beyond calldatasize"); ``` -Nós iremos carregar uma simples palavra de 32-bytes (256-bit) para a memória e remover os bytes que não são parte do campo que nós queremos. Este algoritmo não funciona para valores maiores que 32 bytes, e claro, não podemos ler depois do fim do calldata. Na L1 pode ser necessário pular estes testes para economizar gas, mas na L2 o gas é extremamente barato, o que permite qualquer checagem de sanidade que possamos pensar. +Vamos carregar uma única palavra de 32 bytes (256 bits) para a memória e remover os bytes que não fazem parte do campo que queremos. +Este algoritmo não funciona para valores maiores que 32 bytes e, claro, não podemos ler além do final do calldata. +Na L1, pode ser necessário pular esses testes para economizar gás, mas na L2 o gás é extremamente barato, o que permite quaisquer verificações de sanidade que possamos imaginar. ```solidity assembly { @@ -139,16 +162,18 @@ Nós iremos carregar uma simples palavra de 32-bytes (256-bit) para a memória e } ``` -Nós poderiamos ter copiado os dados da chamada ao `fallback()` (veja abaixo), mas é mais fácil usar [Yul](https://docs.soliditylang.org/en/v0.8.12/yul.html), a linguagem de montagem da EVM. +Poderíamos ter copiado os dados da chamada para `fallback()` (veja abaixo), mas é mais fácil usar [Yul](https://docs.soliditylang.org/en/v0.8.12/yul.html), a linguagem assembly da EVM. -Aqui nós usamos [o opcode CALLDATALOAD](https://www.evm.codes/#35) para ler bytes `startByte` até `startByte+31` na pilha. Em geral, a sintaxe de um opcode em Yul é `(,...)`. +Aqui usamos [o opcode CALLDATALOAD](https://www.evm.codes/#35) para ler os bytes de `startByte` a `startByte+31` na pilha. +Em geral, a sintaxe de um opcode em Yul é `(,...)`. ```solidity _retVal = _retVal >> (256-length*8); ``` -Somente os bytes mais `length` significantes são parte do campo, então nós fazemos [right-shift](https://en.wikipedia.org/wiki/Logical_shift) para se livrar dos outros valores. Isto tem a vantagem adicional de mover o valor para a direita do campo, então é o valor por ele mesmo, ao invés do valor vezes 256alguma coisa. +Apenas os bytes de `comprimento` mais significativos fazem parte do campo, então nós [deslocamos para a direita](https://en.wikipedia.org/wiki/Logical_shift) para nos livrarmos dos outros valores. +Isso tem a vantagem adicional de mover o valor para a direita do campo, então é o valor em si, e não o valor vezes 256algo. ```solidity @@ -159,7 +184,8 @@ Somente os bytes mais `length` significantes são parte do campo, então nós fa fallback() external { ``` -Quando uma chamada a um contrato Solidity não encontra nenhuma das assinaturas de função, ela chama a função [the `fallback()`](https://docs.soliditylang.org/en/v0.8.12/contracts.html#fallback-function) (assumindo que exista uma). No caso de `CalldataInterpreter`, _qualquer_ chamada chega aqui porque não há outras funções `external` ou `public`. +Quando uma chamada para um contrato Solidity não corresponde a nenhuma das assinaturas de função, ela chama [a função `fallback()`](https://docs.soliditylang.org/en/v0.8.12/contracts.html#fallback-function) (supondo que haja uma). +No caso do `CalldataInterpreter`, _qualquer_ chamada chega aqui porque não há outras funções `external` ou `public`. ```solidity uint _func; @@ -167,17 +193,21 @@ Quando uma chamada a um contrato Solidity não encontra nenhuma das assinaturas _func = calldataVal(0, 1); ``` -Leia o primeiro byte do calldata, que nos conta a função. Há duas razões porque uma função não estaria disponível aqui: +Leia o primeiro byte do calldata, que nos diz a função. +Há duas razões pelas quais uma função não estaria disponível aqui: -1. Funções que são `pure` ou `view` não mudam seu estado e não custam gas (quando chamadas off-chain). Não faz sentido tentar reduzir seus custos de gas. -2. Funções que confiam em [`msg.sender`](https://docs.soliditylang.org/en/v0.8.12/units-and-global-variables.html#block-and-transaction-properties). O valor de `msg.sender` será o endereço do `CalldataInterpreter`, não o chamador. +1. Funções que são `pure` ou `view` não alteram o estado e não custam gás (quando chamadas fora da cadeia). + Não faz sentido tentar reduzir seu custo de gás. +2. Funções que dependem de [`msg.sender`](https://docs.soliditylang.org/en/v0.8.12/units-and-global-variables.html#block-and-transaction-properties). + O valor de `msg.sender` será o endereço do `CalldataInterpreter`, não o do chamador. -Infelizmente, [olhando as especificações do ERC-20](https://eips.ethereum.org/EIPS/eip-20), isto deixa apenas uma função, `transfer`. Isto nos deixa com somente duas funções: `transfer` (porque nós podemos chamar `transferFrom`) e `faucet` (porque nós podemos transferir os tokens de volta a quem quer tenha nos chamado). +Infelizmente, [olhando para as especificações do ERC-20](https://eips.ethereum.org/EIPS/eip-20), isso deixa apenas uma função, `transfer`. +Isso nos deixa com apenas duas funções: `transfer` (porque podemos chamar `transferFrom`) e `faucet` (porque podemos transferir os tokens de volta para quem nos chamou). ```solidity - // Call the state changing methods of token using - // information from the calldata + // Chame os métodos de alteração de estado do token usando + // informações do calldata // faucet if (_func == 1) { @@ -192,43 +222,46 @@ Uma chamada para `faucet()`, que não tem parâmetros. } ``` -Depois que nós chamamos `token.faucet()` nós obtivemos tokens. Entretanto, como o contrato proxy, nós não **precisamos** de tokens. O EOA (externally owned account) ou contrato que nos chamou o faz. Então nós transferimos todos nossos tokens para quem quer tenha nos chamado. +Depois que chamamos `token.faucet()`, nós recebemos tokens. No entanto, como o contrato de proxy, não **precisamos** de tokens. +A EOA (conta de propriedade externa) ou contrato que nos chamou precisa. +Então, transferimos todos os nossos tokens para quem nos chamou. ```solidity - // transfer (assume we have an allowance for it) + // transferir (assumir que temos uma permissão para isso) if (_func == 2) { ``` -Transferir tokens requer dois parâmetros: o endereço de destino e a quantidade. +A transferência de tokens requer dois parâmetros: o endereço de destino e a quantidade. ```solidity token.transferFrom( msg.sender, ``` -Nós apenas permitimos chamadores transferir tokens que eles possuam +Nós apenas permitimos que os chamadores transfiram tokens que eles possuem ```solidity address(uint160(calldataVal(1, 20))), ``` -O endereço de destino começa no byte 1 (o byte 0 é a função). Como um endereço, ele tem 20-bytes de comprimento. +O endereço de destino começa no byte #1 (o byte #0 é a função). +Como um endereço, ele tem 20 bytes de comprimento. ```solidity calldataVal(21, 2) ``` -Para esse contrato em particular nós assumimos que o número máximo de tokens que qualquer um poderia querer transferir cabe em dois bytes (menos que 65536). +Para este contrato em particular, assumimos que o número máximo de tokens que alguém gostaria de transferir cabe em dois bytes (menos de 65536). ```solidity ); } ``` -Em geral, uma transferência pega 35 bytes de calldata: +No geral, uma transferência leva 35 bytes de calldata: | Seção | Comprimento | Bytes | -| ------------------- | -----------:| -----:| +| ------------------- | ----------: | ----: | | Seletor de função | 1 | 0 | | Endereço de destino | 32 | 1-32 | | Quantidade | 2 | 33-34 | @@ -241,13 +274,14 @@ Em geral, uma transferência pega 35 bytes de calldata: ### test.js {#test-js} -[Este teste unitário JavaScript](https://github.com/qbzzt/ethereum.org-20220330-shortABI/blob/master/test/test.js) nos mostra como usar este mecanismo (e como verificar que ele trabalha corretamente). Parto do princípio que você entendeu [chai](https://www.chaijs.com/) e [ethers](https://docs.ethers.io/v5/) e apenas explicar as partes que especificamente se aplicam ao contrato. +[Este teste de unidade JavaScript](https://github.com/qbzzt/ethereum.org-20220330-shortABI/blob/master/test/test.js) nos mostra como usar este mecanismo (e como verificar se ele funciona corretamente). +Vou supor que você entende [chai](https://www.chaijs.com/) e [ethers](https://docs.ethers.io/v5/) e explicar apenas as partes que se aplicam especificamente ao contrato. ```js const { expect } = require("chai"); describe("CalldataInterpreter", function () { - it("Should let us use tokens", async function () { + it("Deve nos permitir usar tokens", async function () { const Token = await ethers.getContractFactory("OrisUselessToken") const token = await Token.deploy() await token.deployed() @@ -261,24 +295,27 @@ describe("CalldataInterpreter", function () { const signer = await ethers.getSigner() ``` -Nós começamos por implantar ambos contratos. +Começamos implantando ambos os contratos. ```javascript - // Get tokens to play with + // Obter tokens para usar const faucetTx = { ``` -Nós não podemos usar funções de alto nível que nós normalmente usamos (como `token.faucet()`) para criar transações, porque nós não seguimos o ABI. Ao invés disso, nós temos que construir a transação nós mesmos e enviá-la. +Não podemos usar as funções de alto nível que normalmente usaríamos (como `token.faucet()`) para criar transações, porque não seguimos a ABI. +Em vez disso, temos que construir a transação nós mesmos e depois enviá-la. ```javascript to: cdi.address, data: "0x01" ``` -Há dois parâmetros que nós precisamos fornecer para a transação: +Existem dois parâmetros que precisamos fornecer para a transação: -1. `to`, o endereço de destino. Isto é o contrato interpretador do calldata. -2. `data`, o calldata a enviar. No caso de uma chamada de faucet, o dado é um único byte, `0x01`. +1. `to`, o endereço de destino. + Este é o contrato interpretador de calldata. +2. `data`, o calldata a ser enviado. + No caso de uma chamada de faucet, os dados são um único byte, `0x01`. ```javascript @@ -286,26 +323,27 @@ Há dois parâmetros que nós precisamos fornecer para a transação: await (await signer.sendTransaction(faucetTx)).wait() ``` -Nós chamamos o método `sendTransaction` do [assinante](https://docs.ethers.io/v5/api/signer/#Signer-sendTransaction) porque nós já especificamos o destino (`faucetTx.to`) e nós precisamos que a transação seja assinada. +Chamamos o [método `sendTransaction` do assinante](https://docs.ethers.io/v5/api/signer/#Signer-sendTransaction) porque já especificamos o destino (`faucetTx.to`) e precisamos que a transação seja assinada. ```javascript -// Check the faucet provides the tokens correctly +// Verifique se o faucet fornece os tokens corretamente expect(await token.balanceOf(signer.address)).to.equal(1000) ``` -Aqui nós verificamos o saldo. Não há necessidade de economizar gas em funções `view`, então nós só as rodamos normalmente. +Aqui verificamos o saldo. +Não há necessidade de economizar gás em funções `view`, então apenas as executamos normalmente. ```javascript -// Give the CDI an allowance (approvals cannot be proxied) +// Dê ao CDI uma permissão (aprovações não podem ser intermediadas por proxy) const approveTX = await token.approve(cdi.address, 10000) await approveTX.wait() expect(await token.allowance(signer.address, cdi.address)).to.equal(10000) ``` -Dar ao intérprete calldata uma permissão para ser capaz de fazer transferências. +Dê ao interpretador de calldata uma permissão para poder fazer transferências. ```javascript -// Transfer tokens +// Transferir tokens const destAddr = "0xf5a6ead936fb47f342bb63e676479bddf26ebe1d" const transferTx = { to: cdi.address, @@ -313,53 +351,50 @@ const transferTx = { } ``` -Criar uma transação de transferência. O primeiro byte é "0x02", seguido pelo endereço de destino, e finalmente a quantia (0x0100, que é 256 em decimal). +Crie uma transação de transferência. O primeiro byte é "0x02", seguido pelo endereço de destino e, finalmente, a quantidade (0x0100, que é 256 em decimal). ```javascript await (await signer.sendTransaction(transferTx)).wait() - // Check that we have 256 tokens less + // Verifique se temos 256 tokens a menos expect (await token.balanceOf(signer.address)).to.equal(1000-256) - // And that our destination got them + // E que nosso destino os recebeu expect (await token.balanceOf(destAddr)).to.equal(256) }) // it }) // describe ``` -### Exemplo {#example} - -Se você quiser ver estes arquivos em ação sem precisar rodá-los, siga estes links: - -1. [Implantação de `OrisUselessToken`](https://kovan-optimistic.etherscan.io/tx/1410744) no [endereço `0x950c753c0edbde44a74d3793db738a318e9c8ce8`](https://kovan-optimistic.etherscan.io/address/0x950c753c0edbde44a74d3793db738a318e9c8ce8). -2. [Implantação de `CalldataInterpreter`](https://kovan-optimistic.etherscan.io/tx/1410745) no [endereço `0x16617fea670aefe3b9051096c0eb4aeb4b3a5f55`](https://kovan-optimistic.etherscan.io/address/0x16617fea670aefe3b9051096c0eb4aeb4b3a5f55). -3. [Chamada para `faucet()`](https://kovan-optimistic.etherscan.io/tx/1410746). -4. [Chamada para `OrisUselessToken.approve()`](https://kovan-optimistic.etherscan.io/tx/1410747). Esta chamada tem de ir diretamente para o contrato do token porque o processamento confia no `msg.sender`. -5. [Chamada para `transfer()`](https://kovan-optimistic.etherscan.io/tx/1410748). - -## Reduzindo o custo quando você controla o contrato destino {#reducing-the-cost-when-you-do-control-the-destination-contract} +## Reduzindo o custo quando você controla o contrato de destino {#reducing-the-cost-when-you-do-control-the-destination-contract} -Se você realmente tem controle sobre o contrato destino, você pode criar funções que ignoram as checagens do `msg.sender` porque eles acreditam no intérprete do calldata. [Você pode ver um exemplo de como isto funciona aqui, no branch `control-contract`](https://github.com/qbzzt/ethereum.org-20220330-shortABI/tree/control-contract). +Se você tiver controle sobre o contrato de destino, poderá criar funções que contornem as verificações do `msg.sender` porque elas confiam no interpretador de calldata. +[Você pode ver um exemplo de como isso funciona aqui, na ramificação `control-contract`](https://github.com/qbzzt/ethereum.org-20220330-shortABI/tree/control-contract). -Se o contrato estiver respondendo somente para transações externas, nós poderíamos ter apenas um contrato. Entretanto, isso iria quebrar [a capacidade de composição](/developers/docs/smart-contracts/composability/). É bem melhor ter um contrato que responda a chamadas ERC-20 normais, e outro contrato que responda a transações com chamadas curtas de dados. +Se o contrato estivesse respondendo apenas a transações externas, poderíamos nos virar com apenas um contrato. +No entanto, isso quebraria a [componibilidade](/developers/docs/smart-contracts/composability/). +É muito melhor ter um contrato que responda a chamadas normais de ERC-20 e outro contrato que responda a transações com dados de chamada curtos. ### Token.sol {#token-sol-2} -Neste exemplo nós podemos modificar `Token.sol`. Isto nos deixa ter um número de funções que somente o proxy pode chamar. Eis aqui as novas partes: +Neste exemplo, podemos modificar `Token.sol`. +Isso nos permite ter várias funções que apenas o proxy pode chamar. +Aqui estão as novas partes: ```solidity - // The only address allowed to specify the CalldataInterpreter address + // O único endereço com permissão para especificar o endereço do CalldataInterpreter address owner; - // The CalldataInterpreter address + // O endereço do CalldataInterpreter address proxy = address(0); ``` -O contrato ERC-20 precisa saber a identidade do proxy autorizado. Entretanto, nós não podemos configurar esta variável no construtor, porque nós não sabemos o valor ainda. Este contrato é instanciado primeiro porque o proxy espera o endereço do token no seu construtor. +O contrato ERC-20 precisa saber a identidade do proxy autorizado. +No entanto, não podemos definir essa variável no construtor, porque ainda não sabemos o valor. +Este contrato é instanciado primeiro porque o proxy espera o endereço do token em seu construtor. ```solidity /** - * @dev Calls the ERC20 constructor. + * @dev Chama o construtor ERC20. */ constructor( ) ERC20("Oris useless token-2", "OUT-2") { @@ -367,47 +402,50 @@ O contrato ERC-20 precisa saber a identidade do proxy autorizado. Entretanto, n } ``` -O endereço do criador (chamado`owner`) é armazenado aqui porque este é o único endereço permitido para configurar o proxy. +O endereço do criador (chamado `owner`) é armazenado aqui porque esse é o único endereço com permissão para definir o proxy. ```solidity /** - * @dev set the address for the proxy (the CalldataInterpreter). - * Can only be called once by the owner + * @dev define o endereço para o proxy (o CalldataInterpreter). + * Só pode ser chamado uma vez pelo proprietário */ function setProxy(address _proxy) external { - require(msg.sender == owner, "Can only be called by owner"); - require(proxy == address(0), "Proxy is already set"); + require(msg.sender == owner, "Só pode ser chamado pelo proprietário"); + require(proxy == address(0), "O proxy já foi definido"); proxy = _proxy; } // function setProxy ``` -O proxy tem acesso privilegiado, porque ele pode ignorar checagens de segurança. Para garantir que nós podemos acreditar no proxy, nós somente deixamos `owner` chamar esta função, e somente uma vez. Uma vez que `proxy` tenha um valor real (não zero), este valor não pode mudar, então mesmo se o proprietário decide se tornar trapaceiro, ou caso o mnemônico seja revelado a ele, nós ainda estamos seguros. +O proxy tem acesso privilegiado, porque pode contornar as verificações de segurança. +Para garantir que possamos confiar no proxy, permitimos que apenas `owner` chame esta função, e apenas uma vez. +Uma vez que `proxy` tem um valor real (diferente de zero), esse valor não pode mudar, então mesmo que o proprietário decida se tornar malicioso, ou o mnemônico para ele seja revelado, ainda estamos seguros. ```solidity /** - * @dev Some functions may only be called by the proxy. + * @dev Algumas funções só podem ser chamadas pelo proxy. */ modifier onlyProxy { ``` -Isto é uma função [`modifier`](https://www.tutorialspoint.com/solidity/solidity_function_modifiers.htm), ela modifica a maneira que outras funções trabalham. +Esta é uma [função `modifier`](https://www.tutorialspoint.com/solidity/solidity_function_modifiers.htm), que modifica a forma como outras funções funcionam. ```solidity require(msg.sender == proxy); ``` -Primeiro, verifique que nós fomos chamados pelo proxy e ninguém mais. Se não, `revert`. +Primeiro, verifique se fomos chamados pelo proxy e por mais ninguém. +Se não, `reverta`. ```solidity _; } ``` -Neste caso, rode a função que nós modificamos. +Se sim, execute a função que modificamos. ```solidity - /* Functions that allow the proxy to actually proxy for accounts */ + /* Funções que permitem que o proxy realmente atue como proxy para as contas */ function transferProxy(address from, address to, uint256 amount) public virtual onlyProxy() returns (bool) @@ -436,17 +474,18 @@ Neste caso, rode a função que nós modificamos. } ``` -Há três operações que normalmente requerem que a mensagem venha direto da entidade transferindo tokens ou aprovando uma permissão. Aqui nós temos uma versão de proxy destas operações que: +Estas são três operações que normalmente exigem que a mensagem venha diretamente da entidade que transfere tokens ou aprova uma permissão. +Aqui temos uma versão proxy dessas operações que: -1. É modificada pelo `onlyProxy()`, de modo que ninguém mais tem permissão de controlá-los. -2. Pega o endereço que seria normalmente `msg.sender` como um parâmetro extra. +1. É modificada por `onlyProxy()` para que ninguém mais possa controlá-las. +2. Recebe o endereço que normalmente seria `msg.sender` como um parâmetro extra. ### CalldataInterpreter.sol {#calldatainterpreter-sol-2} -O interpretador calldata é praticamente idêntico ao acima, exceto que as funções com proxy recebem um parâmetro `msg.sender` e não há necessidade de permissão `transfer`. +O interpretador de calldata é quase idêntico ao anterior, exceto que as funções com proxy recebem um parâmetro `msg.sender` e não há necessidade de uma permissão para `transfer`. ```solidity - // transfer (no need for allowance) + // transferir (não é necessária permissão) if (_func == 2) { token.transferProxy( msg.sender, @@ -455,7 +494,7 @@ O interpretador calldata é praticamente idêntico ao acima, exceto que as funç ); } - // approve + // aprovar if (_func == 3) { token.approveProxy( msg.sender, @@ -464,7 +503,7 @@ O interpretador calldata é praticamente idêntico ao acima, exceto que as funç ); } - // transferFrom + // transferirDe if (_func == 4) { token.transferFromProxy( msg.sender, @@ -477,7 +516,7 @@ O interpretador calldata é praticamente idêntico ao acima, exceto que as funç ### Test.js {#test-js-2} -Há pequenas mudanças entre o código de teste anterior e este. +Existem algumas alterações entre o código de teste anterior e este. ```js const Cdi = await ethers.getContractFactory("CalldataInterpreter") @@ -486,21 +525,22 @@ await cdi.deployed() await token.setProxy(cdi.address) ``` -Nós precisamos contar ao contrato ERC-20 qual proxy acreditar +Precisamos dizer ao contrato ERC-20 em qual proxy confiar ```js console.log("CalldataInterpreter addr:", cdi.address) -// Need two signers to verify allowances +// Precisa de dois assinantes para verificar as permissões const signers = await ethers.getSigners() const signer = signers[0] const poorSigner = signers[1] ``` -Para checar `approve()` e `transferFrom()` nós precisamos de um segundo assinante. Nós o chamamos de `poorSigner` porque ele não pega nenhum de nossos tokens (ele precisa ter ETH, claro). +Para verificar `approve()` e `transferFrom()`, precisamos de um segundo assinante. +Nós o chamamos de `poorSigner` porque ele não recebe nenhum de nossos tokens (ele precisa ter ETH, é claro). ```js -// Transfer tokens +// Transferir tokens const destAddr = "0xf5a6ead936fb47f342bb63e676479bddf26ebe1d" const transferTx = { to: cdi.address, @@ -509,10 +549,10 @@ const transferTx = { await (await signer.sendTransaction(transferTx)).wait() ``` -Como o contrato ERC-20 confia no proxy (`cdi`), nós não precisamos de uma permissão para confiar em transferências. +Como o contrato ERC-20 confia no proxy (`cdi`), não precisamos de uma permissão para retransmitir transferências. ```js -// approval and transferFrom +// aprovação e transferirDe const approveTx = { to: cdi.address, data: "0x03" + poorSigner.address.slice(2, 42) + "00FF", @@ -527,24 +567,19 @@ const transferFromTx = { } await (await poorSigner.sendTransaction(transferFromTx)).wait() -// Check the approve / transferFrom combo was done correctly +// Verifique se a combinação de aprovação / transferirDe foi feita corretamente expect(await token.balanceOf(destAddr2)).to.equal(255) ``` -Teste as duas novas funções. Note que `transferFromTx` requer dois parâmetros de endereço: o que deu a permissão e o recebedor. +Teste as duas novas funções. +Observe que `transferFromTx` requer dois parâmetros de endereço: o doador da permissão e o receptor. -### Exemplo {#example-2} - -Se você quiser ver estes arquivos em ação sem precisar rodá-los, siga estes links: +## Conclusão {#conclusion} -1. [Implantação de `OrisUselessToken-2`](https://kovan-optimistic.etherscan.io/tx/1475397) no endereço [`0xb47c1f550d8af70b339970c673bbdb2594011696`](https://kovan-optimistic.etherscan.io/address/0xb47c1f550d8af70b339970c673bbdb2594011696). -2. [Implantação de `CalldataInterpreter`](https://kovan-optimistic.etherscan.io/tx/1475400) no endereço [`0x0dccfd03e3aaba2f8c4ea4008487fd0380815892`](https://kovan-optimistic.etherscan.io/address/0x0dccfd03e3aaba2f8c4ea4008487fd0380815892). -3. [Chamada para `transfer()`](https://kovan-optimistic.etherscan.io/tx/1475402). -4. [Chamada para `faucet()`](https://kovan-optimistic.etherscan.io/tx/1475409). -5. [Chamada para `transferProxy()`](https://kovan-optimistic.etherscan.io/tx/1475416). -6. [Chamada para `approveProxy()`](https://kovan-optimistic.etherscan.io/tx/1475419). -7. [Chamada para `transferFromFProxy()`](https://kovan-optimistic.etherscan.io/tx/1475421). Note que esta chamada vem de um endereço diferente dos outros, `poorSigner` ao invés de `signer`. +Tanto a [Optimism](https://medium.com/ethereum-optimism/the-road-to-sub-dollar-transactions-part-2-compression-edition-6bb2890e3e92) quanto a [Arbitrum](https://developer.offchainlabs.com/docs/special_features) estão procurando maneiras de reduzir o tamanho do calldata escrito na L1 e, portanto, o custo das transações. +No entanto, como provedores de infraestrutura em busca de soluções genéricas, nossas habilidades são limitadas. +Como desenvolvedor de dapps, você tem conhecimento específico da aplicação, o que permite otimizar seu calldata muito melhor do que poderíamos em uma solução genérica. +Esperamos que este artigo o ajude a encontrar a solução ideal para suas necessidades. -## Conclusão {#conclusion} +[Veja aqui mais do meu trabalho](https://cryptodocguy.pro/). -Ambos [Optimism](https://medium.com/ethereum-optimism/the-road-to-sub-dollar-transactions-part-2-compression-edition-6bb2890e3e92) e [Arbitrum](https://developer.offchainlabs.com/docs/special_features) estão procurando por maneiras de reduzir o tamanho do calldata escrito no L1 e portanto o custo das transações. Entretanto, como provedores de infraestrutura procurando por soluções genéricas, nossas habilidades são limitadas. Como desenvolvedor dapp, você tem conhecimento específico de aplicações, o que te leva a otimizar seu calldata muito melhor do que nós poderíamos com uma solução genérica. Esperamos que este artigo ajude você a encontrar a solução ideal para as suas necessidades. diff --git a/public/content/translations/pt-br/developers/tutorials/smart-contract-security-guidelines/index.md b/public/content/translations/pt-br/developers/tutorials/smart-contract-security-guidelines/index.md index 6053257ce85..344f34b77f0 100644 --- a/public/content/translations/pt-br/developers/tutorials/smart-contract-security-guidelines/index.md +++ b/public/content/translations/pt-br/developers/tutorials/smart-contract-security-guidelines/index.md @@ -1,21 +1,18 @@ --- -title: Diretrizes de segurança do contrato inteligente -description: Uma lista de verificações de diretrizes de segurança a considerar ao construir seu dapp +title: "Diretrizes de segurança do contrato inteligente" +description: "Uma lista de verificações de diretrizes de segurança a considerar ao construir seu dapp" author: "Trailofbits" -tags: - - "solidity" - - "contratos inteligentes" - - "segurança" +tags: [ "Solidity", "smart contracts", "segurança" ] skill: intermediate lang: pt-br published: 2020-09-06 -source: Construindo contratos seguros +source: Building secure contracts sourceUrl: https://github.com/crytic/building-secure-contracts/blob/master/development-guidelines/guidelines.md --- Siga estas recomendações de alto nível para construir contratos inteligentes mais seguros. -## Padrões de design {#design-guidelines} +## Diretrizes de design {#design-guidelines} O design do contrato deve ser discutido antecipadamente, antes de escrever qualquer linha de código. @@ -23,40 +20,40 @@ O design do contrato deve ser discutido antecipadamente, antes de escrever qualq A documentação pode ser escrita em diferentes níveis, e deve ser atualizada durante a implementação dos contratos: -- **Uma descrição simples em inglês do sistema**, descrevendo o que os contratos fazem e qualquer suposição no código. -- **Esquemas e diagramas arquitetônicos**, incluindo as interações de contratos e a máquina de estado do sistema. [Impressoras do Slither](https://github.com/crytic/slither/wiki/Printer-documentation) podem ajudar a gerar esses esquemas. -- **Documentação de código Thorough**, o [formato Natspec](https://solidity.readthedocs.io/en/develop/natspec-format.html) pode ser usado para Solidity. +- **Uma descrição em inglês simples do sistema**, descrevendo o que os contratos fazem e quaisquer suposições sobre a base de código. +- **Esquemas e diagramas de arquitetura**, incluindo as interações de contratos e a máquina de estado do sistema. Os [impressores do Slither](https://github.com/crytic/slither/wiki/Printer-documentation) podem ajudar a gerar esses esquemas. +- **Documentação completa do código**, o [formato Natspec](https://docs.soliditylang.org/en/develop/natspec-format.html) pode ser usado para o Solidity. -### Computação on-chain vs off-chain {#on-chain-vs-off-chain-computation} +### Computação onchain vs. offchain {#onchain-vs-offchain-computation} -- **Mantenha o máximo de código que puder off-chain (fora da cadeia).** Mantenha a menor camada on-chain (dentro da cadeia). Pré-processe dados com código off-chain de tal forma que a verificação on-chain torne-se simples. Você precisa de uma lista ordenada? Ordene a lista off-chain, então apenas verifique a ordem on-chain. +- **Mantenha o máximo de código que puder offchain.** Mantenha a camada onchain pequena. Pré-processe dados com código offchain de forma que a verificação onchain seja simples. Você precisa de uma lista ordenada? Ordene a lista off-chain, então apenas verifique a ordem on-chain. -### Capacidade de Atualização {#upgradeability} +### Atualizabilidade {#upgradeability} -Nós discutimos as diferentes soluções de atualização em [nosso blog](https://blog.trailofbits.com/2018/09/05/contract-upgrade-anti-patterns/). Faça ou não uma escolha deliberada para apoiar a capacidade de atualização antes de escrever qualquer código. A decisão irá influenciar como você estrutura nosso código. Em geral, recomendamos: +Discutimos as diferentes soluções de atualizabilidade em [nossa postagem no blog](https://blog.trailofbits.com/2018/09/05/contract-upgrade-anti-patterns/). Faça ou não uma escolha deliberada para apoiar a capacidade de atualização antes de escrever qualquer código. A decisão influenciará como você estrutura seu código. Em geral, recomendamos: -- **Favorecer a [migração do contrato](https://blog.trailofbits.com/2018/10/29/how-contract-migration-works/) sobre a atualização.** O sistema de migração tem muitas das mesmas vantagens do que ser atualizável, sem suas desvantagens. -- **Usando o padrão de separação de dados sobre o proxy delegatecallproxy.** Se o seu projeto tem uma separação de abstração clara, a atualizabilidade usando a separação de dados exigirá apenas alguns ajustes. O delegatecallproxy exige conhecimento de EVM e é altamente susceptível de erros. -- **Documentar o procedimento de migração/atualização antes da implantação.** Se você tiver que reagir sob o estresse sem quaisquer diretrizes, você cometerá erros. Escreva o procedimento a seguir com antecedência. Ele deve incluir: +- **Prefira a [migração de contrato](https://blog.trailofbits.com/2018/10/29/how-contract-migration-works/) em vez da atualizabilidade.** Os sistemas de migração têm muitas das mesmas vantagens que os atualizáveis, sem as suas desvantagens. +- **Usando o padrão de separação de dados em vez do delegatecallproxy.** Se o seu projeto tem uma separação de abstração clara, a atualizabilidade usando a separação de dados necessitará de apenas alguns ajustes. O delegatecallproxy exige conhecimento de EVM e é altamente susceptível de erros. +- **Documente o procedimento de migração/atualização antes da implantação.** Se você tiver que reagir sob estresse sem quaisquer diretrizes, você cometerá erros. Escreva o procedimento a seguir com antecedência. Ele deve incluir: - As exigências que iniciam os novos contratos - Onde são armazenadas as chaves e como acessá-las - Como verificar a implantação de arquivos! Desenvolva e teste um script de pós-implantação. -## Orientações de implementação {#implementation-guidelines} +## Diretrizes de implementação {#implementation-guidelines} -**Esforço pela simplicidade.** Sempre use a solução mais simples que se encaixa em seu propósito. Qualquer membro da sua equipe deve ser capaz de entender a sua solução. +**Busque a simplicidade.** Sempre use a solução mais simples que se adeque ao seu propósito. Qualquer membro da sua equipe deve ser capaz de entender a sua solução. ### Composição de funções {#function-composition} A arquitetura da sua base de código deve facilitar a revisão do seu código. Evite escolhas arquitetônicas que diminuam a capacidade de raciocínio sobre sua exatidão. -- **Divida a lógica do seu sistema**, seja por meio de vários contratos ou agrupando funções semelhantes juntas (por exemplo, autenticação, aritmética, ...). -- **Escreva funções pequenas, com um propósito claro.** Isso facilitará uma revisão mais tranquila e permitirá o teste de componentes individuais. +- **Divida a lógica do seu sistema**, seja por meio de vários contratos ou agrupando funções semelhantes (por exemplo, autenticação, aritmética, ...). +- **Escreva funções pequenas, com um propósito claro.** Isso facilitará a revisão e permitirá o teste de componentes individuais. ### Herança {#inheritance} - **Mantenha a herança gerenciável.** A herança deve ser usada para dividir a lógica, no entanto, seu projeto deve visar minimizar a profundidade e a largura da árvore de herança. -- **Use a [impressora de herança de Slither](https://github.com/crytic/slither/wiki/Printer-documentation#inheritance-graph) para verificar a hierarquia dos contratos.** A impressora de herança irá ajudá-lo a rever o tamanho da hierarquia. +- **Use o [impressor de herança](https://github.com/crytic/slither/wiki/Printer-documentation#inheritance-graph) do Slither para verificar a hierarquia dos contratos.** O impressor de herança ajudará você a revisar o tamanho da hierarquia. ### Eventos {#events} @@ -64,31 +61,31 @@ A arquitetura da sua base de código deve facilitar a revisão do seu código. E ### Evite armadilhas conhecidas {#avoid-known-pitfalls} -- **Esteja ciente dos problemas de segurança mais comuns.** Há muitos recursos on-line para aprender sobre problemas comuns, como [Ethernaut CTF](https://ethernaut.openzeppelin.com/), [Capture o Ether](https://capturetheether.com/), ou [ contratos não tão inteligentes](https://github.com/crytic/not-so-smart-contracts/). -- **Esteja ciente das seções de avisos na [documentação Solidity](https://solidity.readthedocs.io/en/latest/)** As seções de avisos irão informá-lo sobre comportamentos não óbvios da linguagem. +- **Esteja ciente dos problemas de segurança mais comuns.** Existem muitos recursos online para aprender sobre problemas comuns, como [Ethernaut CTF](https://ethernaut.openzeppelin.com/), [Capture the Ether](https://capturetheether.com/) ou [Not so smart contracts](https://github.com/crytic/not-so-smart-contracts/). +- **Esteja ciente das seções de avisos na [documentação do Solidity](https://docs.soliditylang.org/en/latest/).** As seções de avisos informarão sobre comportamentos não óbvios da linguagem. ### Dependências {#dependencies} -- **Use bibliotecas testadas.** A importação de código de bibliotecas testadas reduzirá a probabilidade de você escrever código com erros. Se você deseja escrever um contrato ERC20, use [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20). -- **Use um gerenciador de dependências; evite "copiar-e-colar" códigos.** Se você estiver contando com uma fonte externa, então você deve mantê-lo atualizado com a fonte original. +- **Use bibliotecas bem testadas.** Importar código de bibliotecas bem testadas reduzirá a probabilidade de você escrever código com bugs. Se você quiser escrever um contrato ERC20, use o [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20). +- **Use um gerenciador de dependências; evite copiar e colar código.** Se você depende de uma fonte externa, deve mantê-la atualizada com a fonte original. -### Teste e Validação {#testing-and-verification} +### Teste e verificação {#testing-and-verification} -- **Escreva testes unitários completos.** Um conjunto extenso de testes é crucial para construir softwares de alta qualidade. -- **Escreva propriedades e verificações personalizadas com [Slither](https://github.com/crytic/slither), [Echidna](https://github.com/crytic/echidna) e [Manticore](https://github.com/trailofbits/manticore).** Ferramentas automatizadas ajudarão a garantir que o seu contrato é seguro. Revise o resto deste guia para aprender a escrever propriedades e verificações eficientes. -- **Use o [crytic.io](https://crytic.io/).** O Critic integra-se ao Github, fornece acesso a detectores privados do Slither e executa verificações de propriedade personalizadas pelo Echidna. +- **Escreva testes de unidade completos.** Um conjunto extenso de testes é crucial para construir um software de alta qualidade. +- **Escreva verificações e propriedades personalizadas para [Slither](https://github.com/crytic/slither), [Echidna](https://github.com/crytic/echidna) e [Manticore](https://github.com/trailofbits/manticore).** Ferramentas automatizadas ajudarão a garantir que seu contrato seja seguro. Revise o resto deste guia para aprender a escrever propriedades e verificações eficientes. +- **Use o [crytic.io](https://crytic.io/).** O Crytic se integra ao GitHub, fornece acesso a detectores privados do Slither e executa verificações de propriedade personalizadas do Echidna. ### Solidity {#solidity} -- **Favoreça a Solidity 0.5 em vez de 0.4 e 0.6.** Em nossa opinião, a Solidity 0.5 é mais seguro e tem melhores práticas incorporadas que a 0.4. A Solidity 0.6 provou ser demasiado instável para produção e precisa de tempo para amadurecer. -- **Use um lançamento estável para compilar; use a versão mais recente para verificar se há avisos.** Verifique se o seu código não relatou problemas com a versão mais recente do compilador. No entanto, a Solidity tem um ciclo de lançamento rápido e tem um histórico de erros do compilador, então não recomendamos a versão mais recente para implantar (veja a [recomendação de versão solc do Slither](https://github.com/crytic/slither/wiki/Detector-Documentation#recommendation-33)). -- **Não use montagem embutida.** A montagem requer experiência em EVM. Não escreva o código EVM se você não tiver _dominado_ o Yellow Paper da Ethereum. +- **Prefira o Solidity 0.5 ao 0.4 e 0.6.** Em nossa opinião, o Solidity 0.5 é mais seguro e tem práticas incorporadas melhores que o 0.4. A Solidity 0.6 provou ser demasiado instável para produção e precisa de tempo para amadurecer. +- **Use uma versão estável para compilar; use a versão mais recente para verificar se há avisos.** Verifique se seu código não tem problemas relatados com a versão mais recente do compilador. No entanto, o Solidity tem um ciclo de lançamento rápido e um histórico de bugs de compilador, portanto, não recomendamos a versão mais recente para implantação (veja a [recomendação de versão do solc do Slither](https://github.com/crytic/slither/wiki/Detector-Documentation#recommendation-33)). +- **Não use assembly em linha.** O assembly requer experiência em EVM. Não escreva código EVM se você não tiver _dominado_ o yellow paper. -## Orientações de implantação {#deployment-guidelines} +## Diretrizes de implantação {#deployment-guidelines} Uma vez que o contrato tenha sido desenvolvido e implantado: -- **Monitore seus contratos.** Observe os acessos e esteja pronto para reagir em caso de comprometimento do contrato ou da carteira. -- **Adicione suas informações de contato em [contatos de segurança da blockchain](https://github.com/crytic/blockchain-security-contacts).** Essa lista ajuda a terceiros a entrar em contato com você caso uma falha de segurança seja descoberta. -- **Proteja as carteiras de usuários privilegiados.** Siga nossas [melhores práticas](https://blog.trailofbits.com/2018/11/27/10-rules-for-the-secure-use-of-cryptocurrency-hardware-wallets/) se você armazenar chaves em carteiras físicas (hardware). -- **Tenha uma resposta ao plano de incidentes.** Considere que seus contratos inteligentes possam ser comprometidos. Mesmo que seus contratos estejam livres de erros, um invasor pode assumir o controle das chaves do proprietário do contrato. +- **Monitore seus contratos.** Observe os logs e esteja pronto para reagir em caso de comprometimento do contrato ou da carteira. +- **Adicione suas informações de contato em [blockchain-security-contacts](https://github.com/crytic/blockchain-security-contacts).** Esta lista ajuda terceiros a entrarem em contato com você caso uma falha de segurança seja descoberta. +- **Proteja as carteiras de usuários privilegiados.** Siga nossas [melhores práticas](https://blog.trailofbits.com/2018/11/27/10-rules-for-the-secure-use-of-cryptocurrency-hardware-wallets/) se você armazena chaves em carteiras de hardware. +- **Tenha um plano de resposta a incidentes.** Considere que seus contratos inteligentes podem ser comprometidos. Mesmo que seus contratos estejam livres de erros, um invasor pode assumir o controle das chaves do proprietário do contrato. diff --git a/public/content/translations/pt-br/developers/tutorials/stealth-addr/index.md b/public/content/translations/pt-br/developers/tutorials/stealth-addr/index.md new file mode 100644 index 00000000000..959feca5a6e --- /dev/null +++ b/public/content/translations/pt-br/developers/tutorials/stealth-addr/index.md @@ -0,0 +1,443 @@ +--- +title: "Usando endereços secretos" +description: "Endereços secretos permitem que os usuários transfiram ativos anonimamente. Após ler este artigo, você será capaz de: Explicar o que são endereços secretos e como eles funcionam, entender como usar endereços secretos de uma forma que preserve o anonimato e escrever uma aplicação web que use endereços secretos." +author: Ori Pomerantz +tags: + [ + "Endereço secreto", + "privacidade", + "criptografia", + "Rust", + "wasm" + ] +skill: intermediate +published: 2025-11-30 +lang: pt-br +sidebarDepth: 3 +--- + +Você é o Bill. Por razões que não vamos entrar em detalhes, você quer fazer uma doação para a campanha "Alice para Rainha do Mundo" e que a Alice saiba que você doou para que ela o recompense se ganhar. Infelizmente, a vitória dela não é garantida. Existe uma campanha concorrente, "Carol para Imperatriz do Sistema Solar". Se a Carol ganhar, e ela descobrir que você doou para a Alice, você terá problemas. Então você não pode simplesmente transferir 200 ETH da sua conta para a da Alice. + +O [ERC-5564](https://eips.ethereum.org/EIPS/eip-5564) tem a solução. Este ERC explica como usar [endereços secretos](https://nerolation.github.io/stealth-utils) para transferência anônima. + +**Aviso**: A criptografia por trás dos endereços secretos é, até onde sabemos, sólida. No entanto, existem potenciais ataques de canal lateral. [Abaixo](#go-wrong), você verá o que pode fazer para reduzir este risco. + +## Como os endereços secretos funcionam {#how} + +Este artigo tentará explicar os endereços secretos de duas maneiras. A primeira é [como usá-los](#how-use). Esta parte é suficiente para entender o resto do artigo. Depois, há [uma explicação da matemática por trás disso](#how-math). Se você estiver interessado em criptografia, leia esta parte também. + +### A versão simples (como usar endereços secretos) {#how-use} + +Alice cria duas chaves privadas e publica as chaves públicas correspondentes (que podem ser combinadas em um único meta-endereço de comprimento duplo). Bill também cria uma chave privada e publica a chave pública correspondente. + +Usando a chave pública de uma parte e a chave privada da outra, você pode derivar um segredo compartilhado conhecido apenas por Alice e Bill (ele não pode ser derivado apenas das chaves públicas). Usando este segredo compartilhado, Bill obtém o endereço secreto e pode enviar ativos para ele. + +Alice também obtém o endereço a partir do segredo compartilhado, mas como ela conhece as chaves privadas para as chaves públicas que publicou, ela também pode obter a chave privada que lhe permite sacar desse endereço. + +### A matemática (por que endereços secretos funcionam assim) {#how-math} + +Endereços secretos padrão usam [criptografia de curva elíptica (ECC)](https://blog.cloudflare.com/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography/#elliptic-curves-building-blocks-of-a-better-trapdoor) para obter melhor desempenho com menos bits de chave, mantendo o mesmo nível de segurança. Mas, na maior parte, podemos ignorar isso e fingir que estamos usando aritmética regular. + +Existe um número que todos conhecem, _G_. Você pode multiplicar por _G_. Mas, devido à natureza da ECC, é praticamente impossível dividir por _G_. A forma como a criptografia de chave pública geralmente funciona no Ethereum é que você pode usar uma chave privada, _Ppriv_, para assinar transações que são então verificadas por uma chave pública, _Ppub = GPpriv_. + +Alice cria duas chaves privadas, _Kpriv_ e _Vpriv_. _Kpriv_ será usada para gastar dinheiro do endereço secreto, e _Vpriv_ para visualizar os endereços que pertencem a Alice. Alice então publica as chaves públicas: _Kpub = GKpriv_ e _Vpub = GVpriv_ + +Bill cria uma terceira chave privada, _Rpriv_, e publica _Rpub = GRpriv_ em um registro central (Bill também poderia tê-la enviado para Alice, mas assumimos que Carol está ouvindo). + +Bill calcula _RprivVpub = GRprivVpriv_, que ele espera que Alice também saiba (explicado abaixo). Este valor é chamado _S_, o segredo compartilhado. Isso dá a Bill uma chave pública, _Ppub = Kpub+G\*hash(S)_. A partir desta chave pública, ele pode calcular um endereço e enviar quaisquer recursos que ele queira para ele. No futuro, se Alice ganhar, Bill pode dizer a ela _Rpriv_ para provar que os recursos vieram dele. + +Alice calcula _RpubVpriv = GRprivVpriv_. Isso dá a ela o mesmo segredo compartilhado, _S_. Como ela conhece a chave privada, _Kpriv_, ela pode calcular _Ppriv = Kpriv+hash(S)_. Esta chave permite que ela acesse ativos no endereço que resulta de _Ppub = GPpriv = GKpriv+G\*hash(S) = Kpub+G\*hash(S)_. + +Temos uma chave de visualização separada para permitir que Alice subcontrate os Serviços de Campanha de Dominação Mundial de Dave. Alice está disposta a deixar Dave saber os endereços públicos e informá-la quando mais dinheiro estiver disponível, mas ela não quer que ele gaste o dinheiro da campanha dela. + +Como a visualização e o gasto usam chaves separadas, Alice pode dar a Dave _Vpriv_. Então Dave pode calcular _S = RpubVpriv = GRprivVpriv_ e dessa forma obter as chaves públicas (_Ppub = Kpub+G\*hash(S)_). Mas sem _Kpriv_ Dave não consegue obter a chave privada. + +Para resumir, estes são os valores conhecidos pelos diferentes participantes. + +| Alice | Publicado | Bill | Dave | | +| ------------------------------------------------------------------------- | ----------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------ | +| G | G | G | G | | +| _Kpriv_ | — | — | — | | +| _Vpriv_ | — | — | _Vpriv_ | | +| _Kpub = GKpriv_ | _Kpub_ | _Kpub_ | _Kpub_ | | +| _Vpub = GVpriv_ | _Vpub_ | _Vpub_ | _Vpub_ | | +| — | — | _Rpriv_ | — | | +| _Rpub_ | _Rpub_ | _Rpub = GRpriv_ | _Rpub_ | | +| _S = RpubVpriv = GRprivVpriv_ | — | _S = RprivVpub = GRprivVpriv_ | _S = _RpubVpriv_ = GRprivVpriv_ | | +| _Ppub = Kpub+G\*hash(S)_ | — | _Ppub = Kpub+G\*hash(S)_ | _Ppub = Kpub+G\*hash(S)_ | | +| _Endereço=f(Ppub)_ | — | _Endereço=f(Ppub)_ | _Endereço=f(Ppub)_ | _Endereço=f(Ppub)_ | +| _Ppriv = Kpriv+hash(S)_ | — | — | — | | + +## Quando os endereços secretos dão errado {#go-wrong} + +_Não há segredos na cadeia de blocos_. Embora os endereços secretos possam fornecer privacidade, essa privacidade é suscetível à análise de tráfego. Para dar um exemplo trivial, imagine que Bill financia um endereço e imediatamente envia uma transação para publicar um valor _Rpub_. Sem o _Vpriv_ de Alice, não podemos ter certeza de que este é um endereço secreto, mas essa é a aposta mais segura. Em seguida, vemos outra transação que transfere todo o ETH desse endereço para o endereço do fundo de campanha de Alice. Podemos não ser capazes de provar, mas é provável que Bill tenha acabado de doar para a campanha de Alice. Carol certamente pensaria assim. + +É fácil para Bill separar a publicação de _Rpub_ do financiamento do endereço secreto (fazê-los em momentos diferentes, a partir de endereços diferentes). No entanto, isso não é suficiente. O padrão que Carol procura é que Bill financie um endereço e, em seguida, o fundo de campanha de Alice saca dele. + +Uma solução é a campanha de Alice não sacar o dinheiro diretamente, mas usá-lo para pagar um terceiro. Se a campanha de Alice envia 10 ETH para os Serviços de Campanha de Dominação Mundial de Dave, Carol só sabe que Bill doou para um dos clientes de Dave. Se Dave tiver clientes suficientes, Carol não seria capaz de saber se Bill doou para Alice, que compete com ela, ou para Adam, Albert ou Abigail, com quem Carol não se importa. Alice pode incluir um valor com hash no pagamento e, em seguida, fornecer a Dave a pré-imagem, para provar que foi sua doação. Alternativamente, como observado acima, se Alice der a Dave seu _Vpriv_, ele já saberá de quem veio o pagamento. + +O principal problema com essa solução é que ela exige que Alice se preocupe com o sigilo quando esse sigilo beneficia Bill. Alice pode querer manter sua reputação para que o amigo de Bill, Bob, também doe para ela. Mas também é possível que ela não se importe em expor Bill, porque então ele ficará com medo do que acontecerá se Carol vencer. Bill pode acabar dando ainda mais apoio a Alice. + +### Usando várias camadas secretas {#multi-layer} + +Em vez de confiar em Alice para preservar a privacidade de Bill, o próprio Bill pode fazê-lo. Ele pode gerar múltiplos meta-endereços para pessoas fictícias, Bob e Bella. Bill então envia ETH para Bob, e "Bob" (que na verdade é Bill) o envia para Bella. "Bella" (também Bill) o envia para Alice. + +Carol ainda pode fazer análise de tráfego e ver o pipeline Bill-para-Bob-para-Bella-para-Alice. No entanto, se "Bob" e "Bella" também usarem ETH para outros fins, não parecerá que Bill transferiu nada para Alice, mesmo que Alice saque imediatamente do endereço secreto para seu endereço de campanha conhecido. + +## Escrevendo uma aplicação de endereço secreto {#write-app} + +Este artigo explica uma aplicação de endereço secreto [disponível no GitHub](https://github.com/qbzzt/251022-stealth-addresses.git). + +### Ferramentas {#tools} + +Existe [uma biblioteca de endereço secreto em typescript](https://github.com/ScopeLift/stealth-address-sdk) que poderíamos usar. No entanto, operações criptográficas podem ser intensivas em CPU. Prefiro implementá-las em uma linguagem compilada, como [Rust](https://rust-lang.org/), e usar [WASM](https://webassembly.org/) para executar o código no navegador. + +Vamos usar [Vite](https://vite.dev/) e [React](https://react.dev/). Estas são ferramentas padrão da indústria; se você não estiver familiarizado com elas, pode usar [este tutorial](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/). Para usar o Vite, precisamos do Node. + +### Veja os endereços secretos em ação {#in-action} + +1. Instale as ferramentas necessárias: [Rust](https://rust-lang.org/tools/install/) e [Node](https://nodejs.org/en/download). + +2. Clone o repositório do GitHub. + + ```sh + git clone https://github.com/qbzzt/251022-stealth-addresses.git + cd 251022-stealth-addresses + ``` + +3. Instale os pré-requisitos e compile o código Rust. + + ```sh + cd src/rust-wasm + rustup target add wasm32-unknown-unknown + cargo install wasm-pack + wasm-pack build --target web + ``` + +4. Inicie o servidor web. + + ```sh + cd ../.. + npm install + npm run dev + ``` + +5. Acesse [a aplicação](http://localhost:5173/). Esta página da aplicação tem dois frames: um para a interface de usuário de Alice e outro para a de Bill. Os dois frames não se comunicam; eles estão na mesma página apenas por conveniência. + +6. Como Alice, clique em **Gerar um Meta-endereço Secreto**. Isso exibirá o novo endereço secreto e as chaves privadas correspondentes. Copie o meta-endereço secreto para a área de transferência. + +7. Como Bill, cole o novo meta-endereço secreto e clique em **Gerar um endereço**. Isso lhe dá o endereço para financiar Alice. + +8. Copie o endereço e a chave pública de Bill e cole-os na área "Chave privada para endereço gerado por Bill" da interface do usuário de Alice. Depois que esses campos forem preenchidos, você verá a chave privada para acessar os ativos nesse endereço. + +9. Você pode usar [uma calculadora online](https://iancoleman.net/ethereum-private-key-to-address/) para garantir que a chave privada corresponda ao endereço. + +### Como o programa funciona {#how-the-program-works} + +#### O componente WASM {#wasm} + +O código-fonte que compila para WASM é escrito em [Rust](https://rust-lang.org/). Você pode vê-lo em [`src/rust_wasm/src/lib.rs`](https://github.com/qbzzt/251022-stealth-addresses/blob/main/src/rust-wasm/src/lib.rs). Este código é principalmente uma interface entre o código JavaScript e [a biblioteca `eth-stealth-addresses`](https://github.com/kassandraoftroy/eth-stealth-addresses). + +**`Cargo.toml`** + +[`Cargo.toml`](https://doc.rust-lang.org/cargo/reference/manifest.html) em Rust é análogo a [`package.json`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json) em JavaScript. Ele contém informações do pacote, declarações de dependência, etc. + +```toml +[package] +name = "rust-wasm" +version = "0.1.0" +edition = "2024" + +[dependencies] +eth-stealth-addresses = "0.1.0" +hex = "0.4.3" +wasm-bindgen = "0.2.104" +getrandom = { version = "0.2", features = ["js"] } +``` + +O pacote [`getrandom`](https://docs.rs/getrandom/latest/getrandom/) precisa gerar valores aleatórios. Isso não pode ser feito por meios puramente algorítmicos; requer acesso a um processo físico como fonte de entropia. Esta definição especifica que obteremos essa entropia perguntando ao navegador em que estamos executando. + +```toml +console_error_panic_hook = "0.1.7" +``` + +[Esta biblioteca](https://docs.rs/console_error_panic_hook/latest/console_error_panic_hook/) nos dá mensagens de erro mais significativas quando o código WASM entra em pânico e não pode continuar. + +```toml +[lib] +crate-type = ["cdylib", "rlib"] +``` + +O tipo de saída necessário para produzir código WASM. + +**`lib.rs`** + +Este é o código Rust real. + +```rust +use wasm_bindgen::prelude::*; +``` + +As definições para criar um pacote WASM a partir do Rust. Elas estão documentadas [aqui](https://wasm-bindgen.github.io/wasm-bindgen/reference/attributes/index.html). + +```rust +use eth_stealth_addresses::{ + generate_stealth_meta_address, + generate_stealth_address, + compute_stealth_key +}; +``` + +As funções que precisamos da [biblioteca `eth-stealth-addresses`](https://github.com/kassandraoftroy/eth-stealth-addresses). + +```rust +use hex::{decode,encode}; +``` + +Rust normalmente usa [arrays](https://doc.rust-lang.org/std/primitive.array.html) de bytes (`[u8; ]`) para valores. Mas em JavaScript, normalmente usamos strings hexadecimais. [A biblioteca `hex`](https://docs.rs/hex/latest/hex/) traduz para nós de uma representação para a outra. + +```rust +#[wasm_bindgen] +``` + +Gere bindings WASM para poder chamar esta função a partir do JavaScript. + +```rust +pub fn wasm_generate_stealth_meta_address() -> String { +``` + +A maneira mais fácil de retornar um objeto com vários campos é retornar uma string JSON. + +```rust + let (address, spend_private_key, view_private_key) = + generate_stealth_meta_address(); +``` + +A [`generate_stealth_meta_address`](https://docs.rs/eth-stealth-addresses/latest/eth_stealth_addresses/fn.generate_stealth_meta_address.html) retorna três campos: + +- O meta-endereço (_Kpub_ e _Vpub_) +- A chave privada de visualização (_Vpriv_) +- A chave privada de gastos (_Kpriv_) + +A sintaxe de [tupla](https://doc.rust-lang.org/std/primitive.tuple.html) nos permite separar esses valores novamente. + +```rust + format!("{\"address\":\"{}\",\"view_private_key\":\"{}\",\"spend_private_key\":\"{}\"}", + encode(address), + encode(view_private_key), + encode(spend_private_key) + ) +} +``` + +Use a macro [`format!`](https://doc.rust-lang.org/std/fmt/index.html) para gerar a string codificada em JSON. Use [`hex::encode`](https://docs.rs/hex/latest/hex/fn.encode.html) para alterar os arrays para strings hexadecimais. + +```rust +fn str_to_array(s: &str) -> Option<[u8; N]> { +``` + +Esta função transforma uma string hexadecimal (fornecida pelo JavaScript) em um array de bytes. Nós a usamos para analisar valores fornecidos pelo código JavaScript. Esta função é complicada por causa de como o Rust lida com arrays e vetores. + +A expressão `` é chamada de [genérica](https://doc.rust-lang.org/book/ch10-01-syntax.html). `N` é um parâmetro que controla o comprimento do array retornado. A função é na verdade chamada `str_to_array::`, onde `n` é o comprimento do array. + +O valor de retorno é `Option<[u8; N]>`, o que significa que o array retornado é [opcional](https://doc.rust-lang.org/std/option/). Este é um padrão típico em Rust para funções que podem falhar. + +Por exemplo, se chamarmos `str_to_array::10("bad060a7")`, a função deveria retornar um array de dez valores, mas a entrada tem apenas quatro bytes. A função precisa falhar, e ela faz isso retornando `None`. O valor de retorno para `str_to_array::4("bad060a7")` seria `Some<[0xba, 0xd0, 0x60, 0xa7]>`. + +```rust + // decode returns Result, _> + let vec = decode(s).ok()?; +``` + +A função [`hex::decode`](https://docs.rs/hex/latest/hex/fn.decode.html) retorna um `Result, FromHexError>`. O tipo [`Result`](https://doc.rust-lang.org/std/result/) pode conter um resultado bem-sucedido (`Ok(value)`) ou um erro (`Err(error)`). + +O método `.ok()` transforma o `Result` em um `Option`, cujo valor é o valor de `Ok()` se for bem-sucedido, ou `None` se não for. Finalmente, o [operador de ponto de interrogação](https://doc.rust-lang.org/std/option/#the-question-mark-operator-) aborta as funções atuais e retorna um `None` se o `Option` estiver vazio. Caso contrário, ele desempacota o valor e o retorna (neste caso, para atribuir um valor a `vec`). + +Este parece ser um método estranhamente complicado para lidar com erros, mas `Result` e `Option` garantem que todos os erros sejam tratados, de uma forma ou de outra. + +```rust + if vec.len() != N { return None; } +``` + +Se o número de bytes estiver incorreto, isso é uma falha e retornamos `None`. + +```rust + // try_into consome vec e tenta fazer [u8; N] + let array: [u8; N] = vec.try_into().ok()?; +``` + +Rust tem dois tipos de array. [Arrays](https://doc.rust-lang.org/std/primitive.array.html) têm um tamanho fixo. [Vetores](https://doc.rust-lang.org/std/vec/index.html) podem crescer e encolher. `hex::decode` retorna um vetor, mas a biblioteca `eth_stealth_addresses` quer receber arrays. [`.try_into()`](https://doc.rust-lang.org/std/convert/trait.TryInto.html#required-methods) converte um valor em outro tipo, por exemplo, um vetor em um array. + +```rust + Some(array) +} +``` + +Rust não exige que você use a palavra-chave [`return`](https://doc.rust-lang.org/std/keyword.return.html) ao retornar um valor no final de uma função. + +```rust +#[wasm_bindgen] +pub fn wasm_generate_stealth_address(stealth_address: &str) -> Option { +``` + +Esta função recebe um meta-endereço público, que inclui tanto _Vpub_ quanto _Kpub_. Ele retorna o endereço secreto, a chave pública para publicar (_Rpub_) e um valor de varredura de um byte que acelera a identificação de quais endereços publicados podem pertencer a Alice. + +O valor de varredura faz parte do segredo compartilhado (_S = GRprivVpriv_). Este valor está disponível para Alice, e verificá-lo é muito mais rápido do que verificar se _f(Kpub+G\*hash(S))_ é igual ao endereço publicado. + +```rust + let (address, r_pub, scan) = + generate_stealth_address(&str_to_array::<66>(stealth_address)?); +``` + +Usamos a função [`generate_stealth_address`](https://docs.rs/eth-stealth-addresses/latest/eth_stealth_addresses/fn.generate_stealth_address.html) da biblioteca. + +```rust + format!("{\"address\":\"{}\",\"rPub\":\"{}\",\"scan\":\"{}\"}", + encode(address), + encode(r_pub), + encode(&[scan]) + ).into() +} +``` + +Prepare a string de saída codificada em JSON. + +```rust +#[wasm_bindgen] +pub fn wasm_compute_stealth_key( + address: &str, + bill_pub_key: &str, + view_private_key: &str, + spend_private_key: &str +) -> Option { + . + . + . +} +``` + +Esta função usa a função [`compute_stealth_key`](https://docs.rs/eth-stealth-addresses/latest/eth_stealth_addresses/fn.compute_stealth_key.html) da biblioteca para calcular a chave privada para sacar do endereço (_Rpriv_). Este cálculo requer estes valores: + +- O endereço (_Endereço=f(Ppub)_) +- A chave pública gerada por Bill (_Rpub_) +- A chave privada de visualização (_Vpriv_) +- A chave privada de gastos (_Kpriv_) + +```rust +#[wasm_bindgen(start)] +``` + +[`#[wasm_bindgen(start)]`](https://wasm-bindgen.github.io/wasm-bindgen/reference/attributes/on-rust-exports/start.html) especifica que a função é executada quando o código WASM é inicializado. + +```rust +pub fn main() { + console_error_panic_hook::set_once(); +} +``` + +Este código especifica que a saída de pânico seja enviada para o console JavaScript. Para vê-lo em ação, use a aplicação e dê a Bill um meta-endereço inválido (apenas mude um dígito hexadecimal). Você verá este erro no console do JavaScript: + +``` +rust_wasm.js:236 panicked at /home/ori/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs:701:9: +assertion `left == right` failed + left: 0 + right: 1 +``` + +Seguido por um rastreamento de pilha. Em seguida, dê a Bill o meta-endereço válido e a Alice um endereço inválido ou uma chave pública inválida. Você verá este erro: + +``` +rust_wasm.js:236 panicked at /home/ori/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/eth-stealth-addresses-0.1.0/src/lib.rs:78:9: +keys do not generate stealth address +``` + +Novamente, seguido por um rastreamento de pilha. + +#### A interface do usuário {#ui} + +A interface do usuário é escrita usando [React](https://react.dev/) e servida por [Vite](https://vite.dev/). Você pode aprender sobre eles usando [este tutorial](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/). Não há necessidade de [WAGMI](https://wagmi.sh/) aqui, porque não interagimos diretamente com uma cadeia de blocos ou uma carteira. + +A única parte não óbvia da interface do usuário é a conectividade WASM. Funciona assim. + +**`vite.config.js`** + +Este arquivo contém [a configuração do Vite](https://vite.dev/config/). + +```js +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import wasm from "vite-plugin-wasm"; + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react(), wasm()], +}) +``` + +Precisamos de dois plugins Vite: [react](https://www.npmjs.com/package/@vitejs/plugin-react) e [wasm](https://github.com/Menci/vite-plugin-wasm#readme). + +**`App.jsx`** + +Este arquivo é o componente principal da aplicação. É um contêiner que inclui dois componentes: `Alice` e `Bill`, as interfaces de usuário para esses usuários. A parte relevante para o WASM é o código de inicialização. + +```jsx +import init from './rust-wasm/pkg/rust_wasm.js' +``` + +Quando usamos [`wasm-pack`](https://rustwasm.github.io/docs/wasm-pack/), ele cria dois arquivos que usamos aqui: um arquivo wasm com o código real (aqui, `src/rust-wasm/pkg/rust_wasm_bg.wasm`) e um arquivo JavaScript com as definições para usá-lo (aqui, `src/rust_wasm/pkg/rust_wasm.js`). A exportação padrão desse arquivo JavaScript é um código que precisa ser executado para iniciar o WASM. + +```jsx +function App() { + . + . + . + useEffect(() => { + const loadWasm = async () => { + try { + await init(); + setWasmReady(true) + } catch (err) { + console.error('Error loading wasm:', err) + alert("Wasm error: " + err) + } + } + + loadWasm() + }, [] + ) +``` + +O [hook `useEffect`](https://react.dev/reference/react/useEffect) permite que você especifique uma função que é executada quando as variáveis de estado mudam. Aqui, a lista de variáveis de estado está vazia (`[]`), então esta função é executada apenas uma vez quando a página carrega. + +A função de efeito deve retornar imediatamente. Para usar código assíncrono, como o `init` do WASM (que precisa carregar o arquivo `.wasm` e, portanto, leva tempo), definimos uma função interna [`async`](https://en.wikipedia.org/wiki/Async/await) e a executamos sem um `await`. + +**`Bill.jsx`** + +Esta é a interface de usuário para Bill. Ele tem uma única ação, criar um endereço com base no meta-endereço secreto fornecido por Alice. + +```jsx +import { wasm_generate_stealth_address } from './rust-wasm/pkg/rust_wasm.js' +``` + +Além da exportação padrão, o código JavaScript gerado pelo `wasm-pack` exporta uma função para cada função no código WASM. + +```jsx +