پیشرفته NFT

استاندارد توکن ERC-721 چیست و چگونه یک توکن ساده بسازیم؟

ما در این مقاله به بررسی استاندارد توکن ERC-721 ، عدم قابلیت جایگزینی و ساخت یک توکن ERC-721 ساده می پردازیم. به طور کلی، توکن ERC-721 به توکن غیر قابل جایگزینی گفته می‌شود که توکنیزه کردن هر دیتای دلخواهی را ممکن می‌کند.

خرید ارز دیجیتال با ۱۰ هزار تومان!

تو صرافی ارز پلاس میتونی فقط با ۱۰ هزار تومان و با کارمزد صفر، همه ارزهای دیجیتال رو معامله کنی!

همین الان شروع کن

توکن ERC-721 چیست؟

استاندارد توکن ERC-721 استاندارد توکن اتریوم است که توکن های غیر قابل جایگزین (NFTs) را بر روی بلاک چین اتریوم مقدور می‌کند. درست مانند استاندارد توکن ERC-20 که به ایجاد توکن های قابل جایگزین کمک می کند، ERC-721 متمرکز بر طراحی دارایی غیر قابل جایگزینی است. آیا بازی CryptoKitties را به یاد دارید؟ این بازی یک توکن غیر قابل جایگزینی است یعنی هر دارایی Kitty یا همان گربه شما منحصر به فرد است.

قابلیت جایگزینی (Fungibility)

fungible

قبل از درک عدم قابلیت جایگزینی، لازم است قابلیت جایگزینی را درک کنیم. دو ویژگی اصلی برای قابلیت جایگزینی وجود دارد:

۱- قابلیت معاوضه: شما می توانید به معاوضه یا جابجایی واحد های یک دارایی قابل جایگزینی بپردازید. اسکناس ۲۰ دلاری شما و اسکناس ۲۰ دلاری من یک چیز را ارائه می‌دهند و می‌توان آنها را با هم معاوضه کرد. به عنوان یک مثال دیگر می توانیم بگوییم که یک کیلوگرم شمش طلا با یک کیلوگرم دیگر شمش طلا برابر است . آنها ارزش مشابهی را ارائه می‌دهند و می توانند با همدیگر معاوضه شوند.

۲- مقدار: شما می توانید به ادغام واحدهای یک دارایی قابل جایگزینی بپردازید تا به ارزش بالاتری در کمیت و مقدار دست یابید. به عنوان مثال، شما می‌توانید تعداد زیادی غلات را با هم جمع کنید و حالا شما همان چیز را دارید اما با تعداد و کمیت بالاتری.

عدم قابلیت جایگزینی (NonFungibility)

یک توکن غیر قابل جایگزینی، ارائه دهنده توکن منحصر به فردی است که نمی توان آن را با توکن دیگری معاوضه کرد. در اینجا شما نمی‌توانید برای رسیدن به کمیت بالاتر به تقسیم و یا جمع کردن بپردازید؛ زیرا هر واحد منحصر به فرد است و نمی‌توان آن را با دارایی‌های دیگر جابجا یا معاوضه کرد. به عنوان، مثال دو قطعه زمین را در نظر بگیرید؛ آنها هر دو با توجه به موقعیتی که دارند، غیر قابل جایگزینی هستند.

مثالی از توکن های غیر قابل جایگزین

توکن های غیر قابل جایگزین زیادی وجود دارند. تعدادی از مشهورترین آنها CryptoKitties، Etheremons، Crypto Bots و Blockchain Cuties هستند. می توانید لیست کاملی از توکن های ERC-721 را از طریق این لینک بررسی کنید.

ویژگی‌های استاندارد ERC-721

حال اجازه دهید به بررسی عمیق استاندارد ERC-721 بپردازیم. این استاندارد مجموعه‌ای از روش‌ها را تعریف می‌کند که به شناسایی و تعامل با یک توکن غیر قابل جایگزین کمک می‌کنند.

رویداد ها (Events) در استاندارد ERC-721

رویداد هایی هستند که در انتقال و تایید ها صادر می شوند.

