Contract Upgradability হল একটি গুরুত্বপূর্ণ ধারণা যা স্মার্ট কন্ট্রাক্টে ভবিষ্যতে পরিবর্তন বা আপগ্রেড করার সক্ষমতা প্রদান করে, যখন একটি কন্ট্রাক্ট একবার ডিপ্লয় হয়ে যায় এবং এর মধ্যে কিছু ত্রুটি বা পরিবর্তন করার প্রয়োজন হয়। Ethereum ব্লকচেইনে স্মার্ট কন্ট্রাক্ট একটি অপরিবর্তনীয় কোড হিসেবে ডিপ্লয় হয়, অর্থাৎ একবার ডিপ্লয় হওয়ার পরে সেই কোড পরিবর্তন করা সম্ভব নয়। তবে, Contract Upgradability নিশ্চিত করে যে, আপনি ভবিষ্যতে স্মার্ট কন্ট্রাক্টের কার্যকলাপ এবং লজিক পরিবর্তন করতে পারবেন, যাতে সিস্টেমের উন্নয়ন করা যায়।
1. Contract Upgradability এর প্রয়োজনীয়তা
Smart Contract এর upgradability গুরুত্বপূর্ণ কারণ কিছু কারণে স্মার্ট কন্ট্রাক্টের মধ্যে পরিবর্তন বা আপগ্রেডের প্রয়োজন হতে পারে, যেমন:
- Bug Fixes: স্মার্ট কন্ট্রাক্টে ত্রুটি (bugs) থাকতে পারে যা পরে ঠিক করতে হবে।
- New Features: নতুন বৈশিষ্ট্য বা কার্যকলাপ যুক্ত করতে হতে পারে।
- Security Improvements: নিরাপত্তার উন্নয়ন বা আপডেটের প্রয়োজন হতে পারে।
- Economic Modifications: যেমন Fee Structure বা Tokenomics এর পরিবর্তন।
যেহেতু স্মার্ট কন্ট্রাক্ট একবার ডিপ্লয় হওয়ার পরে পরিবর্তন করা যায় না, তাই upgradable contracts তৈরি করার জন্য কিছু বিশেষ কৌশল এবং প্যাটার্ন ব্যবহার করা হয়।
2. Contract Upgradability এর জন্য কৌশল
Solidity তে Contract Upgradability করতে বেশ কয়েকটি কৌশল ব্যবহার করা হয়। প্রধানত তিনটি পদ্ধতি প্রচলিত:
A. Proxy Pattern
Proxy Pattern হল সবচেয়ে জনপ্রিয় এবং ব্যবহৃত পদ্ধতি যা স্মার্ট কন্ট্রাক্ট আপগ্রেড করার জন্য ব্যবহৃত হয়। এই পদ্ধতিতে দুটি কন্ট্রাক্ট ব্যবহৃত হয়:
- Proxy Contract: এই কন্ট্রাক্টটি ব্যবহারকারীদের কাছে দেখা যায় এবং সমস্ত লেনদেনকে পরিচালনা করে।
- Logic Contract: এই কন্ট্রাক্টে স্মার্ট কন্ট্রাক্টের লজিক বা কার্যকলাপ থাকে এবং এটি পরিবর্তন করা যায়।
Proxy কন্ট্রাক্ট সমস্ত লেনদেন গ্রহণ করে এবং এই লেনদেনগুলোকে Logic Contract-এ প্রেরণ করে। যখন লজিক কন্ট্রাক্ট আপগ্রেড করতে হয়, তখন শুধুমাত্র লজিক কন্ট্রাক্ট পরিবর্তন করা হয় এবং Proxy কন্ট্রাক্ট অপরিবর্তিত থাকে।
Proxy Pattern এর উদাহরণ:
// Proxy Contract
pragma solidity ^0.8.0;
contract Proxy {
address public implementation; // Logic contract address
constructor(address _implementation) {
implementation = _implementation;
}
function upgrade(address _newImplementation) public {
implementation = _newImplementation;
}
fallback() external payable {
address impl = implementation;
require(impl != address(0), "Implementation contract address is zero");
(bool success, ) = impl.delegatecall(msg.data);
require(success, "Delegatecall failed");
}
}
// Logic Contract (Upgradeable)
pragma solidity ^0.8.0;
contract Logic {
uint256 public value;
function setValue(uint256 _value) public {
value = _value;
}
}এখানে:
- Proxy Contract: সকল লেনদেন এই কন্ট্রাক্টের মাধ্যমে চলে এবং এটি ফাংশন কল Logic কন্ট্রাক্টে পাঠিয়ে দেয়।
- Logic Contract: এখানে মূল কার্যকলাপ থাকে এবং যখন নতুন ফাংশন বা লজিক দরকার হয়, তখন এই কন্ট্রাক্ট আপগ্রেড করা হয়।
B. Eternal Storage Pattern
Eternal Storage প্যাটার্নে, ডেটা সংরক্ষণের জন্য একটি আলাদা কন্ট্রাক্ট থাকে, যা বিভিন্ন কন্ট্রাক্ট থেকে ব্যবহৃত হতে পারে। যখন Logic কন্ট্রাক্ট আপগ্রেড করা হয়, তখন স্টোরেজ কন্ট্রাক্ট অপরিবর্তিত থাকে।
এই প্যাটার্নে, স্মার্ট কন্ট্রাক্টের লজিক পরিবর্তন করা হলেও, স্টোরেজ থেকে ডেটা এবং স্টেট মুছে ফেলা হয় না, তাই পুরানো ডেটা রক্ষা করা যায়।
Eternal Storage Example:
// Eternal Storage Contract
pragma solidity ^0.8.0;
contract EternalStorage {
mapping(address => uint256) public data;
function setData(address _user, uint256 _value) public {
data[_user] = _value;
}
function getData(address _user) public view returns (uint256) {
return data[_user];
}
}
// Logic Contract (Upgradeable)
pragma solidity ^0.8.0;
interface EternalStorageInterface {
function setData(address _user, uint256 _value) external;
function getData(address _user) external view returns (uint256);
}
contract Logic {
EternalStorageInterface public storageContract;
constructor(address _storageAddress) {
storageContract = EternalStorageInterface(_storageAddress);
}
function setValue(address _user, uint256 _value) public {
storageContract.setData(_user, _value);
}
function getValue(address _user) public view returns (uint256) {
return storageContract.getData(_user);
}
}এখানে:
- Eternal Storage কন্ট্রাক্টের মাধ্যমে সমস্ত ডেটা সংরক্ষণ করা হয় এবং সেটি যেকোনো লজিক কন্ট্রাক্ট দ্বারা অ্যাক্সেস করা যায়।
- Logic Contract-এ লজিক আপডেট করা হলে ডেটা অপরিবর্তিত থাকে।
C. Upgradeable Contract Libraries
Upgradeable Contract Libraries এমন একটি পদ্ধতি যেখানে লজিক পরিবর্তন করতে Library Contracts ব্যবহার করা হয়। এই লাইব্রেরি কন্ট্রাক্টটি একাধিক কন্ট্রাক্ট দ্বারা ব্যবহার হতে পারে এবং শুধুমাত্র লজিক আপডেট করতে হয়।
Library Contract Example:
// Logic Library
pragma solidity ^0.8.0;
library LogicLibrary {
uint256 public value;
function setValue(uint256 _value) public {
value = _value;
}
}
// Main Contract (Upgradeable)
pragma solidity ^0.8.0;
import "./LogicLibrary.sol";
contract MainContract {
using LogicLibrary for *;
function setValue(uint256 _value) public {
LogicLibrary.setValue(_value);
}
}এখানে, LogicLibrary একটি লাইব্রেরি কন্ট্রাক্ট হিসেবে কাজ করছে, যা একাধিক কন্ট্রাক্টে ব্যবহৃত হতে পারে এবং যখন এটি আপগ্রেড করা হয়, তখন পুরো সিস্টেমটি আপডেট হয়ে যায়।
3. Contract Upgradability এর জন্য OpenZeppelin SDK
OpenZeppelin একটি জনপ্রিয় লাইব্রেরি যা স্মার্ট কন্ট্রাক্টের সুরক্ষা এবং স্ট্যান্ডার্ডাইজেশন নিশ্চিত করে। OpenZeppelin এর মধ্যে Upgradeable Contracts ব্যবহারের জন্য একটি শক্তিশালী SDK এবং প্যাটার্ন রয়েছে। এটি Proxy প্যাটার্নের মাধ্যমে আপগ্রেডেবল কন্ট্রাক্ট তৈরি করতে সহায়ক।
OpenZeppelin SDK Example:
# Install OpenZeppelin SDK
npm install @openzeppelin/upgrades-core// Logic contract
pragma solidity ^0.8.0;
contract Logic {
uint256 public value;
function setValue(uint256 _value) public {
value = _value;
}
}
// Deployment via OpenZeppelin SDK
import "@openzeppelin/hardhat-upgrades";
const Logic = await ethers.getContractFactory("Logic");
const logic = await upgrades.deployProxy(Logic, [10], {initializer: 'initialize'});
await logic.deployed();এখানে, OpenZeppelin SDK ব্যবহার করে Proxy প্যাটার্নের মাধ্যমে স্মার্ট কন্ট্রাক্ট আপগ্রেড করা হয়েছে। এর মাধ্যমে আপনি সহজে আপনার কন্ট্রাক্টকে আপগ্রেড করতে পারেন।
সারাংশ
Contract Upgradability একটি গুরুত্বপূর্ণ ধারণা, কারণ স্মার্ট কন্ট্রাক্ট একবার ডিপ্লয় হওয়ার পর তার কোড পরিবর্তন করা সম্ভব নয়। তবে Proxy Pattern, Eternal Storage Pattern, এবং Upgradeable Contract Libraries এর মতো কৌশল ব্যবহার করে আপনি স্মার্ট কন্ট্রাক্টের লজিক পরিবর্তন বা আপগ্রেড করতে পারেন, এবং OpenZeppelin SDK এর মাধ্যমে এই প্রক্রিয়াটি আরও সহজ ও নিরাপদ করা যায়।
Read more