Integer Overflow এবং Integer Underflow হচ্ছে এমন গাণিতিক ত্রুটি যা Solidity তে বিশেষ করে গুরুত্বপূর্ণ, বিশেষত যখন আপনি গাণিতিক অপারেশন করেন যেমন যোগফল, বিয়োগফল, গুণফল, এবং ভাগফল। যখন একটি সংখ্যা তার সর্বোচ্চ বা সর্বনিম্ন মানের চেয়ে বেশী বা কম হয়ে যায়, তখন এটি overflow এবং underflow ঘটায়।
SafeMath লাইব্রেরি এই ধরনের সমস্যা এড়াতে সহায়ক এবং এটি গাণিতিক অপারেশনের ক্ষেত্রে নিরাপত্তা নিশ্চিত করে।
১. Integer Overflow এবং Underflow
Integer Overflow:
Overflow ঘটে যখন একটি সংখ্যা তার সর্বোচ্চ মান অতিক্রম করে। Solidity তে সাধারণত uint256 (যা 0 থেকে 2^256-1 পর্যন্ত সংখ্যা ধারণ করতে পারে) ব্যবহার করা হয়। যদি একটি সংখ্যা এর সর্বোচ্চ মান (2^256-1) অতিক্রম করে, এটি পুনরায় সর্বনিম্ন মান (0) এ চলে যায়, যা overflow হিসেবে চিহ্নিত হয়।
Integer Underflow:
Underflow ঘটে যখন একটি সংখ্যা তার সর্বনিম্ন মান (যেমন 0) থেকে কম হয়। Solidity তে uint256 টাইপের ক্ষেত্রে, যদি আপনি 0 থেকে কম কিছু বিয়োগ করেন, এটি পুনরায় সর্বোচ্চ মানে (2^256-1) চলে যায়, যা underflow হিসেবে পরিচিত।
২. SafeMath লাইব্রেরি
Solidity 0.8.0 সংস্করণ থেকে গাণিতিক অপারেশনগুলো স্বয়ংক্রিয়ভাবে overflow এবং underflow চেক করে, যার ফলে অতিরিক্ত গ্যাস খরচ হয়। তবে পুরনো সংস্করণে এবং বর্তমান সময়ে SafeMath লাইব্রেরি ব্যবহারের মাধ্যমে আপনি এই সমস্যাগুলো সহজে এড়াতে পারেন। SafeMath লাইব্রেরি মূলত require ব্যবহার করে, যখন একটি অপারেশন overflow বা underflow সৃষ্টি করবে, তখন এটি একটি ত্রুটি সৃষ্টি করবে এবং ট্রানজেকশন বাতিল করবে।
Solidity তে SafeMath লাইব্রেরি ব্যবহারের জন্য একটি উদাহরণ দেখা যাক:
SafeMath লাইব্রেরি ব্যবহার:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// SafeMath লাইব্রেরির উদাহরণ (Solidity 0.8.0 এবং পরবর্তী সংস্করণে গ্যাস অপটিমাইজেশন)
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function subtract(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction underflow");
uint256 c = a - b;
return c;
}
function multiply(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function divide(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
uint256 c = a / b;
return c;
}
}
contract Token {
using SafeMath for uint256;
uint256 public totalSupply;
mapping(address => uint256) public balances;
constructor(uint256 _initialSupply) {
totalSupply = _initialSupply;
balances[msg.sender] = _initialSupply;
}
// Deposit function using SafeMath to avoid overflow/underflow
function deposit(uint256 amount) public {
totalSupply = totalSupply.add(amount); // SafeMath: addition overflow check
balances[msg.sender] = balances[msg.sender].add(amount); // SafeMath
}
// Withdraw function using SafeMath to avoid overflow/underflow
function withdraw(uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] = balances[msg.sender].subtract(amount); // SafeMath: subtraction underflow check
totalSupply = totalSupply.subtract(amount); // SafeMath
}
// Transfer function using SafeMath
function transfer(address recipient, uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] = balances[msg.sender].subtract(amount); // SafeMath: subtraction underflow check
balances[recipient] = balances[recipient].add(amount); // SafeMath: addition overflow check
}
}এখানে:
- SafeMath লাইব্রেরির মাধ্যমে
add,subtract,multiply, এবংdivideঅপারেশনগুলো সঞ্চালিত হচ্ছে। - প্রতিটি গাণিতিক অপারেশনে
requireব্যবহার করা হচ্ছে যা নিশ্চিত করে যে overflow বা underflow ঘটবে না।
৩. Solidity 0.8.0 এর পরবর্তী সংস্করণের স্বয়ংক্রিয় Overflow/Underflow চেক
Solidity 0.8.0 থেকে, গাণিতিক অপারেশনগুলোতে overflow এবং underflow স্বয়ংক্রিয়ভাবে চেক করা হয়। ফলে SafeMath লাইব্রেরি ব্যবহার করার প্রয়োজন কমে গেছে। Solidity 0.8.0 এ যদি আপনি কোনো অপারেশন করে সংখ্যার সীমা অতিক্রম করেন, তবে এটি একটি ত্রুটি (error) তৈরি করবে এবং ট্রানজেকশন বাতিল করে দেবে।
উদাহরণ (Solidity 0.8.0 বা পরবর্তী সংস্করণ):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SafeMathExample {
uint256 public totalSupply;
mapping(address => uint256) public balances;
constructor(uint256 _initialSupply) {
totalSupply = _initialSupply;
balances[msg.sender] = _initialSupply;
}
// Deposit function without SafeMath (using built-in checks)
function deposit(uint256 amount) public {
totalSupply += amount; // Solidity 0.8.0+ automatically checks for overflow
balances[msg.sender] += amount;
}
// Withdraw function without SafeMath (using built-in checks)
function withdraw(uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount; // Solidity 0.8.0+ automatically checks for underflow
totalSupply -= amount;
}
// Transfer function without SafeMath (using built-in checks)
function transfer(address recipient, uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount; // Solidity 0.8.0+ automatically checks for underflow
balances[recipient] += amount; // Solidity 0.8.0+ automatically checks for overflow
}
}এখানে:
- Solidity 0.8.0 এবং তার পরবর্তী সংস্করণে গাণিতিক অপারেশন স্বয়ংক্রিয়ভাবে overflow এবং underflow চেক করে। এই কারণে SafeMath লাইব্রেরি ব্যবহারের প্রয়োজন নেই।
সারাংশ
Integer Overflow এবং Integer Underflow Solidity তে গাণিতিক অপারেশনের সময় দুটি প্রধান সমস্যা যা হতে পারে, এবং এটি স্মার্ট কন্ট্রাক্টে ভুল হিসাবের কারণ হতে পারে। SafeMath লাইব্রেরি ব্যবহারের মাধ্যমে আপনি এই সমস্যা এড়িয়ে যেতে পারেন, যেখানে প্রতিটি গাণিতিক অপারেশন যাচাই করা হয় যাতে overflow বা underflow না ঘটে। Solidity 0.8.0 থেকে, এই ধরনের চেক স্বয়ংক্রিয়ভাবে অন্তর্ভুক্ত করা হয়েছে, যার ফলে SafeMath ব্যবহার করার প্রয়োজন কিছুটা কমে গেছে। তবে, যদি পুরনো সংস্করণ ব্যবহার করেন, তবে SafeMath লাইব্রেরি নিরাপদ এবং গ্যাস-কার্যকরীভাবে এই সমস্যা প্রতিরোধে সহায়তা করে।
Read more