وسائل لوڈ ہو رہے ہیں... لوڈنگ...

ایف ایم زیڈ کا استعمال کرتے ہوئے ایتھریم پر مبنی ویب 3 ڈویلپمنٹ آسانی سے شروع کریں

مصنف:FMZ~Lydia, تخلیق: 2023-06-25 09:17:53, تازہ کاری: 2024-11-11 22:34:49

0000000000164f2434262e1cc،" ٹرانزیکشن ہیش: 0x6aa8d80daf42f442591e7530e31323d05e1d6dd9f9f9b9c102e157d89810c048، پتہ: 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2، blockHash: 0xcd3d567c9bd02a4549b1de0dc638ab5523e847c3c156b096424f56c633000fd9 }، { پتہ: 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2، blockHash: 0xcd3d567c9bd02a4549b1de0dc638ab5523e847c3c156b096424f56c633000fd9، بلاک نمبر: 0x109b1cd، logIndex: 0xde، حذف: غلط، موضوعات: 0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65، 0x00000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b، ڈیٹا: 0x0000000000000000000000000000000000000000000000000164f2434262e1cc، ٹرانزیکشن ہیش: 0x6aa8d80daf42f442591e7530e31323d05e1d6dd9f9f9b9c102e157d89810c048، ٹرانزیکشن انڈیکس: 0x91 }]


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/:

img

ایف ایم زیڈ ڈیبگنگ ٹول میں چلنے والے ٹیسٹ کوڈ کے نتائج:

img

میں اعداد و شمارfrom, toکھیتوں کو بھی تلاش کرنے کے وقت کی ضروریات پر منحصر ہے تجزیہ کیا جا سکتا ہے، مثال کے طور پر:

function main() {
    var from = "0x00000000000000000000000012b791bb27b3a4ee958b5a435fea7d49ec076e9c"
    var address = "0x" + exchange.IO("encodePacked", "address", from)
    Log("address:", address)
}

چلانے کے نتائج:

ایڈریس: 0x12b791bb27b3a4ee958b5a435fea7d49ec076e9c

معاہدے کے واقعات کو سننا

کے بعدڈیبگنگ کا آلہکوڈ کو صرف مختصر وقت کے لئے ٹیسٹ کر سکتے ہیں اور کوڈ کے عمل کو مکمل کرنے کے بعد ہی مواد کو آؤٹ پٹ کرسکتے ہیں ، یہ لاگ کو حقیقی وقت میں ظاہر اور آؤٹ پٹ نہیں کرسکتا ہے۔ اس سیکشن میں ، ہم ٹیسٹ کرنے کے لئے براہ راست تجارت بنانے کے لئے ایف ایم زیڈ کوانٹ ٹریڈنگ پلیٹ فارم کا استعمال کرتے ہیں۔

یہاں ہم ایتھریم مین نیٹ کا استعمال کرتے ہیں، اور ہم کو سننے کےTransfer(address,address,uint256)واقعہUSDTcryptocurrency معاہدہ. گزشتہ سبق میں ہم نے کیا سیکھا کی بنیاد پر، ہم ڈیزائن اور مسلسل ایک مخصوص سمارٹ معاہدے کے واقعات کو سننے کی ایک مثال لکھا:

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])
    }
}
*/

براہ راست تجارت پر چل رہا ہے:

img

عملدرآمد کے نتائج کے لئے ، کوڈ میں توثیق کا ایک سیکشن (TODO: ٹیسٹ) بھی لکھا جاتا ہے۔ ایک سادہ توثیق کے بعد یہ دیکھا جاسکتا ہے کہTransferUSDT معاہدے کے واقعے کی مسلسل نگرانی کی جاتی ہے اور اعداد و شمار ریکارڈ کیے جاتے ہیں اور ان اعداد و شمار اور ایک بار میں حاصل ہونے والے واقعے کے اعداد و شمار کے درمیان موازنہ سے یہ مشاہدہ کیا جاسکتا ہے کہ اعداد و شمار اس کے مطابق ہیں:

img

واقعہ فلٹرنگ

