ప్రధాన కంటెంట్‌కు దాటవేయి

Optimism ప్రామాణిక వారధి కాంట్రాక్ట్ వాక్‌త్రూ

Solidity
వారధి
లేయర్ 2 (l2)
మధ్యస్థ స్థాయి
ఓరి పోమెరాంట్జ్
30 మార్చి, 2022
29 నిమిషాల పఠనం

Optimism (opens in a new tab) అనేది ఒక ఆశావాద రోలప్. ఆశావాద రోల్అప్‌లు ఎథీరియం మెయిన్‌నెట్ (దీనిని లేయర్ 1 (l1) అని కూడా పిలుస్తారు) కంటే చాలా తక్కువ ధరకు లావాదేవీలను ప్రాసెస్ చేయగలవు, ఎందుకంటే నెట్‌వర్క్‌లోని ప్రతి నోడ్‌కు బదులుగా లావాదేవీలు కొన్ని నోడ్‌ల ద్వారా మాత్రమే ప్రాసెస్ చేయబడతాయి. అదే సమయంలో, డేటా అంతా l1కి వ్రాయబడుతుంది, కాబట్టి మెయిన్‌నెట్ యొక్క అన్ని సమగ్రత మరియు లభ్యత హామీలతో ప్రతిదీ నిరూపించబడుతుంది మరియు పునర్నిర్మించబడుతుంది.

Optimism (లేదా ఏదైనా ఇతర l2)లో l1 ఆస్తులను ఉపయోగించడానికి, ఆస్తులను వారధి ద్వారా పంపాలి. దీన్ని సాధించడానికి ఒక మార్గం ఏమిటంటే, వినియోగదారులు l1లో ఆస్తులను (ETH మరియు ERC-20 టోకెన్‌లు అత్యంత సాధారణమైనవి) లాక్ చేయడం మరియు l2లో ఉపయోగించడానికి సమానమైన ఆస్తులను స్వీకరించడం. చివరికి, వాటిని కలిగి ఉన్నవారు వాటిని తిరిగి l1కి వారధి ద్వారా పంపాలనుకోవచ్చు. ఇలా చేస్తున్నప్పుడు, ఆస్తులు l2లో దహనం చేయబడతాయి మరియు ఆ తర్వాత l1లో వినియోగదారుకు తిరిగి విడుదల చేయబడతాయి.

Optimism ప్రామాణిక వారధి (opens in a new tab) ఈ విధంగానే పనిచేస్తుంది. ఈ కథనంలో, ఆ వారధి ఎలా పనిచేస్తుందో చూడటానికి దాని సోర్స్ కోడ్‌ను పరిశీలిస్తాము మరియు బాగా వ్రాయబడిన Solidity కోడ్‌కు ఉదాహరణగా దానిని అధ్యయనం చేస్తాము.

నియంత్రణ ప్రవాహాలు

వారధికి రెండు ప్రధాన ప్రవాహాలు ఉన్నాయి:

  • డిపాజిట్ (l1 నుండి l2కి)
  • ఉపసంహరణ (l2 నుండి l1కి)

డిపాజిట్ ప్రవాహం

లేయర్ 1 (l1)

  1. ERC-20ని డిపాజిట్ చేస్తుంటే, డిపాజిట్ చేసేవారు డిపాజిట్ చేయబడుతున్న మొత్తాన్ని ఖర్చు చేయడానికి వారధికి అనుమతి మొత్తం ఇస్తారు
  2. డిపాజిట్ చేసేవారు l1 వారధిని పిలుస్తారు (depositERC20, depositERC20To, depositETH, లేదా depositETHTo)
  3. l1 వారధి వారధి చేయబడిన ఆస్తిని స్వాధీనం చేసుకుంటుంది
    • ETH: కాల్‌లో భాగంగా డిపాజిట్ చేసేవారి ద్వారా ఆస్తి బదిలీ చేయబడుతుంది
    • ERC-20: డిపాజిట్ చేసేవారు అందించిన అనుమతి మొత్తం ఉపయోగించి వారధి ఆస్తిని తనకు తానుగా బదిలీ చేసుకుంటుంది
  4. l1 వారధి l2 వారధిపై finalizeDepositని పిలవడానికి క్రాస్-డొమైన్ సందేశం యంత్రాంగాన్ని ఉపయోగిస్తుంది

లేయర్ 2 (l2)

  1. l2 వారధి finalizeDepositకి కాల్ చట్టబద్ధమైనదో లేదో ధృవీకరిస్తుంది:
    • క్రాస్ డొమైన్ సందేశం కాంట్రాక్ట్ నుండి వచ్చింది
    • వాస్తవానికి l1లోని వారధి నుండి వచ్చింది
  2. l2లోని ERC-20 టోకెన్ కాంట్రాక్ట్ సరైనదో కాదో l2 వారధి తనిఖీ చేస్తుంది:
    • l2 కాంట్రాక్ట్ దాని l1 కౌంటర్‌పార్ట్ l1లో టోకెన్‌లు వచ్చిన దానితో సమానంగా ఉందని నివేదిస్తుంది
    • l2 కాంట్రాక్ట్ సరైన ఇంటర్‌ఫేస్‌కు మద్దతు ఇస్తుందని నివేదిస్తుంది (ERC-165ని ఉపయోగించి (opens in a new tab)).
  3. l2 కాంట్రాక్ట్ సరైనదైతే, తగిన చిరునామాకు తగిన సంఖ్యలో టోకెన్‌లను ముద్రించడానికి దాన్ని పిలవండి. కాకపోతే, l1లో టోకెన్‌లను క్లెయిమ్ చేయడానికి వినియోగదారుని అనుమతించడానికి ఉపసంహరణ ప్రక్రియను ప్రారంభించండి.

ఉపసంహరణ ప్రవాహం

లేయర్ 2 (l2)

  1. ఉపసంహరించుకునేవారు l2 వారధిని పిలుస్తారు (withdraw లేదా withdrawTo)
  2. l2 వారధి msg.senderకి చెందిన తగిన సంఖ్యలో టోకెన్‌లను దహనం చేస్తుంది
  3. l2 వారధి l1 వారధిపై finalizeETHWithdrawal లేదా finalizeERC20Withdrawalని పిలవడానికి క్రాస్-డొమైన్ సందేశం యంత్రాంగాన్ని ఉపయోగిస్తుంది

లేయర్ 1 (l1)

  1. l1 వారధి finalizeETHWithdrawal లేదా finalizeERC20Withdrawalకి కాల్ చట్టబద్ధమైనదో లేదో ధృవీకరిస్తుంది:
    • క్రాస్ డొమైన్ సందేశం యంత్రాంగం నుండి వచ్చింది
    • వాస్తవానికి l2లోని వారధి నుండి వచ్చింది
  2. l1 వారధి తగిన ఆస్తిని (ETH లేదా ERC-20) తగిన చిరునామాకు బదిలీ చేస్తుంది

