Solidity
# base
- units
- uint is an alias for uint256
- uint8, uint16, uint32
- modifier
- modifier(修饰符)用于修改函数的行为,通常用于访问控制、输入验证、条件检查等场景。
- 推荐使用 modifier 进行权限管理,提高合约的安全性和可维护性
- time
1 days
- 如何安全生成随机数
- Solidity 自带的随机数生成方式不安全,矿工可以操纵结果。
- 真正安全的随机数需要预言机(如 Chainlink VRF)。
- 如果只是简单游戏、测试项目,可以使用 keccak256 方案,但不能用于金融或博彩应用。
- other
- 智能合约如何存储和管理以太坊(Ether),以及如何从合约中提取资金
# gas
- save gas
Struct packing to save gasView functions don't cost gasStorage is Expensive: particularly writes.
# events
Events are a way for your contract to communicate that something happened on the blockchain to your app front-end, which can be 'listening' for certain events and take action when they happen.
# 访问权限
Solidity 允许使用 可见性修饰符 来控制函数和状态变量的访问权限:
| 修饰符 | 适用于 | 访问范围 | 其他合约是否可访问 | 继承合约是否可访问 |
|---|---|---|---|---|
private | 变量 & 函数 | 仅限当前合约 | ❌ 否 | ❌ 否 |
internal | 变量 & 函数 | 当前合约 + 继承合约 | ❌ 否 | ✅ 是 |
public | 变量 & 函数 | 所有地方 | ✅ 是 | ✅ 是 |
external | 仅适用于函数 | 合约外部 | ✅ 是 | ❌ 否(但可用 this.f() 访问) |
# calldata vs memory
| 关键点 | calldata | memory |
|---|---|---|
| 存储位置 | 以太坊 call data(调用数据) | 以太坊 内存(RAM) |
| 可修改性 | 不可修改 | 可修改 |
| gas 成本 | 更便宜(适用于大数据) | 更昂贵(复制到内存) |
| 适用范围 | 仅适用于 外部函数参数 | 适用于 外部 & 内部函数参数 |
# storage vs memory
| 关键点 | storage | memory |
|---|---|---|
| 存储位置 | 以太坊 持久存储(链上) | 以太坊 临时内存(RAM) |
| 生命周期 | 持久化,函数执行后仍然存在 | 临时,函数执行完即释放 |
| gas 成本 | 昂贵(修改 storage 需要链上存储) | 较便宜(仅在执行时占用内存) |
| 可修改性 | 可修改,修改会消耗大量 gas | 可修改,但仅在当前调用中有效 |
| 适用范围 | 适用于 长期数据存储(如状态变量) | 适用于 临时计算和传递数据 |
# keccak256
| 用途 | 代码示例 | 作用 |
|---|---|---|
| 生成唯一 ID | keccak256(abi.encodePacked(msg.sender, block.timestamp)) | 避免重复,标识交易、订单等 |
| 数据完整性校验 | require(keccak256(abi.encodePacked(userInput)) == originalHash, "Data mismatch!"); | 确保数据未被篡改 |
| 伪随机数 | uint(keccak256(abi.encodePacked(block.timestamp, msg.sender))) % 100; | 生成伪随机数(安全性一般) |
| Mapping 键 | bytes32 key = keccak256(abi.encodePacked(user)); | 隐私性更强的键 |
| 签名验证 | keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)) | ECDSA 签名验证 |
总结一句话:keccak256 在 Solidity 中主要用于 哈希计算、数据完整性校验、伪随机数生成、映射键、签名验证等,是智能合约开发中的核心安全工具。
# code
# method
string greeting = "What's up dog";
function sayHello() public view returns (string memory) {
return greeting;
}
1
2
3
4
5
2
3
4
5
- key
- payable: 用于标记函数,表示该函数可以接收 Ether(ETH)
- modifier: 见下
# modifier
modifier aboveLevel(uint _level, uint _zombieId) {
require(zombies[_zombieId].level > _level)
_;
}
1
2
3
4
2
3
4
_;: last line
# link
上次更新: 2025/02/14, 17:50:22