Back

blockchain - solidity - exercise 练习题

发布时间: 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