Web3如何实现仅持有指定ERC20 Token的用户可查看隐藏图片
需求实现方案与现有逻辑调整建议
现有逻辑核心问题
- Solidity代码语法错误:原
Reveal函数的require语句缺失右括号,执行会报错;且校验条件写的>=1 wei不符合需求,如果你要限制至少持有1枚完整的ERC20 Token(多数ERC20精度为18位),1枚对应的是1e18 wei,原条件只要账户有一丁点Token就会通过校验 - 功能冗余:你不需要自己封装校验函数,直接调用ERC20合约原生的
balanceOf方法就能查询用户余额,单独写Reveal函数没有额外价值 - 前端逻辑混淆:你把Solidity语法直接写到了前端JS代码里,前端无法直接识别执行;同时合约调用格式、括号闭合、多余分号都存在语法错误,代码无法正常运行
- 安全漏洞:仅通过前端控制图片的
visibility属性毫无作用,用户只要打开开发者工具修改CSS属性就能直接看到隐藏的图片,完全绕开校验
正确实现步骤
合约端调整(可选)
如果你还是希望保留链上校验的封装,修正后的代码如下:
function Reveal() override public view returns (bool) { // 修正括号缺失问题,这里根据你的Token精度调整阈值,18位精度的1枚对应1e18 wei require(ERC20Token(0xB0Bd09D....).balanceOf(msg.sender) >= 1e18, "Insufficient balance"); return true; }
如果不需要封装,直接用标准ERC20的balanceOf方法即可,无需部署额外函数。
前端逻辑修正(web3.js示例)
首先要确认用户已经完成Metamask钱包连接,再绑定按钮触发事件:
// 标准ERC20的balanceOf方法ABI const erc20ABI = [ {"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"} ]; const TOKEN_ADDR = "0xB0Bd09D...."; // 你的ERC20合约地址 const erc20Contract = new web3.eth.Contract(erc20ABI, TOKEN_ADDR); document.getElementById("revealBtn").addEventListener("click", async () => { try { const userAddr = window.ethereum.selectedAddress; if (!userAddr) { alert("请先连接钱包"); return; } // 查询当前用户的Token余额 const balance = await erc20Contract.methods.balanceOf(userAddr).call(); // 18位精度下1枚Token对应1e18 wei,可根据你的Token实际精度调整 if (BigInt(balance) >= BigInt(10 ** 18)) { // 校验通过再加载图片,不要提前把图片地址写死在HTML里,避免用户直接爬取路径 document.getElementById("instructions").src = "你的说明图片存储地址"; document.getElementById("instructions").style.display = "block"; } else { document.getElementById("revealBtn").innerText = "你需要至少持有1枚指定ERC20 Token才可查看"; } } catch (e) { console.error("校验出错", e); } })
安全加固建议
如果对安全性要求高,不要在前端做判断逻辑:
- 把图片存储在后端服务,不要放在前端静态资源目录
- 前端让用户对当前地址做签名,把签名和地址传给后端,后端自己去链上查询余额,确认符合要求后再返回图片流或者加密后的图片地址,彻底避免前端篡改绕过校验
内容的提问来源于stack exchange,提问作者Brian Lee Victory
相关产品推荐
相关产品推荐

