பிரதான உள்ளடக்கத்திற்குச் செல்

ஆப்டிமிசம் ஸ்டாண்டர்டு பாலம் ஒப்பந்தத்தின் முழு விவரம்

திட்பம்
பாலம்
2ம் அடுக்கு
இடைநிலை
Ori Pomerantz
30 மார்ச், 2022
27 நிமிட வாசிப்பு

Optimismopens in a new tab என்பது ஒரு Optimistic Rollup ஆகும். எத்தேரியம் மெயின்நெட்டை விட (அடுக்கு 1 அல்லது L1 என்றும் அழைக்கப்படுகிறது) ஆப்டிமிஸ்டிக் ரோலப்களால் மிகவும் குறைந்த விலையில் பரிவர்த்தனைகளைச் செயல்படுத்த முடியும், ஏனெனில் நெட்வொர்க்கில் உள்ள ஒவ்வொரு முனைக்கும் பதிலாக சில முனைகளால் மட்டுமே பரிவர்த்தனைகள் செயல்படுத்தப்படுகின்றன. அதே நேரத்தில், தரவு அனைத்தும் L1 இல் எழுதப்பட்டிருப்பதால், மெயின்நெட்டின் அனைத்து ஒருமைப்பாடு மற்றும் கிடைக்கும் தன்மை உத்தரவாதங்களுடன் எல்லாவற்றையும் நிரூபிக்கவும் புனரமைக்கவும் முடியும்.

ஆப்டிமிசத்தில் (அல்லது வேறு எந்த L2 இல்) L1 சொத்துகளைப் பயன்படுத்த, சொத்துகள் பாலமிடப்பட வேண்டும். இதை அடைவதற்கான ஒரு வழி, பயனர்கள் L1 இல் சொத்துக்களை (ETH மற்றும் ERC-20 டோக்கன்கள் மிகவும் பொதுவானவை) பூட்டி, L2 இல் பயன்படுத்த சமமான சொத்துக்களைப் பெறுவதாகும். இறுதியில், அவற்றை வைத்திருப்பவர் அவற்றை மீண்டும் L1 க்கு பாலமிட விரும்பலாம். இதைச் செய்யும்போது, சொத்துகள் L2 இல் எரிக்கப்பட்டு, பின்னர் L1 இல் உள்ள பயனருக்கு மீண்டும் விடுவிக்கப்படுகின்றன.

ஆப்டிமிசம் ஸ்டாண்டர்டு பாலம்opens in a new tab இப்படித்தான் செயல்படுகிறது. இந்தக் கட்டுரையில், அந்த பாலம் எவ்வாறு செயல்படுகிறது என்பதைப் பார்ப்பதற்கும், நன்கு எழுதப்பட்ட சொலிடிட்டி குறியீட்டிற்கான எடுத்துக்காட்டாக அதைப் படிப்பதற்கும் அதன் மூலக் குறியீட்டைப் பார்ப்போம்.

கட்டுப்பாட்டுப் பாய்வுகள்

பாலத்தில் இரண்டு முக்கியப் பாய்வுகள் உள்ளன:

  • டெபாசிட் (L1 இலிருந்து L2 வரை)
  • திரும்பப் பெறுதல் (L2 இலிருந்து L1 வரை)

டெபாசிட் பாய்வு

அடுக்கு 1

  1. ஒரு ERC-20ஐ டெபாசிட் செய்தால், டெபாசிட் செய்பவர் டெபாசிட் செய்யப்படும் தொகையைச் செலவழிக்க பாலத்திற்கு ஒரு கொடுப்பனவை வழங்குகிறார்.
  2. டெபாசிட் செய்பவர் L1 பாலத்தை அழைக்கிறார் (depositERC20, depositERC20To, depositETH, அல்லது depositETHTo)
  3. L1 பாலம் பாலமிடப்பட்ட சொத்தின் உடைமையைப் பெறுகிறது.
    • ETH: அழைப்பின் ஒரு பகுதியாக சொத்து டெபாசிட் செய்பவரால் மாற்றப்படுகிறது.
    • ERC-20: டெபாசிட் செய்பவர் வழங்கிய கொடுப்பனவைப் பயன்படுத்தி சொத்து பாலத்தால் தனக்கே மாற்றப்படுகிறது.
  4. L1 பாலம் L2 பாலத்தில் finalizeDepositஐ அழைக்க கிராஸ்-டொமைன் செய்தி பொறிமுறையைப் பயன்படுத்துகிறது.

அடுக்கு 2

  1. finalizeDeposit அழைப்பு முறையானதா என்பதை L2 பாலம் சரிபார்க்கிறது:
    • கிராஸ் டொமைன் செய்தி ஒப்பந்தத்திலிருந்து வந்தது
    • முதலில் L1 இல் உள்ள பாலத்திலிருந்து வந்தது
  2. L2 இல் உள்ள ERC-20 டோக்கன் ஒப்பந்தம் சரியானதா என்பதை L2 பாலம் சரிபார்க்கிறது:
    • L2 ஒப்பந்தம் அதன் L1 பிரதி டோக்கன்கள் L1 இல் இருந்து வந்ததைப் போலவே இருப்பதாகத் தெரிவிக்கிறது.
    • L2 ஒப்பந்தம் சரியான இடைமுகத்தை ஆதரிப்பதாகத் தெரிவிக்கிறது (ERC-165opens in a new tabஐப் பயன்படுத்தி).
  3. L2 ஒப்பந்தம் சரியானதாக இருந்தால், பொருத்தமான முகவரிக்கு பொருத்தமான எண்ணிக்கையிலான டோக்கன்களை உருவாக்க அதை அழைக்கவும். இல்லையெனில், L1 இல் உள்ள டோக்கன்களைப் பயனர் உரிமை கோர அனுமதிக்கும் விதத்தில் திரும்பப் பெறும் செயல்முறையைத் தொடங்கவும்.

திரும்பப் பெறுதல் பாய்வு

அடுக்கு 2

  1. திரும்பப் பெறுபவர் L2 பாலத்தை அழைக்கிறார் (withdraw அல்லது withdrawTo)
  2. L2 பாலம் msg.senderக்கு சொந்தமான பொருத்தமான எண்ணிக்கையிலான டோக்கன்களை எரிக்கிறது.
  3. L2 பாலம் L1 பாலத்தில் finalizeETHWithdrawal அல்லது finalizeERC20Withdrawal ஐ அழைக்க கிராஸ்-டொமைன் செய்தி பொறிமுறையைப் பயன்படுத்துகிறது.

அடுக்கு 1

  1. finalizeETHWithdrawal அல்லது finalizeERC20Withdrawal க்கான அழைப்பு முறையானதா என்பதை L1 பாலம் சரிபார்க்கிறது:
    • கிராஸ் டொமைன் செய்தி பொறிமுறையிலிருந்து வந்தது
    • முதலில் L2 இல் உள்ள பாலத்திலிருந்து வந்தது
  2. L1 பாலம் பொருத்தமான சொத்தை (ETH அல்லது ERC-20) பொருத்தமான முகவரிக்கு மாற்றுகிறது.

அடுக்கு 1 குறியீடு

இது L1, எத்தேரியம் மெயின்நெட்டில் இயங்கும் குறியீடாகும்.

IL1ERC20Bridge

இந்த இடைமுகம் இங்கு வரையறுக்கப்பட்டுள்ளதுopens in a new tab. ERC-20 டோக்கன்களைப் பாலமிடுவதற்குத் தேவையான செயல்பாடுகள் மற்றும் வரையறைகள் இதில் அடங்கும்.

1// SPDX-License-Identifier: MIT

ஆப்டிமிசத்தின் பெரும்பாலான குறியீடு MIT உரிமத்தின் கீழ் வெளியிடப்படுகிறதுopens in a new tab.

1pragma solidity >0.5.0 <0.9.0;

இதை எழுதும்போது சொலிடிட்டியின் சமீபத்திய பதிப்பு 0.8.12 ஆகும். பதிப்பு 0.9.0 வெளியிடப்படும் வரை, இந்தக் குறியீடு அதனுடன் இணக்கமாக இருக்குமா இல்லையா என்பது எங்களுக்குத் தெரியாது.

1/**
2 * @title IL1ERC20Bridge
3 */
4interface IL1ERC20Bridge {
5 /**********
6 * நிகழ்வுகள் *
7 **********/
8
9 event ERC20DepositInitiated(
அனைத்தையும் காட்டு

ஆப்டிமிசம் பாலம் சொற்களஞ்சியத்தில் டெபாசிட் என்பது L1 இலிருந்து L2 க்கு மாற்றுவதையும், திரும்பப் பெறுதல் என்பது L2 இலிருந்து L1 க்கு மாற்றுவதையும் குறிக்கிறது.

1 address indexed _l1Token,
2 address indexed _l2Token,

பெரும்பாலான சந்தர்ப்பங்களில் L1 இல் உள்ள ஒரு ERC-20 இன் முகவரி L2 இல் உள்ள சமமான ERC-20 இன் முகவரியாக இருக்காது. டோக்கன் முகவரிகளின் பட்டியலை நீங்கள் இங்கே பார்க்கலாம்opens in a new tab. chainId 1 உள்ள முகவரி L1 (மெயின்நெட்) மற்றும் chainId 10 உள்ள முகவரி L2 (ஆப்டிமிசம்) இல் உள்ளது. மற்ற இரண்டு chainId மதிப்புகள் கோவன் சோதனை நெட்வொர்க்கிற்கும் (42) ஆப்டிமிஸ்டிக் கோவன் சோதனை நெட்வொர்க்கிற்கும் (69) ஆகும்.

1 address indexed _from,
2 address _to,
3 uint256 _amount,
4 bytes _data
5 );

மாற்றங்களுக்குக் குறிப்புகளைச் சேர்க்க முடியும், সেক্ষেত্রে அவை புகாரளிக்கும் நிகழ்வுகளுடன் சேர்க்கப்படும்.

1 event ERC20WithdrawalFinalized(
2 address indexed _l1Token,
3 address indexed _l2Token,
4 address indexed _from,
5 address _to,
6 uint256 _amount,
7 bytes _data
8 );

அதே பாலம் ஒப்பந்தம் இரு திசைகளிலும் இடமாற்றங்களைக் கையாளுகிறது. L1 பாலத்தைப் பொறுத்தவரை, இது டெபாசிட்களைத் தொடங்குதல் மற்றும் திரும்பப் பெறுவதை இறுதி செய்தல் ஆகியவற்றைக் குறிக்கிறது.

1
2 /********************
3 * பொது செயல்பாடுகள் *
4 ********************/
5
6 /**
7 * @dev தொடர்புடைய L2 பாலம் ஒப்பந்தத்தின் முகவரியைப் பெறவும்.
8 * @return தொடர்புடைய L2 பாலம் ஒப்பந்தத்தின் முகவரி.
9 */
10 function l2TokenBridge() external returns (address);
அனைத்தையும் காட்டு

இந்தச் செயல்பாடு உண்மையில் தேவையில்லை, ஏனெனில் L2 இல் இது ஒரு முன் வரிசைப்படுத்தப்பட்ட ஒப்பந்தமாகும், எனவே இது எப்போதும் 0x4200000000000000000000000000000000000010 முகவரியில் இருக்கும். L2 பாலத்துடனான சமச்சீர்மைக்காக இது இங்கே உள்ளது, ஏனெனில் L1 பாலத்தின் முகவரி அறிவது அற்பமானதல்ல.

1 /**
2 * @dev L2 இல் அழைப்பாளரின் இருப்புக்கு ERC20 தொகையை டெபாசிட் செய்யவும்.
3 * @param _l1Token நாங்கள் டெபாசிட் செய்யும் L1 ERC20 இன் முகவரி
4 * @param _l2Token L1 இன் அந்தந்த L2 ERC20 இன் முகவரி
5 * @param _amount டெபாசிட் செய்ய வேண்டிய ERC20 இன் அளவு
6 * @param _l2Gas L2 இல் டெபாசிட்டை முடிக்கத் தேவையான கேஸ் வரம்பு.
7 * @param _data L2க்கு அனுப்ப விருப்பத் தரவு. இந்தத் தரவு வழங்கப்பட்டுள்ளது
8 * வெளிப்புற ஒப்பந்தங்களுக்கான வசதிக்காக மட்டுமே. அதிகபட்சமாகச் செயல்படுத்துவதைத் தவிர
9 * நீளம், இந்த ஒப்பந்தங்கள் அதன் உள்ளடக்கம் பற்றி எந்த உத்தரவாதமும் அளிக்காது.
10 */
11 function depositERC20(
12 address _l1Token,
13 address _l2Token,
14 uint256 _amount,
15 uint32 _l2Gas,
16 bytes calldata _data
17 ) external;
அனைத்தையும் காட்டு

_l2Gas அளவுரு என்பது பரிவர்த்தனை செலவழிக்க அனுமதிக்கப்படும் L2 கேஸ் அளவாகும். ஒரு குறிப்பிட்ட (உயர்) வரம்பு வரை, இது இலவசம்opens in a new tab, எனவே ERC-20 ஒப்பந்தம் உருவாக்கும் போது மிகவும் விசித்திரமான ஒன்றைச் செய்யாத வரை, அது ஒரு பிரச்சினையாக இருக்கக்கூடாது. இந்தப் பொதுவான சூழ்நிலையை இந்தச் செயல்பாடு கவனித்துக்கொள்கிறது, அங்கு ஒரு பயனர் ஒரு வேறுபட்ட பிளாக்செயினில் அதே முகவரிக்கு சொத்துக்களைப் பாலமிடுகிறார்.

1 /**
2 * @dev L2 இல் ஒரு பெறுநரின் இருப்புக்கு ERC20 தொகையை டெபாசிட் செய்யவும்.
3 * @param _l1Token நாங்கள் டெபாசிட் செய்யும் L1 ERC20 இன் முகவரி
4 * @param _l2Token L1 இன் அந்தந்த L2 ERC20 இன் முகவரி
5 * @param _to திரும்பப் பெறுதலை வரவு வைக்க L2 முகவரி.
6 * @param _amount டெபாசிட் செய்ய வேண்டிய ERC20 இன் அளவு.
7 * @param _l2Gas L2 இல் டெபாசிட்டை முடிக்கத் தேவையான கேஸ் வரம்பு.
8 * @param _data L2க்கு அனுப்ப விருப்பத் தரவு. இந்தத் தரவு வழங்கப்பட்டுள்ளது
9 * வெளிப்புற ஒப்பந்தங்களுக்கான வசதிக்காக மட்டுமே. அதிகபட்சமாகச் செயல்படுத்துவதைத் தவிர
10 * நீளம், இந்த ஒப்பந்தங்கள் அதன் உள்ளடக்கம் பற்றி எந்த உத்தரவாதமும் அளிக்காது.
11 */
12 function depositERC20To(
13 address _l1Token,
14 address _l2Token,
15 address _to,
16 uint256 _amount,
17 uint32 _l2Gas,
18 bytes calldata _data
19 ) external;
அனைத்தையும் காட்டு

இந்தச் செயல்பாடு depositERC20 உடன் கிட்டத்தட்ட ஒரே மாதிரியாக உள்ளது, ஆனால் இது ERC-20ஐ வேறு முகவரிக்கு அனுப்ப உங்களை அனுமதிக்கிறது.

1 /*************************
2 * கிராஸ்-செயின் செயல்பாடுகள் *
3 *************************/
4
5 /**
6 * @dev L2 இலிருந்து L1 க்கு திரும்பப் பெறுவதை முடித்து, பெறுநரின் இருப்புக்கு நிதியை வரவு வைக்கவும்.
7 * L1 ERC20 டோக்கன்.
8 * L2 இலிருந்து தொடங்கப்பட்ட திரும்பப் பெறுதல் இறுதி செய்யப்படவில்லை என்றால் இந்த அழைப்பு தோல்வியடையும்.
9 *
10 * @param _l1Token finalizeWithdrawal க்கான L1 டோக்கனின் முகவரி.
11 * @param _l2Token திரும்பப் பெறுதல் தொடங்கப்பட்ட L2 டோக்கனின் முகவரி.
12 * @param _from பரிமாற்றத்தைத் தொடங்கும் L2 முகவரி.
13 * @param _to திரும்பப் பெறுதலை வரவு வைக்க L1 முகவரி.
14 * @param _amount டெபாசிட் செய்ய வேண்டிய ERC20 இன் அளவு.
15 * @param _data L2 இல் அனுப்புநர் வழங்கிய தரவு. இந்தத் தரவு வழங்கப்பட்டுள்ளது
16 * வெளிப்புற ஒப்பந்தங்களுக்கான வசதிக்காக மட்டுமே. அதிகபட்சமாகச் செயல்படுத்துவதைத் தவிர
17 * நீளம், இந்த ஒப்பந்தங்கள் அதன் உள்ளடக்கம் பற்றி எந்த உத்தரவாதமும் அளிக்காது.
18 */
19 function finalizeERC20Withdrawal(
20 address _l1Token,
21 address _l2Token,
22 address _from,
23 address _to,
24 uint256 _amount,
25 bytes calldata _data
26 ) external;
27}
அனைத்தையும் காட்டு

