发布时间: 2024-04-04 22:59:00
refer to:
https://github.com/RareSkills/Solidity-Exercises
不错的练习题,下载后, forge test 就可以直接看结果。
1. 进入到对应的目录
2. forge test
3. 看源代码中的注释,说明和代码结构
4. 修改代码
5. forge test,通过即可。
ok AccessModifer
ok Add
BasicBank
BasicBankV2
BasicStorage OK. 设置 getter, setter
BlockNumber OK。 让对应方法不要在同一个block内访问两次
CodeSize OK . 多定义一些乱七八糟的方法即可。我定义了7个。 https://ethereum.org/en/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/ 这个文章写了如何优化contract code size
CrossContract OK. 寻找两个contract中,price()返回值 低的那个值。 知识点:三元表达式,contract(address) 获得实例。
Decoder OK abi.decode(bytes_data, (type1, type2));
DeployContract
Deployer
Distribute OK。 for 循环, to_address.call {value: xx } (""); 发送eth
DistributeV2 TODO 没弄明白。。。
Divide OK solidity中不支持float. 都是整数操作。所以需要调整一下各个数的计算先后顺序。
Donations: OK. 使用mapping (跟js一样的)
Emitter OK. 实现emit简单,难点在于理解 em.expectEmit, 该方法最多测试4个emit的参数,而且需要: 1. expectEmit, 2. 调用写在Test中的emit 3. 调用真实的contract.some_method_which_triggered_event. 太绕了。
Encoder OK. abi.encode(var1, var2);
Enum OK 考察 enum与uint的类型转换。 要明确转换,例如 MyEnum(1) == MyOne 或者 1 == int(MyOne)
EverythingWorks ... 这个似乎不是题目。直接跳过。
Exponent OK 返回N次方。 写个for循环就可以了。
Fibonacci OK fibonacci 数组是 : 0, 1, 1, 2, 3, 5, 8, 13 ... 前两位是固定的0,1 , 后面开始 第n位 = (n - 1)位的值 + (n - 2)位的值 . 这里需要使用数组。另外,console2 不能直接打印数组,需要做一个循环才能打印里面的元素.
FilterOddNumbers OK. 操作数组。odd奇数,even 偶数。这个题目要求去掉某个数组中的奇数,并且返回一个数组。
FizzBuzz OK
IdiotBetting
IfStatement OK 。 太简单了吧,应该叫三元表达式
Immutable OK. 考察immutable关键字。只能在constructor中被修改,不能在其他方法中修改。否则编译器报错。
InheritanceOverride 考察继承
InsertInArray OK. 特别简单。 array[1] = 3; 然后 myContract.array(1) 就是调用。记得: 为array生成的getter是需要参数的,该参数就是element index. 例如 myContract.myArray(3) 表示获得myContract的 public member myArray 的 index = 3 的元素。 具体参考:
https://ethereum.stackexchange.com/questions/60489/why-is-there-a-difference-between-a-public-array-and-a-function-which-returns-it
IsPrime OK. 实现质数,考察for 循环, continue/break
IsSorted OK. 判断某个数组是否是升序排序
Keccak 没搞明白。
ListOfNumbers OK. 自己写一个对数组进行操作(排序的)小函数
Mean OK
MultiInheritance OK
NestedArray OK
NestedMapping OK。 用自己idea方式实现的
NotEnough OK. 使用require
OneWeekLockup OK. 使用require, block.timestamp, 1 weeks, 7 days 作为时间戳的计算,uint256 作为最终计算单位。to.call { value: xx }(""); 作为发送ETH的方法
OriginVsSender 基本OK,不过没明白UT的机制。
1. tx.origin 永远不变
2. msg.sender 会在tx chain 中发生变化。
3. vm.startPrank(address1, address2) 表示,从现在开始往后,所有的tx的 tx.origin都是address2, (address1) 自然就是msg.sender)
Owner OK. 考察modifier 的声明和使用。
PriceIsRight OK. 秒过。
PublicFunction OK . 考察public function的使用。其实改成external一样可以通过UT的。
PublicVariable OK. 记得variable只有public , 没有external这一说。
PureVsView OK. 特别简单。让代码编译通过即可。查看pure 与 view的区别(pure跟链上状态无关,读都不读)
Receive OK. 每个可以接收ETH的contract都要求有个receive.
调用方式: receive(): address(myContract).call { value: 1 ether } ("");
普通payable函数: myContract.theMethodName { value: 1 ether } ();
查看balance的方式: address(this).balance;
ReducingPayout
SelfDestroyer
SpecialNumbers OK. mapping的使用。
Stack OK。 实现一个stack.
StudentDB OK. 考察使用struct ( 就是个hash, 不能用new )
SumArray OK 计算array中的元素的和
Super OK 使用super关键字。 还可以看到virtual
TicTacToe OK. 考察循环。逻辑就是画圈圈。横,竖,斜 只要有3个连在一起的,就算赢
TimelockEscrow 基本OK。
escrow: 托管。
buyer: 充值后,3天内可以随时取。 seller 3天后才能取。 owner是seller.
同时只能存在一个托管。
基本OK了。重点在于require blocktime的使用. 细节没看明白。感觉题目过于啰嗦。
prank, startPrank 见这个 cheatcode:
https://book.getfoundry.sh/cheatcodes/prank
TripleNestedMapping OK. 关键点在于:mapping(string => mapping(uint256 => mapping(uint256 => bool))) users;
另外,需要知道在普通的function中无法创建动态mapping ,只能在function中操作contract member的mapping.
Tupledore 没弄明白,应该是需要struct + assembly 的知识。我看到assembly就贵了。。。555
Typecast 没弄明白如何调用。 从uint160 可以转换到 address, 例如 address(uint160(msg.value)) , 但是uint256, uint128就不可以
unchecked : OK 为了节省gas, 从而不检查 overflow , underflow . 例如 :
function sub(uint a, uint b )returns (uint) ,该函数要做减法,返回的都是unsigned int (正数),那么正常的时候,solidity都会去判断的(是否是负数), 例如:
Ran 1 test for test/Unchecked.t.sol:UncheckedTest
[FAIL. Reason: panic: arithmetic underflow or overflow (0x11)] testSub() (gas: 6281)
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 249.50µs (27.70µs CPU time)
那么使用了uncheck, 运行时就不会报这个错误。
WhoCalledMe OK. msg.sender的使用
Withdraw ok
Back