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
فیلڈ ایک صف کا ڈھانچہ ہے جو ایونٹ کی وضاحت کے لئے استعمال ہوتا ہے۔ یہ مخصوص کیا گیا ہے کہ اس کی (آرری) لمبائی 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
cryptocurrency معاہدہ. گزشتہ سبق میں ہم نے کیا سیکھا کی بنیاد پر، ہم ڈیزائن اور مسلسل ایک مخصوص سمارٹ معاہدے کے واقعات کو سننے کی ایک مثال لکھا:
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
USDT معاہدے کے واقعے کی مسلسل نگرانی کی جاتی ہے اور اعداد و شمار ریکارڈ کیے جاتے ہیں اور ان اعداد و شمار اور ایک بار میں حاصل ہونے والے واقعے کے اعداد و شمار کے درمیان موازنہ سے یہ مشاہدہ کیا جاسکتا ہے کہ اعداد و شمار اس کے مطابق ہیں:
پچھلے سبق کی بنیاد پر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
آپ Binance Exchange گرم بٹوے سے منسلک لین دین کر سکتے ہیں. آپ کو دلچسپی رکھتے ہیں کسی بھی ایونٹ کو سننے کے لئے اس نمونہ پروگرام میں ترمیم اور توسیع, نئے لین دین کیا ہیں کو دیکھنے کے لئےsmart money
کیا کیا ہے، کیا نئی اشیاءNFT
تاجروں نے جلدی کی ہے، وغیرہ.
ایتھرئم سے متعلق بہت سے حسابات میں ایسی اقدار ہیں جو زیادہ سے زیادہ محفوظ انٹیجر سے زیادہ ہیںJavaScript
زبان۔ لہذا ، ایف ایم زیڈ کوانٹ ٹریڈنگ پلیٹ فارم پر بڑے اقدار کو سنبھالنے کے لئے کچھ طریقوں کی ضرورت ہے ، جن کا ہم نے پچھلے کورسز میں خاص طور پر استعمال کیا ہے اور تفصیل سے احاطہ نہیں کیا ہے۔ اس حصے میں اس پہلو پر تفصیل سے تبادلہ خیال کیا جائے گا۔
میں مقرر زیادہ سے زیادہ محفوظ عدد پرنٹ کریں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
.
FMZ کوانٹ ٹریڈنگ پلیٹ فارم میں، ہم پلیٹ فارم استعمال کرتے ہیںBigInt
ان بہت بڑے عددی اعداد و شمار کی نمائندگی کرنے کے لئے اعتراض. کنسٹرکٹر استعمال کریںBigInt()
تعمیر کرنے کے لئےBigInt
اعتراض. آپ تعمیر کر سکتے ہیںBigInt
عددی، hexadecimal عددی حلقوں کے طور پر پیرامیٹرز کا استعمال کرتے ہوئے اشیاء.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
ویب 3 عملی ترقی میں، یہ اکثر کچھ زنجیروں ہیکساڈیسمل ڈیٹا کے ساتھ نمٹنے کے لئے ضروری ہے.
ہم نے اکثر اپنے پچھلے کورسز میں اس کا سامنا کیا ہے، مثال کے طور پر،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:
BigInt ((10000000000000000).toString ((16) ``.
ٹرانزیکشنز کو انجام دینے اورWrite
ایتھرئم پر سمارٹ معاہدوں کا طریقہ کار ایک خاص مقدار میں گیس کی لاگت کرتا ہے اور بعض اوقات یہ ناکام ہوجاتا ہے۔ یہ جاننا ضروری ہے کہ کون سے لین دین کو بھیجنے اور ان کو کال کرنے سے پہلے ناکام ہونے کا امکان ہے۔ ٹیسٹنگ کے لئے ایتھرئم پر نقلی کالز موجود ہیں۔
ایتھریمeth_call
: یہ ایک ٹرانزیکشن کی نقالی کرسکتا ہے اور ممکنہ ٹرانزیکشن کا نتیجہ واپس کرسکتا ہے ، لیکن یہ واقعی بلاکچین پر ٹرانزیکشن کو انجام نہیں دیتا ہے۔
کےeth_call
طریقہ کار میں 2 پیرامیٹرز ہیں، پہلا ایک لغت کا ڈھانچہ ہے،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
آخر میں ایتھریم RPC طریقہ کار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 فراہم کی)
ہم ERC20s سے واقف ہیںtransfer
طریقہ، جس سے آپ کو ایک مخصوص بٹوے کے ایڈریس پر ERC20 ٹوکن منتقل کرنے کی اجازت دیتا ہے، تو
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
}
چونکہ میرے پاس اس ٹیسٹ والیٹ میں ڈی اے آئی ٹوکن نہیں ہیں ، لہذا اسے ڈیبگ ٹول میں چلانے سے غیر متوقع طور پر مندرجہ ذیل غلطی کی اطلاع ملی:
عملدرآمد کی واپسی: ڈائی/ناقص توازن
وٹالک بوٹیرین کے بٹوے کا پتہ چیک کریں:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
، یہ واضح ہے کہ اس بٹوے میں ڈی اے آئی ٹوکن ہیں۔ تو آئیے ہم نقلی کال کی منتقلی کی سمت کو ایڈجسٹ کریں اور وٹالک بوٹیرن سے ہمارے پاس 1000 ڈی اے آئی کی منتقلی کا نقلی کریں۔
کوڈ میں ترمیم کریں، جہاں تبدیلیاں میں نے تبصرے کیا:
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
طریقہ کار کیا ہے؟
ہم جانتے ہیں کہ ای ٹی ایچ اور بی ٹی سی جیسے ٹوکن ہوموجینیزڈ ٹوکن ہیں ، اور آپ کے بٹوے میں موجود ٹوکن میرے بٹوے میں موجود ٹوکن سے مختلف نہیں ہے۔ لیکن دنیا میں بہت سی چیزیں ایسی ہیں جو یکساں نہیں ہیں ، جیسے رئیل اسٹیٹ ، نوادرات ، ورچوئل آرٹ ورک وغیرہ۔ ان کو تجریدی طور پر یکساں ٹوکن کے ذریعہ پیش نہیں کیا جاسکتا ہے۔ لہذا ، غیر یکساں اشیاء کو تجریدی بنانے کے لئے ERC721 معیار ہے ، اور NFT اور اس سے متعلقہ تصورات موجود ہیں۔ تو ایتھریم پر تعینات بہت سے سمارٹ معاہدوں میں سے، ہم کس طرح شناخت کرتے ہیں کہ کون سے سمارٹ معاہدے ERC721 معیاری سمارٹ معاہدے ہیں؟
ERC721 کی نشاندہی کرنے کے لئے، پہلے ERC165 معیار کو جاننا ضروری ہے.
ERC165 معیار کے ساتھ ، ایک سمارٹ معاہدہ دوسرے معاہدوں کی جانچ پڑتال کے ل the انٹرفیس کا اعلان کرسکتا ہے جن کی وہ حمایت کرتا ہے۔ ERC165 انٹرفیس معاہدے کا صرف ایک کام ہے:supportsInterface(bytes4 interfaceId)
، پیرامیٹرinterfaceId
انٹرفیس ID ہے جس سے استفسار کیا جائے گا۔ اگر معاہدہ انٹرفیس ID کو لاگو کرتا ہے تو یہ ایک بولین حقیقی قدر واپس کرتا ہے ، بصورت دیگر یہ ایک غلط قدر واپس کرتا ہے۔
یہاں ہم کس طرح اس کے بارے میں بات کرنے کے لئے جا رہے ہیں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
آبجیکٹ، پھر اس میں ڈیٹا کے ذریعے iterate اور ایک کے بعد ایک iso-or آپریشن انجام دیں.
ڈیبگنگ ٹول میں چلائیں:
2023-06-13 15:04:09 Info 0x80ac58cd
یہ دیکھا جا سکتا ہے کہ حساب نتائج میں بیان کیا ان کے ساتھ ہم آہنگ ہیںeip-721.
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 انٹرفیس ID کے ساتھ، ہم اس بات کا تعین کر سکتے ہیں کہ ایک معاہدہ 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