mirror of
https://github.com/status-im/github-oracle.git
synced 2026-08-27 09:51:10 +00:00
commiteth issuebank
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
import "../bank/TokenBank.sol";
|
||||
import "../management/Controlled.sol";
|
||||
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
/**
|
||||
* @title IssueBank
|
||||
* @author Ricardo Guilherme Schmidt <3esmit>
|
||||
* Enable deposits to be withdrawn by points recievers
|
||||
**/
|
||||
contract IssueBank is Controlled, TokenBank {
|
||||
enum State {OPEN, REFUND, REWARD, FINALIZED }
|
||||
State public state;
|
||||
uint public points;
|
||||
uint public refundNonce;
|
||||
mapping (address => Reward) public rewards;
|
||||
address public repoOwner;
|
||||
|
||||
struct Reward {
|
||||
bool active;
|
||||
uint points;
|
||||
}
|
||||
|
||||
modifier onlyRepoOwner{
|
||||
if (msg.sender != repoOwner) throw;
|
||||
_;
|
||||
}
|
||||
|
||||
function IssueBank(address _repoOwner) {
|
||||
repoOwner = _repoOwner;
|
||||
state = State.OPEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice deposit ether in bank
|
||||
**/
|
||||
function () payable {
|
||||
deposit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice claim all watched tokens based on user points;
|
||||
*/
|
||||
function reward() {
|
||||
_reward(tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Useful if some token is throwing on transfer.
|
||||
* @param _tokens the array of desired watched tokens. If token is not watched it will ignore..
|
||||
*/
|
||||
function rewardEthAnd(address[] _tokens) {
|
||||
_reward(_tokens);
|
||||
}
|
||||
/**
|
||||
* @notice only contoller may set reward to a single address.
|
||||
* @param _claimer the beneficiary
|
||||
* @param _points amount of points
|
||||
**/
|
||||
function setReward(address _claimer, uint _points) onlyController {
|
||||
if(state != State.OPEN) throw;
|
||||
if(rewards[_claimer].active) throw;
|
||||
rewards[_claimer].points = _points;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice only contoller may set reward to an array of addresses.
|
||||
* @param _claimers the array of beneficiaries
|
||||
* @param _points the array of amount of points
|
||||
**/
|
||||
function setReward(address[] _claimers, uint[] _points) onlyController {
|
||||
if(state != State.OPEN) throw;
|
||||
uint len = _claimers.length;
|
||||
for (uint i = 0; i < len; i++){
|
||||
address _claimer = _claimers[i];
|
||||
if(rewards[_claimer].active) throw;
|
||||
rewards[_claimer].points = _points[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice only the repo owner may confirm reward of addresses
|
||||
* @param _claimers array of addresses that are eligible to reward
|
||||
**/
|
||||
function confirm(address [] _claimers) onlyRepoOwner {
|
||||
uint len = _claimers.length;
|
||||
uint nPoints = 0;
|
||||
for (uint i = 0; i < len; i++){
|
||||
address _claimer = _claimers[i];
|
||||
if(rewards[_claimer].active) throw;
|
||||
rewards[_claimer].active = true;
|
||||
nPoints += rewards[_claimer].points;
|
||||
}
|
||||
points += nPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice only the repo owner may confirm reward of single address
|
||||
* @param _claimer the address that is eligible to reward
|
||||
**/
|
||||
function confirm(address _claimer) onlyRepoOwner {
|
||||
if(rewards[_claimer].active) throw;
|
||||
rewards[_claimer].active = true;
|
||||
points += rewards[_claimer].points;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice only repo owner can close deposits and start reward or refund
|
||||
* If no points confirmed the system will start refund, otherwise reward
|
||||
*/
|
||||
function close() onlyRepoOwner {
|
||||
if(state != State.OPEN) throw;
|
||||
state = points > 0 ? State.REWARD : State.REFUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Set a new list of tokens to be rewarded.
|
||||
* User can still reward tokens not listed if he calls `rewardEthAnd(address[]`
|
||||
* providing a list including unlisted tokens.
|
||||
* To list a new token use `watch(address)` that will update the balance aswell
|
||||
* @param _tokens the list of new tokens.
|
||||
*
|
||||
*/
|
||||
function setTokenList(address[] _tokens) onlyController {
|
||||
tokens = _tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Withdraw tokens
|
||||
* only avaliable in REWARD state and all points claimed.
|
||||
*
|
||||
**/
|
||||
function withdraw(address[] _tokens) onlyController {
|
||||
if(state != State.FINALIZED) throw;
|
||||
uint len = _tokens.length;
|
||||
uint amount;
|
||||
for (uint i = 0; i< len; i++){
|
||||
ERC20 token = ERC20(_tokens[i]);
|
||||
amount = token.balanceOf(this);
|
||||
if(amount > 0) withdraw(token, repoOwner, amount);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @notice only controller may kill contract and send all remaining eth and tokens to repo owner
|
||||
* This can only be done when all rewards are claimed.
|
||||
**/
|
||||
function kill() onlyController {
|
||||
if(state != State.FINALIZED) throw;
|
||||
withdraw(tokens);
|
||||
selfdestruct(repoOwner);
|
||||
}
|
||||
/**
|
||||
* @dev overwriten to only allow refund in correct state.
|
||||
**/
|
||||
function refund(uint depositNonce) returns (bool) {
|
||||
if(state != State.REFUND) throw;
|
||||
refundNonce++;
|
||||
if(refundNonce == nonce) state = State.FINALIZED;
|
||||
return super.refund(depositNonce);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev register the deposit to refundings
|
||||
**/
|
||||
function _deposited(address _tokenAddr, address _sender, uint _amount)
|
||||
internal returns (uint receipt) {
|
||||
if(state != State.OPEN) throw;
|
||||
return super._deposited(_tokenAddr, _sender, _amount);
|
||||
}
|
||||
|
||||
function _reward(address[] _tokens) internal {
|
||||
if(state != State.REWARD) throw;
|
||||
address dest = msg.sender;
|
||||
if (!rewards[dest].active) throw;
|
||||
uint _reward_points = rewards[dest].points;
|
||||
delete rewards[dest];
|
||||
if (_reward_points == 0) throw;
|
||||
uint reward;
|
||||
uint len = _tokens.length;
|
||||
for (uint i = 0; i< len; i++){
|
||||
address tokenAddr = _tokens[i];
|
||||
reward = tokenBalances[tokenAddr];
|
||||
if (reward > 0) reward = calculeReward(reward, _reward_points);
|
||||
if (reward > 0) withdraw(tokenAddr, dest, reward);
|
||||
}
|
||||
reward = this.balance;
|
||||
if (reward > 0) reward = (reward / points) * _reward_points;
|
||||
if (reward > 0) withdraw(dest, reward);
|
||||
points -= _reward_points;
|
||||
if(points == 0) state = State.FINALIZED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev amplifies small token balances to divide points
|
||||
**/
|
||||
function calculeReward(uint _balance, uint _reward_points) internal constant returns (uint reward) {
|
||||
uint amplifier = 1;
|
||||
while(_balance * amplifier < points){
|
||||
amplifier *= 10;
|
||||
}
|
||||
reward = (((_balance*amplifier) / points) * _reward_points) / amplifier;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @title IssueBankFactory
|
||||
* @author Ricado Guilherme Schmidt <3esmit>
|
||||
**/
|
||||
contract IssueBankFactory {
|
||||
|
||||
/**
|
||||
* @notice creates new IssueBank with repoOwner as moderator
|
||||
**/
|
||||
function create(address repoOwner) returns(IssueBank){
|
||||
IssueBank bank = new IssueBank(repoOwner);
|
||||
bank.changeController(msg.sender);
|
||||
return bank;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
import "../token/ERC23.sol";
|
||||
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
/**
|
||||
* @title TokenBank
|
||||
* @author Ricardo Guilherme Schmidt <3esmit>
|
||||
* Abstract contract for deposit and withdraw of ETH and ERC20/23 Tokens
|
||||
**/
|
||||
contract TokenBank is ERC23Receiver, ApproveAndCallFallBack {
|
||||
|
||||
event Withdrawn(address reciever, uint amount);
|
||||
event Deposited(address sender, uint value);
|
||||
event TokenWithdrawn(address token, address reciever, uint amount);
|
||||
event TokenDeposited(address token, address sender, uint value);
|
||||
|
||||
mapping (uint => Deposit) public deposits;
|
||||
mapping (address => uint) public tokenBalances;
|
||||
address[] public tokens;
|
||||
|
||||
uint public nonce;
|
||||
|
||||
struct Deposit {
|
||||
address sender;
|
||||
address token;
|
||||
uint amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice deposit ether in bank
|
||||
* @return reciept that can be used for refund
|
||||
**/
|
||||
function deposit() payable returns (uint receipt) {
|
||||
address sender = msg.sender;
|
||||
uint amount = msg.value;
|
||||
if(amount > 0){
|
||||
return _deposited(0x0, sender, amount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice deposit a ERC20 token. The amount of deposit is the allowance set to this contract.
|
||||
* @param _tokenAddr the token contract address
|
||||
* @return reciept that can be used for refund
|
||||
**/
|
||||
function tokenDeposit(address _tokenAddr) returns (uint reciept) {
|
||||
address sender = msg.sender;
|
||||
ERC20 token = ERC20(_tokenAddr);
|
||||
uint amount = token.allowance(sender, this);
|
||||
if(amount == 0) throw;
|
||||
uint _nonce = nonce;
|
||||
if(!token.transferFrom(sender, this, amount)) throw;
|
||||
if(!token.approve(this, amount)) throw;
|
||||
if(nonce == _nonce){
|
||||
reciept = _deposited(_tokenAddr, sender, amount);
|
||||
}else{
|
||||
reciept = _nonce; //ERC23 executed _deposited tokenFallback by
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice watches for balance in a token contract
|
||||
* @param _tokenAddr the token contract address
|
||||
**/
|
||||
function watch(address _tokenAddr){
|
||||
bool neverSeen = false;
|
||||
if(tokenBalances[_tokenAddr] == 0) neverSeen = true;
|
||||
uint amount = ERC20(_tokenAddr).balanceOf(this);
|
||||
if(amount > 0){
|
||||
if(!ERC20(_tokenAddr).approve(this, amount)) throw;
|
||||
if(neverSeen) tokens.push(_tokenAddr);
|
||||
tokenBalances[_tokenAddr] = amount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice refunds a deposit.
|
||||
* @param _nonce the reciept you want to refund
|
||||
**/
|
||||
function refund(uint _nonce) returns (bool) {
|
||||
if(msg.sender != deposits[_nonce].sender) throw;
|
||||
uint amount = deposits[_nonce].amount;
|
||||
address token = deposits[_nonce].token;
|
||||
delete deposits[_nonce];
|
||||
if(token == 0x0){
|
||||
withdraw(msg.sender,amount);
|
||||
} else {
|
||||
withdraw(ERC20(token), msg.sender, amount);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice ERC23 Token fallback
|
||||
* @param _from address incoming token
|
||||
* @param _amount incoming amount
|
||||
**/
|
||||
function tokenFallback(address _from, uint _amount, bytes) {
|
||||
_deposited(msg.sender, _from, _amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Called MiniMeToken approvesAndCall to this contract
|
||||
* @param _from address incoming token
|
||||
* @param _amount incoming amount
|
||||
* @param _token the token contract address
|
||||
*/
|
||||
function receiveApproval(address _from, uint256 _amount, address _token, bytes){
|
||||
_deposited(_token, _from, _amount);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @dev register the deposit to refundings
|
||||
**/
|
||||
function _deposited(address _tokenAddr, address _sender, uint _amount)
|
||||
internal returns (uint receipt) {
|
||||
if(_tokenAddr != 0x0){
|
||||
TokenDeposited(_tokenAddr, _sender, _amount);
|
||||
if(tokenBalances[_tokenAddr] == 0){
|
||||
tokens.push(_tokenAddr);
|
||||
tokenBalances[_tokenAddr] = ERC20(_tokenAddr).balanceOf(this);
|
||||
}else{
|
||||
tokenBalances[_tokenAddr] += _amount;
|
||||
}
|
||||
}else{
|
||||
Deposited(_sender, _amount);
|
||||
}
|
||||
receipt = nonce;
|
||||
nonce++;
|
||||
deposits[receipt] = Deposit({sender: _sender, amount: _amount, token: _tokenAddr});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @dev withdraw amount wei to dest
|
||||
**/
|
||||
function withdraw(address _dest, uint _amount)
|
||||
internal {
|
||||
_dest.transfer(_amount);
|
||||
Withdrawn(msg.sender, _amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev withdraw token amount to dest
|
||||
**/
|
||||
function withdraw(address _tokenAddr, address _dest, uint _amount)
|
||||
internal {
|
||||
if(!ERC20(_tokenAddr).transferFrom(this, _dest, _amount)) throw;
|
||||
tokenBalances[_tokenAddr] -= _amount;
|
||||
TokenWithdrawn(_tokenAddr, _dest, _amount);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user