లేయర్ 1 (l1) కోడ్

ఇది l1, ఎథీరియం మెయిన్‌నెట్‌లో రన్ అయ్యే కోడ్.

IL1ERC20Bridge

ఈ ఇంటర్‌ఫేస్ ఇక్కడ నిర్వచించబడింది (opens in a new tab). ఇది ERC-20 టోకెన్‌లను వారధి చేయడానికి అవసరమైన ఫంక్షన్‌లు మరియు నిర్వచనాలను కలిగి ఉంటుంది.

// SPDX-License-Identifier: MIT

Optimism యొక్క చాలా కోడ్ MIT లైసెన్స్ క్రింద విడుదల చేయబడింది (opens in a new tab).

pragma solidity >0.5.0 <0.9.0;

ఇది వ్రాసే సమయానికి Solidity యొక్క తాజా వెర్షన్ 0.8.12. వెర్షన్ 0.9.0 విడుదలయ్యే వరకు, ఈ కోడ్ దానికి అనుకూలంగా ఉందో లేదో మాకు తెలియదు.

Optimism వారధి పరిభాషలో డిపాజిట్ అంటే l1 నుండి l2కి బదిలీ చేయడం మరియు ఉపసంహరణ అంటే l2 నుండి l1కి బదిలీ చేయడం.

        address indexed _l1Token,
        address indexed _l2Token,

చాలా సందర్భాలలో l1లోని ERC-20 చిరునామా l2లోని సమానమైన ERC-20 చిరునామాతో సమానంగా ఉండదు. మీరు టోకెన్ చిరునామాల జాబితాను ఇక్కడ చూడవచ్చు (opens in a new tab). chainId 1 ఉన్న చిరునామా l1 (మెయిన్‌నెట్)లో ఉంది మరియు chainId 10 ఉన్న చిరునామా l2 (Optimism)లో ఉంది. మిగిలిన రెండు chainId విలువలు Kovan టెస్ట్ నెట్‌వర్క్ (42) మరియు Optimistic Kovan టెస్ట్ నెట్‌వర్క్ (69) కోసం ఉన్నాయి.

        address indexed _from,
        address _to,
        uint256 _amount,
        bytes _data
    );

బదిలీలకు గమనికలను జోడించడం సాధ్యమవుతుంది, ఆ సందర్భంలో అవి వాటిని నివేదించే ఈవెంట్‌లకు జోడించబడతాయి.

    event ERC20WithdrawalFinalized(
        address indexed _l1Token,
        address indexed _l2Token,
        address indexed _from,
        address _to,
        uint256 _amount,
        bytes _data
    );

అదే వారధి కాంట్రాక్ట్ రెండు దిశలలో బదిలీలను నిర్వహిస్తుంది. l1 వారధి విషయంలో, దీని అర్థం డిపాజిట్ల ప్రారంభం మరియు ఉపసంహరణల ముగింపు.

ఈ ఫంక్షన్ నిజంగా అవసరం లేదు, ఎందుకంటే l2లో ఇది ముందుగా డిప్లాయ్ చేయబడిన కాంట్రాక్ట్, కాబట్టి ఇది ఎల్లప్పుడూ 0x4200000000000000000000000000000000000010 చిరునామాలో ఉంటుంది. ఇది l2 వారధితో సమరూపత కోసం ఇక్కడ ఉంది, ఎందుకంటే l1 వారధి చిరునామా తెలుసుకోవడం అంత సులభం కాదు.

_l2Gas పరామితి అనేది లావాదేవీ ఖర్చు చేయడానికి అనుమతించబడిన l2 గ్యాస్ మొత్తం. ఒక నిర్దిష్ట (అధిక) పరిమితి వరకు, ఇది ఉచితం (opens in a new tab), కాబట్టి ERC-20 కాంట్రాక్ట్ ముద్రించేటప్పుడు నిజంగా వింతగా ఏదైనా చేస్తే తప్ప, ఇది సమస్య కాకూడదు. వినియోగదారు వేరొక బ్లాక్‌చైన్‌లోని అదే చిరునామాకు ఆస్తులను వారధి ద్వారా పంపే సాధారణ దృష్టాంతాన్ని ఈ ఫంక్షన్ చూసుకుంటుంది.

ఈ ఫంక్షన్ దాదాపు depositERC20 వలె ఉంటుంది, కానీ ఇది ERC-20ని వేరే చిరునామాకు పంపడానికి మిమ్మల్ని అనుమతిస్తుంది.

Optimismలో ఉపసంహరణలు (మరియు l2 నుండి l1కి ఇతర సందేశాలు) రెండు దశల ప్రక్రియ:

  1. l2లో ప్రారంభ లావాదేవీ.
  2. l1లో ముగించే లేదా క్లెయిమ్ చేసే లావాదేవీ. l2 లావాదేవీకి సంబంధించిన ఫాల్ట్ ఛాలెంజ్ వ్యవధి (opens in a new tab) ముగిసిన తర్వాత ఈ లావాదేవీ జరగాలి.

IL1StandardBridge

ఈ ఇంటర్‌ఫేస్ ఇక్కడ నిర్వచించబడింది (opens in a new tab). ఈ ఫైల్ ETH కోసం ఈవెంట్ మరియు ఫంక్షన్ నిర్వచనాలను కలిగి ఉంది. ఈ నిర్వచనాలు ERC-20 కోసం పైన IL1ERC20Bridgeలో నిర్వచించిన వాటికి చాలా పోలి ఉంటాయి.

కొన్ని ERC-20 టోకెన్‌లకు అనుకూల ప్రాసెసింగ్ అవసరం మరియు ప్రామాణిక వారధి ద్వారా నిర్వహించబడవు కాబట్టి వారధి ఇంటర్‌ఫేస్ రెండు ఫైల్‌ల మధ్య విభజించబడింది. ఈ విధంగా అటువంటి టోకెన్‌ను నిర్వహించే అనుకూల వారధి IL1ERC20Bridgeని అమలు చేయగలదు మరియు ETHని కూడా వారధి చేయాల్సిన అవసరం లేదు.

ఈ ఈవెంట్ l1 మరియు l2 టోకెన్ చిరునామాలు లేకుండా మినహా, ERC-20 వెర్షన్ (ERC20DepositInitiated)కి దాదాపు సమానంగా ఉంటుంది. ఇతర ఈవెంట్‌లు మరియు ఫంక్షన్‌లకు కూడా ఇదే వర్తిస్తుంది.

CrossDomainEnabled

ఇతర లేయర్‌కు సందేశాలను పంపడానికి ఈ కాంట్రాక్ట్ (opens in a new tab) రెండు వారధుల (l1 మరియు l2) ద్వారా వారసత్వంగా పొందబడుతుంది.

// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.9.0;

