自查

最近发现个关于solidity面试的问题网站,正好之前又重新温习了solidity的,所以就来做一下
点击查看面试问题网站

容易

1,私有、内部、公共和外部函数之间有什么区别?

  • private表示只能在合同内部调用其他函数。 internal类似于私有关键字,但也可由继承当前合同的合同调用。 external只能在合同外部调用。 public可在任何地方被调用,无论是内部还是外部。

2,智能合约大约可以有多大?

  • 24KB

3,create 和 create2 有什么区别?

  • 首先它们都是Solidity中重要的操作码,都是用来部署合约的,区别就是,create是通过对发送者地址和nonce值进行哈希运算计算新合约的地址的,keccak256(rlp.encode(deployingAddress, nonce))。而create2更为复杂,它使用是通过一个公式计算新合约的地址的,这个公式包括,发送者地址,随机数,salt,字节码等参数,keccak256(0xff ++ deployingAddr ++ salt ++ keccak256(bytecode)),它也有个优点,可以在部署合约之前预测合约地址。

4,Solidity 0.8.0 版本对算术运算有什么重大变化?

  • 里面有对整数溢出做出了一个保护

5,代理需要哪种特殊的 CALL 才能工作?

  • 一般来说是:delegatecall,因为它主要用于委托调用,允许我们在主合约的上下文中加载和调用另一个合约的代码。被调用合约的代码被执行,但被调用合约所做的任何状态改变实际上是在主合约的存储中进行的,而不是在被调用合约的存储中

6,在 EIP-1559 之前,如何计算以太坊交易的成本?

Ethereum Improvement Proposal (EIP) 1559是以太坊的一个升级,旨在改变以太坊计算和处理网络交易费用(称为“gas费用”)的方式。该升级通过使用基于区块的基础费用basefee和发送方指定的最大费用,而不是对gas价格进行竞价,来更加平衡地激励矿工在高或低网络拥塞期间进行挖矿,从而使以太坊交易更加高效。EIP-1559是一个提案,它改变了gas费用的结构和矿工的奖励方式。该提案于2021年8月5日作为以太坊伦敦硬分叉的一部分实施。
gas费 = 基础费(Basefee)+ 矿工费(Tip),基础费会根据区块的Gas利用率动态调整,如每个区块的Gas费利用率低于50%,就降低手续费,高于50%,就提高手续费。

  • 关于EIP-1559,可以查看。以以太坊的交易成本有矿工通过拍卖机制来决定的,矿工会选出价高的交易,并将其包含在下一个区块上,交易成本,又俩个因素决定,GasPrice和Gas Limit,Gas Price是以太坊网络中的一种计量单位,用于衡量交易的复杂性。Gas Limit是指交易可以使用的最大Gas数量。交易的成本等于Gas Price乘以Gas Limit。因此,交易的成本取决于Gas PriceGas Limit的值,这些值由交易的发送者设置。

7,在区块链上创建随机数有哪些挑战

  • 不可预测,而且比较困难,因为所有矿工都在一个链上,它们有个共同的共识,如果随意产生伪随机数,那么就可能会导致达不成共识。

8,荷兰拍卖会和英国拍卖会有什么区别

  • 这个问感觉和slidity没有太多关系,就不回答了

9,ERC20 中的 和 有什么区别?transfertransferFrom

  • transfer是用户直接发送,transferForm是对于用户授权地址进行发送代币,用户可以不用直接参
  • transfer(address recipient, uint256 amount)
  • transferFrom(address sender, address recipient, uint256 amount)
  • 从上面的表达式也能看出,transfer是直接从当前合约转账给目标合约,transferFrom是可以设置发送账户和目标账户的

10,哪个更适合用于地址允许列表:映射还是数组?为什么

  • 数组是可以快速历遍地址列表,而映射可以快速查找地址是否在地址列表中,所以要根据具体的使用情况来决定使用谁

11,为什么不应该使用 tx.origin 进行身份验证?

  • tx.origin是发起交易的的人,在 Solidity 中,tx.origin 是一个全局变量,它返回发送交易的账户地址。在合约代码中,最常用的是使用 msg.sender 来检查授权,但有时由于有些程序员不熟悉 tx.origin msg.sender 的区别,如果使用了 tx.origin 可能导致合约的安全问题。黑客最典型的攻击场景是利用 tx.origin 的代码问题常与钓鱼攻击相结合的组合拳的方式进行攻击。因为 tx.origin 返回交易的原始发送者,因为攻击的调用链可能是原始发送者 -> 攻击合约 -> 受攻击合约。在受攻击合约中,tx.origin 是原始发送者。因此,通过调用 tx.origin 来检查授权可能会导致合约受到攻击。为了避免这种情况,建议使用 msg.sender 来检查授权

12,1 个Ether 相当于 多少个 gwei ?

  • 1 ether = 10^9gwei

13,1 个Ether 相当于 多少个 wei ?

  • 1 ether = 10^18wei

14,assertrequire 之间有什么区别?

  • require 应该被用于函数中检查条件,assert用于预防不应该发生的情况,即不应该使条件错误。

15,什么是闪电贷?

  • 就是无需抵押,就可以借钱,允许在一笔交易中还款

