forked from Giveth/minime
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
security: make
MiniMeToken
inherit ReentrancyGuard
If a `MiniMeToken` has a `TokenController` configured, it can intercept every transfer using the `onTransfer` callback and reenter the `MiniMeToken` contract. This is a reentrancy vulnerablity as a malicious `TokenController` has access to the `MiniMeToken` `balances` and it privileged to perform transfers. Unfortunately, simply using the CEI-pattern as done in #24 isn't sufficient, because the reentrancy can be done non-recursively, resulting in no error and a possible double spent issue. To prevent this vulnerablity, this commit introduces OZ's `ReentrancyGuard` and makes `MiniMeToken` inherit it. This gives us access to the `nonReentrant` modifer that is attached to every transfer function. The commit also introduces a test that proves that the contract reverts in case of a reentrancy attempt. Closes: #17
- Loading branch information
Showing
3 changed files
with
70 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
pragma solidity ^0.8.0; | ||
|
||
import { TokenController } from "../contracts/TokenController.sol"; | ||
import { MiniMeToken } from "../contracts/MiniMeToken.sol"; | ||
|
||
contract AttackerController is TokenController { | ||
address public attackerEOA; | ||
|
||
constructor(address _attackerEOA) { | ||
attackerEOA = _attackerEOA; | ||
} | ||
|
||
function proxyPayment(address _owner) public payable override returns (bool) { | ||
return true; | ||
} | ||
|
||
function onTransfer(address _from, address _to, uint256 _amount) public override returns (bool) { | ||
// `AttackerController` intercepts transfer and performs `transferFrom` to `attackerEOA` | ||
if (_to != attackerEOA) { | ||
uint256 balance = MiniMeToken(payable(msg.sender)).balanceOfAt(_from, block.number); | ||
MiniMeToken(payable(msg.sender)).transferFrom(_from, attackerEOA, balance); | ||
} | ||
return true; | ||
} | ||
|
||
function onApprove(address _owner, address _spender, uint256 _amount) public pure override returns (bool) { | ||
Check warning on line 27 in test/AttackerController.sol GitHub Actions / lint
Check warning on line 27 in test/AttackerController.sol GitHub Actions / lint
|
||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters