visual-identity/contracts/democracy/FeeRecycler.sol

110 lines
3.5 KiB
Solidity

pragma solidity ^0.4.21;
import "../common/Controlled.sol";
import "../token/ERC20Token.sol";
import "../token/MiniMeTokenInterface.sol";
import "./FeeCollector.sol";
/**
* @title FeeRecycler
* @author Ricardo Guilherme Schmidt (Status Research & Development GmBH)
* @dev Allow user selecting predefined destinations to where this fees will be invested
*/
contract FeeRecycler is Controlled, FeeCollector {
//allowed democratically choosen destinations
mapping (address => bool) public destinations;
//balances of users
mapping (address => uint256) public balances;
//used for withdrawing lost tokens
uint256 public totalLocked;
//base token
MiniMeTokenInterface public token;
/**
* @notice Constructor defines the unchangable (?) baseToken
* @param _token base token
*/
function FeeRecycler(MiniMeTokenInterface _token) public {
token = _token;
}
/**
* @notice Collect a fee from yourself in your address
* @param _amount to be collected
*/
function collect(uint256 _amount) external {
require(token.transferFrom(msg.sender, address(this), _amount));
balances[msg.sender] += _amount;
totalLocked += _amount;
}
/**
* @notice Collect a fee from someone
* @param _from who allowed collection
* @param _amount to be collected
*/
function collectFrom(address _from, uint256 _amount) external {
require(token.transferFrom(_from, address(this), _amount));
balances[_from] += _amount;
totalLocked += _amount;
}
/**
* @notice Lock a fee in name of someone
* @param _from who would be able to recycle this funds
* @param _amount to be locked
*/
function collectFor(address _from, uint256 _amount) external {
require(token.transferFrom(msg.sender, address(this), _amount));
balances[_from] += _amount;
totalLocked += _amount;
}
/**
* @notice Unlock and approveAndCall
* @param _to Allowed destination to get tokens
* @param _amount that will be transfered
*/
function recycle(address _to, uint256 _amount) external {
require(destinations[_to]);
require(balances[msg.sender] >= _amount);
balances[msg.sender] -= _amount;
totalLocked -= _amount;
token.approveAndCall(_to, _amount, new bytes(0));
}
/**
* @notice Controller should enable destinations to recycle
* @param _destination that would be available to recycle
* @param _allowed users can recycle to this address?
*/
function setDestination(address _destination, bool _allowed)
external
onlyController
{
destinations[_destination] = _allowed;
}
/**
* @notice Withdraw lost tokens in the contract
* @param _token if is base token than can only transfer unlocked amount
* @param _destination address receiving this tokens
* @param _amount the amount to be transfered
*/
function withdraw(ERC20Token _token, address _destination, uint256 _amount)
external
onlyController
{
if (address(_token) == address(token)) {
require(_amount <= _token.balanceOf(address(this)) - totalLocked);
} else if (address(_token) == address(0)) {
require(address(this).balance <= _amount);
}
if (address(_token) != address(0)) {
_token.transfer(_destination, _amount);
} else {
_destination.transfer(_amount);
}
}
}