/* ఇంటర్‌ఫేస్ దిగుమతులు */
import { ICrossDomainMessenger } from "./ICrossDomainMessenger.sol";

ఈ ఇంటర్‌ఫేస్ (opens in a new tab) క్రాస్ డొమైన్ మెసెంజర్‌ని ఉపయోగించి ఇతర లేయర్‌కు సందేశాలను ఎలా పంపాలో కాంట్రాక్ట్‌కు చెబుతుంది. ఈ క్రాస్ డొమైన్ మెసెంజర్ అనేది పూర్తిగా మరొక సిస్టమ్, మరియు దీనికి దాని స్వంత కథనం అవసరం, భవిష్యత్తులో నేను దానిని వ్రాయాలని ఆశిస్తున్నాను.

కాంట్రాక్ట్ తెలుసుకోవలసిన ఒక పరామితి, ఈ లేయర్‌లోని క్రాస్ డొమైన్ మెసెంజర్ చిరునామా. ఈ పరామితి కన్స్ట్రక్టర్‌లో ఒకసారి సెట్ చేయబడుతుంది మరియు ఎప్పటికీ మారదు.

క్రాస్ డొమైన్ సందేశం అది రన్ అవుతున్న బ్లాక్‌చైన్‌లోని (ఎథీరియం మెయిన్‌నెట్ లేదా Optimism) ఏదైనా కాంట్రాక్ట్ ద్వారా యాక్సెస్ చేయబడుతుంది. కానీ ప్రతి వైపు ఉన్న వారధి ఇతర వైపు ఉన్న వారధి నుండి వస్తే మాత్రమే నిర్దిష్ట సందేశాలను విశ్వసించేలా మనకు అవసరం.

        require(
            msg.sender == address(getCrossDomainMessenger()),
            "OVM_XCHAIN: messenger contract unauthenticated"
        );

తగిన క్రాస్ డొమైన్ మెసెంజర్ (messenger, మీరు క్రింద చూసినట్లుగా) నుండి వచ్చే సందేశాలను మాత్రమే విశ్వసించవచ్చు.


        require(
            getCrossDomainMessenger().xDomainMessageSender() == _sourceDomainAccount,
            "OVM_XCHAIN: wrong sender of cross-domain message"
        );

క్రాస్ డొమైన్ మెసెంజర్ ఇతర లేయర్‌తో సందేశాన్ని పంపిన చిరునామాను అందించే విధానం .xDomainMessageSender() ఫంక్షన్ (opens in a new tab). సందేశం ద్వారా ప్రారంభించబడిన లావాదేవీలో దీనిని పిలిచినంత కాలం ఇది ఈ సమాచారాన్ని అందించగలదు.

మనం స్వీకరించిన సందేశం ఇతర వారధి నుండి వచ్చిందని మనం నిర్ధారించుకోవాలి.

ఈ ఫంక్షన్ క్రాస్ డొమైన్ మెసెంజర్‌ను అందిస్తుంది. ఏ క్రాస్ డొమైన్ మెసెంజర్‌ని ఉపయోగించాలో పేర్కొనడానికి అల్గారిథమ్‌ను ఉపయోగించడానికి దీని నుండి వారసత్వంగా పొందే కాంట్రాక్ట్‌లను అనుమతించడానికి మనం messenger వేరియబుల్‌కు బదులుగా ఫంక్షన్‌ను ఉపయోగిస్తాము.

చివరగా, ఇతర లేయర్‌కు సందేశాన్ని పంపే ఫంక్షన్.

    ) internal {
        // స్లిదర్-disable-next-line రీఎంట్రెన్సీ-events, రీఎంట్రెన్సీ-benign

స్లిదర్ (opens in a new tab) అనేది దుర్బలత్వాలు మరియు ఇతర సంభావ్య సమస్యల కోసం వెతకడానికి ప్రతి కాంట్రాక్ట్‌పై Optimism రన్ చేసే స్టాటిక్ ఎనలైజర్. ఈ సందర్భంలో, కింది లైన్ రెండు దుర్బలత్వాలను ప్రేరేపిస్తుంది:

  1. రీఎంట్రెన్సీ ఈవెంట్‌లు (opens in a new tab)
  2. నిరపాయమైన రీఎంట్రెన్సీ (opens in a new tab)
        getCrossDomainMessenger().sendMessage(_crossDomainTarget, _message, _gasLimit);
    }
}

ఈ సందర్భంలో మనం రీఎంట్రెన్సీ గురించి ఆందోళన చెందడం లేదు, స్లిదర్‌కు అది తెలుసుకునే మార్గం లేకపోయినా, getCrossDomainMessenger() నమ్మదగిన చిరునామాను అందిస్తుందని మనకు తెలుసు.

l1 వారధి కాంట్రాక్ట్

ఈ కాంట్రాక్ట్ కోసం సోర్స్ కోడ్ ఇక్కడ ఉంది (opens in a new tab).

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

ఇంటర్‌ఫేస్‌లు ఇతర కాంట్రాక్ట్‌లలో భాగం కావచ్చు, కాబట్టి అవి విస్తృత శ్రేణి Solidity వెర్షన్‌లకు మద్దతు ఇవ్వాలి. కానీ వారధి అనేది మన కాంట్రాక్ట్, మరియు అది ఏ Solidity వెర్షన్‌ను ఉపయోగిస్తుందనే దాని గురించి మనం ఖచ్చితంగా ఉండవచ్చు.

/* ఇంటర్‌ఫేస్ దిగుమతులు */
import { IL1StandardBridge } from "./IL1StandardBridge.sol";
import { IL1ERC20Bridge } from "./IL1ERC20Bridge.sol";

IL1ERC20Bridge మరియు IL1StandardBridge పైన వివరించబడ్డాయి.

import { IL2ERC20Bridge } from "../../L2/messaging/IL2ERC20Bridge.sol";

ఈ ఇంటర్‌ఫేస్ (opens in a new tab) l2లో ప్రామాణిక వారధిని నియంత్రించడానికి సందేశాలను సృష్టించడానికి మమ్మల్ని అనుమతిస్తుంది.

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

ఈ ఇంటర్‌ఫేస్ (opens in a new tab) ERC-20 కాంట్రాక్ట్‌లను నియంత్రించడానికి మమ్మల్ని అనుమతిస్తుంది. మీరు దీని గురించి ఇక్కడ మరింత చదవవచ్చు.

/* లైబ్రరీ దిగుమతులు */
import { CrossDomainEnabled } from "../../libraries/bridge/CrossDomainEnabled.sol";

పైన వివరించినట్లుగా, ఈ కాంట్రాక్ట్ ఇంటర్‌లేయర్ సందేశం కోసం ఉపయోగించబడుతుంది.

import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";

Lib_PredeployAddresses (opens in a new tab) ఎల్లప్పుడూ ఒకే చిరునామాను కలిగి ఉండే l2 కాంట్రాక్ట్‌ల చిరునామాలను కలిగి ఉంటుంది. ఇందులో l2లోని ప్రామాణిక వారధి ఉంటుంది.

