Solidity

如何監聽事件以對數組進行排序

  • July 29, 2022

我閱讀了這篇關於使用事件偵聽器對鏈外數組進行排序的文章,但是當在打字稿中呼叫數組時,我的數組似乎沒有及時排序。

這是我的契約:

pragma solidity 0.8.4;
pragma experimental ABIEncoderV2;


contract Test  {


   uint256[] unsortedArr;

   uint256[] sortedArr;

   event sort(uint256[]);


   function addElement(uint256 element) public {
       unsortedArr.push(element);
   }

   function sortOffChain() public  returns (uint[] memory)
   {
   /*On the backend, the algorithm would look something like this -

   *event listener listening for sort()
   *calls sort function in typescript upon getting triggered
   *calls getSortedData() function with returned value of sort()
*/
       emit sort(unsortedArr);
       // I want sortedArr below to be sorted by the time the return is called
       return sortedArr;
   }
   
   function getSortedData(uint256[] memory sortedData) public 
   {
       sortedArr = sortedData;
   }


// for typescript test
function getUnsortedArr() public view returns (uint256[] memory) {
       return unsortedArr;
   }

function getSortedArr() public view returns (uint256[] memory) {
   return sortedArr;
}
}

這是 TypeScript 中事件監聽器的樣子:

async function main() {
;

// deploying
 const Test = await hre.ethers.getContractFactory("Test");
 const test = await Test.deploy();
 await test.deployed();
 console.log("Test deployed to", test.address);
// add elements to array
 await test.addElement(5);
 await test.addElement(3);
 await test.addElement(7);
 await test.addElement(2);
 await test.addElement(1);
 await test.addElement(9);
// event listener
const OffChainResult = await test.sortOffChain();
test.on("sort", (arr: []) => {
 let arrayForSort = [...arr];
 const sortedArr = arrayForSort.sort((n1: number,n2 : number) => n1 - n2);
 console.log("array sorted");
 test.getSortedData(sortedArr);
 console.log("getSortedData completed");
}
);
console.log("output of getSortedData:");
console.log(OffChainResult);

這是我執行腳本時終端中出現的內容:

Test deployed to 0x5FbDB2315678afecb367f032d93F642f64180aa3
output of getSortedData:
{
 hash: '0x40eeca2775e29300e51f3a067c99195f0cf33ee0aac73eaeaf05d826b41c3d4c',
 type: 2,
 accessList: [],
 blockHash: '0xd952eb1b086de3b1ee213fff01b464925670bc6d7e515ac3f7dad3b732471857',
 blockNumber: 8,
 transactionIndex: 0,
 confirmations: 1,
 from: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
 gasPrice: BigNumber { value: "1346048670" },
 maxPriorityFeePerGas: BigNumber { value: "1000000000" },
 maxFeePerGas: BigNumber { value: "1692097340" },
 gasLimit: BigNumber { value: "29021272" },
 to: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
 value: BigNumber { value: "0" },
 nonce: 7,
 data: '0xb8dbac2c',
 r: '0x621282eec4ac159b052250faa62aa5e954510ba91e841d3477bf0228ecf952d9',
 s: '0x7d36e86d604b58006dd918efc52babd3f3e61dd9f80e36fa2e3e8a9a03fe5298',
 v: 1,
 creates: null,
 chainId: 31337,
 wait: [Function (anonymous)]
}
array sorted
getSortedData completed

有兩個問題:(1)在事件偵聽器有機會對數組進行排序並設置為正確的值之前,getSortedData()它被呼叫返回一個值;(2)即使數組沒有排序,也應該返回一個空數組,而不是 OffChain.sortOffChain()sortedArrsortOffChain()`

這只是我如何製作事件監聽器的問題嗎?我需要將程式碼行以不同的順序排列嗎?另外,控制台輸出的東西是什麼OffChainResult

我還聽說無法驗證要提供給智能合約的排序數組。我如何確保它是?

我必須仔細閱讀您的程式碼,並且我也進行了測試,坦率地說,我從這篇文章中學到了很多東西。因此,首先,您的契約有點問題。既然你想趕上事件,你不需要返回任何東西。即使你這樣做了,你也需要view在你的函式中使用。我修改了契約,它看起來像這樣:

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

contract Sort {
   uint256[] unsortedArr;
   uint256[] sortedArr;

   event sort(uint256[]);

   function addElement(uint256 element) public {
       unsortedArr.push(element);
   }

   function sortOffChain() public {
       emit sort(unsortedArr);
   }

   function getSortedData(uint256[] memory sortedData) public {
       sortedArr = sortedData;
   }

   // for typescript test
   function getUnsortedArr() public view returns (uint256[] memory) {
       return unsortedArr;
   }

   function getSortedArr() public view returns (uint256[] memory) {
       return sortedArr;
   }
}

繼續前進,您需要更改方法以更改擷取事件的過程。我可能以不同的方式編寫程式碼。你可以在你的最後解決這個問題。它會是這樣的:

 function get1DArray(arr: any) {
   return arr.join().split(",");
 }

 it("Event get", async () => {
   let data = await sort.sortOffChain();
   let receipt = await data.wait();
   let finalEvent = receipt.events?.find((event) => event.event === "sort");
   let unsortedArray = get1DArray(finalEvent?.args);
   console.log("Unsorted Array: ", unsortedArray);

   const sortedArray = unsortedArray.sort((n1: number, n2: number) => n1 - n2);
   console.log("Sorted Array: ", sortedArray);

   console.log(
     "Previous Sorted array in contract: ",
     await sort.getSortedArr()
   );

   await sort.getSortedData(sortedArray);
   console.log(
     "New Sorted array in contract: ",
     (await sort.getSortedArr()).toString()
   );
 });

最好有這個函式get1DArray,因為它args返回一個數組的數組。您將獲得一個使用此鏈下排序的排序數組。

引用自:https://ethereum.stackexchange.com/questions/132605