استاندارد ERC-1363 در سالیدیتی این امکان را فراهم میکند که یک قرارداد هوشمند بلافاصله پس از دریافت توکن، از آن انتقال مطلع شود و به آن واکنش نشان دهد.
مشکل اصلی که استاندارد ERC-1363 در سالیدیتی حل میکند چیست؟
فرض کنید یک کاربر، تعدادی توکن مبتنی بر استاندارد ERC-20 را برای یک قرارداد هوشمند ارسال میکند. در این حالت، قرارداد هوشمند نمیداند چه کسی این توکن ها را فرستاده و نمیتواند براساس آن عملیات خاصی مثل ثبت واریز برای کاربر انجام دهد؛ چون هیچ مکانیزمی برای شناسایی فرستنده هنگام دریافت مستقیم توکن در برنامه نویسی این قرارداد در نظر گرفته نشده است.
هرچند لاگ های رویداد (eventها) این اطلاعات را ثبت میکنند، اما فقط سیستم های خارج از بلاکچین (off-chain) میتوانند به آن ها دسترسی داشته باشند. قراردادهای هوشمند به تنهایی نمیتوانند این داده ها را بخوانند، مگر اینکه از یک اوراکل (Oracle) استفاده کنند.
راهکار مرسوم در استاندارد ERC-20: استفاده از transferFrom
برای حل این مشکل، راهکاری که اغلب توسعه دهندگان به کار میبرند این است که کاربر ابتدا به قرارداد هوشمند اجازه دهد که توکن ها را به نمایندگی از او منتقل کند.
1 2 3 4 5 6 7 8 |
contract ReceivingContract { function deposit(uint256 amount) external { // در صورتی که این قرارداد از پیش تأیید نشده باشد یا موجودی کافی نباشد، عملیات با خطا مواجه میشود ERC20(token).transferFrom(msg.sender, address(this), amount); deposits[msg.sender] += amount; } } |
approve
، اجازه میدهد قرارداد دریافتکننده مقدار مشخصی از توکن های او را برداشت کند. سپس با فراخوانی تابع deposit
، قرارداد این توکن ها را از حساب کاربر به حساب خودش منتقل میکند. از آنجا که قرارداد مستقیماً این انتقال را انجام داده، بهدرستی حساب کاربر را شارژ میکند.
این راهکار هرچند جوابگوست، اما دو مشکل دارد:
-
هزینه بیشتر گس: نیاز به دو تراکنش دارد — یکی برای
approve
و دیگری برایtransferFrom
— که هزینه کل گس را افزایش میدهد. -
ریسک امنیتی: اگر کاربر پس از انجام عملیات، مقدار مجاز
approve
را مجدد به صفر تغییر ندهد، در صورت هک یا سواستفاده از قرارداد، ممکن است تمام توکن های قابل برداشت از حساب کاربر خارج شود.
استاندارد ERC-1363 در سالیدیتی با هدف ساده سازی این فرایند و حذف نیاز به تأیید مجزا (approve
) ارائه شده است. در ادامه، این استاندارد و نحوه استفاده از آن را بررسی خواهیم کرد.
هوک انتقال در سالیدیتی
هوک انتقال، تابعی از پیش تعریف شده در قرارداد هوشمند گیرنده است که در هنگام دریافت توکن ها، توسط قرارداد توکن فراخوانی میشود. به بیان ساده، زمانی که یک دستور انتقال صادر میشود، قرارداد توکن این تابع را در آدرس گیرنده فراخوانی میکند.
اگر این تابع در قرارداد گیرنده وجود نداشته باشد، یا اجرا با خطا مواجه شود، یا مقدار موفقیت مورد انتظار را بازنگرداند، انتقال لغو میشود.
کسانی که با تابع onERC721Received
در استاندارد ERC-721 در سالیدیتی آشنا هستند، به خوبی با مفهوم هوک انتقال آشنایی دارند.
استاندارد ERC-1363 و افزودن هوک انتقال به ERC-20
استاندارد ERC-1363 نسخه توسعه یافتهای از ERC-20 محسوب میشود که امکان فراخوانی هوک انتقال را به قابلیتهای آن اضافه میکند.
برای استفاده از این استاندارد، توسعهدهنده باید توابع جدیدی را به قرارداد توکن اضافه کند تا هنگام انتقال توکن، تابع هوک در قرارداد گیرنده بهصورت خودکار اجرا شود. از طرف دیگر، قرارداد گیرنده نیز باید این تابع را مطابق استاندارد پیادهسازی کند.
اینترفیس IERC1363Receiver در سالیدیتی
هر قراردادی که میخواهد از دریافت توکن های ERC-1363 مطلع شود، باید اینترفیس IERC1363Receiver
را پیادهسازی کند (میتوانید پیادهسازی آن را در OpenZeppelin ببینید). اینترفیس شامل تنها یک تابع به نام onTransferReceived
است:
1 2 3 4 5 6 7 8 9 10 11 |
pragma solidity ^0.8.20; interface IERC1363Receiver { // returns `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))` on success function onTransferReceived( address operator, address from, uint256 value, bytes calldata data ) external returns (bytes4); } |
توضیح پارامترها:
-
operator
: آدرسی است که انتقال را آغاز کرده است. -
from
: حسابی است که توکن های ERC-1363 از آن کسر شدهاند. -
value
: تعداد توکن های منتقل شده را نشان میدهد. -
data
: دادهای است که توسطoperator
مشخص میشود و به گیرنده منتقل میگردد.
هنگام پیادهسازی این تابع، همیشه بررسی کنید که msg.sender
همان قرارداد توکن ERC-1363 باشد که انتظار دریافت آن را دارید؛ زیرا هر کسی میتواند این تابع را با مقادیر دلخواه فراخوانی کند.
در ادامه یک نمونه قرارداد ساده و حداقلی برای دریافت توکن های ERC-1363 ارائه خواهد شد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
pragma solidity ^0.8.20; import "@openzeppelin/contracts/interfaces/IERC1363Receiver.sol"; import "@openzeppelin/contracts/interfaces/IERC1363.sol"; contract TokenReceiver is IERC1363Receiver { address internal erc1363Token; constructor(address erc1363Token_) { erc1363Token = erc1363Token_; } mapping(address user => uint256 balance) public balances; function onTransferReceived( address operator, address from, uint256 value, bytes calldata data ) external returns (bytes4) { require(msg.sender == erc1363Token, "not the expected token"); balances[from] += value; return this.onTransferReceived.selector; } function withdraw(uint256 value) external { require(balances[msg.sender] >= value, "balance too low"); balances[msg.sender] -= value; IERC1363(erc1363Token).transfer(msg.sender, value); } } |
در روش سنتی، برای اینکه یک قرارداد هوشمند متوجه شود توکن ERC-20 دریافت کرده، باید کاربر ابتدا با استفاده از تابع approve
، قرارداد را مجاز به برداشت توکن کند. سپس قرارداد با استفاده از تابع transferFrom
توکن را از حساب کاربر برداشت میکند.
اما با استاندارد ERC-1363 دیگر نیازی به مرحله تأیید (approve) نیست. تابع transferAndCall
توکن را مستقیماً به قرارداد منتقل میکند و بهطور همزمان، تابع onTransferReceived
را در قرارداد گیرنده فراخوانی میکند. این قابلیت، شناسایی دریافت توکن را برای قرارداد سادهتر میکند و نیاز به دو تراکنش جداگانه را از بین میبرد.
سازگاری حداکثری با استاندارد ERC-20
یکی از مشکلات رایج در تعریف استانداردهای جدید توکن، ناسازگاری با پروتکل های قبلی است. اگر استاندارد جدید به طور کامل با ERC-20 سازگار نباشد، بسیاری از قراردادها و برنامه های موجود نمیتوانند از آن استفاده کنند.
برای حل این مشکل، طراحان ERC-1363 این استاندارد را بر پایه ERC-20 توسعه دادهاند و تمام توابع اصلی آن را دقیقاً مطابق با مشخصات ERC-20 پیادهسازی کردهاند. این توابع شامل موارد زیر هستند:
-
name
-
symbol
-
decimals
-
totalSupply
-
balanceOf
-
transfer
-
transferFrom
-
approve
-
allowance
به این ترتیب، تمام پروتکل های قدیمی که با ERC-20 کار میکنند، میتوانند بدون هیچ تغییری با توکن های ERC-1363 نیز تعامل داشته باشند.
اما برای بهرهبرداری از قابلیت های جدید، استاندارد ERC-1363 توابع اضافهای را معرفی کرده است که فقط در صورت نیاز مورد استفاده قرار میگیرند.
توابع اضافی استاندارد ERC-1363 در سالیدیتی
برای اینکه یک توکن با استاندارد ERC-1363 در سالیدیتی سازگار باشد، باید ۶ تابع اضافی را پیادهسازی کند:
-
دو نسخه از
transferAndCall
-
دو نسخه از
transferFromAndCall
-
دو نسخه از
approveAndCall
همان طور که از نام این توابع پیداست، ابتدا عملیات استاندارد ERC-20 (مثل انتقال یا تأیید) را انجام میدهند و سپس تابع هوک مربوط به گیرنده را فراخوانی میکنند.
هر کدام از این توابع در دو نسخه ارائه میشوند:
-
نسخهای بدون پارامتر
data
-
نسخهای با پارامتر
data
برای ارسال اطلاعات اضافی به قرارداد گیرنده
پارامتر data
به فرستنده این امکان را میدهد که هنگام انتقال توکن، داده دلخواهی را به قرارداد گیرنده ارسال کند (در ادامه، نمونههایی از این کاربرد را نشان خواهیم داد).
به جز پارامتر data
، ساختار سایر پارامترهای این توابع کاملاً مشابه توابع ERC-20 است و ترتیب آن ها نیز تغییر نکرده است.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
// There are two transferAndCall functions, // one with a data argument and one without function transferAndCall( address to, uint256 value ) external returns (bool); function transferAndCall( address to, uint256 value, bytes calldata data ) external returns (bool); // There are two transferFromAndCall functions, // one with a data argument and one without function transferFromAndCall( address from, address to, uint256 value ) external returns (bool); function transferFromAndCall( address from, address to, uint256 value, bytes calldata data ) external returns (bool); // There are two approveAndCall functions,// one with a data argument and one without function approveAndCall( address spender, uint256 value ) external returns (bool); function approveAndCall( address spender, uint256 value, bytes calldata data ) external returns (bool); |
الهامگیری از ERC-721: مقایسه transferFrom و transferFromAndCall
استاندارد ERC-1363 از مفاهیمی مشابه استاندارد ERC-721 الهام گرفته است. همانطور که در ERC-721 تفاوت بین توابع transferFrom
و safeTransferFrom
وجود دارد، در ERC-1363 نیز تفاوتی مشابه بین transferFrom
و transferFromAndCall
دیده میشود.
با این حال، استفاده از واژه “safe” (ایمن) در نام تابع میتواند گمراهکننده باشد. دلیلش این است که استفاده از هوک های انتقال (transfer hooks) در ERC-1363 ممکن است مسیرهایی برای حمله بازگشتی (reentrancy attack) ایجاد کند. بنابراین این عملیات واقعاً “ایمن” نیست.
در عوض، استفاده از واژه call
در نام تابع (همانطور که در transferFromAndCall
دیده میشود)، به وضوح نشان میدهد که این تابع، پس از انجام انتقال، یک فراخوانی (call) به گیرنده انجام میدهد تا او را از دریافت توکن مطلع کند.
نحوه ذخیرهسازی در ERC-1363
استاندارد ERC-1363 برای ذخیره مقادیر مربوط به موجودی حسابها (balances) و مجوزهای برداشت (approvals) دقیقاً از همان متغیرهایی استفاده میکند که در استاندارد ERC-20 به کار رفتهاند. این استاندارد هیچ نوع اطلاعات اضافهای در قرارداد ذخیره نمیکند و ساختار دادههای آن کاملاً با ERC-20 سازگار است.
مروری بر کد ERC-1363 در سالیدیتی
ارثبری از ERC-20
همانطور که پیشتر اشاره شد، استاندارد ERC-1363 در واقع همان ERC-20 است که توابع جدیدی به آن اضافه شدهاند. بنابراین، اولین قدم برای پیادهسازی یک توکن ERC-1363 این است که از قرارداد ERC-20 ارثبری کنیم:
1 2 3 4 5 6 7 8 9 10 11 |
//SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts@5.0.0/token/ERC20/ERC20.sol"; contract ERC1363 is ERC20 { constructor( string memory name, string memory symbol )ERC20(name, symbol) {} } |
تابع transferFromAndCall(address to, uint256 value) external returns (bool)
این تابع زمانی با موفقیت اجرا میشود که آدرس گیرنده تابع onTransferReceived()
را پیادهسازی کرده باشد و مقدار بازگشتی آن دقیقاً برابر با چهار بایت ابتدایی تابع onTransferReceived()
باشد:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
function transferFromAndCall( address from, address to, uint256 value, bytes memory data ) public virtual returns (bool) { // first call the ERC-20 transferFrom function in the parent if (!transferFrom(from, to, value)) { revert ERC1363TransferFromFailed(from, to, value); } // then call the receiver _checkOnTransferReceived(from, to, value, data); return true; } // this function has no data parameter and// this function has no data parameter and // forwards empty data function transferFromAndCall( address from, address to, uint256 value ) public virtual returns (bool) { // `data` is empty return transferFromAndCall(from, to, value, ""); } |
تابع transferAndCall(address to, uint256 value) external returns (bool)
عملکرد این تابع تقریباً مشابه transferFromAndCall
است، با این تفاوت که آدرس فرستنده همان msg.sender
است:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
function transferAndCall( address to, uint256 value, bytes memory data ) public virtual returns (bool) { if (!transfer(to, value)) { revert ERC1363TransferFailed(to, value); } _checkOnTransferReceived(msgSender(), to, value, data); return true; } function transferAndCall( address to, uint256 value ) public virtual returns (bool) { return transferAndCall(to, value, ""); } |
تابع _checkOnTransferReceived()
این تابع عملکرد زیر را انجام میدهد:
-
بررسی میکند که آیا آدرس گیرنده، یک قرارداد هوشمند است یا نه. اگر نباشد، تراکنش را لغو میکند (revert).
-
تلاش میکند تابع
onTransferReceived
را در قرارداد گیرنده صدا بزند. -
اگر خروجی دریافتی برابر با
0x88a7ca5c
نباشد، عملیات را لغو میکند. -
اگر اجرای
onTransferReceived
با خطا مواجه شود، پیام خطا را دریافت و ریورت میکند.
نکته مهم: از آنجا که این تابع برای حساب های معمولی (EOA) اجرا نمیشود و باعث خطا میشود، برای ارسال توکن ERC-1363 به یک آدرس کیف پول معمولی، باید از توابع استاندارد ERC-20 مانند transfer
یا transferFrom
استفاده کنید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
function _checkOnTransferReceived( address from, address to, uint256 value, bytes memory data ) private { if (to.code.length == 0) { revert ERC1363EOAReceiver(to); } try IERC1363Receiver(to).onTransferReceived(_msgSender(), from, value, data) returns (bytes4 retval) { if (retval != IERC1363Receiver.onTransferReceived.selector) { revert ERC1363InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { revert ERC1363InvalidReceiver(to); } else { // this code causes the ERC-1363 to revert // with the same revert string as the // contract it called assembly { revert(add(32, reason), mload(reason)) } } } } |
تابع approveAndCall
در مثالهای قبلی، قرارداد گیرنده همان دریافتکننده توکن های ERC-1363 بود. اما اگر بخواهیم یک قرارداد واسطه، مانند روتری در صرافی Uniswap، به عنوان فرستنده توکن ها عمل کند چه باید کرد؟
در ساختارهای سنتی، این کار با دو مرحله انجام میشود:
-
ابتدا کاربر با استفاده از
approve
به قرارداد اجازه میدهد تا از طرف او توکن خرج کند. -
سپس قرارداد با
transferFrom
توکن را به مقصد میفرستد.
استاندارد ERC-1363 این فرایند را در یک تراکنش با استفاده از approveAndCall
سادهسازی میکند. در این حالت، قراردادی که اجازه برداشت توکن را دریافت کرده، به طور خودکار یک تابع هوک مخصوص را دریافت میکند.
همانند توابع transferAndCall
، توابع approveAndCall
نیز در دو نسخه ارائه شدهاند: یکی با پارامتر data
برای ارسال اطلاعات اضافی و دیگری بدون آن:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
function approveAndCall( address spender, uint256 value ) public virtual returns (bool) { return approveAndCall(spender, value, ""); } function approveAndCall( address spender, uint256 value, bytes memory data ) public virtual returns (bool) { if (!approve(spender, value)) { revert ERC1363ApproveFailed(spender, value); } _checkOnApprovalReceived(spender, value, data); return true; } |
اینترفیس IERC1363Spender
مشابه با IERC1363Receiver
که در آن تابع onTransferReceived
فراخوانی میشد، در اینجا نیز با استفاده از اینترفیس IERC1363Spender
، هنگام فراخوانی تابع approveAndCall
، تابع onApprovalReceived
فعال میشود.
در ادامه، پیادهسازی اینترفیس IERC1363Spender
بر اساس نسخه ارائه شده توسط OpenZeppelin نمایش داده شده است (توضیحات درون کد حذف شدهاند):
1 2 3 4 5 6 7 8 9 |
interface IERC1363Spender { function onApprovalReceived( address owner, uint256 value, bytes calldata data ) external returns (bytes4); } |
-
owner
: این آدرس نشان میدهد چه کسی مالک توکن هاست و شخصاً اجازه برداشت آن ها را صادر کرده است. -
value
: این مقدار مشخص میکند چه تعداد توکن برای برداشت تأیید شدهاند. -
data
: این دادهها همراه تراکنش ارسال میشوند و امکان انتقال اطلاعات سفارشی به قرارداد گیرنده را فراهم میکنند.
از آنجا که فقط صاحب توکن ها میتواند مجوز برداشت صادر کند، نیازی به پارامتر operator
نیست — در اینجا owner
همان کسی است که عمل تأیید را انجام داده است.
در مثال زیر، یک قرارداد به نام Router
تعریف شده که از IERC1363Spender
ارثبری میکند. این قرارداد پس از دریافت مجوز با استفاده از approveAndCall
، توکن ها را به آدرسی که در دادهها (data
) مشخص شده ارسال میکند:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import "@openzeppelin/contracts/interfaces/IERC1363Spender.sol"; contract Router is IERC1363Spender { // additional functions are needed for an approved // wallet to add approved ERC-1363 tokens to this mapping mapping(address => bool) isApprovedToken; function onApprovalReceived( address owner, uint256 value, bytes calldata data ) external returns (bytes4) { require(isApprovedToken[msg.sender], "not an approved token"); // getTarget is not implemented here, // see the next section for how to it work address target = getTarget(data); bool success = IERC1363(msg.sender).transferFrom(owner, target, value); require(success, "transfer failed"); return this.onApprovalReceived.selector; } } |
onApprovalReceived
باید بررسی کند که msg.sender
همان قرارداد توکن مورد انتظار باشد. اگر این بررسی انجام نشود و هر آدرسی بتواند این تابع را فراخوانی کند، ممکن است رفتارهای غیرمنتظره و حتی خطر امنیتی در قرارداد ایجاد شود.
مثال از یک قرارداد گیرنده با استفاده از ERC-1363
در این مثال، یک قرارداد گیرنده نشان داده میشود که از استاندارد ERC-1363 پشتیبانی میکند و از پارامتر data
استفاده میکند تا رفتار قرارداد در زمان دریافت توکن بر اساس داده های دریافتی تغییر کند.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
interface ERC1363Receiver { function onTransferReceived( address operator, address from, uint256 value, bytes memory data ) external returns (bytes4); } contract ReceiverContract is ERC1363Receiver { mapping(address => uint256) public deposits; address immutable token; constructor(address token_) { token = token_; } event Deposit( address indexed from, address indexed beneficiary, uint256 value ); function onTransferReceived( address, // operator address from, uint256 value, bytes memory data ) external returns (bytes4) { require(msg.sender == token, "Caller not ERC1363 token"); address beneficiary; if (data.length == 32) { beneficiary = abi.decode(data, (address)); } else { beneficiary = from; } deposits[from] += value; emit Deposit(from, beneficiary, value); return this.onTransferReceived.selector; } } |
استانداردهای پیشین برای حل مشکل هوک انتقال توکن
استاندارد ERC-1363 اولین تلاشی نبود که سعی کرد قابلیت هوک انتقال (transfer hook) را به توکن های ERC-20 اضافه کند.
استاندارد ERC-223 اولین تلاش رسمی در این زمینه بود. این استاندارد تابع هوک انتقال را به توابع transfer
و transferFrom
اضافه کرد. اما مشکل اصلی اینجا بود که اگر قرارداد گیرنده این هوک را پیادهسازی نکرده بود، نمیتوانست توکن را دریافت کند.
این ویژگی باعث شد که بسیاری از قراردادهایی که بر اساس استاندارد ERC-20 طراحی شده بودند اما تابع هوک نداشتند، نتوانند با ERC-223 سازگار شوند. به همین دلیل، توسعهدهندگان این استاندارد را بهصورت گسترده نپذیرفتند، چون ERC-223 با زیرساختهای قبلی همخوانی نداشت.
در استاندارد ERC-777، فقط قراردادهایی که آدرس آن ها را در رجیستری ERC-1820 ثبت کرده بودند، میتوانستند هوک انتقال را دریافت کنند. این فرآیند پیچیدگی بیشتری به طراحی قراردادها اضافه کرد.
علاوه بر این، استاندارد ERC-777 مشکلات امنیتی خاصی ایجاد کرد. بسیاری از پروتکل ها هنگام طراحی با ERC-20، این احتمال را در نظر نگرفته بودند که توابع transfer
یا transferFrom
بتوانند فراخوانی خارجی به قراردادهای دیگر انجام دهند. همین موضوع باعث شد قراردادهایی که برای چنین سناریویی آماده نبودند، در برابر حملات بازگشتی (reentrancy attacks) آسیبپذیر شوند. یکی از نمونههای شناختهشده این آسیبپذیری، مربوط به نسخه اول Uniswap بود.
علاوه بر این، چون ERC-777 برای اجرای هوکها باید با قرارداد رجیستری ERC-1820 ارتباط برقرار میکرد، مصرف گس در این استاندارد بهطور قابل توجهی افزایش پیدا میکرد.
چگونه ERC-1363 این مشکلات را حل میکند؟
استاندارد ERC-1363 تمامی این مشکلات را با یک رویکرد ساده اما مؤثر برطرف میکند:
-
توابع اصلی ERC-20 یعنی
transfer
وtransferFrom
را بدون هیچ تغییری حفظ میکند. در نتیجه با تمامی پروتکل های قدیمی سازگار باقی میماند. -
هوک های انتقال تنها در توابعی مانند
transferAndCall
یاapproveAndCall
فعال میشوند — نام این توابع بهروشنی نشان میدهد که قرار است پس از انتقال، تابعی در قرارداد گیرنده فراخوانی شود.
این رویکرد باعث میشود هم امنیت حفظ شود، هم توسعه دهندگان از سازگاری کامل با استانداردهای قبلی بهرهمند شوند.
چه زمانی باید از استاندارد ERC-1363 استفاده کرد؟
ERC-1363 میتواند در هر موقعیتی که قبلاً از ERC-20 استفاده میشده، به کار رود. از دید نویسنده مقاله، این استاندارد جایگزین بسیار مناسبی برای ERC-20 است، زیرا نیاز به مرحله approve
را حذف میکند؛ مرحلهای که در گذشته باعث از دست رفتن مقادیر قابل توجهی از دارایی کاربران شده است.
با استفاده از ERC-1363 میتوان قراردادهایی سادهتر، امنتر و کارآمدتر طراحی کرد، در حالی که همچنان با اکوسیستم گسترده ERC-20 سازگار باقی ماند.
راستی! برای دریافت مطالب جدید در کانال تلگرام یا پیج اینستاگرام سورس باران عضو شوید.
- انتشار: ۲ خرداد ۱۴۰۴
دسته بندی موضوعات
- آموزش ارز دیجیتال
- آموزش برنامه نویسی
- آموزش متنی برنامه نویسی
- اطلاعیه و سایر مطالب
- پروژه برنامه نویسی
- دوره های تخصصی برنامه نویسی
- رپورتاژ
- فیلم های آموزشی
- ++C
- ADO.NET
- Adobe Flash
- Ajax
- AngularJS
- apache
- ARM
- Asp.Net
- ASP.NET MVC
- AVR
- Bootstrap
- CCNA
- CCNP
- CMD
- CSS
- Dreameaver
- EntityFramework
- HTML
- IOS
- jquery
- Linq
- Mysql
- Oracle
- PHP
- PHPMyAdmin
- Rational Rose
- silver light
- SQL Server
- Stimulsoft Reports
- Telerik
- UML
- VB.NET&VB6
- WPF
- Xml
- آموزش های پروژه محور
- اتوکد
- الگوریتم تقریبی
- امنیت
- اندروید
- اندروید استودیو
- بک ترک
- بیسیک فور اندروید
- پایتون
- جاوا
- جاوا اسکریپت
- جوملا
- دلفی
- دوره آموزش Go
- دوره های رایگان پیشنهادی
- زامارین
- سئو
- ساخت CMS
- سی شارپ
- شبکه و مجازی سازی
- طراحی الگوریتم
- طراحی بازی
- طراحی وب
- فتوشاپ
- فریم ورک codeigniter
- فلاتر
- کانستراکت
- کریستال ریپورت
- لاراول
- معماری کامپیوتر
- مهندسی اینترنت
- هوش مصنوعی
- یونیتی
- کتاب های آموزشی
- Android
- ASP.NET
- AVR
- LINQ
- php
- Workflow
- اچ تی ام ال
- بانک اطلاعاتی
- برنامه نویسی سوکت
- برنامه نویسی موبایل
- پاسکال
- پایان نامه
- پایتون
- جاوا
- جاوا اسکریپت
- جی کوئری
- داده کاوی
- دلفی
- رباتیک
- سئو
- سایر کتاب ها
- سخت افزار
- سی اس اس
- سی پلاس پلاس
- سی شارپ
- طراحی الگوریتم
- فتوشاپ
- مقاله
- مهندسی نرم افزار
- هک و امنیت
- هوش مصنوعی
- ویژوال بیسیک
- نرم افزار و ابزار برنامه نویسی
- وردپرس