import { Address } from "@openzeppelin/contracts/utils/Address.sol";

ఓపెన్‌జెప్పెలిన్ యొక్క చిరునామా యుటిలిటీలు (opens in a new tab). కాంట్రాక్ట్ చిరునామాలు మరియు బాహ్యంగా స్వంతమైన ఖాతాలకు (EOA) చెందిన వాటి మధ్య తేడాను గుర్తించడానికి ఇది ఉపయోగించబడుతుంది.

ఇది సరైన పరిష్కారం కాదని గమనించండి, ఎందుకంటే డైరెక్ట్ కాల్‌లు మరియు కాంట్రాక్ట్ కన్స్ట్రక్టర్ నుండి చేసిన కాల్‌ల మధ్య తేడాను గుర్తించడానికి మార్గం లేదు, కానీ కనీసం ఇది కొన్ని సాధారణ వినియోగదారు లోపాలను గుర్తించడానికి మరియు నిరోధించడానికి మమ్మల్ని అనుమతిస్తుంది.

import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

ERC-20 ప్రమాణం (opens in a new tab) వైఫల్యాన్ని నివేదించడానికి కాంట్రాక్ట్ కోసం రెండు మార్గాలకు మద్దతు ఇస్తుంది:

  1. రివర్ట్
  2. falseని తిరిగి ఇవ్వడం

రెండు కేసులను నిర్వహించడం మన కోడ్‌ను మరింత క్లిష్టతరం చేస్తుంది, కాబట్టి దానికి బదులుగా మనం ఓపెన్‌జెప్పెలిన్ యొక్క SafeERC20 (opens in a new tab)ని ఉపయోగిస్తాము, ఇది అన్ని వైఫల్యాలు రివర్ట్‌కు దారితీసేలా (opens in a new tab) నిర్ధారిస్తుంది.

మనం IERC20 ఇంటర్‌ఫేస్‌ని ఉపయోగించిన ప్రతిసారీ SafeERC20 ర్యాపర్‌ని ఉపయోగించడాన్ని ఈ లైన్ ద్వారా పేర్కొంటాము.


    /********************************
     * బాహ్య కాంట్రాక్ట్ సూచనలు *
     ********************************/

    address public l2TokenBridge;

L2StandardBridge యొక్క చిరునామా.


    // డిపాజిట్ చేయబడిన లేయర్ 1 (l1) టోకెన్ బ్యాలెన్స్‌కు లేయర్ 1 (l1) టోకెన్ నుండి లేయర్ 2 (l2) టోకెన్ కు మ్యాప్ చేస్తుంది
    mapping(address => mapping(address => uint256)) public deposits;

ఇలాంటి డబుల్ మ్యాపింగ్ (opens in a new tab) అనేది మీరు ద్విమితీయ స్పార్స్ శ్రేణిని (opens in a new tab) నిర్వచించే మార్గం. ఈ డేటా నిర్మాణంలోని విలువలు deposit[L1 token addr][L2 token addr]గా గుర్తించబడతాయి. డిఫాల్ట్ విలువ సున్నా. వేరే విలువకు సెట్ చేయబడిన సెల్‌లు మాత్రమే నిల్వకు వ్రాయబడతాయి.


    /***************
     * కన్స్ట్రక్టర్ *
     ***************/

    // ఈ కాంట్రాక్ట్ ప్రాక్సీ వెనుక ఉంటుంది, కాబట్టి కన్స్ట్రక్టర్ పారామితులు ఉపయోగించబడవు.
    constructor() CrossDomainEnabled(address(0)) {}

నిల్వలోని అన్ని వేరియబుల్స్‌ను కాపీ చేయాల్సిన అవసరం లేకుండా ఈ కాంట్రాక్ట్‌ను అప్‌గ్రేడ్ చేయగలగాలి. అలా చేయడానికి మనం Proxy (opens in a new tab)ని ఉపయోగిస్తాము, ఇది ప్రతినిధి కాంట్రాక్ట్ ద్వారా నిల్వ చేయబడిన చిరునామా ఉన్న ప్రత్యేక కాంట్రాక్ట్‌కు కాల్‌లను బదిలీ చేయడానికి delegatecall (opens in a new tab)ని ఉపయోగించే కాంట్రాక్ట్ (మీరు అప్‌గ్రేడ్ చేసినప్పుడు ఆ చిరునామాను మార్చమని మీరు ప్రాక్సీకి చెబుతారు). మీరు delegatecallని ఉపయోగించినప్పుడు నిల్వ అనేది కాల్ చేసే కాంట్రాక్ట్ యొక్క నిల్వగా మిగిలిపోతుంది, కాబట్టి అన్ని కాంట్రాక్ట్ స్థితి వేరియబుల్స్ యొక్క విలువలు ప్రభావితం కావు.

ఈ నమూనా యొక్క ఒక ప్రభావం ఏమిటంటే, delegatecall ద్వారా కాల్ చేయబడిన కాంట్రాక్ట్ యొక్క నిల్వ ఉపయోగించబడదు మరియు అందువల్ల దానికి పంపబడిన కన్స్ట్రక్టర్ విలువల వల్ల పట్టింపు లేదు. ఈ కారణంగానే మనం CrossDomainEnabled కన్స్ట్రక్టర్‌కు అర్థరహితమైన విలువను అందించగలము. క్రింద ఉన్న ప్రారంభీకరణ కన్స్ట్రక్టర్ నుండి వేరుగా ఉండటానికి కూడా ఇదే కారణం.