ஆப்டிமிசத்தில் திரும்பப் பெறுதல் (மற்றும் 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 ஐயும் பாலமிட வேண்டியதில்லை.

1// SPDX-License-Identifier: MIT
2pragma solidity >0.5.0 <0.9.0;
3
4import "./IL1ERC20Bridge.sol";
5
6/**
7 * @title IL1StandardBridge
8 */
9interface IL1StandardBridge is IL1ERC20Bridge {
10 /**********
11 * நிகழ்வுகள் *
12 **********/
13 event ETHDepositInitiated(
14 address indexed _from,
15 address indexed _to,
16 uint256 _amount,
17 bytes _data
18 );
அனைத்தையும் காட்டு

L1 மற்றும் L2 டோக்கன் முகவரிகள் இல்லாமல், இந்த நிகழ்வு ERC-20 பதிப்பிற்கு (ERC20DepositInitiated) கிட்டத்தட்ட ஒத்ததாக உள்ளது. மற்ற நிகழ்வுகளுக்கும் செயல்பாடுகளுக்கும் இதுவே பொருந்தும்.

1 event ETHWithdrawalFinalized(
2 .
3 .
4 .
5 );
6
7 /********************
8 * பொது செயல்பாடுகள் *
9 ********************/
10
11 /**
12 * @dev L2 இல் அழைப்பாளரின் இருப்புக்கு ETH இன் ஒரு பகுதியை டெபாசிட் செய்யவும்.
13 .
14 .
15 .
16 */
17 function depositETH(uint32 _l2Gas, bytes calldata _data) external payable;
18
19 /**
20 * @dev L2 இல் பெறுநரின் இருப்புக்கு ETH இன் ஒரு பகுதியை டெபாசிட் செய்யவும்.
21 .
22 .
23 .
24 */
25 function depositETHTo(
26 address _to,
27 uint32 _l2Gas,
28 bytes calldata _data
29 ) external payable;
30
31 /*************************
32 * கிராஸ்-செயின் செயல்பாடுகள் *
33 *************************/
34
35 /**
36 * @dev L2 இலிருந்து L1 க்கு திரும்பப் பெறுவதை முடித்து, பெறுநரின் இருப்புக்கு நிதியை வரவு வைக்கவும்.
37 * L1 ETH டோக்கன். xDomainMessenger மட்டுமே இந்தச் செயல்பாட்டை அழைக்க முடியும் என்பதால், அது ஒருபோதும் அழைக்கப்படாது
38 * திரும்பப் பெறுவது இறுதி செய்யப்படும் முன்.
39 .
40 .
41 .
42 */
43 function finalizeETHWithdrawal(
44 address _from,
45 address _to,
46 uint256 _amount,
47 bytes calldata _data
48 ) external;
49}
அனைத்தையும் காட்டு

CrossDomainEnabled

இந்த ஒப்பந்தம்opens in a new tab இரண்டு பாலங்களாலும் (L1 மற்றும் L2) மற்ற அடுக்குக்கு செய்திகளை அனுப்ப மரபுரிமையாகப் பெறப்படுகிறது.

1// SPDX-License-Identifier: MIT
2pragma solidity >0.5.0 <0.9.0;
3
4/* Interface Imports */
5import { ICrossDomainMessenger } from "./ICrossDomainMessenger.sol";

இந்த இடைமுகம்opens in a new tab கிராஸ் டொமைன் மெசஞ்சரைப் பயன்படுத்தி, மற்ற அடுக்குக்கு செய்திகளை எப்படி அனுப்புவது என்று ஒப்பந்தத்திற்குச் சொல்கிறது. இந்த கிராஸ் டொமைன் மெசஞ்சர் முற்றிலும் வேறுபட்ட அமைப்பு, மேலும் அதன் சொந்த கட்டுரைக்குத் தகுதியானது, அதை நான் எதிர்காலத்தில் எழுத நம்புகிறேன்.

1/**
2 * @title CrossDomainEnabled
3 * @dev கிராஸ்-டொமைன் தகவல்தொடர்புகளைச் செய்யும் ஒப்பந்தங்களுக்கான உதவி ஒப்பந்தம்
4 *
5 * பயன்படுத்தப்பட்ட தொகுப்பி: மரபுரிமை பெற்ற ஒப்பந்தத்தால் வரையறுக்கப்பட்டது
6 */
7contract CrossDomainEnabled {
8 /*************
9 * மாறிகள் *
10 *************/
11
12 // Messenger contract used to send and receive messages from the other domain.
13 address public messenger;
14
15 /***************
16 * கட்டமைப்பாளர் *
17 ***************/
18
19 /**
20 * @param _messenger தற்போதைய அடுக்கில் உள்ள கிராஸ்-டொமைன் மெசஞ்சரின் முகவரி.
21 */
22 constructor(address _messenger) {
23 messenger = _messenger;
24 }
அனைத்தையும் காட்டு

ஒப்பந்தம் தெரிந்து கொள்ள வேண்டிய ஒரே அளவுரு, இந்த அடுக்கில் உள்ள கிராஸ் டொமைன் மெசஞ்சரின் முகவரி ஆகும். இந்த அளவுரு ஒருமுறை கட்டமைப்பாளரில் அமைக்கப்பட்டது, அது ஒருபோதும் மாறாது.

1
2 /**********************
3 * செயல்பாட்டு மாற்றியமைப்பாளர்கள் *
4 **********************/
5
6 /**
7 * மாற்றியமைக்கப்பட்ட செயல்பாடு ஒரு குறிப்பிட்ட கிராஸ்-டொமைன் கணக்கிலிருந்து மட்டுமே அழைக்கக்கூடியது என்பதை இது செயல்படுத்துகிறது.
8 * @param _sourceDomainAccount இந்தச் செயல்பாட்டை அழைக்க அங்கீகரிக்கப்பட்ட அசல் டொமைனில் உள்ள ஒரே கணக்கு.
9 */
10 modifier onlyFromCrossDomainAccount(address _sourceDomainAccount) {
அனைத்தையும் காட்டு

கிராஸ் டொமைன் செய்தி அனுப்புதல் அது இயங்கும் பிளாக்செயினில் (எத்தேரியம் மெயின்நெட் அல்லது ஆப்டிமிசம்) உள்ள எந்தவொரு ஒப்பந்தத்தாலும் அணுகக்கூடியது. ஆனால் ஒவ்வொரு பக்கத்திலும் உள்ள பாலம் மறுபக்கத்தில் உள்ள பாலத்திலிருந்து வந்தால் மட்டுமே சில செய்திகளை நம்ப வேண்டும்.

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

பொருத்தமான கிராஸ் டொமைன் மெசஞ்சரிடமிருந்து (மெசஞ்சர், கீழே நீங்கள் காண்பது போல்) வரும் செய்திகளை மட்டுமே நம்ப முடியும்.

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

மற்றொரு அடுக்குடன் ஒரு செய்தியை அனுப்பிய முகவரியை கிராஸ் டொமைன் மெசஞ்சர் வழங்கும் வழி .xDomainMessageSender() செயல்பாடுopens in a new tab ஆகும். செய்தியால் தொடங்கப்பட்ட பரிவர்த்தனையில் அது அழைக்கப்படும் வரை இந்தத் தகவலை வழங்க முடியும்.

நாங்கள் பெற்ற செய்தி மற்ற பாலத்திலிருந்து வந்ததா என்பதை நாங்கள் உறுதி செய்ய வேண்டும்.

1
2 _;
3 }
4
5 /**********************
6 * உள் செயல்பாடுகள் *
7 **********************/
8
9 /**
10 * மெசஞ்சரைப் பெறுகிறது, பொதுவாக சேமிப்பகத்திலிருந்து. ஒரு குழந்தை ஒப்பந்தம் தேவைப்பட்டால் இந்தச் செயல்பாடு வெளிப்படுத்தப்படும்
11 * மேலெழுத வேண்டும்.
12 * @return பயன்படுத்தப்பட வேண்டிய கிராஸ்-டொமைன் மெசஞ்சர் ஒப்பந்தத்தின் முகவரி.
13 */
14 function getCrossDomainMessenger() internal virtual returns (ICrossDomainMessenger) {
15 return ICrossDomainMessenger(messenger);
16 }
அனைத்தையும் காட்டு

இந்த செயல்பாடு கிராஸ் டொமைன் மெசஞ்சரை வழங்குகிறது. எந்த கிராஸ் டொமைன் மெசஞ்சரைப் பயன்படுத்த வேண்டும் என்பதைக் குறிப்பிட ஒரு நெறிமுறையைப் பயன்படுத்த, இதிலிருந்து மரபுரிமையாகப் பெறப்பட்ட ஒப்பந்தங்களை அனுமதிக்க, மெசஞ்சர் என்ற மாறியை விட ஒரு செயல்பாட்டைப் பயன்படுத்துகிறோம்.

1
2 /**
3 * மற்றொரு டொமைனில் உள்ள கணக்கிற்கு ஒரு செய்தியை அனுப்புகிறது
4 * @param _crossDomainTarget இலக்கு டொமைனில் உத்தேசிக்கப்பட்ட பெறுநர்
5 * @param _message இலக்குக்கு அனுப்ப வேண்டிய தரவு (பொதுவாக ஒரு செயல்பாட்டிற்கு calldata உடன்
6 * `onlyFromCrossDomainAccount()`)
7 * @param _gasLimit இலக்கு டொமைனில் செய்தியைப் பெறுவதற்கான கேஸ் லிமிட்.
8 */
9 function sendCrossDomainMessage(
10 address _crossDomainTarget,
11 uint32 _gasLimit,
12 bytes memory _message
அனைத்தையும் காட்டு

இறுதியாக, மற்ற அடுக்குக்கு ஒரு செய்தியை அனுப்பும் செயல்பாடு.

1 ) internal {
2 // slither-disable-next-line reentrancy-events, reentrancy-benign

Slitheropens in a new tab என்பது பாதிப்புகள் மற்றும் பிற சாத்தியமான சிக்கல்களைத் தேட ஒவ்வொரு ஒப்பந்தத்திலும் ஆப்டிமிசம் இயங்கும் ஒரு நிலையான பகுப்பாய்வியாகும். இந்த விஷயத்தில், பின்வரும் வரி இரண்டு பாதிப்புகளைத் தூண்டுகிறது:

  1. மறுநுழைவு நிகழ்வுகள்opens in a new tab
  2. தீங்கற்ற மறுநுழைவுopens in a new tab
1 getCrossDomainMessenger().sendMessage(_crossDomainTarget, _message, _gasLimit);
2 }
3}

இந்த விஷயத்தில், getCrossDomainMessenger() ஒரு நம்பகமான முகவரியை வழங்குவதை நாங்கள் அறிந்திருப்பதால், மறுநுழைவு பற்றி நாங்கள் கவலைப்படவில்லை, ஸ்லித்தருக்கு அதை அறிய வழி இல்லை என்றாலும்.

L1 பாலம் ஒப்பந்தம்

இந்த ஒப்பந்தத்திற்கான மூலக் குறியீடு இங்கே உள்ளதுopens in a new tab.

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

இடைமுகங்கள் மற்ற ஒப்பந்தங்களின் ஒரு பகுதியாக இருக்கலாம், எனவே அவை பரந்த அளவிலான சொலிடிட்டி பதிப்புகளை ஆதரிக்க வேண்டும். ஆனால் பாலம் என்பது எங்கள் ஒப்பந்தம், மேலும் அது எந்த சொலிடிட்டி பதிப்பைப் பயன்படுத்துகிறது என்பதில் நாங்கள் கண்டிப்பாக இருக்க முடியும்.

1/* Interface Imports */
2import { IL1StandardBridge } from "./IL1StandardBridge.sol";
3import { IL1ERC20Bridge } from "./IL1ERC20Bridge.sol";

IL1ERC20Bridge மற்றும் IL1StandardBridge மேலே விளக்கப்பட்டுள்ளன.

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

இந்த இடைமுகம்opens in a new tab L2 இல் உள்ள ஸ்டாண்டர்டு பாலத்தைக் கட்டுப்படுத்த செய்திகளை உருவாக்க உதவுகிறது.

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

இந்த இடைமுகம்opens in a new tab ERC-20 ஒப்பந்தங்களைக் கட்டுப்படுத்த உதவுகிறது. இதைப் பற்றி மேலும் இங்கே படிக்கலாம்.

1/* Library Imports */
2import { CrossDomainEnabled } from "../../libraries/bridge/CrossDomainEnabled.sol";

மேலே விளக்கப்பட்டுள்ளபடி, இந்த ஒப்பந்தம் இன்டர்லேயர் செய்தி அனுப்புதலுக்குப் பயன்படுத்தப்படுகிறது.

1import { 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.solopens in a new tab) எப்போதும் ஒரே முகவரியைக் கொண்டிருக்கும் L2 ஒப்பந்தங்களுக்கான முகவரிகளைக் கொண்டுள்ளது. இதில் L2 இல் உள்ள ஸ்டாண்டர்டு பாலம் அடங்கும்.

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

OpenZeppelin's Address utilitiesopens in a new tab. ஒப்பந்த முகவரிகளுக்கும் வெளிப்புறமாகச் சொந்தமான கணக்குகளுக்கும் (EOA) இடையிலான வேறுபாட்டிற்கு இது பயன்படுத்தப்படுகிறது.

இது ஒரு சரியான தீர்வு அல்ல என்பதை நினைவில் கொள்க, ஏனெனில் நேரடி அழைப்புகளுக்கும் ஒரு ஒப்பந்தத்தின் கட்டமைப்பாளரிடமிருந்து செய்யப்படும் அழைப்புகளுக்கும் இடையில் வேறுபாடு காட்ட வழி இல்லை, ஆனால் குறைந்தபட்சம் இது சில பொதுவான பயனர் பிழைகளைக் கண்டறிந்து தடுக்க உதவுகிறது.

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

ERC-20 தரநிலைopens in a new tab தோல்வியைப் புகாரளிக்க ஒரு ஒப்பந்தத்திற்கு இரண்டு வழிகளை ஆதரிக்கிறது:

  1. திரும்பப்பெறு
  2. false என்பதைத் திருப்பி அனுப்புக

இரண்டு நிகழ்வுகளையும் கையாள்வது எங்கள் குறியீட்டை மிகவும் சிக்கலாக்கும், எனவே அதற்கு பதிலாக நாங்கள் OpenZeppelin's SafeERC20opens in a new tabஐப் பயன்படுத்துகிறோம், இது அனைத்து தோல்விகளும் திரும்பப்பெறுவதில் விளைவதைopens in a new tab உறுதி செய்கிறது.

1/**
2 * @title L1StandardBridge
3 * @dev L1 ETH மற்றும் ERC20 பாலம் என்பது டெபாசிட் செய்யப்பட்ட L1 நிதிகள் மற்றும் L2 இல் பயன்பாட்டில் உள்ள ஸ்டாண்டர்டு டோக்கன்களை சேமிக்கும் ஒரு ஒப்பந்தமாகும்.
4 * இது ஒரு தொடர்புடைய L2 பாலத்தை ஒத்திசைக்கிறது, டெபாசிட்கள் குறித்து அதற்குத் தெரிவிக்கிறது
5 * மற்றும் புதிதாக இறுதி செய்யப்பட்ட திரும்பப் பெறுதல்களுக்காக அதைக் கேட்கிறது.
6 *
7 */
8contract L1StandardBridge is IL1StandardBridge, CrossDomainEnabled {
9 using SafeERC20 for IERC20;
அனைத்தையும் காட்டு

IERC20 இடைமுகத்தை ஒவ்வொரு முறையும் பயன்படுத்தும்போது SafeERC20 ரேப்பரைப் பயன்படுத்த வேண்டும் என்பதைக் குறிப்பிடுவது இந்த வரியாகும்.

1
2 /********************************
3 * வெளிப்புற ஒப்பந்தக் குறிப்புகள் *
4 ********************************/
5
6 address public l2TokenBridge;

L2StandardBridge முகவரி.

1
2 // L1 டோக்கனை L2 டோக்கனுக்கு டெபாசிட் செய்யப்பட்ட L1 டோக்கனின் இருப்புக்கு மேப் செய்கிறது.
3 mapping(address => mapping(address => uint256)) public deposits;

இது போன்ற ஒரு இரட்டை மேப்பிங்opens in a new tab என்பது ஒரு இரு பரிமாண சிதறிய அணியைopens in a new tab வரையறுக்கும் வழியாகும். இந்தத் தரவு கட்டமைப்பில் உள்ள மதிப்புகள் deposit[L1 டோக்கன் addr][L2 டோக்கன் addr] என அடையாளம் காணப்படுகின்றன. இயல்புநிலை மதிப்பு பூஜ்ஜியம். வேறுபட்ட மதிப்புக்கு அமைக்கப்பட்ட செல்கள் மட்டுமே சேமிப்பகத்தில் எழுதப்படும்.

1
2 /***************
3 * கட்டமைப்பாளர் *
4 ***************/
5
6 // இந்த ஒப்பந்தம் ஒரு ப்ராக்ஸியின் பின்னால் வாழ்கிறது, எனவே கட்டமைப்பாளர் அளவுருக்கள் பயன்படுத்தப்படாது.
7 constructor() CrossDomainEnabled(address(0)) {}

சேமிப்பகத்தில் உள்ள அனைத்து மாறிகளையும் நகலெடுக்க வேண்டிய அவசியமின்றி இந்த ஒப்பந்தத்தை மேம்படுத்த விரும்புகிறோம். அதைச் செய்ய, நாங்கள் ஒரு ப்ராக்ஸிopens in a new tabயைப் பயன்படுத்துகிறோம், இது ப்ராக்ஸி ஒப்பந்தத்தால் சேமிக்கப்பட்ட முகவரியைக் கொண்ட ஒரு தனி ஒப்பந்தத்திற்கு அழைப்புகளை மாற்ற delegatecallopens in a new tab ஐப் பயன்படுத்தும் ஒரு ஒப்பந்தமாகும் (நீங்கள் மேம்படுத்தும்போது அந்த முகவரியை மாற்றுமாறு ப்ராக்ஸியிடம் கூறுங்கள்). நீங்கள் delegatecall ஐப் பயன்படுத்தும் போது, சேமிப்பகம் அழைக்கும் ஒப்பந்தத்தின் சேமிப்பகமாகவே உள்ளது, எனவே அனைத்து ஒப்பந்த நிலை மாறிகளின் மதிப்புகளும் பாதிக்கப்படாது.

இந்த முறையின் ஒரு விளைவு என்னவென்றால், delegatecall இன் அழைக்கப்பட்ட ஒப்பந்தத்தின் சேமிப்பகம் பயன்படுத்தப்படவில்லை, எனவே அதற்குக் கொடுக்கப்பட்ட கட்டமைப்பாளர் மதிப்புகள் முக்கியமில்லை. CrossDomainEnabled கட்டமைப்பாளருக்கு நாம் ஒரு அர்த்தமற்ற மதிப்பை வழங்க முடியும் என்பது இதற்குக் காரணம். கீழே உள்ள தொடக்கம் கட்டமைப்பாளரிடமிருந்து பிரிக்கப்பட்டதற்கும் இதுவே காரணம்.

1 /******************
2 * தொடங்குதல் *
3 ******************/
4
5 /**
6 * @param _l1messenger கிராஸ்-செயின் தகவல்தொடர்புகளுக்குப் பயன்படுத்தப்படும் L1 மெசஞ்சர் முகவரி.
7 * @param _l2TokenBridge L2 ஸ்டாண்டர்டு பாலம் முகவரி.
8 */
9 // slither-disable-next-line external-function
அனைத்தையும் காட்டு

இந்த Slither சோதனைopens in a new tab ஒப்பந்தக் குறியீட்டிலிருந்து அழைக்கப்படாத செயல்பாடுகளை அடையாளம் கண்டு, எனவே public க்கு பதிலாக external என அறிவிக்கப்படலாம். external செயல்பாடுகளின் கேஸ் செலவு குறைவாக இருக்கலாம், ஏனெனில் அவை calldataவில் உள்ள அளவுருக்களுடன் வழங்கப்படலாம். public என அறிவிக்கப்பட்ட செயல்பாடுகள் ஒப்பந்தத்திற்குள் இருந்து அணுகக்கூடியதாக இருக்க வேண்டும். ஒப்பந்தங்கள் தங்கள் சொந்த calldataவை மாற்ற முடியாது, எனவே அளவுருக்கள் நினைவகத்தில் இருக்க வேண்டும். அத்தகைய ஒரு செயல்பாடு வெளிப்புறமாக அழைக்கப்படும்போது, calldataவை நினைவகத்திற்கு நகலெடுப்பது அவசியம், இது கேஸ் செலவாகும். இந்த விஷயத்தில் செயல்பாடு ஒரு முறை மட்டுமே அழைக்கப்படுகிறது, எனவே திறமையின்மை எங்களுக்கு ஒரு பொருட்டல்ல.

1 function initialize(address _l1messenger, address _l2TokenBridge) public {
2 require(messenger == address(0), "ஒப்பந்தம் ஏற்கனவே தொடங்கப்பட்டுள்ளது.");

initialize செயல்பாடு ஒரு முறை மட்டுமே அழைக்கப்பட வேண்டும். L1 கிராஸ் டொமைன் மெசஞ்சர் அல்லது L2 டோக்கன் பாலத்தின் முகவரி மாறினால், ஒரு புதிய ப்ராக்ஸியையும், அதை அழைக்கும் ஒரு புதிய பாலத்தையும் உருவாக்குகிறோம். முழு அமைப்பும் மேம்படுத்தப்படும்போது தவிர, இது மிகவும் அரிதான நிகழ்வாக நடக்க வாய்ப்பில்லை.

இந்தச் செயல்பாட்டில் யார் அதை அழைக்கலாம் என்பதைக் கட்டுப்படுத்தும் எந்தவொரு பொறிமுறையும் இல்லை என்பதைக் கவனத்தில் கொள்க. இதன் பொருள், கோட்பாட்டளவில், ஒரு தாக்குதல்காரர் நாங்கள் ப்ராக்ஸியையும் பாலத்தின் முதல் பதிப்பையும் பயன்படுத்தும் வரை காத்திருக்கலாம், பின்னர் சட்டப்பூர்வ பயனர் செய்வதற்கு முன்பு initialize செயல்பாட்டை அடைய முன் ஓட்டம்opens in a new tab செய்யலாம். ஆனால் இதைத் தடுக்க இரண்டு முறைகள் உள்ளன:

  1. ஒப்பந்தங்கள் நேரடியாக ஒரு EOA மூலம் பயன்படுத்தப்படாமல், அவற்றை உருவாக்கும் மற்றொரு ஒப்பந்தத்தைக் கொண்ட பரிவர்த்தனையில்opens in a new tab இருந்தால், முழு செயல்முறையும் அணுவாக இருக்கலாம், மேலும் வேறு எந்த பரிவர்த்தனையும் செயல்படுத்தப்படுவதற்கு முன்பு முடிவடையும்.
  2. initialize க்கான சட்டப்பூர்வ அழைப்பு தோல்வியுற்றால், புதிதாக உருவாக்கப்பட்ட ப்ராக்ஸி மற்றும் பாலத்தை புறக்கணித்து புதியவற்றை உருவாக்குவது எப்போதும் சாத்தியமாகும்.
1 messenger = _l1messenger;
2 l2TokenBridge = _l2TokenBridge;
3 }

பாலம் தெரிந்து கொள்ள வேண்டிய இரண்டு அளவுருக்கள் இவை.

1
2 /**************
3 * டெபாசிட்டிங் *
4 **************/
5
6 /** @dev அனுப்புநர் EOA ஆக இருக்க வேண்டிய மாற்றியமைப்பான். இந்தச் சோதனை ஒரு தீங்கிழைக்கும்
7 * ஒப்பந்தம் வழியாக initcode வழியாக கடந்து செல்லப்படலாம், ஆனால் இது நாம் தவிர்க்க விரும்பும் பயனர் பிழையைக் கவனித்துக்கொள்கிறது.
8 */
9 modifier onlyEOA() {
10 // ஒப்பந்தங்களிலிருந்து டெபாசிட்களைத் தடுக்கப் பயன்படுகிறது (தற்செயலாக இழந்த டோக்கன்களைத் தவிர்க்க)
11 require(!Address.isContract(msg.sender), "கணக்கு EOA அல்ல");
12 _;
13 }
அனைத்தையும் காட்டு

OpenZeppelin இன் முகவரி பயன்பாடுகள் எங்களுக்குத் தேவைப்படுவதற்கு இதுவே காரணம்.

1 /**
2 * @dev இந்தச் செயல்பாட்டை தரவு இல்லாமல் அழைக்கலாம்
3 * L2 இல் அழைப்பாளரின் இருப்புக்கு ETH தொகையை டெபாசிட் செய்ய.
4 * பெறுதல் செயல்பாடு தரவை எடுக்காததால், ஒரு பழமைவாத
5 * இயல்புநிலைத் தொகை L2 க்கு அனுப்பப்படுகிறது.
6 */
7 receive() external payable onlyEOA {
8 _initiateETHDeposit(msg.sender, msg.sender, 200_000, bytes(""));
9 }
அனைத்தையும் காட்டு

இந்தச் செயல்பாடு சோதனை நோக்கங்களுக்காக உள்ளது. இது இடைமுக வரையறைகளில் தோன்றவில்லை என்பதைக் கவனியுங்கள் - இது சாதாரண பயன்பாட்டிற்காக அல்ல.

1 /**
2 * @inheritdoc IL1StandardBridge
3 */
4 function depositETH(uint32 _l2Gas, bytes calldata _data) external payable onlyEOA {
5 _initiateETHDeposit(msg.sender, msg.sender, _l2Gas, _data);
6 }
7
8 /**
9 * @inheritdoc IL1StandardBridge
10 */
11 function depositETHTo(
12 address _to,
13 uint32 _l2Gas,
14 bytes calldata _data
15 ) external payable {
16 _initiateETHDeposit(msg.sender, _to, _l2Gas, _data);
17 }
அனைத்தையும் காட்டு

இந்த இரண்டு செயல்பாடுகளும் உண்மையான ETH டெபாசிட்டைக் கையாளும் செயல்பாடான _initiateETHDepositஐச் சுற்றியுள்ள ரேப்பர்கள் ஆகும்.

1 /**
2 * @dev ETH ஐச் சேமித்து, L2 ETH கேட்வேக்கு டெபாசிட் குறித்துத் தெரிவிப்பதன் மூலம் டெபாசிட்களுக்கான தர்க்கத்தைச் செய்கிறது.
3 * @param _from L1 இல் இருந்து டெபாசிட்டைப் பெற கணக்கு.
4 * @param _to L2 இல் டெபாசிட்டைக் கொடுக்க கணக்கு.
5 * @param _l2Gas L2 இல் டெபாசிட்டை முடிக்கத் தேவையான கேஸ் வரம்பு.
6 * @param _data L2க்கு அனுப்ப விருப்பத் தரவு. இந்தத் தரவு வழங்கப்பட்டுள்ளது
7 * வெளிப்புற ஒப்பந்தங்களுக்கான வசதிக்காக மட்டுமே. அதிகபட்சமாகச் செயல்படுத்துவதைத் தவிர
8 * நீளம், இந்த ஒப்பந்தங்கள் அதன் உள்ளடக்கம் பற்றி எந்த உத்தரவாதமும் அளிக்காது.
9 */
10 function _initiateETHDeposit(
11 address _from,
12 address _to,
13 uint32 _l2Gas,
14 bytes memory _data
15 ) internal {
16 // finalizeDeposit அழைப்பிற்கான calldataவை உருவாக்குங்கள்
17 bytes memory message = abi.encodeWithSelector(
அனைத்தையும் காட்டு

கிராஸ் டொமைன் செய்திகள் செயல்படும் வழி என்னவென்றால், இலக்கு ஒப்பந்தம் செய்தியுடன் அதன் கால்தேட்டாவாக அழைக்கப்படுகிறது. சொலிடிட்டி ஒப்பந்தங்கள் எப்போதும் அவற்றின் கால்தேட்டாவை ABI விவரக்குறிப்புகளுக்குopens in a new tab ஏற்ப விளக்குகின்றன. சொலிடிட்டி செயல்பாடு abi.encodeWithSelectoropens in a new tab அந்தக் கால்தேட்டாவை உருவாக்குகிறது.

1 IL2ERC20Bridge.finalizeDeposit.selector,
2 address(0),
3 Lib_PredeployAddresses.OVM_ETH,
4 _from,
5 _to,
6 msg.value,
7 _data
8 );

இங்கே செய்தி இந்த அளவுருக்களுடன் finalizeDeposit செயல்பாட்டைopens in a new tab அழைப்பதாகும்:

அளவுருமதிப்புபொருள்
_l1Tokenமுகவரி(0)L1 இல் ETH (இது ஒரு ERC-20 டோக்கன் அல்ல) க்கு நிற்க சிறப்பு மதிப்பு
_l2TokenLib_PredeployAddresses.OVM_ETHஆப்டிமிசத்தில் ETH ஐ நிர்வகிக்கும் L2 ஒப்பந்தம், 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000 (இந்த ஒப்பந்தம் உள் ஆப்டிமிசம் பயன்பாட்டிற்கு மட்டுமே)
_from_fromL1 இல் ETH ஐ அனுப்பும் முகவரி
_to_toL2 இல் ETH ஐப் பெறும் முகவரி
தொகைmsg.valueஅனுப்பப்பட்ட wei இன் அளவு (இது ஏற்கனவே பாலத்திற்கு அனுப்பப்பட்டுள்ளது)
_data_dataடெபாசிட்டில் இணைக்க கூடுதல் தரவு
1 // கால்தேட்டாவை L2 இல் அனுப்புங்கள்
2 // slither-disable-next-line reentrancy-events
3 sendCrossDomainMessage(l2TokenBridge, _l2Gas, message);

கிராஸ் டொமைன் மெசஞ்சர் மூலம் செய்தியை அனுப்பவும்.

1 // slither-disable-next-line reentrancy-events
2 emit ETHDepositInitiated(_from, _to, msg.value, _data);
3 }

இந்த இடமாற்றத்தைக் கேட்கும் எந்தவொரு பரவலாக்கப்பட்ட பயன்பாட்டிற்கும் தெரிவிக்க ஒரு நிகழ்வை வெளியிடுங்கள்.

1 /**
2 * @inheritdoc IL1ERC20Bridge
3 */
4 function depositERC20(
5 .
6 .
7 .
8 ) external virtual onlyEOA {
9 _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, msg.sender, _amount, _l2Gas, _data);
10 }
11
12 /**
13 * @inheritdoc IL1ERC20Bridge
14 */
15 function depositERC20To(
16 .
17 .
18 .
19 ) external virtual {
20 _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, _to, _amount, _l2Gas, _data);
21 }
அனைத்தையும் காட்டு

