মূল কন্টেন্টে যান

Vyper ERC-721 কন্ট্রাক্ট ওয়াকথ্রু

Vyper
erc-721
Python
শিক্ষানবিস
ওরি পোমেরান্টজ
1 এপ্রিল, 2021
19 মিনিট পড়ার সময়

ভূমিকা

ERC-721 স্ট্যান্ডার্ডটি নন-ফাঞ্জিবল টোকেন (NFT)-এর মালিকানা ধরে রাখতে ব্যবহৃত হয়। ERC-20 টোকেনগুলো একটি পণ্যের মতো আচরণ করে, কারণ প্রতিটি আলাদা টোকেনের মধ্যে কোনো পার্থক্য নেই। এর বিপরীতে, ERC-721 টোকেনগুলো এমন সম্পদের জন্য ডিজাইন করা হয়েছে যা একই রকম হলেও হুবহু এক নয়, যেমন বিভিন্ন বিড়ালের কার্টুন (একটি নতুন ট্যাবে খোলে) বা বিভিন্ন রিয়েল এস্টেটের মালিকানা।

এই নিবন্ধে আমরা রিউয়া নাকামুরার ERC-721 কন্ট্রাক্ট (একটি নতুন ট্যাবে খোলে) বিশ্লেষণ করব। এই কন্ট্রাক্টটি Vyper (একটি নতুন ট্যাবে খোলে)-এ লেখা হয়েছে, যা একটি Python-এর মতো কন্ট্রাক্ট ভাষা এবং এটি এমনভাবে ডিজাইন করা হয়েছে যাতে Solidity-এর তুলনায় এতে অনিরাপদ কোড লেখা কঠিন হয়।

কন্ট্রাক্ট

# @dev ERC-721 নন-ফাঞ্জিবল টোকেন স্ট্যান্ডার্ডের ইমপ্লিমেন্টেশন।
# @author Ryuya Nakamura (@nrryuya)
# এখান থেকে পরিমার্জিত: https://github.com/vyperlang/vyper/blob/de74722bf2d8718cca46902be165f9fe0e3641dd/examples/tokens/ERC721.vy

Python-এর মতো Vyper-এও মন্তব্যগুলো একটি হ্যাশ (ethereum.ercs) দিয়ে শুরু হয় এবং লাইনের শেষ পর্যন্ত চলতে থাকে। যেসব মন্তব্যে @<keyword> থাকে, সেগুলো NatSpec (একটি নতুন ট্যাবে খোলে) ব্যবহার করে মানুষের পড়ার উপযোগী ডকুমেন্টেশন তৈরি করতে ব্যবহৃত হয়।

from vyper.interfaces import ERC721

implements: ERC721

ERC-721 ইন্টারফেসটি Vyper ভাষার ভেতরেই তৈরি করা আছে। আপনি এখানে কোডের সংজ্ঞা দেখতে পারেন (একটি নতুন ট্যাবে খোলে)। ইন্টারফেসের সংজ্ঞাটি Vyper-এর পরিবর্তে Python-এ লেখা হয়েছে, কারণ ইন্টারফেসগুলো শুধু ব্লকচেইনের ভেতরেই ব্যবহৃত হয় না, বরং কোনো এক্সটার্নাল ক্লায়েন্ট থেকে ব্লকচেইনে ট্রানজ্যাকশন পাঠানোর সময়ও ব্যবহৃত হয়, যা Python-এ লেখা হতে পারে।

প্রথম লাইনটি ইন্টারফেস ইমপোর্ট করে এবং দ্বিতীয় লাইনটি নির্দিষ্ট করে যে আমরা এটি এখানে ইমপ্লিমেন্ট করছি।

#pragma version >0.3.10
#pragma version >0.3.10

ERC721Receiver ইন্টারফেস

