Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(s08): fix markdown warnings #836

Merged
merged 3 commits into from
Nov 5, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions S08_ContractCheck/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,21 @@ tags:
很多 freemint 的项目为了限制科学家(程序员)会用到 `isContract()` 方法,希望将调用者 `msg.sender` 限制为外部账户(EOA),而非合约。这个函数利用 `extcodesize` 获取该地址所存储的 `bytecode` 长度(runtime),若大于0,则判断为合约,否则就是EOA(用户)。

```solidity
// 利用 extcodesize 检查是否为合约
function isContract(address account) public view returns (bool) {
// extcodesize > 0 的地址一定是合约地址
// 但是合约在构造函数时候 extcodesize 为0
uint size;
assembly {
size := extcodesize(account)
}
return size > 0;
// 利用 extcodesize 检查是否为合约
function isContract(address account) public view returns (bool) {
// extcodesize > 0 的地址一定是合约地址
// 但是合约在构造函数时候 extcodesize 为0
uint size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
```

这里有一个漏洞,就是在合约在被创建的时候,`runtime bytecode` 还没有被存储到地址上,因此 `bytecode` 长度为0。也就是说,如果我们将逻辑写在合约的构造函数 `constructor` 中的话,就可以绕过 `isContract()` 检查。

![](./img/S08-1.png)
![image1](./img/S08-1.png)

## 漏洞例子

Expand Down Expand Up @@ -109,14 +109,14 @@ contract NotContract {

## 预防办法

你可以使用 `(tx.origin == msg.sender)` 来检测调用者是否为合约。如果调用者为 EOA,那么`tx.origin`和`msg.sender`相等;如果它们俩不相等,调用者为合约。
你可以使用 `(tx.origin == msg.sender)` 来检测调用者是否为合约。如果调用者为 EOA,那么`tx.origin`和`msg.sender`相等;如果它们俩不相等,调用者为合约。在[eip-3074](https://eips.ethereum.org/EIPS/eip-3074)中,这样检查合约的方式,会失效。

```
```solidity
function realContract(address account) public view returns (bool) {
return (tx.origin == msg.sender);
}
```

## 总结

这一讲,我们介绍了合约长度检查可以被绕过的漏洞,并介绍预防的方法。如果一个地址的 `extcodesize > 0`,则该地址一定为合约;但如果 `extcodesize = 0`,该地址既可能为 `EOA`,也可能为正在创建状态的合约。
这一讲,我们介绍了合约长度检查可以被绕过的漏洞,并介绍预防的方法。如果一个地址的 `extcodesize > 0`,则该地址一定为合约;但如果 `extcodesize = 0`,该地址既可能为 `EOA`,也可能为正在创建状态的合约。
Loading