Files

142 lines
4.6 KiB
Solidity

pragma solidity ^0.4.11;
import "../token/ERC23.sol";
import "../token/MiniMeToken.sol";
/**
* @title TokenBank
* @author Ricardo Guilherme Schmidt
* Abstract contract for deposit and withdraw of ETH and ERC20/23 Tokens, with MiniMe token support.
**/
contract TokenBank is ERC23Receiver, ApproveAndCallFallBack {
event Withdrawn(address token, address reciever, uint amount);
event Deposited(address token, address sender, uint value);
mapping (address => mapping (address => uint)) public deposits;
mapping (address => uint) public tokenBalances;
address[] public tokens;
uint public nonce;
/**
* @notice deposit ether in bank
* @param _data might be used by child implementations
**/
function depositEther(bytes _data) payable {
_deposited(msg.sender, msg.value, 0x0, _data);
}
/**
* @notice deposit a ERC20 token. The amount of deposit is the allowance set to this contract.
* @param _token the token contract address
* @param _data might be used by child implementations
**/
function depositToken(address _token, bytes _data){
address sender = msg.sender;
uint amount = ERC20(_token).allowance(sender, this);
deposit(sender, amount, _token, _data);
}
/**
* @notice deposit a ERC20 token. The amount of deposit is the allowance set to this contract.
* @param _token the token contract address
* @param _data might be used by child implementations
**/
function deposit(address _from, uint256 _amount, address _token, bytes _data) {
if(_from == address(this)) return;
uint _nonce = nonce;
ERC20 token = ERC20(_token);
if(!token.transferFrom(_from, this, _amount)) throw;
if(nonce == _nonce){ //ERC23 not executed _deposited tokenFallback by
_deposited(_from, _amount, _token, _data);
}
}
/**
* @notice watches for balance in a token contract
* @param _tokenAddr the token contract address
**/
function watch(address _tokenAddr) {
uint oldBal = tokenBalances[_tokenAddr];
uint newBal = ERC20(_tokenAddr).balanceOf(this);
if(newBal > oldBal){
_deposited(0x0,newBal-oldBal,_tokenAddr,new bytes(0));
}
}
/**
* @notice refunds a deposit.
* @param _token the token you want to refund
**/
function refund(address _token) returns (bool) {
address _sender = msg.sender;
_withdraw(_token, _sender, deposits[_sender][_token], _sender);
return true;
}
/**
* @notice ERC23 Token fallback
* @param _from address incoming token
* @param _amount incoming amount
**/
function tokenFallback(address _from, uint _amount, bytes _data) {
_deposited(_from, _amount, msg.sender, _data);
}
/**
* @notice Called MiniMeToken approvesAndCall to this contract, calls deposit.
* @param _from address incoming token
* @param _amount incoming amount
* @param _token the token contract address
* @param _data (might be used by child classes)
*/
function receiveApproval(address _from, uint256 _amount, address _token, bytes _data){
deposit(_from, _amount, _token, _data);
}
/**
* @dev register the deposit to refundings
**/
function _deposited(address _sender, uint _amount, address _tokenAddr, bytes _data)
internal {
Deposited(_tokenAddr, _sender, _amount);
nonce++;
if(_tokenAddr != 0x0){
if(tokenBalances[_tokenAddr] == 0){
tokens.push(_tokenAddr);
tokenBalances[_tokenAddr] = ERC20(_tokenAddr).balanceOf(this);
}else{
tokenBalances[_tokenAddr] += _amount;
}
}
deposits[_sender][_tokenAddr] += _amount;
}
/**
* @dev withdraw token amount to dest
**/
function _withdraw(address _tokenAddr, address _dest, uint _amount, address _consumer)
internal returns (bool){
Withdrawn(_tokenAddr, _dest, _amount);
if(_consumer != 0x0) {
require(deposits[_consumer][_tokenAddr] >= _amount);
deposits[_consumer][_tokenAddr] -= _amount;
}
if(_tokenAddr == 0x0){
_dest.transfer(_amount);
return true;
} else {
tokenBalances[_tokenAddr] -= _amount;
ERC20 token = ERC20(_tokenAddr);
token.approve(this, 0);
if(token.approve(this, _amount)){
return token.transferFrom(this, _dest, _amount);
}
}
}
}