cyfrin-updraft

在这一篇文章中介绍过cyfrin-updraft,所以就不赘述了

学习资源: https://updraft.cyfrin.io/courses/solidity/simple-storage/introduction
https://github.com/Cyfrin/foundry-full-course-cu
Blockchain Developer, Smart Contract, & Solidity Career Path - Powered By AI - Beginner to Expert Course
| Foundry Edition 2024 |

英语学习笔记:

1. pace yourself

核心翻译:调整节奏;量力而行(尤指避免因急于求成而过度消耗)
场景与用法

  • 常用于提醒他人在工作、学习或体力活动中合理分配精力,避免疲劳或失误。
    例:You’ve got a whole week to finish the project—pace yourself and don’t work all night.(你有一整周时间完成这个项目,调整好节奏,别熬通宵。)
  • 在运动场景中可译为“控制速度”,如:Pace yourself in the marathon, or you’ll burn out at the halfway mark.(马拉松比赛中要控制好速度,不然中途就会体力不支。)

2. gets ingrained

核心翻译:变得根深蒂固;深入人心(尤指习惯、观念等逐渐固化,难以改变)
语法说明:“get + 过去分词”表被动或状态变化,“ingrained”本义为“根深蒂固的”,此处强调“从无到有、逐渐固化”的过程。
场景与用法

  • 描述习惯养成:Bad habits like procrastination get ingrained if you don’t make an effort to change them.(如果不刻意改变,拖延这类坏习惯会变得根深蒂固。)
  • 描述观念或文化认知:In some industries, the idea that “longer hours mean better work” has gotten ingrained over time.(在一些行业,“工作时间越长=工作越好”的观念逐渐深入人心。)

结合你正在学习Solidity的场景,可延伸例句:Consistent coding practice helps good programming habits get ingrained faster.(持续的编码练习能让良好的编程习惯更快根深蒂固。)

3. get our hands on

“get our hands on” 是口语化表达,意为 “获取、得到”,翻译时用 “获取” 更符合技术文档的简洁性,若用于日常沟通,也可表述为 “拿到”

错题分析1

What does compiling a contract mean?
为什么这个答案是错误的:It converts high-level Solidity functions into machine code that runs natively on any blockchain, eliminating the need for the EVM. 而这个答案是正确的:It converts the Solidity code into bytecode and ABI that can be understood and executed by the Ethereum Virtual Machine (EVM).

要理解两个答案的对错,核心在于Solidity合约编译的本质区块链虚拟机(EVM)的核心作用,以及“机器码”和“字节码”的关键区别——我们拆解成3个核心要点讲清楚:

一、错误答案的核心问题(3个致命偏差)

错误答案:It converts high-level Solidity functions into machine code that runs natively on any blockchain, eliminating the need for the EVM.

1. “machine code(机器码)”是完全错误的

  • Solidity编译输出的不是“机器码”:机器码是直接能被CPU(如x86/ARM架构)执行的二进制指令,依赖具体的硬件架构;
  • 而Solidity编译的产物是EVM字节码(EVM Bytecode) ——这是专门为以太坊虚拟机设计的“虚拟指令集”,不是硬件能直接执行的机器码,只能在EVM中运行。

2. “runs natively on any blockchain”(原生运行在任意区块链)违背事实

  • 不同区块链有不同的虚拟机:比如以太坊用EVM,Solana用Sealevel,Avalanche C-Chain兼容EVM但本质还是依赖EVM,不存在“能原生运行在任意区块链”的编译产物;
  • Solidity是为EVM生态设计的语言,其编译产物仅适配EVM(或兼容EVM的链),无法直接在非EVM链上“原生运行”。

3. “eliminating the need for the EVM”(无需EVM)完全颠倒逻辑

  • EVM是以太坊智能合约的“执行环境”,也是Solidity设计的核心目标:Solidity代码必须先编译成EVM能识别的字节码,再部署到EVM中执行——EVM是Solidity合约运行的必要条件,而非可省略的环节。

二、正确答案的核心逻辑(精准匹配编译本质)

正确答案:It converts the Solidity code into bytecode and ABI that can be understood and executed by the Ethereum Virtual Machine (EVM).

1. 编译产物的准确性:Bytecode + ABI

  • Bytecode(字节码):Solidity代码编译后的核心产物,是一串十六进制的EVM指令(如0x6080604052...),部署到以太坊后,EVM会逐条执行这些指令;
  • ABI(Application Binary Interface,应用二进制接口):相当于“合约的说明书”,定义了合约的函数、参数、返回值等格式——外部程序(如前端、钱包)需要通过ABI才能调用合约的函数,这是错误答案完全遗漏的关键部分。