عملکرد های ERC-721

  • balanceOf: موجودی یک آدرس را برخواهد گرداند.
  • ownerOf: آدرس مالک یک توکن را برخواهد گرداند.
  • safeTransferFrom: انتقال توکن از یک آدرس به آدرس دیگر با بررسی های انجام شده به منظور اطمینان حاصل کردن از این که گیرنده می تواند توکن را بپذیرد، پس توکن منهدم و یا گم نمی شود.
  • transferFrom: انتقال توکن از یک آدرس به آدرس دیگر (استفاده از این عملکرد توصیه نمی شود). دعوت کننده این روش مسئول گذاشتن آدرس گیرنده صحیح می باشد.
  • Approve: به تصویب هر آدرس دیگری برای ارسال یک تراکنش از اکانت مالک توکن به اکانت دیگر می پردازد.
  • setApprovalForAll: به یک اپراتور (هر آدرسی، اکثرا کیف پول ها و صرافی ها) اجازه می دهد و یا گاها اجازه نمی دهد که به ارسال همه توکن ها از آدرس مالک به یک آدرس دیگر بپردازد.
  • getApproved: آدرسی را برمی گرداند که مجاز به انتقال توکن برای مالکان می باشد. اگر آدرسی تنظیم نشده باشد ۰ را برمی گرداند.
  • isApprovedForAll: اگر اپراتور مورد نظر (هر آدرسی) توسط مالک مورد نظر تایید شود، True (درست) را برمی گرداند.
pragma solidity ^0.4.20;interface ERC721 /* is ERC165 */ {event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);function balanceOf(address _owner) external view returns (uint256);function ownerOf(uint256 _tokenId) external view returns (address);function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;function transferFrom(address _from, address _to, uint256 _tokenId) external payable;function approve(address _approved, uint256 _tokenId) external payable;function setApprovalForAll(address _operator, bool _approved) external;function getApproved(uint256 _tokenId) external view returns (address);function isApprovedForAll(address _owner, address _operator) external view returns (bool);}

ساخت یک توکن ERC-721 با استفاده از OpenZeppelin و Truffle

حال اجازه دهید با استفاده از کتابخانه OpenZeppelin و Truffle یک توکن ERC-721 بسازیم. ابتدا به سازمان دادن Truffle می پردازیم:

mkdir simple
truffle init
npm install openzeppelin-solidity

اجازه دهید قرارداد جدیدی برای توکن نمونه خود ایجاد کنیم:

pragma solidity ^0.4.24;import “/openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol”;
import “/openzeppelin-solidity/contracts/ownership/Ownable.sol”;contract SIMPLEToken is ERC721Full, Ownable{

constructor()
ERC721Full(“SIMPLE”, “SMPL”)
public {}function mint(address to, uint256 tokenId) public onlyOwner {
_mint(to, tokenId);
}function _mint(address to) public onlyOwner{
mint(to, totalSupply().add(1));
}}

اجازه دهید ببینیم که ما در اینجا داریم چه کار می کنیم. ما در حال دریافت دو قرارداد ERC721FULL و Ownable هستیم.

Ownable

با استفاده از این قرارداد، ما می توانیم به مدیریت مالکیت قراردادمان بپردازیم و تنها قادر به ایجاد توکن ها از اکانت مالک قرارداد خواهیم بود.

ERC721FULL

این پیاده سازی استاندارد سطح کاربری ERC-721 است که در بالا ذکر شد. اجازه دهید ببینیم که در داخل این قرارداد چه چیزی روی می دهد:

pragma solidity ^0.4.24;import “./ERC721.sol”;
import “./ERC721Enumerable.sol”;
import “./ERC721Metadata.sol”;
contract ERC721Full is ERC721, ERC721Enumerable, ERC721Metadata {
constructor(string name, string symbol) ERC721Metadata(name, symbol)
public
{
}
}

 

ERC721FULL در داخل خود ۳ قرارداد را دریافت می کند. ما اساسا به ERC-721 نگاه می کنیم تا این پیاده سازی را درک کنیم.

