呼叫 Solidity 函式並為其提供比定義接受的參數更多的參數?
我正在關注此頁面上的教程,尤其是這部分程式碼
// 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 unlockHash
和uint256 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]
執行該函式的那個人。但是第三個參數去哪裡了,因為它沒有在函式中定義?另外,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 提供的第三個參數可以讓您確定方法呼叫的上下文。