இந்த இரண்டு செயல்பாடுகளும் உண்மையான ERC-20 டெபாசிட்டைக் கையாளும் செயல்பாடான _initiateERC20Depositஐச் சுற்றியுள்ள ரேப்பர்கள் ஆகும்.

1 /**
2 * @dev டெபாசிட் செய்யப்பட்ட டோக்கன் ஒப்பந்தத்திற்கு டெபாசிட் குறித்துத் தெரிவிப்பதன் மூலம் டெபாசிட்களுக்கான தர்க்கத்தைச் செய்கிறது.
3 * L2 நிதிகளைப் பூட்ட ஒரு ஹேண்ட்லரை அழைத்தல். (எ.கா., transferFrom)
4 *
5 * @param _l1Token நாங்கள் டெபாசிட் செய்யும் L1 ERC20 இன் முகவரி
6 * @param _l2Token L1 இன் அந்தந்த L2 ERC20 இன் முகவரி
7 * @param _from L1 இல் இருந்து டெபாசிட்டைப் பெற கணக்கு
8 * @param _to L2 இல் டெபாசிட்டைக் கொடுக்க கணக்கு
9 * @param _amount டெபாசிட் செய்ய வேண்டிய ERC20 இன் அளவு.
10 * @param _l2Gas L2 இல் டெபாசிட்டை முடிக்கத் தேவையான கேஸ் வரம்பு.
11 * @param _data L2க்கு அனுப்ப விருப்பத் தரவு. இந்தத் தரவு வழங்கப்பட்டுள்ளது
12 * வெளிப்புற ஒப்பந்தங்களுக்கான வசதிக்காக மட்டுமே. அதிகபட்சமாகச் செயல்படுத்துவதைத் தவிர
13 * நீளம், இந்த ஒப்பந்தங்கள் அதன் உள்ளடக்கம் பற்றி எந்த உத்தரவாதமும் அளிக்காது.
14 */
15 function _initiateERC20Deposit(
16 address _l1Token,
17 address _l2Token,
18 address _from,
19 address _to,
20 uint256 _amount,
21 uint32 _l2Gas,
22 bytes calldata _data
23 ) internal {
அனைத்தையும் காட்டு

இந்தச் செயல்பாடு மேலே உள்ள _initiateETHDepositஐப் போன்றது, சில முக்கியமான வேறுபாடுகளுடன். முதல் வேறுபாடு என்னவென்றால், இந்தச் செயல்பாடு டோக்கன் முகவரிகளையும், அளவுருக்களாக மாற்ற வேண்டிய தொகையையும் பெறுகிறது. ETH ஐப் பொறுத்தவரை, பாலத்திற்கான அழைப்பில் ஏற்கனவே சொத்து பாலக் கணக்கிற்கு மாற்றுவது (msg.value) அடங்கும்.

1 // L1 இல் டெபாசிட் தொடங்கப்பட்டதும், L1 பாலம் எதிர்கால திரும்பப் பெறுதல்களுக்காக நிதியைத் தனக்குத்தானே மாற்றும். safeTransferFrom ஒப்பந்தத்தில் குறியீடு உள்ளதா என்பதையும் சரிபார்க்கிறது, எனவே _from ஒரு EOA அல்லது முகவரி(0) ஆக இருந்தால் இது தோல்வியடையும்.
2 // slither-disable-next-line reentrancy-events, reentrancy-benign
3 IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount);