اجازه دهید مرحله به مرحله از عملکرد اصلی گذر کنیم. قبل از آن باید درک کنیم که توکن ها چگونه ذخیره می شوند:

// Mapping from token ID to owner
mapping (uint256 => address) private _tokenOwner;// Mapping from token ID to approved address
mapping (uint256 => address) private _tokenApprovals;// Mapping from owner to number of owned token
mapping (address => uint256) private _ownedTokensCount;// Mapping from owner to operator approvals
mapping (address => mapping (address => bool)) private _operatorApprovals;

  • tokenOwner: این طراحی برای ذخیره یک توکن در برابر مالک خود مورد نیاز است. با استفاده از این می دانیم که مالک یک tokenId کیست.
  • tokenApprovals: این طراحی برای ذخیره tokenId در برابر آدرسی که توسط مالک توکن تصویب شده مورد نیاز می باشد و با استفاده از آن، توکن برای مالک انتقال داده می شود.
  • ownedTokenCount: این طراحی برای دانستن تعداد توکن هایی که یک آدرس مالک آن است مورد نیاز می باشد. اگر این طراحی را ایجاد نکنید، مجبور به تشکیل حلقه برای دسترسی به این اطلاعات هستیم و این تشکیل حلقه نیاز به gas زیادی در EVM دارد.
  • operatorApprovals: طراحی یک مالک و اپراتور برای بررسی این است که آیا مالک تایید شده است یا نه.

حال اجازه دهید به بررسی عملکرد ها در این استاندارد بپردازیم:

balanceOf: این موجودی یک آدرس را برخواهد گرداند. ابتدا آن در جستجوی یک آدرس معتبر می باشد و سپس از _ownedTokensCountاستفاده می کند تا شمار توکن را برگرداند.

function balanceOf(address owner) public view returns (uint256) {
require(owner != address(0));
return _ownedTokensCount[owner];

}

OwnerOf: این آدرس مالک را برای یک توکن مورد نظر با استفاده از طراحی _tokenOwner  برمی گرداند.

function ownerOf(uint256 tokenId) public view returns (address) {
address owner = _tokenOwner[tokenId];
require(owner != address(0));
return owner;
}

Approve: این یک آدرس را برای انتقال توکن به خاطر مالک تصویب خواهد کرد. این عملکرد ابتدا بررسی می کند که آیا مالک عملکرد را دعوت کرده و یا آیا این دعوت توسط مالک برای ارسال همه توکن ها تایید شده است. سپس اگر همه چیز صحیح باشد، طراحی _tokenApprovals را به روز رسانی می کند.

function approve(address to, uint256 tokenId) public {
address owner = ownerOf(tokenId);
require(to != owner);
require(msg.sender == owner || isApprovedForAll(owner, msg.sender));_tokenApprovals[tokenId] = to;
emit Approval(owner, to, tokenId);
}

safeTransferFrom: دو عملکرد وجود دارد که نام های مشابهی دارند اما بحث های آنها متفاوت است. این عملکرد ها به صورت داخلی عملکرد transferfrom نامیده می شوند. آنها همچنین یک وظیفه مهم تر را اجرا می کنند. آنها بررسی می کنند تا ببینند که آیا آدرس گیرنده برای دریافت توکن معتبر است یا نه. این به امنیت توکن کمک می کند.

function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes _data
)
public
{
transferFrom(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data));
}

transferFrom: این عملکرد اصلی برای انتقال یک توکن از یک آدرس به آدرس دیگر است. اجازه دهید ببینیم که این عملکرد چه چیزی انجام می دهد:

۱- بررسی می کند که آیا توکن توسط called به مالکیت درآمده و یا به caller یا دعوت کننده  approved شده است. همچنین به بررسی اعتبار آدرس می‌پردازد.

۲- تصویب واضح، برداشتن مالکیت حال حاضر و کاهش شمار توکن مالک حال حاضر.

۳- اضافه کردن توکن به یک اکانت گیرنده و افزایش شمار توکن برای گیرنده.

