|
|
|
interface Receiver{
|
|
|
|
function send_funds() payable external;
|
|
|
|
}
|
|
|
|
|
|
|
|
contract TestWithBug{
|
|
|
|
|
|
|
|
mapping(address => uint) balances;
|
|
|
|
|
|
|
|
modifier nonReentrant(){
|
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw(uint amount) nonReentrant public{
|
|
|
|
require(amount <= balances[msg.sender]);
|
|
|
|
Receiver(msg.sender).send_funds{value: amount}();
|
|
|
|
balances[msg.sender] -= amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw_all() public{
|
|
|
|
uint amount = balances[msg.sender];
|
|
|
|
balances[msg.sender] = 0;
|
|
|
|
Receiver(msg.sender).send_funds{value: amount}();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
contract TestWithoutBug{
|
|
|
|
|
|
|
|
mapping(address => uint) balances;
|
|
|
|
|
|
|
|
modifier nonReentrant(){
|
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw(uint amount) nonReentrant public{
|
|
|
|
require(amount <= balances[msg.sender]);
|
|
|
|
Receiver(msg.sender).send_funds{value: amount}();
|
|
|
|
balances[msg.sender] -= amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw_all() nonReentrant public{
|
|
|
|
uint amount = balances[msg.sender];
|
|
|
|
balances[msg.sender] = 0;
|
|
|
|
Receiver(msg.sender).send_funds{value: amount}();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
contract TestWithBugInternal{
|
|
|
|
|
|
|
|
mapping(address => uint) balances;
|
|
|
|
|
|
|
|
modifier nonReentrant(){
|
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw(uint amount) nonReentrant public{
|
|
|
|
withdraw_internal(amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw_internal(uint amount) internal{
|
|
|
|
require(amount <= balances[msg.sender]);
|
|
|
|
Receiver(msg.sender).send_funds{value: amount}();
|
|
|
|
balances[msg.sender] -= amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw_all() public{
|
|
|
|
withdraw_all_internal();
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw_all_internal() internal {
|
|
|
|
uint amount = balances[msg.sender];
|
|
|
|
balances[msg.sender] = 0;
|
|
|
|
Receiver(msg.sender).send_funds{value: amount}();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
contract TestWithoutBugInternal{
|
|
|
|
|
|
|
|
mapping(address => uint) balances;
|
|
|
|
|
|
|
|
modifier nonReentrant(){
|
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw(uint amount) nonReentrant public{
|
|
|
|
withdraw_internal(amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw_internal(uint amount) internal{
|
|
|
|
require(amount <= balances[msg.sender]);
|
|
|
|
Receiver(msg.sender).send_funds{value: amount}();
|
|
|
|
balances[msg.sender] -= amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw_all() nonReentrant public{
|
|
|
|
withdraw_all_internal();
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw_all_internal() internal {
|
|
|
|
uint amount = balances[msg.sender];
|
|
|
|
balances[msg.sender] = 0;
|
|
|
|
Receiver(msg.sender).send_funds{value: amount}();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
contract TestBugWithPublicVariable{
|
|
|
|
|
|
|
|
mapping(address => uint) public balances;
|
|
|
|
|
|
|
|
modifier nonReentrant(){
|
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw(uint amount) nonReentrant public{
|
|
|
|
withdraw_internal(amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw_internal(uint amount) internal{
|
|
|
|
require(amount <= balances[msg.sender]);
|
|
|
|
Receiver(msg.sender).send_funds{value: amount}();
|
|
|
|
balances[msg.sender] -= amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
contract TestWithBugNonReentrantRead{
|
|
|
|
|
|
|
|
mapping(address => uint) balances;
|
|
|
|
|
|
|
|
modifier nonReentrant(){
|
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
|
|
|
function withdraw(uint amount) nonReentrant public{
|
|
|
|
require(amount <= balances[msg.sender]);
|
|
|
|
Receiver(msg.sender).send_funds{value: amount}();
|
|
|
|
balances[msg.sender] -= amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Simulate a reentrancy that allows to read variable in a potential incorrect state during a reentrancy
|
|
|
|
// This is more likely to impact protocol like reentrancy
|
|
|
|
function read() public returns(uint){
|
|
|
|
uint amount = balances[msg.sender];
|
|
|
|
return amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|