# safeTransferFrom() দ্বারা কল করা কন্ট্রাক্টের জন্য ইন্টারফেস
interface ERC721Receiver:
    def onERC721Received(

ERC-721 দুই ধরনের হস্তান্তর সমর্থন করে:

  • transferFrom, যা প্রেরককে যেকোনো গন্তব্য ঠিকানা নির্দিষ্ট করতে দেয় এবং হস্তান্তরের দায়িত্ব প্রেরকের ওপর অর্পণ করে। এর মানে হলো আপনি একটি অবৈধ ঠিকানায় হস্তান্তর করতে পারেন, সেক্ষেত্রে NFT চিরতরে হারিয়ে যায়।
  • safeTransferFrom, যা গন্তব্য ঠিকানাটি একটি কন্ট্রাক্ট কিনা তা চেক করে। যদি তাই হয়, তবে ERC-721 কন্ট্রাক্ট গ্রহণকারী কন্ট্রাক্টকে জিজ্ঞাসা করে যে এটি NFT গ্রহণ করতে চায় কিনা।

safeTransferFrom রিকোয়েস্টের উত্তর দিতে একটি গ্রহণকারী কন্ট্রাক্টকে ERC721Receiver ইমপ্লিমেন্ট করতে হবে।

            _operator: address,
            _from: address,

_from ঠিকানাটি হলো টোকেনের বর্তমান মালিক। _operator ঠিকানাটি হলো সেটি যা হস্তান্তরের রিকোয়েস্ট করেছে (অ্যালাউন্সের কারণে এই দুটি একই নাও হতে পারে)। প্রথা অনুযায়ী, এই কন্ট্রাক্টের বেশিরভাগ ফাংশন প্যারামিটার একটি আন্ডারস্কোর (_) দিয়ে শুরু হয়।

            _tokenId: uint256,

ERC-721 টোকেন আইডিগুলো 256 বিটের হয়। সাধারণত টোকেনটি যা উপস্থাপন করে তার একটি বিবরণ হ্যাশিং করে এগুলো তৈরি করা হয়।

            _data: Bytes[1024]

রিকোয়েস্টে 1024 বাইট পর্যন্ত ইউজার ডেটা থাকতে পারে।

        ) -> bytes4: nonpayable

কোনো কন্ট্রাক্ট ভুলবশত কোনো হস্তান্তর গ্রহণ করার ঘটনা রোধ করতে রিটার্ন ভ্যালু কোনো বুলিয়ান নয়, বরং একটি নির্দিষ্ট চার-বাইট ভ্যালু, যা onERC721Received-এর ফাংশন সিলেক্টর। ফাংশনটি nonpayable কারণ একটি গ্রহণকারী কন্ট্রাক্ট টোকেন গ্রহণ করার সময় তার নিজস্ব স্টেট পরিবর্তন করতে পারে।

ইভেন্ট

ব্লকচেইনের বাইরের ইউজার এবং সার্ভারগুলোকে ইভেন্ট সম্পর্কে জানাতে ইভেন্ট এমিট করা হয়। মনে রাখবেন যে ইভেন্টের বিষয়বস্তু ব্লকচেইনে থাকা কন্ট্রাক্টগুলোর জন্য উপলব্ধ নয়। তিনটি ERC-721 ইভেন্ট আমাদের ইমপোর্ট করা IERC721 ইন্টারফেস দ্বারা সংজ্ঞায়িত করা হয়েছে, তাই এই কন্ট্রাক্টটি নিজে থেকে সেগুলো ডিক্লেয়ার করে না; এটি log IERC721.<Event>(...) দিয়ে সেগুলো এমিট করে, যেমনটি আমরা নিচের হস্তান্তর ফাংশনগুলোতে দেখতে পাব।

Transfer (sender, receiver, token_id) একটি NFT-এর মালিকানা পরিবর্তনের রিপোর্ট করে। এটি ERC-20 Transfer ইভেন্টের মতোই, তবে আমরা পরিমাণের পরিবর্তে একটি token_id রিপোর্ট করি। জিরো অ্যাড্রেসের কোনো মালিক নেই, তাই প্রথা অনুযায়ী আমরা টোকেন তৈরি এবং ধ্বংসের রিপোর্ট করতে এটি ব্যবহার করি। এর একটি ব্যতিক্রম হলো কন্ট্রাক্ট তৈরি, যে সময়ে Transfer এমিট না করেই যেকোনো সংখ্যক NFT তৈরি এবং অ্যাসাইন করা যেতে পারে।

