专家问答
向Solidity社区的专家提问
帖子
17- 专家问答Jun 04, 2024
solidity 语法多久更改一次
我想知道 solidity 语法规则多久更改一次,以及跟进最新更新的最佳时事通讯
- Smart Contract
- Solidity
- Language Grammar
- Solidity Compiler
11 - 专家问答Jan 09, 2024
类似 Remix 的 Anvil 工具
我知道你可以将合约从 Remix 部署到 Anvil. 但是有没有办法与我在 Anvil 中的机器上部署的合约进行交互?这些合约在 Remix 中不可见. 还是有其他像Remix这样的工具可以做到这一点? 经验丰富的开发人员如何与合同互动? 谢谢
- Solidity
11 - 专家问答Nov 07, 2023
Solidity-安装铸造厂时出现问题:SSL 连接超时”
我在尝试使用命令安装Foundry时遇到了一个问题. Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:05:01 --:--:-- 0 curl: (28) SSL connection timeout
- Solidity
11 - 专家问答Oct 23, 2023
在 nonFungiblePositionManager 中调用 “增加流动性” 时出错.
我在调用 n increaseLiquidity onFungiblePositionManager 时测试不及格. decreaseLiquidity按预期运行,但增加流动性失败了. 这是代码: underlyingPositionManager.increaseLiquidity( INonfungiblePositionManager.IncreaseLiquidityParams({ tokenId: loan.tokenId, amount0Desired: amount0, amount1Desired: amount1, amount0Min: 0, amount1Min: 0, deadline: block.timestamp }) 这是测试的铸造厂输出 [12350] 0xC36442b4a4522E871399CD717aBDD847Ab11FE88::increaseLiquidity((512098 [5.12e5], 0, 671529 [6.715e5], 0, 0, 1685033235 [1.685e9])) │ │ ├─ [696] 0xCBCdF9626bC03E24f779434178A73a0B4bad62eD::slot0() [staticcall] │ │ │ └─ ← 0x000000000000000000000000000000000005db000f1598ba8f0e02e024506208000000000000000000000000000000000000000000000000000000000003ec8f000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 │ │ ├─ [3747] 0xCBCdF9626bC03E24f779434178A73a0B4bad62eD::mint(0xC36442b4a4522E871399CD717aBDD847Ab11FE88, 253320, 264600, 0, 0x0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b) │ │ │ └─ ← "EvmError: Revert" │ │ └─ ← "EvmError: Revert" │ └─ ← "EvmError: Revert" └─ ← "EvmError: Revert" Test result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 424.01ms Ran 1 test suites: 0 tests passed, 1 failed, 0 skipped (1 total tests) 有人能告诉我可能是什么问题吗,谢谢.
- Smart Contract
- Solidity
01 - 专家问答foufrix10Jul 31, 2023
Foundry cannot estimate gas price on Arbitrum
Hi, I'm trying to solve this CTF on Arbitrum: https://arbiscan.io/address/0xdF7cdFF0c5e85c974D6377244D9A0CEffA2b7A86#code The problem is okay to solve, but I'm having trouble sending the TX from Foundry to Arbitrum. Here is the code: // SPDX-License-Identifier: MIT pragma solidity 0.8.19; import {Script, console} from "forge-std/Script.sol"; interface Challenge { function solveChallenge(uint256 randomGuess, string memory yourTwitterHandle) external; } contract SolveChallenge is Script { Challenge challenge = Challenge(0xdF7cdFF0c5e85c974D6377244D9A0CEffA2b7A86); function run() external { vm.startBroadcast(vm.envUint("PRIVATE_KEY")); uint256 correctAnswer = uint256(keccak256(abi.encodePacked(msg.sender, block.prevrandao, block.timestamp))) % 100000; challenge.solveChallenge(correctAnswer, "foufrix"); vm.stopBroadcast(); } } I'm launching the script with this command: forge script script/SolveChallenge.s.sol:SolveChallenge --private-key $PRIVATE_KEY --rpc-url $RPC_URL --broadcast --skip-simulation -vvvvv Also tried with --with-gas-price 100000000 --gas-price 100000000 --gas-limit 3000000 The preview runs well, but It failed when trying to send the transaction to Arbitrum: Any idea on how to solve that? I tried different command from foundry that are suppose to manually set gas price but it does not seems to work. Note : could be nice to add the foundry tag :) (as well as hardhat & brownie)
- Smart Contract
- Solidity
01 - 专家问答Jul 10, 2023
如何在 solidity 中反转 keccak256
我需要以下代码的帮助,其中给了我一个参数的 keccak256,需要反转它才能找到解决挑战的参数 contract LessonFive is AFoundryCourseChallenge { error LessonFive__WrongPassword(); bytes32 public constant EXPECTED_BYTES = 0xb68fe43f0d1a0d7aef123722670be50268e15365401c442f8806ef83b612976b; /* CALL THIS FUNCTION! * Use all the help you can on this one! Google, AI, friends, peeranha, ethereum stack exchange, etc. * Hint: It's a very common... * @param password - A string that when you keccak256 it will return the EXPECTED_BYTES! @param yourTwitterHandle - Your twitter handle. Can be a blank string. */ function solveChallenge(string memory password, string memory yourTwitterHandle) external { if (keccak256(abi.encodePacked(password)) == EXPECTED_BYTES) { _updateAndRewardSolver(yourTwitterHandle); } else { revert LessonFive__WrongPassword(); } } } `
- Smart Contract
- Solidity
22 - 专家问答Jun 29, 2023
The Trade functionality in my Solidity Contract is not Working
The Trade functionality in my Solidity Contract is not Working. Giving Error "Unknown error: "Execution reverted with reason: Pancake: TRANSFER_FAILED.". Try increasing your slippage tolerance.". It is Deployed in BSC Testnet. I am adding liquidity through PCS Router from BSCScan. Here is my code and it is under Development/ testing: ''' pragma solidity >=0.8.4 uint256) public balanceOf; mapping (address => mapping(address => uint256)) public Allowance; uint256 private BUY_TAX_RATE = 5; // 1% buy tax uint256 private SELL_TAX_RATE = 10; // 2% sell tax IRouter router; address pair; address[] WhiteListed; address public taxAddress = 0xE89145e7d9a9b6a4BCacb82659b8bE0e0fFC70A0; // Address where the tax amount will be deposited event Transfer(address indexed from, address indexed to, uint256 value); event Burn(address indexed from, uint256 value); event TransferOwnerShip(address indexed from,address indexed to); event Approval(address indexed owner, address indexed spender, uint value); //////////////////////////////////////////////////// constructor(address routerAddress) { IRouter _router = IRouter(routerAddress); address _pair = IFactory(_router.factory()).createPair(address(this), _router.WETH()); //create a pair with BNB router = _router; pair = _pair; balanceOf[msg.sender] = totalSupply; Owner = msg.sender; WhiteListed.push(Owner); } //////////////////////////////////////////////////// modifier onlyOwner { require(msg.sender == Owner, "Only Owner can call this Function"); _; } modifier Whitelisted { bool isWhiteListed = false; for(uint256 i = 0; i weth address[] memory path = new address; path[0] = address(this); path[1] = router.WETH(); Approve(address(router), tokenAmount); // make the swap try router.swapExactTokensForETHSupportingFeeOnTransferTokens( tokenAmount, 0, // accept any amount of ETH path, address(this), block.timestamp ) {} catch { return; } } function addLiquidity(uint256 tokenAmount, uint256 BNBamount) public Whitelisted payable { Approve(address(router), tokenAmount); try router.addLiquidityETH{value: BNBamount}( address(this), tokenAmount, 0, 0, Owner, block.timestamp + 1000 ){} catch {return;} } function WhiteListAddress(address Address_to_be_White_listed) public onlyOwner returns(string memory) { WhiteListed.push(Address_to_be_White_listed); return("Succesfully WhiteListed"); } function CheckWhiteListedAddress(address See_Address_to_be_WhiteListed) public view returns(bool isWhiteListed) { isWhiteListed = false; for(uint256 i = 0; i = value, 'balance too low'); //checks that balance of the address is greater or equal to value of the functiom require(Allowancefrom >= value, 'allowance too low'); uint256 _value = value * (10 ** decimals); balanceOf[to] += _value; //adds the amt of token to the recieve address balanceOf[from] -= _value; //subs the amt of token from the sender address emit Transfer(from, to, _value); //call the event } function transfer(address to, uint256 value) public { require(balanceOf[msg.sender] >= value, "Insufficient balance"); uint256 tax = 0; uint256 _value = value * (10 ** decimals); Approve(address(router), _value); if (msg.sender != address(this) && to == address(this)) { // Sell transaction tax = ( _value * SELL_TAX_RATE) / 100; balanceOf[taxAddress] += tax ; } if (msg.sender == address(this)) { // Buy transaction tax = ( _value * BUY_TAX_RATE) / 100; balanceOf[taxAddress] += tax ; } uint256 tokensToTransfer = _value - tax; balanceOf[msg.sender] -= _value; balanceOf[to] += tokensToTransfer; emit Transfer(msg.sender, to, tokensToTransfer); if (tax >= 0) { emit Transfer(msg.sender, taxAddress, tax); } } function Approve(address spender, uint256 value) public { Allowancemsg.sender = value; emit Approval(msg.sender, spender, value); } function burn(uint256 value) external onlyOwner{ require(balanceOf[msg.sender] >= value, "Insufficient balance"); uint256 _value = value * (10 ** decimals); balanceOf[msg.sender] -= _value; totalSupply -= _value; emit Burn(msg.sender, _value); emit Transfer(msg.sender, address(0), _value); } function TransferOwnership(address _owner) public onlyOwner { emit TransferOwnerShip(Owner, _owner); Owner = _owner; } function RenounceOwner() public onlyOwner { emit TransferOwnerShip(Owner, address(0)); TransferOwnership(address(0)); } } '''
- Smart Contract
- Solidity
02最佳答案 - 专家问答May 27, 2023
Solidity 和 ethers.js 用同一个签名计算出不同的地址
这个脚本: const { ethers } = require('ethers'); async function recoverSigner(address, nonce, deadline, v, r, s) { const domain = { name: "RandomReachDebug5Local", version: "1", chainId: 31337, verifyingContract: "0x8464135c8F25Da09e49BC8782676a84730C318bC", }; const types = { RequestRandomNFT: [ { name: 'minter', type: 'address' }, { name: 'nonce', type: 'uint256' }, { name: 'deadline', type: 'uint256' }, ], }; const value = { minter: address, nonce: nonce, deadline: deadline, }; // Get the digest of the message const digest = ethers.utils._TypedDataEncoder.hash(domain, types, value); const sig = { r: r, s: s, v: v, }; if (sig.v But this solidity contract: // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.18; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol"; contract GetAddressFromSig is ERC721, EIP712 { struct Request { address minter; uint256 nonce; uint256 deadline; } bytes32 public constant REQUEST_TYPEHASH = keccak256("Request(address minter,uint256 nonce,uint256 deadline)"); // Initialize _DOMAIN_SEPARATOR directly with static values bytes32 private immutable _DOMAIN_SEPARATOR = keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes("RandomReachDebug5Local")), // static name keccak256(bytes("1")), // static version 31337, // static chainId 0x8464135c8F25Da09e49BC8782676a84730C318bC // static verifyingContract ) ); constructor(string memory name, string memory symbol) ERC721(name, symbol) EIP712(name, "1") {} function domainSeparator() public view returns (bytes32) { return _DOMAIN_SEPARATOR; } function recoverSigner(Request memory request, uint8 v, bytes32 r, bytes32 s) public view returns (address) { bytes32 digest = keccak256( abi.encodePacked( "\x19\x01", _DOMAIN_SEPARATOR, keccak256( abi.encode( REQUEST_TYPEHASH, request.minter, request.nonce, request.deadline ) ) ) ); // ECDSA.recover returns the address that is associated with the public key // that was used to sign the given data, in this case, the digest. return ECDSA.recover(digest, v, r, s); } } Deployed with this script in hardhat: import { ethers } from "hardhat"; const hre = require("hardhat"); const dotenv = require("dotenv"); dotenv.config(); async function main() { const GetAddressFromSig = await hre.ethers.getContractFactory("GetAddressFromSig"); const gasPrice = await GetAddressFromSig.signer.getGasPrice(); console.log(Current gas price: ${gasPrice}); const estimatedGas = await GetAddressFromSig.signer.estimateGas( GetAddressFromSig.getDeployTransaction("RANDOM NFT 5", "RNFT5"), ); console.log(Estimated gas: ${estimatedGas}); const deploymentPrice = gasPrice.mul(estimatedGas); const deployerBalance = await GetAddressFromSig.signer.getBalance(); console.log(Deployer balance: ${ethers.utils.formatEther(deployerBalance)}); console.log(Deployment price: ${ethers.utils.formatEther(deploymentPrice)}); const getAddressFromSig = await GetAddressFromSig.deploy("RANDOM NFT 5", "RNFT5"); await getAddressFromSig.deployed(); console.log("GetAddressFromSig deployed to:", getAddressFromSig.address); } main() .then(() => process.exit(0)) .catch((error) => { console.error(error); process.exit(1); }); And ran with these commands in the hardhat console: const Token = await ethers.getContractFactory("GetAddressFromSig"); const token = await Token.attach("0x8464135c8F25Da09e49BC8782676a84730C318bC"); const request = { minter: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", nonce: ethers.BigNumber.from("0"), deadline: ethers.BigNumber.from("1685162164") }; const v = 28 const r = "0xe0e4cc2f8b6bac3784f9feb3db4382291631d5f317d08a0b82305e5eb5ffc60a"; const s = "0x0416d521d12e26b8fc1f4bd566d5d67c5dffebe9564fe90db4f12c0a69b63d5e"; const signer = await token.recoverSigner(request, v, r, s); console.log(The signer is: ${signer}); 给出这样的输出:签名者是:0xeb7265f6625eae66403a637c073e63ccf33b8CDC 那么为什么 javascript 会计算 0x1ab26702a8068a247bd33a9555dfef791d2bd68D,而 hardhat 的 solidity 编译器会计算 0xeb7265f6625ea66403a637c073e63ccf33b8CDC?
- Smart Contract
- Solidity
21最佳答案 - 专家问答May 26, 2023
为什么 Solidity 使用私钥生成的地址与 ether.js 生成的地址不同?
我的 solidity 合约中有这个功能: function requestRandomNFT( address minter, uint256 nonce, uint256 deadline, uint8 v, bytes32 r, bytes32 s, uint256 randomUint256 ) external payable { require(block.timestamp { if (window.ethereum && randomReachDebug5Address) { console.log("initContract is running"); // If you use MetaMask // const provider = new ethers.providers.Web3Provider(window.ethereum); // If you use a local node (e.g., Ganache) const provider = new ethers.providers.JsonRpcProvider('http://localhost:8545'); const balance = await provider.getBalance(connectedAddrs); console.log("Balance: ", ethers.utils.formatEther(balance)); const contractInstance = new ethers.Contract(randomReachDebug5Address, RandomReachDebug5Local.abi, provider.getSigner()); console.log(contract is set here: ${contractInstance}); if (!sigData) { setContract(contractInstance); try { const nonce = await contractInstance.nonces(connectedAddrs); console.log("Nonce fetched: ", nonce); const deadline = Math.floor(Date.now() / 1000) + 120; // 2 minutes from now const sig = await signRandomNFTRequest(connectedAddrs, nonce, deadline); setSigData(sig); const randomUint256 = ethers.utils.hexlify(ethers.BigNumber.from(ethers.utils.randomBytes(32))); // generating random uint256 const argsInUseEffect = [connectedAddrs, nonce.toString(), deadline, sig.v, sig.r, sig.s, randomUint256]; console.log("Args in use effect: ", argsInUseEffect); setArgs(argsInUseEffect); } catch (error) { console.error("Error fetching nonce: ", error); setFetchNonceError(error); } } console.log(sig is here: ${sigData}); console.log(args is here: ${args}); } }, [args, connectedAddrs, randomReachDebug5Address, setContract]); useEffect(() => { initializeContract(); }, [initializeContract]); console.log(args outside of use effect ${args}); const { config, prepareError, isPrepareError } = usePrepareContractWrite({ address: randomReachDebug5Address, abi: RandomReachDebug5Local.abi, functionName: 'requestRandomNFT', args: args, value: '10000000000000000', // This is 0.01 Ether represented in Wei gas: 300000n, // Set your desired gas limit here gasPrice: parseGwei('50'), }); console.log(this is config: ${config}); const { data, error, isError, write } = useContractWrite(config || {}); console.log(this is the error ${error} and this is the error bool ${isError}); const { isLoading, isSuccess } = useWaitForTransaction({hash: data?.hash}); const mintNFT = () => { if (sigData) { console.log('Minting...'); write?.(); } else { console.error('sigData is not defined.'); } }; return { mintNFT, isLoading, isSuccess, isError, error, data, write, isPrepareError, prepareError, fetchNonceError }; } So here's the weird thing... When I ran the minting code within a next.js app, I got this in my console for the hardhat node: console.log: below this is signer 0x2d0b2215d4e00807a6982877a9762ef41541ecef below this is aithorizedAccount 0x1ab26702a8068a247bd33a9555dfef791d2bd68d But the private key I used gives me the address 0x1AB26702A8068a247BD33a9555dfEf791d2BD68D when I test it in javascript with ethers.js, but solidity gives me 0x2d0b2215d4e00807a6982877a9762ef41541ecef ??? I used this script with const privateKey = "0x REST OF MY PRIVATE KEY": const ethers = require('ethers'); function getAddressFromPrivateKey(privateKey) { const wallet = new ethers.Wallet(privateKey); return wallet.address; } const privateKey = "0x REST OF MY PRIVATE KEY"; console.log(getAddressFromPrivateKey(privateKey)); // This should log your expected address 这段代码给了我 0x1ab26702a8068a247bd33a9555dfef791d2bd68D,但我的 solidity 代码给了我 0x2d0b2215d4e00807a6982877a9762ef4154ecef. 那没有任何意义. 为什么会发生这种情况?
- Smart Contract
- Solidity
11最佳答案 - 专家问答May 22, 2023
尝试铸造需要 2 个签名的 NFT 并使用 API3 时,我遇到 “验证失败” 错误
我有这份稳固合同: // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.18; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; import "@api3/airnode-protocol/contracts/rrp/requesters/RrpRequesterV0.sol"; contract RandomSurfaceReachT1 is ERC721URIStorage, Ownable, RrpRequesterV0 { event RequestedRandom(bytes32 indexed requestId); event MintedRandomNFT(bytes32 indexed requestId, uint256 response); event MintCostChanged(uint256 newCost); event Withdrawn(address indexed to, uint256 amount); address public airnode; bytes32 public endpointIdUint256; address public sponsorWallet; address public authorizedAccount; uint256 public tokenCounter; uint256 public mintCost = 0.01 ether; uint256 public constant MAX_MINTS_PER_ADDRESS = 3; enum Classifier {FIRST, SECOND, THIRD} mapping(uint256 => Classifier) public tokenIdToClassifier; mapping(bytes32 => bool) public awaitingFulfillment; mapping(bytes32 => address) public requestToMinter; mapping(address => uint256) public minterToMintCount; struct RandomNft { uint256 nonce; address from; } string public firstUri; string public secondUri; string public thirdUri; string private constant ERR_INVALID_SIGNER = "INVALID_SIGNER"; string private constant ERR_REQUEST_ID_UNKNOWN = "Request ID not known"; string private constant ERR_MINT_COST_NOT_MET = "Minting cost not met"; string private constant ERR_MINT_LIMIT_REACHED = "Mint limit reached"; string private constant ERR_VERIFICATION_FAILED = "Verification failed"; constructor(address _airnodeRrp) RrpRequesterV0(_airnodeRrp) ERC721("PRIVATE MINT RANDOM NFT", "PMRNFT") {} function setParameters( address _airnode, bytes32 _endpointIdUint256, address _sponsorWallet, address _authorizedAccount ) external onlyOwner() { airnode = _airnode; endpointIdUint256 = _endpointIdUint256; sponsorWallet = _sponsorWallet; authorizedAccount = _authorizedAccount; } function setURIs( string calldata _firstUri, string calldata _secondUri, string calldata _thirdUri ) external onlyOwner() { firstUri = _firstUri; secondUri = _secondUri; thirdUri = _thirdUri; } function setMintCost(uint256 _newCost) public onlyOwner() { mintCost = _newCost; emit MintCostChanged(_newCost); } function requestRandomNFT( RandomNft memory nft, bytes32 sigR, bytes32 sigS, uint8 sigV ) external payable { require(msg.value == mintCost, ERR_MINT_COST_NOT_MET); require(minterToMintCount[msg.sender] < MAX_MINTS_PER_ADDRESS, ERR_MINT_LIMIT_REACHED); require(verify(authorizedAccount, nft, sigR, sigS, sigV), ERR_VERIFICATION_FAILED); bytes32 requestId = airnodeRrp.makeFullRequest( airnode, endpointIdUint256, address(this), sponsorWallet, address(this), this.fulfill.selector, "" ); awaitingFulfillment[requestId] = true; requestToMinter[requestId] = msg.sender; emit RequestedRandom(requestId); } function fulfill(bytes32 requestId, bytes calldata data) external onlyAirnodeRrp { require(awaitingFulfillment[requestId], ERR_REQUEST_ID_UNKNOWN); uint256 newId = tokenCounter++; uint256 randomUint256 = abi.decode(data, (uint256)); Classifier classifier = Classifier(randomUint256 % 3); tokenIdToClassifier[newId] = classifier; _safeMint(requestToMinter[requestId], newId); minterToMintCount[requestToMinter[requestId]]++; awaitingFulfillment[requestId] = false; if (classifier == Classifier.FIRST) { _setTokenURI(newId, firstUri); } else if (classifier == Classifier.SECOND) { _setTokenURI(newId, secondUri); } else if (classifier == Classifier.THIRD) { _setTokenURI(newId, thirdUri); } emit MintedRandomNFT(requestId, randomUint256); } function verify( address signer, RandomNft memory nft, bytes32 sigR, bytes32 sigS, uint8 sigV ) internal pure returns (bool) { require(signer != address(0), ERR_INVALID_SIGNER); return signer == ecrecover( keccak256(abi.encode(nft.nonce, nft.from)), sigV, sigR, sigS ); } function withdraw() external onlyOwner() { uint balance = address(this).balance; payable(owner()).transfer(balance); emit Withdrawn(owner(), balance); } } Notice that it uses API3 to select a random Classifier for the minted NFT from 3 Classification choices. Also an external signature is required. This is so I can have a next.js app with a private key on the backend that enables the website to be the sole source of NFT mints. I deployed the contract then the derived my sponsor wallet with the following command (P.S. my deployed contract instance is 0x8Ca82f3b509F18e79a4880415Df0cCB9807FA39a): npx @api3/airnode-admin derive-sponsor-wallet-address --airnode-xpub xpub6CuDdF9zdWTRuGybJPuZUGnU4suZowMmgu15bjFZT2o6PUtk4Lo78KGJUGBobz3pPKRaN9sLxzj21CMe6StP3zUsd8tWEJPgZBesYBMY7Wo --airnode-address 0x6238772544f029ecaBfDED4300f13A3c4FE84E1D --sponsor-address 0x8Ca82f3b509F18e79a4880415Df0cCB9807FA39a This output 0x320ce404b4e9a0ab44e890a91162109bf5b8fe80 as the sponsor wallet. I ran the following function with hardhat: const Token = await ethers.getContractFactory("RandomSurfaceReachT1"); const token = await Token.attach("0x8Ca82f3b509F18e79a4880415Df0cCB9807FA39a"); // API3 Nodary address: 0x6238772544f029ecaBfDED4300f13A3c4FE84E1D // API3 Nodary RPC Connect String: 0xfb6d017bb87991b7495f563db3c8cf59ff87b09781947bb1e417006ad7f55a78 // address for private key that I'm going to use for signing 0xBcc0785B2Fe7e8E2875E8Ee110EBE9A3d948f6D2 await token.setParameters("0x6238772544f029ecaBfDED4300f13A3c4FE84E1D", "0xfb6d017bb87991b7495f563db3c8cf59ff87b09781947bb1e417006ad7f55a78", "0x320ce404b4e9a0ab44e890a91162109bf5b8fe80", "0xBcc0785B2Fe7e8E2875E8Ee110EBE9A3d948f6D2"); await token.setURIs("ipfs://bafybeif7eum33srxx2eeh73vzpzaeidcz4olkak644kcduto3vtnon7bya/firstBlue.json", "ipfs://bafybeif7eum33srxx2eeh73vzpzaeidcz4olkak644kcduto3vtnon7bya/secondGreen.json", "ipfs://bafybeif7eum33srxx2eeh73vzpzaeidcz4olkak644kcduto3vtnon7bya/thirdRed.json"); This is a repo to my next.js app https://github.com/ChristianOConnor/nft-sig-verify-mint-page-pub. My .env.local file looks like this: NODE_ENV=development NEXT_PUBLIC_CONTRACTS_ADDRESS='0x8Ca82f3b509F18e79a4880415Df0cCB9807FA39a' PRIVATE_KEY_FOR_SIGNING='PRIVATE KEY FOR 0xBcc0785B2Fe7e8E2875E8Ee110EBE9A3d948f6D2' I replaced PRIVATE_KEY_FOR_SIGNING with a placeholder. When I connect my wallet and click "Mint Now!" I get this in my web browser console: Browser: ContractFunctionExecutionError: The contract function "requestRandomNFT" reverted with the following reason: Verification failed Contract Call: address: 0x8Ca82f3b509F18e79a4880415Df0cCB9807FA39a function: requestRandomNFT((uint256 nonce, address from), bytes32 sigR, bytes32 sigS, uint8 sigV) args: ({"nonce":7121712914477423,"from":"0x41Ae1A06481FFf8DaE7dBBB90508A0fe50632449"}, 0x04d42a0436d2d5122cbebaca45e89ffef1c221e2c283a7f5216e3129d430271d, 0x3fe532453c5e08a757cc6a3ac4787714f53a9b537a58c118ad0763afe00e73a4, 28) sender: 0x41Ae1A06481FFf8DaE7dBBB90508A0fe50632449 Docs: https://viem.sh/docs/contract/simulateContract.html Version: viem@0.3.31 at Module.getContractError (getContractError.js:24:12) at Module.simulateContract (simulateContract.js:40:15) at async Module.prepareWriteContract (chunk-NRSD7F2O.js:2075:31) And this is the output of (prepareError || error)?.message: Error: The contract function "requestRandomNFT" reverted with the following reason: Verification failed Contract Call: address: 0x8Ca82f3b509F18e79a4880415Df0cCB9807FA39a function: requestRandomNFT((uint256 nonce, address from), bytes32 sigR, bytes32 sigS, uint8 sigV) args: ({"nonce":7121712914477423,"from":"0x41Ae1A06481FFf8DaE7dBBB90508A0fe50632449"}, 0x04d42a0436d2d5122cbebaca45e89ffef1c221e2c283a7f5216e3129d430271d, 0x3fe532453c5e08a757cc6a3ac4787714f53a9b537a58c118ad0763afe00e73a4, 28) sender: 0x41Ae1A06481FFf8DaE7dBBB90508A0fe50632449 Docs: https://viem.sh/docs/contract/simulateContract.html Version: viem@0.3.31 我现在如何获得铸币厂!成功铸造 NFT 的按钮?
- Smart Contract
- Solidity
11最佳答案
- 76
- 50
- 46
- 37
- 36
- 25
- 25
- 25
- 20
- 16
- Solidity
- Smart Contract
- Solidity Compiler
- Use cases
- Optimizer
- Yul
- Language Grammar
- Internals
- Private