function transferFrom(
address from,
address to,
uint256 tokenId
)
public
{
require(_isApprovedOrOwner(msg.sender, tokenId));
require(to != address(0));_clearApproval(from, tokenId);
_removeTokenFrom(from, tokenId);
_addTokenTo(to, tokenId);emit Transfer(from, to, tokenId);
}

setApprovalForAll: این عملکرد آدرس را برای انتقال همه توکن‌ها به خاطر مالک تایید می‌کند. آن ابتدا بررسی می‌کند که آدرس called و to مشابه نباشند و سپس طراحی operatorApprovals را به روز رسانی می‌کند.

function setApprovalForAll(address to, bool approved) public {
require(to != msg.sender);
_operatorApprovals[msg.sender][to] = approved;
emit ApprovalForAll(msg.sender, to, approved);
}

isApprovedForAll: این عملکرد بررسی می کند که آیا owner، operator را برای انتقال توکن ها تایید کرده است یا نه.

function isApprovedForAll(
address owner,
address operator
)
public
view
returns (bool)
{
return _operatorApprovals[owner][operator];
}

getApproved: آدرس تصویب شده برای tokenId مورد نظر را برمی‌گرداند.

function getApproved(uint256 tokenId) public view returns (address) {
require(_exists(tokenId));
return _tokenApprovals[tokenId];
}

شما می‌توانید به بررسی دیگر عملکردهای کمک کننده و قراردادهای دریافت شده بپردازید.

امتحان کردن توکن ERC-721

حال به امتحان و بررسی توکن نمونه خود می‌پردازیم. ما از یک بلاک چین محلی تعبیه شده در داخل برای نصب و تست قرارداد استفاده می‌کنیم.

truffle develop

این میز فرمان  Truffle را برای ما فراهم می کند.

حال به نصب قرارداد می‌پردازیم. به یاد داشته باشید که لازم است یک فایل migration اضافه کنیم.

truffle compile
migrate –reset
SIMPLEToken.deployed().then((simple) => {token = simple;})

حال اجازه دهید تعدادی توکن ایجاد کنیم و یک تست انتقال و تایید را انجام دهیم.

oken._mint(web3.eth.accounts[0]) // will mint a new tokentoken.totalSupply() // check token’s total supplytoken.safeTransferFrom(web3.eth.accounts[0] , web3.eth.accounts[1], 1) // transfer token (token id 1) from 0’th account to 1st accounttoken.ownerOf(1) // check owner of token id 1token._mint(web3.eth.accounts[0]) // will mint another tokentoken.approve(web3.eth.accounts[3] , 2) // approve token id 2 to  account[3]token.safeTransferFrom(web3.eth.accounts[0] , web3.eth.accounts[1], 2 , {from:web3.eth.accounts[3]})   // Note that we are adding {from:web3.eth.accounts[3]}, this mean that we are invoking this function using account[3]

شما می‌توانید به تست همه روش‌ها بپردازید (openZeppelin کتابخانه‌ای است که به خوبی تست شده است و بنابراین لازم نیست نگران عملکردی باشید که توسط کتابخانه فراهم شده است). شما باید در عوض متمرکز بر تست هر عملکردی باشید که توسط شما اضافه شده است.

نتیجه گیری

امروز ما با استفاده از زبان برنامه نویسی سالیدیتی (Solidity) بر روی اتریوم یک توکن غیر قابل جایگزین را ایجاد کردیم. این توکن‌ها اکثرا به عنوان چیزهای باارزش برای جمع آوری مورد استفاده قرار می گیرند و دارای گستره‌ای از کاربردهای دیگر مانند املاک و مستغلات، کار هنری، گواهی نامه ها، وام ها و غیره هستند. یک استفاده برجسته دیگر این توکن ها در صنعت بازی می باشد که در این پلتفرم ها می تواند مورد استفاده قرار بگیرد. این واقعا هیجان برانگیز است.

 

آخرین به روز رسانی: ۱۳۹۹/۳/۳

منبع
medium

نوشته های مشابه

اشتراک
اطلاع از
1 دیدگاه
جدید ترین
قدیمی ترین محبوب ترین
Inline Feedbacks
View all comments
دکمه بازگشت به بالا