একটি ERC-721 অনুমোদন একটি ERC-20 অ্যালাউন্সের মতোই: একটি নির্দিষ্ট ঠিকানাকে একটি নির্দিষ্ট টোকেন হস্তান্তর করার অনুমতি দেওয়া হয়, এবং যখনই সেই অনুমোদিত ঠিকানাটি সেট বা পুনরায় নিশ্চিত করা হয় তখন Approval (owner, approved, token_id) এমিট করা হয়। এটি কন্ট্রাক্টগুলোকে টোকেন গ্রহণ করার সময় সাড়া দেওয়ার একটি মেকানিজম দেয়। কন্ট্রাক্টগুলো ইভেন্ট শুনতে পারে না, তাই আপনি যদি শুধু তাদের কাছে টোকেন হস্তান্তর করেন তবে তারা এটি সম্পর্কে "জানতে" পারে না। এইভাবে মালিক প্রথমে একটি অনুমোদন সাবমিট করে এবং তারপর কন্ট্রাক্টে একটি রিকোয়েস্ট পাঠায়: "আমি আপনাকে টোকেন X হস্তান্তর করার অনুমোদন দিয়েছি, অনুগ্রহ করে ... করুন"। ERC-721 স্ট্যান্ডার্ডকে ERC-20 স্ট্যান্ডার্ডের মতো করার জন্য এটি একটি ডিজাইনগত পছন্দ। যেহেতু ERC-721 টোকেনগুলো ফাঞ্জিবল নয়, তাই একটি কন্ট্রাক্ট টোকেনের মালিকানা দেখেও শনাক্ত করতে পারে যে এটি একটি নির্দিষ্ট টোকেন পেয়েছে।

সবশেষে, যখন কোনো মালিকের জন্য একজন অপারেটর এনাবল বা ডিজেবল করা হয় তখন ApprovalForAll (owner, operator, approved) এমিট করা হয়। পাওয়ার অফ অ্যাটর্নির মতো এমন একজন অপারেটর থাকা মাঝে মাঝে দরকারী যে একটি অ্যাকাউন্টের নির্দিষ্ট ধরনের (যেগুলো একটি নির্দিষ্ট কন্ট্রাক্ট দ্বারা পরিচালিত হয়) সমস্ত টোকেন পরিচালনা করতে পারে। উদাহরণস্বরূপ, আমি এমন একটি কন্ট্রাক্টকে এই ক্ষমতা দিতে চাইতে পারি যা চেক করে যে আমি ছয় মাস ধরে এর সাথে যোগাযোগ করিনি কিনা, এবং যদি তাই হয় তবে আমার সম্পদগুলো আমার উত্তরাধিকারীদের মধ্যে বিতরণ করে (যদি তাদের মধ্যে কেউ এটি চায়, ট্রানজ্যাকশন দ্বারা কল করা ছাড়া কন্ট্রাক্টগুলো কিছুই করতে পারে না)। ERC-20-তে আমরা শুধু একটি ইনহেরিটেন্স কন্ট্রাক্টকে একটি উচ্চ অ্যালাউন্স দিতে পারি, কিন্তু ERC-721-এর জন্য এটি কাজ করে না কারণ টোকেনগুলো ফাঞ্জিবল নয়। এটি তারই সমতুল্য। approved ভ্যালুটি আমাদের বলে যে ইভেন্টটি কোনো অনুমোদনের জন্য, নাকি কোনো অনুমোদন প্রত্যাহারের জন্য。

স্টেট ভেরিয়েবল

এই ভেরিয়েবলগুলোতে টোকেনগুলোর বর্তমান স্টেট থাকে: কোনগুলো উপলব্ধ এবং সেগুলোর মালিক কে। এগুলোর বেশিরভাগই হলো HashMap অবজেক্ট, দুটি টাইপের মধ্যে থাকা একমুখী ম্যাপিং (একটি নতুন ট্যাবে খোলে)

# @dev NFT আইডি থেকে এর মালিকানাধীন ঠিকানায় ম্যাপিং।
idToOwner: HashMap[uint256, address]

# @dev NFT আইডি থেকে অনুমোদিত ঠিকানায় ম্যাপিং।
idToApprovals: HashMap[uint256, address]

ইথেরিয়ামে ইউজার এবং কন্ট্রাক্টের পরিচয় 160-বিট ঠিকানা দ্বারা উপস্থাপন করা হয়। এই দুটি ভেরিয়েবল টোকেন আইডি থেকে সেগুলোর মালিক এবং সেগুলো হস্তান্তর করার জন্য অনুমোদিত ব্যক্তিদের (প্রতিটির জন্য সর্বোচ্চ একজন) ম্যাপ করে। ইথেরিয়ামে, আনইনিশিয়ালাইজড ডেটা সর্বদা শূন্য হয়, তাই যদি কোনো মালিক বা অনুমোদিত হস্তান্তরকারী না থাকে তবে সেই টোকেনের ভ্যালু শূন্য হয়।