స్లిదర్ పరీక్ష (opens in a new tab) కాంట్రాక్ట్ కోడ్ నుండి కాల్ చేయబడని ఫంక్షన్‌లను గుర్తిస్తుంది మరియు అందువల్ల publicకి బదులుగా externalగా ప్రకటించబడవచ్చు. external ఫంక్షన్‌ల గ్యాస్ ధర తక్కువగా ఉండవచ్చు, ఎందుకంటే వాటికి కాల్ డేటాలో పారామితులను అందించవచ్చు. publicగా ప్రకటించబడిన ఫంక్షన్‌లు కాంట్రాక్ట్ లోపల నుండి యాక్సెస్ చేయబడాలి. కాంట్రాక్ట్‌లు వాటి స్వంత కాల్ డేటాను సవరించలేవు, కాబట్టి పారామితులు మెమరీలో ఉండాలి. అటువంటి ఫంక్షన్‌ను బాహ్యంగా పిలిచినప్పుడు, కాల్ డేటాను మెమరీకి కాపీ చేయడం అవసరం, దీనికి గ్యాస్ ఖర్చవుతుంది. ఈ సందర్భంలో ఫంక్షన్ ఒకసారి మాత్రమే పిలువబడుతుంది, కాబట్టి అసమర్థత మనకు పట్టింపు లేదు.

    function initialize(address _l1messenger, address _l2TokenBridge) public {
        require(messenger == address(0), "Contract has already been initialized.");

initialize ఫంక్షన్ ఒకసారి మాత్రమే పిలువబడాలి. l1 క్రాస్ డొమైన్ మెసెంజర్ లేదా l2 టోకెన్ వారధి చిరునామా మారితే, మనం కొత్త ప్రాక్సీని మరియు దాన్ని పిలిచే కొత్త వారధిని సృష్టిస్తాము. మొత్తం సిస్టమ్ అప్‌గ్రేడ్ చేయబడినప్పుడు మినహా ఇది జరగడానికి అవకాశం లేదు, ఇది చాలా అరుదైన సంఘటన.

ఈ ఫంక్షన్‌ను ఎవరు పిలవగలరో పరిమితం చేసే యంత్రాంగం ఏదీ లేదని గమనించండి. దీని అర్థం సిద్ధాంతపరంగా దాడి చేసే వ్యక్తి మనం ప్రాక్సీని మరియు వారధి యొక్క మొదటి వెర్షన్‌ను డిప్లాయ్ చేయు వరకు వేచి ఉండి, ఆపై చట్టబద్ధమైన వినియోగదారు కంటే ముందుగా initialize ఫంక్షన్‌ను చేరుకోవడానికి ముందుగా అమలు చేయడం (opens in a new tab) చేయవచ్చు. కానీ దీనిని నిరోధించడానికి రెండు పద్ధతులు ఉన్నాయి:

  1. కాంట్రాక్ట్‌లు నేరుగా EOA ద్వారా కాకుండా వాటిని సృష్టించే మరొక కాంట్రాక్ట్ ఉన్న లావాదేవీలో (opens in a new tab) డిప్లాయ్ చేయబడితే, మొత్తం ప్రక్రియ అటామిక్‌గా ఉంటుంది మరియు మరే ఇతర లావాదేవీ అమలు చేయబడక ముందే పూర్తవుతుంది.
  2. initializeకి చట్టబద్ధమైన కాల్ విఫలమైతే, కొత్తగా సృష్టించబడిన ప్రాక్సీ మరియు వారధిని విస్మరించి కొత్త వాటిని సృష్టించడం ఎల్లప్పుడూ సాధ్యమే.
        messenger = _l1messenger;
        l2TokenBridge = _l2TokenBridge;
    }

వారధి తెలుసుకోవలసిన రెండు పారామితులు ఇవి.

మనకు ఓపెన్‌జెప్పెలిన్ యొక్క Address యుటిలిటీలు అవసరం కావడానికి ఇదే కారణం.

ఈ ఫంక్షన్ పరీక్ష ప్రయోజనాల కోసం ఉంది. ఇది ఇంటర్‌ఫేస్ నిర్వచనాలలో కనిపించదని గమనించండి - ఇది సాధారణ ఉపయోగం కోసం కాదు.

ఈ రెండు ఫంక్షన్‌లు _initiateETHDeposit చుట్టూ ఉన్న ర్యాపర్‌లు, ఇది వాస్తవ ETH డిపాజిట్‌ను నిర్వహించే ఫంక్షన్.

క్రాస్ డొమైన్ సందేశాలు పనిచేసే విధానం ఏమిటంటే, గమ్యస్థాన కాంట్రాక్ట్ సందేశాన్ని దాని కాల్ డేటాగా పిలుస్తుంది. Solidity కాంట్రాక్ట్‌లు ఎల్లప్పుడూ వాటి కాల్ డేటాను ABI స్పెసిఫికేషన్‌లకు (opens in a new tab) అనుగుణంగా అర్థం చేసుకుంటాయి. Solidity ఫంక్షన్ abi.encodeWithSelector (opens in a new tab) ఆ కాల్ డేటాను సృష్టిస్తుంది.

            IL2ERC20Bridge.finalizeDeposit.selector,
            address(0),
            Lib_PredeployAddresses.OVM_ETH,
            _from,
            _to,
            msg.value,
            _data
        );

ఇక్కడ సందేశం ఏమిటంటే, ఈ పారామితులతో finalizeDeposit ఫంక్షన్‌ను (opens in a new tab) పిలవడం:

పరామితివిలువఅర్థం
_l1Tokenaddress(0)l1లో ETH (ఇది ERC-20 టోకెన్ కాదు) కోసం నిలబడే ప్రత్యేక విలువ
_l2TokenLib_PredeployAddresses.OVM_ETHOptimismలో ETHని నిర్వహించే l2 కాంట్రాక్ట్, 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000 (ఈ కాంట్రాక్ట్ అంతర్గత Optimism ఉపయోగం కోసం మాత్రమే)
_from_fromETHని పంపే l1లోని చిరునామా
_to_toETHని స్వీకరించే l2లోని చిరునామా
amountmsg.valueపంపబడిన Wei మొత్తం (ఇది ఇప్పటికే వారధికి పంపబడింది)
_data_dataడిపాజిట్‌కు జోడించడానికి అదనపు డేటా
        // లేయర్ 2 (l2) లోకి కాల్ డేటా ని పంపండి
        // స్లిదర్-disable-next-line రీఎంట్రెన్సీ-events
        sendCrossDomainMessage(l2TokenBridge, _l2Gas, message);

క్రాస్ డొమైన్ మెసెంజర్ ద్వారా సందేశాన్ని పంపండి.

        // స్లిదర్-disable-next-line రీఎంట్రెన్సీ-events
        emit ETHDepositInitiated(_from, _to, msg.value, _data);
    }

ఈ బదిలీని వినే ఏదైనా వికేంద్రీకృత అప్లికేషన్ (dapp)కి తెలియజేయడానికి ఈవెంట్‌ను విడుదల చేయండి.

ఈ రెండు ఫంక్షన్‌లు _initiateERC20Deposit చుట్టూ ఉన్న ర్యాపర్‌లు, ఇది వాస్తవ ERC-20 డిపాజిట్‌ను నిర్వహించే ఫంక్షన్.

ఈ ఫంక్షన్ పైన ఉన్న _initiateETHDepositకి సమానంగా ఉంటుంది, కొన్ని ముఖ్యమైన తేడాలతో. మొదటి వ్యత్యాసం ఏమిటంటే, ఈ ఫంక్షన్ టోకెన్ చిరునామాలను మరియు బదిలీ చేయవలసిన మొత్తాన్ని పారామితులుగా స్వీకరిస్తుంది. ETH విషయంలో వారధికి చేసే కాల్‌లో ఇప్పటికే వారధి ఖాతాకు ఆస్తి బదిలీ ఉంటుంది (msg.value).

        // లేయర్ 1 (l1) లో డిపాజిట్ ప్రారంభించబడినప్పుడు, లేయర్ 1 (l1) వారధి భవిష్యత్తు కోసం నిధులను తనకు తానుగా బదిలీ చేస్తుంది
        // ఉపసంహరణ లు. safeTransferFrom కాంట్రాక్ట్ లో కోడ్ ఉందో లేదో కూడా తనిఖీ చేస్తుంది, కాబట్టి ఇది విఫలమవుతుంది
        // _from అనేది EOA లేదా చిరునామా(0) అయితే.
        // స్లిదర్-disable-next-line రీఎంట్రెన్సీ-events, రీఎంట్రెన్సీ-benign
        IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount);

