0000000000164f2434262e1cc",
We can see that there are various events in the logs data, if we only care about ```Transfer``` events, we need to filter out the ```Transfer``` events in these data.
### Retrieving Logs
The Ethereum log is divided into two parts: 1. ```topics```; 2. ```data```.
- ```topics```
Taking the results of the code run for the ```eth_getLogs``` section test as an example, the data in the ```topics``` field is:
```desc
"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x00000000000000000000000012b791bb27b3a4ee958b5a435fea7d49ec076e9c", "0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b"],
এর মূল্যtopics
field একটি অ্যারে কাঠামো যা ইভেন্টটি বর্ণনা করতে ব্যবহৃত হয়। এটি নির্দিষ্ট করা হয়েছে যে এর (অ্যারে) দৈর্ঘ্য 4 এর বেশি হতে পারে না এবং প্রথম উপাদানটি ইভেন্টের স্বাক্ষর হ্যাশ।
FMZ কোয়ান্ট ট্রেডিং প্ল্যাটফর্মে, আমরা এই স্বাক্ষর হ্যাশ গণনা করতে পারিEncode
ফাংশন, নিম্নলিখিত কোড ব্যবহার করেঃ
function main() {
var eventFunction = "Transfer(address,address,uint256)"
var eventHash = Encode("keccak256", "string", "hex", eventFunction)
Log("eventHash:", "0x" + eventHash)
// eventHash: 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
}
হিসাব করুনkeccak256
এর হ্যাশ মান (হেক্স কোডিং)Transfer(address,address,uint256)
হয়0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
.
এর মূল্যtopics
ক্ষেত্র একটি অ্যারে কাঠামো, যার দ্বিতীয় উপাদান, এবং তৃতীয় উপাদান, যথাক্রমেঃ
পাঠানোর ঠিকানাfrom
প্রাপ্তির ঠিকানাto
data
এই তথ্যdata
ক্ষেত্রগুলি হলঃ
"data": "0x0000000000000000000000000000000000000000000000000164f2434262e1cc",
স্মার্ট কন্ট্রাক্টের সলিডিটি কোডে ইনডেক্সড বিবৃতি ছাড়াই কিছু পরামিতি (প্যারামিটার) সঞ্চিত হয়।data
section.
তথ্য বিশ্লেষণ করুন0x0000000000000000000000000000000000000000000000000164f2434262e1cc
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
var value = "0x0000000000000000000000000000000000000000000000000164f2434262e1cc"
Log(toAmount(value, 0) / 1e18) // 0.10047146239950075
}
এই তথ্যগুলি 0.10047146239950075 হিসাবে পাওয়া যায় এবংdata
হল সংশ্লিষ্ট ট্রান্সফারের পরিমাণ।
উপরের কথাগুলো ব্যাখ্যা করা হয়েছে, অনুশীলন করা হয়েছে এবং শুরু করার জন্য প্রস্তুত। আমরা লগগুলি পুনরুদ্ধার শুরু করতে পারিঃ
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function toInnerAmount(n, decimals) {
return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function main() {
// getBlockNumber
var blockNumber = exchange.IO("api", "eth", "eth_blockNumber")
Log("blockNumber:", blockNumber)
// get logs
var fromBlock = "0x" + (toAmount(blockNumber, 0) - 1).toString(16)
var toBlock = "0x" + toAmount(blockNumber, 0).toString(16)
var params = {
"fromBlock" : fromBlock,
"toBlock" : toBlock,
"address" : "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
}
var logs = exchange.IO("api", "eth", "eth_getLogs", params)
// Traverse logs
var eventFunction = "Transfer(address,address,uint256)"
var eventHash = "0x" + Encode("keccak256", "string", "hex", eventFunction)
Log("eventHash:", eventHash)
var counter = 0
for (var i = logs.length - 1; i >= 0 && counter < 10; i--) {
if (logs[i].topics[0] == eventHash) {
Log("Event Transfer, data:", toAmount(logs[i].data, 0) / 1e18, ", blockNumber:", toAmount(logs[i].blockNumber, 0), ", transactionHash:", logs[i].transactionHash,
", log:", logs[i])
counter++
}
}
}
চেক ইন করুনhttps://etherscan.io/
:
এফএমজেড ডিবাগিং টুল-এ চালিত পরীক্ষার কোডের ফলাফলঃ
তথ্যfrom
, to
ক্ষেত্রগুলি পুনরুদ্ধারের সময় প্রয়োজনীয়তার উপর নির্ভর করে বিশ্লেষণ করা যেতে পারে, উদাহরণস্বরূপঃ
function main() {
var from = "0x00000000000000000000000012b791bb27b3a4ee958b5a435fea7d49ec076e9c"
var address = "0x" + exchange.IO("encodePacked", "address", from)
Log("address:", address)
}
চলমান ফলাফল:
ঠিকানাঃ 0x12b791bb27b3a4ee958b5a435fea7d49ec076e9c
যেহেতুডিবাগিং টুলএই বিভাগে, আমরা এফএমজেড কোয়ান্ট ট্রেডিং প্ল্যাটফর্ম ব্যবহার করি লাইভ ট্রেডিং তৈরি করতে পরীক্ষা করার জন্য।
এখানে আমরা ইথেরিয়াম মেইননেট ব্যবহার করি, এবং আমরাTransfer(address,address,uint256)
ঘটনাUSDT
গত পাঠে আমরা যা শিখেছি তার ভিত্তিতে, আমরা একটি নির্দিষ্ট স্মার্ট কন্ট্রাক্টের ইভেন্টগুলি ক্রমাগত শোনার একটি উদাহরণ ডিজাইন এবং লিখেছিঃ
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function toInnerAmount(n, decimals) {
return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function addEventListener(contractAddress, event, callBack) {
var self = {}
self.eventHash = "0x" + Encode("keccak256", "string", "hex", event)
self.contractAddress = contractAddress
self.latestBlockNumber = 0
self.fromBlockNumber = 0
self.firstBlockNumber = 0
/* TODO: test
self.isFirst = true
*/
self.getBlockNumber = function() {
var maxTry = 10
for (var i = 0; i < maxTry; i++) {
var ret = exchange.IO("api", "eth", "eth_blockNumber")
if (ret) {
return toAmount(ret, 0)
}
Sleep(5000)
}
throw "getBlockNumber failed"
}
self.run = function() {
var currBlockNumber = self.getBlockNumber()
var fromBlock = "0x" + self.fromBlockNumber.toString(16)
var toBlock = "0x" + currBlockNumber.toString(16)
var params = {
"fromBlock" : fromBlock,
"toBlock" : toBlock,
"address" : self.contractAddress,
"topics" : [self.eventHash]
}
// Log("fromBlockNumber:", self.fromBlockNumber, ", currBlockNumber:", currBlockNumber, "#FF0000")
var logs = exchange.IO("api", "eth", "eth_getLogs", params)
if (!logs) {
return
}
for (var i = 0; i < logs.length; i++) {
if (toAmount(logs[i].blockNumber, 0) > self.latestBlockNumber) {
/* TODO: test
if (self.isFirst) {
self.firstBlockNumber = toAmount(logs[i].blockNumber, 0)
Log("firstBlockNumber:", self.firstBlockNumber)
self.isFirst = false
}
*/
callBack(logs[i])
}
}
self.latestBlockNumber = currBlockNumber
self.fromBlockNumber = self.latestBlockNumber - 1
}
self.latestBlockNumber = self.getBlockNumber()
self.fromBlockNumber = self.latestBlockNumber - 1
return self
}
var listener = null
function main() {
var event = "Transfer(address,address,uint256)"
var contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7"
var decimals = exchange.IO("api", contractAddress, "decimals")
Log(exchange.IO("api", contractAddress, "name"), " decimals:", decimals)
listener = addEventListener(contractAddress, event, function(log) {
var fromAddress = "0x" + exchange.IO("encodePacked", "address", log.topics[1])
var toAddress = "0x" + exchange.IO("encodePacked", "address", log.topics[2])
Log("Transfer:", fromAddress, "->", toAddress, ", value:", toAmount(log.data, decimals), ", blockNumber:", toAmount(log.blockNumber, 0))
/* TODO: test
arrLog.push(log)
*/
})
while (true) {
listener.run()
Sleep(5000)
}
}
/* TODO: test
var arrLog = []
function onexit() {
Log("End the run and verify the record")
var firstBlockNumber = listener.firstBlockNumber
var endBlockNumber = listener.latestBlockNumber
Log("getLogs, from:", firstBlockNumber, " -> to:", endBlockNumber)
var fromBlock = "0x" + (firstBlockNumber).toString(16)
var toBlock = "0x" + (endBlockNumber).toString(16)
var params = {
"fromBlock" : fromBlock,
"toBlock" : toBlock,
"topics" : ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
"address" : "0xdac17f958d2ee523a2206206994597c13d831ec7"
}
var logs = exchange.IO("api", "eth", "eth_getLogs", params)
Log("arrLog:", arrLog.length)
Log("logs:", logs.length)
if (arrLog.length != logs.length) {
Log("Length varies!")
return
}
for (var i = 0; i < arrLog.length; i++) {
Log("Determine the blockNumber:", logs[i].blockNumber == arrLog[i].blockNumber, ", Determine from:", logs[i].topics[1] == arrLog[i].topics[1],
"Determine to:", logs[i].topics[2] == arrLog[i].topics[2])
}
}
*/
লাইভ ট্রেডিং চালাচ্ছে:
এক্সিকিউশন ফলাফলের জন্য, একটি বৈধতা বিভাগ (TODO: পরীক্ষা) কোড লিখিত হয়। একটি সহজ বৈধতা পরে এটি দেখা যায় যেTransfer
ইউএসডিটি কন্ট্রাক্টের ইভেন্টটি ক্রমাগত পর্যবেক্ষণ করা হয় এবং ডেটা রেকর্ড করা হয় এবং এই ডেটা এবং একযোগে প্রাপ্ত ইভেন্ট ডেটাগুলির মধ্যে তুলনা করে দেখা যায় যে ডেটাগুলি নিম্নলিখিতগুলির সাথে সামঞ্জস্যপূর্ণঃ
পূর্ববর্তী পাঠের উপর ভিত্তি করেListening to contract events
, আমরা এটি সম্প্রসারণ করে শোনার প্রক্রিয়া ফিল্টার যোগ নির্দিষ্ট ঠিকানাগুলি থেকে এবং স্থানান্তর জন্য শুনতে. যখন একটি স্মার্ট চুক্তি একটি লগ তৈরি করে (যেমন একটি ইভেন্ট মুক্তি), লগ ডেটাtopics
তথ্যের 4 টুকরা পর্যন্ত রয়েছে. তাই আমরা একটি ফিল্টার নিয়ম ডিজাইন[[A1, A2, ...An], null, [C1], D]
উদাহরণস্বরূপ।
[A1, A2, ...An]
অবস্থানের সাথে মিলে যায়topics[0]
.Null
অবস্থানের সাথে মিলে যায়topics[1]
.[C1]
অবস্থানের সাথে মিলে যায়topics[2]
.D
অবস্থানের সাথে মিলে যায়topics[3]
.null
এর মানে হল এটি ফিল্টার করা হয়নি, যেমনঃnull
এর সাথে মিলে যায়topics[1]
এবং যেকোনো মানের মিল।[C1]
এর সাথে মিলে যায়topics[2]
অথবাD
এর সাথে মিলে যায়topics[3]
, এবং অনুপযুক্ত লগগুলি ফিল্টার করা হয়।[A1, A2, ...An]
এর সাথে মিলে যায়topics[0]
, [A1, A2, ...An]
তাদের কোন এক মিলেtopics[0]
, তাহলে লগগুলি ফিল্টার করা হবে না।এক্সচেঞ্জ থেকে ইউএসডিটি স্থানান্তর শুনতে
পর্যবেক্ষণUSDT
বিয়ানান্স এক্সচেঞ্জ থেকে এবং সেখানে স্থানান্তরিত লেনদেনঃ
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function toInnerAmount(n, decimals) {
return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function addEventListener(contractAddress, event, callBack) {
var self = {}
self.eventHash = "0x" + Encode("keccak256", "string", "hex", event)
self.contractAddress = contractAddress
self.latestBlockNumber = 0
self.fromBlockNumber = 0
self.firstBlockNumber = 0
self.filters = []
self.setFilter = function(filterCondition) {
if (filterCondition.length > 4) {
throw "filterCondition error"
}
self.filters.push(filterCondition)
Log("Set filter conditions:", filterCondition)
}
self.getTokenBalanceOfWallet = function(walletAddress, tokenAddress, tokenDecimals) {
var balance = exchange.IO("api", tokenAddress, "balanceOf", walletAddress)
if (balance) {
return toAmount(balance, tokenDecimals)
}
return null
}
self.getBlockNumber = function() {
var maxTry = 10
for (var i = 0; i < maxTry; i++) {
var ret = exchange.IO("api", "eth", "eth_blockNumber")
if (ret) {
return toAmount(ret, 0)
}
Sleep(5000)
}
throw "getBlockNumber failed"
}
self.run = function() {
var currBlockNumber = self.getBlockNumber()
var fromBlock = "0x" + self.fromBlockNumber.toString(16)
var toBlock = "0x" + currBlockNumber.toString(16)
var params = {
"fromBlock" : fromBlock,
"toBlock" : toBlock,
"address" : self.contractAddress,
"topics" : [self.eventHash]
}
var logs = exchange.IO("api", "eth", "eth_getLogs", params)
if (!logs) {
return
}
for (var i = 0; i < logs.length; i++) {
if (toAmount(logs[i].blockNumber, 0) > self.latestBlockNumber) {
// Check the filter condition, and execute the judgment if the filter condition is set
if (self.filters.length != 0) {
// Initial filter marker
var isFilter = true
// Traverse filter condition setting
for (var j = 0; j < self.filters.length; j++) {
// Take a filter setting, e.g: [[A1, A2, ...An], null, [C1], D]
var cond = self.filters[j]
// Traverse the filter setting
var final = true
for (var topicsIndex = 0; topicsIndex < cond.length; topicsIndex++) {
// Take one of the conditions in the filter setting, if it is the first condition: i.e. the data to be compared with topics[0]
var condValue = cond[topicsIndex]
// Data in the logs
if (topicsIndex > logs[i].topics.length - 1) {
continue
}
var topicsEleValue = logs[i].topics[topicsIndex]
// If it's a Transfer event, you need to handle the from and to
if (logs[i].topics[0] == "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef") {
if (topicsIndex == 1 || topicsIndex == 2) {
topicsEleValue = "0x" + exchange.IO("encodePacked", "address", topicsEleValue)
}
}
// If the condValue type is an array, it means that there are multiple comparison conditions in this position, and the multiple condition comparison is a logical or relationship
if (Array.isArray(condValue) && condValue.length > 1) {
// Determine condValue[0] == topicsEleValue || condValue[1] == topicsEleValue
final = final && condValue.some(element => element === topicsEleValue)
}else if (condValue === null) {
final = final && true
} else {
final = final && (condValue === topicsEleValue)
}
}
if (final) {
isFilter = false
}
}
if (isFilter) {
continue
}
}
callBack(logs[i])
}
}
self.latestBlockNumber = currBlockNumber
self.fromBlockNumber = self.latestBlockNumber - 1
}
self.latestBlockNumber = self.getBlockNumber()
self.fromBlockNumber = self.latestBlockNumber - 1
return self
}
var listener = null
function main() {
// Initial clean-up log
LogReset(1)
LogProfitReset()
var event = "Transfer(address,address,uint256)" // Listening to events
var contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7" // USDT contract address
var decimals = exchange.IO("api", contractAddress, "decimals") // Get the precision information of USDT token
var accountBinanceAddress = "0x28C6c06298d514Db089934071355E5743bf21d60" // Binance hot wallet address
accountBinanceAddress = accountBinanceAddress.toLowerCase() // Addresses are handled in lowercase
Log(exchange.IO("api", contractAddress, "name"), " decimals:", decimals)
// Creating a listener object
listener = addEventListener(contractAddress, event, function(log) {
var fromAddress = "0x" + exchange.IO("encodePacked", "address", log.topics[1])
var toAddress = "0x" + exchange.IO("encodePacked", "address", log.topics[2])
if (fromAddress == accountBinanceAddress) {
Log("Binance transfer out - ", " Transfer:", fromAddress, "->", toAddress, ", value:", toAmount(log.data, decimals), ", blockNumber:", toAmount(log.blockNumber, 0), "#CD32CD")
} else if (toAddress == accountBinanceAddress) {
Log("Binance transfer in - ", " Transfer:", fromAddress, "->", toAddress, ", value:", toAmount(log.data, decimals), ", blockNumber:", toAmount(log.blockNumber, 0), "#FF0000")
}
})
// Set up event filtering
listener.setFilter([null, accountBinanceAddress, null]) // Binance -> USDT
listener.setFilter([null, null, accountBinanceAddress]) // USDT -> Binance
var preBalance = 0
while (true) {
listener.run()
var balance = listener.getTokenBalanceOfWallet(accountBinanceAddress, contractAddress, decimals)
if (balance) {
var direction = ""
if (preBalance != 0 && preBalance > balance) {
direction = " ↓ " + (preBalance - balance) + "#CD32CD"
} else if (preBalance != 0 && preBalance < balance) {
direction = " ↑ " + (balance - preBalance) + "#FF0000"
}
Log("Binance wallet address:", accountBinanceAddress, " balance:", balance, direction)
LogProfit(balance, "&") // Drawing only, no log printing
preBalance = balance
}
LogStatus(_D(), "Binance wallet address:", accountBinanceAddress, ", balance:", balance)
Sleep(5000 * 3)
}
}
উপরের কোডটি লাইভ ট্রেডিং-এ চলমানঃ
এই পাঠে, আমরা একটি ইভেন্ট ফিল্টার ডিজাইন কিভাবে চালু.USDT
আপনি এই নমুনা প্রোগ্রামটি সংশোধন এবং প্রসারিত করতে পারেন যে কোন ইভেন্ট আপনি আগ্রহী শুনতে, কি নতুন লেনদেন দেখতেsmart money
কি নতুন আইটেম তৈরি করেছেNFT
টাইকুনরা তাড়াহুড়ো করেছে, ইত্যাদি।
ইথেরিয়ামের সাথে সম্পর্কিত অনেক গণনার মান রয়েছে যা সর্বোচ্চ নিরাপদ পূর্ণসংখ্যা অতিক্রম করেJavaScript
তাই, বড় মানগুলি পরিচালনা করার জন্য FMZ কোয়ান্ট ট্রেডিং প্ল্যাটফর্মে কিছু পদ্ধতি প্রয়োজন, যা আমরা পূর্ববর্তী কোর্সে বিশেষভাবে ব্যবহার করেছি এবং বিস্তারিতভাবে কভার করি নি। এই বিভাগে এই দিকটি বিস্তারিতভাবে আলোচনা করা হবে।
সর্বাধিক নিরাপদ পূর্ণসংখ্যা মুদ্রণ করুনJavaScript
ভাষা:
function main() {
Log("Number.MAX_SAFE_INTEGER:", Number.MAX_SAFE_INTEGER)
}
চলমান ফলাফল:
নম্বর.MAX_SAFE_INTEGER: 9007199254740991
ইথেরিয়ামে সংজ্ঞায়িত ক্ষুদ্রতম একক হল1wei
, এবং সংজ্ঞা1Gwei
সমান1000000000 wei
. 1Gwei
ইথেরিয়ামের সাথে সম্পর্কিত হিসাবের ক্ষেত্রে এটি খুব বড় সংখ্যা নয়, এবং কিছু ডেটা এর চেয়ে অনেক বড়। সুতরাং খুব বড় মানের এই ডেটা সহজেই অতিক্রম করতে পারেNumber.MAX_SAFE_INTEGER: 9007199254740991
.
এফএমজেড কোয়ান্ট ট্রেডিং প্ল্যাটফর্মে, আমরা প্ল্যাটফর্মগুলি ব্যবহার করিBigInt
এই খুব বড় পূর্ণসংখ্যা তথ্য প্রতিনিধিত্ব করতে বস্তুর ব্যবহার করুন।BigInt()
তৈরি করতেBigInt
আপনি নির্মাণ করতে পারেনBigInt
প্যারামিটার হিসাবে সংখ্যাসূচক, ষোড়শ সংখ্যাসূচক স্ট্রিং ব্যবহার করে বস্তুর.toString()
পদ্ধতিBigInt
বস্তুর দ্বারা প্রতিনিধিত্বকৃত তথ্য একটি স্ট্রিং হিসাবে আউটপুট করার জন্য।
এই প্রকল্পের আওতাভুক্ত কর্মকাণ্ডBigInt
উদ্দেশ্য হল:
+
-
*
/
%
*
নিম্নলিখিত কোডের উদাহরণ দেখুনঃ
function main() {
// Decimal representation of 1Gwei
var oneGwei = 1000000000
// Decimal to hexadecimal conversion of 1Gwei
var oneGweiForHex = "0x" + oneGwei.toString(16)
Log("oneGwei : ", oneGwei)
Log("oneGweiForHex : ", oneGweiForHex)
// Constructing BigInt objects
Log("1Gwei / 1Gwei : ", (BigInt(oneGwei) / BigInt(oneGweiForHex)).toString(10))
Log("1Gwei * 1Gwei : ", (BigInt(oneGwei) * BigInt(oneGweiForHex)).toString(10))
Log("1Gwei - 1Gwei : ", (BigInt(oneGwei) - BigInt(oneGweiForHex)).toString(10))
Log("1Gwei + 1Gwei : ", (BigInt(oneGwei) + BigInt(oneGweiForHex)).toString(10))
Log("(1Gwei + 1) % 1Gwei : ", (BigInt(oneGwei + 1) % BigInt(oneGweiForHex)).toString(10))
Log("1Gwei ** 2 : ", (BigInt(oneGwei) ** BigInt(2)).toString(10))
Log("The square root of 100 : ", (BigInt(100) ** BigFloat(0.5)).toString(10))
Log("Number.MAX_SAFE_INTEGER : ", BigInt(Number.MAX_SAFE_INTEGER).toString(10))
Log("Number.MAX_SAFE_INTEGER * 2 : ", (BigInt(Number.MAX_SAFE_INTEGER) * BigInt("2")).toString(10))
}
ডিবাগিং টুল টেস্টিংঃ
2023-06-08 11:39:50 Info Number.MAX_SAFE_INTEGER * 2 : 18014398509481982
2023-06-08 11:39:50 Info Number.MAX_SAFE_INTEGER : 9007199254740991
2023-06-08 11:39:50 Info The square root of 100 : 10
2023-06-08 11:39:50 Info 1Gwei ** 2 : 1000000000000000000
2023-06-08 11:39:50 Info (1Gwei + 1) % 1Gwei : 1
2023-06-08 11:39:50 Info 1Gwei + 1Gwei : 2000000000
2023-06-08 11:39:50 Info 1Gwei - 1Gwei : 0
2023-06-08 11:39:50 Info 1Gwei * 1Gwei : 1000000000000000000
2023-06-08 11:39:50 Info 1Gwei / 1Gwei : 1
2023-06-08 11:39:50 Info oneGweiForHex : 0x3b9aca00
2023-06-08 11:39:50 Info oneGwei : 1000000000
দ্যBigFloat
বস্তুর অনুরূপভাবে ব্যবহার করা হয়BigInt
বড় মানের সাথে ভাসমান বিন্দু সংখ্যা উপস্থাপন করতে, এবং এটি যোগ, বিয়োগ, গুণ এবং বিভাজন সমর্থন করে।
দ্যBigFloat
বস্তুর সমর্থন করেtoFixed()
method.
নিম্নলিখিত কোড উদাহরণ দেখুনঃ
function main() {
var pi = 3.14
var oneGwei = "1000000000"
var oneGweiForHex = "0x3b9aca00"
Log("pi + oneGwei : ", (BigFloat(pi) + BigFloat(oneGwei)).toFixed(2))
Log("pi - oneGweiForHex : ", (BigFloat(pi) - BigFloat(oneGweiForHex)).toFixed(2))
Log("pi * 2.0 : ", (BigFloat(pi) * BigFloat(2.0)).toFixed(2))
Log("pi / 2.0 : ", (BigFloat(pi) / BigFloat(2.0)).toFixed(2))
}
ডিবাগিং টুল টেস্টিংঃ
2023-06-08 13:56:44 Info pi / 2.0 : 1.57
2023-06-08 13:56:44 Info pi * 2.0 : 6.28
2023-06-08 13:56:44 Info pi - oneGweiForHex : -999999996.86
2023-06-08 13:56:44 Info pi + oneGwei : 1000000003.14
দ্যBigDecimal
বস্তুর পূর্ণসংখ্যা মান এবং ভাসমান বিন্দু মান সঙ্গে সামঞ্জস্যপূর্ণ, এবংBigInt
বস্তুর এবংBigFloat
এবং এটি যোগ, বিয়োগ, গুণ এবং বিভাজন সমর্থন করে।
নিম্নলিখিত কোড উদাহরণ দেখুনঃ
function main() {
var pi = 3.1415
var oneGwei = 1000000000
var oneGweiForHex = "0x3b9aca00"
Log("pi : ", BigDecimal(pi).toFixed(2))
Log("oneGwei : ", BigDecimal(oneGwei).toString())
Log("oneGweiForHex : ", BigDecimal(BigInt(oneGweiForHex)).toString())
Log("BigInt(oneGwei) : ", BigDecimal(BigInt(oneGwei)).toString())
Log("BigFloat(pi) : ", BigDecimal(BigFloat(pi)).toFixed(4))
Log("oneGwei + pi : ", (BigDecimal(oneGwei) + BigDecimal(pi)).toString())
Log("oneGwei - pi : ", (BigDecimal(oneGwei) - BigDecimal(pi)).toString())
Log("2.0 * pi : ", (BigDecimal(2.0) * BigDecimal(pi)).toString())
Log("pi / pi : ", (BigDecimal(pi) / BigDecimal(pi)).toString())
}
ডিবাগিং টুল চালানো হচ্ছেঃ
2023-06-08 14:52:53 Info pi / pi : 1
2023-06-08 14:52:53 Info 2.0 * pi : 6.283
2023-06-08 14:52:53 Info oneGwei - pi : 999999996.8585
2023-06-08 14:52:53 Info oneGwei + pi : 1000000003.1415
2023-06-08 14:52:53 Info BigFloat(pi) : 3.1415
2023-06-08 14:52:53 Info BigInt(oneGwei) : 1e+9
2023-06-08 14:52:53 Info oneGweiForHex : 1e+9
2023-06-08 14:52:53 Info oneGwei : 1e+9
2023-06-08 14:52:53 Info pi : 3.14
নিম্নলিখিত দুটি ফাংশনঃtoAmount()
, toInnerAmount()
আমরা পূর্ববর্তী কোর্সে অনেকবার ব্যবহার করেছি, এই দুটি ফাংশন প্রধানত ডেটা যথার্থ রূপান্তর জন্য ব্যবহৃত হয়।
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function toInnerAmount(n, decimals) {
return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
দ্যtoAmount()
ফাংশন একটি ভেরিয়েবলকে রূপান্তর করেs
যথার্থতা পরামিতি অনুযায়ীdecimals
ওয়েব৩ এর ব্যবহারিক উন্নয়নে, প্রায়ই কিছু চেইনড হেক্সাডেসিমাল ডেটা নিয়ে কাজ করা প্রয়োজন।
আমাদের পূর্ববর্তী কোর্সে আমরা প্রায়ই এর মুখোমুখি হয়েছি, উদাহরণস্বরূপ,data
ক্ষেত্রের তথ্যTransfer(address,address,uint256)
স্মার্ট কন্ট্রাক্টের ঘটনাঃ
{
"data": "0x00000000000000000000000000000000000000000000000001c1a55000000000",
"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000006b75d8af000000e20b7a7ddf000ba900b4009a80", "0x000000000000000000000000bcb095c1f9c3dc02e834976706c87dee5d0f1fb6"],
"transactionHash": "0x27f9bf5abe3148169b4b85a83e1de32bd50eb81ecc52e5af006157d93353e4c4",
"transactionIndex": "0x0",
"removed": false,
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"blockHash": "0x847be24a7b159c292bda030a011dfec89487b70e71eed486969b032d6ef04bad",
"blockNumber": "0x109b1cc",
"logIndex": "0x0"
}
তথ্য প্রক্রিয়াকরণের সময়"data": "0x00000000000000000000000000000000000000000000000001c1a55000000000"
, আমরা ব্যবহারtoAmount()
এই প্রক্রিয়াকরণটি ডাটা ফিল্ড ডেটাকে পাঠযোগ্য মানগুলিতে রূপান্তর করার জন্য একটি ভাল কাজ করার জন্য ডিজাইন করা হয়েছে।
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
var data = "0x00000000000000000000000000000000000000000000000001c1a55000000000"
Log(toAmount(data, 18)) // Print out 0.12656402755905127
}
1 ETH টোকেন, যেমনটা আমরা জানি,1e18 wei
, যদি আমরা একটি তথ্য পেতে126564027559051260
মধ্যেwei
, কিভাবে এটি ETH টোকেনে রূপান্তর করা যায়?
ব্যবহার করেtoAmount(, 18)
ফাংশন একটি খুব সহজ রূপান্তর পদ্ধতি.toInnerAmount()
ফাংশন হলtoAmount()
ফাংশন (নির্ভর করে, সঠিকতা জুম ইন), এবং এটি এই দুটি ফাংশন ব্যবহার করে তথ্য রূপান্তর করা সহজ।
জাভাস্ক্রিপ্ট ভাষায় পূর্ণসংখ্যা মান নিরাপত্তা পরিসীমা উল্লেখ করা গুরুত্বপূর্ণ,Number.MAX_SAFE_INTEGER
, এবং নিম্নলিখিত উদাহরণটি তথ্য রূপান্তর করার সময় একটি গোপন সমস্যা চিত্রিত করেঃ
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function toInnerAmount(n, decimals) {
return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function main() {
var amount = 0.01
var innerAmount = Number(toInnerAmount(amount, 18))
Log("Number.MAX_SAFE_INTEGER:", Number.MAX_SAFE_INTEGER) // 9007199254740991
Log("innerAmount:", innerAmount) // 10000000000000000
Log("typeof(innerAmount):", typeof(innerAmount), ", innerAmount:", innerAmount)
// Decimal value 10000000000000000 -> Hexadecimal value 0x2386f26fc10000
Log("Convert", innerAmount, "to hexadecimal:", innerAmount.toString(16))
Log("Convert", BigInt(10000000000000000).toString(10), "to hexadecimal:", BigInt(10000000000000000).toString(16))
Log("0x" + BigInt(10000000000000000).toString(16), "Convert to decimal:", toAmount("0x" + BigInt(10000000000000000).toString(16), 0))
}
ডিবাগিং টুল এ চালানো সম্ভবঃ
2023-06-15 16:21:40 Info Convert 0x2386f26fc10000 to decimal: 10000000000000000
2023-06-15 16:21:40 Info Convert 10000000000000000 to hexadecimal: 2386f26fc10000
2023-06-15 16:21:40 Info Convert 10000000000000000 to hexadecimal: 10000000000000000
2023-06-15 16:21:40 Info typeof(innerAmount): number , innerAmount: 10000000000000000
2023-06-15 16:21:40 Info innerAmount: 10000000000000000
2023-06-15 16:21:40 Info Number.MAX_SAFE_INTEGER: 9007199254740991
পর্যবেক্ষণের মাধ্যমে আমরা জানতে পেরেছি যে:
Log("Convert", innerAmount, "to hexadecimal:", innerAmount.toString(16))
কোডের এই লাইনটি লগ আউটপুটের সাথে মিলে যায়ঃConverting 10000000000000000 to hex: 10000000000000000
, যা সঠিকভাবে রূপান্তরিত হয় না। কারণ স্বাভাবিকভাবেই যে 100000000000000000000 অতিক্রমNumber.MAX_SAFE_INTEGER
.
কিন্তু যখন দশমিক মান নিরাপদ পরিসীমা মধ্যে হয়, অর্থাৎ, কমNumber.MAX_SAFE_INTEGER
,toString(16)
ফাংশন এটি আবার সঠিকভাবে রূপান্তর করে, উদাহরণস্বরূপঃ
function main() {
var value = 1000
Log("Convert value to hexadecimal:", "0x" + value.toString(16)) // 0x3e8
Log("Convert 0x3e8 to decimal:", Number("0x3e8")) // 1000
}
ব্লকচেইনে, এমনকি0.01
ETH এর মান রূপান্তরিত10000000000000000
মধ্যেwei
অতিক্রম করবেNumber.MAX_SAFE_INTEGER``, so a safer conversion for such cases is:
বিগ ইন্ট (১০০০০০০০০০০০০০০) স্ট্রিং (১৬) ``
লেনদেন সম্পাদন এবংWrite
ইথেরিয়ামের স্মার্ট কন্ট্রাক্টের পদ্ধতিতে নির্দিষ্ট পরিমাণে গ্যাস খরচ হয় এবং কখনও কখনও এটি ব্যর্থ হয়। এটি পাঠানোর আগে এবং তাদের কল করার আগে কোন লেনদেন ব্যর্থ হওয়ার সম্ভাবনা রয়েছে তা জানা গুরুত্বপূর্ণ। পরীক্ষার জন্য ইথেরিয়ামে সিমুলেটেড কল রয়েছে।
ইথেরিয়ামের আরপিসি পদ্ধতিeth_call
: এটি একটি লেনদেন সিমুলেট করতে পারে এবং একটি সম্ভাব্য লেনদেনের ফলাফল ফেরত দিতে পারে, কিন্তু এটি আসলে ব্লকচেইনে লেনদেন চালায় না।
দ্যeth_call
পদ্ধতিতে দুটি পরামিতি রয়েছে, প্রথমটি একটি অভিধান গঠন,transactionObject
:
// transactionObject
{
"from" : ..., // The address from which the transaction is sent
"to" : ..., // The address to which the transaction is addressed
"gas" : ..., // The integer of gas provided for the transaction execution
"gasPrice" : ..., // The integer of gasPrice used for each paid gas encoded as hexadecimal
"value" : ..., // The integer of value sent with this transaction encoded as hexadecimal
"data" : ..., // The hash of the method signature and encoded parameters. For more information, see the Contract ABI description in the Solidity documentation
}
দ্বিতীয় প্যারামিটার হলblockNumber
: আপনি লেবেল পাস করতে পারেনlatest/pending/earliest
ইত্যাদিঃ
/* blockNumber
The block number in hexadecimal format or the string latest, earliest, pending, safe or
finalized (safe and finalized tags are only supported on Ethereum, Gnosis, Arbitrum,
Arbitrum Nova and Avalanche C-chain), see the default block parameter description in
the official Ethereum documentation
*/
পরবর্তী, আমরা স্মার্ট চুক্তি পদ্ধতি নিতেapprove
এবংtransfer
টোকেনের কলDAI
সিমুলেশন কলের উদাহরণ হিসেবে, এবং নিম্নলিখিত পরীক্ষার পরিবেশ হল প্রধান ইথেরিয়াম নেটওয়ার্ক।
আমরা সবাই জানিapprove
ERC20 চুক্তির জন্য পদ্ধতি, এবং আমরা এটি পূর্ববর্তী কোর্সে অনুশীলন করেছি। যেহেতু ERC20 চুক্তি ইতিমধ্যে FMZ প্ল্যাটফর্ম ABI মধ্যে নির্মিত হয়, সিমুলেশন দ্বারা কল করা স্মার্ট চুক্তির ABI নিবন্ধন করার প্রয়োজন নেই।
function main() {
var contractAddressUniswapV3SwapRouterV2 = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
var contractAddress_DAI = "0x6b175474e89094c44da98b954eedeac495271d0f"
var wallet = exchange.IO("address")
// encode approve
var data = exchange.IO("encode", contractAddress_DAI, "approve(address,uint256)",
contractAddressUniswapV3SwapRouterV2, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
Log("ERC20 token DAI approve encode, data:", data)
var transactionObject = {
"from" : wallet,
"to" : contractAddress_DAI,
// "gasPrice" : "0x" + parseInt("21270894680").toString(16),
// "gas" : "0x" + parseInt("21000").toString(16),
"data" : "0x" + data,
}
var blockNumber = "latest"
var ret = exchange.IO("api", "eth", "eth_call", transactionObject, blockNumber)
Log("ret:", ret)
}
উদাহরণে কোডটি প্রথমে কোড করেapprove(address,uint256)
পদ্ধতি এবং পরামিতি, এবং পরামিতি মান0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
এরapprove
পদ্ধতি সর্বোচ্চ সংখ্যা অনুমোদন নির্দেশ করে. অনুমোদন ঠিকানায় স্মার্ট চুক্তি দেওয়া হয়0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45
অর্থাৎ রাউটার চুক্তিUniswap V3
অবশেষে ইথেরিয়াম আরপিসি পদ্ধতিeth_call
আপনি দেখতে পারেন যেgasPrice
এবংgas
জমিতেtransactionObject
প্যারামিটার বাদ দেওয়া যেতে পারে।
ডিবাগিং টুলটি চালানো হয় এবং সিমুলেশনটি অনুমোদন পদ্ধতিকে সফলভাবে অনুমোদন করার জন্য কল করে (এটি আসলে অনুমোদন করে না):
2023-06-09 11:58:39 Info ret: 0x0000000000000000000000000000000000000000000000000000000000000001
2023-06-09 11:58:39 Info ERC20 token DAI approve encode, data: 095ea7b300000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
এটিও সম্ভব কিছু ব্যর্থতার দৃশ্যকল্প সিমুলেট করা, যখন আমরাgasPrice
এবংgas
প্যারামিটার, যদি ওয়ালেটে ETH গ্যাস ফি পরিশোধের জন্য যথেষ্ট না হয়, একটি ত্রুটি রিপোর্ট করা হবে::
পর্যাপ্ত তহবিল নেই
যখন গ্যাসের খরচ খুব কম সেট করা হয়, তখন একটি ত্রুটি রিপোর্ট করা হবেঃ
অভ্যন্তরীণ গ্যাস খুব কমঃ 21000 আছে, 21944 চান (সরবরাহ গ্যাস 21000)
আমরা ERC20 transfer
পদ্ধতি, যা আপনাকে ERC20 টোকেন একটি নির্দিষ্ট মানিব্যাগ ঠিকানায় স্থানান্তর করতে দেয়, তাই আসুন 1000 DAI এর একটি স্থানান্তরকে ভিটালিক বুটারিনে সিমুলেট করার চেষ্টা করি।
function toInnerAmount(n, decimals) {
return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function main() {
var walletVitalik = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
var contractAddress_DAI = "0x6b175474e89094c44da98b954eedeac495271d0f"
var wallet = exchange.IO("address")
// transfer to Vitalik Buterin
var decimals_DAI = exchange.IO("api", contractAddress_DAI, "decimals")
var transferAmount = toInnerAmount(1000, decimals_DAI)
Log("Transfer amount:", 1000, "DAI, use toInnerAmount convert to:", transferAmount)
// encode transfer
var data = exchange.IO("encode", contractAddress_DAI, "transfer(address,uint256)",
walletVitalik, transferAmount)
var transactionObject = {
"from" : wallet,
"to" : contractAddress_DAI,
"data" : "0x" + data,
}
var blockNumber = "latest"
var ret = exchange.IO("api", "eth", "eth_call", transactionObject, blockNumber)
return ret
}
যেহেতু আমার এই টেস্ট ওয়ালেটে DAI টোকেন নেই, তাই এটি ডিবাগ টুলের মধ্যে চালানো অপ্রত্যাশিতভাবে নিম্নলিখিত ত্রুটি রিপোর্ট করেছেঃ
বাস্তবায়ন বিপরীতঃ Dai/insufficient-balance
ভিটালিক বুটারিনের মানিব্যাগের ঠিকানা দেখুন:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
, এটা স্পষ্ট যে এই মানিব্যাগ DAI টোকেন আছে. তাই আসুন অনুকরণ কল স্থানান্তর দিক সামঞ্জস্য এবং Vitalik Buterin থেকে আমাদের 1000 DAI স্থানান্তর অনুকরণ.
কোড পরিবর্তন করুন, যেখানে আমি পরিবর্তন মন্তব্য করেছেনঃ
function toInnerAmount(n, decimals) {
return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function main() {
var walletVitalik = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
var contractAddress_DAI = "0x6b175474e89094c44da98b954eedeac495271d0f"
var wallet = exchange.IO("address")
var decimals_DAI = exchange.IO("api", contractAddress_DAI, "decimals")
var transferAmount = toInnerAmount(1000, decimals_DAI)
Log("Transfer amount:", 1000, "DAI, use toInnerAmount convert to:", transferAmount)
// encode transfer
var data = exchange.IO("encode", contractAddress_DAI, "transfer(address,uint256)",
wallet, transferAmount) // Use the wallet variable as a parameter and change the transfer recipient's address to my own
var transactionObject = {
"from" : walletVitalik, // Use the walletVitalik variable as the value of the from field to simulate that the call was made from the Vitalik Buterin's wallet address
"to" : contractAddress_DAI,
"data" : "0x" + data,
}
var blockNumber = "latest"
var ret = exchange.IO("api", "eth", "eth_call", transactionObject, blockNumber)
Log(ret)
}
ডিবাগিং টুল পরীক্ষাঃ
2023-06-09 13:34:31 Info 0x0000000000000000000000000000000000000000000000000000000000000001
2023-06-09 13:34:31 Info Transfer amount: 1000 DAI, use toInnerAmount convert to: 1000000000000000000000
এফএমজেড কোয়ান্ট ট্রেডিং প্ল্যাটফর্ম ব্যবহার করে, লেনদেনের ফলাফল সিমুলেট করা সহজ এবং সম্ভাব্য ব্যর্থ লেনদেন পাঠানোর কারণে গ্যাস ফি অপ্রয়োজনীয় ক্ষতি এড়ানো। আমরা এই অধ্যায়ের উদাহরণ কোডটি ব্যবহার করেছি ভিটালিক বুটারিনের ওয়ালেটে অর্থ স্থানান্তর করতে এবং ভিটালিক বুটারিনের ওয়ালেটে আমাদের কাছে অর্থ স্থানান্তর করতে কলটি সিমুলেট করতে। অবশ্যই এর জন্য আরও অনেকগুলি ব্যবহার রয়েছে।eth_call
আপনার কল্পনা ব্যবহার করুন, আপনি কি ব্যবহার করবেeth_call
কিসের জন্য?
আমরা জানি যে ইটিএইচ এবং বিটিসির মতো টোকেনগুলি হোমোজেনাইজড টোকেন এবং আপনার ওয়ালেটের টোকেনটি আমার ওয়ালেটের টোকেন থেকে আলাদা নয়। তবে পৃথিবীতে এমন অনেক জিনিস রয়েছে যা হোমোজেন নয়, যেমন রিয়েল এস্টেট, প্রাচীন জিনিস, ভার্চুয়াল আর্টওয়ার্ক ইত্যাদি। এগুলিকে বিমূর্তভাবে হোমোজেন টোকেন দ্বারা উপস্থাপন করা যায় না। অতএব, অ-হোমোজেন বস্তুগুলিকে বিমূর্ত করার জন্য ইআরসি 721 স্ট্যান্ডার্ড রয়েছে এবং এনএফটি এবং সম্পর্কিত ধারণাগুলি রয়েছে। সুতরাং ইথেরিয়ামে প্রয়োগ করা অনেক স্মার্ট কন্ট্রাক্টের মধ্যে, আমরা কীভাবে সনাক্ত করব কোন স্মার্ট কন্ট্রাক্টগুলি ERC721 স্ট্যান্ডার্ড স্মার্ট কন্ট্রাক্ট?
ERC721 সনাক্ত করতে, প্রথমে ERC165 স্ট্যান্ডার্ড জানা গুরুত্বপূর্ণ।
ERC165 স্ট্যান্ডার্ডের সাহায্যে একটি স্মার্ট কন্ট্রাক্ট অন্য কন্ট্রাক্টগুলির জন্য এটি সমর্থন করে এমন ইন্টারফেসগুলিকে ঘোষণা করতে পারে। একটি ERC165 ইন্টারফেস কন্ট্রাক্টের কেবলমাত্র একটি ফাংশন রয়েছেঃsupportsInterface(bytes4 interfaceId)
প্যারামিটারinterfaceId
is the interface Id to be queried. যদি চুক্তিটি interfaceId বাস্তবায়ন করে তবে এটি একটি বুলিয়ান সত্য মান প্রদান করে, অন্যথায় এটি একটি মিথ্যা মান প্রদান করে।
এখানে আমরা কিভাবে এই সম্পর্কে কথা বলতে যাচ্ছিinterfaceId
নির্দিষ্টভাবে গণনা করা হয় এবং কোড করা হয়।
ERC165 স্ট্যান্ডার্ডএকটি উদাহরণ দেখায়ঃ
pragma solidity ^0.4.20;
interface Solidity101 {
function hello() external pure;
function world(int) external pure;
}
contract Selector {
function calculateSelector() public pure returns (bytes4) {
Solidity101 i;
return i.hello.selector ^ i.world.selector;
}
}
ইন্টারফেসের ফাংশন স্বাক্ষরের জন্য (একটি ফাংশন নাম এবং প্যারামিটার প্রকারের একটি তালিকা সমন্বিত) একটি অসামঞ্জস্য অপারেশন সম্পাদন করার জন্য, ERC165 ইন্টারফেস চুক্তির জন্য যেখানে চুক্তিতে শুধুমাত্র একটি ফাংশন রয়েছেঃ
pragma solidity ^0.4.20;
interface ERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
এই ইন্টারফেসের জন্য ইন্টারফেস সনাক্তকারী 0x01ffc9a7। আপনি এটি বাইটস 4 ((keccak256 ((
supportsInterface ((bytes4) ) চালিয়ে গণনা করতে পারেন); অথবা উপরে নির্বাচক চুক্তি ব্যবহার করে।
সরাসরি ফাংশন স্বাক্ষর গণনা করুন এবং তার প্রথম 4 বাইট নিতেinterfaceId
.
function main() {
var ret = Encode("keccak256", "string", "hex", "supportsInterface(bytes4)")
Log("supportsInterface(bytes4) interfaceId:", "0x" + ret.slice(0, 8))
}
ডিবাগ টুল এ পরীক্ষা চালানো যাবেঃ
2023-06-13 14:53:35 Info supportsInterface(bytes4) interfaceId: 0x01ffc9a7
এটি দেখা যায় যে গণনা করা ফলাফলগুলি বর্ণনাটির সাথে সামঞ্জস্যপূর্ণERC165 স্ট্যান্ডার্ড document.
এরপরে আসুন ERC721 চুক্তি মানের ইন্টারফেস সংজ্ঞাটি দেখুনঃ
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);
}
আমরা যদি স্মার্ট কন্ট্রাক্টটি ERC721 কন্ট্রাক্ট কিনা তা নির্ধারণ করতে চাই, তাহলে প্রথমে আমাদের জানতে হবেinterfaceId
ERC721 চুক্তির আগে আমরা ব্যবহার করার চেষ্টা করতে পারেনsupportsInterface(bytes4 interfaceId)
পূর্ববর্তী কোর্সে আমরা ERC165 স্ট্যান্ডার্ডের কিছু ধারণার সাথে পরিচিত হয়েছি এবংinterfaceId
, এবং আমরা সরাসরি গণনা করতে কোড লিখুনঃ
function calcSelector(arrSelector) {
var ret = null
if (Array.isArray(arrSelector)) {
if (arrSelector.length == 1) {
ret = Encode("keccak256", "string", "hex", arrSelector[0])
} else if (arrSelector.length == 0) {
throw "Error: the number of elements in the array is 0"
} else {
var viewEncodeData = null
for (var i = 0; i < arrSelector.length; i++) {
if (i == 0) {
ret = new Uint8Array(Encode("keccak256", "string", "raw", arrSelector[i]))
} else {
viewData = new Uint8Array(Encode("keccak256", "string", "raw", arrSelector[i]))
if (viewData.length != ret.length) {
throw "Error: TypeArray view length is different"
}
for (var index = 0; index < ret.length; index++) {
ret[index] ^= viewData[index]
}
}
}
ret = Encode("raw", "raw", "hex", ret.buffer)
}
} else {
throw "Error: The parameter requires an array type."
}
return "0x" + ret.slice(0, 8)
}
function main() {
// supportsInterface(bytes4): 0x01ffc9a7
// var ret = calcSelector(["supportsInterface(bytes4)"])
// ERC721Metadata: 0x5b5e139f
/*
var arrSelector = [
"name()",
"symbol()",
"tokenURI(uint256)"
]
var ret = calcSelector(arrSelector)
*/
// ERC721: 0x80ac58cd
// /*
var arrSelector = [
"balanceOf(address)",
"ownerOf(uint256)",
"safeTransferFrom(address,address,uint256,bytes)",
"safeTransferFrom(address,address,uint256)",
"transferFrom(address,address,uint256)",
"approve(address,uint256)",
"setApprovalForAll(address,bool)",
"getApproved(uint256)",
"isApprovedForAll(address,address)",
]
var ret = calcSelector(arrSelector)
// */
Log(ret)
}
কোডটি ব্যবহার করেEncode()
ফাংশন স্বাক্ষর হিসাবের জন্য ফাংশনkeccak256
অ্যালগরিদম), এবং উপরের কোড উদাহরণে গণনার জন্য, আউটপুট প্যারামিটার নির্দিষ্টEncode()
হিসাবে ফাংশন"raw"
, ফাংশন রিটার্ন করেArrayBuffer
প্রকারJavaScript
ভাষা।
একটি সম্পাদন করতে^
(আইসো-অথবা) অপারেশন দুইArrayBuffer
বস্তুর, আপনি একটি তৈরি করতে হবেTypedArray
উপর ভিত্তি করে মতামতArrayBuffer
অবজেক্ট, তারপর এটির মধ্যে থাকা তথ্যের মাধ্যমে পুনরাবৃত্তি করুন এবং একের পর এক আইসো-অথবা অপারেশনটি সম্পাদন করুন।
ডিবাগিং টুল চালানঃ
2023-06-13 15:04:09 Info 0x80ac58cd
এটি দেখা যায় যে গণনা করা ফলাফলগুলিইআইপি-৭২১.
pragma solidity ^0.4.20;
/// @title ERC-721 Non-Fungible Token Standard/// @dev See https://eips.ethereum.org/EIPS/eip-721/// Note: the ERC-165 identifier for this interface is 0x80ac58cd.interface ERC721 /* is ERC165 */ {
/// @dev This emits when ownership of any NFT changes by any mechanism.
/// This event emits when NFTs are created (`from` == 0) and destroyed
/// (`to` == 0). Exception: during contract creation, any number of NFTs
/// may be created and assigned without emitting Transfer. At the time of
/// any transfer, the approved address for that NFT (if any) is reset to none.
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
...
ERC721 ইন্টারফেস আইডি দিয়ে, আমরা নির্ধারণ করতে পারি যে একটি চুক্তি একটি ERC721 স্ট্যান্ডার্ড চুক্তি কিনা। আমরা ব্যবহার করিBAYC
ERC721 অনুসরণ করে একটি চুক্তি যা পরীক্ষা করতে, প্রথম আমরা ABI নিবন্ধন করতে হবে, এবং যেহেতু আমরা শুধুমাত্র নিম্নলিখিত তিনটি পদ্ধতি কল, আমরা এই তিনটি পদ্ধতি নিবন্ধন করতে পারেনঃ
নির্দিষ্ট কোডগুলি নিম্নরূপঃ
function main() {
// Contract address for ERC721, BAYC is used here
var testContractAddress = "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d"
var testABI = `[{
"inputs": [{
"internalType": "bytes4",
"name": "interfaceId",
"type": "bytes4"
}],
"name": "supportsInterface",
"outputs": [{
"internalType": "bool",
"name": "",
"type": "bool"
}],
"stateMutability": "view",
"type": "function"
}, {
"inputs": [],
"name": "symbol",
"outputs": [{
"internalType": "string",
"name": "",
"type": "string"
}],
"stateMutability": "view",
"type": "function"
}, {
"inputs": [],
"name": "name",
"outputs": [{
"internalType": "string",
"name": "",
"type": "string"
}],
"stateMutability": "view",
"type": "function"
}]`
// ERC721 Interface Id, calculated in the previous course
var interfaceId = "0x80ac58cd"
// Register ABI
exchange.IO("abi", testContractAddress, testABI)
// Call the supportsInterface method
var isErc721 = exchange.IO("api", testContractAddress, "supportsInterface", interfaceId)
// Output Information
Log("Contract address:", testContractAddress)
Log("Contract name:", exchange.IO("api", testContractAddress, "name"))
Log("Contract code:", exchange.IO("api", testContractAddress, "symbol"))
Log("Whether the contract is ERC721 standard:", isErc721)
}
ডিবাগিং টুল দিয়ে পরীক্ষা চালানো যেতে পারে:
2023-06-13 16:32:57 Info Whether the contract is ERC721 standard: true
2023-06-13 16:32:57 Info Contract code: BAYC
2023-06-13 16:32:57 Info