2. 执行环境的准确性:EVM是唯一执行者

Solidity的设计初衷就是为EVM编写智能合约,其编译过程本质是“将人类可读的Solidity代码,转换成EVM专属的可执行指令”——正确答案精准点出“EVM能理解并执行”,符合以太坊的核心运行逻辑。

总结:关键认知边界

错误答案的误区 正确的核心逻辑
产物是“机器码” 产物是EVM专属“字节码”+ABI
可在任意区块链原生运行 仅适配EVM(或兼容EVM的链)
无需EVM EVM是Solidity合约运行的必要环境

简单来说:Solidity编译不是“跨硬件的机器码转换”,而是“针对EVM的指令转换”,且必须输出ABI才能让合约被外部调用——这也是以太坊智能合约开发的基础认知。

错题分析2

Why can’t the storage location be used for new variables inside a function in Solidity? 答案:Because storage variables are meant to persist between function calls and are only declared at the contract level.我选的答案是:Because storage variables are reserved for constants only.

1. 核心概念澄清:Solidity 中 Storage 的本质

Solidity 里的 Storage 是以太坊区块链上的持久化存储区域,属于合约账户的永久状态(对比 Memory 是函数执行时的临时内存)。其核心规则是:

  • Storage 变量仅能在合约级别(全局)声明,生命周期与合约一致,跨函数调用持久化;
  • 函数内部无法直接声明新的 Storage 变量(仅能引用已有的合约级 Storage 变量,或通过指针/引用操作)。

2. 你的答案错误原因:“Storage 仅用于常量”是完全错误的

  • 常量(constant/immutable) 并不存储在 Storage 中:
    • constant 变量的值编译期确定,直接嵌入字节码,不占用 Storage 插槽;
    • immutable 变量部署时赋值,也不占用常规 Storage 插槽,存储在合约字节码的特殊区域;
  • Storage 真正存储的是合约的可变状态变量(比如用户余额、代币持仓等),而非常量——这是你答案的核心错误。

3. 正确答案的逻辑解析

“Because storage variables are meant to persist between function calls and are only declared at the contract level.”
(因为 Storage 变量旨在跨函数调用持久化,且仅能在合约级别声明)

  • 跨函数持久化:Storage 是合约的“永久内存”,如果允许函数内声明新的 Storage 变量,会导致这些变量的生命周期与函数绑定(执行完就销毁),违背 Storage 的设计初衷;
  • 仅合约级声明:Solidity 语法强制 Storage 变量在合约全局作用域声明,函数内只能操作(读取/修改)已存在的 Storage 变量,无法新建——这是语言层面的硬性规则,也是函数内不能用 Storage 声明新变量的直接原因。

4. 补充:函数内操作 Storage 的正确方式

函数内虽不能声明新的 Storage 变量,但可以引用已有的合约级 Storage 变量,或通过 Storage 指针操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
contract Example {
// 合约级 Storage 变量(合法)
uint256 public storageVar;

function updateStorage() external {
// 函数内引用已有 Storage 变量(合法)
storageVar = 100;

// Storage 指针(操作已有 Storage 数据,非新建)
uint256 storage ref = storageVar;
ref = 200; // 等价于修改 storageVar
}

// 函数内声明 Storage 变量(语法错误!)
// function wrong() external {
// uint256 storage newVar; // 编译报错
// }
}

总结

你答案的核心错误是混淆了“Storage 的用途”(存储合约可变状态)和“常量的存储位置”(不占用 Storage);而正确答案精准命中了 Storage 的两大核心特征:持久化生命周期 + 仅合约级声明,这也是函数内无法新建 Storage 变量的根本原因。

错题分析3

Given the following mapping mapping(address->uint256), what is the default value returned when accessing a key that does not exist?答案是zero,我选的是null

1. 核心结论:Solidity 映射不存在“null”,未赋值键的默认值是零值(zero value)

在 Solidity 中,mapping(address => uint256) 这类映射的核心规则是:所有未显式赋值的键,都会返回对应值类型的“零值(zero value)”,而非编程中常见的 null/nil/undefined

2. 你的答案错误原因:混淆了 Solidity 与其他语言的空值逻辑

  • null 并非 Solidity 的合法值:Solidity 没有 null 关键字(也无 undefined),这是和 JavaScript、Java 等语言的关键区别——Solidity 不会用“空值”表示“未初始化/不存在”,而是为每种基础类型定义了固定的零值。
  • **uint256 类型的零值就是 0**:映射的值类型是 uint256(无符号整数),其零值为数字 0;即使访问从未赋值的 address 键,返回结果也必然是 0,而非“空”。

