mirror of
https://github.com/status-im/github-oracle.git
synced 2026-08-30 19:31:08 +00:00
abstraction of CollaborationToken and BountyBank
This commit is contained in:
@@ -3,8 +3,17 @@ pragma solidity ^0.4.9;
|
||||
|
||||
contract Bank {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
event Withdrawn(address reciever, uint256 amount);
|
||||
event Deposited(address sender,uint256 value);
|
||||
//allow deposit and call event
|
||||
function deposit() payable {
|
||||
Deposited(msg.sender, msg.value);
|
||||
}
|
||||
|
||||
//withdraw if locked and not paid, updates epoch
|
||||
function withdrawal(address dest, uint amount)
|
||||
internal {
|
||||
if(!dest.send(amount)) throw;
|
||||
Withdrawn(msg.sender, amount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
pragma solidity ^0.4.0;
|
||||
|
||||
/**
|
||||
* Abstract contract used for recieving donations or profits
|
||||
* Withdraw is divided by total tokens each account owns
|
||||
* Unlock period allows transfers
|
||||
* Lock period allow withdraws
|
||||
* Child contract that implement minting should use modifier not_locked in minting function
|
||||
* Inspired by ProfitContainer and Lockable by vDice
|
||||
*
|
||||
* By Ricardo Guilherme Schmidt
|
||||
* Released under GPLv3 License
|
||||
*/
|
||||
|
||||
import "./Bank.sol";
|
||||
import "../management/EpochLocker.sol";
|
||||
import "../token/LockerToken.sol";
|
||||
|
||||
contract CollaborationBank is Bank, EpochLocker {
|
||||
|
||||
LockableToken public token;
|
||||
//used for calculating balance and for checking if account withdrawn
|
||||
uint256 public currentPayEpoch;
|
||||
//stores the balance from the lock time
|
||||
uint256 public epochBalance;
|
||||
//used for hecking if account withdrawn
|
||||
mapping (address => uint) lastPaidOutEpoch;
|
||||
//events
|
||||
event Withdrawn(address tokenHolder, uint256 amountPaidOut);
|
||||
event Deposited(address donator,uint256 value);
|
||||
|
||||
public CollaborationBank(LockableToken _token) EpochLockable(8 minutes,12 minutes){
|
||||
token = _token;
|
||||
}
|
||||
|
||||
//update the balance and payout epoch
|
||||
modifier update_epoch {
|
||||
if(currentPayEpoch < CURRENT_EPOCH) {
|
||||
currentPayEpoch = _token.CURRENT_EPOCH();
|
||||
epochBalance = this.balance;
|
||||
}
|
||||
_;
|
||||
}
|
||||
|
||||
//checks if user already withdrawn
|
||||
modifier not_paid {
|
||||
if (lastPaidOutEpoch[msg.sender] == currentPayEpoch) throw;
|
||||
_;
|
||||
}
|
||||
|
||||
//check overflow in multiply
|
||||
function safeMultiply(uint256 _a, uint256 _b) private {
|
||||
if (!(_b == 0 || ((_a * _b) / _b) == _a)) throw;
|
||||
_;
|
||||
}
|
||||
|
||||
//allow deposit and call event
|
||||
function ()
|
||||
payable {
|
||||
deposit();
|
||||
}
|
||||
|
||||
function setLock(bool _lock){
|
||||
token.setLock(_lock);
|
||||
|
||||
}
|
||||
//withdraw if locked and not paid, updates epoch
|
||||
function withdrawal()
|
||||
external
|
||||
check_lock(true)
|
||||
update_epoch
|
||||
not_paid {
|
||||
uint256 _tokenBalance = token.balanceOf(msg.sender);
|
||||
uint256 _tokenSupply = token.totalSupply();
|
||||
safeMultiply(_tokenBalance, epochBalance);
|
||||
lastPaidOutEpoch[msg.sender] = currentPayEpoch;
|
||||
if (this.balance >= epochBalance || _tokenBalance == 0 || _tokenSupply == 0) throw;
|
||||
super.withdrawal(msg.sender, (_tokenBalance * epochBalance) / _tokenSupply);
|
||||
}
|
||||
|
||||
//if this coin owns tokens of other CollaborationBank, allow withdraw
|
||||
function withdrawalFrom(CollaborationBank _otherCollaborationToken) {
|
||||
_otherCollaborationToken.withdrawal();
|
||||
}
|
||||
|
||||
//return expected payout in lock or estimated when not locked
|
||||
function expectedPayout(address _tokenHolder)
|
||||
external
|
||||
constant
|
||||
returns (uint256 payout) {
|
||||
if (now < NEXT_LOCK) //unlocked, estimate
|
||||
payout = (token.balanceOf(_tokenHolder) * this.balance) / token.totalSupply();
|
||||
else
|
||||
payout = (token.balanceOf(_tokenHolder) * epochBalance) / token.totalSupply();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
contract EpochLocker is Lockable {
|
||||
|
||||
uint256 public creationTime = now;
|
||||
uint256 public unlockedTime = 25 days
|
||||
uint256 public lockedTime = 5 days;
|
||||
uint256 public constant EPOCH_LENGTH = unlockedTime + lockedTime;
|
||||
//current epoch constant formula, recalculated in any contract call
|
||||
uint256 public constant CURRENT_EPOCH = (now - creationTime) / EPOCH_LENGTH + 1;
|
||||
//next lock constant formula, recalculated in any contract call
|
||||
uint256 public constant NEXT_LOCK = (creationTime + CURRENT_EPOCH * unlockedTime) + (CURRENT_EPOCH - 1) * lockedTime;
|
||||
|
||||
|
||||
function EpochLockable(uint256 _unlockedTime, uint256 _lockedTime){
|
||||
unlockedTime = _unlockedTime;
|
||||
lockedTime = _lockedTime;
|
||||
}
|
||||
|
||||
//update lock value if needed or throw if unexpected lock
|
||||
modifier check_lock(bool lockedOnly) {
|
||||
if(lockedOnly){ //method allowed when locked
|
||||
if (NEXT_LOCK < now) { //is locked!
|
||||
if (!lock) setLock(true); //storage says other thing, update it.
|
||||
}
|
||||
else { //is not locked!
|
||||
if (!lock) throw; //unlocked and storage already say so, throw to prevent event flood.
|
||||
setLock(false); //update storage
|
||||
return; //prevent method from running post states.
|
||||
}
|
||||
}else{ //method allowed when unlocked.
|
||||
if (NEXT_LOCK < now) { //is locked!
|
||||
if (lock) throw; //no need to update storage.
|
||||
setLock(true);//update storage
|
||||
return; //prevent method from running post states.
|
||||
}
|
||||
else { //is not locked!
|
||||
if (lock) setLock(false); //storage says other thing, update it.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
import "./Owned.sol";
|
||||
|
||||
contract Lockable {
|
||||
bool public lock = true;
|
||||
event Locked(bool lock);
|
||||
|
||||
fuction setLock(bool _lock) internal {
|
||||
Locked(_lock);
|
||||
lock = _lock;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
pragma solidity ^0.4.0;
|
||||
|
||||
/**
|
||||
* Abstract contract used for recieving donations or profits
|
||||
* Withdraw is divided by total tokens each account owns
|
||||
* Unlock period allows transfers
|
||||
* Lock period allow withdraws
|
||||
* Child contract that implement minting should use modifier not_locked in minting function
|
||||
* Inspired by ProfitContainer and Lockable by vDice
|
||||
*
|
||||
* By Ricardo Guilherme Schmidt
|
||||
* Released under GPLv3 License
|
||||
*/
|
||||
|
||||
import "./AbstractToken.sol";
|
||||
|
||||
contract CollaborationToken is AbstractToken {
|
||||
//creation time, defined when contract is created
|
||||
uint256 public creationTime = now;
|
||||
//time constants, defines epoch size and periods
|
||||
uint256 public constant UNLOCKED_TIME = 25 days;
|
||||
uint256 public constant LOCKED_TIME = 5 days;
|
||||
uint256 public constant EPOCH_LENGTH = UNLOCKED_TIME + LOCKED_TIME;
|
||||
//current epoch constant formula, recalculated in any contract call
|
||||
uint256 public constant CURRENT_EPOCH = (now - creationTime) / EPOCH_LENGTH + 1;
|
||||
//next lock constant formula, recalculated in any contract call
|
||||
uint256 public constant NEXT_LOCK = (creationTime + CURRENT_EPOCH * UNLOCKED_TIME) + (CURRENT_EPOCH - 1) * LOCKED_TIME;
|
||||
//used for calculating balance and for checking if account withdrawn
|
||||
uint256 public currentPayEpoch;
|
||||
//stores the balance from the lock time
|
||||
uint256 public epochBalance;
|
||||
//stores lock state, used for events
|
||||
bool public lock;
|
||||
//used for hecking if account withdrawn
|
||||
mapping (address => uint) lastPaidOutEpoch;
|
||||
//events
|
||||
event Withdrawn(address tokenHolder, uint256 amountPaidOut);
|
||||
event Deposited(address donator,uint256 value);
|
||||
event Locked();
|
||||
event Unlocked();
|
||||
|
||||
//checks if not locked and call event on change
|
||||
modifier not_locked {
|
||||
if (NEXT_LOCK < now) {
|
||||
if (lock) throw;
|
||||
lock = true;
|
||||
Locked();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (lock) {
|
||||
lock = false;
|
||||
Unlocked();
|
||||
}
|
||||
}
|
||||
_;
|
||||
}
|
||||
|
||||
//checks if is locked and call event on change
|
||||
modifier locked {
|
||||
if (NEXT_LOCK < now) {
|
||||
if (!lock){
|
||||
lock = true;
|
||||
Locked();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!lock) throw;
|
||||
lock = false;
|
||||
Unlocked();
|
||||
return;
|
||||
}
|
||||
_;
|
||||
}
|
||||
|
||||
//update the balance and payout epoch
|
||||
modifier update_epoch {
|
||||
if(currentPayEpoch < CURRENT_EPOCH) {
|
||||
currentPayEpoch = CURRENT_EPOCH;
|
||||
epochBalance = this.balance;
|
||||
}
|
||||
_;
|
||||
}
|
||||
|
||||
//checks if user already withdrawn
|
||||
modifier not_paid {
|
||||
if (lastPaidOutEpoch[msg.sender] == currentPayEpoch) throw;
|
||||
_;
|
||||
}
|
||||
|
||||
//check overflow in multiply
|
||||
modifier safe_multiply(uint256 _a, uint256 _b) {
|
||||
if (!(_b == 0 || ((_a * _b) / _b) == _a)) throw;
|
||||
_;
|
||||
}
|
||||
|
||||
//allow deposit and call event
|
||||
function ()
|
||||
payable {
|
||||
Deposited(msg.sender, msg.value);
|
||||
}
|
||||
|
||||
//withdraw if locked and not paid, updates epoch
|
||||
function withdrawal()
|
||||
external
|
||||
locked
|
||||
update_epoch
|
||||
not_paid
|
||||
safe_multiply(balanceOf(msg.sender), epochBalance) {
|
||||
uint256 _currentEpoch = CURRENT_EPOCH;
|
||||
uint256 _tokenBalance = balanceOf(msg.sender);
|
||||
uint256 _totalSupply = totalSupply;
|
||||
if (this.balance == 0 || _tokenBalance == 0) throw;
|
||||
lastPaidOutEpoch[msg.sender] = currentPayEpoch;
|
||||
uint256 amountToPayOut = (_tokenBalance * epochBalance) / _totalSupply;
|
||||
if(!msg.sender.send(amountToPayOut)) {
|
||||
throw;
|
||||
}
|
||||
Withdrawn(msg.sender, amountToPayOut);
|
||||
}
|
||||
|
||||
//if this coin owns tokens of other lockablecoin, allow withdraw
|
||||
function withdrawalFrom(CollaborationToken _otherCollaborationToken) {
|
||||
_otherCollaborationToken.withdrawal();
|
||||
}
|
||||
|
||||
//return expected payout in lock or estimated when not locked
|
||||
function expectedPayout(address _tokenHolder)
|
||||
external
|
||||
constant
|
||||
returns (uint256 payout) {
|
||||
if (now < NEXT_LOCK) //unlocked, estimate
|
||||
payout = (balanceOf(_tokenHolder) * this.balance) / totalSupply;
|
||||
else
|
||||
payout = (balanceOf(_tokenHolder) * epochBalance) / totalSupply;
|
||||
}
|
||||
|
||||
//overwrite not allow transfer during lock
|
||||
function transfer(address _to, uint256 _value)
|
||||
not_locked
|
||||
returns (bool ok) {
|
||||
return super.transfer(_to,_value);
|
||||
}
|
||||
|
||||
//overwrite not allow transfer during lock
|
||||
function transferFrom(address _from, address _to, uint256 _value)
|
||||
not_locked
|
||||
returns (bool ok) {
|
||||
return super.transferFrom(_from,_to,_value);
|
||||
}
|
||||
|
||||
//overwrite not allow transfer during lock
|
||||
function approve(address _spender, uint256 _value)
|
||||
returns (bool ok) {
|
||||
return super.approve(_spender,_value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
pragma solidity ^0.4.0;
|
||||
|
||||
/**
|
||||
* Abstract contract used for recieving donations or profits
|
||||
* Withdraw is divided by total tokens each account owns
|
||||
* Unlock period allows transfers
|
||||
* Lock period allow withdraws
|
||||
* Child contract that implement minting should use modifier not_locked in minting function
|
||||
* Inspired by ProfitContainer and Lockable by vDice
|
||||
*
|
||||
* By Ricardo Guilherme Schmidt
|
||||
* Released under GPLv3 License
|
||||
*/
|
||||
|
||||
import "./AbstractToken.sol";
|
||||
import "../management/Lockable.sol";
|
||||
|
||||
contract LockerToken is AbstractToken, Lockable, Owned {
|
||||
Lockable public locker = this;
|
||||
|
||||
|
||||
function unlinkLocker() only_owner {
|
||||
locker = this;
|
||||
}
|
||||
function linkLocker(Lockable _locker) only_owner {
|
||||
locker = _locker;
|
||||
}
|
||||
function lock(bool _lock) only_owner {
|
||||
setLock(_lock);
|
||||
}
|
||||
|
||||
modifier when_locked(bool value){
|
||||
if (lock != value && locker.lock() != value) throw;
|
||||
_;
|
||||
}
|
||||
|
||||
//overwrite not allow transfer during lock
|
||||
function transfer(address _to, uint256 _value) when_locked(true);
|
||||
returns (bool ok) {
|
||||
return super.transfer(_to,_value);
|
||||
}
|
||||
|
||||
//overwrite not allow transfer during lock
|
||||
function transferFrom(address _from, address _to, uint256 _value)
|
||||
returns (bool ok) when_locked(true) {
|
||||
return super.transferFrom(_from,_to,_value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
pragma solidity ^0.4.9;
|
||||
|
||||
import "lib/ethereans/management/Owned.sol"
|
||||
|
||||
contract BountyBank is Owned {
|
||||
|
||||
enum State {CLOSED, OPEN, CLAIMED};
|
||||
struct Bounty {
|
||||
State state;
|
||||
uint closedAt;
|
||||
mapping (address => int) deposits;
|
||||
mapping (address => int) claimers;
|
||||
uint balance;
|
||||
uint points;
|
||||
}
|
||||
|
||||
mapping (uint => Bounty) bounties;
|
||||
uint count = 0;
|
||||
|
||||
function deposit(int num) payable {
|
||||
if(bounties[num].state != OPEN || msg.value == 0) throw;
|
||||
bounties[num].deposits[msg.sender] += msg.value;
|
||||
bounties[num].balance += msg.value;
|
||||
}
|
||||
|
||||
function withdraw(int num) {
|
||||
uint value = bounties[num].deposits[msg.sender];
|
||||
if(bounties[num].state != OPEN || value == 0) throw;
|
||||
delete bounties[num].deposits[msg.sender];
|
||||
if(!msg.sender.send(value)) throw;
|
||||
}
|
||||
|
||||
function open(uint num) only_owner {
|
||||
if(bounties[num].claimed == true) throw;
|
||||
bounties[num].state = State.OPEN;
|
||||
}
|
||||
|
||||
function setClaimer(uint num, address claimer, uint points) only_owner {
|
||||
if(bounties[num].state == State.CLAIMED) throw;
|
||||
bounties[num].claimers[claimer] += points;
|
||||
bounties[num].points += points;
|
||||
}
|
||||
|
||||
function close(uint num) only_owner {
|
||||
if(bounties[num].state == State.CLAIMED) throw;
|
||||
bounties[num].close = true;
|
||||
bounties[num].closedAt = now;
|
||||
}
|
||||
|
||||
function claim(uint num){
|
||||
if (bounties[num].state == State.OPEN) throw;
|
||||
uint totalPoints = bounties[num].points;
|
||||
if(totalPoints == 0) throw;
|
||||
uint points = bounties[num].claimers[msg.sender];
|
||||
if (points == 0) throw;
|
||||
delete bounties[num].claimers[msg.sender];
|
||||
uint award = (bounties[num].balance / totalPoints)*points;
|
||||
bounties[num].points -= points;
|
||||
bounties[num].balance -= award;
|
||||
if(!msg.sender.send(award)) throw;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,6 +15,7 @@ pragma solidity ^0.4.8;
|
||||
* Released under GPLv3 License
|
||||
*/
|
||||
|
||||
import "lib/ethereans/bank/CollaborationBank.sol";
|
||||
import "lib/ethereans/management/Owned.sol";
|
||||
import "./GitRepositoryI.sol";
|
||||
import "./GitRepositoryToken.sol";
|
||||
@@ -25,6 +26,9 @@ contract GitRepository is GitRepositoryI, Owned {
|
||||
//Address of the oracle, used for github login address lookup
|
||||
GitRepositoryStorage public db;
|
||||
GitRepositoryToken public token;
|
||||
CollaborationBank public donationBank;
|
||||
BountyBank
|
||||
mapping (address=>uint) beers;
|
||||
|
||||
uint256 public subscribers;
|
||||
uint256 public watchers;
|
||||
@@ -37,9 +41,17 @@ contract GitRepository is GitRepositoryI, Owned {
|
||||
_;
|
||||
}
|
||||
|
||||
function () payable {
|
||||
donationBank.deposit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
function GitRepository(uint256 _uid, string _name) {
|
||||
db = new GitRepositoryStorage(_uid,_name);
|
||||
token = new GitRepositoryToken(_name);
|
||||
donationBank = new CollaborationBank(token);
|
||||
token.linkLocker(donationBank);
|
||||
}
|
||||
|
||||
//checks if a commit is already claimed
|
||||
|
||||
@@ -15,10 +15,10 @@ pragma solidity ^0.4.8;
|
||||
* Released under GPLv3 License
|
||||
*/
|
||||
|
||||
import "lib/ethereans/token/CollaborationToken.sol";
|
||||
import "lib/ethereans/token/LockerToken.sol";
|
||||
import "lib/ethereans/management/Owned.sol";
|
||||
|
||||
contract GitRepositoryToken is CollaborationToken, Owned {
|
||||
contract GitRepositoryToken is LockerToken {
|
||||
|
||||
function GitRepositoryToken(string _repository) {
|
||||
setAttribute("name", _repository);
|
||||
@@ -27,7 +27,7 @@ contract GitRepositoryToken is CollaborationToken, Owned {
|
||||
}
|
||||
|
||||
function mint(address _who, uint256 _value)
|
||||
only_owner {
|
||||
only_owner when_locked(false)) {
|
||||
_mint(_who,_value);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user