ERC-20 టోకెన్ బదిలీలు ETH నుండి భిన్నమైన ప్రక్రియను అనుసరిస్తాయి:

  1. వినియోగదారు (_from) తగిన టోకెన్‌లను బదిలీ చేయడానికి వారధికి అనుమతి మొత్తం ఇస్తారు.
  2. వినియోగదారు టోకెన్ కాంట్రాక్ట్ చిరునామా, మొత్తం మొదలైన వాటితో వారధిని పిలుస్తారు.
  3. డిపాజిట్ ప్రక్రియలో భాగంగా వారధి టోకెన్‌లను (తనకు తానుగా) బదిలీ చేస్తుంది.

మొదటి దశ చివరి రెండింటి నుండి ప్రత్యేక లావాదేవీలో జరగవచ్చు. అయినప్పటికీ, ముందుగా అమలు చేయడం సమస్య కాదు ఎందుకంటే _initiateERC20Depositని పిలిచే రెండు ఫంక్షన్‌లు (depositERC20 మరియు depositERC20To) _from పరామితిగా msg.senderతో మాత్రమే ఈ ఫంక్షన్‌ను పిలుస్తాయి.

డిపాజిట్ చేయబడిన టోకెన్‌ల మొత్తాన్ని deposits డేటా నిర్మాణానికి జోడించండి. అదే l1 ERC-20 టోకెన్‌కు అనుగుణంగా l2లో బహుళ చిరునామాలు ఉండవచ్చు, కాబట్టి డిపాజిట్‌లను ట్రాక్ చేయడానికి l1 ERC-20 టోకెన్ యొక్క వారధి బ్యాలెన్స్‌ను ఉపయోగించడం సరిపోదు.

l2 వారధి l2 క్రాస్ డొమైన్ మెసెంజర్‌కు సందేశాన్ని పంపుతుంది, ఇది l1 క్రాస్ డొమైన్ మెసెంజర్ ఈ ఫంక్షన్‌ను పిలిచేలా చేస్తుంది (వాస్తవానికి, సందేశాన్ని ముగించే లావాదేవీ (opens in a new tab) l1లో సమర్పించబడిన తర్వాత).

    ) external onlyFromCrossDomainAccount(l2TokenBridge) {

ఇది క్రాస్ డొమైన్ మెసెంజర్ నుండి వస్తున్న మరియు l2 టోకెన్ వారధితో ఉద్భవించిన చట్టబద్ధమైన సందేశం అని నిర్ధారించుకోండి. ఈ ఫంక్షన్ వారధి నుండి ETHని ఉపసంహరించుకోవడానికి ఉపయోగించబడుతుంది, కాబట్టి ఇది అధీకృత కాలర్ ద్వారా మాత్రమే పిలువబడుతుందని మనం నిర్ధారించుకోవాలి.

        // స్లిదర్-disable-next-line రీఎంట్రెన్సీ-events
        (bool success, ) = _to.call{ value: _amount }(new bytes(0));

ETHని బదిలీ చేయడానికి మార్గం ఏమిటంటే, msg.valueలో Wei మొత్తంతో గ్రహీతను పిలవడం.

        require(success, "TransferHelper::safeTransferETH: ETH transfer failed");

        // స్లిదర్-disable-next-line రీఎంట్రెన్సీ-events
        emit ETHWithdrawalFinalized(_from, _to, _amount, _data);

ఉపసంహరణ గురించి ఈవెంట్‌ను విడుదల చేయండి.

ఈ ఫంక్షన్ ERC-20 టోకెన్‌ల కోసం అవసరమైన మార్పులతో పైన ఉన్న finalizeETHWithdrawalకి సమానంగా ఉంటుంది.

        deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] - _amount;

deposits డేటా నిర్మాణాన్ని నవీకరించండి.

వారధి యొక్క మునుపటి అమలు ఉంది. మనం ఆ అమలు నుండి దీనికి మారినప్పుడు, మనం అన్ని ఆస్తులను తరలించాల్సి వచ్చింది. ERC-20 టోకెన్‌లను సులభంగా తరలించవచ్చు. అయినప్పటికీ, కాంట్రాక్ట్‌కు ETHని బదిలీ చేయడానికి మీకు ఆ కాంట్రాక్ట్ ఆమోదం అవసరం, అదే donateETH మనకు అందిస్తుంది.

l2లో ERC-20 టోకెన్‌లు

ERC-20 టోకెన్ ప్రామాణిక వారధికి సరిపోవాలంటే, అది ప్రామాణిక వారధిని మరియు ప్రామాణిక వారధిని మాత్రమే టోకెన్‌ను ముద్రించడానికి అనుమతించాలి. ఇది అవసరం ఎందుకంటే Optimismలో చెలామణి అవుతున్న టోకెన్‌ల సంఖ్య l1 వారధి కాంట్రాక్ట్ లోపల లాక్ చేయబడిన టోకెన్‌ల సంఖ్యకు సమానంగా ఉండేలా వారధులు నిర్ధారించుకోవాలి. l2లో చాలా టోకెన్‌లు ఉంటే కొంతమంది వినియోగదారులు తమ ఆస్తులను తిరిగి l1కి వారధి ద్వారా పంపలేరు. విశ్వసనీయ వారధికి బదులుగా, మనం తప్పనిసరిగా ఫ్రాక్షనల్ రిజర్వ్ బ్యాంకింగ్ (opens in a new tab)ని పునఃసృష్టిస్తాము. l1లో చాలా టోకెన్‌లు ఉంటే, ఆ టోకెన్‌లలో కొన్ని ఎప్పటికీ వారధి కాంట్రాక్ట్ లోపల లాక్ చేయబడి ఉంటాయి ఎందుకంటే l2 టోకెన్‌లను దహనం చేయకుండా వాటిని విడుదల చేయడానికి మార్గం లేదు.

IL2StandardERC20

ప్రామాణిక వారధిని ఉపయోగించే l2లోని ప్రతి ERC-20 టోకెన్ ఈ ఇంటర్‌ఫేస్‌ను (opens in a new tab) అందించాలి, ఇది ప్రామాణిక వారధికి అవసరమైన ఫంక్షన్‌లు మరియు ఈవెంట్‌లను కలిగి ఉంటుంది.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