ERC-20 டோக்கன் இடமாற்றங்கள் ETH இலிருந்து வேறுபட்ட செயல்முறையைப் பின்பற்றுகின்றன:

  1. பயனர் (_from) பொருத்தமான டோக்கன்களை மாற்ற பாலத்திற்கு ஒரு கொடுப்பனவை வழங்குகிறார்.
  2. பயனர் டோக்கன் ஒப்பந்தத்தின் முகவரி, தொகை போன்றவற்றைக் கொண்டு பாலத்தை அழைக்கிறார்.
  3. பாலம் டெபாசிட் செயல்முறையின் ஒரு பகுதியாக டோக்கன்களை (தனக்கே) மாற்றுகிறது.

முதல் படி கடைசி இரண்டு பரிவர்த்தனையிலிருந்து ஒரு தனி பரிவர்த்தனையில் நடக்கலாம். இருப்பினும், முன்-ஓட்டம் ஒரு பிரச்சனை அல்ல, ஏனெனில் _initiateERC20Deposit (depositERC20 மற்றும் depositERC20To) ஐ அழைக்கும் இரண்டு செயல்பாடுகள் _from அளவுருவாக msg.sender உடன் மட்டுமே இந்தச் செயல்பாட்டை அழைக்கின்றன.

1 // _l2Token.finalizeDeposit(_to, _amount) க்கான கால்தேட்டாவை உருவாக்குங்கள்
2 bytes memory message = abi.encodeWithSelector(
3 IL2ERC20Bridge.finalizeDeposit.selector,
4 _l1Token,
5 _l2Token,
6 _from,
7 _to,
8 _amount,
9 _data
10 );
11
12 // கால்தேட்டாவை L2 இல் அனுப்புங்கள்
13 // slither-disable-next-line reentrancy-events, reentrancy-benign
14 sendCrossDomainMessage(l2TokenBridge, _l2Gas, message);
15
16 // slither-disable-next-line reentrancy-benign
17 deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] + _amount;
அனைத்தையும் காட்டு

