Solidity

呼叫 Solidity 函式並為其提供比定義接受的參數更多的參數?

  • March 1, 2022

我正在關注此頁面上的教程,尤其是這部分程式碼

// SPDX-License-Identifier: MIT
   pragma solidity 0.8.3;

   import "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol";
   import "@openzeppelin/contracts/utils/Counters.sol";

   contract AisthisiToken is ERC721PresetMinterPauserAutoId {
   using Counters for Counters.Counter;
   Counters.Counter private _tokenIds;

   mapping (uint => uint) public tokenLockedFromTimestamp;
   mapping (uint => bytes32) public tokenUnlockCodeHashes;
   mapping (uint => bool) public tokenUnlocked;

   event TokenUnlocked(uint tokenId, address unlockerAddress);

   constructor() ERC721PresetMinterPauserAutoId("AisthisiToken", "AIS", "https://aisthisi.art/metadata/") {}

   function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override {
       require(tokenLockedFromTimestamp[tokenId] > block.timestamp || tokenUnlocked[tokenId], "AishtisiToken: Token locked");
       super._beforeTokenTransfer(from, to, tokenId);
   }

   function unlockToken(bytes32 unlockHash, uint256 tokenId) public {
       require(msg.sender == ownerOf(tokenId), "AishtisiToken: Only the Owner can unlock the Token"); //not 100% sure about that one yet
       require(keccak256(abi.encode(unlockHash)) == tokenUnlockCodeHashes[tokenId], "AishtisiToken: Unlock Code Incorrect");
       tokenUnlocked[tokenId] = true;
       emit TokenUnlocked(tokenId, msg.sender);
   }

   /**
   * This one is the mint function that sets the unlock code, then calls the parent mint
   */
   function mint(address to, uint lockedFromTimestamp, bytes32 unlockHash) public {
       tokenLockedFromTimestamp[_tokenIds.current()] = lockedFromTimestamp;
       tokenUnlockCodeHashes[_tokenIds.current()] = unlockHash;
       _tokenIds.increment();
       super.mint(to);
   }

   function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
   return string(abi.encodePacked(super.tokenURI(tokenId),".json"));
   }
}

我可以使用 Truffle 部署它,一切都很好。

現在當我想在 Truffle 控制台上呼叫這個函式時

function unlockToken(bytes32 unlockHash, uint256 tokenId) public {
   require(msg.sender == ownerOf(tokenId), "AishtisiToken: Only the Owner can unlock the Token"); //not 100% sure about that one yet
   require(keccak256(abi.encode(unlockHash)) == tokenUnlockCodeHashes[tokenId], "AishtisiToken: Unlock Code Incorrect");
   tokenUnlocked[tokenId] = true;
   emit TokenUnlocked(tokenId, msg.sender);
}

然後我需要在 Truffle 控制台上做這些

let token = await AisthisiToken.deployed()

let txMint = await token.mint(accounts[1], Math.round(Date.now()/1000)+3, web3.utils.sha3(web3.utils.sha3('mySecretHash')))

let txUnlock = await token.unlockToken(web3.utils.sha3('mySecretHash'), 0, {from: accounts[1]})

我的問題是function unlockToken只需要 2 個參數bytes32 unlockHashuint256 tokenId. 為什麼我需要用 3 個參數呼叫該函式(web3.utils.sha3('mySecretHash'), 0, {from: accounts[1]})

如果我只使用 2 個參數呼叫該函式let txUnlock = await token.unlockToken(web3.utils.sha3('mySecretHash'), 0),那麼它會認為我正在呼叫該函式accounts[0],因此將返回錯誤,因為只accounts[1]允許解鎖令牌。因此,看起來我必須提供第三個參數來明確指定account[1]執行該函式的那個人。但是第三個參數去哪裡了,因為它沒有在函式中定義?

2 個參數返回錯誤

3個參數OK

另外,solidity 中的函式可以接受比預期更多的參數嗎?我嘗試了一個簡單的測試並在 Remix IDE 上執行它

contract Simple {
   uint public sum;
   function taker(uint _a, uint _b) public returns (uint) {
       sum = _a + _b;
       return sum;
   }
}

將其部署在 Remix 上並進行測試

在此處輸入圖像描述

它會返回我的錯誤

transact to Simple.taker errored: Error encoding arguments: Error: types/values length mismatch (count={"types":2,"values":3}, value={"types":["uint256","uint256"],"values":["1","2","3"]}, code=INVALID_ARGUMENT, version=abi/5.5.0)

那麼,看起來我們不能為函式提供比預期更多的參數?

token對像是契約的包裝器(或外觀),而不是契約本身。如果您閱讀truffle 文件,您會注意到以下段落:

我們將一個對像作為第三個參數傳遞給 sendCoin。請注意,我們的 Solidity 合約中的 sendCoin 函式沒有第三個參數。您在上面看到的是一個特殊對象,它始終可以作為最後一個參數傳遞給一個函式,該函式允許您編輯有關事務的特定詳細資訊(“事務參數”)。在這裡,我們設置了發件人地址,確保此交易來自賬戶

$$ 0 $$. 您可以設置的交易參數對應於乙太坊交易中的欄位:from,to,gas,gasPrice,value,data,nonce

這基本上意味著 Truffle 正在創建一個幫助對象,使您可以方便地呼叫合約的方法。您可能已經知道,每個乙太坊合約方法都需要在錢包(地址/公鑰)的上下文中呼叫,因此 Truffle 提供的第三個參數可以讓您確定方法呼叫的上下文。

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