# @dev মালিকের ঠিকানা থেকে তার টোকেনের সংখ্যায় ম্যাপিং।
ownerToNFTokenCount: HashMap[address, uint256]

এই ভেরিয়েবলটি প্রতিটি মালিকের জন্য টোকেনের সংখ্যা ধারণ করে। মালিকদের থেকে টোকেনগুলোতে কোনো ম্যাপিং নেই, তাই কোনো নির্দিষ্ট মালিকের মালিকানাধীন টোকেনগুলো শনাক্ত করার একমাত্র উপায় হলো ব্লকচেইনের ইভেন্ট হিস্ট্রিতে ফিরে তাকানো এবং উপযুক্ত Transfer ইভেন্টগুলো দেখা। আমরা এই ভেরিয়েবলটি ব্যবহার করে জানতে পারি কখন আমাদের কাছে সমস্ত NFT আছে এবং সময়ের আরও পেছনে ফিরে দেখার প্রয়োজন নেই।

মনে রাখবেন যে এই অ্যালগরিদমটি শুধুমাত্র ইউজার ইন্টারফেস এবং এক্সটার্নাল সার্ভারগুলোর জন্য কাজ করে। ব্লকচেইনে চলা কোড অতীতের ইভেন্টগুলো পড়তে পারে না।

# @dev মালিকের ঠিকানা থেকে অপারেটরের ঠিকানার ম্যাপিংয়ে ম্যাপিং।
ownerToOperators: HashMap[address, HashMap[address, bool]]

একটি অ্যাকাউন্টের একাধিক অপারেটর থাকতে পারে। সেগুলোর ট্র্যাক রাখার জন্য একটি সাধারণ HashMap অপর্যাপ্ত, কারণ প্রতিটি কী একটি একক ভ্যালুর দিকে নিয়ে যায়। এর পরিবর্তে, আপনি ভ্যালু হিসেবে HashMap[address, bool] ব্যবহার করতে পারেন। ডিফল্টরূপে প্রতিটি ঠিকানার ভ্যালু False হয়, যার মানে এটি কোনো অপারেটর নয়। আপনি প্রয়োজন অনুযায়ী ভ্যালুগুলো True সেট করতে পারেন।

# @dev মিন্টারের ঠিকানা, যে টোকেন মিন্ট করতে পারে
minter: address

নতুন টোকেন কোনো না কোনোভাবে তৈরি করতে হবে। এই কন্ট্রাক্টে শুধুমাত্র একটি এনটিটিকে এটি করার অনুমতি দেওয়া হয়েছে, যা হলো minter। উদাহরণস্বরূপ, একটি গেমের জন্য এটি সম্ভবত যথেষ্ট। অন্যান্য উদ্দেশ্যে, আরও জটিল ব্যবসায়িক লজিক তৈরি করার প্রয়োজন হতে পারে।

# @dev সমর্থিত ERC165 ইন্টারফেস আইডিগুলোর স্ট্যাটিক তালিকা
SUPPORTED_INTERFACES: constant(bytes4[2]) = [
    # ERC165-এর ERC165 ইন্টারফেস আইডি
    0x01ffc9a7,
    # ERC721-এর ERC165 ইন্টারফেস আইডি
    0x80ac58cd,
]

ERC-165 (একটি নতুন ট্যাবে খোলে) একটি কন্ট্রাক্টের জন্য একটি মেকানিজম নির্দিষ্ট করে যা প্রকাশ করে যে অ্যাপ্লিকেশনগুলো কীভাবে এর সাথে যোগাযোগ করতে পারে, এটি কোন ERC-গুলো মেনে চলে। SUPPORTED_INTERFACES হলো দুটি চার-বাইট ইন্টারফেস আইডির একটি ধ্রুবক তালিকা যা এই কন্ট্রাক্টটি মেনে চলে: ERC-165 নিজে এবং ERC-721।

ফাংশন

এগুলো হলো সেই ফাংশন যা আসলে ERC-721 ইমপ্লিমেন্ট করে।

কনস্ট্রাক্টর

@deploy
def __init__():

Python-এর মতো Vyper-এও কনস্ট্রাক্টর ফাংশনটিকে __init__ বলা হয়। এটি @deploy ডেকোরেশন দিয়ে চিহ্নিত করা হয়, যার মানে হলো কন্ট্রাক্টটি ডিপ্লয় করার সময় এটি একবার চলে।

    """
    @dev কন্ট্রাক্ট কনস্ট্রাক্টর।
    """