deposits தரவு அமைப்பில் டெபாசிட் செய்யப்பட்ட டோக்கன்களின் அளவைச் சேர்க்கவும். ஒரே L1 ERC-20 டோக்கனுக்குரிய பல முகவரிகள் L2 இல் இருக்கலாம், எனவே டெபாசிட்களைக் கண்காணிக்க பாலத்தின் L1 ERC-20 டோக்கன் இருப்பைப் பயன்படுத்துவது போதுமானதல்ல.

1
2 // slither-disable-next-line reentrancy-events
3 emit ERC20DepositInitiated(_l1Token, _l2Token, _from, _to, _amount, _data);
4 }
5
6 /*************************
7 * கிராஸ்-செயின் செயல்பாடுகள் *
8 *************************/
9
10 /**
11 * @inheritdoc IL1StandardBridge
12 */
13 function finalizeETHWithdrawal(
14 address _from,
15 address _to,
16 uint256 _amount,
17 bytes calldata _data
அனைத்தையும் காட்டு

L2 பாலம் L2 கிராஸ் டொமைன் மெசஞ்சருக்கு ஒரு செய்தியை அனுப்புகிறது, இது L1 கிராஸ் டொமைன் மெசஞ்சரை இந்தச் செயல்பாட்டை அழைக்கச் செய்கிறது (செய்தியை இறுதி செய்யும் பரிவர்த்தனைopens in a new tab L1 இல் சமர்ப்பிக்கப்பட்டவுடன், நிச்சயமாக).

1 ) external onlyFromCrossDomainAccount(l2TokenBridge) {

இது கிராஸ் டொமைன் மெசஞ்சரிடமிருந்து மற்றும் L2 டோக்கன் பாலத்திலிருந்து உருவாகும் ஒரு சட்டப்பூர்வமான செய்தி என்பதை உறுதிப்படுத்திக் கொள்ளுங்கள். இந்தச் செயல்பாடு பாலத்திலிருந்து ETH ஐத் திரும்பப் பெறப் பயன்படுகிறது, எனவே இது அங்கீகரிக்கப்பட்ட அழைப்பாளரால் மட்டுமே அழைக்கப்படுவதை நாங்கள் உறுதி செய்ய வேண்டும்.

1 // slither-disable-next-line reentrancy-events
2 (bool success, ) = _to.call{ value: _amount }(new bytes(0));

ETH ஐ மாற்றுவதற்கான வழி, msg.value இல் wei இன் தொகையுடன் பெறுநரை அழைப்பதாகும்.

1 require(success, "TransferHelper::safeTransferETH: ETH இடமாற்றம் தோல்வியடைந்தது");
2
3 // slither-disable-next-line reentrancy-events
4 emit ETHWithdrawalFinalized(_from, _to, _amount, _data);

திரும்பப் பெறுவது பற்றிய ஒரு நிகழ்வை வெளியிடுங்கள்.

1 }
2
3 /**
4 * @inheritdoc IL1ERC20Bridge
5 */
6 function finalizeERC20Withdrawal(
7 address _l1Token,
8 address _l2Token,
9 address _from,
10 address _to,
11 uint256 _amount,
12 bytes calldata _data
13 ) external onlyFromCrossDomainAccount(l2TokenBridge) {
அனைத்தையும் காட்டு

இந்தச் செயல்பாடு மேலே உள்ள finalizeETHWithdrawal ஐப் போன்றது, ERC-20 டோக்கன்களுக்குத் தேவையான மாற்றங்களுடன்.

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

deposits தரவு கட்டமைப்பைப் புதுப்பிக்கவும்.

1
2 // L1 இல் திரும்பப் பெறுவது இறுதி செய்யப்பட்டதும், L1 பாலம் திரும்பப் பெறுபவருக்கு நிதியை மாற்றுகிறது.
3 // slither-disable-next-line reentrancy-events
4 IERC20(_l1Token).safeTransfer(_to, _amount);
5
6 // slither-disable-next-line reentrancy-events
7 emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);
8 }
9
10
11 /*****************************
12 * தற்காலிகம் - ETH ஐ இடம்பெயர்தல் *
13 *****************************/
14
15 /**
16 * @dev கணக்கிற்கு ETH இருப்பைச் சேர்க்கிறது. இது ETH
17 * பழைய நுழைவாயிலிலிருந்து புதிய நுழைவாயிலுக்கு இடம்பெயர்வதை அனுமதிக்க வேண்டும்.
18 * குறிப்பு: இது ஒரு மேம்பாட்டிற்கு மட்டுமே விடப்பட்டுள்ளது, எனவே பழைய ஒப்பந்தத்திலிருந்து இடம்பெயர்ந்த ETH ஐப் பெற முடிகிறது.
19 *
20 */
21 function donateETH() external payable {}
22}
அனைத்தையும் காட்டு

பாலத்தின் முந்தைய செயலாக்கம் இருந்தது. இந்த செயலாக்கத்திலிருந்து இதற்கு மாறியபோது, நாங்கள் அனைத்து சொத்துகளையும் நகர்த்த வேண்டியிருந்தது. ERC-20 டோக்கன்களை நகர்த்தலாம். இருப்பினும், ஒரு ஒப்பந்தத்திற்கு ETH ஐ மாற்றுவதற்கு அந்த ஒப்பந்தத்தின் ஒப்புதல் தேவை, அதை donateETH எங்களுக்கு வழங்குகிறது.

L2 இல் ERC-20 டோக்கன்கள்

ஒரு ERC-20 டோக்கன் ஸ்டாண்டர்டு பாலத்தில் பொருந்துவதற்கு, அது ஸ்டாண்டர்டு பாலத்தை, மற்றும் மட்டுமே ஸ்டாண்டர்டு பாலத்தை டோக்கனை உருவாக்க அனுமதிக்க வேண்டும். ஆப்டிமிசத்தில் புழக்கத்தில் உள்ள டோக்கன்களின் எண்ணிக்கை L1 பாலம் ஒப்பந்தத்திற்குள் பூட்டப்பட்ட டோக்கன்களின் எண்ணிக்கைக்கு சமம் என்பதை பாலங்கள் உறுதி செய்ய வேண்டியது அவசியம். L2 இல் அதிகப்படியான டோக்கன்கள் இருந்தால், சில பயனர்கள் தங்கள் சொத்துக்களை மீண்டும் L1 க்கு பாலமிட முடியாது. நம்பகமான பாலத்திற்கு பதிலாக, நாங்கள் அடிப்படையில் பகுதி இருப்பு வங்கியைopens in a new tab மீண்டும் உருவாக்குவோம். L1 இல் அதிகப்படியான டோக்கன்கள் இருந்தால், அந்த டோக்கன்களில் சில பாலம் ஒப்பந்தத்திற்குள் என்றென்றும் பூட்டப்படும், ஏனெனில் L2 டோக்கன்களை எரிக்காமல் அவற்றை விடுவிக்க வழி இல்லை.

IL2StandardERC20

ஸ்டாண்டர்டு பாலத்தைப் பயன்படுத்தும் L2 இல் உள்ள ஒவ்வொரு ERC-20 டோக்கனும் இந்த இடைமுகத்தைopens in a new tab வழங்க வேண்டும், இது ஸ்டாண்டர்டு பாலத்திற்குத் தேவையான செயல்பாடுகள் மற்றும் நிகழ்வுகளைக் கொண்டுள்ளது.

1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.9;
3
4import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

ஸ்டாண்டர்டு ERC-20 இடைமுகம்opens in a new tab mint மற்றும் burn செயல்பாடுகளை உள்ளடக்கவில்லை. அந்த முறைகள் ERC-20 தரநிலைopens in a new tab மூலம் தேவைப்படாது, இது டோக்கன்களை உருவாக்குவதற்கும் அழிப்பதற்கும் உள்ள பொறிமுறைகளை குறிப்பிடாமல் விட்டுவிடுகிறது.

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

ERC-165 இடைமுகம்opens in a new tab ஒரு ஒப்பந்தம் என்னென்ன செயல்பாடுகளை வழங்குகிறது என்பதைக் குறிப்பிடப் பயன்படுகிறது. தரநிலையை இங்கே படிக்கலாம்opens in a new tab.

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

இந்த ஒப்பந்தத்தில் இணைக்கப்பட்ட L1 டோக்கனின் முகவரியை இந்தச் செயல்பாடு வழங்குகிறது. எதிர் திசையில் இதேபோன்ற செயல்பாடு எங்களிடம் இல்லை என்பதை நினைவில் கொள்க. L2 ஆதரவு திட்டமிடப்பட்டதா இல்லையா என்பதைப் பொருட்படுத்தாமல், எந்த L1 டோக்கனையும் நாங்கள் பாலமிட வேண்டும்.

1
2 function mint(address _to, uint256 _amount) external;
3
4 function burn(address _from, uint256 _amount) external;
5
6 event Mint(address indexed _account, uint256 _amount);
7 event Burn(address indexed _account, uint256 _amount);
8}

டோக்கன்களை உருவாக்க (create) மற்றும் எரிக்க (destroy) செயல்பாடுகள் மற்றும் நிகழ்வுகள். டோக்கன்களின் எண்ணிக்கை சரியானது (L1 இல் பூட்டப்பட்ட டோக்கன்களின் எண்ணிக்கைக்கு சமம்) என்பதை உறுதிப்படுத்த இந்தச் செயல்பாடுகளை இயக்கக்கூடிய ஒரே நிறுவனம் பாலமாக இருக்க வேண்டும்.

L2StandardERC20

இது IL2StandardERC20 இடைமுகத்தின் எங்கள் செயல்படுத்தலாகும்opens in a new tab. உங்களுக்கு ஏதேனும் தனிப்பயன் தர்க்கம் தேவைப்படாவிட்டால், இதைப் பயன்படுத்த வேண்டும்.

1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.9;
3
4import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

OpenZeppelin ERC-20 ஒப்பந்தம்opens in a new tab. ஆப்டிமிசம் சக்கரத்தை மீண்டும் கண்டுபிடிப்பதில் நம்பிக்கை கொள்ளவில்லை, குறிப்பாக சக்கரம் நன்கு தணிக்கை செய்யப்பட்டு, சொத்துக்களை வைத்திருக்க போதுமான நம்பகத்தன்மையுடன் இருக்க வேண்டும்.

