Solidity.

Hỏi đáp Chuyên Gia

Hỏi đáp với các chuyên gia trong cộng đồng Solidity

Bài viết

17
  • 0xa0c8...4ff4.
    Jun 04, 2024
    Hỏi đáp Chuyên Gia

    Cú pháp solidity thay đổi bao lâu một lần

    Tôi muốn biết tần suất thay đổi các quy tắc cú pháp solidity và bản tin tốt nhất để theo dõi các bản cập nhật gần đây nhất

    • Smart Contract
    • Solidity
    • Language Grammar
    • Solidity Compiler
    1
    1
  • 0x3c83...1469.
    Jan 09, 2024
    Hỏi đáp Chuyên Gia

    Công cụ giống như Remix cho Anvil

    Tôi biết bạn có thể triển khai các hợp đồng từ Remix đến Anvil. Nhưng có cách nào để tương tác với các hợp đồng được triển khai từ máy của tôi trong Anvil không? Những hợp đồng này không hiển thị trong Remix. Hay có một công cụ khác như Remix có thể làm được điều đó không? Các nhà phát triển có kinh nghiệm tương tác với các hợp đồng như thế nào? Cảm ơn

    • Solidity
    1
    1
  • 0x60a8...9bf8.
    Nov 07, 2023
    Hỏi đáp Chuyên Gia

    Solidity - Sự cố khi cài đặt Foundry: Thời gian chờ kết nối SSL”

    Tôi gặp sự cố trong khi cố gắng cài đặt Foundry bằng lệnh Quá 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
    1
    1
  • 0x6ea2...bab7.
    Oct 23, 2023
    Hỏi đáp Chuyên Gia

    Lỗi khi gọi `IncreaseLiquidity `trong NonFungiblePositionManager.

    Tôi gặp các bài kiểm tra thất bại khi gọi increaseLiquidity vào NonFungiblePositionManager. decreaseLiquidityhoạt động như mong đợi nhưng IncreaseLiquidity không thành công. Đây là mã: underlyingPositionManager.increaseLiquidity( INonfungiblePositionManager.IncreaseLiquidityParams({ tokenId: loan.tokenId, amount0Desired: amount0, amount1Desired: amount1, amount0Min: 0, amount1Min: 0, deadline: block.timestamp }) Đây là đầu ra của xưởng đúc cho thử nghiệm [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) Ai đó có thể cho tôi biết vấn đề có thể là gì không, cảm ơn bạn.

    • Smart Contract
    • Solidity
    0
    1
  • foufrix.
    Jul 31, 2023
    Hỏi đáp Chuyên Gia

    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
    0
    1
  • 0x0375...f041.
    Jul 10, 2023
    Hỏi đáp Chuyên Gia

    Làm thế nào để đảo ngược keccak256 trong độ rắn

    Tôi cần trợ giúp với đoạn mã sau, nơi tôi được cung cấp keccak256 của một tham số và cần đảo ngược nó để tìm tham số để giải quyết thách thức 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
    2
    2
  • 0x4ec1...6edc.
    Jun 29, 2023
    Hỏi đáp Chuyên Gia

    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
    0
    2
    Câu trả lời hay nhất
  • Christian O'Connor.
    May 27, 2023
    Hỏi đáp Chuyên Gia

    Solidity và ethers.js Tính toán các địa chỉ khác nhau từ cùng một chữ ký

    Kịch bản này: 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}); Cung cấp cho đầu ra này: người ký là: 0xEB7265F6625EAE66403A637C073E63CCF33B8CDC Vậy tại sao javascript tính 0x1AB26702A8068A247BD33A9555DFEF791D2BD68D, trong khi trình biên dịch solidity của hardhat tính 0xEB7265F6625EAE66403A637C073E63CCF33B8CDC?

    • Smart Contract
    • Solidity
    2
    1
    Câu trả lời hay nhất
  • Christian O'Connor.
    May 26, 2023
    Hỏi đáp Chuyên Gia

    Tại sao Solidity tạo ra một địa chỉ khác với một khóa riêng tư hơn ether.js?

    Tôi có chức năng này trong hợp đồng vững chắc của tôi: 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 Mã này cho tôi 0x1AB26702A8068A247BD33A9555DFEF791D2BD68D, nhưng mã rắn của tôi cho tôi 0x2d0b2215d4e00807a6982877a9762ef41541ecef. Điều đó chẳng có ý nghĩa gì cả. Tại sao chuyện này lại xảy ra?

    • Smart Contract
    • Solidity
    1
    1
    Câu trả lời hay nhất
  • Christian O'Connor.
    May 22, 2023
    Hỏi đáp Chuyên Gia

    Tôi nhận được lỗi “Xác minh không thành công” khi cố gắng làm bạc hà một NFT yêu cầu 2 chữ ký và sử dụng API3

    Tôi có một hợp đồng vững chắc này: // 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 Làm thế nào để có được Mint ngay bây giờ! để thành công bạc hà một NFT?

    • Smart Contract
    • Solidity
    1
    1
    Câu trả lời hay nhất
Chúng tôi sử dụng cookie để đảm bảo bạn có trải nghiệm tốt nhất trên trang web của chúng tôi.
Thêm thông tin