+ Ongeza tu kiungo cha mali yako, jina, na maelezo, kisha bonyeza "Unda."
+
+
+
+
{status}
+
+)
+```
+
+Mwishowe, hebu tushughulikie mahali ambapo kijenzi hiki cha Minter kinaongezwa.
+
+Ukienda kwenye faili ya `App.js`, ambayo ni kijenzi kikuu katika React ambacho hufanya kazi kama kontena kwa vijenzi vingine vyote, utaona kwamba kijenzi chetu cha Minter kinaingizwa kwenye mstari wa 7.
+
+**Katika mafunzo haya, tutakuwa tukihariri faili ya `Minter.js` pekee na kuongeza faili kwenye folda yetu ya `src`.**
+
+Sasa kwa kuwa tunaelewa tunachofanyia kazi, hebu tusanidi pochi yetu ya Ethereum!
+
+## Sanidi pochi yako ya Ethereum {#set-up-your-ethereum-wallet}
+
+Ili watumiaji waweze kuingiliana na mkataba wako erevu, watahitaji kuunganisha pochi yao ya Ethereum kwenye mfumo wako uliotawanywa.
+
+### Pakua MetaMask {#download-metamask}
+
+Kwa mafunzo haya, tutatumia MetaMask, mkoba wa mtandaoni katika kivinjari unaotumika kudhibiti anwani ya akaunti yako ya Ethereum. Ikiwa unataka kuelewa zaidi kuhusu jinsi miamala kwenye Ethereum inavyofanya kazi, angalia [ukurasa huu](/developers/docs/transactions/).
+
+Unaweza kupakua na kuunda akaunti ya MetaMask bure [hapa](https://metamask.io/download). Unapounda akaunti, au ikiwa tayari una akaunti, hakikisha umebadilisha hadi "Ropsten Test Network" upande wa juu kulia (ili tusiwe tunashughulika na pesa halisi).
+
+### Ongeza ether kutoka kwa Bomba {#add-ether-from-faucet}
+
+Ili kuunda NFT zetu (au kusaini miamala yoyote kwenye mnyororo wa bloku wa Ethereum), tutahitaji Eth bandia. Ili kupata Eth unaweza kwenda kwenye [Bomba la Ropsten](https://faucet.ropsten.be/) na uingize anwani ya akaunti yako ya Ropsten, kisha bofya "Tuma Ropsten Eth." Unapaswa kuona Eth katika akaunti yako ya MetaMask muda mfupi baadaye!
+
+### Angalia salio lako {#check-your-balance}
+
+Ili kuhakikisha salio letu lipo, hebu tufanye ombi la [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) kwa kutumia [zana ya mtunzi ya 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). Hii itarudisha kiasi cha Eth katika pochi yetu. Baada ya kuweka anwani ya akaunti yako ya MetaMask na kubofya βTuma Ombiβ, unapaswa kuona jibu kama hili:
+
+```text
+{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"}
+```
+
+**KUMBUKA:** Matokeo haya yako katika wei si eth. Wei hutumika kama denomina ndogo zaidi ya ether. Ubadilishaji kutoka wei hadi eth ni: 1 eth = 10ΒΉβΈ wei. Kwa hivyo, tukibadilisha 0xde0b6b3a7640000 hadi desimali tunapata 1\*10ΒΉβΈ ambayo ni sawa na eth 1.
+
+Phew! Pesa zetu bandia zote zipo!
+
+## Unganisha MetaMask kwenye UI yako {#connect-metamask-to-your-UI}
+
+Sasa kwa kuwa pochi yetu ya MetaMask imesanidiwa, hebu tuunganishe mfumo wetu uliotawanywa nayo!
+
+Kwa sababu tunataka kufuata dhana ya [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller), tutaunda faili tofauti ambayo ina kazi zetu za kudhibiti mantiki, data, na sheria za mfumo wetu uliotawanywa, na kisha kupitisha kazi hizo kwenye frontend yetu (kijenzi chetu cha Minter.js).
+
+### Kazi ya `connectWallet` {#connect-wallet-function}
+
+Ili kufanya hivyo, hebu tuunde folda mpya inayoitwa `utils` katika saraka yako ya `src` na tuongeze faili inayoitwa `interact.js` ndani yake, ambayo itakuwa na kazi zetu zote za mwingiliano wa pochi na mkataba erevu.
+
+Katika faili yetu ya `interact.js`, tutaandika kazi ya `connectWallet`, ambayo tutaiingiza na kuiita katika kijenzi chetu cha `Minter.js`.
+
+Katika faili yako ya `interact.js`, ongeza yafuatayo
+
+```javascript
+export const connectWallet = async () => {
+ if (window.ethereum) {
+ try {
+ const addressArray = await window.ethereum.request({
+ method: "eth_requestAccounts",
+ })
+ const obj = {
+ status: "ππ½ Andika ujumbe katika sehemu ya maandishi hapo juu.",
+ address: addressArray[0],
+ }
+ return obj
+ } catch (err) {
+ return {
+ address: "",
+ status: "π₯ " + err.message,
+ }
+ }
+ } else {
+ return {
+ address: "",
+ status: (
+
+
+
+ ),
+ }
+ }
+}
+```
+
+Hebu tuchanganue msimbo huu unafanya nini:
+
+Kwanza, kazi yetu inakagua ikiwa `window.ethereum` imewezeshwa kwenye kivinjari chako.
+
+`window.ethereum` ni API ya kimataifa inayoingizwa na MetaMask na watoa huduma wengine wa pochi ambayo inaruhusu tovuti kuomba akaunti za Ethereum za watumiaji. Ikiidhinishwa, inaweza kusoma data kutoka kwenye minyororo ya bloku ambayo mtumiaji ameunganishwa nayo, na kupendekeza mtumiaji asaini ujumbe na miamala. Angalia [hati za MetaMask](https://docs.metamask.io/guide/ethereum-provider.html#table-of-contents) kwa maelezo zaidi!
+
+Ikiwa `window.ethereum` _haipo_, basi hiyo inamaanisha kuwa MetaMask haijasakinishwa. Hii inasababisha kurudishwa kwa kitu cha JSON, ambapo `anwani` iliyorudishwa ni mfuatano tupu, na kitu cha `status` cha JSX kinaeleza kuwa mtumiaji lazima asakinishe MetaMask.
+
+**Kazi nyingi tutakazoandika zitakuwa zikirudisha vitu vya JSON ambavyo tunaweza kutumia kusasisha vigeu vyetu vya hali na UI.**
+
+Sasa ikiwa `window.ethereum` _ipo_, hapo ndipo mambo yanapopendeza.
+
+Kwa kutumia kitanzi cha kujaribu/kukamatwa, tutajaribu kuunganisha kwenye MetaMask kwa kuita [`window.ethereum.request({ method: "eth_requestAccounts" });`](https://docs.metamask.io/guide/rpc-api.html#eth-requestaccounts). Kuita kazi hii kutafungua MetaMask kwenye kivinjari, ambapo mtumiaji ataombwa kuunganisha pochi yake kwenye mfumo wako uliotawanywa.
+
+- Ikiwa mtumiaji atachagua kuunganisha, `method: "eth_requestAccounts"` itarudisha safu iliyo na anwani zote za akaunti za mtumiaji ambazo zimeunganishwa kwenye mfumo uliotawanywa. Kwa pamoja, kazi yetu ya `connectWallet` itarudisha kitu cha JSON kilicho na `anwani` ya _kwanza_ katika safu hii (tazama mstari wa 9) na ujumbe wa `status` unaomwomba mtumiaji aandike ujumbe kwenye mkataba erevu.
+- Ikiwa mtumiaji atakataa muunganisho, basi kitu cha JSON kitakuwa na mfuatano tupu kwa `anwani` iliyorudishwa na ujumbe wa `status` unaoonyesha kuwa mtumiaji alikataa muunganisho.
+
+### Ongeza kazi ya connectWallet kwenye Kijenzi chako cha UI cha Minter.js {#add-connect-wallet}
+
+Sasa kwa kuwa tumeandika kazi hii ya `connectWallet`, hebu tuiunganishe kwenye kijenzi chetu cha `Minter.js`.
+
+Kwanza, itabidi tuingize kazi yetu kwenye faili yetu ya `Minter.js` kwa kuongeza `import { connectWallet } from "./utils/interact.js";` juu ya faili ya `Minter.js`. Mistari yako 11 ya kwanza ya `Minter.js` sasa inapaswa kuonekana hivi:
+
+```javascript
+import { useEffect, useState } from "react";
+import { connectWallet } from "./utils/interact.js";
+
+const Minter = (props) => {
+
+ //Vigezo vya hali
+ const [walletAddress, setWallet] = useState("");
+ const [status, setStatus] = useState("");
+ const [name, setName] = useState("");
+ const [description, setDescription] = useState("");
+ const [url, setURL] = useState("");
+```
+
+Kisha, ndani ya kazi yetu ya `connectWalletPressed`, tutaita kazi yetu iliyoingizwa ya `connectWallet`, kama ifuatavyo:
+
+```javascript
+const connectWalletPressed = async () => {
+ const walletResponse = await connectWallet()
+ setStatus(walletResponse.status)
+ setWallet(walletResponse.address)
+}
+```
+
+Je, unaona jinsi utendakazi wetu mwingi unavyofichwa kutoka kwa kijenzi chetu cha `Minter.js` kutoka kwenye faili ya `interact.js`? Hii ni ili tuendane na dhana ya M-V-C!
+
+Katika `connectWalletPressed`, tunafanya tu wito wa kusubiri kwa kazi yetu iliyoingizwa ya `connectWallet`, na kwa kutumia jibu lake, tunasasisha vigezo vyetu vya `status` na `walletAddress` kupitia ndoana zao za hali.
+
+Sasa, hebu tuhifadhi faili zote mbili `Minter.js` na `interact.js` na tujaribu UI yetu hadi sasa.
+
+Fungua kivinjari chako kwenye localhost:3000, na ubonyeze kitufe cha "Unganisha Pochi" upande wa juu kulia wa ukurasa.
+
+Ikiwa umesakinisha MetaMask, unapaswa kuombwa kuunganisha pochi yako kwenye mfumo wako uliotawanywa. Kubali mwaliko wa kuunganisha.
+
+Unapaswa kuona kwamba kitufe cha pochi sasa kinaonyesha kwamba anwani yako imeunganishwa.
+
+Kisha, jaribu kuonyesha upya ukurasa... hii ni ajabu. Kitufe chetu cha pochi kinatuomba tuunganishe MetaMask, ingawa tayari imeunganishwa...
+
+Lakini usijali! Tunaweza kurekebisha hilo kwa urahisi kwa kutekeleza kazi inayoitwa `getCurrentWalletConnected`, ambayo itakagua ikiwa anwani tayari imeunganishwa kwenye mfumo wetu uliotawanywa na kusasisha UI yetu ipasavyo!
+
+### Kazi ya getCurrentWalletConnected {#get-current-wallet}
+
+Katika faili yako ya `interact.js`, ongeza kazi ifuatayo ya `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: "ππ½ Andika ujumbe katika sehemu ya maandishi hapo juu.",
+ }
+ } else {
+ return {
+ address: "",
+ status: "π¦ Unganisha kwenye MetaMask ukitumia kitufe cha juu kulia.",
+ }
+ }
+ } catch (err) {
+ return {
+ address: "",
+ status: "π₯ " + err.message,
+ }
+ }
+ } else {
+ return {
+ address: "",
+ status: (
+
+
+
+ ),
+ }
+ }
+}
+```
+
+Msimbo huu _unafanana sana_ na kazi ya `connectWallet` tuliyoiandika mapema.
+
+Tofauti kuu ni kwamba badala ya kuita mbinu ya `eth_requestAccounts`, ambayo inafungua MetaMask kwa mtumiaji kuunganisha pochi yake, hapa tunaita mbinu ya `eth_accounts`, ambayo inarudisha tu safu iliyo na anwani za MetaMask zilizounganishwa kwa sasa kwenye mfumo wetu uliotawanywa.
+
+Ili kuona kazi hii ikifanya kazi, hebu tuiite katika kazi ya `useEffect` ya kijenzi chetu cha `Minter.js`.
+
+Kama tulivyofanya kwa `connectWallet`, lazima tuingize kazi hii kutoka kwenye faili yetu ya `interact.js` hadi kwenye faili yetu ya `Minter.js` kama ifuatavyo:
+
+```javascript
+import { useEffect, useState } from "react"
+import {
+ connectWallet,
+ getCurrentWalletConnected, //ingiza hapa
+} from "./utils/interact.js"
+```
+
+Sasa, tunaiita tu katika kazi yetu ya `useEffect`:
+
+```javascript
+useEffect(async () => {
+ const { address, status } = await getCurrentWalletConnected()
+ setWallet(address)
+ setStatus(status)
+}, [])
+```
+
+Kumbuka, tunatumia jibu la wito wetu kwa `getCurrentWalletConnected` kusasisha vigezo vyetu vya hali vya `walletAddress` na `status`.
+
+Mara tu umeongeza msimbo huu, jaribu kuonyesha upya dirisha la kivinjari chetu. Kitufe kinapaswa kusema kuwa umeunganishwa, na kuonyesha hakikisho la anwani ya pochi yako iliyounganishwa - hata baada ya kuonyesha upya!
+
+### Tekeleza addWalletListener {#implement-add-wallet-listener}
+
+Hatua ya mwisho katika usanidi wa pochi ya mfumo wetu uliotawanywa ni kutekeleza msikilizaji wa pochi ili UI yetu isasishwe wakati hali ya pochi yetu inabadilika, kama vile mtumiaji anapokatisha muunganisho au kubadilisha akaunti.
+
+Katika faili yako ya `Minter.js`, ongeza kazi `addWalletListener` inayoonekana kama ifuatavyo:
+
+```javascript
+function addWalletListener() {
+ if (window.ethereum) {
+ window.ethereum.on("accountsChanged", (accounts) => {
+ if (accounts.length > 0) {
+ setWallet(accounts[0])
+ setStatus("ππ½ Andika ujumbe katika sehemu ya maandishi hapo juu.")
+ } else {
+ setWallet("")
+ setStatus("π¦ Unganisha kwenye MetaMask ukitumia kitufe cha juu kulia.")
+ }
+ })
+ } else {
+ setStatus(
+
+ )
+ }
+}
+```
+
+Hebu tuchanganue kwa haraka kile kinachotokea hapa:
+
+- Kwanza, kazi yetu inakagua ikiwa `window.ethereum` imewezeshwa (yaani, MetaMask imesakinishwa).
+ - Ikiwa sivyo, tunaweka tu kigezo chetu cha hali cha `status` kuwa mfuatano wa JSX unaomwomba mtumiaji asakinishe MetaMask.
+ - Ikiwa imewezeshwa, tunaweka msikilizaji `window.ethereum.on("accountsChanged")` kwenye mstari wa 3 anayesikiliza mabadiliko ya hali katika pochi ya MetaMask, ambayo ni pamoja na wakati mtumiaji anapounganisha akaunti ya ziada kwenye mfumo uliotawanywa, anapobadilisha akaunti, au anapokatisha muunganisho wa akaunti. Ikiwa kuna angalau akaunti moja iliyounganishwa, kigezo cha hali cha `walletAddress` kinasasishwa kama akaunti ya kwanza katika safu ya `accounts` iliyorudishwa na msikilizaji. Vinginevyo, `walletAddress` huwekwa kama mfuatano tupu.
+
+Mwishowe, lazima tuiite katika kazi yetu ya `useEffect`:
+
+```javascript
+useEffect(async () => {
+ const { address, status } = await getCurrentWalletConnected()
+ setWallet(address)
+ setStatus(status)
+
+ addWalletListener()
+}, [])
+```
+
+Na voilΓ ! Tumekamilisha kupanga utendakazi wote wa pochi yetu! Sasa kwa kuwa pochi yetu imesanidiwa, hebu tujue jinsi ya kuunda NFT yetu!
+
+## Metadata ya NFT 101 {#nft-metadata-101}
+
+Kwa hivyo kumbuka metadata ya NFT tuliyozungumzia katika Hatua ya 0 ya mafunzo hayaβinaipa NFT uhai, na kuiruhusu iwe na sifa, kama vile mali ya kidijitali, jina, maelezo, na sifa zingine.
+
+Tutahitaji kusanidi metadata hii kama kitu cha JSON na kuihifadhi, ili tuweze kuipitisha kama kigezo cha `tokenURI` wakati wa kuita kazi ya `mintNFT` ya mkataba wetu erevu.
+
+Maandishi katika sehemu za "Kiungo cha Mali", "Jina", "Maelezo" yatajumuisha sifa tofauti za metadata ya NFT yetu. Tutaumbiza metadata hii kama kitu cha JSON, lakini kuna chaguzi kadhaa za mahali tunaweza kuhifadhi kitu hiki cha JSON:
+
+- Tunaweza kuihifadhi kwenye mnyororo wa bloku wa Ethereum; hata hivyo, kufanya hivyo kungegharimu sana.
+- Tunaweza kuihifadhi kwenye seva ya kati, kama AWS au Firebase. Lakini hiyo ingepinga ethos yetu ya ugatuzi.
+- Tunaweza kutumia IPFS, itifaki iliyogatuliwa na mtandao wa rika-kwa-rika wa kuhifadhi na kushiriki data katika mfumo wa faili uliosambazwa. Kwa kuwa itifaki hii imegatuliwa na ni ya bure, ndiyo chaguo letu bora!
+
+Ili kuhifadhi metadata yetu kwenye IPFS, tutatumia [Pinata](https://pinata.cloud/), API na zana rahisi ya IPFS. Katika hatua inayofuata, tutaelezea hasa jinsi ya kufanya hivi!
+
+## Tumia Pinata kubandika metadata yako kwenye IPFS {#use-pinata-to-pin-your-metadata-to-IPFS}
+
+Ikiwa huna akaunti ya [Pinata](https://pinata.cloud/), jisajili kwa akaunti ya bure [hapa](https://app.pinata.cloud/auth/signup) na ukamilishe hatua za kuthibitisha barua pepe na akaunti yako.
+
+### Tengeneza ufunguo wako wa API wa Pinata {#create-pinata-api-key}
+
+Nenda kwenye ukurasa wa [https://pinata.cloud/keys](https://pinata.cloud/keys), kisha chagua kitufe cha "Ufunguo Mpya" juu, weka wijeti ya Msimamizi kama imewezeshwa, na upe ufunguo wako jina.
+
+Kisha utaonyeshwa ibukizi na maelezo yako ya API. Hakikisha unaiweka mahali salama.
+
+Sasa kwa kuwa ufunguo wetu umesanidiwa, hebu tuuongeze kwenye mradi wetu ili tuweze kuutumia.
+
+### Unda faili ya .env {#create-a-env}
+
+Tunaweza kuhifadhi ufunguo na siri yetu ya Pinata kwa usalama katika faili ya mazingira. Hebu tusakinishe [kifurushi cha dotenv](https://www.npmjs.com/package/dotenv) katika saraka ya mradi wako.
+
+Fungua kichupo kipya kwenye terminal yako (tofauti na ile inayoendesha local host) na hakikisha uko kwenye folda ya `minter-starter-files`, kisha endesha amri ifuatayo kwenye terminal yako:
+
+```text
+npm install dotenv --save
+```
+
+Kisha, tengeneza faili ya `.env` kwenye saraka ya mizizi ya `minter-starter-files` yako kwa kuingiza yafuatayo kwenye mstari wako wa amri:
+
+```javascript
+vim.env
+```
+
+Hii itafungua faili yako ya `.env` kwenye vim (kihariri cha maandishi). Ili kuihifadhi, bonyeza "esc" + ":" + "q" kwenye kibodi yako kwa mpangilio huo.
+
+Kisha, katika VSCode, nenda kwenye faili yako ya `.env` na uongeze ufunguo wako wa API wa Pinata na siri ya API kwake, kama ifuatavyo:
+
+```text
+REACT_APP_PINATA_KEY =
+REACT_APP_PINATA_SECRET =
+```
+
+Hifadhi faili, na kisha uko tayari kuanza kuandika kazi ya kupakia metadata yako ya JSON kwenye IPFS!
+
+### Tekeleza pinJSONToIPFS {#pin-json-to-ipfs}
+
+Kwa bahati nzuri kwetu, Pinata ina [API mahususi ya kupakia data ya JSON kwenye IPFS](https://docs.pinata.cloud/api-reference/endpoint/ipfs/pin-json-to-ipfs#pin-json) na mfano rahisi wa JavaScript na axios ambao tunaweza kutumia, pamoja na marekebisho madogo.
+
+Katika folda yako ya `utils`, hebu tuunde faili nyingine inayoitwa `pinata.js` na kisha tuingize siri na ufunguo wetu wa Pinata kutoka kwenye faili ya .env kama ifuatavyo:
+
+```javascript
+require("dotenv").config()
+const key = process.env.REACT_APP_PINATA_KEY
+const secret = process.env.REACT_APP_PINATA_SECRET
+```
+
+Kisha, bandika msimbo wa ziada kutoka chini hadi kwenye faili yako ya `pinata.js`. Usijali, tutachanganua maana ya kila kitu!
+
+```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`
+ //kufanya ombi la POST la axios kwa 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,
+ }
+ })
+}
+```
+
+Kwa hivyo msimbo huu unafanya nini hasa?
+
+Kwanza, inaingiza [axios](https://www.npmjs.com/package/axios), mteja wa HTTP anayetegemea ahadi kwa kivinjari na node.js, ambayo tutatumia kufanya ombi kwa Pinata.
+
+Kisha tuna kazi yetu isiyolingana ya `pinJSONToIPFS`, ambayo inachukua `JSONBody` kama ingizo lake na ufunguo wa api wa Pinata na siri katika kichwa chake, yote kufanya ombi la POST kwa API yao ya `pinJSONToIPFS`.
+
+- Ikiwa ombi hili la POST litafanikiwa, basi kazi yetu inarudisha kitu cha JSON na boolean ya `success` kama kweli na `pinataUrl` ambapo metadata yetu ilibandikwa. Tutatumia `pinataUrl` hii iliyorudishwa kama ingizo la `tokenURI` kwa kazi ya uundaji ya mkataba wetu erevu.
+- Ikiwa chapisho hili litashindwa, basi kazi yetu inarudisha kitu cha JSON na boolean ya `success` kama uongo na mfuatano wa `message` unaoeleza kosa letu.
+
+Kama ilivyo kwa aina zetu za kurudi za kazi ya `connectWallet`, tunarudisha vitu vya JSON ili tuweze kutumia vigezo vyao kusasisha vigeu vyetu vya hali na UI.
+
+## Pakia mkataba wako erevu {#load-your-smart-contract}
+
+Sasa kwa kuwa tuna njia ya kupakia metadata yetu ya NFT kwenye IPFS kupitia kazi yetu ya `pinJSONToIPFS`, tutahitaji njia ya kupakia mfano wa mkataba wetu erevu ili tuweze kuita kazi yake ya `mintNFT`.
+
+Kama tulivyotaja awali, katika mafunzo haya tutatumia [mkataba erevu uliopo wa NFT](https://ropsten.etherscan.io/address/0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE); hata hivyo, ikiwa ungependa kujifunza jinsi tulivyoiunda, au kuunda moja wewe mwenyewe, tunapendekeza sana uangalie mafunzo yetu mengine, ["Jinsi ya Kuunda NFT."](https://www.alchemy.com/docs/how-to-create-an-nft).
+
+### ABI ya mkataba {#contract-abi}
+
+Ikiwa umechunguza faili zetu kwa karibu, utakuwa umegundua kuwa katika saraka yetu ya `src`, kuna faili ya `contract-abi.json`. ABI ni muhimu kwa kubainisha kazi ipi mkataba utaomba na pia kuhakikisha kuwa kazi hiyo itarudisha data katika umbizo unalotarajia.
+
+Pia tutahitaji ufunguo wa API wa Alchemy na API ya Alchemy Web3 ili kuunganisha kwenye mnyororo wa bloku wa Ethereum na kupakia mkataba wetu erevu.
+
+### Tengeneza ufunguo wako wa API wa Alchemy {#create-alchemy-api}
+
+Ikiwa bado huna akaunti ya Alchemy, [jisajili bila malipo hapa.](https://alchemy.com/?a=eth-org-nft-minter)
+
+Mara tu unapounda akaunti ya Alchemy, unaweza kutengeneza ufunguo wa API kwa kuunda programu. Hii itaturuhusu kufanya maombi kwa mtandao wa majaribio wa Ropsten.
+
+Nenda kwenye ukurasa wa "Tengeneza Programu" kwenye Dashibodi yako ya Alchemy kwa kuelea juu ya "Programu" kwenye upau wa kusogeza na kubofya "Tengeneza Programu".
+
+Ipe programu yako jina, tulichagua "NFT Yangu ya Kwanza!", toa maelezo mafupi, chagua "Staging" kwa Mazingira yanayotumika kwa uwekaji hesabu wa programu yako, na uchague "Ropsten" kwa mtandao wako.
+
+Bofya βUnda programuβ na ndivyo hivyo! Programu yako inapaswa kuonekana kwenye jedwali lililo hapa chini.
+
+Safi sana, sasa kwa kuwa tumeunda URL yetu ya API ya HTTP Alchemy, inakili kwenye ubao wako wa kunakili...
+
+β¦na kisha tuiongeze kwenye faili yetu ya `.env`. Kwa pamoja, faili yako ya .env inapaswa kuonekana hivi:
+
+```text
+REACT_APP_PINATA_KEY =
+REACT_APP_PINATA_SECRET =
+REACT_APP_ALCHEMY_KEY = https://eth-ropsten.alchemyapi.io/v2/
+```
+
+Sasa kwa kuwa tuna ABI ya mkataba wetu na ufunguo wetu wa API wa Alchemy, tuko tayari kupakia mkataba wetu erevu kwa kutumia [Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3).
+
+### Sanidi sehemu yako ya mwisho ya Alchemy Web3 na mkataba {#setup-alchemy-endpoint}
+
+Kwanza, ikiwa bado huna, utahitaji kusakinisha [Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3) kwa kwenda kwenye saraka ya nyumbani: `nft-minter-tutorial` kwenye terminal:
+
+```text
+cd ..
+npm install @alch/alchemy-web3
+```
+
+Kisha turudi kwenye faili yetu ya `interact.js`. Juu ya faili, ongeza msimbo ufuatao ili kuingiza ufunguo wako wa Alchemy kutoka kwenye faili yako ya .env na kusanidi sehemu yako ya mwisho ya 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) ni kifuniko karibu na [Web3.js](https://docs.web3js.org/), inayotoa mbinu za API zilizoboreshwa na manufaa mengine muhimu ili kurahisisha maisha yako kama msanidi programu wa web3. Imeundwa kuhitaji usanidi mdogo ili uweze kuanza kuitumia katika programu yako mara moja!
+
+Kisha, hebu tuongeze ABI ya mkataba wetu na anwani ya mkataba kwenye faili yetu.
+
+```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"
+```
+
+Mara tu tunapokuwa na zote mbili, tuko tayari kuanza kuandika kazi yetu ya uundaji!
+
+## Tekeleza kazi ya mintNFT {#implement-the-mintnft-function}
+
+Ndani ya faili yako ya `interact.js`, hebu tufafanue kazi yetu, `mintNFT`, ambayo itaunda NFT yetu.
+
+Kwa sababu tutakuwa tukifanya simu nyingi zisizolingana (kwa Pinata kubandika metadata yetu kwenye IPFS, Alchemy Web3 kupakia mkataba wetu erevu, na MetaMask kusaini miamala yetu), kazi yetu pia itakuwa isiyolingana.
+
+Maingizo matatu kwa kazi yetu yatakuwa `url` ya mali yetu ya kidijitali, `name`, na `description`. Ongeza saini ifuatayo ya kazi chini ya kazi ya `connectWallet`:
+
+```javascript
+export const mintNFT = async (url, name, description) => {}
+```
+
+### Ushughulikiaji wa hitilafu ya ingizo {#input-error-handling}
+
+Kwa kawaida, inaleta maana kuwa na aina fulani ya ushughulikiaji wa hitilafu ya ingizo mwanzoni mwa kazi, ili tuondoke kwenye kazi hii ikiwa vigezo vyetu vya ingizo si sahihi. Ndani ya kazi yetu, hebu tuongeze msimbo ufuatao:
+
+```javascript
+export const mintNFT = async (url, name, description) => {
+ //ushughulikiaji wa hitilafu
+ if (url.trim() == "" || name.trim() == "" || description.trim() == "") {
+ return {
+ success: false,
+ status: "βTafadhali hakikisha sehemu zote zimekamilika kabla ya kuunda.",
+ }
+ }
+}
+```
+
+Kimsingi, ikiwa kigezo chochote cha ingizo ni mfuatano tupu, basi tunarudisha kitu cha JSON ambapo boolean ya `success` ni uongo, na mfuatano wa `status` unaeleza kuwa sehemu zote katika UI yetu lazima zikamilike.
+
+### Pakia metadata kwenye IPFS {#upload-metadata-to-ipfs}
+
+Mara tu tunapojua metadata yetu imeumbizwa ipasavyo, hatua inayofuata ni kuifunga katika kitu cha JSON na kuipakia kwenye IPFS kupitia `pinJSONToIPFS` tuliyoiandika!
+
+Ili kufanya hivyo, kwanza tunahitaji kuingiza kazi ya `pinJSONToIPFS` kwenye faili yetu ya `interact.js`. Juu kabisa ya `interact.js`, hebu tuongeze:
+
+```javascript
+import { pinJSONToIPFS } from "./pinata.js"
+```
+
+Kumbuka kwamba `pinJSONToIPFS` inachukua mwili wa JSON. Kwa hivyo kabla ya kuifanyia wito, tutahitaji kuumbiza vigezo vyetu vya `url`, `name`, na `description` kuwa kitu cha JSON.
+
+Hebu tusasishe msimbo wetu ili kuunda kitu cha JSON kinachoitwa `metadata` na kisha kufanya wito kwa `pinJSONToIPFS` na kigezo hiki cha `metadata`:
+
+```javascript
+export const mintNFT = async (url, name, description) => {
+ //ushughulikiaji wa hitilafu
+ if (url.trim() == "" || name.trim() == "" || description.trim() == "") {
+ return {
+ success: false,
+ status: "βTafadhali hakikisha sehemu zote zimekamilika kabla ya kuunda.",
+ }
+ }
+
+ //tengeneza metadata
+ const metadata = new Object()
+ metadata.name = name
+ metadata.image = url
+ metadata.description = description
+
+ //fanya wito wa pinata
+ const pinataResponse = await pinJSONToIPFS(metadata)
+ if (!pinataResponse.success) {
+ return {
+ success: false,
+ status: "π’ Kitu kiliharibika wakati wa kupakia tokenURI yako.",
+ }
+ }
+ const tokenURI = pinataResponse.pinataUrl
+}
+```
+
+Kumbuka, tunahifadhi jibu la wito wetu kwa `pinJSONToIPFS(metadata)` katika kitu cha `pinataResponse`. Kisha, tunachanganua kitu hiki kwa makosa yoyote.
+
+Ikiwa kuna hitilafu, tunarudisha kitu cha JSON ambapo boolean ya `success` ni uongo na mfuatano wetu wa `status` unaeleza kuwa wito wetu umeshindwa. Vinginevyo, tunatoa `pinataURL` kutoka kwa `pinataResponse` na kuihifadhi kama kigezo chetu cha `tokenURI`.
+
+Sasa ni wakati wa kupakia mkataba wetu erevu kwa kutumia API ya Alchemy Web3 ambayo tuliianzisha juu ya faili yetu. Ongeza mstari ufuatao wa msimbo chini ya kazi ya `mintNFT` ili kuweka mkataba kwenye kigezo cha kimataifa cha `window.contract`:
+
+```javascript
+window.contract = await new web3.eth.Contract(contractABI, contractAddress)
+```
+
+Jambo la mwisho la kuongeza katika kazi yetu ya `mintNFT` ni muamala wetu wa Ethereum:
+
+```javascript
+//weka muamala wako wa Ethereum
+const transactionParameters = {
+ to: contractAddress, // Inahitajika isipokuwa wakati wa uchapishaji wa mkataba.
+ from: window.ethereum.selectedAddress, // lazima ifanane na anwani amilifu ya mtumiaji.
+ data: window.contract.methods
+ .mintNFT(window.ethereum.selectedAddress, tokenURI)
+ .encodeABI(), //fanya wito kwa mkataba erevu wa NFT
+}
+
+//tia saini muamala kupitia MetaMask
+try {
+ const txHash = await window.ethereum.request({
+ method: "eth_sendTransaction",
+ params: [transactionParameters],
+ })
+ return {
+ success: true,
+ status:
+ "β Angalia muamala wako kwenye Etherscan: https://ropsten.etherscan.io/tx/" +
+ txHash,
+ }
+} catch (error) {
+ return {
+ success: false,
+ status: "π₯ Kitu kiliharibika: " + error.message,
+ }
+}
+```
+
+Ikiwa tayari unafahamu miamala ya Ethereum, utagundua kuwa muundo unafanana sana na ule uliouona.
+
+- Kwanza, tunaweka vigezo vyetu vya miamala.
+ - `to` inabainisha anwani ya mpokeaji (mkataba wetu erevu)
+ - `from` inabainisha mtia saini wa muamala (anwani iliyounganishwa ya mtumiaji kwenye MetaMask: `window.ethereum.selectedAddress`)
+ - `data` ina wito kwa mbinu yetu ya `mintNFT` ya mkataba erevu, ambayo inapokea `tokenURI` yetu na anwani ya pochi ya mtumiaji, `window.ethereum.selectedAddress`, kama maingizo
+- Kisha, tunafanya wito wa kusubiri, `window.ethereum.request,` ambapo tunaiomba MetaMask isaini muamala. Kumbuka, katika ombi hili, tunabainisha mbinu yetu ya eth (eth_SentTransaction) na kupitisha vigezo vyetu vya `transactionParameters`. Katika hatua hii, MetaMask itafunguka kwenye kivinjari, na kumwomba mtumiaji asaini au kukataa muamala.
+ - Ikiwa muamala utafanikiwa, kazi hiyo itarudisha kitu cha JSON ambapo boolean `success` imewekwa kuwa kweli na mfuatano wa `status` unamwomba mtumiaji aangalie Etherscan kwa maelezo zaidi kuhusu muamala wao.
+ - Ikiwa muamala utashindwa, kazi hiyo itarudisha kitu cha JSON ambapo boolean `success` imewekwa kuwa uongo, na mfuatano wa `status` unaeleza ujumbe wa hitilafu.
+
+Kwa pamoja, kazi yetu ya `mintNFT` inapaswa kuonekana hivi:
+
+```javascript
+export const mintNFT = async (url, name, description) => {
+ //ushughulikiaji wa hitilafu
+ if (url.trim() == "" || name.trim() == "" || description.trim() == "") {
+ return {
+ success: false,
+ status: "βTafadhali hakikisha sehemu zote zimekamilika kabla ya kuunda.",
+ }
+ }
+
+ //tengeneza metadata
+ const metadata = new Object()
+ metadata.name = name
+ metadata.image = url
+ metadata.description = description
+
+ //ombi la kubandika la pinata
+ const pinataResponse = await pinJSONToIPFS(metadata)
+ if (!pinataResponse.success) {
+ return {
+ success: false,
+ status: "π’ Kitu kiliharibika wakati wa kupakia tokenURI yako.",
+ }
+ }
+ const tokenURI = pinataResponse.pinataUrl
+
+ //pakia mkataba erevu
+ window.contract = await new web3.eth.Contract(contractABI, contractAddress) //loadContract();
+
+ //weka muamala wako wa Ethereum
+ const transactionParameters = {
+ to: contractAddress, // Inahitajika isipokuwa wakati wa uchapishaji wa mkataba.
+ from: window.ethereum.selectedAddress, // lazima ifanane na anwani amilifu ya mtumiaji.
+ data: window.contract.methods
+ .mintNFT(window.ethereum.selectedAddress, tokenURI)
+ .encodeABI(), //fanya wito kwa mkataba erevu wa NFT
+ }
+
+ //saini muamala kupitia MetaMask
+ try {
+ const txHash = await window.ethereum.request({
+ method: "eth_sendTransaction",
+ params: [transactionParameters],
+ })
+ return {
+ success: true,
+ status:
+ "β Angalia muamala wako kwenye Etherscan: https://ropsten.etherscan.io/tx/" +
+ txHash,
+ }
+ } catch (error) {
+ return {
+ success: false,
+ status: "π₯ Kitu kiliharibika: " + error.message,
+ }
+ }
+}
+```
+
+Hiyo ni kazi kubwa sana! Sasa, tunahitaji tu kuunganisha kazi yetu ya `mintNFT` kwenye kijenzi chetu cha `Minter.js`...
+
+## Unganisha mintNFT kwenye frontend yetu ya Minter.js {#connect-our-frontend}
+
+Fungua faili yako ya `Minter.js` na usasishe mstari wa `import { connectWallet, getCurrentWalletConnected } from "./utils/interact.js";` juu ili uwe:
+
+```javascript
+import {
+ connectWallet,
+ getCurrentWalletConnected,
+ mintNFT,
+} from "./utils/interact.js"
+```
+
+Mwishowe, tekeleza kazi ya `onMintPressed` ili kufanya wito wa kusubiri kwa kazi yako iliyoingizwa ya `mintNFT` na usasishe kigezo cha hali cha `status` ili kuonyesha kama muamala wetu ulifanikiwa au ulishindwa:
+
+```javascript
+const onMintPressed = async () => {
+ const { status } = await mintNFT(url, name, description)
+ setStatus(status)
+}
+```
+
+## Sambaza NFT yako kwenye tovuti ya moja kwa moja {#deploy-your-NFT}
+
+Uko tayari kupeleka mradi wako moja kwa moja ili watumiaji waingiliane nao? Angalia [mafunzo haya](https://docs.alchemy.com/alchemy/tutorials/nft-minter/how-do-i-deploy-nfts-online) kwa ajili ya kusambaza Minter yako kwenye tovuti ya moja kwa moja.
+
+Hatua moja ya mwisho...
+
+## Tikisa ulimwengu wa mnyororo wa bloku {#take-the-blockchain-world-by-storm}
+
+Utani tu, umefika mwisho wa mafunzo!
+
+Kwa muhtasari, kwa kuunda muunda wa NFT, umefanikiwa kujifunza jinsi ya:
+
+- Unganisha kwenye MetaMask kupitia mradi wako wa frontend
+- Ita mbinu za mkataba erevu kutoka kwa frontend yako
+- Saini miamala kwa kutumia MetaMask
+
+Labda, ungependa kuweza kuonyesha NFT zilizoundwa kupitia mfumo wako uliotawanywa kwenye pochi yako β kwa hivyo hakikisha unaangalia mafunzo yetu ya haraka [Jinsi ya Kuona NFT Yako Kwenye Pochi Yako](https://www.alchemy.com/docs/how-to-view-your-nft-in-your-mobile-wallet)!
+
+Na, kama kawaida, ikiwa una maswali yoyote, tuko hapa kusaidia katika [Alchemy Discord](https://discord.gg/gWuC7zB). Hatuwezi kusubiri kuona jinsi utakavyotumia dhana kutoka kwa mafunzo haya kwenye miradi yako ya baadaye!
diff --git a/public/content/translations/sw/developers/tutorials/optimism-std-bridge-annotated-code/index.md b/public/content/translations/sw/developers/tutorials/optimism-std-bridge-annotated-code/index.md
new file mode 100644
index 00000000000..ae4617b2b71
--- /dev/null
+++ b/public/content/translations/sw/developers/tutorials/optimism-std-bridge-annotated-code/index.md
@@ -0,0 +1,1356 @@
+---
+title: "Mwongozo wa mkataba wa daraja la kawaida la Optimism"
+description: Je, daraja la kawaida la Optimism linafanyaje kazi? Kwa nini linafanya kazi kwa njia hii?
+author: Ori Pomerantz
+tags: ["solidity", "bridge", "layer 2"]
+skill: intermediate
+published: 2022-03-30
+lang: sw
+---
+
+[Optimism](https://www.optimism.io/) ni [Optimistic Rollup](/developers/docs/scaling/optimistic-rollups/).
+Optimistic rollups zinaweza kuchakata miamala kwa bei ya chini zaidi kuliko Mtandao Mkuu wa Ethereum (pia inajulikana kama safu 1 au L1) kwa sababu miamala inachakatwa na nodi chache tu, badala ya kila nodi kwenye mtandao.
+Wakati huo huo, data yote imeandikwa kwa L1 ili kila kitu kiweze kuthibitishwa na kujengwa upya kwa uadilifu wote na dhamana ya upatikanaji wa Mtandao Mkuu.
+
+Ili kutumia rasilimali za L1 kwenye Optimism (au L2 nyingine yoyote), rasilimali zinahitaji [kuvushwa kwa daraja](/bridges/#prerequisites).
+Njia moja ya kufanikisha hili ni kwa watumiaji kufunga rasilimali (ETH na [tokeni za ERC-20](/developers/docs/standards/tokens/erc-20/) ndizo za kawaida zaidi) kwenye L1, na kupokea rasilimali sawa za kutumia kwenye L2.
+Hatimaye, yeyote atakayeishia nazo anaweza kutaka kuzivusha kwa daraja kurudi L1.
+Wakati wa kufanya hivi, rasilimali huchomwa kwenye L2 na kisha kurejeshwa kwa mtumiaji kwenye L1.
+
+Hivi ndivyo [daraja la kawaida la Optimism](https://docs.optimism.io/app-developers/bridging/standard-bridge) linavyofanya kazi.
+Katika makala haya tunapitia msimbo chanzo wa daraja hilo ili kuona jinsi linavyofanya kazi na kulichunguza kama mfano wa msimbo wa Solidity ulioandikwa vizuri.
+
+## Mtiririko wa udhibiti {#control-flows}
+
+Daraja lina mitiririko mikuu miwili:
+
+- Kuweka (kutoka L1 hadi L2)
+- Kutoa (kutoka L2 hadi L1)
+
+### Mtiririko wa uwekaji {#deposit-flow}
+
+#### Safu 1 {#deposit-flow-layer-1}
+
+1. Ikiwa unaweka ERC-20, mwekaji anatoa ruhusa kwa daraja kutumia kiasi kinachowekwa
+2. Mwekaji anapiga simu daraja la L1 (`depositERC20`, `depositERC20To`, `depositETH`, au `depositETHTo`)
+3. Daraja la L1 linachukua umiliki wa rasilimali iliyovushwa kwa daraja
+ - ETH: Rasilimali inahamishwa na mwekaji kama sehemu ya simu
+ - ERC-20: Rasilimali inahamishwa na daraja kwake yenyewe kwa kutumia ruhusa iliyotolewa na mwekaji
+4. Daraja la L1 linatumia utaratibu wa ujumbe wa vikoa tofauti kupiga simu `finalizeDeposit` kwenye daraja la L2
+
+#### Safu 2 {#deposit-flow-layer-2}
+
+5. Daraja la L2 huhakikisha simu kwa `finalizeDeposit` ni halali:
+ - Imetoka kwenye mkataba wa ujumbe wa vikoa tofauti
+ - Hapo awali ilitoka kwenye daraja kwenye L1
+6. Daraja la L2 huangalia ikiwa mkataba wa tokeni ya ERC-20 kwenye L2 ni sahihi:
+ - Mkataba wa L2 unaripoti kuwa mwenzake wa L1 ni sawa na ule ambao tokeni zilitoka kwenye L1
+ - Mkataba wa L2 unaripoti kuwa unaauni kiolesura sahihi ([kwa kutumia ERC-165](https://eips.ethereum.org/EIPS/eip-165)).
+7. Ikiwa mkataba wa L2 ni sahihi, piga simu ili kutoa idadi ifaayo ya tokeni kwa anwani ifaayo. Ikiwa sivyo, anza mchakato wa kutoa ili kumruhusu mtumiaji kudai tokeni kwenye L1.
+
+### Mtiririko wa utoaji {#withdrawal-flow}
+
+#### Safu 2 {#withdrawal-flow-layer-2}
+
+1. Mtoaji anapiga simu daraja la L2 (`withdraw` au `withdrawTo`)
+2. Daraja la L2 huchoma idadi ifaayo ya tokeni za `msg.sender`
+3. Daraja la L2 hutumia utaratibu wa ujumbe wa vikoa tofauti kupiga simu `finalizeETHWithdrawal` au `finalizeERC20Withdrawal` kwenye daraja la L1
+
+#### Safu 1 {#withdrawal-flow-layer-1}
+
+4. Daraja la L1 huhakikisha simu kwa `finalizeETHWithdrawal` au `finalizeERC20Withdrawal` ni halali:
+ - Imetoka kwenye utaratibu wa ujumbe wa vikoa tofauti
+ - Hapo awali ilitoka kwenye daraja kwenye L2
+5. Daraja la L1 huhamisha rasilimali ifaayo (ETH au ERC-20) kwa anwani ifaayo
+
+## Msimbo wa Safu 1 {#layer-1-code}
+
+Huu ndio msimbo unaoendeshwa kwenye L1, Mtandao Mkuu wa Ethereum.
+
+### IL1ERC20Bridge {#IL1ERC20Bridge}
+
+[Kiolesura hiki kimefafanuliwa hapa](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/IL1ERC20Bridge.sol).
+Inajumuisha kazi na ufafanuzi unaohitajika kwa kuvusha tokeni za ERC-20 kwa daraja.
+
+```solidity
+// SPDX-License-Identifier: MIT
+```
+
+[Sehemu kubwa ya msimbo wa Optimism hutolewa chini ya leseni ya 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;
+```
+
+Wakati wa kuandika toleo la hivi karibuni la Solidity ni 0.8.12.
+Hadi toleo la 0.9.0 litolewe, hatujui kama msimbo huu unaendana nalo au la.
+
+```solidity
+/**
+ * @title IL1ERC20Bridge
+ */
+interface IL1ERC20Bridge {
+ /**********
+ * Matukio *
+ **********/
+
+ event ERC20DepositInitiated(
+```
+
+Katika istilahi za daraja la Optimism _kuweka_ kunamaanisha uhamisho kutoka L1 hadi L2, na _kutoa_ kunamaanisha uhamisho kutoka L2 hadi L1.
+
+```solidity
+ anwani iliyoorodheshwa _l1Token,
+ anwani iliyoorodheshwa _l2Token,
+```
+
+Katika hali nyingi anwani ya ERC-20 kwenye L1 si sawa na anwani ya ERC-20 inayolingana kwenye L2.
+[Unaweza kuona orodha ya anwani za tokeni hapa](https://static.optimism.io/optimism.tokenlist.json).
+Anwani yenye `chainId` 1 iko kwenye L1 (Mtandao Mkuu) na anwani yenye `chainId` 10 iko kwenye L2 (Optimism).
+Thamani zingine mbili za `chainId` ni za mtandao wa majaribio wa Kovan (42) na mtandao wa majaribio wa Optimistic Kovan (69).
+
+```solidity
+ anwani iliyoorodheshwa _from,
+ anwani _to,
+ uint256 _amount,
+ bytes _data
+ );
+```
+
+Inawezekana kuongeza maelezo kwenye uhamisho, ambapo huongezwa kwenye matukio yanayoyaripoti.
+
+```solidity
+ event ERC20WithdrawalFinalized(
+ anwani iliyoorodheshwa _l1Token,
+ anwani iliyoorodheshwa _l2Token,
+ anwani iliyoorodheshwa _from,
+ anwani _to,
+ uint256 _amount,
+ bytes _data
+ );
+```
+
+Mkataba huo huo wa daraja hushughulikia uhamisho katika pande zote mbili.
+Kwa upande wa daraja la L1, hii inamaanisha uanzishaji wa uwekaji na ukamilishaji wa utoaji.
+
+```solidity
+
+ /********************
+ * Kazi za Umma *
+ ********************/
+
+ /**
+ * @dev pata anwani ya mkataba wa daraja la L2 unaolingana.
+ * @return Anwani ya mkataba wa daraja la L2 unaolingana.
+ */
+ function l2TokenBridge() external returns (anwani);
+```
+
+Kazi hii haihitajiki sana, kwa sababu kwenye L2 ni mkataba uliotumwa awali, kwa hivyo huwa kwenye anwani `0x4200000000000000000000000000000000000010`.
+Iko hapa kwa ulinganifu na daraja la L2, kwa sababu anwani ya daraja la L1 si rahisi kujua.
+
+```solidity
+ /**
+ * @dev weka kiasi cha ERC20 kwenye salio la mpigaji simu kwenye L2.
+ * @param _l1Token Anwani ya ERC20 ya L1 tunayoweka
+ * @param _l2Token Anwani ya ERC20 ya L2 inayolingana na L1
+ * @param _amount Kiasi cha ERC20 cha kuweka
+ * @param _l2Gas Kikomo cha gesi kinachohitajika kukamilisha uwekaji kwenye L2.
+ * @param _data Data ya hiari ya kupeleka kwa L2. Data hii hutolewa
+ * kama urahisi tu kwa mikataba ya nje. Mbali na kutekeleza urefu wa juu,
+ * mikataba hii haitoi dhamana yoyote kuhusu maudhui yake.
+ */
+ function depositERC20(
+ anwani _l1Token,
+ anwani _l2Token,
+ uint256 _amount,
+ uint32 _l2Gas,
+ bytes calldata _data
+ ) external;
+```
+
+Kigezo cha `_l2Gas` ni kiasi cha gesi ya L2 ambacho muamala unaruhusiwa kutumia.
+[Hadi kikomo fulani (cha juu), hii ni bure](https://community.optimism.io/docs/developers/bridge/messaging/#for-l1-%E2%87%92-l2-transactions-2), kwa hivyo isipokuwa mkataba wa ERC-20 unafanya jambo la ajabu sana wakati wa kutoa, haipaswi kuwa suala.
+Kazi hii inashughulikia hali ya kawaida, ambapo mtumiaji huvusha rasilimali kwa daraja kwenda anwani ileile kwenye mnyororo wa bloku tofauti.
+
+```solidity
+ /**
+ * @dev weka kiasi cha ERC20 kwenye salio la mpokeaji kwenye L2.
+ * @param _l1Token Anwani ya ERC20 ya L1 tunayoweka
+ * @param _l2Token Anwani ya ERC20 ya L2 inayolingana na L1
+ * @param _to Anwani ya L2 ya kuweka utoaji.
+ * @param _amount Kiasi cha ERC20 cha kuweka.
+ * @param _l2Gas Kikomo cha gesi kinachohitajika kukamilisha uwekaji kwenye L2.
+ * @param _data Data ya hiari ya kupeleka kwa L2. Data hii hutolewa
+ * kama urahisi tu kwa mikataba ya nje. Mbali na kutekeleza urefu wa juu,
+ * mikataba hii haitoi dhamana yoyote kuhusu maudhui yake.
+ */
+ function depositERC20To(
+ anwani _l1Token,
+ anwani _l2Token,
+ anwani _to,
+ uint256 _amount,
+ uint32 _l2Gas,
+ bytes calldata _data
+ ) external;
+```
+
+Kazi hii ni karibu sawa na `depositERC20`, lakini inakuwezesha kutuma ERC-20 kwa anwani tofauti.
+
+```solidity
+ /*************************
+ * Kazi za Mnyororo-Msalaba *
+ *************************/
+
+ /**
+ * @dev Kamilisha utoaji kutoka L2 hadi L1, na weka fedha kwenye salio la mpokeaji la
+ * tokeni ya L1 ERC20.
+ * Simu hii itashindwa ikiwa utoaji ulioanzishwa kutoka L2 haujakamilishwa.
+ *
+ * @param _l1Token Anwani ya tokeni ya L1 ya kukamilisha utoaji.
+ * @param _l2Token Anwani ya tokeni ya L2 ambapo utoaji ulianzishwa.
+ * @param _from Anwani ya L2 inayoanzisha uhamisho.
+ * @param _to Anwani ya L1 ya kuweka utoaji.
+ * @param _amount Kiasi cha ERC20 cha kuweka.
+ * @param _data Data iliyotolewa na mtumaji kwenye L2. Data hii hutolewa
+ * kama urahisi tu kwa mikataba ya nje. Mbali na kutekeleza urefu wa juu,
+ * mikataba hii haitoi dhamana yoyote kuhusu maudhui yake.
+ */
+ function finalizeERC20Withdrawal(
+ anwani _l1Token,
+ anwani _l2Token,
+ anwani _from,
+ anwani _to,
+ uint256 _amount,
+ bytes calldata _data
+ ) external;
+}
+```
+
+Utoaji (na ujumbe mwingine kutoka L2 hadi L1) katika Optimism ni mchakato wa hatua mbili:
+
+1. Muamala wa kuanzisha kwenye L2.
+2. Muamala wa ukamilishaji au kudai kwenye L1.
+ Muamala huu unahitaji kufanyika baada ya [kipindi cha changamoto ya makosa](https://community.optimism.io/docs/how-optimism-works/#fault-proofs) kwa muamala wa L2 kuisha.
+
+### IL1StandardBridge {#il1standardbridge}
+
+[Kiolesura hiki kimefafanuliwa hapa](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/IL1StandardBridge.sol).
+Faili hili lina ufafanuzi wa matukio na kazi kwa ETH.
+Ufafanuzi huu unafanana sana na ule uliofafanuliwa katika `IL1ERC20Bridge` hapo juu kwa ERC-20.
+
+Kiolesura cha daraja kimegawanywa kati ya faili mbili kwa sababu baadhi ya tokeni za ERC-20 zinahitaji usindikaji maalum na haziwezi kushughulikiwa na daraja la kawaida.
+Kwa njia hii daraja maalum linaloshughulikia tokeni kama hiyo linaweza kutekeleza `IL1ERC20Bridge` na sio lazima pia kuvusha ETH kwa daraja.
+
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity >0.5.0 <0.9.0;
+
+import "./IL1ERC20Bridge.sol";
+
+/**
+ * @title IL1StandardBridge
+ */
+interface IL1StandardBridge is IL1ERC20Bridge {
+ /**********
+ * Matukio *
+ **********/
+ event ETHDepositInitiated(
+ anwani iliyoorodheshwa _from,
+ anwani iliyoorodheshwa _to,
+ uint256 _amount,
+ bytes _data
+ );
+```
+
+Tukio hili ni karibu sawa na toleo la ERC-20 (`ERC20DepositInitiated`), isipokuwa bila anwani za tokeni za L1 na L2.
+Hali kadhalika kwa matukio mengine na kazi.
+
+```solidity
+ event ETHWithdrawalFinalized(
+ .
+ .
+ .
+ );
+
+ /********************
+ * Kazi za Umma *
+ ********************/
+
+ /**
+ * @dev Weka kiasi cha ETH kwenye salio la mpigaji simu kwenye L2.
+ .
+ .
+ .
+ */
+ function depositETH(uint32 _l2Gas, bytes calldata _data) external payable;
+
+ /**
+ * @dev Weka kiasi cha ETH kwenye salio la mpokeaji kwenye L2.
+ .
+ .
+ .
+ */
+ function depositETHTo(
+ anwani _to,
+ uint32 _l2Gas,
+ bytes calldata _data
+ ) external payable;
+
+ /*************************
+ * Kazi za Mnyororo-Msalaba *
+ *************************/
+
+ /**
+ * @dev Kamilisha utoaji kutoka L2 hadi L1, na weka fedha kwenye salio la mpokeaji la
+ * tokeni ya L1 ETH. Kwa kuwa ni xDomainMessenger pekee anayeweza kupiga simu kazi hii, haitapigwa kamwe
+ * kabla ya utoaji kukamilishwa.
+ .
+ .
+ .
+ */
+ function finalizeETHWithdrawal(
+ anwani _from,
+ anwani _to,
+ uint256 _amount,
+ bytes calldata _data
+ ) external;
+}
+```
+
+### CrossDomainEnabled {#crossdomainenabled}
+
+[Mkataba huu](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/bridge/CrossDomainEnabled.sol) unarithiwa na madaraja yote mawili ([L1](#the-l1-bridge-contract) na [L2](#the-l2-bridge-contract)) kutuma ujumbe kwa safu nyingine.
+
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity >0.5.0 <0.9.0;
+
+/* Interface Imports */
+import { ICrossDomainMessenger } from "./ICrossDomainMessenger.sol";
+```
+
+[Kiolesura hiki](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/bridge/ICrossDomainMessenger.sol) kinaeleza mkataba jinsi ya kutuma ujumbe kwa safu nyingine, kwa kutumia mtumaji ujumbe wa vikoa tofauti.
+Mtumaji ujumbe huu wa vikoa tofauti ni mfumo mwingine kabisa, na unastahili makala yake, ambayo natumai kuandika katika siku zijazo.
+
+```solidity
+/**
+ * @title CrossDomainEnabled
+ * @dev Mkataba msaidizi kwa mikataba inayofanya mawasiliano ya vikoa tofauti
+ *
+ * Mkusanyaji uliotumika: umefafanuliwa na mkataba unaorithi
+ */
+contract CrossDomainEnabled {
+ /*************
+ * Vigeu *
+ *************/
+
+ // Mkataba wa Mtumaji Ujumbe unaotumika kutuma na kupokea ujumbe kutoka kwa kikoa kingine.
+ anwani public messenger;
+
+ /***************
+ * Kijenzi *
+ ***************/
+
+ /**
+ * @param _messenger Anwani ya CrossDomainMessenger kwenye safu ya sasa.
+ */
+ constructor(anwani _messenger) {
+ messenger = _messenger;
+ }
+```
+
+Kigezo kimoja ambacho mkataba unahitaji kujua, anwani ya mtumaji ujumbe wa vikoa tofauti kwenye safu hii.
+Kigezo hiki kinawekwa mara moja, katika kijenzi, na hakibadiliki kamwe.
+
+```solidity
+
+ /**********************
+ * Virekebishaji Kazi *
+ **********************/
+
+ /**
+ * Hutekeleza kwamba kazi iliyorekebishwa inaweza kupigwa simu tu na akaunti maalum ya kikoa tofauti.
+ * @param _sourceDomainAccount Akaunti pekee kwenye kikoa cha asili ambayo
+ * imethibitishwa kupiga simu kazi hii.
+ */
+ modifier onlyFromCrossDomainAccount(anwani _sourceDomainAccount) {
+```
+
+Ujumbe wa vikoa tofauti unaweza kufikiwa na mkataba wowote kwenye mnyororo wa bloku ambapo unaendeshwa (iwe Mtandao Mkuu wa Ethereum au Optimism).
+Lakini tunahitaji daraja kwa kila upande _tu_ kuamini ujumbe fulani ikiwa unatoka kwenye daraja kwa upande mwingine.
+
+```solidity
+ require(
+ msg.sender == address(getCrossDomainMessenger()),
+ "OVM_XCHAIN: mkataba wa mtumaji ujumbe haujathibitishwa"
+ );
+```
+
+Ujumbe tu kutoka kwa mtumaji ujumbe wa vikoa tofauti unaofaa (`messenger`, kama unavyoona hapa chini) unaweza kuaminiwa.
+
+```solidity
+
+ require(
+ getCrossDomainMessenger().xDomainMessageSender() == _sourceDomainAccount,
+ "OVM_XCHAIN: mtumaji asiye sahihi wa ujumbe wa kikoa tofauti"
+ );
+```
+
+Njia ambayo mtumaji ujumbe wa vikoa tofauti anatoa anwani iliyotuma ujumbe na safu nyingine ni [kazi ya `.xDomainMessageSender()`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol#L122-L128).
+Muda wote inapoitwa katika muamala ulioanzishwa na ujumbe inaweza kutoa habari hii.
+
+Tunahitaji kuhakikisha kuwa ujumbe tuliopokea ulitoka kwenye daraja lingine.
+
+```solidity
+
+ _;
+ }
+
+ /**********************
+ * Kazi za Ndani *
+ **********************/
+
+ /**
+ * Hupata mtumaji ujumbe, kawaida kutoka kwenye hifadhi. Kazi hii inawekwa wazi iwapo mkataba mtoto
+ * unahitaji kubatilisha.
+ * @rejesha Anwani ya mkataba wa mtumaji ujumbe wa vikoa tofauti ambayo inapaswa kutumika.
+ */
+ function getCrossDomainMessenger() internal virtual returns (ICrossDomainMessenger) {
+ return ICrossDomainMessenger(messenger);
+ }
+```
+
+Kazi hii inarejesha mtumaji ujumbe wa vikoa tofauti.
+Tunatumia kazi badala ya kigezo `messenger` kuruhusu mikataba inayorithi kutoka kwa hii kutumia algoriti kubainisha ni mtumaji ujumbe gani wa vikoa tofauti wa kutumia.
+
+```solidity
+
+ /**
+ * Hutuma ujumbe kwa akaunti kwenye kikoa kingine
+ * @param _crossDomainTarget Mpokeaji aliyekusudiwa kwenye kikoa lengwa
+ * @param _message Data ya kutuma kwa lengo (kawaida calldata kwa kazi yenye
+ * `onlyFromCrossDomainAccount()`)
+ * @param _gasLimit Kikomo cha gesi kwa risiti ya ujumbe kwenye kikoa lengwa.
+ */
+ function sendCrossDomainMessage(
+ anwani _crossDomainTarget,
+ uint32 _gasLimit,
+ bytes memory _message
+```
+
+Hatimaye, kazi inayotuma ujumbe kwa safu nyingine.
+
+```solidity
+ ) internal {
+ // slither-disable-next-line reentrancy-events, reentrancy-benign
+```
+
+[Slither](https://github.com/crytic/slither) ni kichanganuzi tuli ambacho Optimism huendesha kwenye kila mkataba kutafuta udhaifu na matatizo mengine yanayoweza kutokea.
+Katika kesi hii, mstari unaofuata unasababisha udhaifu mbili:
+
+1. [Matukio ya Kuingia Tena](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3)
+2. [Kuingia tena kusiko na madhara](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2)
+
+```solidity
+ getCrossDomainMessenger().sendMessage(_crossDomainTarget, _message, _gasLimit);
+ }
+}
+```
+
+Katika kesi hii hatuna wasiwasi kuhusu kuingia tena tunajua `getCrossDomainMessenger()` inarejesha anwani inayoaminika, hata kama Slither haina njia ya kujua hilo.
+
+### Mkataba wa daraja la L1 {#the-l1-bridge-contract}
+
+[Msimbo chanzo wa mkataba huu uko hapa](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;
+```
+
+Violesura vinaweza kuwa sehemu ya mikataba mingine, kwa hivyo vinapaswa kuunga mkono anuwai ya matoleo ya Solidity.
+Lakini daraja lenyewe ni mkataba wetu, na tunaweza kuwa wakali kuhusu toleo gani la Solidity linatumia.
+
+```solidity
+/* Interface Imports */
+import { IL1StandardBridge } from "./IL1StandardBridge.sol";
+import { IL1ERC20Bridge } from "./IL1ERC20Bridge.sol";
+```
+
+[IL1ERC20Bridge](#IL1ERC20Bridge) na [IL1StandardBridge](#IL1StandardBridge) zimeelezwa hapo juu.
+
+```solidity
+import { IL2ERC20Bridge } from "../../L2/messaging/IL2ERC20Bridge.sol";
+```
+
+[Kiolesura hiki](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol) kinaturuhusu kuunda ujumbe wa kudhibiti daraja la kawaida kwenye L2.
+
+```solidity
+import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+```
+
+[Kiolesura hiki](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol) kinaturuhusu kudhibiti mikataba ya ERC-20.
+[Unaweza kusoma zaidi kuhusu hilo hapa](/developers/tutorials/erc20-annotated-code/#the-interface).
+
+```solidity
+/* Library Imports */
+import { CrossDomainEnabled } from "../../libraries/bridge/CrossDomainEnabled.sol";
+```
+
+[Kama ilivyoelezwa hapo juu](#crossdomainenabled), mkataba huu unatumika kwa ujumbe wa kati ya safu.
+
+```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) ina anwani za mikataba ya L2 ambayo huwa na anwani sawa kila wakati. Hii inajumuisha daraja la kawaida kwenye L2.
+
+```solidity
+import { Address } from "@openzeppelin/contracts/utils/Address.sol";
+```
+
+[Huduma za Anwani za OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol). Inatumika kutofautisha kati ya anwani za mkataba na zile za akaunti zinazomilikiwa na watu wa nje (EOA).
+
+Kumbuka kuwa hili si suluhisho kamilifu, kwa sababu hakuna njia ya kutofautisha kati ya simu za moja kwa moja na simu zilizopigwa kutoka kwa kijenzi cha mkataba, lakini angalau hii inatuwezesha kutambua na kuzuia baadhi ya makosa ya kawaida ya watumiaji.
+
+```solidity
+import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
+```
+
+[Kiwango cha ERC-20](https://eips.ethereum.org/EIPS/eip-20) kinaauni njia mbili kwa mkataba kuripoti kutofaulu:
+
+1. Batilisha
+2. Rejesha `false`
+
+Kushughulikia kesi zote mbili kungefanya msimbo wetu kuwa mgumu zaidi, kwa hivyo badala yake tunatumia [`SafeERC20` ya OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol), ambayo inahakikisha [kushindwa kote kunasababisha ubatilishaji](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol#L96).
+
+```solidity
+/**
+ * @title L1StandardBridge
+ * @dev L1 ETH na ERC20 Bridge ni mkataba unaohifadhi fedha za L1 zilizowekwa na tokeni za kawaida
+ * ambazo zinatumika kwenye L2. Inasawazisha Daraja la L2 linalolingana, kulijulisha kuhusu uwekaji
+ * na kulisikiliza kwa utoaji mpya uliokamilishwa.
+ *
+ */
+contract L1StandardBridge is IL1StandardBridge, CrossDomainEnabled {
+ using SafeERC20 for IERC20;
+```
+
+Mstari huu ndivyo tunavyobainisha kutumia kifuniko cha `SafeERC20` kila tunapotumia kiolesura cha `IERC20`.
+
+```solidity
+
+ /********************************
+ * Marejeleo ya Mkataba wa Nje *
+ ********************************/
+
+ anwani public l2TokenBridge;
+```
+
+Anwani ya [L2StandardBridge](#the-l2-bridge-contract).
+
+```solidity
+
+ // Ramani za tokeni ya L1 kwa tokeni ya L2 kwa salio la tokeni ya L1 iliyowekwa
+ mapping(anwani => mapping(anwani => uint256)) public deposits;
+```
+
+Ramani maradufu kama hii ndiyo njia unayofafanua [safu ya pande mbili isiyo na mpangilio](https://en.wikipedia.org/wiki/Sparse_matrix).
+Thamani katika muundo huu wa data zinatambuliwa kama `deposit[anwani ya tokeni ya L1][anwani ya tokeni ya L2]`.
+Thamani chaguo-msingi ni sufuri.
+Seli tu zilizowekwa kwa thamani tofauti ndizo huandikwa kwenye hifadhi.
+
+```solidity
+
+ /***************
+ * Kijenzi *
+ ***************/
+
+ // Mkataba huu unaishi nyuma ya wakala, kwa hivyo vigezo vya kijenzi havitatumika.
+ constructor() CrossDomainEnabled(anwani(0)) {}
+```
+
+Ili kutaka kuweza kusasisha mkataba huu bila kulazimika kunakili vigezo vyote kwenye hifadhi.
+Ili kufanya hivyo tunatumia [`Wakala`](https://docs.openzeppelin.com/contracts/3.x/api/proxy), mkataba unaotumia [`delegatecall`](https://solidity-by-example.org/delegatecall/) kuhamisha simu kwa mkataba tofauti ambao anwani yake imehifadhiwa na mkataba wa wakala (unaposasisha unamwambia wakala kubadilisha anwani hiyo).
+Unapotumia `delegatecall` hifadhi inabaki kuwa hifadhi ya mkataba _unaopiga simu_, kwa hivyo thamani za vigezo vyote vya hali ya mkataba haziathiriwi.
+
+Moja ya athari za muundo huu ni kwamba hifadhi ya mkataba ambao ni _uliopigiwa simu_ wa `delegatecall` haitumiwi na kwa hivyo thamani za kijenzi zilizopitishwa kwake hazijalishi.
+Hii ndiyo sababu tunaweza kutoa thamani isiyo na maana kwa kijenzi cha `CrossDomainEnabled`.
+Pia ndiyo sababu uanzishaji hapa chini umetenganishwa na kijenzi.
+
+```solidity
+ /******************
+ * Uanzishaji *
+ ******************/
+
+ /**
+ * @param _l1messenger Anwani ya L1 Messenger inayotumika kwa mawasiliano ya mnyororo-msalaba.
+ * @param _l2TokenBridge Anwani ya daraja la kawaida la L2.
+ */
+ // slither-disable-next-line external-function
+```
+
+[Jaribio hili la Slither](https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-external) linatambua kazi ambazo hazipigwi simu kutoka kwa msimbo wa mkataba na kwa hivyo zinaweza kutangazwa kuwa `za nje` badala ya `za umma`.
+Gharama ya gesi ya kazi za `nje` inaweza kuwa chini, kwa sababu zinaweza kupewa vigezo katika calldata.
+Kazi zilizotangazwa kuwa `za umma` zinapaswa kufikiwa kutoka ndani ya mkataba.
+Mikataba haiwezi kurekebisha calldata zao wenyewe, kwa hivyo vigezo vinapaswa kuwa kwenye kumbukumbu.
+Wakati kazi kama hiyo inapoitwa kutoka nje, ni muhimu kunakili calldata kwenye kumbukumbu, ambayo inagharimu gesi.
+Katika kesi hii kazi inaitwa mara moja tu, kwa hivyo ufanisi haujalishi kwetu.
+
+```solidity
+ function initialize(anwani _l1messenger, anwani _l2TokenBridge) public {
+ require(messenger == address(0), "Mkataba tayari umeanzishwa.");
+```
+
+Kazi ya `initialize` inapaswa kuitwa mara moja tu.
+Ikiwa anwani ya mtumaji ujumbe wa vikoa tofauti wa L1 au daraja la tokeni la L2 itabadilika, tunaunda wakala mpya na daraja jipya linaloiita.
+Hili haliwezekani kutokea isipokuwa mfumo mzima unaposasishwa, tukio la nadra sana.
+
+Kumbuka kuwa kazi hii haina utaratibu wowote unaozuia _nani_ anaweza kuiita.
+Hii inamaanisha kuwa kwa nadharia mshambuliaji anaweza kusubiri hadi tutumie wakala na toleo la kwanza la daraja na kisha [kufanya shughuli haraka](https://solidity-by-example.org/hacks/front-running/) kufikia kazi ya `initialize` kabla ya mtumiaji halali kufanya hivyo. Lakini kuna njia mbili za kuzuia hili:
+
+1. Ikiwa mikataba haitumwi moja kwa moja na EOA lakini [katika muamala ambao una mkataba mwingine uwaumbe](https://medium.com/upstate-interactive/creating-a-contract-with-a-smart-contract-bdb67c5c8595) mchakato mzima unaweza kuwa wa atomiki, na kumalizika kabla ya muamala mwingine wowote kutekelezwa.
+2. Ikiwa simu halali kwa `initialize` itashindwa daima inawezekana kupuuza wakala na daraja jipya lililoundwa na kuunda mpya.
+
+```solidity
+ messenger = _l1messenger;
+ l2TokenBridge = _l2TokenBridge;
+ }
+```
+
+Hivi ni vigezo viwili ambavyo daraja linahitaji kujua.
+
+```solidity
+
+ /**************
+ * Uwekaji *
+ **************/
+
+ /** @dev Kirekebishaji kinachohitaji mtumaji awe EOA. Ukaguzi huu unaweza kuepukwa na mkataba hasidi
+ * kupitia initcode, lakini inashughulikia kosa la mtumiaji tunalotaka kuepuka.
+ */
+ modifier onlyEOA() {
+ // Inatumika kusimamisha uwekaji kutoka kwa mikataba (epuka tokeni zilizopotea kwa bahati mbaya)
+ require(!Address.isContract(msg.sender), "Akaunti si EOA");
+ _;
+ }
+```
+
+Hii ndiyo sababu tulihitaji huduma za `Anwani` za OpenZeppelin.
+
+```solidity
+ /**
+ * @dev Kazi hii inaweza kuitwa bila data
+ * kuweka kiasi cha ETH kwenye salio la mpigaji simu kwenye L2.
+ * Kwa kuwa kazi ya kupokea haichukui data, kiasi
+ * chaguo-msingi cha kihafidhina hupelekwa L2.
+ */
+ receive() external payable onlyEOA {
+ _initiateETHDeposit(msg.sender, msg.sender, 200_000, bytes(""));
+ }
+```
+
+Kazi hii ipo kwa madhumuni ya majaribio.
+Kumbuka kuwa haionekani katika ufafanuzi wa kiolesura - si kwa matumizi ya kawaida.
+
+```solidity
+ /**
+ * @inheritdoc IL1StandardBridge
+ */
+ function depositETH(uint32 _l2Gas, bytes calldata _data) external payable onlyEOA {
+ _initiateETHDeposit(msg.sender, msg.sender, _l2Gas, _data);
+ }
+
+ /**
+ * @inheritdoc IL1StandardBridge
+ */
+ function depositETHTo(
+ anwani _to,
+ uint32 _l2Gas,
+ bytes calldata _data
+ ) external payable {
+ _initiateETHDeposit(msg.sender, _to, _l2Gas, _data);
+ }
+```
+
+Kazi hizi mbili ni vifuniko vinavyozunguka `_initiateETHDeposit`, kazi inayoshughulikia uwekaji halisi wa ETH.
+
+```solidity
+ /**
+ * @dev Hufanya mantiki ya uwekaji kwa kuhifadhi ETH na kumjulisha Lango la ETH la L2 kuhusu
+ * uwekaji.
+ * @param _from Akaunti ya kuchukua uwekaji kutoka L1.
+ * @param _to Akaunti ya kumpa uwekaji kwenye L2.
+ * @param _l2Gas Kikomo cha gesi kinachohitajika kukamilisha uwekaji kwenye L2.
+ * @param _data Data ya hiari ya kupeleka kwa L2. Data hii hutolewa
+ * kama urahisi tu kwa mikataba ya nje. Mbali na kutekeleza urefu wa juu,
+ * mikataba hii haitoi dhamana yoyote kuhusu maudhui yake.
+ */
+ function _initiateETHDeposit(
+ anwani _from,
+ anwani _to,
+ uint32 _l2Gas,
+ bytes memory _data
+ ) internal {
+ // Jenga calldata kwa simu ya finalizeDeposit
+ bytes memory message = abi.encodeWithSelector(
+```
+
+Njia ambayo ujumbe wa vikoa tofauti hufanya kazi ni kwamba mkataba lengwa unaitwa na ujumbe kama calldata yake.
+Mikataba ya Solidity daima hutafsiri calldata zao kulingana na
+[vipimo vya ABI](https://docs.soliditylang.org/en/v0.8.12/abi-spec.html).
+Kazi ya Solidity [`abi.encodeWithSelector`](https://docs.soliditylang.org/en/v0.8.12/units-and-global-variables.html#abi-encoding-and-decoding-functions) huunda calldata hiyo.
+
+```solidity
+ IL2ERC20Bridge.finalizeDeposit.selector,
+ anwani(0),
+ Lib_PredeployAddresses.OVM_ETH,
+ _from,
+ _to,
+ msg.value,
+ _data
+ );
+```
+
+Ujumbe hapa ni kupiga simu [kazi ya `finalizeDeposit`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/L2StandardBridge.sol#L141-L148) na vigezo hivi:
+
+| Kigezo | Thamani | Maana |
+| ------------------------------- | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| \_l1Token | anwani(0) | Thamani maalum ya kuwakilisha ETH (ambayo si tokeni ya ERC-20) kwenye L1 |
+| \_l2Token | Lib_PredeployAddresses.OVM_ETH | Mkataba wa L2 unaosimamia ETH kwenye Optimism, `0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000` (mkataba huu ni kwa matumizi ya ndani ya Optimism pekee) |
+| \_kutoka | \_kutoka | Anwani kwenye L1 inayotuma ETH |
+| \_kwa | \_kwa | Anwani kwenye L2 inayopokea ETH |
+| kiasi | msg.value | Kiasi cha wei kilichotumwa (ambacho tayari kimetumwa kwenye daraja) |
+| \_data | \_data | Data ya ziada ya kuambatisha kwenye uwekaji |
+
+```solidity
+ // Tuma calldata kwenye L2
+ // slither-disable-next-line reentrancy-events
+ sendCrossDomainMessage(l2TokenBridge, _l2Gas, ujumbe);
+```
+
+Tuma ujumbe kupitia mtumaji ujumbe wa vikoa tofauti.
+
+```solidity
+ // slither-disable-next-line reentrancy-events
+ emit ETHDepositInitiated(_from, _to, msg.value, _data);
+ }
+```
+
+Toa tukio la kujulisha programu yoyote iliyogatuliwa inayosikiliza kuhusu uhamisho huu.
+
+```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);
+ }
+```
+
+Kazi hizi mbili ni vifuniko vinavyozunguka `_initiateERC20Deposit`, kazi inayoshughulikia uwekaji halisi wa ERC-20.
+
+```solidity
+ /**
+ * @dev Hufanya mantiki ya uwekaji kwa kumjulisha mkataba wa Tokeni Iliyowekwa ya L2
+ * kuhusu uwekaji na kuita mshughulikiaji kufunga fedha za L1. (k.m., transferFrom)
+ *
+ * @param _l1Token Anwani ya ERC20 ya L1 tunayoweka
+ * @param _l2Token Anwani ya ERC20 ya L2 inayolingana na L1
+ * @param _from Akaunti ya kuchukua uwekaji kutoka L1
+ * @param _to Akaunti ya kumpa uwekaji kwenye L2
+ * @param _amount Kiasi cha ERC20 cha kuweka.
+ * @param _l2Gas Kikomo cha gesi kinachohitajika kukamilisha uwekaji kwenye L2.
+ * @param _data Data ya hiari ya kupeleka kwa L2. Data hii hutolewa
+ * kama urahisi tu kwa mikataba ya nje. Mbali na kutekeleza urefu wa juu,
+ * mikataba hii haitoi dhamana yoyote kuhusu maudhui yake.
+ */
+ function _initiateERC20Deposit(
+ anwani _l1Token,
+ anwani _l2Token,
+ anwani _from,
+ anwani _to,
+ uint256 _amount,
+ uint32 _l2Gas,
+ bytes calldata _data
+ ) internal {
+```
+
+Kazi hii inafanana na `_initiateETHDeposit` hapo juu, na tofauti chache muhimu.
+Tofauti ya kwanza ni kwamba kazi hii inapokea anwani za tokeni na kiasi cha kuhamisha kama vigezo.
+Kwa upande wa ETH simu kwa daraja tayari inajumuisha uhamisho wa rasilimali kwenda akaunti ya daraja (`msg.value`).
+
+```solidity
+ // Uwekaji unapoanzishwa kwenye L1, Daraja la L1 huhamisha fedha kwake lenyewe kwa ajili ya
+ // utoaji wa siku zijazo. safeTransferFrom pia huangalia ikiwa mkataba una msimbo, kwa hivyo hii itashindwa ikiwa
+ // _from ni EOA au anwani(0).
+ // slither-disable-next-line reentrancy-events, reentrancy-benign
+ IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount);
+```
+
+Uhamisho wa tokeni za ERC-20 hufuata mchakato tofauti na ETH:
+
+1. Mtumiaji (`_from`) anatoa ruhusa kwa daraja kuhamisha tokeni zinazofaa.
+2. Mtumiaji anapiga simu daraja na anwani ya mkataba wa tokeni, kiasi, n.k.
+3. Daraja linahamisha tokeni (kwake lenyewe) kama sehemu ya mchakato wa uwekaji.
+
+Hatua ya kwanza inaweza kutokea katika muamala tofauti na mbili za mwisho.
+Hata hivyo, uendeshaji-wa-mbele si tatizo kwa sababu kazi mbili zinazoita `_initiateERC20Deposit` (`depositERC20` na `depositERC20To`) huita kazi hii tu na `msg.sender` kama kigezo cha `_from`.
+
+```solidity
+ // Jenga calldata kwa _l2Token.finalizeDeposit(_to, _amount)
+ bytes memory message = abi.encodeWithSelector(
+ IL2ERC20Bridge.finalizeDeposit.selector,
+ _l1Token,
+ _l2Token,
+ _from,
+ _to,
+ _amount,
+ _data
+ );
+
+ // Tuma calldata kwenye L2
+ // slither-disable-next-line reentrancy-events, reentrancy-benign
+ sendCrossDomainMessage(l2TokenBridge, _l2Gas, ujumbe);
+
+ // slither-disable-next-line reentrancy-benign
+ deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] + _amount;
+```
+
+Ongeza kiasi cha tokeni zilizowekwa kwenye muundo wa data wa `deposits`.
+Kunaweza kuwa na anwani nyingi kwenye L2 zinazolingana na tokeni ileile ya L1 ERC-20, kwa hivyo haitoshi kutumia salio la daraja la tokeni ya L1 ERC-20 kufuatilia uwekaji.
+
+```solidity
+
+ // slither-disable-next-line reentrancy-events
+ emit ERC20DepositInitiated(_l1Token, _l2Token, _from, _to, _amount, _data);
+ }
+
+ /*************************
+ * Kazi za Mnyororo-Msalaba *
+ *************************/
+
+ /**
+ * @inheritdoc IL1StandardBridge
+ */
+ function finalizeETHWithdrawal(
+ anwani _from,
+ anwani _to,
+ uint256 _amount,
+ bytes calldata _data
+```
+
+Daraja la L2 hutuma ujumbe kwa mtumaji ujumbe wa vikoa tofauti wa L2 ambao husababisha mtumaji ujumbe wa vikoa tofauti wa L1 kupiga simu kazi hii (mara tu [muamala unaokamilisha ujumbe](https://community.optimism.io/docs/developers/bridge/messaging/#fees-for-l2-%E2%87%92-l1-transactions) utakapowasilishwa kwenye L1, bila shaka).
+
+```solidity
+ ) external onlyFromCrossDomainAccount(l2TokenBridge) {
+```
+
+Hakikisha kuwa huu ni ujumbe _halali_, unaotoka kwa mtumaji ujumbe wa vikoa tofauti na unaotokana na daraja la tokeni la L2.
+Kazi hii inatumika kutoa ETH kutoka kwa daraja, kwa hivyo tunapaswa kuhakikisha inaitwa tu na mpigaji simu aliyeidhinishwa.
+
+```solidity
+ // slither-disable-next-line reentrancy-events
+ (bool success, ) = _to.call{ value: _amount }(new bytes(0));
+```
+
+Njia ya kuhamisha ETH ni kumpigia simu mpokeaji na kiasi cha wei katika `msg.value`.
+
+```solidity
+ require(success, "TransferHelper::safeTransferETH: Uhamisho wa ETH umeshindwa");
+
+ // slither-disable-next-line reentrancy-events
+ emit ETHWithdrawalFinalized(_from, _to, _amount, _data);
+```
+
+Toa tukio kuhusu utoaji.
+
+```solidity
+ }
+
+ /**
+ * @inheritdoc IL1ERC20Bridge
+ */
+ function finalizeERC20Withdrawal(
+ anwani _l1Token,
+ anwani _l2Token,
+ anwani _from,
+ anwani _to,
+ uint256 _amount,
+ bytes calldata _data
+ ) external onlyFromCrossDomainAccount(l2TokenBridge) {
+```
+
+Kazi hii inafanana na `finalizeETHWithdrawal` hapo juu, na mabadiliko muhimu kwa tokeni za ERC-20.
+
+```solidity
+ deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] - _amount;
+```
+
+Sasisha muundo wa data wa `deposits`.
+
+```solidity
+ // Utoaji unapokamilishwa kwenye L1, Daraja la L1 huhamisha fedha kwa mtoaji
+ // 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);
+ }
+
+
+ /*****************************
+ * Ya muda - Kuhamisha ETH *
+ *****************************/
+
+ /**
+ * @dev Huongeza salio la ETH kwenye akaunti. Hii inakusudiwa kuruhusu ETH
+ * kuhamishwa kutoka lango la zamani hadi lango jipya.
+ * KUMBUKA: Hii imeachwa kwa sasisho moja tu ili tuweze kupokea ETH iliyohamishwa kutoka
+ * mkataba wa zamani
+ */
+ function donateETH() external payable {}
+}
+```
+
+Kulikuwa na utekelezaji wa awali wa daraja.
+Tulipohamia kutoka kwa utekelezaji huo hadi huu, tulilazimika kuhamisha rasilimali zote.
+Tokeni za ERC-20 zinaweza tu kuhamishwa.
+Hata hivyo, ili kuhamisha ETH kwa mkataba unahitaji idhini ya mkataba huo, ambayo ndiyo `donateETH` inatupatia.
+
+## Tokeni za ERC-20 kwenye L2 {#erc-20-tokens-on-l2}
+
+Ili tokeni ya ERC-20 iingie kwenye daraja la kawaida, inahitaji kuruhusu daraja la kawaida, na _tu_ daraja la kawaida, kutoa tokeni.
+Hii ni muhimu kwa sababu madaraja yanahitaji kuhakikisha kuwa idadi ya tokeni zinazozunguka kwenye Optimism ni sawa na idadi ya tokeni zilizofungwa ndani ya mkataba wa daraja la L1.
+Ikiwa kuna tokeni nyingi sana kwenye L2 baadhi ya watumiaji wasingeweza kuvusha rasilimali zao kwa daraja kurudi L1.
+Badala ya daraja linaloaminika, kimsingi tungeunda upya [benki ya hifadhi ya sehemu](https://www.investopedia.com/terms/f/fractionalreservebanking.asp).
+Ikiwa kuna tokeni nyingi sana kwenye L1, baadhi ya tokeni hizo zingebaki zimefungwa ndani ya mkataba wa daraja milele kwa sababu hakuna njia ya kuzitoa bila kuchoma tokeni za L2.
+
+### IL2StandardERC20 {#il2standarderc20}
+
+Kila tokeni ya ERC-20 kwenye L2 inayotumia daraja la kawaida inahitaji kutoa [kiolesura hiki](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/standards/IL2StandardERC20.sol), ambacho kina kazi na matukio ambayo daraja la kawaida linahitaji.
+
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.9;
+
+import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+```
+
+[Kiolesura cha kawaida cha ERC-20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol) hakijumuishi kazi za `mint` na `burn`.
+Njia hizo hazihitajiki na [kiwango cha ERC-20](https://eips.ethereum.org/EIPS/eip-20), ambacho kinaacha taratibu za kuunda na kuharibu tokeni bila kubainishwa.
+
+```solidity
+import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
+```
+
+[Kiolesura cha ERC-165](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/IERC165.sol) kinatumika kubainisha kazi ambazo mkataba unatoa.
+[Unaweza kusoma kiwango hapa](https://eips.ethereum.org/EIPS/eip-165).
+
+```solidity
+interface IL2StandardERC20 is IERC20, IERC165 {
+ function l1Token() external returns (anwani);
+```
+
+Kazi hii inatoa anwani ya tokeni ya L1 ambayo imevushwa kwa daraja kwenda mkataba huu.
+Kumbuka kuwa hatuna kazi kama hiyo kwa upande mwingine.
+Tunahitaji kuweza kuvusha kwa daraja tokeni yoyote ya L1, bila kujali kama msaada wa L2 ulipangwa wakati ilitekelezwa au la.
+
+```solidity
+
+ function mint(anwani _to, uint256 _amount) external;
+
+ function burn(anwani _from, uint256 _amount) external;
+
+ event Mint(anwani iliyoorodheshwa _account, uint256 _amount);
+ event Burn(anwani iliyoorodheshwa _account, uint256 _amount);
+}
+```
+
+Kazi na matukio ya kutoa (kuunda) na kuchoma (kuharibu) tokeni.
+Daraja linapaswa kuwa chombo pekee kinachoweza kuendesha kazi hizi ili kuhakikisha idadi ya tokeni ni sahihi (sawa na idadi ya tokeni zilizofungwa kwenye L1).
+
+### L2StandardERC20 {#L2StandardERC20}
+
+[Huu ndio utekelezaji wetu wa kiolesura cha `IL2StandardERC20`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/standards/L2StandardERC20.sol).
+Isipokuwa unahitaji aina fulani ya mantiki maalum, unapaswa kutumia hii.
+
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.9;
+
+import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
+```
+
+[Mkataba wa OpenZeppelin ERC-20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol).
+Optimism haiamini katika kuunda upya gurudumu, hasa wakati gurudumu limekaguliwa vizuri na linahitaji kuwa la kuaminika vya kutosha kushikilia rasilimali.
+
+```solidity
+import "./IL2StandardERC20.sol";
+
+contract L2StandardERC20 is IL2StandardERC20, ERC20 {
+ anwani public l1Token;
+ anwani public l2Bridge;
+```
+
+Hivi ni vigezo viwili vya ziada vya usanidi ambavyo tunahitaji na ERC-20 kawaida haihitaji.
+
+```solidity
+
+ /**
+ * @param _l2Bridge Anwani ya daraja la kawaida la L2.
+ * @param _l1Token Anwani ya tokeni ya L1 inayolingana.
+ * @param _name jina la ERC20.
+ * @param _symbol alama ya ERC20.
+ */
+ constructor(
+ anwani _l2Bridge,
+ anwani _l1Token,
+ string memory _name,
+ string memory _symbol
+ ) ERC20(_name, _symbol) {
+ l1Token = _l1Token;
+ l2Bridge = _l2Bridge;
+ }
+```
+
+Kwanza piga simu kijenzi cha mkataba tunachorithi kutoka (`ERC20(_name, _symbol)`) na kisha weka vigezo vyetu wenyewe.
+
+```solidity
+
+ modifier onlyL2Bridge() {
+ require(msg.sender == l2Bridge, "Ni Daraja la L2 pekee linaweza kutoa na kuchoma");
+ _;
+ }
+
+
+ // 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;
+ }
+```
+
+Hivi ndivyo [ERC-165](https://eips.ethereum.org/EIPS/eip-165) inavyofanya kazi.
+Kila kiolesura ni idadi ya kazi zinazoungwa mkono, na kinatambuliwa kama [au ya kipekee](https://en.wikipedia.org/wiki/Exclusive_or) ya [viteuzi vya kazi vya ABI](https://docs.soliditylang.org/en/v0.8.12/abi-spec.html#function-selector) vya kazi hizo.
+
+Daraja la L2 linatumia ERC-165 kama ukaguzi wa usalama kuhakikisha kuwa mkataba wa ERC-20 ambao linatuma rasilimali ni `IL2StandardERC20`.
+
+**Kumbuka:** Hakuna kinachozuia mkataba hasidi kutoa majibu ya uwongo kwa `supportsInterface`, kwa hivyo huu ni utaratibu wa ukaguzi wa usalama, _sio_ utaratibu wa usalama.
+
+```solidity
+ // slither-disable-next-line external-function
+ function mint(anwani _to, uint256 _amount) public virtual onlyL2Bridge {
+ _mint(_to, _amount);
+
+ emit Mint(_to, _amount);
+ }
+
+ // slither-disable-next-line external-function
+ function burn(anwani _from, uint256 _amount) public virtual onlyL2Bridge {
+ _burn(_from, _amount);
+
+ emit Burn(_from, _amount);
+ }
+}
+```
+
+Ni daraja la L2 pekee linaloruhusiwa kutoa na kuchoma rasilimali.
+
+`_mint` na `_burn` kwa kweli zimefafanuliwa katika [mkataba wa OpenZeppelin ERC-20](/developers/tutorials/erc20-annotated-code/#the-_mint-and-_burn-functions-_mint-and-_burn).
+Mkataba huo hauwaweki wazi nje, kwa sababu masharti ya kutoa na kuchoma tokeni ni tofauti kama idadi ya njia za kutumia ERC-20.
+
+## Msimbo wa Daraja la L2 {#l2-bridge-code}
+
+Huu ni msimbo unaoendesha daraja kwenye Optimism.
+[Chanzo cha mkataba huu kiko hapa](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 */
+import { IL1StandardBridge } from "../../L1/messaging/IL1StandardBridge.sol";
+import { IL1ERC20Bridge } from "../../L1/messaging/IL1ERC20Bridge.sol";
+import { IL2ERC20Bridge } from "./IL2ERC20Bridge.sol";
+```
+
+Kiolesura cha [IL2ERC20Bridge](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol) kinafanana sana na [sawa ya L1](#IL1ERC20Bridge) tuliyoona hapo juu.
+Kuna tofauti mbili muhimu:
+
+1. Kwenye L1 unaanzisha uwekaji na kukamilisha utoaji.
+ Hapa unaanzisha utoaji na kukamilisha uwekaji.
+2. Kwenye L1 ni muhimu kutofautisha kati ya ETH na tokeni za ERC-20.
+ Kwenye L2 tunaweza kutumia kazi zile zile kwa zote mbili kwa sababu ndani ya Optimism salio za ETH hushughulikiwa kama tokeni ya ERC-20 yenye anwani [0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000](https://explorer.optimism.io/address/0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000).
+
+```solidity
+/* Library Imports */
+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 */
+import { IL2StandardERC20 } from "../../standards/IL2StandardERC20.sol";
+
+/**
+ * @title L2StandardBridge
+ * @dev Daraja la Kawaida la L2 ni mkataba unaofanya kazi pamoja na daraja la Kawaida la L1
+ * kuwezesha mabadiliko ya ETH na ERC20 kati ya L1 na L2.
+ * Mkataba huu hufanya kazi kama mtoaji wa tokeni mpya inaposikia kuhusu uwekaji kwenye daraja la Kawaida la L1
+ *.
+ * Mkataba huu pia hufanya kazi kama mchomaji wa tokeni zilizokusudiwa kwa utoaji, ukijulisha daraja la L1
+ * kutoa fedha za L1.
+ */
+contract L2StandardBridge is IL2ERC20Bridge, CrossDomainEnabled {
+ /********************************
+ * Marejeleo ya Mkataba wa Nje *
+ ********************************/
+
+ anwani public l1TokenBridge;
+```
+
+Fuatilia anwani ya daraja la L1.
+Kumbuka kuwa tofauti na sawa ya L1, hapa _tunahitaji_ kigezo hiki.
+Anwani ya daraja la L1 haijulikani mapema.
+
+```solidity
+
+ /***************
+ * Kijenzi *
+ ***************/
+
+ /**
+ * @param _l2CrossDomainMessenger Mtumaji ujumbe wa vikoa tofauti unaotumiwa na mkataba huu.
+ * @param _l1TokenBridge Anwani ya daraja la L1 iliyotumwa kwenye mnyororo mkuu.
+ */
+ constructor(anwani _l2CrossDomainMessenger, anwani _l1TokenBridge)
+ CrossDomainEnabled(_l2CrossDomainMessenger)
+ {
+ l1TokenBridge = _l1TokenBridge;
+ }
+
+ /***************
+ * Utoaji *
+ ***************/
+
+ /**
+ * @inheritdoc IL2ERC20Bridge
+ */
+ function withdraw(
+ anwani _l2Token,
+ uint256 _amount,
+ uint32 _l1Gas,
+ bytes calldata _data
+ ) external virtual {
+ _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _l1Gas, _data);
+ }
+
+ /**
+ * @inheritdoc IL2ERC20Bridge
+ */
+ function withdrawTo(
+ anwani _l2Token,
+ anwani _to,
+ uint256 _amount,
+ uint32 _l1Gas,
+ bytes calldata _data
+ ) external virtual {
+ _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _l1Gas, _data);
+ }
+```
+
+Kazi hizi mbili zinaanzisha utoaji.
+Kumbuka kuwa hakuna haja ya kubainisha anwani ya tokeni ya L1.
+Tokeni za L2 zinatarajiwa kutuambia anwani sawa ya L1.
+
+```solidity
+
+ /**
+ * @dev Hufanya mantiki ya utoaji kwa kuchoma tokeni na kumjulisha
+ * Lango la tokeni la L1 kuhusu utoaji.
+ * @param _l2Token Anwani ya tokeni ya L2 ambapo utoaji unaanzishwa.
+ * @param _from Akaunti ya kuchukua utoaji kutoka L2.
+ * @param _to Akaunti ya kumpa utoaji kwenye L1.
+ * @param _amount Kiasi cha tokeni ya kutoa.
+ * @param _l1Gas Haijatumiwa, lakini imejumuishwa kwa mazingatio ya utangamano wa mbele.
+ * @param _data Data ya hiari ya kupeleka kwa L1. Data hii hutolewa
+ * kama urahisi tu kwa mikataba ya nje. Mbali na kutekeleza urefu wa juu,
+ * mikataba hii haitoi dhamana yoyote kuhusu maudhui yake.
+ */
+ function _initiateWithdrawal(
+ anwani _l2Token,
+ anwani _from,
+ anwani _to,
+ uint256 _amount,
+ uint32 _l1Gas,
+ bytes calldata _data
+ ) internal {
+ // Utoaji unapoanzishwa, tunachoma fedha za mtoaji ili kuzuia matumizi ya L2
+ //.
+ // slither-disable-next-line reentrancy-events
+ IL2StandardERC20(_l2Token).burn(msg.sender, _amount);
+```
+
+Kumbuka kuwa _hatutegemei_ kigezo cha `_from` bali `msg.sender` ambayo ni ngumu zaidi kughushi (haiwezekani, kwa kadiri ninavyojua).
+
+```solidity
+
+ // Jenga calldata kwa l1TokenBridge.finalizeERC20Withdrawal(_to, _amount)
+ // slither-disable-next-line reentrancy-events
+ anwani l1Token = IL2StandardERC20(_l2Token).l1Token();
+ bytes memory message;
+
+ if (_l2Token == Lib_PredeployAddresses.OVM_ETH) {
+```
+
+Kwenye L1 ni muhimu kutofautisha kati ya ETH na ERC-20.
+
+```solidity
+ ujumbe = abi.encodeWithSelector(
+ IL1StandardBridge.finalizeETHWithdrawal.selector,
+ _from,
+ _to,
+ _amount,
+ _data
+ );
+ } else {
+ ujumbe = abi.encodeWithSelector(
+ IL1ERC20Bridge.finalizeERC20Withdrawal.selector,
+ l1Token,
+ _l2Token,
+ _from,
+ _to,
+ _amount,
+ _data
+ );
+ }
+
+ // Tuma ujumbe hadi daraja la L1
+ // slither-disable-next-line reentrancy-events
+ sendCrossDomainMessage(l1TokenBridge, _l1Gas, ujumbe);
+
+ // slither-disable-next-line reentrancy-events
+ emit WithdrawalInitiated(l1Token, _l2Token, msg.sender, _to, _amount, _data);
+ }
+
+ /************************************
+ * Kazi ya Mnyororo-Msalaba: Uwekaji *
+ ************************************/
+
+ /**
+ * @inheritdoc IL2ERC20Bridge
+ */
+ function finalizeDeposit(
+ anwani _l1Token,
+ anwani _l2Token,
+ anwani _from,
+ anwani _to,
+ uint256 _amount,
+ bytes calldata _data
+```
+
+Kazi hii inaitwa na `L1StandardBridge`.
+
+```solidity
+ ) external virtual onlyFromCrossDomainAccount(l1TokenBridge) {
+```
+
+Hakikisha chanzo cha ujumbe ni halali.
+Hii ni muhimu kwa sababu kazi hii huita `_mint` na inaweza kutumika kutoa tokeni ambazo hazifunikwa na tokeni ambazo daraja linamiliki kwenye L1.
+
+```solidity
+ // Angalia tokeni lengwa inatii na
+ // hakikisha tokeni iliyowekwa kwenye L1 inalingana na uwakilishi wa tokeni iliyowekwa ya L2 hapa
+ if (
+ // slither-disable-next-line reentrancy-events
+ ERC165Checker.supportsInterface(_l2Token, 0x1d1d8b63) &&
+ _l1Token == IL2StandardERC20(_l2Token).l1Token()
+```
+
+Ukaguzi wa usalama:
+
+1. Kiolesura sahihi kinaauniwa
+2. Anwani ya L1 ya mkataba wa L2 ERC-20 inalingana na chanzo cha L1 cha tokeni
+
+```solidity
+ ) {
+ // Uwekaji unapokamilishwa, tunaweka kiasi sawa cha
+ // tokeni kwenye akaunti kwenye 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);
+```
+
+Ikiwa ukaguzi wa usalama utapita, kamilisha uwekaji:
+
+1. Toa tokeni
+2. Toa tukio linalofaa
+
+```solidity
+ } else {
+ // Labda tokeni ya L2 ambayo inawekwa-ndani haikubaliani kuhusu anwani sahihi
+ // ya tokeni yake ya L1, au haiauni kiolesura sahihi.
+ // Hii inapaswa kutokea tu ikiwa kuna tokeni hasidi ya L2, au ikiwa mtumiaji kwa namna fulani
+ // alibainisha anwani isiyo sahihi ya tokeni ya L2 ya kuweka.
+ // Katika hali yoyote, tunasimamisha mchakato hapa na kuunda ujumbe wa
+ // utoaji ili watumiaji waweze kutoa fedha zao katika baadhi ya kesi.
+ // Hakuna njia ya kuzuia mikataba ya tokeni hasidi kabisa, lakini hii inapunguza
+ // kosa la mtumiaji na kupunguza baadhi ya aina za tabia ya mkataba hasidi.
+```
+
+Ikiwa mtumiaji alifanya kosa linaloweza kugunduliwa kwa kutumia anwani isiyo sahihi ya tokeni ya L2, tunataka kughairi uwekaji na kurudisha tokeni kwenye L1.
+Njia pekee tunayoweza kufanya hivi kutoka L2 ni kutuma ujumbe ambao utalazimika kusubiri kipindi cha changamoto ya makosa, lakini hiyo ni bora zaidi kwa mtumiaji kuliko kupoteza tokeni kabisa.
+
+```solidity
+ bytes memory message = abi.encodeWithSelector(
+ IL1ERC20Bridge.finalizeERC20Withdrawal.selector,
+ _l1Token,
+ _l2Token,
+ _to, // tulibadilisha _to na _from hapa kurudisha uwekaji kwa mtumaji
+ _from,
+ _amount,
+ _data
+ );
+
+ // Tuma ujumbe hadi daraja la L1
+ // slither-disable-next-line reentrancy-events
+ sendCrossDomainMessage(l1TokenBridge, 0, ujumbe);
+ // slither-disable-next-line reentrancy-events
+ emit DepositFailed(_l1Token, _l2Token, _from, _to, _amount, _data);
+ }
+ }
+}
+```
+
+## Hitimisho {#conclusion}
+
+Daraja la kawaida ndio utaratibu unaobadilika zaidi kwa uhamisho wa rasilimali.
+Hata hivyo, kwa sababu ni ya jumla sana si rahisi kila wakati kutumia utaratibu huu.
+Hasa kwa utoaji, watumiaji wengi wanapendelea kutumia [madaraja ya watu wengine](https://optimism.io/apps#bridge) ambayo hayasubiri kipindi cha changamoto na hayahitaji uthibitisho wa Merkle kukamilisha utoaji.
+
+Madaraja haya kwa kawaida hufanya kazi kwa kuwa na rasilimali kwenye L1, ambazo hutoa mara moja kwa ada ndogo (mara nyingi chini ya gharama ya gesi kwa utoaji wa daraja la kawaida).
+Wakati daraja (au watu wanaoliendesha) linapotarajia kupungukiwa na rasilimali za L1 linahamisha rasilimali za kutosha kutoka L2. Kwa kuwa haya ni utoaji mkubwa sana, gharama ya utoaji inapunguzwa kwa kiasi kikubwa na ni asilimia ndogo zaidi.
+
+Tunatumai makala hii imekusaidia kuelewa zaidi kuhusu jinsi safu 2 inavyofanya kazi, na jinsi ya kuandika msimbo wa Solidity ulio wazi na salama.
+
+[Tazama hapa kwa kazi zangu zaidi](https://cryptodocguy.pro/).
diff --git a/public/content/translations/sw/developers/tutorials/reverse-engineering-a-contract/index.md b/public/content/translations/sw/developers/tutorials/reverse-engineering-a-contract/index.md
new file mode 100644
index 00000000000..f935bb8b37f
--- /dev/null
+++ b/public/content/translations/sw/developers/tutorials/reverse-engineering-a-contract/index.md
@@ -0,0 +1,744 @@
+---
+title: "Uhandisi wa Nyuma wa Mkataba"
+description: Jinsi ya kuelewa mkataba wakati huna msimbo chanzo
+author: Ori Pomerantz
+lang: sw
+tags: [ "evm", "opcodes" ]
+skill: advanced
+published: 2021-12-30
+---
+
+## Utangulizi {#introduction}
+
+_Hakuna siri kwenye blockchain_, kila kitu kinachotokea ni thabiti, kinaweza kuthibitishwa na kinapatikana kwa umma. Kimsingi, [mikataba inapaswa kuwa na msimbo wake chanzo uliochapishwa na kuthibitishwa kwenye Etherscan](https://etherscan.io/address/0xb8901acb165ed027e32754e0ffe830802919727f#code). Hata hivyo, [sio wakati wote ndivyo ilivyo](https://etherscan.io/address/0x2510c039cc3b061d79e564b38836da87e31b342f#code). Katika makala hii utajifunza jinsi ya kufanya uhandisi wa nyuma wa mikataba kwa kuangalia mkataba bila msimbo chanzo, [`0x2510c039cc3b061d79e564b38836da87e31b342f`](https://etherscan.io/address/0x2510c039cc3b061d79e564b38836da87e31b342f).
+
+Kuna vikompaila vya kinyume, lakini sio kila wakati vinatoa [matokeo yanayoweza kutumika](https://etherscan.io/bytecode-decompiler?a=0x2510c039cc3b061d79e564b38836da87e31b342f). Katika makala hii unajifunza jinsi ya kufanya uhandisi wa nyuma na kuelewa mkataba kutoka [kwa opcodes](https://github.com/wolflo/evm-opcodes), pamoja na jinsi ya kutafsiri matokeo ya decompiler.
+
+Ili kuweza kuelewa makala hii unapaswa kuwa unajua misingi ya EVM, na angalau uwe unafahamu kwa kiasi fulani mkusanyaji wa EVM. [Unaweza kusoma kuhusu mada hizi hapa](https://medium.com/mycrypto/the-ethereum-virtual-machine-how-does-it-work-9abac2b7c9e).
+
+## Andaa Msimbo Unaoweza Kutekelezwa {#prepare-the-executable-code}
+
+Unaweza kupata opcodes kwa kwenda Etherscan kwa ajili ya mkataba, kubofya kichupo cha **Contract** na kisha **Switch to Opcodes View**. Unapata mwonekano ambao ni opcode moja kwa kila mstari.
+
+
+
+Ili kuweza kuelewa miruko, hata hivyo, unahitaji kujua ni wapi katika msimbo kila opcode iko. Ili kufanya hivyo, njia moja ni kufungua Google Spreadsheet na kubandika opcodes katika safu C. [Unaweza kuruka hatua zifuatazo kwa kutengeneza nakala ya jedwali hili lililoandaliwa tayari](https://docs.google.com/spreadsheets/d/1tKmTJiNjUwHbW64wCKOSJxHjmh0bAUapt6btUYE7kDA/edit?usp=sharing).
+
+Hatua inayofuata ni kupata maeneo sahihi ya msimbo ili tuweze kuelewa miruko. Tutaweka ukubwa wa opcode katika safu B, na eneo (katika heksadesimali) katika safu A. Andika chaguo hili la kukokotoa katika seli `B1` na kisha nakili na ubandike kwa safu B iliyobaki, hadi mwisho wa msimbo. Baada ya kufanya hivi unaweza kuficha safu B.
+
+```
+=1+IF(REGEXMATCH(C1,"PUSH"),REGEXEXTRACT(C1,"PUSH(\d+)"),0)
+```
+
+Kwanza chaguo hili la kukokotoa linaongeza baiti moja kwa opcode yenyewe, na kisha hutafuta `PUSH`. Opcodes za kusukuma ni maalum kwa sababu zinahitaji kuwa na baiti za ziada kwa thamani inayosukumwa. Ikiwa opcode ni `PUSH`, tunatoa idadi ya baiti na kuiongeza.
+
+Katika `A1` weka kukabiliana kwanza, sifuri. Kisha, katika `A2`, weka chaguo hili la kukokotoa na tena nakili na ubandike kwa safu A iliyobaki:
+
+```
+=dec2hex(hex2dec(A1)+B1)
+```
+
+Tunahitaji chaguo hili la kukokotoa ili kutupa thamani ya heksadesimali kwa sababu thamani zinazosukumwa kabla ya miruko (`JUMP` na `JUMPI`) tunapewa katika heksadesimali.
+
+## Mahali pa Kuingilia (0x00) {#the-entry-point-0x00}
+
+Mikataba daima hutekelezwa kutoka kwa baiti ya kwanza. Hii ni sehemu ya awali ya msimbo:
+
+| Kukabiliana | Opcode | Rafu (baada ya opcode) |
+| ----------: | ------------ | ---------------------------------------------- |
+| 0 | PUSH1 0x80 | 0x80 |
+| 2 | PUSH1 0x40 | 0x40, 0x80 |
+| 4 | MSTORE | Tupu |
+| 5 | PUSH1 0x04 | 0x04 |
+| 7 | CALLDATASIZE | CALLDATASIZE 0x04 |
+| 8 | LT | CALLDATASIZE\<4 |
+| 9 | PUSH2 0x005e | 0x5E CALLDATASIZE\<4 |
+| C | JUMPI | Tupu |
+
+Msimbo huu hufanya mambo mawili:
+
+1. Andika 0x80 kama thamani ya baiti 32 kwenye maeneo ya kumbukumbu 0x40-0x5F (0x80 huhifadhiwa katika 0x5F, na 0x40-0x5E zote ni sifuri).
+2. Soma ukubwa wa calldata. Kwa kawaida data ya simu kwa ajili ya mkataba wa Ethereum hufuata [ABI (kiolesura cha binary cha mfumo)](https://docs.soliditylang.org/en/v0.8.10/abi-spec.html), ambayo kwa kiwango cha chini inahitaji baiti nne kwa kiteuzi cha chaguo la kukokotoa. Ikiwa ukubwa wa data ya simu ni chini ya nne, ruka hadi 0x5E.
+
+
+
+### Mshughulikiaji katika 0x5E (kwa data ya simu isiyo ya ABI) {#the-handler-at-0x5e-for-non-abi-call-data}
+
+| Kukabiliana | Opcode |
+| ----------: | ------------ |
+| 5E | JUMPDEST |
+| 5F | CALLDATASIZE |
+| 60 | PUSH2 0x007c |
+| 63 | JUMPI |
+
+Kipande hiki kinaanza na `JUMPDEST`. Programu za EVM (mashine halisi ya ethereum) hutupa ubaguzi ikiwa utaruka hadi opcode ambayo sio `JUMPDEST`. Kisha inaangalia CALLDATASIZE, na ikiwa ni "kweli" (yaani, sio sifuri) inaruka hadi 0x7C. Tutafikia hilo hapo chini.
+
+| Kukabiliana | Opcode | Rafu (baada ya opcode) |
+| ----------: | ---------- | ---------------------------------------------------------------------------------------------- |
+| 64 | CALLVALUE | [Wei](/glossary/#wei) iliyotolewa na simu. Inaitwa `msg.value` katika 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 | Ghala[6] CALLVALUE 0 6 CALLVALUE |
+
+Kwa hivyo wakati hakuna data ya simu tunasoma thamani ya Ghala[6]. Bado hatujui thamani hii ni nini, lakini tunaweza kutafuta miamala ambayo mkataba ulipokea bila data ya simu. Miamala ambayo huhamisha ETH tu bila data yoyote ya simu (na kwa hivyo hakuna njia) ina njia ya `Transfer` katika Etherscan. Kwa kweli, [muamala wa kwanza kabisa ambao mkataba ulipokea](https://etherscan.io/tx/0xeec75287a583c36bcc7ca87685ab41603494516a0f5986d18de96c8e630762e7) ni uhamisho.
+
+Tukiangalia katika muamala huo na kubofya **Click to see More**, tunaona kwamba data ya simu, inayoitwa data ya ingizo, kwa kweli haina kitu (`0x`). Angalia pia kwamba thamani ni ETH 1.559, hiyo itakuwa muhimu baadaye.
+
+
+
+Ifuatayo, bofya kichupo cha **Hali** na upanue mkataba tunaofanyia uhandisi wa nyuma (0x2510...). Unaweza kuona kwamba `Ghala[6]` ilibadilika wakati wa muamala, na ukibadilisha Hex kuwa **Nambari**, unaona ikawa 1,559,000,000,000,000,000, thamani iliyohamishwa katika wei (nimeongeza koma kwa uwazi), inayolingana na thamani ya mkataba unaofuata.
+
+![Mabadiliko katika Ghala[6]](storage6.png)
+
+Tukiangalia katika mabadiliko ya hali yaliyosababishwa na [miamala mingine ya `Transfer` kutoka kipindi hicho](https://etherscan.io/tx/0xf708d306de39c422472f43cb975d97b66fd5d6a6863db627067167cbf93d84d1#statechange) tunaona kwamba `Ghala[6]` ilifuatilia thamani ya mkataba kwa muda. Kwa sasa tutaiita `Value*`. Nyota (`*`) inatukumbusha kwamba bado hatu_jui_ kigezo hiki hufanya nini, lakini haiwezi kuwa tu kufuatilia thamani ya mkataba kwa sababu hakuna haja ya kutumia ghala, ambayo ni ghali sana, wakati unaweza kupata salio la akaunti yako ukitumia `ADDRESS BALANCE`. Opcode ya kwanza inasukuma anwani ya mkataba yenyewe. Ya pili inasoma anwani iliyo juu ya rafu na kuibadilisha na salio la anwani hiyo.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------ | --------------------------------------------- |
+| 6C | PUSH2 0x0075 | 0x75 Thamani\* CALLVALUE 0 6 CALLVALUE |
+| 6F | SWAP2 | CALLVALUE Thamani\* 0x75 0 6 CALLVALUE |
+| 70 | SWAP1 | Thamani\* CALLVALUE 0x75 0 6 CALLVALUE |
+| 71 | PUSH2 0x01a7 | 0x01A7 Thamani\* CALLVALUE 0x75 0 6 CALLVALUE |
+| 74 | JUMP | |
+
+Tutaendelea kufuatilia msimbo huu katika marudio ya mruko.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ---------- | ------------------------------------------------------------- |
+| 1A7 | JUMPDEST | Thamani\* CALLVALUE 0x75 0 6 CALLVALUE |
+| 1A8 | PUSH1 0x00 | 0x00 Thamani\* CALLVALUE 0x75 0 6 CALLVALUE |
+| 1AA | DUP3 | CALLVALUE 0x00 Thamani\* CALLVALUE 0x75 0 6 CALLVALUE |
+| 1AB | NOT | 2^256-CALLVALUE-1 0x00 Thamani\* CALLVALUE 0x75 0 6 CALLVALUE |
+
+`NOT` ni bitwise, kwa hivyo inabadilisha thamani ya kila biti katika thamani ya simu.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------ | ---------------------------------------------------------------------------------------------------------- |
+| 1AC | DUP3 | Thamani\* 2^256-CALLVALUE-1 0x00 Thamani\* CALLVALUE 0x75 0 6 CALLVALUE |
+| 1AD | GT | Thamani\*>2^256-CALLVALUE-1 0x00 Thamani\* CALLVALUE 0x75 0 6 CALLVALUE |
+| 1AE | ISZERO | Thamani\*\<=2^256-CALLVALUE-1 0x00 Thamani\* CALLVALUE 0x75 0 6 CALLVALUE |
+| 1AF | PUSH2 0x01df | 0x01DF Thamani\*\<=2^256-CALLVALUE-1 0x00 Thamani\* CALLVALUE 0x75 0 6 CALLVALUE |
+| 1B2 | JUMPI | |
+
+Tunaruka ikiwa `Value*` ni ndogo kuliko 2^256-CALLVALUE-1 au sawa nayo. Hii inaonekana kama mantiki ya kuzuia kufurika. Na kwa hakika, tunaona kwamba baada ya shughuli chache zisizo na maana (kuandika kwa kumbukumbu kunakaribia kufutwa, kwa mfano) kwa kukabiliana 0x01DE mkataba unarudi nyuma ikiwa kufurika kutagunduliwa, ambayo ni tabia ya kawaida.
+
+Kumbuka kuwa kufurika kama hivyo hakuna uwezekano mkubwa, kwa sababu kungehitaji thamani ya simu pamoja na `Thamani*` kulinganishwa na wei 2^256, takriban ETH 10^59. [Jumla ya usambazaji wa ETH, wakati wa kuandika, ni chini ya milioni mia mbili](https://etherscan.io/stat/supply).
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | -------- | ------------------------------------------- |
+| 1DF | JUMPDEST | 0x00 Thamani\* CALLVALUE 0x75 0 6 CALLVALUE |
+| 1E0 | POP | Thamani\* CALLVALUE 0x75 0 6 CALLVALUE |
+| 1E1 | ADD | Thamani\*+CALLVALUE 0x75 0 6 CALLVALUE |
+| 1E2 | SWAP1 | 0x75 Thamani\*+CALLVALUE 0 6 CALLVALUE |
+| 1E3 | JUMP | |
+
+Ikiwa tulifika hapa, pata `Thamani* + CALLVALUE` na uruke ili kukabiliana na 0x75.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | -------- | --------------------------------- |
+| 75 | JUMPDEST | Thamani\*+CALLVALUE 0 6 CALLVALUE |
+| 76 | SWAP1 | 0 Thamani\*+CALLVALUE 6 CALLVALUE |
+| 77 | SWAP2 | 6 Thamani\*+CALLVALUE 0 CALLVALUE |
+| 78 | SSTORE | 0 CALLVALUE |
+
+Tukifika hapa (ambayo inahitaji data ya simu kuwa tupu) tunaongeza kwa `Thamani*` thamani ya simu. Hii inaambatana na kile tunachosema miamala ya `Transfer` hufanya.
+
+| Kukabiliana | Opcode |
+| ----------: | ------ |
+| 79 | POP |
+| 7A | POP |
+| 7B | STOP |
+
+Hatimaye, futa rafu (ambayo si lazima) na uashiria mwisho wa mafanikio wa muamala.
+
+Ili kujumlisha yote, hii hapa chati ya mtiririko kwa msimbo wa awali.
+
+
+
+## Mshughulikiaji katika 0x7C {#the-handler-at-0x7c}
+
+Sikuweka kichwa cha habari kwa makusudi nini mhudumu huyu anafanya. Hoja sio kukufundisha jinsi mkataba huu maalum unavyofanya kazi, lakini jinsi ya kufanya uhandisi wa nyuma wa mikataba. Utajifunza inachofanya kwa njia ile ile niliyoifanya, kwa kufuata msimbo.
+
+Tunafika hapa kutoka sehemu kadhaa:
+
+- Ikiwa kuna data ya simu ya baiti 1, 2, au 3 (kutoka kwa kukabiliana 0x63)
+- Ikiwa saini ya mbinu haijulikani (kutoka kwa makabiliano 0x42 na 0x5D)
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------ | ---------------------------------------------------------------------- |
+| 7C | JUMPDEST | |
+| 7D | PUSH1 0x00 | 0x00 |
+| 7F | PUSH2 0x009d | 0x9D 0x00 |
+| 82 | PUSH1 0x03 | 0x03 0x9D 0x00 |
+| 84 | SLOAD | Ghala[3] 0x9D 0x00 |
+
+Hii ni seli nyingine ya ghala, ambayo sikuweza kupata katika miamala yoyote kwa hivyo ni ngumu kujua inamaanisha nini. Msimbo ulio hapa chini utaiweka wazi zaidi.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| 85 | PUSH20 0xffffffffffffffffffffffffffffffffffffffff | 0xff....ff Ghala[3] 0x9D 0x00 |
+| 9A | AND | Ghala[3]-kama-anwani 0x9D 0x00 |
+
+Opcode hizi hupunguza thamani tunayosoma kutoka kwa Ghala[3] hadi biti 160, urefu wa anwani ya Ethereum.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------ | ---------------------------------------------------------------------------------- |
+| 9B | SWAP1 | 0x9D Ghala[3]-kama-anwani 0x00 |
+| 9C | JUMP | Ghala[3]-kama-anwani 0x00 |
+
+Mruko huu ni wa ziada, kwani tunaenda kwa opcode inayofuata. Msimbo huu hauna ufanisi wa gesi kama unavyoweza kuwa.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ---------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 9D | JUMPDEST | Ghala[3]-kama-anwani 0x00 |
+| 9E | SWAP1 | 0x00 Ghala[3]-kama-anwani |
+| 9F | POP | Ghala[3]-kama-anwani |
+| A0 | PUSH1 0x40 | 0x40 Ghala[3]-kama-anwani |
+| A2 | MLOAD | Mem[0x40] Ghala[3]-kama-anwani |
+
+Mwanzoni kabisa mwa msimbo tuliweka Mem[0x40] kuwa 0x80. Tukiangalia 0x40 baadaye, tunaona kwamba hatuibadilishi - kwa hivyo tunaweza kudhani ni 0x80.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------ | ---------------------------------------------------------------------------------------------------- |
+| A3 | CALLDATASIZE | CALLDATASIZE 0x80 Ghala[3]-kama-anwani |
+| A4 | PUSH1 0x00 | 0x00 CALLDATASIZE 0x80 Ghala[3]-kama-anwani |
+| A6 | DUP3 | 0x80 0x00 CALLDATASIZE 0x80 Ghala[3]-kama-anwani |
+| A7 | CALLDATACOPY | 0x80 Ghala[3]-kama-anwani |
+
+Nakili data yote ya simu kwenye kumbukumbu, kuanzia 0x80.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| A8 | PUSH1 0x00 | 0x00 0x80 Ghala[3]-kama-anwani |
+| AA | DUP1 | 0x00 0x00 0x80 Ghala[3]-kama-anwani |
+| AB | CALLDATASIZE | CALLDATASIZE 0x00 0x00 0x80 Ghala[3]-kama-anwani |
+| AC | DUP4 | 0x80 CALLDATASIZE 0x00 0x00 0x80 Ghala[3]-kama-anwani |
+| AD | DUP6 | Ghala[3]-kama-anwani 0x80 CALLDATASIZE 0x00 0x00 0x80 Ghala[3]-kama-anwani |
+| AE | GAS | Gesi Ghala[3]-kama-anwani 0x80 CALLDATASIZE 0x00 0x00 0x80 Ghala[3]-kama-anwani |
+| AF | DELEGATE_CALL | |
+
+Sasa mambo ni wazi zaidi. Mkataba huu unaweza kufanya kazi kama [proksi](https://blog.openzeppelin.com/proxy-patterns/), ukiita anwani katika Ghala[3] kufanya kazi halisi. `DELEGATE_CALL` huita mkataba tofauti, lakini hubaki katika ghala moja. Hii inamaanisha kuwa mkataba uliokabidhiwa, ambao sisi ni proksi wake, hufikia nafasi sawa ya ghala. Vigezo vya simu ni:
+
+- _Gesi_: Gesi yote iliyobaki
+- _Anwani iliyopigiwa simu_: Ghala[3]-kama-anwani
+- _Data ya simu_: baiti za CALLDATASIZE kuanzia 0x80, ambayo ndipo tulipo weka data ya awali ya simu
+- _Data ya kurudisha_: Hakuna (0x00 - 0x00) Tutapata data ya kurudisha kwa njia zingine (tazama hapa chini)
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| B0 | RETURNDATASIZE | RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+| B1 | DUP1 | RETURNDATASIZE RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+| B2 | PUSH1 0x00 | 0x00 RETURNDATASIZE RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+| B4 | DUP5 | 0x80 0x00 RETURNDATASIZE RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+| B5 | RETURNDATACOPY | RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+
+Hapa tunakili data yote ya kurudi kwenye bafa ya kumbukumbu kuanzia 0x80.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| B6 | DUP2 | (((mafanikio/kutofaulu kwa simu))) RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+| B7 | DUP1 | (((mafanikio/kutofaulu kwa simu))) (((mafanikio/kutofaulu kwa simu))) RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+| B8 | ISZERO | (((simu ilishindwa))) (((mafanikio/kutofaulu kwa simu))) RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+| B9 | PUSH2 0x00c0 | 0xC0 (((simu ilishindwa))) (((mafanikio/kutofaulu kwa simu))) RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+| BC | JUMPI | (((mafanikio/kutofaulu kwa simu))) RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+| BD | DUP2 | RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+| BE | DUP5 | 0x80 RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+| BF | RETURN | |
+
+Kwa hivyo baada ya simu tunakili data ya kurudi kwenye bafa 0x80 - 0x80+RETURNDATASIZE, na ikiwa simu imefanikiwa basi `RETURN` na bafa hiyo haswa.
+
+### DELEGATECALL Imeshindwa {#delegatecall-failed}
+
+Tukifika hapa, hadi 0xC0, inamaanisha kwamba mkataba tuliopiga simu ulirudishwa nyuma. Kwa vile sisi ni proksi tu wa mkataba huo, tunataka kurudisha data sawa na pia kurudi nyuma.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| C0 | JUMPDEST | (((mafanikio/kutofaulu kwa simu))) RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+| C1 | DUP2 | RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+| C2 | DUP5 | 0x80 RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) RETURNDATASIZE (((mafanikio/kutofaulu kwa simu))) 0x80 Ghala[3]-kama-anwani |
+| C3 | REVERT | |
+
+Kwa hivyo sisi `REVERT` na bafa ile ile tuliyotumia kwa `RETURN` hapo awali: 0x80 - 0x80+RETURNDATASIZE
+
+
+
+## Simu za ABI {#abi-calls}
+
+Ikiwa ukubwa wa data ya simu ni baiti nne au zaidi hii inaweza kuwa simu halali ya ABI.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------ | -------------------------------------------------------------------------------------------------------------------------------- |
+| D | PUSH1 0x00 | 0x00 |
+| F | CALLDATALOAD | (((Neno la kwanza (biti 256) la data ya simu))) |
+| 10 | PUSH1 0xe0 | 0xE0 (((Neno la kwanza (biti 256) la data ya simu))) |
+| 12 | SHR | (((biti 32 za kwanza (baiti 4) za data ya simu))) |
+
+Etherscan inatuambia kwamba `1C` ni opcode isiyojulikana, kwa sababu [iliongezwa baada ya Etherscan kuandika kipengele hiki](https://eips.ethereum.org/EIPS/eip-145) na hawajaisasisha. Jedwali la [opcode lililosasishwa](https://github.com/wolflo/evm-opcodes) linatuonyesha kuwa hii ni shift right
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| 13 | DUP1 | (((biti 32 za kwanza (baiti 4) za data ya simu))) (((biti 32 za kwanza (baiti 4) za data ya simu))) |
+| 14 | PUSH4 0x3cd8045e | 0x3CD8045E (((biti 32 za kwanza (baiti 4) za data ya simu))) (((biti 32 za kwanza (baiti 4) za data ya simu))) |
+| 19 | GT | 0x3CD8045E>biti-32-za-kwanza-za-data-ya-simu (((biti 32 za kwanza (baiti 4) za data ya simu))) |
+| 1A | PUSH2 0x0043 | 0x43 0x3CD8045E>biti-32-za-kwanza-za-data-ya-simu (((biti 32 za kwanza (baiti 4) za data ya simu))) |
+| 1D | JUMPI | (((biti 32 za kwanza (baiti 4) za data ya simu))) |
+
+Kwa kugawanya majaribio ya ulinganishaji wa saini ya mbinu katika mbili kama hii huokoa nusu ya majaribio kwa wastani. Msimbo unaofuata mara moja hii na msimbo katika 0x43 hufuata muundo sawa: `DUP1` biti 32 za kwanza za data ya simu, `PUSH4 (((saini ya mbinu>`, endesha `EQ` ili kuangalia usawa, na kisha `JUMPI` ikiwa saini ya mbinu inalingana. Hapa kuna saini za mbinu, anwani zao, na ikiwa inajulikana [ufafanuzi wa mbinu unaolingana](https://www.4byte.directory/):
+
+| Njia | Sahihi ya njia | Kukabiliana na kuruka ndani |
+| --------------------------------------------------------------------------------------------------------- | -------------- | --------------------------- |
+| [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 |
+
+Ikiwa hakuna mechi inayopatikana, msimbo huruka hadi kwa [mshughulikiaji wa proksi saa 0x7C](#the-handler-at-0x7c), kwa matumaini kwamba mkataba ambao sisi ni proksi wake una mechi.
+
+
+
+## splitter() {#splitter}
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------ | ----------------------------- |
+| 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 | |
+
+Jambo la kwanza ambalo chaguo hili la kukokotoa hufanya ni kuangalia kuwa simu haikutuma ETH yoyote. Chaguo hili la kukokotoa sio [`payable`](https://solidity-by-example.org/payable/). Ikiwa mtu alitutumia ETH hiyo lazima iwe kosa na tunataka `REVERT` ili kuepuka kuwa na ETH hiyo ambapo hawawezi kuirudisha.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| 10F | JUMPDEST | |
+| 110 | POP | |
+| 111 | PUSH1 0x03 | 0x03 |
+| 113 | SLOAD | (((Ghala[3] a.k.a mkataba ambao sisi ni proksi))) |
+| 114 | PUSH1 0x40 | 0x40 (((Ghala[3] a.k.a mkataba ambao sisi ni proksi))) |
+| 116 | MLOAD | 0x80 (((Ghala[3] a.k.a mkataba ambao sisi ni proksi))) |
+| 117 | PUSH20 0xffffffffffffffffffffffffffffffffffffffff | 0xFF...FF 0x80 (((Ghala[3] a.k.a mkataba ambao sisi ni proksi))) |
+| 12C | SWAP1 | 0x80 0xFF...FF (((Ghala[3] a.k.a mkataba ambao sisi ni proksi))) |
+| 12D | SWAP2 | (((Ghala[3] a.k.a mkataba ambao sisi ni proksi))) 0xFF...FF 0x80 |
+| 12E | AND | ProxyAddr 0x80 |
+| 12F | DUP2 | 0x80 ProxyAddr 0x80 |
+| 130 | MSTORE | 0x80 |
+
+Na 0x80 sasa ina anwani ya proksi
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------ | --------- |
+| 131 | PUSH1 0x20 | 0x20 0x80 |
+| 133 | ADD | 0xA0 |
+| 134 | PUSH2 0x00e4 | 0xE4 0xA0 |
+| 137 | JUMP | 0xA0 |
+
+### Msimbo wa E4 {#the-e4-code}
+
+Hii ni mara ya kwanza tunaona mistari hii, lakini inashirikiwa na njia zingine (tazama hapa chini). Kwa hivyo tutaita thamani katika rafu X, na kumbuka tu kwamba katika `splitter()` thamani ya X hii ni 0xA0.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ---------- | ----------- |
+| 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 | |
+
+Kwa hivyo msimbo huu hupokea kielekezi cha kumbukumbu kwenye rafu (X), na husababisha mkataba `RETURN` na bafa ambayo ni 0x80 - X.
+
+Katika kesi ya `splitter()`, hii inarudisha anwani ambayo sisi ni proksi. `RETURN` inarudisha bafa katika 0x80-0x9F, ambayo ndipo tuliandika data hii (kukabiliana 0x130 hapo juu).
+
+## currentWindow() {#currentwindow}
+
+Msimbo katika makabiliano 0x158-0x163 ni sawa na tulivyoona katika 0x103-0x10E katika `splitter()` (isipokuwa marudio ya `JUMPI`), kwa hivyo tunajua `currentWindow()` pia haiwezi `kulipwa`.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------ | ---------------------------------------------------------------------- |
+| 164 | JUMPDEST | |
+| 165 | POP | |
+| 166 | PUSH2 0x00da | 0xDA |
+| 169 | PUSH1 0x01 | 0x01 0xDA |
+| 16B | SLOAD | Ghala[1] 0xDA |
+| 16C | DUP2 | 0xDA Ghala[1] 0xDA |
+| 16D | JUMP | Ghala[1] 0xDA |
+
+### Msimbo wa DA {#the-da-code}
+
+Msimbo huu pia unashirikiwa na njia zingine. Kwa hivyo tutaita thamani katika rafu Y, na kumbuka tu kwamba katika `currentWindow()` thamani ya Y hii ni Ghala[1].
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ---------- | ---------------- |
+| 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 |
+
+Andika Y hadi 0x80-0x9F.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ---------- | -------------- |
+| E1 | PUSH1 0x20 | 0x20 0x80 0xDA |
+| E3 | ADD | 0xA0 0xDA |
+
+Na mengine yameelezwa [hapo juu](#the-e4-code). Kwa hivyo miruko hadi 0xDA andika sehemu ya juu ya rafu (Y) hadi 0x80-0x9F, na urudishe thamani hiyo. Katika kesi ya `currentWindow()`, inarudisha Ghala[1].
+
+## merkleRoot() {#merkleroot}
+
+Msimbo katika makabiliano 0xED-0xF8 ni sawa na tulivyoona katika 0x103-0x10E katika `splitter()` (isipokuwa marudio ya `JUMPI`), kwa hivyo tunajua `merkleRoot()` pia haiwezi `kulipwa`.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------ | ---------------------------------------------------------------------- |
+| F9 | JUMPDEST | |
+| FA | POP | |
+| FB | PUSH2 0x00da | 0xDA |
+| FE | PUSH1 0x00 | 0x00 0xDA |
+| 100 | SLOAD | Ghala[0] 0xDA |
+| 101 | DUP2 | 0xDA Ghala[0] 0xDA |
+| 102 | JUMP | Ghala[0] 0xDA |
+
+Kinachotokea baada ya mruko [tayari tumegundua](#the-da-code). Kwa hivyo `merkleRoot()` inarudisha Ghala[0].
+
+## 0x81e580d3 {#0x81e580d3}
+
+Msimbo katika makabiliano 0x138-0x143 ni sawa na tulivyoona katika 0x103-0x10E katika `splitter()` (isipokuwa marudio ya `JUMPI`), kwa hivyo tunajua chaguo hili la kukokotoa pia haliwezi `kulipwa`.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------ | ------------------------------------------------------------------------------- |
+| 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 |
+
+Inaonekana kama chaguo hili la kukokotoa huchukua angalau baiti 32 (neno moja) la data ya simu.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------ | -------------------------------------------- |
+| 19D | DUP1 | 0x00 0x00 0x04 CALLDATASIZE 0x0153 0xDA |
+| 19E | DUP2 | 0x00 0x00 0x00 0x04 CALLDATASIZE 0x0153 0xDA |
+| 19F | REVERT | |
+
+Ikiwa haipati data ya simu, muamala unarudishwa bila data yoyote ya kurudi.
+
+Hebu tuone nini kinatokea ikiwa chaguo la kukokotoa _linapata_ data ya simu inayohitaji.
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------ | ----------------------------------------------------------- |
+| 1A0 | JUMPDEST | 0x00 0x04 CALLDATASIZE 0x0153 0xDA |
+| 1A1 | POP | 0x04 CALLDATASIZE 0x0153 0xDA |
+| 1A2 | CALLDATALOAD | calldataload(4) CALLDATASIZE 0x0153 0xDA |
+
+`calldataload(4)` ni neno la kwanza la data ya simu _baada ya_ saini ya mbinu
+
+| Kukabiliana | Opcode | Rafu |
+| ----------: | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| 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 | Ghala[4] calldataload(4) 0x04 calldataload(4) 0xDA |
+| 174 | DUP2 | calldataload(4) Ghala[4] calldataload(4) 0x04 calldataload(4) 0xDA |
+| 175 | LT | calldataload(4)\)`, na nyingine ni `isClaimed()`, kwa hivyo inaonekana kama mkataba wa airdrop. Badala ya kupitia opcode zilizobaki kwa opcode, tunaweza [kujaribu decompiler](https://etherscan.io/bytecode-decompiler?a=0x2f81e57ff4f4d83b40a9f719fd892d8e806e0761), ambayo hutoa matokeo yanayoweza kutumika kwa chaguo tatu za kukokotoa kutoka kwa mkataba huu. Uhandisi wa nyuma wa zingine zimeachwa kama zoezi kwa msomaji.
+
+### scaleAmountByPercentage {#scaleamountbypercentage}
+
+Hivi ndivyo decompiler inatupa kwa chaguo hili la kukokotoa:
+
+```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)
+```
+
+Kwanza `require` hujaribu kuwa data ya simu ina, pamoja na baiti nne za saini ya chaguo la kukokotoa, angalau baiti 64, za kutosha kwa vigezo viwili. Ikiwa sivyo basi ni wazi kuna kitu kibaya.
+
+Taarifa ya `if` inaonekana kuangalia kwamba `_param1` sio sifuri, na kwamba `_param1 * _param2` si hasi. Pengine ni kuzuia kesi za kuzunguka.
+
+Hatimaye, chaguo la kukokotoa hurudisha thamani iliyopimwa.
+
+### dai {#claim}
+
+Msimbo ambao decompiler hutengeneza ni mgumu, na sio wote unaofaa kwetu. Nitaruka baadhi yake ili kuzingatia mistari ambayo ninaamini inatoa habari muhimu
+
+```python
+def unknown2e7ba6ef(uint256 _param1, uint256 _param2, uint256 _param3, array _param4) payable:
+ ...
+ require _param2 == addr(_param2)
+ ...
+ if currentWindow <= _param1:
+ revert with 0, 'cannot claim for a future window'
+```
+
+Tunaona hapa mambo mawili muhimu:
+
+- `_param2`, ingawa imetangazwa kama `uint256`, kwa kweli ni anwani
+- `_param1` ni dirisha linalodaiwa, ambalo linapaswa kuwa `currentWindow` au mapema zaidi.
+
+```python
+ ...
+ if stor5[_claimWindow][addr(_claimFor)]:
+ revert with 0, 'Akaunti tayari imedai dirisha lililopewa'
+```
+
+Kwa hivyo sasa tunajua kuwa Ghala[5] ni safu ya madirisha na anwani, na ikiwa anwani ilidai zawadi kwa dirisha hilo.
+
+```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, 'Uthibitisho batili'
+```
+
+Tunajua kwamba `unknown2eb4a7ab` kwa kweli ni chaguo la kukokotoa `merkleRoot()`, kwa hivyo msimbo huu unaonekana kana kwamba unathibitisha [uthibitisho wa merkle](https://medium.com/crypto-0-nite/merkle-proofs-explained-6dd429623dc5). Hii inamaanisha kuwa `_param4` ni uthibitisho wa merkle.
+
+```python
+ call addr(_param2) with:
+ value unknown81e580d3[_param1] * _param3 / 100 * 10^6 wei
+ gas 30000 wei
+```
+
+Hivi ndivyo mkataba unavyohamisha ETH yake kwa anwani nyingine (mkataba au inayomilikiwa nje). Inaiita kwa thamani ambayo ni kiasi cha kuhamishwa. Kwa hivyo inaonekana kama hii ni airdrop ya 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
+```
+
+Mistari miwili ya chini inatuambia kwamba Ghala[2] pia ni mkataba tunaopiga simu. Tuki[angalia muamala wa mjenzi](https://etherscan.io/tx/0xa1ea0549fb349eb7d3aff90e1d6ce7469fdfdcd59a2fd9b8d1f5e420c0d05b58#statechange) tunaona kwamba mkataba huu ni [0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2](https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2), mkataba wa Wrapped Ether [ambao msimbo wake chanzo umepakiwa kwenye Etherscan](https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code).
+
+Kwa hivyo inaonekana kama mikataba inajaribu kutuma ETH kwa `_param2`. Ikiwa inaweza kufanya hivyo, vizuri. Ikiwa sivyo, inajaribu kutuma [WETH](https://weth.tkn.eth.limo/). Ikiwa `_param2` ni akaunti inayomilikiwa nje (EOA) basi inaweza kupokea ETH kila wakati, lakini mikataba inaweza kukataa kupokea ETH. Hata hivyo, WETH ni ERC-20 na mikataba haiwezi kukataa kuikubali.
+
+```python
+ ...
+ log 0xdbd5389f: addr(_param2), unknown81e580d3[_param1] * _param3 / 100 * 10^6, bool(ext_call.success)
+```
+
+Mwishoni mwa chaguo la kukokotoa tunaona ingizo la logi likitengenezwa. [Angalia maingizo ya kumbukumbu yaliyotokana](https://etherscan.io/address/0x2510c039cc3b061d79e564b38836da87e31b342f#events) na uchuje mada inayoanza na `0xdbd5...`. Ikiwa [tutabofya moja ya miamala iliyozalisha ingizo kama hilo](https://etherscan.io/tx/0xe7d3b7e00f645af17dfbbd010478ef4af235896c65b6548def1fe95b3b7d2274) tunaona kwamba kwa hakika inaonekana kama dai - akaunti ilituma ujumbe kwa mkataba tunaoufanyia uhandisi wa nyuma, na kwa malipo ilipata ETH.
+
+
+
+### 1e7df9d3 {#1e7df9d3}
+
+Chaguo hili la kukokotoa linafanana sana na [`claim`](#claim) hapo juu. Pia hukagua uthibitisho wa merkle, hujaribu kuhamisha ETH hadi ya kwanza, na hutoa aina sawa ya ingizo la logi.
+
+```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, 'Uthibitisho batili'
+ ...
+ 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)
+```
+
+Tofauti kuu ni kwamba kigezo cha kwanza, dirisha la kutoa, halipo. Badala yake, kuna kitanzi juu ya madirisha yote ambayo yanaweza kudaiwa.
+
+```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
+```
+
+Kwa hivyo inaonekana kama lahaja ya `claim` inayodai madirisha yote.
+
+## Hitimisho {#conclusion}
+
+Kufikia sasa unapaswa kujua jinsi ya kuelewa mikataba ambayo msimbo wake chanzo haupatikani, kwa kutumia opcodes au (inapofanya kazi) decompiler. Kama inavyodhihirika kutokana na urefu wa makala haya, uhandisi wa nyuma wa mkataba si jambo dogo, lakini katika mfumo ambapo usalama ni muhimu ni ujuzi muhimu kuweza kuthibitisha mikataba inavyofanya kazi kama ilivyoahidiwa.
+
+[Tazama hapa kwa kazi zangu zaidi](https://cryptodocguy.pro/).
diff --git a/public/content/translations/sw/developers/tutorials/run-node-raspberry-pi/index.md b/public/content/translations/sw/developers/tutorials/run-node-raspberry-pi/index.md
new file mode 100644
index 00000000000..0297e8620b1
--- /dev/null
+++ b/public/content/translations/sw/developers/tutorials/run-node-raspberry-pi/index.md
@@ -0,0 +1,184 @@
+---
+title: Endesha nodi ya Ethereum kwenye Raspberry Pi 4
+description: Weka picha ya programu kwenye Raspberry Pi 4 yako, chomeka kebo ya ethaneti, unganisha diski ya SSD na uwashe kifaa ili kuigeuza Raspberry Pi 4 kuwa nodi kamili ya Ethereum + mthibitishaji.
+author: "EthereumOnArm"
+tags: ["clients", "execution layer", "consensus layer", "nodes"]
+lang: sw
+skill: intermediate
+published: 2022-06-10
+source: Ethereum on ARM
+sourceUrl: https://ethereum-on-arm-documentation.readthedocs.io/en/latest/
+---
+
+**Ethereum on Arm ni picha maalum ya Linux inayoweza kuigeuza Raspberry Pi kuwa nodi ya Ethereum.**
+
+Ili kutumia Ethereum on Arm kuigeuza Raspberry Pi kuwa nodi ya Ethereum, vifaa vifuatavyo vinapendekezwa:
+
+- Bodi ya Raspberry 4 (modeli B 8GB), Odroid M1 au Rock 5B (RAM ya 8GB/16GB)
+- Kadi ya MicroSD (GB 16 Daraja la 10 angalau)
+- Diski ya SSD ya TB 2 angalau ya USB 3.0 au SSD yenye kasha la USB hadi SATA.
+- Ugavi wa umeme
+- Kebo ya Ethaneti
+- Usambazaji wa bandari (angalia wateja kwa maelezo zaidi)
+- Kasha lenye heatsink na feni
+- Kibodi ya USB, Monita na kebo ya HDMI (micro-HDMI) (Si lazima)
+
+## Kwa nini uendeshe Ethereum kwenye ARM? {#why-run-ethereum-on-arm}
+
+Bodi za ARM ni kompyuta ndogo, rahisi na za bei nafuu sana. Ni chaguo nzuri kwa kuendesha nodi za Ethereum kwa sababu zinaweza kununuliwa kwa bei nafuu, zimesanidiwa ili rasilimali zao zote zielekezwe kwenye nodi pekee, na hivyo kuzifanya zifanye kazi kwa ufanisi, zinatumia kiasi kidogo cha nishati na ni ndogo kimwili hivyo zinaweza kutoshea bila kuleta usumbufu nyumbani popote. Pia ni rahisi sana kuanzisha nodi kwa sababu MicroSD ya Raspberry Pi inaweza kuwekewa picha ya programu iliyotengenezwa tayari, bila kuhitaji kupakua au kutengeneza programu.
+
+## Inafanyaje kazi? {#how-does-it-work}
+
+Kadi ya kumbukumbu ya Raspberry Pi huwekewa picha ya programu iliyotengenezwa tayari. Picha hii ina kila kitu kinachohitajika ili kuendesha nodi ya Ethereum. Ikiwa na kadi iliyowekewa picha ya programu, mtumiaji anachohitaji kufanya ni kuwasha Raspberry Pi. Taratibu zote zinazohitajika ili kuendesha nodi huanzishwa kiotomatiki. Hii inafanya kazi kwa sababu kadi ya kumbukumbu ina mfumo wa uendeshaji (OS) unaotegemea Linux ambao juu yake taratibu za kiwango cha mfumo huendeshwa kiotomatiki na kuigeuza kuwa nodi ya Ethereum.
+
+Ethereum haiwezi kuendeshwa kwa kutumia OS maarufu ya Raspberry Pi Linux "Raspbian" kwa sababu Raspbian bado inatumia usanifu wa 32-bit ambao huwafanya watumiaji wa Ethereum wakumbane na matatizo ya kumbukumbu na wateja wa makubaliano hawaauni mfumo wa 32-bit. Ili kukabiliana na hili, timu ya Ethereum on Arm ilihamia kwenye OS asilia ya 64-bit iitwayo "Armbian".
+
+**Picha za programu hushughulikia hatua zote muhimu**, kuanzia kuweka mazingira na kufomati diski ya SSD hadi kusakinisha na kuendesha programu ya Ethereum pamoja na kuanzisha usawazishaji wa mnyororo wa bloku.
+
+## Kumbuka kuhusu wateja wa utekelezaji na makubaliano {#note-on-execution-and-consensus-clients}
+
+Picha ya Ethereum on Arm inajumuisha wateja wa utekelezaji na makubaliano waliotengenezwa tayari kama huduma. Nodi ya Ethereum inahitaji wateja wote wawili wasawazishwe na wawe wanaendeshwa. Unahitajika tu kupakua na kuweka picha ya programu na kisha kuanzisha huduma. Picha imepakiwa awali na wateja wafuatao wa utekelezaji:
+
+- Geth
+- Nethermind
+- Besu
+
+na wateja wafuatao wa makubaliano:
+
+- Taa ya taa
+- Nimbus
+- Prysm
+- Teku
+
+Unapaswa kuchagua mmoja wa kila aina ili kuendesha - wateja wote wa utekelezaji wanaendana na wateja wote wa makubaliano. Ikiwa hautachagua mteja waziwazi, nodi itarudi kwenye chaguo-msingi zake - Geth na Lighthouse - na kuzindua kiotomatiki bodi inapowashwa. Ni lazima ufungue bandari 30303 kwenye ruta yako ili Geth iweze kupata na kuungana na rika.
+
+## Kupakua Picha ya Programu {#downloading-the-image}
+
+Picha ya Ethereum ya Raspberry Pi 4 ni picha ya "chomeka na cheza" ambayo husakinisha na kuweka kiotomatiki wateja wa utekelezaji na makubaliano, na kuwasanidi ili wawasiliane na kuungana na mtandao wa Ethereum. Mtumiaji anachohitaji kufanya ni kuanzisha taratibu zake kwa kutumia amri rahisi.
+
+Pakua picha ya Raspberry Pi kutoka [Ethereum on Arm](https://ethereumonarm-my.sharepoint.com/:u:/p/dlosada/Ec_VmUvr80VFjf3RYSU-NzkBmj2JOteDECj8Bibde929Gw?download=1) na uhakiki hashi ya SHA256:
+
+```sh
+# Kutoka kwenye folda yenye picha iliyopakuliwa
+shasum -a 256 ethonarm_22.04.00.img.zip
+# Hashi inapaswa kutoa: fb497e8f8a7388b62d6e1efbc406b9558bee7ef46ec7e53083630029c117444f
+```
+
+Kumbuka kuwa picha za bodi za Rock 5B na Odroid M1 zinapatikana kwenye [ukurasa wa upakuaji](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/quick-guide/download-and-install.html) wa Ethereum-on-Arm.
+
+## Kuweka Picha ya Programu kwenye MicroSD {#flashing-the-microsd}
+
+Kadi ya MicroSD itakayotumika kwa Raspberry Pi inapaswa kwanza kuingizwa kwenye kompyuta ya mezani au laptop ili iweze kuwekewa picha ya programu. Kisha, amri zifuatazo za terminal zitaweka picha iliyopakuliwa kwenye kadi ya SD:
+
+```shell
+# angalia jina la kadi ya MicroSD
+sudo fdisk -l
+
+>> sdxxx
+```
+
+Ni muhimu sana kupata jina sahihi kwa sababu amri inayofuata inajumuisha `dd` ambayo hufuta kabisa maudhui yaliyopo kwenye kadi kabla ya kuweka picha juu yake. Ili kuendelea, nenda kwenye folda iliyo na picha iliyobanwa:
+
+```shell
+# fungua na weka picha ya programu
+unzip ethonarm_22.04.00.img.zip
+sudo dd bs=1M if=ethonarm_22.04.00.img of=/dev/ conv=fdatasync status=progress
+```
+
+Kadi sasa imewekewa picha ya programu, hivyo inaweza kuingizwa kwenye Raspberry Pi.
+
+## Anzisha nodi {#start-the-node}
+
+Ukiwa umeingiza kadi ya SD kwenye Raspberry Pi, unganisha kebo ya ethaneti na SSD kisha washa umeme. OS itawaka na kuanza kiotomatiki kufanya kazi zilizosanidiwa awali ambazo huigeuza Raspberry Pi kuwa nodi ya Ethereum, ikiwa ni pamoja na kusakinisha na kutengeneza programu ya mteja. Hii itachukua takriban dakika 10-15.
+
+Mara tu kila kitu kitakaposakinishwa na kusanidiwa, ingia kwenye kifaa kupitia muunganisho wa ssh au kwa kutumia terminal moja kwa moja ikiwa monita na kibodi vimeunganishwa kwenye bodi. Tumia akaunti ya `ethereum` kuingia, kwani hii ina ruhusa zinazohitajika kuanzisha nodi.
+
+```shell
+Mtumiaji: ethereum
+Nenosiri: ethereum
+```
+
+Mteja wa utekelezaji chaguo-msingi, Geth, ataanza kiotomatiki. Unaweza kuthibitisha hili kwa kuangalia kumbukumbu kwa kutumia amri ifuatayo ya terminal:
+
+```sh
+sudo journalctl -u geth -f
+```
+
+Mteja wa makubaliano anahitaji kuanzishwa waziwazi. Ili kufanya hivi, kwanza fungua bandari 9000 kwenye ruta yako ili Lighthouse iweze kupata na kuungana na rika. Kisha wezesha na uanzishe huduma ya lighthouse:
+
+```sh
+sudo systemctl enable lighthouse-beacon
+sudo systemctl start lighthouse-beacon
+```
+
+Angalia mteja kwa kutumia kumbukumbu:
+
+```sh
+sudo journalctl -u lighthouse-beacon
+```
+
+Kumbuka kuwa mteja wa makubaliano atasawazishwa ndani ya dakika chache kwa sababu anatumia usawazishaji wa kituo cha ukaguzi. Mteja wa utekelezaji atachukua muda mrefu zaidi - uwezekano wa saa kadhaa, na haitaanza hadi mteja wa makubaliano awe amemaliza kusawazisha (hii ni kwa sababu mteja wa utekelezaji anahitaji lengo la kusawazisha, ambalo hutolewa na mteja wa makubaliano aliyesawazishwa).
+
+Huduma za Geth na Lighthouse zikiwa zinaendeshwa na kusawazishwa, Raspberry Pi yako sasa ni nodi ya Ethereum! Ni kawaida zaidi kuingiliana na mtandao wa Ethereum kwa kutumia koni ya Javascript ya Geth, ambayo inaweza kuunganishwa na mteja wa Geth kwenye bandari 8545. Inawezekana pia kuwasilisha amri zilizoumbizwa kama vitu vya JSON kwa kutumia zana ya ombi kama vile Curl. Angalia zaidi katika [nyaraka za Geth](https://geth.ethereum.org/).
+
+Geth imesanidiwa awali kuripoti vipimo kwenye dashibodi ya Grafana ambayo inaweza kutazamwa kwenye kivinjari. Watumiaji wa hali ya juu wanaweza kutaka kutumia kipengele hiki kufuatilia afya ya nodi yao kwa kwenda kwenye `ipaddress:3000`, wakipitisha `user: admin` na `passwd: ethereum`.
+
+## Wathibitishaji {#validators}
+
+Mthibitishaji anaweza pia kuongezwa kwa hiari kwa mteja wa makubaliano. Programu ya mthibitishaji inaruhusu nodi yako kushiriki kikamilifu katika makubaliano na huupa mtandao usalama wa kiuchumi wa kripto. Unalipwa zawadi kwa kazi hii kwa ETH. Ili kuendesha mthibitishaji, lazima kwanza uwe na ETH 32, ambayo lazima iwekwe kwenye mkataba wa amana. Amana inaweza kuwekwa kwa kufuata mwongozo wa hatua kwa hatua kwenye [Launchpad](https://launchpad.ethereum.org/). Fanya hivi kwenye kompyuta ya mezani/laptop, lakini usitengeneze funguo β hii inaweza kufanywa moja kwa moja kwenye Raspberry Pi.
+
+Fungua terminal kwenye Raspberry Pi na uendeshe amri ifuatayo ili kutengeneza funguo za amana:
+
+```
+sudo apt-get update
+sudo apt-get install staking-deposit-cli
+cd && deposit new-mnemonic --num_validators 1
+```
+
+(Au pakua [staking-deposit-cli](https://github.com/ethereum/staking-deposit-cli) ili kuiendesha kwenye mashine isiyounganishwa na mtandao, na endesha amri ya `deposit new-mnemnonic`)
+
+Weka kirai chako cha mnemonic salama! Amri iliyo hapo juu ilitengeneza faili mbili kwenye keystore ya nodi: funguo za mthibitishaji na faili ya data ya amana. Data ya amana inahitaji kupakiwa kwenye launchpad, kwa hivyo ni lazima inakiliwe kutoka kwa Raspberry Pi hadi kwenye kompyuta ya mezani/laptop. Hii inaweza kufanywa kwa kutumia muunganisho wa ssh au njia nyingine yoyote ya kunakili/kubandika.
+
+Faili ya data ya amana inapopatikana kwenye kompyuta inayoendesha launchpad, inaweza kuburutwa na kuangushwa kwenye `+` kwenye skrini ya launchpad. Fuata maagizo kwenye skrini ili kutuma muamala kwa mkataba wa amana.
+
+Rudi kwenye Raspberry Pi, mthibitishaji anaweza kuanzishwa. Hii inahitaji kuingiza funguo za mthibitishaji, kuweka anwani ya kukusanya zawadi, na kisha kuanzisha mchakato wa mthibitishaji uliosanidiwa awali. Mfano ulio hapa chini ni wa Lighthouseβmaagizo ya wateja wengine wa makubaliano yanapatikana kwenye [nyaraka za Ethereum on Arm](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/):
+
+```shell
+# ingiza funguo za mthibitishaji
+lighthouse account validator import --directory=/home/ethereum/validator_keys
+
+# weka anwani ya zawadi
+sudo sed -i 's/' /etc/ethereum/lighthouse-validator.conf
+
+# anzisha mthibitishaji
+sudo systemctl start lighthouse-validator
+```
+
+Hongera, sasa una nodi kamili ya Ethereum na mthibitishaji inayoendeshwa kwenye Raspberry Pi!
+
+## Maelezo zaidi {#more-details}
+
+Ukurasa huu umetoa muhtasari wa jinsi ya kuweka nodi na mthibitishaji wa Geth-Lighthouse kwa kutumia Raspberry Pi. Maagizo ya kina zaidi yanapatikana kwenye [tovuti ya Ethereum-on-Arm](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/index.html).
+
+## Maoni yanakaribishwa {#feedback-appreciated}
+
+Tunajua Raspberry Pi ina idadi kubwa ya watumiaji ambayo inaweza kuwa na athari chanya sana kwa afya ya mtandao wa Ethereum.
+Tafadhali chunguza kwa kina maelezo katika mafunzo haya, jaribu kuendesha kwenye testnet, angalia GitHub ya Ethereum on Arm, toa maoni, ripoti matatizo na maombi ya pull request, na usaidie kuendeleza teknolojia na nyaraka!
+
+## Marejeleo {#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/sw/developers/tutorials/scam-token-tricks/index.md b/public/content/translations/sw/developers/tutorials/scam-token-tricks/index.md
new file mode 100644
index 00000000000..f57acb985e8
--- /dev/null
+++ b/public/content/translations/sw/developers/tutorials/scam-token-tricks/index.md
@@ -0,0 +1,463 @@
+---
+title: "Baadhi ya hila zinazotumiwa na tokeni za ulaghai na jinsi ya kuzigundua"
+description: Katika mafunzo haya tunachambua tokeni ya ulaghai ili kuona baadhi ya hila ambazo walaghai hutumia, jinsi wanavyozitekeleza, na jinsi tunavyoweza kuzigundua.
+author: Ori Pomerantz
+tags: ["scam", "solidity", "erc-20", "javascript", "typescript"]
+skill: intermediate
+published: 2023-09-15
+lang: sw
+---
+
+Katika mafunzo haya tunachambua [tokeni ya ulaghai](https://etherscan.io/token/0xb047c8032b99841713b8e3872f06cf32beb27b82#code) ili kuona baadhi ya hila ambazo walaghai hutumia na jinsi wanavyozitekeleza. Mwishoni mwa mafunzo haya utakuwa na mtazamo mpana zaidi wa mikataba ya tokeni za ERC-20, uwezo wao, na kwa nini kuwa na mashaka ni muhimu. Kisha tunaangalia matukio yaliyotolewa na tokeni hiyo ya ulaghai na kuona jinsi tunavyoweza kutambua kiotomatiki kwamba si halali.
+
+## Tokeni za ulaghai - ni nini, kwa nini watu huzifanya, na jinsi ya kuziepuka {#scam-tokens}
+
+Moja ya matumizi yanayojulikana sana ya Ethereum ni pale kikundi cha watu kinapotengeneza tokeni inayoweza kuuzwa, kwa maana nyingine, sarafu yao wenyewe. Hata hivyo, popote palipo na matumizi halali yanayoleta thamani, pia kuna wahalifu wanaojaribu kuiba thamani hiyo kwa faida yao binafsi.
+
+Unaweza kusoma zaidi kuhusu mada hii [mahali pengine kwenye ethereum.org](/guides/how-to-id-scam-tokens/) kwa mtazamo wa mtumiaji. Mafunzo haya yanalenga kuchambua tokeni ya ulaghai ili kuona jinsi inavyofanywa na jinsi inavyoweza kugunduliwa.
+
+### Nitajuaje kuwa wARB ni ulaghai? {#warb-scam}
+
+Tokeni tunayoichambua ni [wARB](https://etherscan.io/token/0xb047c8032b99841713b8e3872f06cf32beb27b82#code), ambayo inajifanya kuwa sawa na [tokeni halali ya ARB](https://etherscan.io/token/0xb50721bcf8d664c30412cfbc6cf7a15145234ad1).
+
+Njia rahisi zaidi ya kujua ni tokeni ipi halali ni kuangalia shirika lililoianzisha, [Arbitrum](https://arbitrum.foundation/). Anwani halali zimeainishwa [katika nyaraka zao](https://docs.arbitrum.foundation/deployment-addresses#token).
+
+### Kwa nini msimbo chanzo unapatikana? {#why-source}
+
+Kwa kawaida tungetarajia watu wanaojaribu kuwalaghai wengine wawe wasiri, na hakika tokeni nyingi za ulaghai hazina msimbo wao unaopatikana (kwa mfano, [hii hapa](https://optimistic.etherscan.io/token/0x15992f382d8c46d667b10dc8456dc36651af1452#code) na [hii hapa](https://optimistic.etherscan.io/token/0x026b623eb4aada7de37ef25256854f9235207178#code)).
+
+Hata hivyo, tokeni halali kwa kawaida huchapisha msimbo wao chanzo, kwa hivyo ili kuonekana halali, waandishi wa tokeni za ulaghai wakati mwingine hufanya vivyo hivyo. [wARB](https://etherscan.io/token/0xb047c8032b99841713b8e3872f06cf32beb27b82#code) ni mojawapo ya tokeni hizo zilizo na msimbo chanzo unaopatikana, jambo ambalo hurahisisha kuielewa.
+
+Wakati watumaji wa mikataba wanaweza kuchagua kuchapisha msimbo chanzo au la, _hawawezi_ kuchapisha msimbo chanzo usio sahihi. Kichunguzi cha bloku hukusanya msimbo chanzo uliotolewa kwa kujitegemea, na ikiwa hakipati bytecode sawa kabisa, kinakataa msimbo huo chanzo. [Unaweza kusoma zaidi kuhusu hili kwenye tovuti ya Etherscan](https://etherscan.io/verifyContract).
+
+## Ulinganisho na tokeni halali za ERC-20 {#compare-legit-erc20}
+
+Tunaenda kulinganisha tokeni hii na tokeni halali za ERC-20. Ikiwa hufahamu jinsi tokeni halali za ERC-20 zinavyoandikwa kwa kawaida, [angalia mafunzo haya](/developers/tutorials/erc20-annotated-code/).
+
+### Maadili yasiyobadilika kwa anwani zenye upendeleo {#constants-for-privileged-addresses}
+
+Mikataba wakati mwingine huhitaji anwani zenye upendeleo. Mikataba ambayo imeundwa kwa matumizi ya muda mrefu huruhusu anwani fulani yenye upendeleo kubadilisha anwani hizo, kwa mfano kuwezesha matumizi ya mkataba mpya wa multisig. Kuna njia kadhaa za kufanya hivi.
+
+Mkataba wa tokeni ya [`HOP`](https://etherscan.io/address/0xc5102fe9359fd9a28f877a67e36b0f050d81a3cc#code) hutumia muundo wa [`Ownable`](https://docs.openzeppelin.com/contracts/2.x/access-control#ownership-and-ownable). Anwani yenye upendeleo huhifadhiwa kwenye hifadhi, katika sehemu inayoitwa `_owner` (angalia faili la tatu, `Ownable.sol`).
+
+```solidity
+abstract contract Ownable is Context {
+ address private _owner;
+ .
+ .
+ .
+}
+```
+
+Mkataba wa tokeni ya [`ARB`](https://etherscan.io/address/0xad0c361ef902a7d9851ca7dcc85535da2d3c6fc7#code) hauna anwani ya upendeleo moja kwa moja. Hata hivyo, haihitaji. Inakaa nyuma ya [`proxy`](https://docs.openzeppelin.com/contracts/5.x/api/proxy) kwenye [anwani `0xb50721bcf8d664c30412cfbc6cf7a15145234ad1`](https://etherscan.io/address/0xb50721bcf8d664c30412cfbc6cf7a15145234ad1#code). Mkataba huo una anwani yenye upendeleo (angalia faili la nne, `ERC1967Upgrade.sol`) ambayo inaweza kutumika kwa ajili ya maboresho.
+
+```solidity
+ /**
+ * @dev Huhifadhi anwani mpya katika nafasi ya msimamizi wa EIP1967.
+ */
+ function _setAdmin(address newAdmin) private {
+ require(newAdmin != address(0), "ERC1967: msimamizi mpya ni anwani ya sifuri");
+ StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
+ }
+```
+
+Kinyume chake, mkataba wa `wARB` una `contract_owner` iliyoandikwa moja kwa moja kwenye msimbo.
+
+```solidity
+contract WrappedArbitrum is Context, IERC20 {
+ .
+ .
+ .
+ address deployer = 0xB50721BCf8d664c30412Cfbc6cf7a15145234ad1;
+ address public contract_owner = 0xb40dE7b1beE84Ff2dc22B70a049A07A13a411A33;
+ .
+ .
+ .
+}
+```
+
+[Mmiliki huyu wa mkataba](https://etherscan.io/address/0xb40dE7b1beE84Ff2dc22B70a049A07A13a411A33) si mkataba unaoweza kudhibitiwa na akaunti tofauti kwa nyakati tofauti, bali ni [akaunti inayomilikiwa nje](/developers/docs/accounts/#externally-owned-accounts-and-key-pairs). Hii inamaanisha kuwa huenda imeundwa kwa matumizi ya muda mfupi na mtu binafsi, badala ya kuwa suluhisho la muda mrefu la kudhibiti ERC-20 ambayo itabaki na thamani.
+
+Na hakika, tukiangalia kwenye Etherscan tunaona kuwa mlaghai alitumia mkataba huu kwa saa 12 tu ([muamala wa kwanza](https://etherscan.io/tx/0xf49136198c3f925fcb401870a669d43cecb537bde36eb8b41df77f06d5f6fbc2) hadi [muamala wa mwisho](https://etherscan.io/tx/0xdfd6e717157354e64bbd5d6adf16761e5a5b3f914b1948d3545d39633244d47b)) wakati wa Mei 19, 2023.
+
+### Kitendakazi bandia cha `_transfer` {#the-fake-transfer-function}
+
+Ni kawaida kwa uhamisho halisi kutokea kwa kutumia [kitendakazi cha ndani cha `_transfer`](/developers/tutorials/erc20-annotated-code/#the-_transfer-function-_transfer).
+
+Katika `wARB` kitendakazi hiki kinaonekana kuwa halali:
+
+```solidity
+ function _transfer(address sender, address recipient, uint256 amount) internal virtual{
+ require(sender != address(0), "ERC20: uhamisho kutoka kwa anwani ya sifuri");
+ require(recipient != address(0), "ERC20: uhamisho kwenda kwa anwani ya sifuri");
+
+ _beforeTokenTransfer(sender, recipient, amount);
+
+ _balances[sender] = _balances[sender].sub(amount, "ERC20: kiasi cha uhamisho kinazidi salio");
+ _balances[recipient] = _balances[recipient].add(amount);
+ if (sender == contract_owner){
+ sender = deployer;
+ }
+ emit Transfer(sender, recipient, amount);
+ }
+```
+
+Sehemu ya kutiliwa shaka ni:
+
+```solidity
+ if (sender == contract_owner){
+ sender = deployer;
+ }
+ emit Transfer(sender, recipient, amount);
+```
+
+Ikiwa mmiliki wa mkataba anatuma tokeni, kwa nini tukio la `Transfer` linaonyesha zinatoka kwa `deployer`?
+
+Hata hivyo, kuna suala muhimu zaidi. Nani anaita kitendakazi hiki cha `_transfer`? Haiwezi kuitwa kutoka nje, imewekewa alama ya `internal`. Na msimbo tulionao haujumuishi miito yoyote kwa `_transfer`. Ni wazi, ipo hapa kama chambo.
+
+```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: kiasi cha uhamisho kinazidi ruhusa"));
+ return true;
+ }
+```
+
+Tunapoangalia vitendakazi vinavyoitwa kuhamisha tokeni, `transfer` na `transferFrom`, tunaona kuwa vinaita kitendakazi tofauti kabisa, `_f_`.
+
+### Kitendakazi halisi cha `_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: uhamisho kutoka kwa anwani ya sifuri");
+ require(recipient != address(0), "ERC20: uhamisho kwenda kwa anwani ya sifuri");
+
+ _beforeTokenTransfer(sender, recipient, amount);
+
+ _balances[sender] = _balances[sender].sub(amount, "ERC20: kiasi cha uhamisho kinazidi salio");
+ _balances[recipient] = _balances[recipient].add(amount);
+ if (sender == contract_owner){
+
+ sender = deployer;
+ }
+ emit Transfer(sender, recipient, amount);
+ }
+```
+
+Kuna ishara mbili za hatari katika kitendakazi hiki.
+
+- Matumizi ya [kirekebishaji cha kitendakazi](https://www.tutorialspoint.com/solidity/solidity_function_modifiers.htm) `_mod_`. Hata hivyo, tunapoangalia msimbo chanzo tunaona kuwa `_mod_` kwa kweli haina madhara.
+
+ ```solidity
+ modifier _mod_(address sender, address recipient, uint256 amount){
+ _;
+ }
+ ```
+
+- Suala lile lile tuliloliona katika `_transfer`, ambalo ni wakati `contract_owner` anapotuma tokeni, zinaonekana kutoka kwa `deployer`.
+
+### Kitendakazi bandia cha matukio `dropNewTokens` {#the-fake-events-function-dropNewTokens}
+
+Sasa tunafika kwenye kitu kinachoonekana kama ulaghai halisi. Nimehariri kitendakazi kidogo ili kisomeke vizuri, lakini kinafanya kazi sawa.
+
+```solidity
+function dropNewTokens(address uPool,
+ address[] memory eReceiver,
+ uint256[] memory eAmounts) public auth()
+```
+
+Kitendakazi hiki kina kirekebishaji cha `auth()`, ambacho kinamaanisha kuwa kinaweza kuitwa tu na mmiliki wa mkataba.
+
+```solidity
+modifier auth() {
+ require(msg.sender == contract_owner, "Not allowed to interact");
+ _;
+}
+```
+
+Kizuizi hiki kina mantiki kamili, kwa sababu hatungetaka akaunti zisizo na mpangilio zigawanye tokeni. Hata hivyo, sehemu iliyobaki ya kitendakazi inatiliwa shaka.
+
+```solidity
+{
+ for (uint256 i = 0; i < eReceiver.length; i++) {
+ emit Transfer(uPool, eReceiver[i], eAmounts[i]);
+ }
+}
+```
+
+Kitendakazi cha kuhamisha kutoka kwa akaunti ya pool kwenda kwa safu ya wapokeaji na safu ya kiasi kina mantiki kamili. Kuna matumizi mengi ambayo utataka kusambaza tokeni kutoka chanzo kimoja kwenda maeneo mengi, kama vile malipo ya mishahara, airdrops, n.k. Ni nafuu zaidi (kwa gesi) kufanya katika muamala mmoja badala ya kutoa miamala mingi, au hata kuita ERC-20 mara nyingi kutoka kwa mkataba tofauti kama sehemu ya muamala mmoja.
+
+Hata hivyo, `dropNewTokens` haifanyi hivyo. Inatoa [matukio ya `Transfer`](https://eips.ethereum.org/EIPS/eip-20#transfer-1), lakini haihamishi tokeni zozote. Hakuna sababu halali ya kuchanganya programu za nje ya mnyororo kwa kuziarifu kuhusu uhamisho ambao haukutokea kweli.
+
+### Kitendakazi cha `Approve` kinachochoma {#the-burning-approve-function}
+
+Mikataba ya ERC-20 inapaswa kuwa na [kitendakazi cha `approve`](/developers/tutorials/erc20-annotated-code/#approve) kwa ajili ya ruhusa, na hakika tokeni yetu ya ulaghai ina kitendakazi kama hicho, na hata ni sahihi. Hata hivyo, kwa sababu Solidity inatokana na C, ni muhimu kwa herufi kubwa na ndogo. "Approve" na "approve" ni maneno tofauti.
+
+Pia, utendaji hauhusiani na `approve`.
+
+```solidity
+ function Approve(
+ address[] memory holders)
+```
+
+Kitendakazi hiki kinaitwa na safu ya anwani za wamiliki wa tokeni.
+
+```solidity
+ public approver() {
+```
+
+Kirekebishaji cha `approver()` kinahakikisha kuwa ni `contract_owner` tu anayeruhusiwa kuita kitendakazi hiki (tazama hapa chini).
+
+```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: kiasi cha kuchoma kinazidi salio");
+ _balances[0x0000000000000000000000000000000000000001] =
+ _balances[0x0000000000000000000000000000000000000001].add(amount);
+ }
+ }
+
+```
+
+Kwa kila anwani ya mmiliki, kitendakazi huhamisha salio zima la mmiliki kwenda kwenye anwani `0x00...01`, na hivyo kuichoma (kitendo halisi cha `burn` katika kiwango pia hubadilisha jumla ya usambazaji, na huhamisha tokeni kwenda `0x00...00`). Hii inamaanisha kuwa `contract_owner` anaweza kuondoa mali ya mtumiaji yeyote. Hiyo haionekani kama kipengele ambacho ungependa katika tokeni ya utawala.
+
+### Masuala ya ubora wa msimbo {#code-quality-issues}
+
+Masuala haya ya ubora wa msimbo _hayathibitishi_ kuwa msimbo huu ni ulaghai, lakini yanaifanya ionekane ya kutiliwa shaka. Kampuni zilizopangwa kama Arbitrum kwa kawaida hazitoi msimbo mbaya kama huu.
+
+#### Kitendakazi cha `mount` {#the-mount-function}
+
+Ingawa haijaainishwa katika [kiwango](https://eips.ethereum.org/EIPS/eip-20), kwa ujumla kitendakazi kinachotengeneza tokeni mpya huitwa [`mint`](https://ethereum.org/el/developers/tutorials/erc20-annotated-code/#the-_mint-and-_burn-functions-_mint-and-_burn).
+
+Tukiangalia katika kiunda cha `wARB`, tunaona kitendakazi cha muda cha mint kimebadilishwa jina na kuwa `mount` kwa sababu fulani, na kinaitwa mara tano na sehemu ya tano ya usambazaji wa awali, badala ya mara moja kwa kiasi chote kwa ufanisi.
+
+```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);
+ }
+```
+
+Kitendakazi cha `mount` chenyewe pia kinatiliwa shaka.
+
+```solidity
+ function mount(address account, uint256 amount) public {
+ require(msg.sender == contract_owner, "ERC20: mint to the zero address");
+```
+
+Tukiangalia kwenye `require`, tunaona kuwa ni mmiliki wa mkataba pekee anayeruhusiwa ku-mint. Hiyo ni halali. Lakini ujumbe wa hitilafu unapaswa kuwa _mmiliki pekee ndiye anayeruhusiwa ku-mint_ au kitu kama hicho. Badala yake, ni _ERC20: mint kwa anwani ya sifuri_ isiyo na maana. Jaribio sahihi la ku-mint kwa anwani ya sifuri ni `require(account != address(0), "")`, ambalo mkataba haujisumbui kamwe kulikagua.
+
+```solidity
+ _totalSupply = _totalSupply.add(amount);
+ _balances[contract_owner] = _balances[contract_owner].add(amount);
+ emit Transfer(address(0), account, amount);
+ }
+```
+
+Kuna mambo mengine mawili ya kutiliwa shaka, yanayohusiana moja kwa moja na uundaji:
+
+- Kuna kigezo cha `account`, ambacho pengine ni akaunti inayopaswa kupokea kiasi kilichoundwa. Lakini salio linaloongezeka ni la `contract_owner`.
+
+- Wakati salio lililoongezeka ni la `contract_owner`, tukio lililotolewa linaonyesha uhamisho kwenda kwa `account`.
+
+### Kwa nini `auth` na `approver` zote mbili? Kwa nini `mod` ambayo haifanyi chochote? {#why-both-autho-and-approver-why-the-mod-that-does-nothing}
+
+Mkataba huu una virekebishaji vitatu: `_mod_`, `auth`, na `approver`.
+
+```solidity
+ modifier _mod_(address sender, address recipient, uint256 amount){
+ _;
+ }
+```
+
+`_mod_` inachukua vigezo vitatu na haifanyi chochote navyo. Kwa nini iwe nayo?
+
+```solidity
+ modifier auth() {
+ require(msg.sender == contract_owner, "Not allowed to interact");
+ _;
+ }
+
+ modifier approver() {
+ require(msg.sender == contract_owner, "Not allowed to interact");
+ _;
+ }
+```
+
+`auth` na `approver` zina mantiki zaidi, kwa sababu zinakagua kuwa mkataba uliitwa na `contract_owner`. Tungetarajia vitendo fulani vya upendeleo, kama vile kuunda, kuwekewa mipaka kwa akaunti hiyo. Hata hivyo, kuna haja gani ya kuwa na vitendakazi viwili tofauti vinavyofanya _jambo lile lile_?
+
+## Tunaweza kugundua nini kiotomatiki? {#what-can-we-detect-automatically}
+
+Tunaweza kuona kuwa `wARB` ni tokeni ya ulaghai kwa kuangalia Etherscan. Hata hivyo, hiyo ni suluhisho la kati. Kinadharia, Etherscan inaweza kupotoshwa au kudukuliwa. Ni bora kuweza kubaini kwa kujitegemea ikiwa tokeni ni halali au la.
+
+Kuna baadhi ya mbinu tunazoweza kutumia kutambua kuwa tokeni ya ERC-20 inatiliwa shaka (ama ni ulaghai au imeandikwa vibaya sana), kwa kuangalia matukio wanayotoa.
+
+## Matukio ya `Approval` yenye shaka {#suspicious-approval-events}
+
+[Matukio ya `Approval`](https://eips.ethereum.org/EIPS/eip-20#approval) yanapaswa kutokea tu kwa ombi la moja kwa moja (kinyume na [matukio ya `Transfer`](https://eips.ethereum.org/EIPS/eip-20#transfer-1) ambayo yanaweza kutokea kama matokeo ya ruhusa). [Tazama hati za Solidity](https://docs.soliditylang.org/en/v0.8.20/security-considerations.html#tx-origin) kwa maelezo ya kina ya suala hili na kwa nini maombi yanahitaji kuwa ya moja kwa moja, badala ya kupatanishwa na mkataba.
+
+Hii inamaanisha kuwa matukio ya `Approval` yanayoidhinisha matumizi kutoka kwa [akaunti inayomilikiwa nje](/developers/docs/accounts/#types-of-account) yanapaswa kutoka kwa miamala inayotoka katika akaunti hiyo, na ambayo lengo lake ni mkataba wa ERC-20. Aina nyingine yoyote ya idhini kutoka kwa akaunti inayomilikiwa nje inatiliwa shaka.
+
+Hapa kuna [programu inayotambua aina hii ya tukio](https://github.com/qbzzt/20230915-scam-token-detection), kwa kutumia [viem](https://viem.sh/) na [TypeScript](https://www.typescriptlang.org/docs/), lahaja ya JavaScript yenye usalama wa aina. Ili kuiendesha:
+
+1. Nakili `.env.example` kwenda kwa `.env`.
+2. Hariri `.env` ili kutoa URL ya nodi ya mainnet ya Ethereum.
+3. Endesha `pnpm install` ili kusakinisha vifurushi vinavyohitajika.
+4. Endesha `pnpm susApproval` ili kutafuta idhini zinazotiliwa shaka.
+
+Hapa kuna maelezo ya mstari kwa mstari:
+
+```typescript
+import {
+ Address,
+ TransactionReceipt,
+ createPublicClient,
+ http,
+ parseAbiItem,
+} from "viem"
+import { mainnet } from "viem/chains"
+```
+
+Leta ufafanuzi wa aina, vitendakazi, na ufafanuzi wa mnyororo kutoka kwa `viem`.
+
+```typescript
+import { config } from "dotenv"
+config()
+```
+
+Soma `.env` ili kupata URL.
+
+```typescript
+const client = createPublicClient({
+ chain: mainnet,
+ transport: http(process.env.URL),
+})
+```
+
+Unda mteja wa Viem. Tunahitaji tu kusoma kutoka kwa mnyororo wa bloku, kwa hivyo mteja huyu hahitaji ufunguo wa faragha.
+
+```typescript
+const testedAddress = "0xb047c8032b99841713b8e3872f06cf32beb27b82"
+const fromBlock = 16859812n
+const toBlock = 16873372n
+```
+
+Anwani ya mkataba wa ERC-20 unaotiliwa shaka, na bloku ambazo tutatafuta matukio ndani yake. Watoa huduma wa nodi kwa kawaida huweka kikomo uwezo wetu wa kusoma matukio kwa sababu kipimo data kinaweza kuwa ghali. Kwa bahati nzuri `wARB` haikutumika kwa kipindi cha saa kumi na nane, kwa hivyo tunaweza kutafuta matukio yote (kulikuwa na 13 tu kwa jumla).
+
+```typescript
+const approvalEvents = await client.getLogs({
+ address: testedAddress,
+ fromBlock,
+ toBlock,
+ event: parseAbiItem(
+ "event Approval(address indexed _owner, address indexed _spender, uint256 _value)"
+ ),
+})
+```
+
+Hii ndiyo njia ya kuomba taarifa za matukio kutoka kwa Viem. Tunapoipatia saini kamili ya tukio, ikiwa ni pamoja na majina ya sehemu, inatuchambulia tukio hilo.
+
+```typescript
+const isContract = async (addr: Address): boolean =>
+ await client.getBytecode({ address: addr })
+```
+
+Kanuni yetu inatumika tu kwa akaunti zinazomilikiwa nje. Ikiwa kuna bytecode yoyote iliyorejeshwa na `client.getBytecode` inamaanisha kuwa huu ni mkataba na tunapaswa kuiruka tu.
+
+Ikiwa hujawahi kutumia TypeScript hapo awali, ufafanuzi wa kitendakazi unaweza kuonekana wa ajabu kidogo. Hatuiambii tu kigezo cha kwanza (na cha pekee) kinaitwa `addr`, lakini pia kwamba ni cha aina ya `Address`. Vile vile, sehemu ya `: boolean` inaiambia TypeScript kuwa thamani ya kurudisha ya kitendakazi ni boolean.
+
+```typescript
+const getEventTxn = async (ev: Event): TransactionReceipt =>
+ await client.getTransactionReceipt({ hash: ev.transactionHash })
+```
+
+Kitendakazi hiki kinapata risiti ya muamala kutoka kwa tukio. Tunahitaji risiti ili kuhakikisha tunajua lengo la muamala lilikuwa nini.
+
+```typescript
+const suspiciousApprovalEvent = async (ev : Event) : (Event | null) => {
+```
+
+Hiki ndicho kitendakazi muhimu zaidi, kinachoamua ikiwa tukio linatiliwa shaka au la. Aina ya kurudisha, `(Event | null)`, inaiambia TypeScript kuwa kitendakazi hiki kinaweza kurudisha ama `Event` au `null`. Tunarejesha `null` ikiwa tukio halitiliwi shaka.
+
+```typescript
+const owner = ev.args._owner
+```
+
+Viem ina majina ya sehemu, kwa hivyo imetuchambulia tukio. `_owner` ni mmiliki wa tokeni zitakazotumiwa.
+
+```typescript
+// Idhini za mikataba hazitiliwi shaka
+if (await isContract(owner)) return null
+```
+
+Ikiwa mmiliki ni mkataba, chukulia kuwa idhini hii haitiliwi shaka. Ili kuangalia ikiwa idhini ya mkataba inatiliwa shaka au la, tutahitaji kufuatilia utekelezaji kamili wa muamala ili kuona ikiwa umewahi kufika kwenye mkataba wa mmiliki, na ikiwa mkataba huo uliita mkataba wa ERC-20 moja kwa moja. Hiyo ni ghali zaidi kwa rasilimali kuliko tunavyopenda kufanya.
+
+```typescript
+const txn = await getEventTxn(ev)
+```
+
+Ikiwa idhini inatoka kwa akaunti inayomilikiwa nje, pata muamala ulioisababisha.
+
+```typescript
+// Idhini inatiliwa shaka ikiwa inatoka kwa mmiliki wa EOA ambaye si `from` ya muamala
+if (owner.toLowerCase() != txn.from.toLowerCase()) return ev
+```
+
+Hatuwezi tu kuangalia usawa wa maneno kwa sababu anwani ni za mfumo wa heksadesimali, kwa hivyo zina herufi. Wakati mwingine, kwa mfano katika `txn.from`, herufi hizo zote ni ndogo. Katika hali zingine, kama vile `ev.args._owner`, anwani iko katika [herufi mchanganyiko kwa ajili ya utambuzi wa makosa](https://eips.ethereum.org/EIPS/eip-55).
+
+Lakini ikiwa muamala hautoki kwa mmiliki, na mmiliki huyo anamilikiwa nje, basi tuna muamala unaotiliwa shaka.
+
+```typescript
+// Pia inatiliwa shaka ikiwa lengo la muamala si mkataba wa ERC-20 tunaouchunguza
+// uchunguzi
+if (txn.to.toLowerCase() != testedAddress) return ev
+```
+
+Vile vile, ikiwa anwani ya `to` ya muamala, mkataba wa kwanza kuitwa, si mkataba wa ERC-20 unaochunguzwa basi inatiliwa shaka.
+
+```typescript
+ // Ikiwa hakuna sababu ya kutilia shaka, rudisha null.
+ return null
+}
+```
+
+Ikiwa hakuna sharti kati ya hayo mawili lililo kweli basi tukio la `Approval` halitiliwi shaka.
+
+```typescript
+const testPromises = approvalEvents.map((ev) => suspiciousApprovalEvent(ev))
+const testResults = (await Promise.all(testPromises)).filter((x) => x != null)
+
+console.log(testResults)
+```
+
+[Kitendakazi cha `async`](https://www.w3schools.com/js/js_async.asp) kinarudisha kitu cha `Promise`. Kwa sintaksia ya kawaida, `await x()`, tunasubiri `Promise` hiyo itimizwe kabla ya kuendelea na uchakataji. Hii ni rahisi kupanga na kufuata, lakini pia haina ufanisi. Wakati tunasubiri `Promise` kwa tukio maalum litimizwe tayari tunaweza kuanza kufanyia kazi tukio linalofuata.
+
+Hapa tunatumia [`map`](https://www.w3schools.com/jsref/jsref_map.asp) kuunda safu ya vitu vya `Promise`. Kisha tunatumia [`Promise.all`](https://www.javascripttutorial.net/es6/javascript-promise-all/) kusubiri ahadi zote hizo zitimizwe. Kisha tunachuja [`filter`](https://www.w3schools.com/jsref/jsref_filter.asp) matokeo hayo ili kuondoa matukio yasiyotiliwa shaka.
+
+### Matukio ya `Transfer` yenye shaka {#suspicious-transfer-events}
+
+Njia nyingine inayowezekana ya kutambua tokeni za ulaghai ni kuona ikiwa zina uhamisho wowote unaotiliwa shaka. Kwa mfano, uhamisho kutoka kwa akaunti ambazo hazina tokeni nyingi kiasi hicho. Unaweza kuona [jinsi ya kutekeleza jaribio hili](https://github.com/qbzzt/20230915-scam-token-detection/blob/main/susTransfer.ts), lakini `wARB` haina suala hili.
+
+## Hitimisho {#conclusion}
+
+Ugunduzi wa kiotomatiki wa ulaghai wa ERC-20 unakabiliwa na [matokeo hasi ya uwongo](https://en.wikipedia.org/wiki/False_positives_and_false_negatives#False_negative_error), kwa sababu ulaghai unaweza kutumia mkataba wa tokeni wa ERC-20 wa kawaida kabisa ambao hauwakilishi kitu halisi. Kwa hivyo unapaswa kujaribu kila wakati _kupata anwani ya tokeni kutoka chanzo kinachoaminika_.
+
+Ugunduzi wa kiotomatiki unaweza kusaidia katika hali fulani, kama vile vipande vya DeFi, ambapo kuna tokeni nyingi na zinahitaji kushughulikiwa kiotomatiki. Lakini kama kawaida [caveat emptor](https://www.investopedia.com/terms/c/caveatemptor.asp), fanya utafiti wako mwenyewe, na wahimize watumiaji wako kufanya vivyo hivyo.
+
+[Tazama hapa kwa kazi zangu zaidi](https://cryptodocguy.pro/).
diff --git a/public/content/translations/sw/developers/tutorials/secret-state/index.md b/public/content/translations/sw/developers/tutorials/secret-state/index.md
new file mode 100644
index 00000000000..be5da67eff9
--- /dev/null
+++ b/public/content/translations/sw/developers/tutorials/secret-state/index.md
@@ -0,0 +1,728 @@
+---
+title: Kutumia zero-knowledge kwa hali ya siri
+description: michezo ya onchain ina mipaka kwa sababu haiwezi kutunza taarifa zozote zilizofichwa. Baada ya kusoma mafunzo haya, msomaji ataweza kuchanganya uthibitisho wa zero-knowledge na vipengele vya seva ili kuunda michezo inayoweza kuthibitishwa na hali ya siri, offchain, na sehemu. Mbinu ya kufanya hivi itaonyeshwa kwa kuunda mchezo wa minesweeper.
+author: Ori Pomerantz
+tags: ["server", "offchain", "centralized", "zero-knowledge", "zokrates", "mud"]
+skill: advanced
+lang: sw
+published: 2025-03-15
+---
+
+_Hakuna siri kwenye mnyororo wa bloku_. Kila kitu kinachowekwa kwenye mnyororo wa bloku kiko wazi kwa kila mtu kusoma. Hii ni muhimu, kwa sababu mnyororo wa bloku unategemea mtu yeyote kuweza kuuthibitisha. Hata hivyo, mara nyingi michezo hutegemea hali ya siri. Kwa mfano, mchezo wa [minesweeper](https://en.wikipedia.org/wiki/Minesweeper_\(video_game\)) hauna maana kabisa ikiwa unaweza tu kwenda kwenye kichunguzi cha mnyororo wa bloku na kuona ramani.
+
+Suluhisho rahisi zaidi ni kutumia [sehemu ya seva](/developers/tutorials/server-components/) kushikilia hali ya siri. Hata hivyo, sababu tunayotumia mnyororo wa bloku ni kuzuia udanganyifu na msanidi programu wa mchezo. Tunahitaji kuhakikisha uaminifu wa sehemu ya seva. Seva inaweza kutoa hashi ya hali, na kutumia [uthibitisho wa zero-knowledge](/zero-knowledge-proofs/#why-zero-knowledge-proofs-are-important) kuthibitisha kuwa hali iliyotumiwa kuhesabu matokeo ya hatua ndiyo sahihi.
+
+Baada ya kusoma makala hii utajua jinsi ya kuunda aina hii ya seva inayoshikilia hali ya siri, wateja wa kuonyesha hali, na sehemu ya onchain kwa mawasiliano kati ya hizi mbili. Zana kuu tutakazotumia zitakuwa:
+
+| Zana | Madhumuni | Imethibitishwa kwenye toleo |
+| --------------------------------------------- | --------------------------------------------------- | --------------------------------------: |
+| [Zokrates](https://zokrates.github.io/) | Uthibitisho wa zero-knowledge na uthibitishaji wake | 1.1.9 |
+| [Typescript](https://www.typescriptlang.org/) | Lugha ya programu kwa seva na wateja | 5.4.2 |
+| [Nodi](https://nodejs.org/en) | Kuendesha seva | 20.18.2 |
+| [Viem](https://viem.sh/) | Mawasiliano na Mnyororo wa bloku | 2.9.20 |
+| [MUD](https://mud.dev/) | Usimamizi wa data ya Onchain | 2.0.12 |
+| [React](https://react.dev/) | Kiolesura cha mtumiaji wa Wateja | 18.2.0 |
+| [Vite](https://vitejs.dev/) | Kutumikia msimbo wa wateja | 4.2.1 |
+
+## Mfano wa Minesweeper {#minesweeper}
+
+[Minesweeper](https://en.wikipedia.org/wiki/Minesweeper_\(video_game\)) ni mchezo unaojumuisha ramani ya siri yenye uwanja wa migodi. Mchezaji anachagua kuchimba katika eneo maalum. Ikiwa eneo hilo lina mgodi, mchezo umeisha. Vinginevyo, mchezaji anapata idadi ya migodi katika viwanja nane vinavyozunguka eneo hilo.
+
+Programu hii imeandikwa kwa kutumia [MUD](https://mud.dev/), mfumo unaoturuhusu kuhifadhi data onchain kwa kutumia [hifadhidata ya ufunguo-thamani](https://aws.amazon.com/nosql/key-value/) na kusawazisha data hiyo kiotomatiki na vipengele vya offchain. Mbali na usawazishaji, MUD hurahisisha kutoa udhibiti wa ufikiaji, na kwa watumiaji wengine [kupanua](https://mud.dev/guides/extending-a-world) programu yetu bila ruhusa.
+
+### Kuendesha mfano wa minesweeper {#running-minesweeper-example}
+
+Ili kuendesha mfano wa minesweeper:
+
+1. Hakikisha [una mahitaji ya awali yaliyowekwa](https://mud.dev/quickstart#prerequisites): [Nodi](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), na [`mprocs`](https://github.com/pvolok/mprocs).
+
+2. Kloni hifadhi.
+
+ ```sh copy
+ git clone https://github.com/qbzzt/20240901-secret-state.git
+ ```
+
+3. Sakinisha vifurushi.
+
+ ```sh copy
+ cd 20240901-secret-state/
+ pnpm install
+ npm install -g mprocs
+ ```
+
+ Ikiwa Foundry ilisakinishwa kama sehemu ya `pnpm install`, unahitaji kuanzisha upya ganda la mstari wa amri.
+
+4. Kusanya mikataba
+
+ ```sh copy
+ cd packages/contracts
+ forge build
+ cd ../..
+ ```
+
+5. Anzisha programu (pamoja na mnyororo wa bloku wa [anvil](https://book.getfoundry.sh/anvil/)) na subiri.
+
+ ```sh copy
+ mprocs
+ ```
+
+ Kumbuka kuwa uanzishaji unachukua muda mrefu. Ili kuona maendeleo, kwanza tumia mshale wa chini kusogeza hadi kwenye kichupo cha _contracts_ ili kuona mikataba ya MUD ikisambazwa. Unapopata ujumbe _Waiting for file changesβ¦_, mikataba imesambazwa na maendeleo zaidi yatatokea kwenye kichupo cha _server_. Hapo, unasubiri hadi upate ujumbe _Verifier address: 0x...._.
+
+ Ikiwa hatua hii itafanikiwa, utaona skrini ya `mprocs`, na michakato tofauti upande wa kushoto na matokeo ya console kwa mchakato uliochaguliwa kwa sasa upande wa kulia.
+
+ 
+
+ Ikiwa kuna tatizo na `mprocs`, unaweza kuendesha michakato minne kwa mikono, kila mmoja katika dirisha lake la mstari wa amri:
+
+ - **Anvil**
+
+ ```sh
+ cd packages/contracts
+ anvil --base-fee 0 --block-time 2
+ ```
+
+ - **Mikataba**
+
+ ```sh
+ cd packages/contracts
+ pnpm mud dev-contracts --rpc http://127.0.0.1:8545
+ ```
+
+ - **Seva**
+
+ ```sh
+ cd packages/server
+ pnpm start
+ ```
+
+ - **Wateja**
+
+ ```sh
+ cd packages/client
+ pnpm run dev
+ ```
+
+6. Sasa unaweza kuvinjari kwa [wateja](http://localhost:3000), bonyeza **New Game**, na uanze kucheza.
+
+### Majedwali {#tables}
+
+Tunahitaji [majedwali kadhaa](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/mud.config.ts) onchain.
+
+- `Configuration`: Jedwali hili ni la pekee, halina ufunguo na rekodi moja tu. Hutumika kushikilia taarifa za usanidi wa mchezo:
+ - `height`: Urefu wa uwanja wa migodi
+ - `width`: Upana wa uwanja wa migodi
+ - `numberOfBombs`: Idadi ya mabomu katika kila uwanja wa migodi
+
+- `VerifierAddress`: Jedwali hili pia ni la pekee. Hutumika kushikilia sehemu moja ya usanidi, anwani ya mkataba wa mthibitishaji (`verifier`). Tungeweza kuweka taarifa hizi kwenye jedwali la `Configuration`, lakini imewekwa na sehemu tofauti, seva, kwa hivyo ni rahisi kuiweka kwenye jedwali tofauti.
+
+- `PlayerGame`: Ufunguo ni anwani ya mchezaji. Data ni:
+
+ - `gameId`: Thamani ya baiti 32 ambayo ni hashi ya ramani ambayo mchezaji anacheza (kitambulisho cha mchezo).
+ - `win`: boolean inayoonyesha kama mchezaji alishinda mchezo.
+ - `lose`: boolean inayoonyesha kama mchezaji alishindwa mchezo.
+ - `digNumber`: idadi ya uchimbaji uliofanikiwa katika mchezo.
+
+- `GamePlayer`: Jedwali hili linashikilia ramani ya kinyume, kutoka `gameId` hadi anwani ya mchezaji.
+
+- `Map`: Ufunguo ni tupo ya thamani tatu:
+
+ - `gameId`: Thamani ya baiti 32 ambayo ni hashi ya ramani ambayo mchezaji anacheza (kitambulisho cha mchezo).
+ - kuratibu ya `x`
+ - kuratibu ya `y`
+
+ Thamani ni nambari moja. Ni 255 ikiwa bomu liligunduliwa. Vinginevyo, ni idadi ya mabomu karibu na eneo hilo pamoja na moja. Hatuwezi tu kutumia idadi ya mabomu, kwa sababu kwa chaguo-msingi hifadhi zote katika EVM na thamani zote za safu katika MUD ni sifuri. Tunahitaji kutofautisha kati ya "mchezaji bado hajachimba hapa" na "mchezaji alichimba hapa, na akakuta hakuna mabomu karibu".
+
+Kwa kuongeza, mawasiliano kati ya wateja na seva hufanyika kupitia sehemu ya onchain. Hii pia inatekelezwa kwa kutumia majedwali.
+
+- `PendingGame`: Maombi ambayo hayajashughulikiwa ya kuanza mchezo mpya.
+- `PendingDig`: Maombi ambayo hayajashughulikiwa ya kuchimba katika eneo maalum katika mchezo maalum. Hili ni [jedwali la offchain](https://mud.dev/store/tables#types-of-tables), ikimaanisha kuwa haliandikwi kwenye ghala la EVM, linasomeka tu offchain kwa kutumia matukio.
+
+### Utekelezaji na mtiririko wa data {#execution-data-flows}
+
+Mtiririko huu unaratibu utekelezaji kati ya wateja, sehemu ya onchain, na seva.
+
+#### Uanzishaji {#initialization-flow}
+
+Unapoendesha `mprocs`, hatua hizi hutokea:
+
+1. [`mprocs`](https://github.com/pvolok/mprocs) inaendesha vipengele vinne:
+
+ - [Anvil](https://book.getfoundry.sh/anvil/), ambayo inaendesha mnyororo wa bloku wa ndani
+ - [Mikataba](https://github.com/qbzzt/20240901-secret-state/tree/main/packages/contracts), ambayo inakusanya (ikihitajika) na kusambaza mikataba ya MUD
+ - [Wateja](https://github.com/qbzzt/20240901-secret-state/tree/main/packages/client), ambayo inaendesha [Vite](https://vitejs.dev/) ili kuhudumia UI na msimbo wa wateja kwa vivinjari vya wavuti.
+ - [Seva](https://github.com/qbzzt/20240901-secret-state/tree/main/packages/server), ambayo hufanya vitendo vya seva
+
+2. Kifurushi cha `contracts` kinasambaza mikataba ya MUD na kisha kinaendesha [hati ya `PostDeploy.s.sol`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/script/PostDeploy.s.sol). Hati hii inaweka usanidi. Msimbo kutoka github unabainisha [uwanja wa migodi wa 10x5 wenye migodi nane ndani yake](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/script/PostDeploy.s.sol#L23).
+
+3. [Seva](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts) inaanza kwa [kuweka MUD](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L6). Miongoni mwa mambo mengine, hii inawasha usawazishaji wa data, ili nakala ya majedwali husika iwepo kwenye kumbukumbu ya seva.
+
+4. Seva inasajili kazi ya kutekelezwa [wakati jedwali la `Configuration` linabadilika](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L23). [Kazi hii](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L24-L168) inaitwa baada ya `PostDeploy.s.sol` kutekeleza na kurekebisha jedwali.
+
+5. Wakati kazi ya uanzishaji wa seva inapokuwa na usanidi, [inaita `zkFunctions`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L34-L35) ili kuanzisha [sehemu ya zero-knowledge ya seva](#using-zokrates-from-typescript). Hii haiwezi kutokea hadi tupate usanidi kwa sababu kazi za zero-knowledge lazima ziwe na upana na urefu wa uwanja wa migodi kama viwango vya kudumu.
+
+6. Baada ya sehemu ya zero-knowledge ya seva kuanzishwa, hatua inayofuata ni [kusambaza mkataba wa uthibitishaji wa zero-knowledge kwenye mnyororo wa bloku](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L42-L53) na kuweka anwani ya mthibitishwa katika MUD.
+
+7. Mwishowe, tunasajili masasisho ili tuone mchezaji anapoomba ama [kuanza mchezo mpya](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L55-L71) au [kuchimba kwenye mchezo uliopo](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L73-L108).
+
+#### Mchezo mpya {#new-game-flow}
+
+Hivi ndivyo hutokea mchezaji anapoomba mchezo mpya.
+
+1. Ikiwa hakuna mchezo unaoendelea kwa mchezaji huyu, au kuna mmoja lakini una gameId ya sifuri, wateja wanaonyesha [kitufe cha mchezo mpya](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L175). Mtumiaji anapobonyeza kitufe hiki, [React inaendesha kazi ya `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) ni wito wa `System`. Katika MUD simu zote zinaelekezwa kupitia mkataba wa `World`, na katika hali nyingi unaita `__`. Katika kesi hii, wito ni kwa `app__newGame`, ambayo MUD kisha inaelekeza kwa [`newGame` katika `GameSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L16-L22).
+
+3. Kazi ya onchain inakagua kwamba mchezaji hana mchezo unaoendelea, na ikiwa hakuna [inaongeza ombi kwenye jedwali la `PendingGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L21).
+
+4. Seva inagundua mabadiliko katika `PendingGame` na [inaendesha kazi iliyosajiliwa](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L55-L71). Kazi hii inaita [`newGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L110-L114), ambayo kwa upande wake inaita [`createGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L116-L144).
+
+5. Jambo la kwanza `createGame` hufanya ni [kuunda ramani isiyo ya kawaida na idadi inayofaa ya migodi](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L120-L135). Kisha, inaita [`makeMapBorders`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L147-L166) ili kuunda ramani yenye mipaka tupu, ambayo ni muhimu kwa Zokrates. Mwishowe, `createGame` inaita [`calculateMapHash`](#calculateMapHash), ili kupata hashi ya ramani, ambayo hutumiwa kama kitambulisho cha mchezo.
+
+6. Kazi ya `newGame` inaongeza mchezo mpya kwenye `gamesInProgress`.
+
+7. Jambo la mwisho ambalo seva hufanya ni kuita [`app__newGameResponse`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L38-L43), ambayo iko onchain. Kazi hii iko katika `System` tofauti, [`ServerSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol), ili kuwezesha udhibiti wa ufikiaji. Udhibiti wa ufikiaji umefafanuliwa katika [faili ya usanidi ya MUD](https://mud.dev/config), [`mud.config.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/mud.config.ts#L67-L72).
+
+ Orodha ya ufikiaji inaruhusu anwani moja tu kuita `System`. Hii inazuia ufikiaji wa kazi za seva kwa anwani moja, kwa hivyo hakuna anayeweza kujifanya kuwa seva.
+
+8. Sehemu ya onchain inasasisha majedwali husika:
+
+ - Unda mchezo katika `PlayerGame`.
+ - Weka ramani ya kinyume katika `GamePlayer`.
+ - Ondoa ombi kutoka `PendingGame`.
+
+9. Seva inatambua mabadiliko katika `PendingGame`, lakini haifanyi chochote kwa sababu [`wantsGame`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L58-L60) ni ya uongo.
+
+10. Kwa upande wa wateja [`gameRecord`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L143-L148) imewekwa kwenye ingizo la `PlayerGame` kwa anwani ya mchezaji. Wakati `PlayerGame` inapobadilika, `gameRecord` pia hubadilika.
+
+11. Ikiwa kuna thamani katika `gameRecord`, na mchezo haujashindwa wala kushindwa, wateja [wanaonyesha ramani](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L175-L190).
+
+#### Chimba {#dig-flow}
+
+1. Mchezaji [anabonyeza kitufe cha seli ya ramani](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L188), ambayo inaita [kazi ya `dig`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/mud/createSystemCalls.ts#L33-L36). Kazi hii inaita [`dig` onchain](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L24-L32).
+
+2. Sehemu ya onchain [inafanya ukaguzi kadhaa wa kiakili](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L25-L30), na ikiwa imefanikiwa inaongeza ombi la kuchimba kwenye [`PendingDig`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/GameSystem.sol#L31).
+
+3. Seva [inagundua mabadiliko katika `PendingDig`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L73). [Ikiwa ni halali](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L75-L84), [inaita msimbo wa zero-knowledge](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L86-L95) (imeelezewa hapa chini) ili kutoa matokeo na uthibitisho kwamba ni halali.
+
+4. [Seva](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L97-L107) inaita [`digResponse`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L45-L64) onchain.
+
+5. `digResponse` hufanya mambo mawili. Kwanza, inakagua [uthibitisho wa zero knowledge](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L47-L61). Kisha, ikiwa uthibitisho umekaguliwa, inaita [`processDigResult`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L67-L86) ili kushughulikia matokeo.
+
+6. `processDigResult` inakagua ikiwa mchezo [umeshindwa](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L76-L78) au [umeshinda](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L83-L86), na [inasasisha `Ramani`, ramani ya onchain](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol#L80).
+
+7. Mteja huchukua masasisho kiotomatiki na [husasisha ramani inayoonyeshwa kwa mchezaji](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/client/src/App.tsx#L175-L190), na inapohitajika humwambia mchezaji ikiwa ameshinda au ameshindwa.
+
+## Kutumia Zokrates {#using-zokrates}
+
+Katika mtiririko ulioelezwa hapo juu tuliruka sehemu za maarifa-sifuri, tukizichukulia kama sanduku jeusi. Sasa tufungue tuone jinsi msimbo huo umeandikwa.
+
+### Kupiga hashi ramani {#hashing-map}
+
+Tunaweza kutumia [msimbo huu wa JavaScript](https://github.com/ZK-Plus/ICBC24_Tutorial_Compute-Offchain-Verify-onchain/tree/solutions/exercise) kutekeleza [Poseidon](https://www.poseidon-hash.info), kazi ya hashi ya Zokrates tunayotumia. Hata hivyo, ingawa hii ingekuwa haraka zaidi, pia ingekuwa ngumu zaidi kuliko kutumia tu kazi ya hashi ya Zokrates kuifanya. Hii ni mafunzo, na kwa hivyo msimbo umeboreshwa kwa urahisi, si kwa utendaji. Kwa hivyo, tunahitaji programu mbili tofauti za Zokrates, moja ya kuhesabu tu hashi ya ramani (`hashi`) na nyingine ya kuunda uthibitisho wa maarifa-sifuri wa matokeo ya kuchimba katika eneo kwenye ramani (`chimba`).
+
+### Kazi ya hashi {#hash-function}
+
+Hii ni kazi inayokokotoa hashi ya ramani. Tutapitia msimbo huu mstari kwa mstari.
+
+```
+import "hashes/poseidon/poseidon.zok" as poseidon;
+import "utils/pack/bool/pack128.zok" as pack128;
+```
+
+Mistari hii miwili inaingiza kazi mbili kutoka kwa [maktaba ya kawaida ya Zokrates](https://zokrates.github.io/toolbox/stdlib.html). [Kazi ya kwanza](https://github.com/Zokrates/ZoKrates/blob/latest/zokrates_stdlib/stdlib/hashes/poseidon/poseidon.zok) ni [hashi ya Poseidon](https://www.poseidon-hash.info/). Inachukua safu ya [`vipengele vya uwanja`](https://zokrates.github.io/language/types.html#field) na kurudisha `uwanja`.
+
+Kipengele cha uwanja katika Zokrates kwa kawaida huwa na urefu usiozidi biti 256, lakini si kwa kiasi kikubwa. Ili kurahisisha msimbo, tunazuia ramani iwe na biti zisizozidi 512, na kupiga hashi safu ya nyanja nne, na katika kila uwanja tunatumia biti 128 tu. [Kazi ya `pack128`](https://github.com/Zokrates/ZoKrates/blob/latest/zokrates_stdlib/stdlib/utils/pack/bool/pack128.zok) hubadilisha safu ya biti 128 kuwa `uwanja` kwa kusudi hili.
+
+```
+ def hashMap(bool[${width+2}][${height+2}] map) -> field {
+```
+
+Mstari huu unaanzisha ufafanuzi wa kazi. `hashMap` inapokea kigezo kimoja kiitwacho `map`, safu ya pande mbili ya `bool`(ean). Ukubwa wa ramani ni `width+2` kwa `height+2` kwa sababu ambazo [zimeelezwa hapa chini](#why-map-border).
+
+Tunaweza kutumia `${width+2}` na `${height+2}` kwa sababu programu za Zokrates zimehifadhiwa katika programu hii kama [kamba za kiolezo](https://www.w3schools.com/js/js_string_templates.asp). Msimbo kati ya `${` na `}` unathminiwa na JavaScript, na kwa njia hii programu inaweza kutumika kwa saizi tofauti za ramani. Kigezo cha ramani kina mpaka wa upana wa eneo moja kuzunguka bila mabomu yoyote, ambayo ndiyo sababu tunahitaji kuongeza mbili kwenye upana na urefu.
+
+Thamani ya kurudi ni `uwanja` ambao una hashi.
+
+```
+ bool[512] mut map1d = [false; 512];
+```
+
+Ramani ni ya pande mbili. Hata hivyo, kazi ya `pack128` haifanyi kazi na safu za pande mbili. Kwa hivyo, kwanza tunalaza ramani kuwa safu ya baiti 512, kwa kutumia `map1d`. Kwa chaguo-msingi vigezo vya Zokrates ni viwango vya kudumu, lakini tunahitaji kugawa thamani kwa safu hii katika kitanzi, kwa hivyo tunakifafanua kama [`mut`](https://zokrates.github.io/language/variables.html#mutability).
+
+Tunahitaji kuanzisha safu kwa sababu Zokrates haina `undefined`. Usemi wa `[false; 512]` unamaanisha [safu ya thamani 512 za `uongo`](https://zokrates.github.io/language/types.html#declaration-and-initialization).
+
+```
+ u32 mut counter = 0;
+```
+
+Pia tunahitaji kaunta kutofautisha kati ya biti ambazo tayari tumejaza katika `map1d` na zile ambazo hatujajaza.
+
+```
+ for u32 x in 0..${width+2} {
+```
+
+Hivi ndivyo unavyotangaza [kitanzi cha `kwa`](https://zokrates.github.io/language/control_flow.html#for-loops) katika Zokrates. Kitanzi cha Zokrates `kwa` lazima kiwe na mipaka maalum, kwa sababu ingawa kinaonekana kama kitanzi, mkalimani kwa kweli "huifungua". Usemi `${width+2}` ni kiwango cha kudumu cha wakati wa kukusanya kwa sababu `width` imewekwa na msimbo wa TypeScript kabla ya kuita mkusanyaji.
+
+```
+ for u32 y in 0..${height+2} {
+ map1d[counter] = map[x][y];
+ counter = counter+1;
+ }
+ }
+```
+
+Kwa kila eneo kwenye ramani, weka thamani hiyo kwenye safu ya `map1d` na uongeze kaunta.
+
+```
+ field[4] hashMe = [
+ pack128(map1d[0..128]),
+ pack128(map1d[128..256]),
+ pack128(map1d[256..384]),
+ pack128(map1d[384..512])
+ ];
+```
+
+`pack128` kuunda safu ya thamani nne za `uwanja` kutoka `map1d`. Katika Zokrates `array[a..b]` inamaanisha kipande cha safu kinachoanzia `a` na kuishia `b-1`.
+
+```
+ return poseidon(hashMe);
+}
+```
+
+Tumia `poseidon` kubadilisha safu hii kuwa hashi.
+
+### Programu ya hashi {#hash-program}
+
+Seva inahitaji kuita `hashMap` moja kwa moja ili kuunda vitambulisho vya mchezo. Hata hivyo, Zokrates inaweza tu kuita kazi ya `main` kwenye programu kuanza, kwa hivyo tunaunda programu yenye `main` inayoita kazi ya hashi.
+
+```
+${hashFragment}
+
+def main(bool[${width+2}][${height+2}] map) -> field {
+ return hashMap(map);
+}
+```
+
+### Programu ya kuchimba {#dig-program}
+
+Hii ndiyo moyo wa sehemu ya maarifa-sifuri ya programu, ambapo tunatoa uthibitisho unaotumika kuthibitisha matokeo ya kuchimba.
+
+```
+${hashFragment}
+
+// Idadi ya migodi katika eneo (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 };
+}
+```
+
+#### Kwa nini mpaka wa ramani {#why-map-border}
+
+Uthibitisho wa maarifa-sifuri hutumia [mizunguko ya kihesabu](https://medium.com/web3studio/simple-explanations-of-arithmetic-circuits-and-zero-knowledge-proofs-806e59a79785), ambayo haina mbadala rahisi kwa taarifa ya `if`. Badala yake, wanatumia mbadala wa [kiendeshaji chenye masharti](https://en.wikipedia.org/wiki/Ternary_conditional_operator). Ikiwa `a` inaweza kuwa sifuri au moja, unaweza kuhesabu `if a { b } else { c }` kama `ab+(1-a)c`.
+
+Kwa sababu hii, taarifa ya `if` ya Zokrates daima inathmini matawi yote mawili. Kwa mfano, ikiwa una msimbo huu:
+
+```
+bool[5] arr = [false; 5];
+u32 index=10;
+return if index>4 { 0 } else { arr[index] }
+```
+
+Itatoa hitilafu, kwa sababu inahitaji kuhesabu `arr[10]`, ingawa thamani hiyo itazidishwa na sifuri baadaye.
+
+Hii ndiyo sababu tunahitaji mpaka wa upana wa eneo moja kuzunguka ramani. Tunahitaji kuhesabu jumla ya idadi ya migodi karibu na eneo, na hiyo inamaanisha tunahitaji kuona eneo la safu moja juu na chini, kushoto na kulia, kwa eneo tunalochimba. Hiyo inamaanisha maeneo hayo lazima yawepo kwenye safu ya ramani ambayo Zokrates inapewa.
+
+```
+def main(private bool[${width+2}][${height+2}] map, u32 x, u32 y) -> (field, u8) {
+```
+
+Kwa chaguo-msingi, uthibitisho wa Zokrates unajumuisha pembejeo zao. Haina faida kujua kuna migodi mitano karibu na eneo isipokuwa unajua ni eneo gani (na huwezi tu kuilinganisha na ombi lako, kwa sababu basi mthibitishaji anaweza kutumia thamani tofauti na asikuambie). Hata hivyo, tunahitaji kuweka ramani kuwa siri, huku tukiitoa kwa Zokrates. Suluhisho ni kutumia kigezo cha `private`, ambacho _hakifunuliwi_ na uthibitisho.
+
+Hii inafungua njia nyingine ya matumizi mabaya. Mthibitishaji anaweza kutumia kuratibu sahihi, lakini kuunda ramani yenye idadi yoyote ya migodi karibu na eneo, na labda katika eneo lenyewe. Ili kuzuia matumizi haya mabaya, tunafanya uthibitisho wa maarifa-sifuri ujumuishe hashi ya ramani, ambayo ni kitambulisho cha mchezo.
+
+```
+ return (hashMap(map),
+```
+
+Thamani ya kurudi hapa ni tuple inayojumuisha safu ya hashi ya ramani pamoja na matokeo ya kuchimba.
+
+```
+ if map2mineCount(map, x, y) > 0 { 0xFF } else {
+```
+
+Tunatumia 255 kama thamani maalum endapo eneo lenyewe lina bomu.
+
+```
+ 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)
+ }
+ );
+}
+```
+
+Ikiwa mchezaji hajagonga mgodi, ongeza hesabu za migodi kwa eneo linalozunguka eneo hilo na urudishe hiyo.
+
+### Kutumia Zokrates kutoka TypeScript {#using-zokrates-from-typescript}
+
+Zokrates ina kiolesura cha mstari wa amri, lakini katika programu hii tunaitumia katika [msimbo wa TypeScript](https://zokrates.github.io/toolbox/zokrates_js.html).
+
+Maktaba yenye ufafanuzi wa Zokrates inaitwa [`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"
+```
+
+Leta [mafungo ya JavaScript ya Zokrates](https://zokrates.github.io/toolbox/zokrates_js.html). Tunahitaji tu kazi ya [`initialize`](https://zokrates.github.io/toolbox/zokrates_js.html#initialize) kwa sababu inarudisha ahadi inayotatua ufafanuzi wote wa Zokrates.
+
+```typescript
+export const zkFunctions = async (width: number, height: number) : Promise => {
+```
+
+Sawa na Zokrates yenyewe, pia tunasafirisha kazi moja tu, ambayo pia ni [isiyosawazisha](https://www.w3schools.com/js/js_async.asp). Inaporudi hatimaye, inatoa kazi kadhaa kama tutakavyoona hapa chini.
+
+```typescript
+const zokrates = await zokratesInitialize()
+```
+
+Anzisha Zokrates, pata kila kitu tunachohitaji kutoka kwa maktaba.
+
+```typescript
+const hashFragment = `
+ import "utils/pack/bool/pack128.zok" as pack128;
+ import "hashes/poseidon/poseidon.zok" as poseidon;
+ .
+ .
+ .
+ }
+ `
+
+const hashProgram = `
+ ${hashFragment}
+ .
+ .
+ .
+ `
+
+const digProgram = `
+ ${hashFragment}
+ .
+ .
+ .
+ `
+```
+
+Kisha tuna kazi ya hashi na programu mbili za Zokrates tulizoona hapo juu.
+
+```typescript
+const digCompiled = zokrates.compile(digProgram)
+const hashCompiled = zokrates.compile(hashProgram)
+```
+
+Hapa tunakusanya programu hizo.
+
+```typescript
+// Tengeneza funguo za uthibitishaji wa zero-knowledge.\n// Kwenye mfumo wa uzalishaji ungetaka kutumia sherehe ya usanidi.\n// (https://zokrates.github.io/toolbox/trusted_setup.html#initializing-a-phase-2-ceremony).\nconst keySetupResults = zokrates.setup(digCompiled.program, \"\")\nconst verifierKey = keySetupResults.vk\nconst proverKey = keySetupResults.pk
+```
+
+Kwenye mfumo wa uzalishaji tunaweza kutumia [hafla ya kuanzisha](https://zokrates.github.io/toolbox/trusted_setup.html#initializing-a-phase-2-ceremony) ngumu zaidi, lakini hii ni nzuri ya kutosha kwa maonyesho. Sio tatizo watumiaji kujua ufunguo wa mthibitishaji - bado hawawezi kuitumia kuthibitisha mambo isipokuwa ni kweli. Kwa sababu tunabainisha entropy (kigezo cha pili, `""`), matokeo yatakuwa sawa kila wakati.
+
+**Kumbuka:** Uundaji wa programu za Zokrates na uundaji wa ufunguo ni michakato ya polepole. Hakuna haja ya kuzirudia kila wakati, ila tu wakati saizi ya ramani inabadilika. Kwenye mfumo wa uzalishaji ungewafanya mara moja, kisha uhifadhi matokeo. Sababu pekee kwa nini siifanyi hapa ni kwa ajili ya urahisi.
+
+#### `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")
+ )
+}
+```
+
+Kazi ya [`computeWitness`](https://zokrates.github.io/toolbox/zokrates_js.html#computewitnessartifacts-args-options) inatekeleza programu ya Zokrates. Inarudisha muundo wenye nyanja mbili: `output`, ambayo ni matokeo ya programu kama kamba ya JSON, na `witness`, ambayo ni taarifa inayohitajika kuunda uthibitisho wa maarifa-sifuri wa matokeo. Hapa tunahitaji tu matokeo.
+
+Matokeo ni kamba ya fomu `"31337"`, nambari ya desimali iliyofungwa kwenye alama za nukuu. Lakini matokeo tunayohitaji kwa `viem` ni nambari ya heksadesimali ya fomu `0x60A7`. Kwa hivyo tunatumia `.slice(1,-1)` kuondoa alama za nukuu na kisha `BigInt` kuendesha kamba iliyobaki, ambayo ni nambari ya desimali, kwa [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt). `.toString(16)` inabadilisha `BigInt` hii kuwa kamba ya heksadesimali, na `"0x"+` inaongeza alama ya nambari za heksadesimali.
+
+```typescript
+// Chimba na urudishe uthibitisho wa maarifa-sifuri wa matokeo
+// (msimbo wa upande wa seva)
+```
+
+Uthibitisho wa maarifa-sifuri unajumuisha pembejeo za umma (`x` na `y`) na matokeo (hashi ya ramani na idadi ya mabomu).
+
+```typescript
+ const zkDig = function(map: boolean[][], x: number, y: number) : any {
+ if (x<0 || x>=width || y<0 || y>=height)
+ throw new Error("Trying to dig outside the map")
+```
+
+Ni tatizo kuangalia ikiwa faharasa iko nje ya mipaka katika Zokrates, kwa hivyo tunafanya hapa.
+
+```typescript
+const runResults = zokrates.computeWitness(digCompiled, [map, `${x}`, `${y}`])
+```
+
+Tekeleza programu ya kuchimba.
+
+```typescript
+ const proof = zokrates.generateProof(
+ digCompiled.program,
+ runResults.witness,
+ proverKey)
+
+ return proof
+ }
+```
+
+Tumia [`generateProof`](https://zokrates.github.io/toolbox/zokrates_js.html#generateproofprogram-witness-provingkey-entropy) na urudishe uthibitisho.
+
+```typescript
+const solidityVerifier = `
+ // Ukubwa wa ramani: ${width} x ${height}
+ \n${zokrates.exportSolidityVerifier(verifierKey)}
+ `
+```
+
+Mthibitishaji wa Solidity, mkataba-erevu tunaoweza kusambaza kwenye mnyororo wa bloku na kutumia kuthibitisha uthibitisho unaotokana na `digCompiled.program`.
+
+```typescript
+ return {
+ zkDig,
+ calculateMapHash,
+ solidityVerifier,
+ }
+}
+```
+
+Mwishowe, rudisha kila kitu ambacho msimbo mwingine unaweza kuhitaji.
+
+## Majaribio ya usalama {#security-tests}
+
+Majaribio ya usalama ni muhimu kwa sababu hitilafu ya utendakazi hatimaye itajidhihirisha. Lakini ikiwa programu haina usalama, kuna uwezekano itabaki imefichwa kwa muda mrefu kabla ya kufunuliwa na mtu anayedanganya na kuondoka na rasilimali ambazo ni za wengine.
+
+### Ruhusa {#permissions}
+
+Kuna chombo kimoja cha upendeleo katika mchezo huu, seva. Ni mtumiaji pekee anayeruhusiwa kuita kazi katika [`ServerSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol). Tunaweza kutumia [`cast`](https://book.getfoundry.sh/cast/) kuthibitisha wito kwa kazi zilizoidhinishwa zinaruhusiwa tu kama akaunti ya seva.
+
+[Ufunguo binafsi wa seva uko katika `setupNetwork.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/mud/setupNetwork.ts#L52).
+
+1. Kwenye kompyuta inayoendesha `anvil` (mnyororo wa bloku), weka vigezo hivi vya mazingira.
+
+ ```sh copy
+ WORLD_ADDRESS=0x8d8b6b8414e1e3dcfd4168561b9be6bd3bf6ec4b
+ UNAUTHORIZED_KEY=0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a
+ AUTHORIZED_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
+ ```
+
+2. Tumia `cast` kujaribu kuweka anwani ya mthibitishaji kama anwani isiyoidhinishwa.
+
+ ```sh copy
+ cast send $WORLD_ADDRESS 'app__setVerifier(address)' `cast address-zero` --private-key $UNAUTHORIZED_KEY
+ ```
+
+ Sio tu kwamba `cast` inaripoti kutofaulu, lakini unaweza kufungua **Zana za Maendeleo za MUD** kwenye mchezo kwenye kivinjari, bonyeza **Majedwali**, na uchague **app\_\_VerifierAddress**. Angalia kwamba anwani sio sifuri.
+
+3. Weka anwani ya mthibitishaji kama anwani ya seva.
+
+ ```sh copy
+ cast send $WORLD_ADDRESS 'app__setVerifier(address)' `cast address-zero` --private-key $AUTHORIZED_KEY
+ ```
+
+ Anwani katika **app\_\_VerifiedAddress** sasa inapaswa kuwa sifuri.
+
+Kazi zote za MUD katika `Mfumo` huo huo hupitia udhibiti sawa wa ufikiaji, kwa hivyo nachukulia jaribio hili linatosha. Ikiwa hutafanya hivyo, unaweza kuangalia kazi zingine katika [`ServerSystem`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/contracts/src/systems/ServerSystem.sol).
+
+### Matumizi mabaya ya maarifa-sifuri {#zero-knowledge-abuses}
+
+Hisabati ya kuthibitisha Zokrates iko nje ya wigo wa mafunzo haya (na uwezo wangu). Hata hivyo, tunaweza kufanya ukaguzi mbalimbali kwenye msimbo wa maarifa-sifuri ili kuthibitisha kwamba ikiwa haijafanywa kwa usahihi inashindwa. Majaribio haya yote yatatuhitaji kubadilisha [`zero-knowledge.ts`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts) na kuanzisha upya programu nzima. Haitoshi kuanzisha upya mchakato wa seva, kwa sababu inaweka programu katika hali isiyowezekana (mchezaji ana mchezo unaoendelea, lakini mchezo haupatikani tena kwa seva).
+
+#### Jibu lisilo sahihi {#wrong-answer}
+
+Uwezekano rahisi zaidi ni kutoa jibu lisilo sahihi katika uthibitisho wa maarifa-sifuri. Ili kufanya hivyo, tunaingia ndani ya `zkDig` na [kurekebisha mstari wa 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")
+```
+
+Hii inamaanisha tutadai kila wakati kuna bomu moja, bila kujali jibu sahihi. Jaribu kucheza na toleo hili, na utaona kwenye kichupo cha **seva** cha skrini ya `pnpm dev` hitilafu hii:
+
+```
+ cause: {
+ code: 3,
+ message: 'execution reverted: revert: Zero knowledge verification fail',
+ data: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000
+000000000000000000000000000000000000000000000000205a65726f206b6e6f776c6564676520766572696669636174696f6
+e206661696c'
+ },
+```
+
+Kwa hivyo aina hii ya udanganyifu inashindwa.
+
+#### Uthibitisho usio sahihi {#wrong-proof}
+
+Nini kinatokea ikiwa tunatoa taarifa sahihi, lakini tuna data isiyo sahihi ya uthibitisho? Sasa, badilisha mstari wa 91 na:
+
+```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")],
+}
+```
+
+Bado inashindwa, lakini sasa inashindwa bila sababu kwa sababu inatokea wakati wa wito wa mthibitishaji.
+
+### Mtumiaji anawezaje kuthibitisha msimbo wa imani-sifuri? {#user-verify-zero-trust}
+
+Mikataba-erevu ni rahisi kiasi kuthibitisha. Kwa kawaida, msanidi programu anachapisha msimbo chanzo kwa kichunguzi cha bloku, na kichunguzi cha bloku kinathibitisha kwamba msimbo chanzo unakusanywa kwa msimbo katika [shughuli ya usambazaji wa mkataba](/developers/docs/smart-contracts/deploying/). Katika kesi ya MUD `Mfumo` huu ni [ngumu kidogo](https://mud.dev/cli/verify), lakini si kwa kiasi kikubwa.
+
+Hii ni ngumu zaidi na maarifa-sifuri. Mthibitishaji anajumuisha viwango vya kudumu na anafanya mahesabu juu yao. Hii haikuambii nini kinachothibitishwa.
+
+```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)]);
+```
+
+Suluhisho, angalau hadi wachunguzi wa bloku wataongeza uthibitishaji wa Zokrates kwenye violesura vyao vya watumiaji, ni kwa wasanidi programu kufanya programu za Zokrates zipatikane, na angalau baadhi ya watumiaji kuzikusanya wenyewe na ufunguo sahihi wa uthibitishaji.
+
+Kufanya hivyo:
+
+1. [Sakinisha Zokrates](https://zokrates.github.io/gettingstarted.html).
+
+2. Unda faili, `dig.zok`, na programu ya Zokrates. Msimbo hapa chini unadhania umehifadhi saizi ya ramani ya asili, 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);
+ }
+
+
+ // Idadi ya migodi katika eneo (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. Kusanya msimbo wa Zokrates na uunde ufunguo wa uthibitishaji. Ufunguo wa uthibitishaji unapaswa kuundwa na entropy sawa iliyotumika katika seva ya awali, [katika kesi hii kamba tupu](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. Unda mthibitishaji wa Solidity peke yako, na uthibitishe kuwa unafanya kazi sawa na ule ulioko kwenye mnyororo wa bloku (seva inaongeza maoni, lakini hiyo sio muhimu).
+
+ ```sh copy
+ zokrates export-verifier
+ diff verifier.sol ~/20240901-secret-state/packages/contracts/src/verifier.sol
+ ```
+
+## Maamuzi ya kubuni {#design}
+
+Katika programu yoyote ngumu vya kutosha kuna malengo ya kubuni yanayoshindana ambayo yanahitaji maelewano. Wacha tuangalie baadhi ya maelewano na kwa nini suluhisho la sasa ni bora kuliko chaguzi zingine.
+
+### Kwa nini maarifa-sifuri {#why-zero-knowledge}
+
+Kwa minesweeper hauitaji maarifa-sifuri kweli. Seva inaweza kushikilia ramani kila wakati, na kisha kufunua yote wakati mchezo umekwisha. Kisha, mwishoni mwa mchezo, mkataba-erevu unaweza kuhesabu hashi ya ramani, kuthibitisha inalingana, na ikiwa haifanyi hivyo adhibu seva au kupuuzia mchezo kabisa.
+
+Sikutumia suluhisho hili rahisi kwa sababu inafanya kazi tu kwa michezo mifupi yenye hali ya mwisho iliyoelezwa vizuri. Wakati mchezo unaweza kuwa hauna mwisho (kama ilivyo kwa [ulimwengu huru](https://0xparc.org/blog/autonomous-worlds)), unahitaji suluhisho linalothibitisha hali _bila_ kuifunua.
+
+Kama mafunzo, makala hii ilihitaji mchezo mfupi ambao ni rahisi kuelewa, lakini mbinu hii ni muhimu zaidi kwa michezo mirefu.
+
+### Kwa nini Zokrates? {#why-zokrates}
+
+[Zokrates](https://zokrates.github.io/) sio maktaba pekee ya maarifa-sifuri inayopatikana, lakini inafanana na lugha ya kawaida ya programu [inayoelekeza](https://en.wikipedia.org/wiki/Imperative_programming) na inasaidia vigezo vya boolean.
+
+Kwa programu yako, na mahitaji tofauti, unaweza kupendelea kutumia [Circum](https://docs.circom.io/getting-started/installation/) au [Cairo](https://www.cairo-lang.org/tutorials/getting-started-with-cairo/).
+
+### Wakati wa kukusanya Zokrates {#when-compile-zokrates}
+
+Katika programu hii tunakusanya programu za Zokrates [kila wakati seva inapoanza](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L60-L61). Hii ni wazi ni upotevu wa rasilimali, lakini hii ni mafunzo, yaliyoboreshwa kwa urahisi.
+
+Ikiwa ningekuwa ninaandika programu ya kiwango cha uzalishaji, ningeangalia kama nina faili na programu za Zokrates zilizokusanywa kwa saizi hii ya uwanja wa migodi, na ikiwa ndivyo nitumie hiyo. Vivyo hivyo kwa kusambaza mkataba wa mthibitishaji onchain.
+
+### Kuunda funguo za mthibitishaji na mthibitishaji {#key-creation}
+
+[Uundaji wa ufunguo](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L63-L69) ni hesabu nyingine safi ambayo haihitaji kufanywa zaidi ya mara moja kwa saizi fulani ya uwanja wa migodi. Tena, inafanywa mara moja tu kwa ajili ya urahisi.
+
+Kwa kuongeza, tunaweza kutumia [hafla ya kuanzisha](https://zokrates.github.io/toolbox/trusted_setup.html#initializing-a-phase-2-ceremony). Faida ya hafla ya kuanzisha ni kwamba unahitaji ama entropy au matokeo ya kati kutoka kwa kila mshiriki ili kudanganya kwenye uthibitisho wa maarifa-sifuri. Ikiwa angalau mshiriki mmoja wa hafla ni mkweli na anafuta habari hiyo, uthibitisho wa maarifa-sifuri uko salama kutokana na mashambulizi fulani. Hata hivyo, _hakuna utaratibu_ wa kuthibitisha kwamba habari imefutwa kutoka kila mahali. Ikiwa uthibitisho wa maarifa-sifuri ni muhimu sana, unataka kushiriki katika hafla ya kuanzisha.
+
+Hapa tunategemea [nguvu za milele za tau](https://github.com/privacy-scaling-explorations/perpetualpowersoftau), ambayo ilikuwa na washiriki wengi. Pengine ni salama vya kutosha, na rahisi zaidi. Pia hatuongezi entropy wakati wa uundaji wa ufunguo, ambayo inafanya iwe rahisi kwa watumiaji [kuthibitisha usanidi wa maarifa-sifuri](#user-verify-zero-trust).
+
+### Wapi pa kuthibitisha {#where-verification}
+
+Tunaweza kuthibitisha uthibitisho wa maarifa-sifuri ama onchain (ambayo inagharimu gesi) au katika mteja (kwa kutumia [`verify`](https://zokrates.github.io/toolbox/zokrates_js.html#verifyverificationkey-proof)). Nilichagua ya kwanza, kwa sababu hii inakuwezesha [kuthibitisha mthibitishaji](#user-verify-zero-trust) mara moja na kisha kuamini kwamba haibadiliki maadamu anwani ya mkataba wake inabaki sawa. Ikiwa uthibitishaji ungefanywa kwa mteja, ungehitaji kuthibitisha msimbo unaopokea kila unapopakua mteja.
+
+Pia, ingawa mchezo huu ni wa mchezaji mmoja, michezo mingi ya mnyororo wa bloku ni ya wachezaji wengi. uthibitishaji wa onchain unamaanisha unathibitisha tu uthibitisho wa maarifa-sifuri mara moja. Kuifanya katika mteja kungehitaji kila mteja kuthibitisha kivyake.
+
+### Kufanya ramani iwe bapa katika TypeScript au Zokrates? {#where-flatten}
+
+Kwa ujumla, wakati usindikaji unaweza kufanywa ama katika TypeScript au Zokrates, ni bora kuifanya katika TypeScript, ambayo ni haraka sana, na haihitaji uthibitisho wa maarifa-sifuri. Hii ndiyo sababu, kwa mfano, kwamba hatutoi Zokrates na hashi na kuifanya ithibitishe kuwa ni sahihi. Hashing inapaswa kufanywa ndani ya Zokrates, lakini mechi kati ya hashi iliyorudishwa na hashi onchain inaweza kutokea nje yake.
+
+Hata hivyo, bado [tunalainisha ramani katika Zokrates](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L15-L20), ambapo tungeweza kuifanya katika TypeScript. Sababu ni kwamba chaguzi zingine, kwa maoni yangu, ni mbaya zaidi.
+
+- Toa safu ya boolean ya mwelekeo mmoja kwa msimbo wa Zokrates, na utumie usemi kama `x*(height+2)
+ +y` kupata ramani ya mwelekeo miwili. [Msimbo](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/zero-knowledge.ts#L44-L47) ungekuwa mgumu kidogo, kwa hivyo niliamua kuwa faida ya utendaji haifai kwa mafunzo.
+
+- Tuma Zokrates safu ya mwelekeo mmoja na safu ya mwelekeo miwili. Hata hivyo, suluhisho hili halitupati faida yoyote. Msimbo wa Zokrates ungehitaji kuthibitisha kwamba safu ya mwelekeo mmoja inayoletwa ni kweli uwakilishi sahihi wa safu ya mwelekeo miwili. Kwa hivyo hakungekuwa na faida yoyote ya utendaji.
+
+- Laza safu ya mwelekeo miwili katika Zokrates. Hii ndiyo chaguo rahisi zaidi, kwa hivyo niliichagua.
+
+### Wapi pa kuhifadhi ramani {#where-store-maps}
+
+Katika programu hii [`gamesInProgress`](https://github.com/qbzzt/20240901-secret-state/blob/main/packages/server/src/app.ts#L20) ni kigezo tu kwenye kumbukumbu. Hii inamaanisha kwamba ikiwa seva yako itakufa na kuhitaji kuanzishwa upya, habari zote ilizohifadhi zinapotea. Sio tu kwamba wachezaji hawawezi kuendelea na mchezo wao, hawawezi hata kuanza mchezo mpya kwa sababu sehemu ya onchain inafikiri bado wana mchezo unaoendelea.
+
+Huu ni muundo mbaya kwa mfumo wa uzalishaji, ambapo utahifadhi habari hii kwenye hifadhidata. Sababu pekee niliyotumia kigezo hapa ni kwa sababu hii ni mafunzo na urahisi ndio jambo kuu.
+
+## Hitimisho: Chini ya hali gani hii ni mbinu inayofaa? {#conclusion}
+
+Kwa hivyo, sasa unajua jinsi ya kuandika mchezo na seva inayohifadhi hali ya siri ambayo sio ya onchain. Lakini katika kesi gani unapaswa kuifanya? Kuna mambo makuu mawili ya kuzingatia.
+
+- _Mchezo unaoendelea kwa muda mrefu_: [Kama ilivyoelezwa hapo juu](#why-zero-knowledge), katika mchezo mfupi unaweza tu kuchapisha hali mara mchezo unapokwisha na kila kitu kuthibitishwa basi. Lakini hiyo sio chaguo wakati mchezo unachukua muda mrefu au usiojulikana, na hali inahitaji kubaki siri.
+
+- _Ugawanyaji fulani wa kati unakubalika_: Uthibitisho wa maarifa-sifuri unaweza kuthibitisha uadilifu, kwamba chombo hakighushi matokeo. Wanachoweza kufanya ni kuhakikisha kuwa chombo bado kitapatikana na kujibu ujumbe. Katika hali ambapo upatikanaji pia unahitaji kugawanywa, uthibitisho wa maarifa-sifuri sio suluhisho la kutosha, na unahitaji [hesabu za vyama vingi](https://en.wikipedia.org/wiki/Secure_multi-party_computation).
+
+[Tazama hapa kwa kazi zangu zaidi](https://cryptodocguy.pro/).
+
+### Shukrani {#acknowledgements}
+
+- Alvaro Alonso alisoma rasimu ya makala hii na akanifafanulia baadhi ya kutoelewa kwangu kuhusu Zokrates.
+
+Makosa yoyote yaliyobaki ni jukumu langu.
diff --git a/public/content/translations/sw/developers/tutorials/secure-development-workflow/index.md b/public/content/translations/sw/developers/tutorials/secure-development-workflow/index.md
new file mode 100644
index 00000000000..63bd5bd0ccf
--- /dev/null
+++ b/public/content/translations/sw/developers/tutorials/secure-development-workflow/index.md
@@ -0,0 +1,52 @@
+---
+title: Orodha hakiki ya usalama wa mkataba-erevu
+description: Mtiririko wa kazi unaopendekezwa wa kuandika mikataba-erevu salama
+author: "Trailofbits"
+tags: ["smart contracts", "security", "solidity"]
+skill: intermediate
+lang: sw
+published: 2020-09-07
+source: Building secure contracts
+sourceUrl: https://github.com/crytic/building-secure-contracts/blob/master/development-guidelines/workflow.md
+---
+
+## Orodha hakiki ya uendelezaji wa mkataba-erevu {#smart-contract-development-checklist}
+
+Huu hapa ni mchakato wa kiwango cha juu tunaopendekeza ufuate unapoandika mikataba yako-erevu.
+
+Angalia masuala ya usalama yanayojulikana:
+
+- Pitia mikataba yako na [Slither](https://github.com/crytic/slither). Ina vigunduzi zaidi ya 40 vilivyojengewa ndani kwa ajili ya udhaifu wa kawaida. Iendeshe kwa kila uwasilishaji wa msimbo mpya na hakikisha inapata ripoti safi (au tumia hali ya kutatua kunyamazisha masuala fulani).
+- Pitia mikataba yako na [Crytic](https://crytic.io/). Hukagua masuala 50 ambayo Slither haikagui. Crytic inaweza kusaidia timu yako kuendelea kufuatiliana pia, kwa kuibua kwa urahisi masuala ya usalama katika Maombi ya Kuunganisha (Pull Requests) kwenye GitHub.
+
+Fikiria vipengele maalum vya mkataba wako:
+
+- Je, mikataba yako inaweza kusasishwa? Pitia msimbo wako wa uwezo wa kusasishwa kwa ajili ya dosari ukitumia [`slither-check-upgradeability`](https://github.com/crytic/slither/wiki/Upgradeability-Checks) au [Crytic](https://blog.trailofbits.com/2020/06/12/upgradeable-contracts-made-safer-with-crytic/). Tumeandika njia 17 ambazo masasisho yanaweza kwenda mrama.
+- Je, mikataba yako inadai kukidhi ERC? Zikague na [`slither-check-erc`](https://github.com/crytic/slither/wiki/ERC-Conformance). Zana hii hutambua papo hapo mikengeuko kutoka kwa sifa sita za kawaida.
+- Je, unaunganisha na tokeni za wahusika wengine? Pitia [orodha hakiki yetu ya uunganishaji wa tokeni](/developers/tutorials/token-integration-checklist/) kabla ya kutegemea mikataba ya nje.
+
+Kagua kwa macho vipengele muhimu vya usalama vya msimbo wako:
+
+- Pitia printa ya [inheritance-graph](https://github.com/trailofbits/slither/wiki/Printer-documentation#inheritance-graph) ya Slither. Epuka kuficha kusiko kwa kukusudia na masuala ya urasmiishaji wa C3.
+- Pitia printa ya [function-summary](https://github.com/trailofbits/slither/wiki/Printer-documentation#function-summary) ya Slither. Huripoti mwonekano wa kazi na vidhibiti vya ufikiaji.
+- Pitia printa ya [vars-and-auth](https://github.com/trailofbits/slither/wiki/Printer-documentation#variables-written-and-authorization) ya Slither. Huripoti vidhibiti vya ufikiaji kwenye vigezo vya hali.
+
+Andika sifa muhimu za usalama na utumie jenereta za majaribio za kiotomatiki kuzitathmini:
+
+- Jifunze [kuandika sifa za usalama kwa msimbo wako](/developers/tutorials/guide-to-smart-contract-security-tools/). Ni ngumu mwanzoni, lakini ndiyo shughuli muhimu zaidi ili kufikia matokeo mazuri. Pia ni sharti la kutumia mbinu zozote za hali ya juu katika mafunzo haya.
+- Fafanua sifa za usalama katika Solidity, kwa matumizi na [Echidna](https://github.com/crytic/echidna) na [Manticore](https://manticore.readthedocs.io/en/latest/verifier.html). Zingatia mashine yako ya hali, vidhibiti vya ufikiaji, operesheni za hesabu, maingiliano ya nje, na ukubalifu wa viwango.
+- Fafanua sifa za usalama kwa [API ya Python ya Slither](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/). Zingatia urithi, utegemezi wa vigezo, vidhibiti vya ufikiaji, na masuala mengine ya kimuundo.
+- Endesha majaribio yako ya sifa kwa kila commit na [Crytic](https://crytic.io). Crytic inaweza kutumia na kutathmini majaribio ya sifa za usalama ili kila mtu kwenye timu yako aweze kuona kwa urahisi kwamba yamefaulu kwenye GitHub. Majaribio yanayofeli yanaweza kuzuia commit.
+
+Mwisho, kuwa mwangalifu na masuala ambayo zana za kiotomatiki haziwezi kupata kwa urahisi:
+
+- Ukosefu wa faragha: kila mtu mwingine anaweza kuona miamala yako wakati imepangwa kwenye foleni katika pool
+- Miamala ya front-running
+- Operesheni za kroptografia
+- Maingiliano hatarishi na vijenzi vya nje vya DeFi
+
+## Omba msaada {#ask-for-help}
+
+[Saa za ofisi za Ethereum](https://calendly.com/dan-trailofbits/office-hours) hufanyika kila Jumanne alasiri. Vipindi hivi vya saa 1, vya ana kwa ana ni fursa ya kutuuliza maswali yoyote uliyo nayo kuhusu usalama, kutatua matatizo kwa kutumia zana zetu, na kupata maoni kutoka kwa wataalamu kuhusu mbinu yako ya sasa. Tutakusaidia kupitia mwongozo huu.
+
+Jiunge na Slack yetu: [Empire Hacking](https://join.slack.com/t/empirehacking/shared_invite/zt-h97bbrj8-1jwuiU33nnzg67JcvIciUw). Tunapatikana kila wakati katika chaneli za #crytic na #ethereum ikiwa una maswali yoyote.
diff --git a/public/content/translations/sw/developers/tutorials/send-token-ethersjs/index.md b/public/content/translations/sw/developers/tutorials/send-token-ethersjs/index.md
new file mode 100644
index 00000000000..e79058d6716
--- /dev/null
+++ b/public/content/translations/sw/developers/tutorials/send-token-ethersjs/index.md
@@ -0,0 +1,210 @@
+---
+title: Kutuma Tokeni Kwa Kutumia ethers.js
+description: Mwongozo rahisi kwa wanaoanza wa kutuma tokeni kwa kutumia ethers.js.
+author: Kim YongJun
+tags: ["ETHERS.JS", "ERC-20", "TOKENS"]
+skill: beginner
+lang: sw
+published: 2021-04-06
+---
+
+## Tuma Tokeni Kwa Kutumia ethers.js(5.0) {#send-token}
+
+### Katika Somo Hili Utajifunza Jinsi ya {#you-learn-about}
+
+- Ingiza ethers.js
+- Hamisha tokeni
+- Weka bei ya gesi kulingana na hali ya msongamano wa mtandao
+
+### Ili Kuanza {#to-get-started}
+
+Ili kuanza, ni lazima kwanza tuingize maktaba ya ethers.js kwenye javascript yetu
+Jumuisha ethers.js(5.0)
+
+### Kusakinisha {#install-ethersjs}
+
+```shell
+/home/ricmoo> npm install --save ethers
+```
+
+ES6 katika Kivinjari
+
+```html
+
+```
+
+ES3(UMD) katika Kivinjari
+
+```html
+
+```
+
+### Vigezo {#param}
+
+1. **`contract_address`**: Anwani ya mkataba wa Tokeni (anwani ya mkataba inahitajika wakati tokeni unayotaka kuhamisha si ether)
+2. **`send_token_amount`**: Kiasi unachotaka kutuma kwa mpokeaji
+3. **`to_address`**: Anwani ya mpokeaji
+4. **`send_account`**: Anwani ya mtumaji
+5. **`private_key`**: Ufunguo binafsi wa mtumaji ili kusaini muamala na kuhamisha tokeni
+
+## Tangazo {#notice}
+
+`signTransaction(tx)` imeondolewa kwa sababu `sendTransaction()` inaifanya ndani kwa ndani.
+
+## Taratibu za Kutuma {#procedure}
+
+### 1. Unganisha na mtandao (testnet) {#connect-to-network}
+
+#### Weka Mtoa Huduma (Infura) {#set-provider}
+
+Unganisha na Ropsten testnet
+
+```javascript
+window.ethersProvider = new ethers.providers.InfuraProvider("ropsten")
+```
+
+### 2. Tengeneza mkoba {#create-wallet}
+
+```javascript
+let wallet = new ethers.Wallet(private_key)
+```
+
+### 3. Unganisha Mkoba na mtandao {#connect-wallet-to-net}
+
+```javascript
+let walletSigner = wallet.connect(window.ethersProvider)
+```
+
+### 4. Pata bei ya sasa ya gesi {#get-gas}
+
+```javascript
+window.ethersProvider.getGasPrice() // bei ya gesi
+```
+
+### 5. Bainisha Muamala {#define-transaction}
+
+Vigezo hivi vilivyobainishwa hapa chini vinategemea `send_token()`
+
+### Vigezo vya muamala {#transaction-params}
+
+1. **`send_account`**: anwani ya mtumaji wa tokeni
+2. **`to_address`**: anwani ya mpokeaji wa tokeni
+3. **`send_token_amount`**: kiasi cha tokeni za kutuma
+4. **`gas_limit`**: kikomo cha gesi
+5. **`gas_price`**: bei ya gesi
+
+[Tazama hapa chini jinsi ya kutumia](#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. Hamisha {#transfer}
+
+```javascript
+walletSigner.sendTransaction(tx).then((transaction) => {
+ console.dir(transaction)
+ alert("Kutuma kumekamilika!")
+})
+```
+
+## Jinsi ya kuitumia {#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
+)
+```
+
+### Imefanikiwa! {#success}
+
+
+
+## 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: ${gas_price}`)
+
+ if (contract_address) {
+ // utumaji wa tokeni wa jumla
+ let contract = new ethers.Contract(
+ contract_address,
+ send_abi,
+ walletSigner
+ )
+
+ // Tokeni ngapi?
+ let numberOfTokens = ethers.utils.parseUnits(send_token_amount, 18)
+ console.log(`numberOfTokens: ${numberOfTokens}`)
+
+ // Tuma tokeni
+ contract.transfer(to_address, numberOfTokens).then((transferResult) => {
+ console.dir(transferResult)
+ alert("tokeni imetumwa")
+ })
+ } // utumaji wa ether
+ 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("Kutuma kumekamilika!")
+ })
+ } catch (error) {
+ alert("imeshindwa kutuma!!")
+ }
+ }
+ })
+}
+```
diff --git a/public/content/translations/sw/developers/tutorials/sending-transactions-using-web3-and-alchemy/index.md b/public/content/translations/sw/developers/tutorials/sending-transactions-using-web3-and-alchemy/index.md
new file mode 100644
index 00000000000..7ee3c44556b
--- /dev/null
+++ b/public/content/translations/sw/developers/tutorials/sending-transactions-using-web3-and-alchemy/index.md
@@ -0,0 +1,208 @@
+---
+title: Kutuma Miamala Kwa Kutumia Web3
+description: "Huu ni mwongozo rahisi kwa wanaoanza wa kutuma miamala ya Ethereum kwa kutumia Web3. Kuna hatua tatu kuu ili kutuma muamala kwa mnyororo wa bloku wa Ethereum: tengeneza, saini, na tangaza. Tutapitia zote tatu."
+author: "Elan Halpern"
+tags: ["transactions", "web3.js", "alchemy"]
+skill: beginner
+lang: sw
+published: 2020-11-04
+source: Alchemy docs
+sourceUrl: https://www.alchemy.com/docs/how-to-send-transactions-on-ethereum
+---
+
+Huu ni mwongozo rahisi kwa wanaoanza wa kutuma miamala ya Ethereum kwa kutumia Web3. Kuna hatua tatu kuu ili kutuma muamala kwa mnyororo wa bloku wa Ethereum: tengeneza, saini, na tangaza. Tutapitia zote tatu, tunatumai tutajibu maswali yoyote ambayo unaweza kuwa nayo! Katika somo hili, tutatumia [Alchemy](https://www.alchemy.com/) kutuma miamala yetu kwa mnyororo wa Ethereum. Unaweza [kufungua akaunti ya Alchemy bila malipo hapa](https://auth.alchemyapi.io/signup).
+
+**KUMBUKA:** Mwongozo huu ni wa kusaini miamala yako kwenye _backend_ ya programu yako. Ikiwa unataka kuunganisha kusaini miamala yako kwenye frontend, angalia kuunganisha [Web3 na mtoa huduma wa kivinjari](https://docs.alchemy.com/reference/api-overview#with-a-browser-provider).
+
+## Mambo ya Msingi {#the-basics}
+
+Kama wasanidi programu wengi wa mnyororo wa bloku wanapoanza, huenda umefanya utafiti fulani kuhusu jinsi ya kutuma muamala (kitu ambacho kinapaswa kuwa rahisi sana) na ukakutana na miongozo mingi, kila mmoja ukisema mambo tofauti na kukuacha ukiwa umezidiwa na kuchanganyikiwa. Ikiwa uko katika hali hiyo, usijali; sote tulikuwa hapo wakati fulani! Kwa hivyo, kabla hatujaanza, hebu tuweke mambo machache sawa:
+
+### 1. Alchemy haihifadhi funguo zako za binafsi {#alchemy-does-not-store-your-private-keys}
+
+- Hii inamaanisha kuwa Alchemy haiwezi kusaini na kutuma miamala kwa niaba yako. Sababu ya hii ni kwa madhumuni ya usalama. Alchemy haitakuuliza kamwe kushiriki ufunguo wako binafsi, na hupaswi kamwe kushiriki ufunguo wako binafsi na nodi iliyohifadhiwa (au mtu yeyote kwa jambo hilo).
+- Unaweza kusoma kutoka kwenye mnyororo wa bloku kwa kutumia API ya msingi ya Alchemy, lakini ili kuandika humo utahitaji kutumia kitu kingine kusaini miamala yako kabla ya kuituma kupitia Alchemy (hii ni sawa kwa huduma nyingine yoyote ya [nodi](/developers/docs/nodes-and-clients/nodes-as-a-service/)).
+
+### 2. βSignerβ ni nini? {#what-is-a-signer}
+
+- Signers watasaini miamala kwa ajili yako kwa kutumia ufunguo wako binafsi. Katika somo hili tutakuwa tukitumia [Alchemy web3](https://docs.alchemyapi.io/alchemy/documentation/alchemy-web3) kusaini muamala wetu, lakini unaweza pia kutumia maktaba nyingine yoyote ya web3.
+- Kwenye frontend, mfano mzuri wa signer itakuwa [MetaMask](https://metamask.io/), ambayo itasaini na kutuma miamala kwa niaba yako.
+
+### 3. Kwa nini ninahitaji kusaini miamala yangu? {#why-do-i-need-to-sign-my-transactions}
+
+- Kila mtumiaji anayetaka kutuma muamala kwenye mtandao wa Ethereum lazima asaini muamala (kwa kutumia ufunguo wake binafsi), ili kuthibitisha kuwa chimbuko la muamala huo ndilo linavyodaiwa kuwa.
+- Ni muhimu sana kulinda ufunguo huu binafsi, kwani kuwa na ufikiaji kwayo kunatoa udhibiti kamili juu ya akaunti yako ya Ethereum, kukuruhusu wewe (au mtu yeyote mwenye ufikiaji) kufanya miamala kwa niaba yako.
+
+### 4. Ninalindaje ufunguo wangu binafsi? {#how-do-i-protect-my-private-key}
+
+- Kuna njia nyingi za kulinda ufunguo wako binafsi na kuutumia kutuma miamala. Katika somo hili tutakuwa tukitumia faili ya `.env`. Hata hivyo, unaweza pia kutumia mtoa huduma tofauti anayehifadhi funguo za binafsi, kutumia faili ya keystore, au chaguo zingine.
+
+### 5. Kuna tofauti gani kati ya `eth_sendTransaction` na `eth_sendRawTransaction`? {#difference-between-send-and-send-raw}
+
+`eth_sendTransaction` na `eth_sendRawTransaction` zote ni kazi za API za Ethereum zinazotangaza muamala kwa mtandao wa Ethereum ili uongezwe kwenye bloku ya baadaye. Zinatofautiana katika jinsi zinavyoshughulikia usainishaji wa miamala.
+
+- [`eth_sendTransaction`](https://docs.web3js.org/api/web3-eth/function/sendTransaction) hutumika kwa kutuma miamala _isiyosainiwa_, ambayo inamaanisha nodi unayoituma lazima idhibiti ufunguo wako binafsi ili iweze kusaini muamala kabla ya kuutangaza kwenye mnyororo. Kwa kuwa Alchemy haishikilii funguo za binafsi za mtumiaji, hawasaidii njia hii.
+- [`eth_sendRawTransaction`](https://docs.alchemyapi.io/documentation/alchemy-api-reference/json-rpc#eth_sendrawtransaction) hutumika kutangaza miamala ambayo tayari imesainiwa. Hii inamaanisha kwanza lazima utumie [`signTransaction(tx, private_key)`](https://docs.web3js.org/api/web3-eth-accounts/function/signTransaction), kisha upitishe matokeo katika `eth_sendRawTransaction`.
+
+Unapotumia web3, `eth_sendRawTransaction` hupatikana kwa kuita kazi [web3.eth.sendSignedTransaction](https://docs.web3js.org/api/web3-eth/function/sendSignedTransaction).
+
+Hiki ndicho tutakachokuwa tukitumia katika somo hili.
+
+### 6. Maktaba ya web3 ni nini? {#what-is-the-web3-library}
+
+- Web3.js ni maktaba inayofunika miito ya kawaida ya JSON-RPC ambayo ni ya kawaida sana kutumika katika usanidi programu wa Ethereum.
+- Kuna maktaba nyingi za web3 za lugha tofauti. Katika somo hili tutakuwa tukitumia [Alchemy Web3](https://docs.alchemy.com/reference/api-overview) ambayo imeandikwa kwa JavaScript. Unaweza kuangalia chaguo zingine [hapa](https://docs.alchemyapi.io/guides/getting-started#other-web3-libraries) kama [ethers.js](https://docs.ethers.org/v5/).
+
+Sawa, sasa kwa kuwa tumeshughulikia baadhi ya maswali haya, hebu tuendelee na somo. Jisikie huru kuuliza maswali wakati wowote katika [discord](https://discord.gg/gWuC7zB) ya Alchemy!
+
+### 7. Jinsi ya kutuma miamala salama, iliyoboreshwa kwa gesi, na ya faragha? {#how-to-send-secure-gas-optimized-and-private-transactions}
+
+- [Alchemy ina seti ya APIs za Transact](https://docs.alchemy.com/reference/transact-api-quickstart). Unaweza kutumia hizi kutuma miamala iliyoimarishwa, kuiga miamala kabla haijatokea, kutuma miamala ya faragha, na kutuma miamala iliyoboreshwa kwa gesi
+- Unaweza pia kutumia [API ya Notify](https://docs.alchemy.com/docs/alchemy-notify) kuarifiwa muamala wako unapotolewa kwenye mempool na kuongezwa kwenye mnyororo
+
+**KUMBUKA:** Mwongozo huu unahitaji akaunti ya Alchemy, anwani ya Ethereum au mkoba wa MetaMask, NodeJs, na npm zilizosakinishwa. Ikiwa sivyo, fuata hatua hizi:
+
+1. [Fungua akaunti ya Alchemy bila malipo](https://auth.alchemyapi.io/signup)
+2. [Fungua akaunti ya MetaMask](https://metamask.io/) (au pata anwani ya Ethereum)
+3. [Fuata hatua hizi ili kusakinisha NodeJs na NPM](https://docs.alchemy.com/alchemy/guides/alchemy-for-macs)
+
+## Hatua za Kutuma Muamala wako {#steps-to-sending-your-transaction}
+
+### 1. Fungua programu ya Alchemy kwenye testnet ya Sepolia {#create-an-alchemy-app-on-the-sepolia-testnet}
+
+Nenda kwenye [Dashibodi yako ya Alchemy](https://dashboard.alchemyapi.io/) na uunde programu mpya, ukichagua Sepolia (au testnet nyingine yoyote) kwa mtandao wako.
+
+### 2. Omba ETH kutoka kwa bomba la Sepolia {#request-eth-from-sepolia-faucet}
+
+Fuata maagizo kwenye [bomba la Sepolia la Alchemy](https://www.sepoliafaucet.com/) ili kupokea ETH. Hakikisha unajumuisha anwani yako ya Ethereum ya **Sepolia** (kutoka MetaMask) na si mtandao mwingine. Baada ya kufuata maagizo, hakikisha tena kuwa umepokea ETH kwenye mkoba wako.
+
+### 3. Unda saraka mpya ya mradi na `cd` ndani yake {#create-a-new-project-direction}
+
+Unda saraka mpya ya mradi kutoka kwa mstari wa amri (terminal kwa macs) na uingie ndani yake:
+
+```
+mkdir sendtx-example
+cd sendtx-example
+```
+
+### 4. Sakinisha Alchemy Web3 (au maktaba yoyote ya web3) {#install-alchemy-web3}
+
+Endesha amri ifuatayo katika saraka yako ya mradi ili kusakinisha [Alchemy Web3](https://docs.alchemy.com/reference/api-overview):
+
+Kumbuka, ikiwa ungependa kutumia maktaba ya ethers.js, [fuata maagizo hapa](https://docs.alchemy.com/docs/how-to-send-transactions-on-ethereum).
+
+```
+npm install @alch/alchemy-web3
+```
+
+### 5. Sakinisha dotenv {#install-dotenv}
+
+Tutatumia faili ya `.env` kuhifadhi kwa usalama ufunguo wetu wa API na ufunguo binafsi.
+
+```
+npm install dotenv --save
+```
+
+### 6. Tengeneza faili ya `.env` {#create-the-dotenv-file}
+
+Tengeneza faili ya `.env` katika saraka yako ya mradi na uongeze yafuatayo (ukibadilisha "`your-api-url`" na "`your-private-key`")
+
+- Ili kupata URL yako ya API ya Alchemy, nenda kwenye ukurasa wa maelezo ya programu uliyotengeneza kwenye dashibodi yako, bofya "View Key" kwenye kona ya juu kulia, na uchukue URL ya HTTP.
+- Ili kupata ufunguo wako binafsi kwa kutumia MetaMask, angalia [mwongozo huu](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"
+```
+
+
+
+
+Usitume .env! Tafadhali hakikisha kamwe hushiriki au kufichua faili yako ya .env na mtu yeyote, kwani unahatarisha siri zako kwa kufanya hivyo. Ikiwa unatumia udhibiti wa toleo, ongeza .env yako kwenye faili ya gitignore.
+
+
+
+
+### 7. Tengeneza faili ya `sendTx.js` {#create-sendtx-js}
+
+Safi, sasa kwa kuwa data yetu nyeti imelindwa katika faili ya `.env`, hebu tuanze kuandika msimbo. Kwa mfano wetu wa kutuma muamala, tutakuwa tukituma ETH kurudi kwenye bomba la Sepolia.
+
+Tengeneza faili ya `sendTx.js`, ambapo tutasanidi na kutuma muamala wetu wa mfano, na kuongeza mistari ifuatayo ya msimbo ndani yake:
+
+```
+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: badilisha anwani hii na anwani yako ya umma
+
+ const nonce = await web3.eth.getTransactionCount(myAddress, 'latest'); // nonce huanza kuhesabu kutoka 0
+
+ const transaction = {
+ 'to': '0x31B98D14007bDEe637298086988A0bBd31184523', // anwani ya bomba la kurudisha eth
+ 'value': 1000000000000000000, // ETH 1
+ 'gas': 30000,
+ 'nonce': nonce,
+ // sehemu ya data ya hiari kutuma ujumbe au kutekeleza mkataba-erevu
+ };
+
+ const signedTx = await web3.eth.accounts.signTransaction(transaction, PRIVATE_KEY);
+
+ web3.eth.sendSignedTransaction(signedTx.rawTransaction, function(error, hash) {
+ if (!error) {
+ console.log("π Hashi ya muamala wako ni: ", hash, "\n Angalia Mempool ya Alchemy ili kuona hali ya muamala wako!");
+ } else {
+ console.log("βKitu kilienda mrama wakati wa kuwasilisha muamala wako:", error)
+ }
+ });
+}
+
+main();
+```
+
+Hakikisha unabadilisha anwani kwenye **mstari wa 6** na anwani yako mwenyewe ya umma.
+
+Sasa, kabla ya kuanza kuendesha msimbo huu, hebu tuzungumzie baadhi ya vipengele hapa.
+
+- `nonce` : Ufafanuzi wa nonce hutumika kufuatilia idadi ya miamala iliyotumwa kutoka kwa anwani yako. Tunahitaji hii kwa madhumuni ya usalama na kuzuia [mashambulizi ya kurudia](https://docs.alchemyapi.io/resources/blockchain-glossary#account-nonce). Ili kupata idadi ya miamala iliyotumwa kutoka kwa anwani yako tunatumia [getTransactionCount](https://docs.alchemyapi.io/documentation/alchemy-api-reference/json-rpc#eth_gettransactioncount).
+- `transaction`: Kitu cha muamala kina vipengele vichache tunavyohitaji kubainisha
+ - `to`: Hii ni anwani tunayotaka kutuma ETH. Katika kesi hii, tunatuma ETH kurudi kwenye [bomba la Sepolia](https://sepoliafaucet.com/) ambalo tuliomba awali.
+ - `value`: Hii ni kiasi tunachotaka kutuma, kilichoainishwa katika Wei ambapo Wei 10^18 = ETH 1
+ - `gas`: Kuna njia nyingi za kuamua kiasi sahihi cha gesi cha kujumuisha na muamala wako. Alchemy hata ina [webhook ya bei ya gesi](https://docs.alchemyapi.io/guides/alchemy-notify#address-activity-1) kukuarifu bei ya gesi inaposhuka ndani ya kizingiti fulani. Kwa miamala ya Mtandao Mkuu, ni mazoea mazuri kuangalia kikadiriaji cha gesi kama [ETH Gas Station](https://ethgasstation.info/) ili kuamua kiasi sahihi cha gesi cha kujumuisha. 21000 ni kiasi cha chini cha gesi ambacho operesheni kwenye Ethereum itatumia, kwa hivyo ili kuhakikisha muamala wetu utatekelezwa tunaweka 30000 hapa.
+ - `nonce`: tazama ufafanuzi wa nonce hapo juu. Nonce huanza kuhesabu kutoka sifuri.
+ - [SI LAZIMA] data: Hutumika kutuma taarifa za ziada na uhamisho wako, au kuita mkataba-erevu, hauhitajiki kwa uhamisho wa salio, angalia dokezo hapa chini.
+- `signedTx`: Ili kusaini kitu chetu cha muamala tutatumia mbinu ya `signTransaction` na `PRIVATE_KEY` yetu
+- `sendSignedTransaction`: Mara tu tunapokuwa na muamala uliosainiwa, tunaweza kuutuma ili ujumuishwe katika bloku inayofuata kwa kutumia `sendSignedTransaction`
+
+**Dokezo kuhusu data**
+Kuna aina mbili kuu za miamala zinazoweza kutumwa katika Ethereum.
+
+- Uhamisho wa salio: Tuma ETH kutoka anwani moja kwenda nyingine. Hakuna sehemu ya data inayohitajika, hata hivyo, ikiwa ungependa kutuma taarifa za ziada pamoja na muamala wako, unaweza kujumuisha taarifa hiyo katika umbizo la HEX katika sehemu hii.
+ - Kwa mfano, tuseme tulitaka kuandika hashi ya hati ya IPFS kwenye mnyororo wa Ethereum ili kuipa muhuri wa muda usioweza kubadilika. Sehemu yetu ya data inapaswa kuonekana kama data: `web3.utils.toHex('hashi ya IPFS')`. Na sasa mtu yeyote anaweza kuuliza mnyororo na kuona ni lini hati hiyo iliongezwa.
+- Muamala wa mkataba-erevu: Tekeleza msimbo fulani wa mkataba-erevu kwenye mnyororo. Katika kesi hii, sehemu ya data inapaswa kuwa na kazi mahiri unayotaka kutekeleza, pamoja na vigezo vyovyote.
+ - Kwa mfano wa vitendo, angalia Hatua ya 8 katika [Somo hili la Hello World](https://docs.alchemyapi.io/alchemy/tutorials/hello-world-smart-contract#step-8-create-the-transaction).
+
+### 8. Endesha msimbo kwa kutumia `node sendTx.js` {#run-the-code-using-node-sendtx-js}
+
+Rudi kwenye terminal yako au mstari wa amri na uendeshe:
+
+```
+node sendTx.js
+```
+
+### 9. Angalia muamala wako katika Mempool {#see-your-transaction-in-the-mempool}
+
+Fungua [ukurasa wa Mempool](https://dashboard.alchemyapi.io/mempool) kwenye dashibodi yako ya Alchemy na uchuje kwa programu uliyounda ili kupata muamala wako. Hapa ndipo tunaweza kutazama mpito wa muamala wetu kutoka hali ya kusubiri hadi hali ya kuchimbwa (ikiwa imefanikiwa) au hali ya kuachwa ikiwa haikufanikiwa. Hakikisha unaiweka kwenye "All" ili uweze kunasa miamala ya "mined", "pending", na "dropped". Unaweza pia kutafuta muamala wako kwa kutafuta miamala iliyotumwa kwa anwani `0x31b98d14007bdee637298086988a0bbd31184523` .
+
+Ili kuona maelezo ya muamala wako mara tu umeupata, chagua hashi ya tx, ambayo inapaswa kukupeleka kwenye mwonekano unaofanana na huu:
+
+
+
+Kutoka hapo unaweza kuona muamala wako kwenye Etherscan kwa kubofya ikoni iliyozungushiwa duara nyekundu!
+
+**Yippieeee!** Umetuma muamala wako wa kwanza wa Ethereum kwa kutumia Alchemy π\*\*
+
+_Kwa maoni na mapendekezo kuhusu mwongozo huu, tafadhali mtumie Elan ujumbe kwenye [Discord](https://discord.gg/A39JVCM) ya Alchemy!_
+
+_Ilichapishwa awali katika [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/sw/developers/tutorials/server-components/index.md b/public/content/translations/sw/developers/tutorials/server-components/index.md
new file mode 100644
index 00000000000..ffab39ab721
--- /dev/null
+++ b/public/content/translations/sw/developers/tutorials/server-components/index.md
@@ -0,0 +1,295 @@
+---
+title: "Vipengele vya seva na mawakala kwa ajili ya programu za web3"
+description: Baada ya kusoma mafunzo haya, utaweza kuandika seva za TypeScript zinazosikiliza matukio kwenye mnyororo wa bloku na kujibu ipasavyo kwa miamala yao wenyewe. Hii itakuwezesha kuandika programu za kati (kwa sababu seva ni mahali pa kushindwa), lakini inaweza kuingiliana na mashirika ya web3. Mbinu hizi hizi zinaweza pia kutumika kuandika wakala anayeshughulikia matukio ya onchain bila kuhusisha binadamu.
+
+author: Ori Pomerantz
+lang: sw
+tags: ["agent", "server", "offchain"]
+skill: beginner
+published: 2024-07-15
+---
+
+## Utangulizi {#introduction}
+
+Katika hali nyingi, programu isiyo ya kati hutumia seva kusambaza programu, lakini mwingiliano wote halisi hutokea kati ya mteja (kawaida, kivinjari cha wavuti) na mnyororo wa bloku.
+
+
+
+Hata hivyo, kuna baadhi ya matukio ambapo programu ingenufaika kutokana na kuwa na kipengele cha seva kinachofanya kazi kivyake. Seva kama hiyo itaweza kujibu matukio, na maombi yanayotoka kwenye vyanzo vingine, kama vile API, kwa kutoa miamala.
+
+
+
+Kuna kazi kadhaa zinazowezekana ambazo seva kama hiyo inaweza kutimiza.
+
+- Mmiliki wa hali ya siri. Katika michezo ya kubahatisha mara nyingi ni muhimu kutokuwa na taarifa zote ambazo mchezo unajua zinazopatikana kwa wachezaji. Hata hivyo, _hakuna siri kwenye mnyororo wa bloku_, taarifa yoyote iliyo kwenye mnyororo wa bloku ni rahisi kwa yeyote kuigundua. Kwa hiyo, kama sehemu ya hali ya mchezo inapaswa kuwekwa siri, ni lazima ihifadhiwe mahali pengine (na ikiwezekana athari za hali hiyo zithibitishwe kwa kutumia [uthibitisho wa zero-knowledge](/zero-knowledge-proofs)).
+
+- Oracle ya kati. Ikiwa hisa ni za chini vya kutosha, seva ya nje inayosoma baadhi ya taarifa mtandaoni na kisha kuichapisha kwenye chaini inaweza kuwa nzuri ya kutosha kutumia kama [oracle](/developers/docs/oracles/).
+
+- Wakala. Hakuna kinachotokea kwenye mnyororo wa bloku bila muamala wa kuiwasha. Seva inaweza kutenda kwa niaba ya mtumiaji kutekeleza vitendo kama vile [arbitrage](/developers/docs/mev/#mev-examples-dex-arbitrage) wakati fursa inapojitokeza.
+
+## Programu ya mfano {#sample-program}
+
+Unaweza kuona seva ya mfano [kwenye github](https://github.com/qbzzt/20240715-server-component). Seva hii inasikiliza matukio yanayotoka kwenye [mkataba huu](https://eth-holesky.blockscout.com/address/0xB8f6460Dc30c44401Be26B0d6eD250873d8a50A6?tab=contract_code), toleo lililobadilishwa la Greeter ya Hardhat. Wakati salamu inabadilishwa, inairudisha kama ilivyokuwa.
+
+Ili kuiendesha:
+
+1. Kloni hifadhi.
+
+ ```sh copy
+ git clone https://github.com/qbzzt/20240715-server-component.git
+ cd 20240715-server-component
+ ```
+
+2. Sakinisha vifurushi vinavyohitajika. Kama huna tayari, [sakinisha Node kwanza](https://nodejs.org/en/download/package-manager).
+
+ ```sh copy
+ npm install
+ ```
+
+3. Hariri `.env` ili kubainisha ufunguo binafsi wa akaunti iliyo na ETH kwenye testnet ya Holesky. Ikiwa huna ETH kwenye Holesky, unaweza [kutumia bomba hili](https://holesky-faucet.pk910.de/).
+
+ ```sh filename=".env" copy
+ PRIVATE_KEY=0x
+ ```
+
+4. Anzisha seva.
+
+ ```sh copy
+ npm start
+ ```
+
+5. Nenda kwenye [kichunguzi cha bloku](https://eth-holesky.blockscout.com/address/0xB8f6460Dc30c44401Be26B0d6eD250873d8a50A6?tab=write_contract), na ukitumia anwani tofauti na ile iliyo na ufunguo binafsi rekebisha salamu. Tazama kwamba salamu inarekebishwa kiotomatiki.
+
+### Inafanyaje kazi? {#how-it-works}
+
+Njia rahisi zaidi ya kuelewa jinsi ya kuandika kipengele cha seva ni kupitia sampuli mstari kwa mstari.
+
+#### `src/app.ts` {#src-app-ts}
+
+Idadi kubwa ya programu imo ndani ya [`src/app.ts`](https://github.com/qbzzt/20240715-server-component/blob/main/src/app.ts).
+
+##### Kuunda vitu vinavyohitajika
+
+```typescript
+import {
+ createPublicClient,
+ createWalletClient,
+ getContract,
+ http,
+ Address,
+} from "viem"
+```
+
+Hizi ni huluki za [Viem](https://viem.sh/) tunazohitaji, kazi na [aina ya `Anwani`](https://viem.sh/docs/glossary/types#address). Seva hii imeandikwa kwa [TypeScript](https://www.typescriptlang.org/), ambayo ni nyongeza kwa JavaScript inayoifanya iwe na [aina madhubuti](https://en.wikipedia.org/wiki/Strong_and_weak_typing).
+
+```typescript
+import { privateKeyToAccount } from "viem/accounts"
+```
+
+[Kitendakazi hiki](https://viem.sh/docs/accounts/privateKey) kinaturuhusu kutoa maelezo ya mkoba, ikiwa ni pamoja na anwani, inayolingana na ufunguo binafsi.
+
+```typescript
+import { holesky } from "viem/chains"
+```
+
+Ili kutumia mnyororo wa bloku katika Viem unahitaji kuingiza ufafanuzi wake. Katika kesi hii, tunataka kuunganisha kwenye mnyororo wa bloku wa majaribio wa [Holesky](https://github.com/eth-clients/holesky).
+
+```typescript
+// Hivi ndivyo tunavyoongeza ufafanuzi katika .env kwa process.env.
+import * as dotenv from "dotenv"
+dotenv.config()
+```
+
+Hivi ndivyo tunavyosoma `.env` katika mazingira. Tunaihitaji kwa ufunguo binafsi (tazama baadaye).
+
+```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
+```
+
+Ili kutumia mkataba tunahitaji anwani yake na [ABI](/glossary/#abi) yake. Tunatoa zote mbili hapa.
+
+Katika JavaScript (na kwa hiyo TypeScript) huwezi kugawa thamani mpya kwa kistari, lakini _unaweza_ kurekebisha kitu kilichohifadhiwa ndani yake. Kwa kutumia kiambishi tamati `as const` tunaiambia TypeScript kwamba orodha yenyewe ni ya kudumu na haiwezi kubadilishwa.
+
+```typescript
+const publicClient = createPublicClient({
+ chain: holesky,
+ transport: http(),
+})
+```
+
+Unda [mteja wa umma](https://viem.sh/docs/clients/public.html) wa Viem. Wateja wa umma hawana ufunguo binafsi ulioambatanishwa, na kwa hivyo hawawezi kutuma miamala. Wanaweza kuita [kazi za `view`](https://www.tutorialspoint.com/solidity/solidity_view_functions.htm), kusoma salio za akaunti, n.k.
+
+```typescript
+const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`)
+```
+
+Vigezo vya mazingira vinapatikana katika [`process.env`](https://www.totaltypescript.com/how-to-strongly-type-process-env). Hata hivyo, TypeScript ina aina madhubuti. Kigezo cha mazingira kinaweza kuwa mfuatano wowote, au tupu, kwa hivyo aina ya kigezo cha mazingira ni `string | undefined`. Hata hivyo, ufunguo umefafanuliwa katika Viem kama `0x${string}` (`0x` ikifuatiwa na mfuatano). Hapa tunaiambia TypeScript kwamba kigezo cha mazingira cha `PRIVATE_KEY` kitakuwa cha aina hiyo. Ikiwa sivyo, tutapata hitilafu ya muda wa utekelezaji.
+
+Kitendakazi cha [`privateKeyToAccount`](https://viem.sh/docs/accounts/privateKey) kisha hutumia ufunguo huu binafsi kuunda kitu kamili cha akaunti.
+
+```typescript
+const walletClient = createWalletClient({
+ account,
+ chain: holesky,
+ transport: http(),
+})
+```
+
+Ifuatayo, tunatumia kitu cha akaunti kuunda [mteja wa mkoba](https://viem.sh/docs/clients/wallet). Mteja huyu ana ufunguo binafsi na anwani, kwa hivyo inaweza kutumika kutuma miamala.
+
+```typescript
+const greeter = getContract({
+ address: greeterAddress,
+ abi: greeterABI,
+ client: { public: publicClient, wallet: walletClient },
+})
+```
+
+Sasa kwa kuwa tuna mahitaji yote, hatimaye tunaweza kuunda [mfano wa mkataba](https://viem.sh/docs/contract/getContract). Tutatumia mfano huu wa mkataba kuwasiliana na mkataba wa onchain.
+
+##### Kusoma kutoka kwenye mnyororo wa bloku
+
+```typescript
+console.log(`Current greeting:`, await greeter.read.greet())
+```
+
+Kazi za mkataba ambazo zinasomwa tu ([`view`](https://www.tutorialspoint.com/solidity/solidity_view_functions.htm) na [`pure`](https://www.tutorialspoint.com/solidity/solidity_pure_functions.htm)) zinapatikana chini ya `read`. Katika kisa hiki, tunaitumia kufikia kitendakazi cha [`greet`](https://eth-holesky.blockscout.com/address/0xB8f6460Dc30c44401Be26B0d6eD250873d8a50A6?tab=read_contract#cfae3217), ambacho hurudisha salamu.
+
+JavaScript ina uzi mmoja, kwa hivyo tunapoanzisha mchakato mrefu tunahitaji [kubainisha kuwa tunafanya hivyo kwa njia isiyosawazishwa](https://eloquentjavascript.net/11_async.html#h-XvLsfAhtsE). Kuita mnyororo wa bloku, hata kwa operesheni ya kusoma tu, inahitaji safari ya kwenda na kurudi kati ya kompyuta na nodi ya mnyororo wa bloku. Hiyo ndiyo sababu tunabainisha hapa msimbo unahitaji `kusubiri` matokeo.
+
+Ikiwa una nia ya jinsi hii inavyofanya kazi unaweza [kusoma kuihusu hapa](https://www.w3schools.com/js/js_promise.asp), lakini kwa vitendo unachohitaji kujua ni kwamba `unasubiri` matokeo ukianza operesheni inayochukua muda mrefu, na kwamba kitendakazi chochote kinachofanya hivi lazima kitangazwe kama `async`.
+
+##### Kutoa miamala
+
+```typescript
+const setGreeting = async (greeting: string): Promise => {
+```
+
+Hiki ndicho kitendakazi unachoita ili kutoa muamala unaobadilisha salamu. Kwa kuwa hii ni operesheni ndefu, kitendakazi kinatangazwa kama `async`. Kwa sababu ya utekelezaji wa ndani, kitendakazi chochote cha `async` kinahitaji kurudisha kitu cha `Promise`. Katika kesi hii, `Promise` inamaanisha kuwa hatubainishi nini hasa kitarudishwa katika `Promise`.
+
+```typescript
+const txHash = await greeter.write.setGreeting([greeting])
+```
+
+Sehemu ya `write` ya mfano wa mkataba ina kazi zote zinazoandika kwenye hali ya mnyororo wa bloku (zile zinazohitaji kutuma muamala), kama vile [`setGreeting`](https://eth-holesky.blockscout.com/address/0xB8f6460Dc30c44401Be26B0d6eD250873d8a50A6?tab=write_contract#a4136862). Vigezo, ikiwa vipo, vinatolewa kama orodha, na kitendakazi hurudisha hashi ya muamala.
+
+```typescript
+ console.log(`Working on a fix, see https://eth-holesky.blockscout.com/tx/${txHash}`)
+
+ return txHash
+}
+```
+
+Ripoti hashi ya muamala (kama sehemu ya URL kwa kichunguzi cha bloku ili kuitazama) na uirudishe.
+
+##### Kujibu matukio
+
+```typescript
+greeter.watchEvent.SetGreeting({
+```
+
+[Kitendakazi cha `watchEvent`](https://viem.sh/docs/actions/public/watchEvent) hukuruhusu kubainisha kuwa kitendakazi kitaendeshwa tukio linapotolewa. Ikiwa unajali tu aina moja ya tukio (katika kesi hii, `SetGreeting`), unaweza kutumia sintaksia hii kujizuia kwa aina hiyo ya tukio.
+
+```typescript
+ onLogs: logs => {
+```
+
+Kitendakazi cha `onLogs` huitwa kunapokuwa na maingizo ya kumbukumbu. Katika Ethereum "log" na "tukio" kawaida hubadilishana.
+
+```typescript
+console.log(
+ `Address ${logs[0].args.sender} changed the greeting to ${logs[0].args.greeting}`
+)
+```
+
+Kunaweza kuwa na matukio mengi, lakini kwa urahisi tunajali tu lile la kwanza. `logs[0].args` ni hoja za tukio, katika kesi hii `sender` na `greeting`.
+
+```typescript
+ if (logs[0].args.sender != account.address)
+ setGreeting(`${account.address} insists on it being Hello!`)
+ }
+})
+```
+
+Ikiwa mtumaji _sio_ seva hii, tumia `setGreeting` kubadilisha salamu.
+
+#### `package.json` {#package-json}
+
+[Faili hii](https://github.com/qbzzt/20240715-server-component/blob/main/package.json) inadhibiti usanidi wa [Node.js](https://nodejs.org/en). Makala hii inaelezea tu ufafanuzi muhimu.
+
+```json
+{
+ "main": "dist/index.js",
+```
+
+Ufafanuzi huu unabainisha faili gani ya JavaScript itaendeshwa.
+
+```json
+ "scripts": {
+ "start": "tsc && node dist/app.js",
+ },
+```
+
+Hati ni vitendo mbalimbali vya programu. Katika kesi hii, pekee tuliyo nayo ni `start`, ambayo inakusanya na kisha kuendesha seva. Amri ya `tsc` ni sehemu ya kifurushi cha `typescript` na inakusanya TypeScript kuwa JavaScript. Ikiwa unataka kuiendesha mwenyewe, iko katika `node_modules/.bin`. Amri ya pili inaendesha seva.
+
+```json
+ "type": "module",
+```
+
+Kuna aina nyingi za programu za Node za JavaScript. Aina ya `module` inaturuhusu kuwa na `await` katika msimbo wa kiwango cha juu, ambayo ni muhimu unapofanya operesheni za polepole (na kwa hivyo zisizosawazishwa).
+
+```json
+ "devDependencies": {
+ "@types/node": "^20.14.2",
+ "typescript": "^5.4.5"
+ },
+```
+
+Hivi ni vifurushi vinavyohitajika tu kwa ajili ya maendeleo. Hapa tunahitaji `typescript` na kwa sababu tunaitumia na Node.js, tunapata pia aina za vigezo na vitu vya Node, kama vile `process`. [Nukuu ya `^`](https://github.com/npm/node-semver?tab=readme-ov-file#caret-ranges-123-025-004) inamaanisha toleo hilo au toleo la juu zaidi ambalo halina mabadiliko ya kuvunja. Tazama [hapa](https://semver.org) kwa habari zaidi kuhusu maana ya nambari za toleo.
+
+```json
+ "dependencies": {
+ "dotenv": "^16.4.5",
+ "viem": "2.14.1"
+ }
+}
+```
+
+Hivi ni vifurushi vinavyohitajika wakati wa utekelezaji, wakati wa kuendesha `dist/app.js`.
+
+## Hitimisho {#conclusion}
+
+Seva ya kati tuliyoiunda hapa inafanya kazi yake, ambayo ni kutenda kama wakala kwa mtumiaji. Mtu mwingine yeyote anayetaka mfumo mtawanyo wa kimamlaka uendelee kufanya kazi na yuko tayari kutumia gesi anaweza kuendesha mfano mpya wa seva na anwani yake mwenyewe.
+
+Hata hivyo, hii inafanya kazi tu wakati vitendo vya seva ya kati vinaweza kuthibitishwa kwa urahisi. Ikiwa seva ya kati ina habari yoyote ya hali ya siri, au inafanya hesabu ngumu, ni chombo cha kati ambacho unahitaji kuamini ili kutumia programu, ambacho ndicho hasa minyororo ya bloku inajaribu kuepuka. Katika makala ya baadaye napanga kuonyesha jinsi ya kutumia [uthibitisho wa zero-knowledge](/zero-knowledge-proofs) ili kutatua tatizo hili.
+
+[Tazama hapa kwa kazi zangu zaidi](https://cryptodocguy.pro/).