Python এবং Vyper-এ, আপনি একটি মাল্টি-লাইন স্ট্রিং (যা """ দিয়ে শুরু এবং শেষ হয়) নির্দিষ্ট করে এবং কোনোভাবেই এটি ব্যবহার না করেও একটি মন্তব্য তৈরি করতে পারেন। এই মন্তব্যগুলোতে NatSpec (একটি নতুন ট্যাবে খোলে)-ও অন্তর্ভুক্ত থাকতে পারে।

    self.minter = msg.sender

স্টেট ভেরিয়েবলগুলো অ্যাক্সেস করতে আপনি self.<variable name> ব্যবহার করেন (আবারও, Python-এর মতোই)। কনস্ট্রাক্টর সেই অ্যাকাউন্টটিকে minter হিসেবে রেকর্ড করে যা কন্ট্রাক্টটি ডিপ্লয় করেছে।

ভিউ ফাংশন

এগুলো হলো সেই ফাংশন যা ব্লকচেইনের স্টেট পরিবর্তন করে না, এবং তাই যদি এগুলোকে এক্সটার্নালি কল করা হয় তবে এগুলো বিনামূল্যে এক্সিকিউট করা যেতে পারে। যদি ভিউ ফাংশনগুলোকে কোনো কন্ট্রাক্ট দ্বারা কল করা হয় তবে সেগুলোকে এখনও প্রতিটি নোডে এক্সিকিউট করতে হবে এবং তাই গ্যাস খরচ হবে।

@view
@external

ফাংশন সংজ্ঞার আগে থাকা এই কিওয়ার্ডগুলো যা একটি অ্যাট সাইন (@) দিয়ে শুরু হয় সেগুলোকে ডেকোরেশন বলা হয়। এগুলো নির্দিষ্ট করে যে কোন পরিস্থিতিতে একটি ফাংশন কল করা যেতে পারে।

  • @view নির্দিষ্ট করে যে এই ফাংশনটি একটি ভিউ।
  • @external নির্দিষ্ট করে যে এই নির্দিষ্ট ফাংশনটি ট্রানজ্যাকশন এবং অন্যান্য কন্ট্রাক্ট দ্বারা কল করা যেতে পারে।
def supportsInterface(interface_id: bytes4) -> bool:

Python-এর বিপরীতে, Vyper হলো একটি স্ট্যাটিক টাইপড ভাষা (একটি নতুন ট্যাবে খোলে)। আপনি ডেটা টাইপ (একটি নতুন ট্যাবে খোলে) শনাক্ত না করে কোনো ভেরিয়েবল বা ফাংশন প্যারামিটার ডিক্লেয়ার করতে পারবেন না। এই ক্ষেত্রে ইনপুট প্যারামিটার হলো bytes4, একটি চার-বাইট ভ্যালু, এবং আউটপুট হলো একটি বুলিয়ান ভ্যালু।

    """
    @dev ইন্টারফেস শনাক্তকরণ ERC-165-এ নির্দিষ্ট করা আছে।
    @param interface_id ইন্টারফেসের আইডি
    """
    return interface_id in SUPPORTED_INTERFACES

যদি interface_id SUPPORTED_INTERFACES তালিকার ইন্টারফেস আইডিগুলোর মধ্যে একটি হয় তবে True রিটার্ন করে।

### ভিউ ফাংশনগুলো ###

এগুলো হলো সেই ভিউ ফাংশন যা ইউজার এবং অন্যান্য কন্ট্রাক্টের কাছে টোকেন সম্পর্কে তথ্য উপলব্ধ করে।

এই লাইনটি অ্যাসার্ট (একটি নতুন ট্যাবে খোলে) করে যে _owner জিরো অ্যাড্রেস নয়, যা empty(address) হিসেবে লেখা হয়। যদি এটি হয়, তবে একটি ত্রুটি দেখা দেয় এবং অপারেশনটি রিভার্ট করা হয়।

ইথেরিয়াম ভার্চুয়াল মেশিনে (EVM) এমন যেকোনো স্টোরেজ যার মধ্যে কোনো ভ্যালু স্টোর করা নেই তা শূন্য হয়। যদি _tokenId-এ কোনো টোকেন না থাকে তবে self.idToOwner[_tokenId]-এর ভ্যালু শূন্য হয়। সেক্ষেত্রে ফাংশনটি রিভার্ট হয়。

মনে রাখবেন যে getApproved শূন্য রিটার্ন করতে পারে। যদি টোকেনটি বৈধ হয় তবে এটি self.idToApprovals[_tokenId] রিটার্ন করে। যদি কোনো অনুমোদনকারী না থাকে তবে সেই ভ্যালুটি শূন্য হয়।

এই ফাংশনটি চেক করে যে _operator-কে এই কন্ট্রাক্টে _owner-এর সমস্ত টোকেন পরিচালনা করার অনুমতি দেওয়া হয়েছে কিনা। যেহেতু একাধিক অপারেটর থাকতে পারে, তাই এটি একটি দুই স্তরের HashMap।

হস্তান্তর হেল্পার ফাংশন

এই ফাংশনগুলো এমন অপারেশন ইমপ্লিমেন্ট করে যা টোকেন হস্তান্তর বা পরিচালনার অংশ।


### হস্তান্তর ফাংশন হেল্পারগুলো ###

@view
@internal

এই ডেকোরেশন, @internal-এর মানে হলো ফাংশনটি শুধুমাত্র একই কন্ট্রাক্টের মধ্যে থাকা অন্যান্য ফাংশন থেকে অ্যাক্সেসযোগ্য। প্রথা অনুযায়ী, এই ফাংশনের নামগুলোও একটি আন্ডারস্কোর (_) দিয়ে শুরু হয়।

একটি ঠিকানাকে টোকেন হস্তান্তর করার অনুমতি দেওয়ার তিনটি উপায় রয়েছে:

  1. ঠিকানাটি টোকেনের মালিক
  2. ঠিকানাটি সেই টোকেন খরচ করার জন্য অনুমোদিত
  3. ঠিকানাটি টোকেনের মালিকের জন্য একজন অপারেটর

ওপরের ফাংশনটি একটি ভিউ হতে পারে কারণ এটি স্টেট পরিবর্তন করে না। অপারেটিং খরচ কমানোর জন্য, যে ফাংশনটি একটি ভিউ হতে পারে সেটি একটি ভিউ হওয়া উচিত

যখন কোনো হস্তান্তরে সমস্যা হয় তখন আমরা কলটি রিভার্ট করি।

শুধুমাত্র প্রয়োজন হলেই ভ্যালু পরিবর্তন করুন। স্টেট ভেরিয়েবলগুলো স্টোরেজে থাকে। স্টোরেজে লেখা হলো EVM (ইথেরিয়াম ভার্চুয়াল মেশিন)-এর করা সবচেয়ে ব্যয়বহুল অপারেশনগুলোর মধ্যে একটি (গ্যাস-এর ক্ষেত্রে)। তাই, এটি কমানো একটি ভালো ধারণা, এমনকি বিদ্যমান ভ্যালু লেখারও উচ্চ খরচ রয়েছে।

আমাদের এই ইন্টারনাল ফাংশনটি রয়েছে কারণ টোকেন হস্তান্তর করার দুটি উপায় রয়েছে (নিয়মিত এবং নিরাপদ), তবে অডিটিং সহজ করার জন্য আমরা কোডে শুধুমাত্র একটি স্থানে এটি করতে চাই।

Vyper-এ একটি ইভেন্ট এমিট করতে আপনি একটি log স্টেটমেন্ট ব্যবহার করেন (আরও বিস্তারিত জানার জন্য এখানে দেখুন (একটি নতুন ট্যাবে খোলে))। যেহেতু ইভেন্টগুলো ইমপোর্ট করা ইন্টারফেসের অন্তর্গত, তাই আমরা সেগুলোকে IERC721.Transfer হিসেবে উল্লেখ করি এবং কিওয়ার্ডের মাধ্যমে সেগুলোর ফিল্ডগুলো পাস করি।

হস্তান্তর ফাংশনগুলো

এই ফাংশনটি আপনাকে যেকোনো ঠিকানায় হস্তান্তর করার অনুমতি দেয়। যদি ঠিকানাটি কোনো ব্যবহারকারীর না হয়, অথবা এমন কোনো কন্ট্রাক্ট না হয় যা টোকেন হস্তান্তর করতে জানে, তবে আপনার হস্তান্তর করা যেকোনো টোকেন সেই ঠিকানায় আটকে যাবে এবং অকেজো হয়ে পড়বে।

এখানে @payable ডেকোরেশনটি রয়েছে কারণ IERC721 ইন্টারফেস transferFrom, safeTransferFrom, এবং approve-কে পেয়েবল (payable) হিসেবে ঘোষণা করে, তাই যে কন্ট্রাক্টটি এই ইন্টারফেস ইমপ্লিমেন্ট করে তাকে অবশ্যই সেই সিগনেচারগুলোর সাথে মিল রাখতে হবে।

প্রথমে হস্তান্তর করা ঠিক আছে কারণ যদি কোনো সমস্যা হয় তবে আমরা এমনিতেই রিভার্ট করব, তাই কলে করা সবকিছু বাতিল হয়ে যাবে।

    if _to.is_contract: # `_to` একটি কন্ট্রাক্ট ঠিকানা কিনা তা চেক করুন

প্রথমে চেক করুন ঠিকানাটি কোনো কন্ট্রাক্ট কিনা (যদি এতে কোড থাকে)। যদি না হয়, তবে ধরে নিন এটি একটি ব্যবহারকারীর ঠিকানা এবং ব্যবহারকারী টোকেনটি ব্যবহার করতে বা হস্তান্তর করতে সক্ষম হবেন। তবে এটি যেন আপনাকে মিথ্যা নিরাপত্তার অনুভূতি না দেয়। আপনি টোকেন হারাতে পারেন, এমনকি safeTransferFrom ব্যবহার করলেও, যদি আপনি সেগুলোকে এমন কোনো ঠিকানায় হস্তান্তর করেন যার প্রাইভেট কী কেউ জানে না।

        returnValue: bytes4 = extcall ERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data)

টার্গেট কন্ট্রাক্টটি ERC-721 টোকেন গ্রহণ করতে পারে কিনা তা দেখতে সেটিকে কল করুন। Vyper 0.4-এ অন্যান্য কন্ট্রাক্টে কলগুলোকে চিহ্নিত করা প্রয়োজন, তাই কলের আগে extcall যুক্ত করা হয়েছে।

        # হস্তান্তরের গন্তব্য যদি এমন কোনো কন্ট্রাক্ট হয় যা 'onERC721Received' ইমপ্লিমেন্ট করে না, তবে থ্রো করে
        assert returnValue == method_id("onERC721Received(address,address,uint256,bytes)", output_type=bytes4)

যদি গন্তব্যটি একটি কন্ট্রাক্ট হয়, কিন্তু এমন একটি যা ERC-721 টোকেন গ্রহণ করে না (অথবা যা এই নির্দিষ্ট হস্তান্তরটি গ্রহণ না করার সিদ্ধান্ত নিয়েছে), তবে রিভার্ট করুন।

প্রথা অনুযায়ী, যদি আপনি কোনো অনুমোদনকারী না রাখতে চান তবে আপনি নিজেকে নয়, বরং জিরো অ্যাড্রেস নিয়োগ করেন।

    # প্রয়োজনীয়তাগুলো চেক করুন
    senderIsOwner: bool = self.idToOwner[_tokenId] == msg.sender
    senderIsApprovedForAll: bool = (self.ownerToOperators[owner])[msg.sender]
    assert (senderIsOwner or senderIsApprovedForAll)

একটি অনুমোদন সেট করার জন্য আপনাকে হয় মালিক হতে হবে, অথবা মালিক দ্বারা অনুমোদিত একজন অপারেটর হতে হবে।

নতুন টোকেন মিন্ট করা এবং বিদ্যমানগুলো ধ্বংস করা

যে অ্যাকাউন্টটি কন্ট্রাক্ট তৈরি করেছে সেটি হলো minter, সুপার ইউজার যা নতুন NFT মিন্ট করার জন্য অনুমোদিত। তবে, এমনকি এটিকেও বিদ্যমান টোকেন পোড়ানোর অনুমতি দেওয়া হয় না। শুধুমাত্র মালিক, বা মালিক দ্বারা অনুমোদিত কোনো এনটিটি এটি করতে পারে।

### মিন্ট এবং পোড়ানো ফাংশনগুলো ###

@external
def mint(_to: address, _tokenId: uint256) -> bool:

এই ফাংশনটি সর্বদা True রিটার্ন করে, কারণ যদি অপারেশনটি ব্যর্থ হয় তবে এটি রিভার্ট করা হয়।

শুধুমাত্র মিন্টার (যে অ্যাকাউন্টটি ERC-721 কন্ট্রাক্ট তৈরি করেছে) নতুন টোকেন মিন্ট করতে পারে। ভবিষ্যতে যদি আমরা মিন্টারের পরিচয় পরিবর্তন করতে চাই তবে এটি একটি সমস্যা হতে পারে। একটি প্রোডাকশন কন্ট্রাক্টে আপনি সম্ভবত এমন একটি ফাংশন চাইবেন যা মিন্টারকে অন্য কারও কাছে মিন্টারের সুবিধাগুলো হস্তান্তর করার অনুমতি দেয়।

    # `_to` জিরো অ্যাড্রেস হলে থ্রো করে
    assert _to != ZERO_ADDRESS
    # NFT যোগ করুন। `_tokenId` কারও মালিকানাধীন হলে থ্রো করে
    self._addTokenTo(_to, _tokenId)
    log Transfer(ZERO_ADDRESS, _to, _tokenId)
    return True

প্রথা অনুযায়ী, নতুন টোকেন মিন্টিং জিরো অ্যাড্রেস থেকে একটি হস্তান্তর হিসেবে গণ্য হয়।

যে কাউকে টোকেন হস্তান্তর করার অনুমতি দেওয়া হয়, তাকে এটি পোড়ানোরও অনুমতি দেওয়া হয়। যদিও পোড়ানো জিরো অ্যাড্রেসে হস্তান্তর করার সমতুল্য বলে মনে হয়, জিরো অ্যাড্রেস আসলে টোকেনটি গ্রহণ করে না। এটি আমাদের টোকেনের জন্য ব্যবহৃত সমস্ত স্টোরেজ খালি করার অনুমতি দেয়, যা ট্রানজ্যাকশনের গ্যাস খরচ কমাতে পারে।

এই কন্ট্রাক্ট ব্যবহার করা

Solidity-এর বিপরীতে, Vyper-এ ইনহেরিটেন্স নেই। কোডটিকে আরও পরিষ্কার এবং তাই সুরক্ষিত করা সহজ করার জন্য এটি একটি ইচ্ছাকৃত ডিজাইনগত সিদ্ধান্ত। তাই আপনার নিজস্ব Vyper ERC-721 কন্ট্রাক্ট তৈরি করতে আপনি এই কন্ট্রাক্টটি (একটি নতুন ট্যাবে খোলে) নিতে পারেন এবং আপনি যে ব্যবসায়িক লজিক চান তা ইমপ্লিমেন্ট করতে এটি পরিবর্তন করতে পারেন।

উপসংহার

পর্যালোচনার জন্য, এখানে এই কন্ট্রাক্টের সবচেয়ে গুরুত্বপূর্ণ কিছু ধারণা দেওয়া হলো:

  • নিরাপদ হস্তান্তরের মাধ্যমে ERC-721 টোকেন গ্রহণ করতে, কন্ট্রাক্টগুলোকে ERC721Receiver ইন্টারফেস ইমপ্লিমেন্ট করতে হবে।
  • এমনকি আপনি নিরাপদ হস্তান্তর ব্যবহার করলেও, টোকেনগুলো আটকে যেতে পারে যদি আপনি সেগুলোকে এমন কোনো ঠিকানায় পাঠান যার প্রাইভেট কী অজানা।
  • যখন কোনো অপারেশনে সমস্যা হয় তখন শুধু একটি ব্যর্থতার মান রিটার্ন করার পরিবর্তে কলটি revert করা একটি ভালো ধারণা।
  • ERC-721 টোকেনগুলোর অস্তিত্ব থাকে যখন সেগুলোর একজন মালিক থাকে।
  • একটি NFT হস্তান্তর করার জন্য অনুমোদিত হওয়ার তিনটি উপায় রয়েছে। আপনি মালিক হতে পারেন, একটি নির্দিষ্ট টোকেনের জন্য অনুমোদিত হতে পারেন, অথবা মালিকের সমস্ত টোকেনের জন্য একজন অপারেটর হতে পারেন।
  • অতীতের ইভেন্টগুলো শুধুমাত্র ব্লকচেইনের বাইরে দৃশ্যমান। ব্লকচেইনের ভেতরে চলা কোড সেগুলো দেখতে পারে না।

এখন যান এবং সুরক্ষিত Vyper কন্ট্রাক্ট ইমপ্লিমেন্ট করুন।

আমার আরও কাজের জন্য এখানে দেখুন (একটি নতুন ট্যাবে খোলে)