ques mid
Solidity 问题汇总
1. transfer 和 send 之间有什么区别?为什么不应该使用它们?
2. 如何在 Solidity 中编写高效的 gas 循环?
3. 代理合约中的存储冲突是什么?
4. abi.encode 和 abi.encodePacked 之间有什么区别?
5. uint8、uint32、uint64、uint128、uint256 都是有效的 uint 大小。还有其他的吗?
6. 在权益证明之前后,block.timestamp 发生了什么变化?
7. 什么是抢跑(frontrunning)?
抢跑(frontrunning)是一种攻击行为,指在一笔正常交易等待打包的过程中,抢跑机器人通过设置更高 Gas 费用抢先完成攻击交易。在所有 Front-Running 中,最典型最具危害性的就是针对 AMM 交易的 Sandwich Attacks (三明治攻击) 注意:夹子交易有时也成三明治攻击,但是它是有矿工或验证节点端完成的,能把被攻击的那笔交易夹在中间打包区块。
8. 什么是提交-揭示方案,何时使用它?
9. 在什么情况下,abi.encodePacked 可能会产生漏洞?
10. 以太坊如何确定 EIP-1559 中的 BASEFEE?
11. 冷读(cold read)和热读(warm read)之间有什么区别?
12. AMM 如何定价资产?
13. 代理中的函数选择器冲突是什么,它是如何发生的?
14. payable 函数对 gas 的影响是什么?
15. 什么是签名重放攻击?
签名重放攻击是一种网络攻击,攻击者通过 重复使用已经被验证的数字签名来欺骗系统。数字签名是一种用于验证数据完整性和身份验证的技术,它使用公钥密码学来生成和验证签名。在签名重放攻击中,攻击者截获了一个数字签名并将其重复使用,以便在未经授权的情况下执行某些操作。例如,攻击者可以使用重放攻击来多次执行某个交易,从而导致资金损失。为了防止签名重放攻击,您可以使用以下方法: 使用时间戳或随机数来确保每个数字签名只能使用一次。 使用序列号来确保数字签名按顺序使用。 使用加密协议来保护数字签名,例如 TLS 或 SSL。
16. 什么是 gas griefing ? gas 恶意消耗
简单来说,为了防止 Gas griefing,智能合约的设计应确保用户不能通过自己的行为来不合理地增加其他用户的 Gas 成本。这意味着避免设计那些允许用户在不受限制的情况下影响其他用户交易 Gas 成本的合约功能。
例如,避免这种情况的方法可能包括:
- 对于那些可能被恶意利用来增加 Gas 成本的操作,实施严格的访问控制。
- 限制合约中的状态变化,这些状态变化可能导致函数执行的 Gas 成本显著变化。
- 使用固定的 Gas 费用,或者设置一个上限,以减少状态变化对 Gas 成本的影响。
- 避免在关键的合约操作中使用不受信任的外部合约调用。
- 对于必须使用的外部调用,进行彻底的审计和测试,确保它们不会导致不可预见的 Gas 消耗。
总之,智能合约的开发者需要仔细考虑其设计,以确保合约的使用不会受到 Gas griefing 的影响,从而保护用户免受不必要的高 Gas 费用的侵害。
17. 如何设计一个石头-剪刀-布的智能合约游戏,使玩家无法作弊?
18. 自由内存指针是什么,它存储在哪里?
19. 接口中有效的函数修饰符有哪些?
20. 函数参数中的 memory 和 calldata 有什么区别?
21. 描述三种存储 gas 成本类型。
22. 为什么可升级合约不应该使用构造函数?
23. UUPS 和 Transparent Upgradeable Proxy 模式之间有什么区别?
24. 如果合约通过 delegatecall 调用一个空地址或之前已自毁的实现,会发生什么?如果是常规调用而不是 delegatecall 呢?
25. ERC777 代币存在什么危险?
26. 根据 Solidity 风格指南,函数应该如何排序?
27. 根据 Solidity 风格指南,函数修饰符应该如何排序?
28. 什么是债券曲线(bonding curve)?
29. OpenZeppelin ERC721 实现中的 safeMint 与 mint 有何不同?
30. Solidity 提供哪些关键字来测量时间?
31. 什么是三明治(sandwich)攻击?
三明治攻击是去中心化的一种攻击手段,主要出现在 swap 交易中。黑客节点把用户的交易夹在中间,前后是攻击者的交易,利用用户的交易改变价格,获取价差套利。例如用户买入 eth, 黑客会在创建一个 eth 买单,和卖单,然后打包交易,区块内的交易顺序是:黑客买单 - 用户买单 - 黑客卖单。导致用户真正的买入价格偏高。解决:可设置低滑点,如果价格超出预算范围交易失败。
32. 如果向一个会回滚的函数进行 delegatecall,delegatecall 会怎么做?
如果向一个会回滚的函数进行 delegatecall,delegatecall 会返回 false,并且不会发生任何状态更改。如果是常规调用而不是 delegatecall,则会导致交易失败并回滚,因为您不能调用一个不存在的合约或已自毁的合约。
33. 乘以和除以二的倍数的 gas 高效替代方法是什么?
在 Solidity 中,将一个数乘以或除以 2 的倍数可以通过移位运算来实现,这比使用乘法或除法运算更高效。具体来说,将一个数左移 n 位相当于将它乘以 2 的 n 次方,而将一个数右移 n 位相当于将它除以 2 的 n 次方。例如,将一个数除以 8 可以通过将它右移 3 位来实现,而将一个数乘以 16 可以通过将它左移 4 位来实现。在 Solidity 0.8.3 及更高版本中,编译器会自动将乘法和除法运算转换为移位运算,从而提高代码的效率。
34. 多大 uint 可以与一个地址在一个槽中?
一个地址是 20 个字节(160 位),而一个 uint256 是 32 个字节(256 位), 256-160 = 96。uint96 及以下的都可以