پچھلے سبق کی بنیاد پرListening to contract events، ہم اس پر توسیع کرتے ہیں جس میں سننے کے عمل میں فلٹرز شامل کیے جاتے ہیں تاکہ مخصوص پتوں سے اور ان سے منتقلی کی سماعت کی جاسکے۔ جب ایک سمارٹ معاہدہ لاگ بناتا ہے (یعنی کوئی واقعہ جاری کرتا ہے) ، لاگ ڈیٹاtopicsمعلومات کے 4 ٹکڑے ٹکڑے تک پر مشتمل ہے. تو ہم کے ساتھ ایک فلٹر اصول ڈیزائن[[A1, A2, ...An], null, [C1], D]مثال کے طور پر.

  1. [A1, A2, ...An]پوزیشن پر اعداد و شمار کے مطابق ہےtopics[0].
  2. Nullپوزیشن پر اعداد و شمار کے مطابق ہےtopics[1].
  3. [C1]پوزیشن پر اعداد و شمار سے مطابقت رکھتا ہےtopics[2].
  4. 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)
    }
}

مندرجہ بالا کوڈ براہ راست تجارت میں چل رہا ہے:

img

اس سبق میں، ہم ایک واقعہ فلٹر ڈیزائن کرنے کا طریقہ متعارف کرایا. اور اس کے لئے سننے کے لئے استعمال کیا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.01ETH کو ایک قدر میں تبدیل کیا گیا10000000000000000میںweiسے زیادہ ہو جائے گاNumber.MAX_SAFE_INTEGER``, so a safer conversion for such cases is:BigInt ((10000000000000000).toString ((16) ``.

سمولیشن کالز

ٹرانزیکشنز کو انجام دینے اورWriteایتھرئم پر سمارٹ معاہدوں کا طریقہ کار ایک خاص مقدار میں گیس کی لاگت کرتا ہے اور بعض اوقات یہ ناکام ہوجاتا ہے۔ یہ جاننا ضروری ہے کہ کون سے لین دین کو بھیجنے اور ان کو کال کرنے سے پہلے ناکام ہونے کا امکان ہے۔ ٹیسٹنگ کے لئے ایتھرئم پر نقلی کالز موجود ہیں۔

eth_call

ایتھریم کا آر پی سی طریقہ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ایک مثال کے طور پر تخروپن کالوں کے لئے، اور مندرجہ ذیل ٹیسٹ ماحول اہم ایتھریم نیٹ ورک ہے.

سمولیشن کال منظور

ہم سب اس سے واقف ہیںapproveERC20 معاہدوں کے لئے طریقہ کار ، اور ہم نے اسے پچھلے کورسز میں مشق کی ہے۔ چونکہ 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 ٹوکن منتقل کرنے کی اجازت دیتا ہے، تو چلو 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")

    // 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 معاہدوں کی شناخت کریں

ہم جانتے ہیں کہ ای ٹی ایچ اور بی ٹی سی جیسے ٹوکن ہوموجینیزڈ ٹوکن ہیں ، اور آپ کے بٹوے میں موجود ٹوکن میرے بٹوے میں موجود ٹوکن سے مختلف نہیں ہے۔ لیکن دنیا میں بہت سی چیزیں ایسی ہیں جو یکساں نہیں ہیں ، جیسے رئیل اسٹیٹ ، نوادرات ، ورچوئل آرٹ ورک وغیرہ۔ ان کو تجریدی طور پر یکساں ٹوکن کے ذریعہ پیش نہیں کیا جاسکتا ہے۔ لہذا ، غیر یکساں اشیاء کو تجریدی بنانے کے لئے ERC721 معیار ہے ، اور NFT اور اس سے متعلقہ تصورات موجود ہیں۔ تو ایتھریم پر تعینات بہت سے سمارٹ معاہدوں میں سے، ہم کس طرح شناخت کرتے ہیں کہ کون سے سمارٹ معاہدے ERC721 معیاری سمارٹ معاہدے ہیں؟

ERC721 کی نشاندہی کرنے کے لئے، پہلے ERC165 معیار کو جاننا ضروری ہے.

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

اب آئیے 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 کنٹریکٹ ہے، تو پہلے ہمیں جاننے کی ضرورت ہےinterfaceIdERC721 معاہدے سے پہلے ہم استعمال کرنے کی کوشش کر سکتے ہیں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

متعلقہ

مزید