3. 扩展验证:不同类型映射的零值

映射类型 访问不存在键的返回值(零值)
mapping(address => uint256) 0
mapping(address => bool) false
mapping(address => address) 0x0000000000000000000000000000000000000000(空地址)
mapping(address => bytes) 空字节数组 []

4. 代码示例验证

1
2
3
4
5
6
7
8
9
contract MappingTest {
mapping(address => uint256) public userBalances;

function getNonExistentKey() external view returns (uint256) {
// 访问一个从未赋值的地址(比如随机地址)
address randomAddr = 0x1234567890123456789012345678901234567890;
return userBalances[randomAddr]; // 返回 0,而非 null
}
}

编译并调用 getNonExistentKey(),结果必然是 0,不存在“返回 null”的可能。

总结

你选 null 的核心错误是将其他语言的“空值逻辑”套用到 Solidity 上——Solidity 设计上无 null 概念,映射对不存在的键始终返回值类型的零值;对于 uint256 类型,零值就是 0(zero),这也是正确答案的依据。

错误分析4

Which of the following code snippets is a valid way to declare a public function that accepts a uint256 parameter and sets a state variable to its value?
答案是: function store(uint256 _favoriteNumber) public { favoriteNumber = _favoriteNumber; }
我选的是 function store(uint256 _favoriteNumber) public { _favoriteNumber = favoriteNumber; }

1. 核心结论:赋值方向完全颠倒导致答案错误

Solidity 中赋值语句的规则和绝大多数编程语言一致:等号(=)左侧是“被赋值的变量”,右侧是“赋值的来源”
你选择的代码把赋值方向写反了,最终效果是“将状态变量的值覆盖传入的参数”(而非题目要求的“把参数值设置给状态变量”),因此不符合题意。

2. 逐行解析正确/错误代码

前提:合约中需先声明状态变量(题目隐含此前提)

