I am following the tutorial on this page, especially this part of code
// 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"));
}
}
I can deploy it using Truffle and everything is fine.
Now when I want to call this function on Truffle console
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);
}
Then I need to do these on Truffle console
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]})
My question is function unlockToken
only expects 2 arguments bytes32 unlockHash
and uint256 tokenId
.
Why do I need to call that function with 3 arguments (web3.utils.sha3('mySecretHash'), 0, {from: accounts[1]})
?
If I call that function using 2 arguments only like let txUnlock = await token.unlockToken(web3.utils.sha3('mySecretHash'), 0)
, then it will think I am calling that function as accounts[0]
and thus will return error, since only accounts[1]
is allowed to unlock the Token. So, it looks like I must provide the 3rd argument to explicitly specify that account[1]
is the one who runs that function. But where does the 3rd argument go, since it is not defined in the function?
Also, Can function in solidity accept more parameters than what it expects? I tried with a simple test and run it on Remix IDE
contract Simple {
uint public sum;
function taker(uint _a, uint _b) public returns (uint) {
sum = _a + _b;
return sum;
}
}
Deploy it on Remix and test it
It will return me error
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)
So, it looks like we can't feed a function with more arguments than what it expects ?