Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
noReentrancy modifier implementation sample (executable on Remix)
pragma solidity ^0.4.24;
/**
* 攻撃される銀行
*/
contract Bank {
/**
* リエントランシ対策
*
* 関数実行中なら再度実行させない。
*/
modifier noReentrancy () {
require(!locked);
locked = true;
_;
locked = false;
}
bool locked = false;
/**
* 引き出し可能な残高
*/
uint256 public balance = 0;
/**
* 引き出し
*/
function withdraw (uint256 amount) public noReentrancy {
// 1. 実行条件チェック
require(amount <= balance);
// 2. 振込
Attacker(msg.sender).fallback(amount);
// 3. 残高更新
balance -= amount;
}
/**
* 預金
*/
function deposit(uint256 amount) public {
balance += amount;
}
}
/**
* 攻撃者
*/
contract Attacker {
Bank bank;
/**
* 保有する資金
*/
uint256 public balance = 0;
/**
* 一度の引き出しで振込された回数
*/
uint256 public count = 0;
/**
* 一度の引き出しのログ
*/
event Log(uint256 count, uint256 balance, uint256 bankBalance);
constructor () public {
// バンクを新規作成
bank = new Bank();
// 10000 wei 預金
bank.deposit(10000);
}
/**
* 送金時に実行される.
* amount を受け取る.
*/
function fallback (uint256 amount) public {
count++;
balance += amount;
emit Log(count, balance, bank.balance());
// 引き出し可能残高の10倍でやめてあげる.
if (count >= 10) {
count = 0;
return;
}
// 着金時に再度引き出しすると...
bank.withdraw(amount);
}
/**
* 攻撃開始
*/
function attack() public {
withdraw(10000);
}
/**
* Bankから引き出し
*/
function withdraw(uint256 amount) public {
bank.withdraw(amount);
}
/**
* Bankに預金
*/
function deposit(uint256 amount) public {
bank.deposit(amount);
}
/**
* Bankの残高チェック
*/
function bankBalance() public view returns (uint256) {
return bank.balance();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.