1
2
contract NumberStorage {
uint256 favoriteNumber; // 合约级状态变量(Storage)

正确代码(答案)

1
2
3
function store(uint256 _favoriteNumber) public { 
favoriteNumber = _favoriteNumber;
}
  • 左侧 favoriteNumber:合约的状态变量(需要被修改的目标);
  • 右侧 _favoriteNumber:函数传入的参数(赋值的来源);
  • 效果:把用户传入的参数值,赋值给合约的状态变量,完全匹配题目“sets a state variable to its value”(将状态变量设为参数值)的要求。

错误代码(你选的)

1
2
3
function store(uint256 _favoriteNumber) public { 
_favoriteNumber = favoriteNumber;
}
  • 左侧 _favoriteNumber:函数的局部参数(Memory 类型,临时变量);
  • 右侧 favoriteNumber:合约的状态变量(当前值,比如初始零值 0);
  • 效果:把状态变量的当前值覆盖到参数里——参数是函数内的临时变量,函数执行完就销毁,状态变量本身完全没被修改,违背题目核心要求。

3. 关键补充:参数命名的下划线规范

Solidity 中常用下划线(_)前缀区分函数参数和状态变量(比如 _favoriteNumber 是参数,favoriteNumber 是状态变量),这个规范的目的就是避免赋值方向混淆——但核心规则还是“左目标、右来源”。

4. 验证:错误代码的实际执行效果

假设状态变量 favoriteNumber 初始值为 0,调用 store(100)

  • 正确代码:favoriteNumber 被设为 100(符合要求);
  • 错误代码:参数 _favoriteNumber 被改成 0,但 favoriteNumber 仍为 0(状态变量无变化,完全不符合题意)。

总结

你选错的核心原因是赋值语句的方向理解错误:题目要求“将状态变量设为参数值”,需要把参数放在等号右侧(作为值的来源),状态变量放在左侧(作为赋值目标);而你选的代码恰好颠倒了这一逻辑,导致状态变量未被修改,因此不符合要求。

错误分析5

What keyword can be used in a function declaration to specify that the function can only be accessed from within the same contract? 答案是private,我选的是internal

1. 核心结论:private vs internal 的访问权限边界是关键

Solidity 中函数/变量的访问权限关键字里,**private 严格限制“仅当前合约内部可访问”**,而 internal 允许“当前合约 + 继承它的子合约”访问——你选错的核心原因是混淆了两者的权限范围,题目明确要求“only be accessed from within the same contract(仅同一合约内访问)”,因此 private 是唯一正确答案。

2. 权限关键字对比表(函数/状态变量通用)

关键字 访问范围 核心特征
private 定义该关键字的合约本身可访问 子合约也无法访问,最严格
internal 定义合约 + 所有继承该合约的子合约可访问 禁止外部账户调用,但允许继承
public 所有合约/外部账户均可访问 自动生成 getter 函数
external 仅外部账户/其他合约可访问,当前合约需用 this. 调用 禁止内部直接调用

3. 代码示例验证:private vs internal

场景1:private 函数——子合约无法访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
contract Parent {
// private 函数:仅 Parent 内部可调用
function privateFunc() private pure returns (string memory) {
return "Only Parent can call me";
}

// 内部调用 private 函数(合法)
function callPrivate() public pure returns (string memory) {
return privateFunc();
}
}

contract Child is Parent {
// 子合约调用父合约的 private 函数(编译报错!)
function tryCallPrivate() public pure returns (string memory) {
return privateFunc(); // Error: member "privateFunc" is private
}
}

场景2:internal 函数——子合约可访问

1
2
3
4
5
6
7
8
9
10
11
12
13
contract Parent {
// internal 函数:Parent + Child 均可调用
function internalFunc() internal pure returns (string memory) {
return "Parent and Child can call me";
}
}

contract Child is Parent {
// 子合约调用父合约的 internal 函数(合法)
function callInternal() public pure returns (string memory) {
return internalFunc(); // 无报错,正常执行
}
}

4. 题目要求的精准匹配

题目关键词是 “only be accessed from within the same contract(仅同一合约内访问)”

  • private:完全符合“仅同一合约”,子合约都被排除;
  • internal:超出了“同一合约”的范围(包含子合约),因此不符合要求。

总结

你选 internal 的核心错误是未区分“同一合约”和“继承合约”的边界internal 的权限范围是“当前合约 + 子合约”,而题目严格限定“仅同一合约内访问”,只有 private 能满足这一条件。简单记:
private = 仅本合约;internal = 本合约 + 子合约。

phind是什么

https://www.phind.com/

Phind是一款专为开发者量身定制的AI驱动对话式搜索引擎,由美国旧金山的Hello Cognition, Inc.于2022年开发,隶属于Y Combinator S22批次,核心是结合生成式AI与网络搜索,为技术相关问题提供快速、精准的答案,大幅优化开发者的编码和调试效率。以下是其核心特点和功能的详细介绍:

  1. 主打开发者导向的精准技术响应
    • 它基于Phind - 405B、Phind - 70B等专属模型,在编程领域表现突出,比如Phind - 70B模型在HumanEval基准测试中得分82.3%,优于GPT - 4 Turbo的81.1%。面对“Python如何处理JSON数据”这类编程问题,能直接给出可复用的代码片段和最佳实践,无需用户在海量搜索结果中筛选。
    • 支持Python、Java、C++等多种主流编程语言,还能识别代码报错并提供调试方案,例如准确指出Python缩进错误位置并给出修正方式。
  2. 高效的代码相关核心功能
    • 除基础代码生成外,Phind Pro用户可使用浏览器内代码测试功能;其Phind - 405B模型支持128K上下文窗口,能应对大型代码库分析这类复杂任务,而Phind Instant模型速度可达350令牌/秒,满足快速查询需求。
    • 提供VS Code扩展插件,开发者无需切换界面,在编码环境中就能直接查询问题、获取代码建议,无缝融入开发流程。
  3. 灵活的交互与使用模式
    • 支持连续对话和上下文理解,用户可针对复杂问题逐步追问,比如先问“HTML表单验证失败原因”,再进一步探讨具体报错的解决办法。同时提供简洁、详细等多种回答模式,还包含专家、创意等回复模型,适配不同用户需求。
    • 无需注册即可使用,支持PWA功能,可添加到手机主屏幕实现原生应用般的使用体验;Phind Pro用户还能选择GPT - 4o、Claude 3.5 Sonnet等第三方模型,且支持图像分析,可上传错误截图获取针对性解决方案。
  4. 相比传统工具的独特优势
    • 响应速度快,75%的首次回答准确,且通常15秒内就能生成答案,远超传统搜索引擎筛选信息的耗时;和ChatGPT等通用AI相比,它具备实时联网能力,能获取最新的技术文档、第三方库信息,避免了通用模型知识滞后的问题。
    • 支持多查询搜索,可同时处理多个相关技术问题,适合多模块并行开发时的批量疑问解答。

zksync是什么

ZKsync是由德国团队Matter Labs开发的以太坊二层(Layer 2)扩容协议,核心基于零知识汇总(ZK - Rollup)技术,致力于解决以太坊主网交易速度慢、手续费高的问题,同时继承以太坊的高安全性,如今已发展为包含多条互联链的弹性网络,以下是其核心相关信息:

  1. 核心发展历程
    • ZKsync 1.0(后更名ZKsync Lite):2020年推出,虽能实现每秒3000笔交易的吞吐量,但存在功能局限,无法兼容以太坊虚拟机(EVM),仅支持转账、铸造NFT等简单操作,难以部署复杂DeFi协议,未能适配当时的生态需求。
    • ZKsync 2.0(后更名ZKsync Era):2022年底对外开放,核心突破是推出zkEVM,实现了与EVM的兼容,让开发者可无缝迁移以太坊上的Solidity/Vyper智能合约。同时还带来zkPorter等技术,大幅降低交易费用,生态也开始快速发展,吸引众多知名项目入驻。
    • ZKsync 3.0(弹性链):2024年6月通过v24升级推出,将ZKsync从单条ZK链升级为弹性链网络。该网络包含Rollup、Validium等多种类型的链,链之间可无缝互操作,还借助原生代币金库、共享路由器、ZK网关等组件,实现了生态的无限扩展和高效交互。
  2. 关键技术与核心优势
    • zkEVM:作为开创性技术,它实现零知识证明与EVM的结合,既保障交易隐私,又能高效运行智能合约,降低了以太坊开发者迁移项目到ZKsync的门槛,是ZKsync生态繁荣的重要基础。
    • zkPorter:链下数据存储方案,把二层账户状态拆分为链上zkRollup部分和链下PoS网络保护的zkPorter部分。采用zkPorter账户的交易费用极低,仅约0.001美元,且能与zkRollup账户无缝交互,大幅提升用户使用性价比。
    • 高安全性与兼容性:所有交易的有效性证明都会在以太坊主网验证,用户资金安全和以太坊主网同等;同时支持MetaMask等主流以太坊钱包,开发者可使用Hardhat、Foundry等常用框架,Web3 API也保持兼容,使用和开发体验接近以太坊。
  3. 生态与经济体系
    • 生态布局:生态内已聚集超200个项目,涵盖DeFi、NFT、钱包、基础设施等多个领域,1inch、Sushiswap、Uniswap等知名协议均已入驻,还在向社交、隐私保护等新方向拓展。此外,其ZK Stack框架支持开发者搭建定制化ZK区块链,Prividium平台则面向机构提供隐私合规的区块链服务。
    • 原生代币ZK:2024年6月推出,总供应量210亿枚。代币持有者可参与协议升级投票等治理活动,也能通过原生账户抽象功能支付网络费用。上线时曾开展大规模空投,空投量占总供应量的17.5%,是业内较大规模的Layer2项目空投。

zksync bridge是什么

ZKsync Bridge 并非单一款桥接工具,而是支撑ZKsync(以太坊Layer2扩展方案)生态的一系列跨链/跨层资产桥接工具集合。其核心作用是实现以太坊主网(L1)与ZKsync网络(L2),以及ZKsync与其他区块链网络、中心化交易所间的资产安全转移,核心依赖零知识证明(ZKP)技术保障交易安全性与高效性,主流桥接工具可分为官方原生桥和第三方桥两类,具体如下:

  1. 官方原生桥(Portal Bridge)
    这是以太坊与ZKsync间资产转移的默认工具,也是安全性优先级最高的桥接方式。它通过在以太坊主网和ZKsync分别部署智能合约,借助L1-L2互操作性实现资产流转。当用户从以太坊向ZKsync转账时,资产会被锁定在L1的桥接合约中,同时触发L2合约铸造等额资产;提款时则反之,L2上的资产会被销毁,L1合约会解锁对应数量的资产释放给用户。该桥接无额外服务费,适合高价值交易,但提款存在3小时延迟以保障安全,且仅支持标准ERC20代币,不兼容再平衡代币等定制化代币。
  2. 主流第三方桥接工具
    这类工具主要弥补官方桥的局限性,比如拓展跨链范围、提升转账速度等,适配不同用户的需求,常见类型有:
    • Across:主打去中心化跨Rollup桥接,聚焦Layer2间的互操作性。它采用乐观预言机保障安全,通过流动性提供者预存资金的模式,实现近乎即时的资产转账,中位桥接费常低于0.04美元,适合追求高效转账的普通用户。
    • LayerSwap:支持连接55种以上区块链网络,还能直接对接15家以上中心化交易所。除了跨链,它还可实现ZKsync Lite网络的快速提款,适合需要在链上与中心化交易所间灵活转移资产的场景。
    • Orbiter Finance:是ZKsync生态中常用的第三方桥,以低费率和快速转账为特点,支持以太坊生态内多个Layer2与ZKsync间的资产流转,适配小额高频的转账需求。