1import "./IL2StandardERC20.sol";
2
3contract L2StandardERC20 is IL2StandardERC20, ERC20 {
4 address public l1Token;
5 address public l2Bridge;

எங்களுக்குத் தேவைப்படும் மற்றும் ERC-20 பொதுவாக இல்லாத இரண்டு கூடுதல் கட்டமைப்பு அளவுருக்கள் இவை.

1
2 /**
3 * @param _l2Bridge L2 ஸ்டாண்டர்டு பாலத்தின் முகவரி.
4 * @param _l1Token தொடர்புடைய L1 டோக்கனின் முகவரி.
5 * @param _name ERC20 பெயர்.
6 * @param _symbol ERC20 சின்னம்.
7 */
8 constructor(
9 address _l2Bridge,
10 address _l1Token,
11 string memory _name,
12 string memory _symbol
13 ) ERC20(_name, _symbol) {
14 l1Token = _l1Token;
15 l2Bridge = _l2Bridge;
16 }
அனைத்தையும் காட்டு

முதலில் நாம் மரபுரிமையாகப் பெறும் ஒப்பந்தத்திற்கான கட்டமைப்பாளரை அழைக்கவும் (ERC20(_name, _symbol)) பின்னர் எங்கள் சொந்த மாறிகளை அமைக்கவும்.

1
2 modifier onlyL2Bridge() {
3 require(msg.sender == l2Bridge, "L2 பாலம் மட்டுமே உருவாக்கி எரிக்க முடியும்");
4 _;
5 }
6
7
8 // slither-disable-next-line external-function
9 function supportsInterface(bytes4 _interfaceId) public pure returns (bool) {
10 bytes4 firstSupportedInterface = bytes4(keccak256("supportsInterface(bytes4)")); // ERC165
11 bytes4 secondSupportedInterface = IL2StandardERC20.l1Token.selector ^
12 IL2StandardERC20.mint.selector ^
13 IL2StandardERC20.burn.selector;
14 return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;
15 }
அனைத்தையும் காட்டு

ERC-165opens in a new tab இப்படித்தான் செயல்படுகிறது. ஒவ்வொரு இடைமுகமும் பல ஆதரிக்கப்படும் செயல்பாடுகளாகும், மேலும் அந்தச் செயல்பாடுகளின் ABI செயல்பாட்டு தேர்வாளர்களின்opens in a new tab பிரத்தியேகமான அல்லதுopens in a new tab என அடையாளம் காணப்படுகிறது.

L2 பாலம் ERC-165 ஐ அது சொத்துக்களை அனுப்பும் ERC-20 ஒப்பந்தம் ஒரு IL2StandardERC20 என்பதை உறுதிப்படுத்த ஒரு நல்ல சோதனையாகப் பயன்படுத்துகிறது.

குறிப்பு: supportsInterface க்கு தவறான பதில்களை வழங்குவதிலிருந்து மோசடி ஒப்பந்தத்தைத் தடுக்க எதுவும் இல்லை, எனவே இது ஒரு ஆரோக்கியமான சோதனை வழிமுறையாகும், ஒரு பாதுகாப்பு வழிமுறை அல்ல.

1 // slither-disable-next-line external-function
2 function mint(address _to, uint256 _amount) public virtual onlyL2Bridge {
3 _mint(_to, _amount);
4
5 emit Mint(_to, _amount);
6 }
7
8 // slither-disable-next-line external-function
9 function burn(address _from, uint256 _amount) public virtual onlyL2Bridge {
10 _burn(_from, _amount);
11
12 emit Burn(_from, _amount);
13 }
14}
அனைத்தையும் காட்டு

L2 பாலம் மட்டுமே சொத்துக்களை உருவாக்கி எரிக்க அனுமதிக்கப்படுகிறது.

_mint மற்றும் _burn உண்மையில் OpenZeppelin ERC-20 ஒப்பந்தத்தில் வரையறுக்கப்பட்டுள்ளன. அந்த ஒப்பந்தம் அவற்றை வெளிப்புறமாக வெளிப்படுத்தவில்லை, ஏனெனில் டோக்கன்களை உருவாக்குவதற்கும் எரிப்பதற்கும் உள்ள நிபந்தனைகள் ERC-20 ஐப் பயன்படுத்துவதற்கான வழிகளின் எண்ணிக்கையைப் போலவே மாறுபட்டவை.

L2 பாலம் குறியீடு

இது ஆப்டிமிசத்தில் பாலத்தை இயக்கும் குறியீடாகும். இந்த ஒப்பந்தத்திற்கான ஆதாரம் இங்கே உள்ளதுopens in a new tab.

1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.9;
3
4/* Interface Imports */
5import { IL1StandardBridge } from "../../L1/messaging/IL1StandardBridge.sol";
6import { IL1ERC20Bridge } from "../../L1/messaging/IL1ERC20Bridge.sol";
7import { IL2ERC20Bridge } from "./IL2ERC20Bridge.sol";

IL2ERC20Bridgeopens in a new tab இடைமுகம் மேலே நாம் பார்த்த L1 க்கு சமமானதற்கு மிகவும் ஒத்ததாகும். இரண்டு குறிப்பிடத்தக்க வேறுபாடுகள் உள்ளன:

  1. L1 இல் நீங்கள் டெபாசிட்களைத் தொடங்கி, திரும்பப் பெறுதல்களை இறுதி செய்கிறீர்கள். இங்கே நீங்கள் திரும்பப் பெறுதல்களைத் தொடங்கி, டெபாசிட்களை இறுதி செய்கிறீர்கள்.
  2. L1 இல் ETH மற்றும் ERC-20 டோக்கன்களுக்கு இடையில் வேறுபாடு காண்பது அவசியம். L2 இல் நாம் இரண்டிற்கும் ஒரே செயல்பாடுகளைப் பயன்படுத்தலாம், ஏனெனில் ஆப்டிமிசத்தில் உள்ள ETH இருப்புகள் உள்நாட்டில் 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000opens in a new tab முகவரியுடன் ERC-20 டோக்கனாகக் கையாளப்படுகின்றன.
1/* Library Imports */
2import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
3import { CrossDomainEnabled } from "../../libraries/bridge/CrossDomainEnabled.sol";
4import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
5
6/* Contract Imports */
7import { IL2StandardERC20 } from "../../standards/IL2StandardERC20.sol";
8
9/**
10 * @title L2StandardBridge
11 * @dev L2 ஸ்டாண்டர்டு பாலம் என்பது L1 ஸ்டாண்டர்டு பாலத்துடன் இணைந்து செயல்படும் ஒரு ஒப்பந்தமாகும்.
12 * L1 மற்றும் L2 க்கு இடையில் ETH மற்றும் ERC20 மாற்றங்களை இயக்கவும்.
13 * L1 ஸ்டாண்டர்டு பாலத்தில் டெபாசிட்கள் குறித்துக் கேட்கும் போது இந்த ஒப்பந்தம் புதிய டோக்கன்களுக்கு ஒரு மின்ட்டராகச் செயல்படுகிறது.
14 * திரும்பப் பெறுவதற்காக உத்தேசிக்கப்பட்ட டோக்கன்களை எரிப்பதாகவும் இந்த ஒப்பந்தம் செயல்படுகிறது, L1 நிதிகளை விடுவிப்பதற்காக L1 பாலத்திற்குத் தெரிவிக்கிறது.
15 *
16 */
17contract L2StandardBridge is IL2ERC20Bridge, CrossDomainEnabled {
18 /********************************
19 * வெளிப்புற ஒப்பந்தக் குறிப்புகள் *
20 ********************************/
21
22 address public l1TokenBridge;
அனைத்தையும் காட்டு

L1 பாலத்தின் முகவரியைக் கண்காணிக்கவும். L1 க்கு சமமானதைக் காட்டிலும், இங்கே இந்த மாறி எங்களுக்குத் தேவை என்பதைக் கவனத்தில் கொள்க. L1 பாலத்தின் முகவரி முன்கூட்டியே தெரியாது.

1
2 /***************
3 * கட்டமைப்பாளர் *
4 ***************/
5
6 /**
7 * @param _l2CrossDomainMessenger இந்த ஒப்பந்தத்தால் பயன்படுத்தப்படும் கிராஸ்-டொமைன் மெசஞ்சர்.
8 * @param _l1TokenBridge பிரதான சங்கிலியில் பயன்படுத்தப்பட்ட L1 பாலத்தின் முகவரி.
9 */
10 constructor(address _l2CrossDomainMessenger, address _l1TokenBridge)
11 CrossDomainEnabled(_l2CrossDomainMessenger)
12 {
13 l1TokenBridge = _l1TokenBridge;
14 }
15
16 /***************
17 * திரும்பப் பெறுதல் *
18 ***************/
19
20 /**
21 * @inheritdoc IL2ERC20Bridge
22 */
23 function withdraw(
24 address _l2Token,
25 uint256 _amount,
26 uint32 _l1Gas,
27 bytes calldata _data
28 ) external virtual {
29 _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _l1Gas, _data);
30 }
31
32 /**
33 * @inheritdoc IL2ERC20Bridge
34 */
35 function withdrawTo(
36 address _l2Token,
37 address _to,
38 uint256 _amount,
39 uint32 _l1Gas,
40 bytes calldata _data
41 ) external virtual {
42 _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _l1Gas, _data);
43 }
அனைத்தையும் காட்டு

இந்த இரண்டு செயல்பாடுகளும் திரும்பப் பெறுதல்களைத் தொடங்குகின்றன. L1 டோக்கன் முகவரியைக் குறிப்பிட வேண்டிய அவசியமில்லை என்பதைக் கவனத்தில் கொள்க. L2 டோக்கன்கள் L1 க்கு சமமானவற்றின் முகவரியை எங்களுக்குத் தெரிவிக்கும் என்று எதிர்பார்க்கப்படுகிறது.