16,什么是 check-effects-interaction 模式?

  • Checks-Effects-Interactions模式确保所有通过合约的代码路径在修改合约的状态(Checks)之前完成对所提供的参数的所有必要检查;然后才对状态(Effects)进行任何改变。 在所有计划中的状态变化被写入存储空间之后,它可以调用其他合约中的函数(Interactions)。检查-生效-交互

17,运行一个单独的质押节点所需的最低以太币数量是多少?

  • 32个以太币

18,fallbackreceive 之间有什么区别?

  • fallbackreceive都是特殊的回调函数,用于处理合约中不存在的函数调用和接收以太币。它们之间的区别在于,fallback函数会在调用合约不存在的函数时被触发,而receive函数只用于处理接收以太币。

19,如何向没有payable 函数、receive 或回退的合约发送以太?

  • 通过自毁合约,将自毁的eth发送给目标合约

20, viewpure 之间有什么区别?

  • viewpure都是函数的修饰符,view可以访问合约中的状态变量,不能修改;pure不能访问也不能修改状态变量。

21,访问控制是什么,为什么重要?

  • 访问控制是一种重要的机制,用于限制对智能合约的访问。通过使用访问控制,您可以确保只有经过授权的用户才能执行特定操作或访问敏感信息。这可以帮助保护您的智能合约免受未经授权的访问和攻击。Solidity提供了几种访问控制修饰符,例如publicprivateinternalexternal。这些修饰符用于控制函数和状态变量的可见性和访问权限。

22, uint256 可以存储的最大值是多少?

  • 2^256-1

23,修饰符(modifier)的作用是什么?

  • 增加对函数的限制或者修饰

中等

1, transfer send 之间有什么区别?为什么不应该使用它们?

  • transfersend函数都是用于将以太币从一个地址转移到另一个地址的函数。它们之间的区别在于它们的gas限制不同,这可能会导致一些安全问题。因此,您应该使用call函数来转移以太币,但是会有重入攻击风险。

    (transfer函数的gas限制为2300 gas,这意味着如果接收方合约没有实现fallback函数,或者fallback函数消耗的gas超过了2300,那么转账将失败并回滚所有更改。这可以防止重入攻击,但也可能导致一些问题,例如无法向某些合约发送以太币。
    send函数的gas限制也为2300 gas,但它返回一个布尔值,指示转账是否成功。如果转账失败,它将返回false。但是,如果接收方合约没有实现fallback函数,或者fallback函数消耗的gas超过了2300,那么转账将失败并回滚所有更改。
    由于这些限制,transfer和send函数已经被认为是不安全的,因此不应该使用它们。相反,您应该使用call函数来转移以太币。call函数没有gas限制,可以向任何地址发送以太币,并且可以指定要发送的gas数量。但是,您应该小心使用call函数,因为它可能会导致一些安全问题,例如重入攻击。)

2,代理合约中的存储冲突是什么?

  • 存储冲突是指多个合约尝试访问同一存储位置时发生的问题。当多个合约同时尝试更新同一存储位置时,可能会发生存储冲突,导致数据不一致或合约无法正常工作。

3,在权益证明之前后,block.timestamp 发生了什么变化?

  • 在PoW协议中,block.timestamp表示矿工开始挖掘新块的时间戳。在PoS协议中,block.timestamp表示验证器开始验证新块的时间戳。

4,什么是抢跑(frontrunning)?

  • 抢跑就是抢先在别人的交易的执行前执行,它是通过提交更高的gas费用来达到的

5,以太坊如何确定 EIP-1559 中的 BASEFEE

  • BASEFEE是由以太坊网络根据交易需求和区块大小动态调整的。BASEFEE的计算方式是通过一个名为“基础费用追踪器”的算法来实现的。该算法会根据当前区块的交易需求和区块大小来动态调整BASEFEE,以确保交易能够在合理的时间内得到确认。

6,什么是 commit-reveal 方案,何时使用它?

  • 提交-揭示方案(Commit-Reveal Scheme)是一种用于在区块链上进行投票或竞标的协议。该协议的目的是防止参与者在提交投票或竞标之前查看其他参与者的提交,从而保护投票或竞标的公正性。

7,在什么情况下,abi.encodePacked 可能会产生漏洞?

  • abi.encodePacked可能会产生漏洞,因为它不会在参数之间添加填充,而是将所有参数拼接在一起。这可能会导致哈希碰撞,从而使攻击者能够伪造交易或执行其他恶意操作。例如,如果攻击者知道您使用abi.encodePacked来编码交易数据,他们可以构造一个具有相同哈希值的交易,从而欺骗您的智能合约。

8,AMM 如何定价资产?

  • 通过恒定乘积算法,a * b = k ,兑换 m个a 需要的b数量算法 = k/(a+m) - b ,这里没计算手续费。

9, 函数参数中的 memory 和 calldata 有什么区别?

  • memory:用于声明函数参数将被存储在内存中。内存中的数据只在函数执行期间存在,执行完毕后就被销毁。在函数内部,您可以使用memory关键字来创建临时变量,但是不能在函数之外使用它们。在函数调用期间,函数参数的值将从调用方复制到内存中,并在函数执行完毕后被销毁。
    calldata:用于声明函数参数将被存储在调用数据区域中。调用数据区域是一个不可修改的区域,用于保存函数参数。在函数内部,您可以使用calldata关键字来访问函数参数,但是不能在函数之外使用它们。在函数调用期间,函数参数的值将从调用方复制到调用数据区域中,并在函数执行完毕后被销毁