当前位置: 首页 > java >正文

NodeJS全栈WEB3面试题——P2智能合约与 Solidity

2.1 简述 Solidity 的数据类型、作用域、函数修饰符。

  • 数据类型:

    • 值类型(Value Types)uint, int, bool, address, bytes1bytes32, enum

    • 引用类型(Reference Types)array, struct, mapping

    • 特殊类型string(动态字节数组)

  • 作用域(Scope):

    • 状态变量(State variables):存储在区块链上的合约存储中,合约生命周期内存在。

    • 局部变量(Local variables):函数内部声明的变量,生命周期仅限于函数调用。

    • 全局变量(Global variables):Solidity提供的如msg.sender, block.timestamp等,访问链上信息。

  • 函数修饰符(Function Modifiers):
    用于改变函数行为的代码片段,可以控制访问权限、前置条件、后置操作等。常见如onlyOwner限制调用者,payable允许函数接收以太币等。修饰符可以复用代码,提高合约安全性。


2.2 require、assert、revert 区别?使用场景?

  • require(condition, message):
    用于输入校验和外部条件判断。失败时回退交易并返还剩余Gas。常用于验证用户输入、状态或权限。

  • assert(condition):
    用于检查不变量(程序内部错误)。失败时消耗所有Gas,通常表示合约出现严重BUG。

  • revert(message):
    显式回退交易,通常用于复杂的错误处理流程。与require类似,但可嵌套调用并提供错误信息。

总结:

  • require验证外部输入和条件,防止错误操作。

  • assert检测不应发生的内部错误。

  • revert做复杂错误处理或在条件不满足时回退。


2.3 什么是重入攻击(Reentrancy)?如何防御?

  • 重入攻击指攻击者在一个合约调用过程中,通过递归调用同一合约的漏洞函数,重复利用尚未更新状态的合约逻辑,窃取资产。最经典的例子是The DAO攻击。

  • 防御方法:

    1. “检查-效果-交互”模式:先修改合约状态,再调用外部合约。

    2. 使用ReentrancyGuard修饰器(如OpenZeppelin库),防止函数被重入调用。

    3. 限制调用次数和控制流

    4. 减少对外部合约的依赖


2.4 如何通过 Node.js 与 Solidity 合约交互?

  • 主要借助 web3.jsethers.js 这两个库。流程如下:

    1. 通过ABI和合约地址创建合约实例。

    2. 配置钱包私钥和Provider(如Infura、Alchemy或本地节点)。

    3. 调用合约的读取方法(call)或写入方法(send),写入需签名交易。

    4. 监听交易回执和事件。

示例代码(用ethers.js):

const { ethers } = require("ethers");
const provider = new ethers.providers.InfuraProvider("homestead", "INFURA_API_KEY");
const wallet = new ethers.Wallet("PRIVATE_KEY", provider);
const contractABI = [...]; // 合约ABI
const contractAddress = "0xYourContractAddress";
const contract = new ethers.Contract(contractAddress, contractABI, wallet);async function transferTokens(to, amount) {const tx = await contract.transfer(to, amount);await tx.wait();console.log("Transfer successful:", tx.hash);
}

2.5 写一个简单的ERC-20或ERC-721合约,并用 JavaScript 发起转账交易。

示例:一个简单的ERC-20合约

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract SimpleToken {string public name = "SimpleToken";string public symbol = "STK";uint8 public decimals = 18;uint256 public totalSupply;mapping(address => uint256) public balanceOf;event Transfer(address indexed from, address indexed to, uint256 value);constructor(uint256 _initialSupply) {totalSupply = _initialSupply * 10 ** decimals;balanceOf[msg.sender] = totalSupply;}function transfer(address _to, uint256 _value) public returns (bool) {require(balanceOf[msg.sender] >= _value, "Insufficient balance");balanceOf[msg.sender] -= _value;balanceOf[_to] += _value;emit Transfer(msg.sender, _to, _value);return true;}
}

JavaScript 发送转账交易示例(用ethers.js):

const { ethers } = require("ethers");const provider = new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/YOUR_INFURA_ID");
const privateKey = "YOUR_PRIVATE_KEY";
const wallet = new ethers.Wallet(privateKey, provider);const contractAddress = "YOUR_CONTRACT_ADDRESS";
const abi = ["function transfer(address to, uint amount) public returns (bool)",
];const contract = new ethers.Contract(contractAddress, abi, wallet);async function sendToken(to, amount) {const decimals = 18;const amountInWei = ethers.utils.parseUnits(amount.toString(), decimals);const tx = await contract.transfer(to, amountInWei);console.log("Transaction hash:", tx.hash);await tx.wait();console.log("Transfer confirmed");
}sendToken("0xRecipientAddress", 10).catch(console.error);

http://www.xdnf.cn/news/10511.html

相关文章:

  • 单调栈(打卡)
  • 【C++/Linux】TinyWebServer前置知识之IP协议详解
  • 【iOS】YYModel源码解析
  • 告别printf!嵌入式系统高效日志记录方案
  • 如何评估 RAG 的分块Chunking策略
  • 【沉浸式求职学习day52】【初识Mybaits】
  • 风控研发大数据学习路线
  • Java生态中的NLP框架
  • 【C语言】C语言经典小游戏:贪吃蛇(上)
  • Vortex GPGPU的github流程跑通与功能模块波形探索(四)
  • 解决:install via Git URL失败的问题
  • 【LLM vs Agent】从语言模型到智能体,人工智能迈出的关键一步
  • Java中对象哈希值的解析
  • 力扣HOT100之多维动态规划:64. 最小路径和
  • Langchian - 自定义提示词模板 提取结构化的数据
  • bismark OT CTOT OB CTOB 以及mapping后的bam文件中的XG,XR列的含义
  • 用go从零构建写一个RPC(4)--gonet网络框架重构+聚集发包
  • 【知识点】第3章:基本数据类型
  • Linux之进程间通信
  • 600+纯CSS加载动画一键获取指南
  • NLP学习路线图(十九):GloVe
  • Windows不关防火墙,安全开放端口方法
  • 【图论 拓扑排序 贪心 临项交换】P5603 小 C 与桌游 题解|普及+
  • ubuntu 添加应用到启动菜单
  • Unity中应对高速运动的物体,碰撞组件失效的问题?
  • Android高级开发第四篇 - JNI性能优化技巧和高级调试方法
  • 小团队如何落地 Scrum 模型:从 0 到 1 的实战指南
  • Mysql水平分表(基于Mycat)及常用分片规则
  • 【黑马程序员uniapp】项目配置、请求函数封装
  • win32相关(虚拟内存和物理内存)