1
2 /**
3 * @dev டோக்கனை எரிப்பதன் மூலம் மற்றும் திரும்பப் பெறுவது குறித்து L1 டோக்கன் கேட்வேக்குத் தெரிவிப்பதன் மூலம்
4 * திரும்பப் பெறுதல்களுக்கான தர்க்கத்தைச் செய்கிறது.
5 * @param _l2Token திரும்பப் பெறுதல் தொடங்கப்பட்ட L2 டோக்கனின் முகவரி.
6 * @param _from L2 இல் இருந்து திரும்பப் பெறுவதைக் கணக்கிடுங்கள்.
7 * @param _to L1 இல் திரும்பப் பெறுவதைக் கணக்கிடுங்கள்.
8 * @param _amount திரும்பப் பெற வேண்டிய டோக்கனின் அளவு.
9 * @param _l1Gas பயன்படுத்தப்படாதது, ஆனால் சாத்தியமான முன்னோக்கி பொருந்தக்கூடிய கருத்தில் சேர்க்கப்பட்டுள்ளது.
10 * @param _data L1 க்கு அனுப்ப விருப்பத் தரவு. இந்தத் தரவு வழங்கப்பட்டுள்ளது
11 * வெளிப்புற ஒப்பந்தங்களுக்கான வசதிக்காக மட்டுமே. அதிகபட்சமாகச் செயல்படுத்துவதைத் தவிர
12 * நீளம், இந்த ஒப்பந்தங்கள் அதன் உள்ளடக்கம் பற்றி எந்த உத்தரவாதமும் அளிக்காது.
13 */
14 function _initiateWithdrawal(
15 address _l2Token,
16 address _from,
17 address _to,
18 uint256 _amount,
19 uint32 _l1Gas,
20 bytes calldata _data
21 ) internal {
22 // திரும்பப் பெறுதல் தொடங்கப்பட்டதும், அடுத்தடுத்த L2 பயன்பாட்டைத் தடுக்க திரும்பப் பெறுபவரின் நிதியை நாங்கள் எரிக்கிறோம்.
23 // slither-disable-next-line reentrancy-events
24 IL2StandardERC20(_l2Token).burn(msg.sender, _amount);
அனைத்தையும் காட்டு

நாங்கள் _from அளவுருவைச் சார்ந்திருக்கவில்லை, ஆனால் msg.senderஐச் சார்ந்திருக்கிறோம், இது போலியாக மாற்றுவது மிகவும் கடினமானது (எனக்குத் தெரிந்தவரை சாத்தியமற்றது).

1
2 // l1TokenBridge.finalizeERC20Withdrawal(_to, _amount) க்கான கால்தேட்டாவை உருவாக்குங்கள்
3 // slither-disable-next-line reentrancy-events
4 address l1Token = IL2StandardERC20(_l2Token).l1Token();
5 bytes memory message;
6
7 if (_l2Token == Lib_PredeployAddresses.OVM_ETH) {

L1 இல் ETH மற்றும் ERC-20 க்கு இடையில் வேறுபாடு காண்பது அவசியம்.

1 message = abi.encodeWithSelector(
2 IL1StandardBridge.finalizeETHWithdrawal.selector,
3 _from,
4 _to,
5 _amount,
6 _data
7 );
8 } else {
9 message = abi.encodeWithSelector(
10 IL1ERC20Bridge.finalizeERC20Withdrawal.selector,
11 l1Token,
12 _l2Token,
13 _from,
14 _to,
15 _amount,
16 _data
17 );
18 }
19
20 // செய்தியை L1 பாலத்திற்கு அனுப்பவும்
21 // slither-disable-next-line reentrancy-events
22 sendCrossDomainMessage(l1TokenBridge, _l1Gas, message);
23
24 // slither-disable-next-line reentrancy-events
25 emit WithdrawalInitiated(l1Token, _l2Token, msg.sender, _to, _amount, _data);
26 }
27
28 /************************************
29 * கிராஸ்-செயின் செயல்பாடு: டெபாசிட் செய்தல் *
30 ************************************/
31
32 /**
33 * @inheritdoc IL2ERC20Bridge
34 */
35 function finalizeDeposit(
36 address _l1Token,
37 address _l2Token,
38 address _from,
39 address _to,
40 uint256 _amount,
41 bytes calldata _data
அனைத்தையும் காட்டு

இந்தச் செயல்பாடு L1StandardBridgeஆல் அழைக்கப்படுகிறது.

1 ) external virtual onlyFromCrossDomainAccount(l1TokenBridge) {

செய்தியின் ஆதாரம் சட்டப்பூர்வமானது என்பதை உறுதிப்படுத்தவும். இந்தச் செயல்பாடு _mintஐ அழைப்பதால் இது முக்கியமானது, மேலும் L1 இல் பாலத்திற்குச் சொந்தமான டோக்கன்களால் மூடப்படாத டோக்கன்களை வழங்கப் பயன்படுத்தப்படலாம்.

1 // இலக்கு டோக்கன் இணக்கமாக உள்ளதா எனச் சரிபார்த்து, L1 இல் டெபாசிட் செய்யப்பட்ட டோக்கன் இங்குள்ள L2 டெபாசிட் செய்யப்பட்ட டோக்கன் பிரதிநிதித்துவத்துடன் பொருந்துகிறதா என்பதைச் சரிபார்க்கவும்.
2 if (
3 // slither-disable-next-line reentrancy-events
4 ERC165Checker.supportsInterface(_l2Token, 0x1d1d8b63) &&
5 _l1Token == IL2StandardERC20(_l2Token).l1Token()

ஆரோக்கிய சோதனைகள்:

  1. சரியான இடைமுகம் ஆதரிக்கப்படுகிறது
  2. L2 ERC-20 ஒப்பந்தத்தின் L1 முகவரி டோக்கன்களின் L1 மூலத்துடன் பொருந்துகிறது.
1 ) {
2 // டெபாசிட் இறுதி செய்யப்பட்டதும், அதே அளவு டோக்கன்களுடன் L2 இல் உள்ள கணக்கிற்கு நாங்கள் வரவு வைக்கிறோம்.
3 //
4 // slither-disable-next-line reentrancy-events
5 IL2StandardERC20(_l2Token).mint(_to, _amount);
6 // slither-disable-next-line reentrancy-events
7 emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);

ஆரோக்கிய சோதனைகள் தேர்ச்சி பெற்றால், டெபாசிட்டை இறுதி செய்யவும்:

  1. டோக்கன்களை உருவாக்கவும்
  2. பொருத்தமான நிகழ்வை வெளியிடுங்கள்
1 } else {
2 // டெபாசிட் செய்யப்படும் L2 டோக்கன் அதன் L1 டோக்கனின் சரியான முகவரி குறித்து உடன்படவில்லை, அல்லது சரியான இடைமுகத்தை ஆதரிக்கவில்லை.
3 // இது ஒரு தீங்கிழைக்கும் L2 டோக்கன் இருந்தால், அல்லது ஒரு பயனர் எப்படியாவது தவறான L2 டோக்கன் முகவரியை டெபாசிட் செய்யக் குறிப்பிட்டால் மட்டுமே இது நடக்க வேண்டும்.
4 // எந்தவொரு சந்தர்ப்பத்திலும், நாங்கள் இங்கே செயல்முறையை நிறுத்தி, பயனர்கள் தங்கள் நிதியை சில சந்தர்ப்பங்களில் வெளியேற்றுவதற்காக ஒரு திரும்பப் பெறுதல் செய்தியை உருவாக்குகிறோம்.
5 // தீங்கிழைக்கும் டோக்கன் ஒப்பந்தங்களை முற்றிலும் தடுக்க வழி இல்லை, ஆனால் இது பயனர் பிழையைக் கட்டுப்படுத்துகிறது மற்றும் தீங்கிழைக்கும் ஒப்பந்த நடத்தை வடிவங்களை ஓரளவு குறைக்கிறது.
6

ஒரு பயனர் தவறான L2 டோக்கன் முகவரியைப் பயன்படுத்தி கண்டறியக்கூடிய பிழை செய்தால், டெபாசிட்டை ரத்துசெய்து L1 இல் டோக்கன்களைத் திருப்பி அனுப்ப விரும்புகிறோம். L2 இலிருந்து இதைச் செய்ய ஒரே வழி, தவறு சவால் காலம் காத்திருக்க வேண்டிய ஒரு செய்தியை அனுப்புவதாகும், ஆனால் அது டோக்கன்களை நிரந்தரமாக இழப்பதை விட பயனருக்கு மிகவும் நல்லது.

1 bytes memory message = abi.encodeWithSelector(
2 IL1ERC20Bridge.finalizeERC20Withdrawal.selector,
3 _l1Token,
4 _l2Token,
5 _to, // டெபாசிட்டை அனுப்புநருக்குத் திருப்பி அனுப்ப இங்கே _to மற்றும் _from ஐ மாற்றியது
6 _from,
7 _amount,
8 _data
9 );
10
11 // செய்தியை L1 பாலத்திற்கு அனுப்பவும்
12 // slither-disable-next-line reentrancy-events
13 sendCrossDomainMessage(l1TokenBridge, 0, message);
14 // slither-disable-next-line reentrancy-events
15 emit DepositFailed(_l1Token, _l2Token, _from, _to, _amount, _data);
16 }
17 }
18}
அனைத்தையும் காட்டு

முடிவுரை

சொத்து இடமாற்றங்களுக்கான மிகவும் நெகிழ்வான பொறிமுறையே ஸ்டாண்டர்டு பாலம் ஆகும். இருப்பினும், இது மிகவும் பொதுவானதாக இருப்பதால், இது எப்போதும் பயன்படுத்த எளிதான பொறிமுறை அல்ல. குறிப்பாகத் திரும்பப் பெறுதல்களுக்கு, பெரும்பாலான பயனர்கள் சவால் காலத்திற்கு காத்திருக்காத மற்றும் திரும்பப் பெறுவதை இறுதி செய்ய மெர்க்கிள் ஆதாரம் தேவையில்லாத மூன்றாம் தரப்புப் பாலங்களைப்opens in a new tab பயன்படுத்த விரும்புகிறார்கள்.

இந்தப் பாலங்கள் பொதுவாக L1 இல் சொத்துக்களைக் கொண்டிருப்பதன் மூலம் வேலை செய்கின்றன, அதை அவை ஒரு சிறிய கட்டணத்திற்கு உடனடியாக வழங்குகின்றன (பெரும்பாலும் ஒரு ஸ்டாண்டர்டு பாலம் திரும்பப் பெறுதலுக்கான கேஸ் செலவை விடக் குறைவு). பாலம் (அல்லது அதை இயக்கும் நபர்கள்) L1 சொத்துக்கள் பற்றாக்குறையாக இருக்கும் என்று எதிர்பார்க்கும்போது, அது L2 இலிருந்து போதுமான சொத்துக்களை மாற்றுகிறது. இவை மிகவும் பெரிய திரும்பப் பெறுதல்கள் என்பதால், திரும்பப் பெறுதல் செலவு ஒரு பெரிய தொகையில் செலுத்தப்படுகிறது மற்றும் இது மிகவும் சிறிய சதவீதமாகும்.

இந்தப் கட்டுரை, அடுக்கு 2 எவ்வாறு செயல்படுகிறது மற்றும் தெளிவான மற்றும் பாதுகாப்பான சொலிடிட்டி குறியீட்டை எவ்வாறு எழுதுவது என்பது பற்றி மேலும் புரிந்துகொள்ள உங்களுக்கு உதவியது என்று நம்புகிறோம்.

எனது மேலும் பணிகளை இங்கே பார்க்கவும்opens in a new tab.

பக்கத்தின் கடைசி புதுப்பிப்பு: 22 அக்டோபர், 2025

இந்தப் பயிற்சி உதவியாக இருந்ததா?