mirror of
https://github.com/status-im/github-oracle.git
synced 2026-08-30 11:21:07 +00:00
142 lines
4.6 KiB
Solidity
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|