ప్రామాణిక ERC-20 ఇంటర్‌ఫేస్ (opens in a new tab) mint మరియు burn ఫంక్షన్‌లను కలిగి ఉండదు. ఆ పద్ధతులు ERC-20 ప్రమాణం (opens in a new tab) ద్వారా అవసరం లేదు, ఇది టోకెన్‌లను సృష్టించడానికి మరియు నాశనం చేయడానికి యంత్రాంగాలను పేర్కొనకుండా వదిలివేస్తుంది.

import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

కాంట్రాక్ట్ ఏ ఫంక్షన్‌లను అందిస్తుందో పేర్కొనడానికి ERC-165 ఇంటర్‌ఫేస్ (opens in a new tab) ఉపయోగించబడుతుంది. మీరు ప్రమాణాన్ని ఇక్కడ చదవవచ్చు (opens in a new tab).

interface IL2StandardERC20 is IERC20, IERC165 {
    function l1Token() external returns (address);

ఈ ఫంక్షన్ ఈ కాంట్రాక్ట్‌కు వారధి చేయబడిన l1 టోకెన్ చిరునామాను అందిస్తుంది. వ్యతిరేక దిశలో మనకు ఇలాంటి ఫంక్షన్ లేదని గమనించండి. అది అమలు చేయబడినప్పుడు l2 మద్దతు ప్లాన్ చేయబడిందా లేదా అనే దానితో సంబంధం లేకుండా మనం ఏదైనా l1 టోకెన్‌ను వారధి చేయగలగాలి.


    function mint(address _to, uint256 _amount) external;

    function burn(address _from, uint256 _amount) external;

    event Mint(address indexed _account, uint256 _amount);
    event Burn(address indexed _account, uint256 _amount);
}

టోకెన్‌లను ముద్రించడానికి (సృష్టించడానికి) మరియు దహనం చేయడానికి (నాశనం చేయడానికి) ఫంక్షన్‌లు మరియు ఈవెంట్‌లు. టోకెన్‌ల సంఖ్య సరైనదని (l1లో లాక్ చేయబడిన టోకెన్‌ల సంఖ్యకు సమానం) నిర్ధారించడానికి ఈ ఫంక్షన్‌లను రన్ చేయగల ఏకైక ఎంటిటీ వారధి మాత్రమే అయి ఉండాలి.

L2StandardERC20

ఇది IL2StandardERC20 ఇంటర్‌ఫేస్ యొక్క మన అమలు (opens in a new tab). మీకు ఏదైనా అనుకూల లాజిక్ అవసరమైతే తప్ప, మీరు దీన్ని ఉపయోగించాలి.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

ఓపెన్‌జెప్పెలిన్ ERC-20 కాంట్రాక్ట్ (opens in a new tab). Optimism చక్రాన్ని తిరిగి ఆవిష్కరించడాన్ని విశ్వసించదు, ప్రత్యేకించి చక్రం బాగా ఆడిట్ చేయబడినప్పుడు మరియు ఆస్తులను కలిగి ఉండటానికి తగినంత నమ్మదగినదిగా ఉండాలి.

import "./IL2StandardERC20.sol";

contract L2StandardERC20 is IL2StandardERC20, ERC20 {
    address public l1Token;
    address public l2Bridge;

ఇవి మనకు అవసరమైన రెండు అదనపు కాన్ఫిగరేషన్ పారామితులు మరియు ERC-20కి సాధారణంగా అవసరం లేదు.

ముందుగా మనం వారసత్వంగా పొందే కాంట్రాక్ట్ (ERC20(_name, _symbol)) కోసం కన్స్ట్రక్టర్‌ను పిలవండి మరియు ఆపై మన స్వంత వేరియబుల్స్‌ను సెట్ చేయండి.

ERC-165 (opens in a new tab) పనిచేసే విధానం ఇది. ప్రతి ఇంటర్‌ఫేస్ అనేది మద్దతు ఉన్న ఫంక్షన్‌ల సంఖ్య, మరియు ఆ ఫంక్షన్‌ల యొక్క ABI ఫంక్షన్ సెలెక్టర్ల (opens in a new tab) ఎక్స్‌క్లూజివ్ ఆర్ (opens in a new tab)గా గుర్తించబడుతుంది.

l2 వారధి ఆస్తులను పంపే ERC-20 కాంట్రాక్ట్ IL2StandardERC20 అని నిర్ధారించుకోవడానికి ERC-165ని శానిటీ చెక్‌గా ఉపయోగిస్తుంది.

గమనిక: supportsInterfaceకి తప్పుడు సమాధానాలు అందించకుండా రోగ్ కాంట్రాక్ట్‌ను నిరోధించడానికి ఏమీ లేదు, కాబట్టి ఇది శానిటీ చెక్ యంత్రాంగం, భద్రతా యంత్రాంగం కాదు.

l2 వారధి మాత్రమే ఆస్తులను ముద్రించడానికి మరియు దహనం చేయడానికి అనుమతించబడుతుంది.

_mint మరియు _burn వాస్తవానికి ఓపెన్‌జెప్పెలిన్ ERC-20 కాంట్రాక్ట్లో నిర్వచించబడ్డాయి. ఆ కాంట్రాక్ట్ వాటిని బాహ్యంగా బహిర్గతం చేయదు, ఎందుకంటే టోకెన్‌లను ముద్రించడానికి మరియు దహనం చేయడానికి షరతులు ERC-20ని ఉపయోగించే మార్గాల సంఖ్య వలె వైవిధ్యంగా ఉంటాయి.

లేయర్ 2 (l2) వారధి కోడ్

ఇది Optimismలో వారధిని రన్ చేసే కోడ్. ఈ కాంట్రాక్ట్ కోసం సోర్స్ ఇక్కడ ఉంది (opens in a new tab).

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

/* ఇంటర్‌ఫేస్ దిగుమతులు */
import { IL1StandardBridge } from "../../L1/messaging/IL1StandardBridge.sol";
import { IL1ERC20Bridge } from "../../L1/messaging/IL1ERC20Bridge.sol";
import { IL2ERC20Bridge } from "./IL2ERC20Bridge.sol";

IL2ERC20Bridge (opens in a new tab) ఇంటర్‌ఫేస్ మనం పైన చూసిన l1 సమానమైన దానికి చాలా పోలి ఉంటుంది. రెండు ముఖ్యమైన తేడాలు ఉన్నాయి:

  1. l1లో మీరు డిపాజిట్లను ప్రారంభిస్తారు మరియు ఉపసంహరణలను ముగిస్తారు. ఇక్కడ మీరు ఉపసంహరణలను ప్రారంభిస్తారు మరియు డిపాజిట్లను ముగిస్తారు.
  2. l1లో ETH మరియు ERC-20 టోకెన్‌ల మధ్య తేడాను గుర్తించడం అవసరం. l2లో మనం రెండింటికీ ఒకే ఫంక్షన్‌లను ఉపయోగించవచ్చు ఎందుకంటే అంతర్గతంగా Optimismలో ETH బ్యాలెన్స్‌లు 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000 (opens in a new tab) చిరునామాతో ERC-20 టోకెన్‌గా నిర్వహించబడతాయి.

l1 వారధి చిరునామాను ట్రాక్ చేయండి. l1 సమానమైన దానికి భిన్నంగా, ఇక్కడ మనకు ఈ వేరియబుల్ అవసరం అని గమనించండి. l1 వారధి చిరునామా ముందుగా తెలియదు.

ఈ రెండు ఫంక్షన్‌లు ఉపసంహరణలను ప్రారంభిస్తాయి. l1 టోకెన్ చిరునామాను పేర్కొనవలసిన అవసరం లేదని గమనించండి. l2 టోకెన్‌లు l1 సమానమైన చిరునామాను మనకు చెబుతాయని భావిస్తున్నారు.

మనం _from పరామితిపై కాకుండా నకిలీ చేయడం చాలా కష్టమైన (నాకు తెలిసినంత వరకు అసాధ్యం) msg.senderపై ఆధారపడుతున్నామని గమనించండి.


        // l1TokenBridge.finalizeERC20Withdrawal(_to, _amount) కోసం కాల్ డేటా ని నిర్మించండి
        // స్లిదర్-disable-next-line రీఎంట్రెన్సీ-events
        address l1Token = IL2StandardERC20(_l2Token).l1Token();
        bytes memory message;

        if (_l2Token == Lib_PredeployAddresses.OVM_ETH) {

l1లో ETH మరియు ERC-20 మధ్య తేడాను గుర్తించడం అవసరం.

ఈ ఫంక్షన్ L1StandardBridge ద్వారా పిలువబడుతుంది.

    ) external virtual onlyFromCrossDomainAccount(l1TokenBridge) {

సందేశం యొక్క మూలం చట్టబద్ధమైనదని నిర్ధారించుకోండి. ఇది ముఖ్యం ఎందుకంటే ఈ ఫంక్షన్ _mintని పిలుస్తుంది మరియు l1లో వారధి స్వంతమైన టోకెన్‌ల ద్వారా కవర్ చేయబడని టోకెన్‌లను ఇవ్వడానికి ఉపయోగించవచ్చు.

        // లక్ష్య టోకెన్ కంప్లైంట్ అని తనిఖీ చేయండి మరియు
        // లేయర్ 1 (l1) లో డిపాజిట్ చేయబడిన టోకెన్ ఇక్కడ ఉన్న లేయర్ 2 (l2) డిపాజిట్ చేయబడిన టోకెన్ ప్రాతినిధ్యంతో సరిపోలుతుందని ధృవీకరించండి
        if (
            // స్లిదర్-disable-next-line రీఎంట్రెన్సీ-events
            ERC165Checker.supportsInterface(_l2Token, 0x1d1d8b63) &&
            _l1Token == IL2StandardERC20(_l2Token).l1Token()

శానిటీ తనిఖీలు:

  1. సరైన ఇంటర్‌ఫేస్‌కు మద్దతు ఉంది
  2. l2 ERC-20 కాంట్రాక్ట్ యొక్క l1 చిరునామా టోకెన్‌ల l1 మూలంతో సరిపోలుతుంది
        ) {
            // డిపాజిట్ ఖరారు అయినప్పుడు, మేము లేయర్ 2 (l2) లోని ఖాతాకు అదే మొత్తంలో క్రెడిట్ చేస్తాము
            // టోకెన్ లు.
            // స్లిదర్-disable-next-line రీఎంట్రెన్సీ-events
            IL2StandardERC20(_l2Token).mint(_to, _amount);
            // స్లిదర్-disable-next-line రీఎంట్రెన్సీ-events
            emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);

శానిటీ తనిఖీలు ఉత్తీర్ణత సాధిస్తే, డిపాజిట్‌ను ముగించండి:

  1. టోకెన్‌లను ముద్రించండి
  2. తగిన ఈవెంట్‌ను విడుదల చేయండి

వినియోగదారు తప్పు l2 టోకెన్ చిరునామాను ఉపయోగించడం ద్వారా గుర్తించదగిన లోపం చేస్తే, మనం డిపాజిట్‌ను రద్దు చేసి, l1లో టోకెన్‌లను తిరిగి ఇవ్వాలనుకుంటున్నాము. l2 నుండి మనం దీన్ని చేయగల ఏకైక మార్గం ఫాల్ట్ ఛాలెంజ్ వ్యవధి కోసం వేచి ఉండాల్సిన సందేశాన్ని పంపడం, కానీ టోకెన్‌లను శాశ్వతంగా కోల్పోవడం కంటే వినియోగదారుకు ఇది చాలా మంచిది.

ముగింపు

ఆస్తి బదిలీలకు ప్రామాణిక వారధి అత్యంత సౌకర్యవంతమైన యంత్రాంగం. అయినప్పటికీ, ఇది చాలా సాధారణమైనది కాబట్టి ఇది ఎల్లప్పుడూ ఉపయోగించడానికి సులభమైన యంత్రాంగం కాదు. ముఖ్యంగా ఉపసంహరణల కోసం, చాలా మంది వినియోగదారులు ఛాలెంజ్ వ్యవధి కోసం వేచి ఉండని మరియు ఉపసంహరణను ముగించడానికి మెర్కల్ రుజువు అవసరం లేని మూడవ పక్ష వారధులను (opens in a new tab) ఉపయోగించడానికి ఇష్టపడతారు.

ఈ వారధులు సాధారణంగా l1లో ఆస్తులను కలిగి ఉండటం ద్వారా పనిచేస్తాయి, వీటిని వారు చిన్న రుసుముతో (తరచుగా ప్రామాణిక వారధి ఉపసంహరణ కోసం గ్యాస్ ధర కంటే తక్కువ) వెంటనే అందిస్తారు. వారధి (లేదా దానిని నడుపుతున్న వ్యక్తులు) l1 ఆస్తులు తక్కువగా ఉంటాయని ఊహించినప్పుడు అది l2 నుండి తగినంత ఆస్తులను బదిలీ చేస్తుంది. ఇవి చాలా పెద్ద ఉపసంహరణలు కాబట్టి, ఉపసంహరణ ఖర్చు పెద్ద మొత్తంలో రుణ విమోచన చేయబడుతుంది మరియు చాలా తక్కువ శాతంగా ఉంటుంది.

లేయర్ 2 (l2) ఎలా పనిచేస్తుందో మరియు స్పష్టమైన మరియు సురక్షితమైన Solidity కోడ్‌ను ఎలా వ్రాయాలో మరింత అర్థం చేసుకోవడానికి ఈ కథనం మీకు సహాయపడిందని ఆశిస్తున్నాము.

నా మరిన్ని పనుల కోసం ఇక్కడ చూడండి (opens in a new tab).