From 1c408aefe9020eb4f9d341c66a0628233d97755f Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Fri, 24 Mar 2017 03:34:31 +0000 Subject: [PATCH 1/4] abstraction of CollaborationToken and BountyBank --- contracts/lib/ethereans/bank/Bank.sol | 17 +- .../lib/ethereans/bank/CollaborationBank.sol | 98 +++++++++++ .../lib/ethereans/management/EpochLocker.sol | 44 +++++ .../lib/ethereans/management/Lockable.sol | 14 ++ .../ethereans/token/CollaborationToken.sol | 158 ------------------ contracts/lib/ethereans/token/LockerToken.sol | 49 ++++++ contracts/src/BountyBank.sol | 63 +++++++ .../{AbstractBounty.sol => GitBountyBank.sol} | 0 .../src/git-repository/GitRepository.sol | 12 ++ .../src/git-repository/GitRepositoryToken.sol | 6 +- 10 files changed, 296 insertions(+), 165 deletions(-) create mode 100644 contracts/lib/ethereans/bank/CollaborationBank.sol create mode 100644 contracts/lib/ethereans/management/EpochLocker.sol create mode 100644 contracts/lib/ethereans/management/Lockable.sol delete mode 100644 contracts/lib/ethereans/token/CollaborationToken.sol create mode 100644 contracts/lib/ethereans/token/LockerToken.sol create mode 100644 contracts/src/BountyBank.sol rename contracts/src/{AbstractBounty.sol => GitBountyBank.sol} (100%) diff --git a/contracts/lib/ethereans/bank/Bank.sol b/contracts/lib/ethereans/bank/Bank.sol index fa27df6..e12081d 100644 --- a/contracts/lib/ethereans/bank/Bank.sol +++ b/contracts/lib/ethereans/bank/Bank.sol @@ -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); + } } \ No newline at end of file diff --git a/contracts/lib/ethereans/bank/CollaborationBank.sol b/contracts/lib/ethereans/bank/CollaborationBank.sol new file mode 100644 index 0000000..b41ed74 --- /dev/null +++ b/contracts/lib/ethereans/bank/CollaborationBank.sol @@ -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(); + } + + +} diff --git a/contracts/lib/ethereans/management/EpochLocker.sol b/contracts/lib/ethereans/management/EpochLocker.sol new file mode 100644 index 0000000..1d25737 --- /dev/null +++ b/contracts/lib/ethereans/management/EpochLocker.sol @@ -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. + } + } + } + + +} \ No newline at end of file diff --git a/contracts/lib/ethereans/management/Lockable.sol b/contracts/lib/ethereans/management/Lockable.sol new file mode 100644 index 0000000..eae6ef9 --- /dev/null +++ b/contracts/lib/ethereans/management/Lockable.sol @@ -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; + } + +} \ No newline at end of file diff --git a/contracts/lib/ethereans/token/CollaborationToken.sol b/contracts/lib/ethereans/token/CollaborationToken.sol deleted file mode 100644 index 6a44312..0000000 --- a/contracts/lib/ethereans/token/CollaborationToken.sol +++ /dev/null @@ -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); - } - -} diff --git a/contracts/lib/ethereans/token/LockerToken.sol b/contracts/lib/ethereans/token/LockerToken.sol new file mode 100644 index 0000000..89425b9 --- /dev/null +++ b/contracts/lib/ethereans/token/LockerToken.sol @@ -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); + } + +} diff --git a/contracts/src/BountyBank.sol b/contracts/src/BountyBank.sol new file mode 100644 index 0000000..ef04915 --- /dev/null +++ b/contracts/src/BountyBank.sol @@ -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; + } + + } \ No newline at end of file diff --git a/contracts/src/AbstractBounty.sol b/contracts/src/GitBountyBank.sol similarity index 100% rename from contracts/src/AbstractBounty.sol rename to contracts/src/GitBountyBank.sol diff --git a/contracts/src/git-repository/GitRepository.sol b/contracts/src/git-repository/GitRepository.sol index cf15a3a..75ced84 100644 --- a/contracts/src/git-repository/GitRepository.sol +++ b/contracts/src/git-repository/GitRepository.sol @@ -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 diff --git a/contracts/src/git-repository/GitRepositoryToken.sol b/contracts/src/git-repository/GitRepositoryToken.sol index 7b7a9c6..1cb70ff 100644 --- a/contracts/src/git-repository/GitRepositoryToken.sol +++ b/contracts/src/git-repository/GitRepositoryToken.sol @@ -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); } From 3c461c5bfe3107923a13270f7037854f1ae8ca36 Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Sat, 25 Mar 2017 16:39:23 +0000 Subject: [PATCH 2/4] fixed code errors --- .../lib/ethereans/bank/CollaborationBank.sol | 12 ++++------- .../lib/ethereans/management/EpochLocker.sol | 21 ++++++++++++------- .../lib/ethereans/management/Lockable.sol | 2 +- .../token/JustifiedCollaborationToken.sol | 5 ++--- contracts/lib/ethereans/token/LockerToken.sol | 18 ++++++---------- contracts/src/GitBountyBank.sol | 11 +++++----- contracts/src/GitHubIssues.sol | 10 ++++----- contracts/src/GitHubOracle.sol | 2 +- .../src/{ => git-repository}/BountyBank.sol | 21 ++++++++++--------- .../src/git-repository/GitRepository.sol | 10 ++++----- .../src/git-repository/GitRepositoryToken.sol | 2 +- 11 files changed, 56 insertions(+), 58 deletions(-) rename contracts/src/{ => git-repository}/BountyBank.sol (75%) diff --git a/contracts/lib/ethereans/bank/CollaborationBank.sol b/contracts/lib/ethereans/bank/CollaborationBank.sol index b41ed74..91031cd 100644 --- a/contracts/lib/ethereans/bank/CollaborationBank.sol +++ b/contracts/lib/ethereans/bank/CollaborationBank.sol @@ -18,7 +18,7 @@ import "../token/LockerToken.sol"; contract CollaborationBank is Bank, EpochLocker { - LockableToken public token; + LockerToken public token; //used for calculating balance and for checking if account withdrawn uint256 public currentPayEpoch; //stores the balance from the lock time @@ -29,14 +29,15 @@ contract CollaborationBank is Bank, EpochLocker { event Withdrawn(address tokenHolder, uint256 amountPaidOut); event Deposited(address donator,uint256 value); - public CollaborationBank(LockableToken _token) EpochLockable(8 minutes,12 minutes){ + function CollaborationBank(LockerToken _token) EpochLocker(8 minutes, 12 minutes){ token = _token; + } //update the balance and payout epoch modifier update_epoch { if(currentPayEpoch < CURRENT_EPOCH) { - currentPayEpoch = _token.CURRENT_EPOCH(); + currentPayEpoch = CURRENT_EPOCH; epochBalance = this.balance; } _; @@ -51,7 +52,6 @@ contract CollaborationBank is Bank, EpochLocker { //check overflow in multiply function safeMultiply(uint256 _a, uint256 _b) private { if (!(_b == 0 || ((_a * _b) / _b) == _a)) throw; - _; } //allow deposit and call event @@ -60,10 +60,6 @@ contract CollaborationBank is Bank, EpochLocker { deposit(); } - function setLock(bool _lock){ - token.setLock(_lock); - - } //withdraw if locked and not paid, updates epoch function withdrawal() external diff --git a/contracts/lib/ethereans/management/EpochLocker.sol b/contracts/lib/ethereans/management/EpochLocker.sol index 1d25737..c98c240 100644 --- a/contracts/lib/ethereans/management/EpochLocker.sol +++ b/contracts/lib/ethereans/management/EpochLocker.sol @@ -1,18 +1,23 @@ pragma solidity ^0.4.8; +/** + * Abstract contract that locks and unlock in period of a time. + * + */ + +import "lib/ethereans/management/Lockable.sol"; + contract EpochLocker is Lockable { uint256 public creationTime = now; - uint256 public unlockedTime = 25 days + 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){ + + + function EpochLocker(uint256 _unlockedTime, uint256 _lockedTime){ unlockedTime = _unlockedTime; lockedTime = _lockedTime; } @@ -22,6 +27,7 @@ contract EpochLocker is Lockable { if(lockedOnly){ //method allowed when locked if (NEXT_LOCK < now) { //is locked! if (!lock) setLock(true); //storage says other thing, update it. + _; //continue } else { //is not locked! if (!lock) throw; //unlocked and storage already say so, throw to prevent event flood. @@ -31,11 +37,12 @@ contract EpochLocker is Lockable { }else{ //method allowed when unlocked. if (NEXT_LOCK < now) { //is locked! if (lock) throw; //no need to update storage. - setLock(true);//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. + _; //continue } } } diff --git a/contracts/lib/ethereans/management/Lockable.sol b/contracts/lib/ethereans/management/Lockable.sol index eae6ef9..0edd67e 100644 --- a/contracts/lib/ethereans/management/Lockable.sol +++ b/contracts/lib/ethereans/management/Lockable.sol @@ -6,7 +6,7 @@ contract Lockable { bool public lock = true; event Locked(bool lock); - fuction setLock(bool _lock) internal { + function setLock(bool _lock) internal { Locked(_lock); lock = _lock; } diff --git a/contracts/lib/ethereans/token/JustifiedCollaborationToken.sol b/contracts/lib/ethereans/token/JustifiedCollaborationToken.sol index f2f19ea..303cf06 100644 --- a/contracts/lib/ethereans/token/JustifiedCollaborationToken.sol +++ b/contracts/lib/ethereans/token/JustifiedCollaborationToken.sol @@ -8,9 +8,9 @@ pragma solidity ^0.4.1; */ import "../management/Owned.sol"; -import "./CollaborationToken.sol"; +import "./AbstractToken.sol"; -contract JustifiedCollaborationToken is CollaborationToken, Owned { +contract JustifiedCollaborationToken is AbstractToken, Owned { event Claim(bytes32 _data); mapping (bytes32 => Receipt) public receipts; mapping (address => bool) public minters; @@ -23,7 +23,6 @@ contract JustifiedCollaborationToken is CollaborationToken, Owned { } function claim(address _beneficiary, uint256 _value, bytes32 _data) - not_locked only_owner { if(receipts[_data].claimed) throw; receipts[_data] = Receipt ({beneficiary: _beneficiary, value: _value, claimed: true}); diff --git a/contracts/lib/ethereans/token/LockerToken.sol b/contracts/lib/ethereans/token/LockerToken.sol index 89425b9..ed915ca 100644 --- a/contracts/lib/ethereans/token/LockerToken.sol +++ b/contracts/lib/ethereans/token/LockerToken.sol @@ -1,12 +1,7 @@ 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 + * Abstract contract to accept lock and linked locker. * * By Ricardo Guilherme Schmidt * Released under GPLv3 License @@ -17,15 +12,14 @@ 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 { + function setlock(bool _lock) only_owner { setLock(_lock); } @@ -35,14 +29,14 @@ contract LockerToken is AbstractToken, Lockable, Owned { } //overwrite not allow transfer during lock - function transfer(address _to, uint256 _value) when_locked(true); + 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) { + function transferFrom(address _from, address _to, uint256 _value) when_locked(true) + returns (bool ok) { return super.transferFrom(_from,_to,_value); } diff --git a/contracts/src/GitBountyBank.sol b/contracts/src/GitBountyBank.sol index 94c180d..8dbab75 100644 --- a/contracts/src/GitBountyBank.sol +++ b/contracts/src/GitBountyBank.sol @@ -9,7 +9,7 @@ import "lib/ethereans/management/Owned.sol" ; contract GitBountyBank is Owned { mapping (uint => Bounty) bounties; - uint lockPeriod = 1 month; + uint lockPeriod = 30 days; struct Bounty { bool open; uint closedAt; @@ -45,9 +45,9 @@ contract GitBountyBank is Owned { payable returns (uint reciept) { if (!bounties[num].open) throw; reciept = bounties[num].depositIndex; - bounties[num].deposits[reciept] = { owner: account, amount: msg.value }; + bounties[num].deposits[reciept] = Account({ owner: account, amount: msg.value }); bounties[num].depositIndex++; - bounties[num].balance += msg.value; + bounties[num].deposited += msg.value; return reciept; } @@ -56,7 +56,7 @@ contract GitBountyBank is Owned { if(bounties[num].deposits[reciept].owner != account) throw; uint avaliable = bounties[num].deposits[reciept].amount; delete bounties[num].deposits[reciept]; - bounties[num].balance -= avaliable; + bounties[num].deposited -= avaliable; if(!account.send(avaliable)) throw; } @@ -64,7 +64,8 @@ contract GitBountyBank is Owned { if (bounties[num].open || now < bounties[num].closedAt+lockPeriod) throw; uint balance = bounties[num].deposited - bounties[num].claimed; uint remainingStats = bounties[num].stats - bounties[num].statsClaimed; - bounties[num].claims[commitid] = { owner: account, amount: stats }; + bounties[num].claims[commitid] = Account({ owner: beneficiary, amount: stats }); + //bounties[num].claimed+= } diff --git a/contracts/src/GitHubIssues.sol b/contracts/src/GitHubIssues.sol index 577defe..a41c363 100644 --- a/contracts/src/GitHubIssues.sol +++ b/contracts/src/GitHubIssues.sol @@ -4,15 +4,15 @@ pragma solidity ^0.4.8; * DO NOT USE: under development */ import "./GitHubOracle.sol"; - import "./AbstractBounty.sol"; + - contract GitHubIssues is AbstractBounty { + contract GitHubIssues { //Address of the oracle, used for github login address lookup GitHubOracle public oracle; //stores repository name, used for claim calls string private repository; - string private uid; + uint private uid; mapping (uint => Issue) issues; struct Issue { @@ -36,10 +36,10 @@ pragma solidity ^0.4.8; } function setState(uint num, bool open){ - issues[num] = open; + //issues[num] = open; } function placeBounty(uint num){ - issues[num] + } } \ No newline at end of file diff --git a/contracts/src/GitHubOracle.sol b/contracts/src/GitHubOracle.sol index 07ade2e..f4a771f 100644 --- a/contracts/src/GitHubOracle.sol +++ b/contracts/src/GitHubOracle.sol @@ -80,7 +80,7 @@ contract GitHubOracle is Owned, usingOraclize { } - function getRepository(uint id) constant returns (address){ + function getRepository(uint projectId) constant returns (address){ return db.getRepositoryAddress(projectId); } diff --git a/contracts/src/BountyBank.sol b/contracts/src/git-repository/BountyBank.sol similarity index 75% rename from contracts/src/BountyBank.sol rename to contracts/src/git-repository/BountyBank.sol index ef04915..5a97762 100644 --- a/contracts/src/BountyBank.sol +++ b/contracts/src/git-repository/BountyBank.sol @@ -1,15 +1,16 @@ pragma solidity ^0.4.9; -import "lib/ethereans/management/Owned.sol" +import "lib/ethereans/management/Owned.sol"; contract BountyBank is Owned { - enum State {CLOSED, OPEN, CLAIMED}; + enum State {CLOSED, OPEN, CLAIMED} + struct Bounty { State state; uint closedAt; - mapping (address => int) deposits; - mapping (address => int) claimers; + mapping (address => uint) deposits; + mapping (address => uint) claimers; uint balance; uint points; } @@ -17,21 +18,21 @@ contract BountyBank is Owned { mapping (uint => Bounty) bounties; uint count = 0; - function deposit(int num) payable { - if(bounties[num].state != OPEN || msg.value == 0) throw; + function deposit(uint num) payable { + if(bounties[num].state != State.OPEN || msg.value == 0) throw; bounties[num].deposits[msg.sender] += msg.value; bounties[num].balance += msg.value; } - function withdraw(int num) { + function withdraw(uint num) { uint value = bounties[num].deposits[msg.sender]; - if(bounties[num].state != OPEN || value == 0) throw; + if(bounties[num].state != 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; + if(bounties[num].state == State.CLAIMED) throw; bounties[num].state = State.OPEN; } @@ -43,7 +44,7 @@ contract BountyBank is Owned { function close(uint num) only_owner { if(bounties[num].state == State.CLAIMED) throw; - bounties[num].close = true; + bounties[num].state = State.CLOSED; bounties[num].closedAt = now; } diff --git a/contracts/src/git-repository/GitRepository.sol b/contracts/src/git-repository/GitRepository.sol index 75ced84..d91ba9d 100644 --- a/contracts/src/git-repository/GitRepository.sol +++ b/contracts/src/git-repository/GitRepository.sol @@ -17,6 +17,7 @@ pragma solidity ^0.4.8; import "lib/ethereans/bank/CollaborationBank.sol"; import "lib/ethereans/management/Owned.sol"; +import "./BountyBank.sol"; import "./GitRepositoryI.sol"; import "./GitRepositoryToken.sol"; import "./GitRepositoryStorage.sol"; @@ -27,7 +28,7 @@ contract GitRepository is GitRepositoryI, Owned { GitRepositoryStorage public db; GitRepositoryToken public token; CollaborationBank public donationBank; - BountyBank + BountyBank public bountyBank; mapping (address=>uint) beers; uint256 public subscribers; @@ -43,15 +44,15 @@ contract GitRepository is GitRepositoryI, Owned { function () payable { donationBank.deposit(); + beers[msg.sender] = msg.value; } - - - + function GitRepository(uint256 _uid, string _name) { db = new GitRepositoryStorage(_uid,_name); token = new GitRepositoryToken(_name); donationBank = new CollaborationBank(token); token.linkLocker(donationBank); + bountyBank = new BountyBank(); } //checks if a commit is already claimed @@ -78,7 +79,6 @@ contract GitRepository is GitRepositoryI, Owned { subscribers = _subscribers; watchers = _watchers; } - } diff --git a/contracts/src/git-repository/GitRepositoryToken.sol b/contracts/src/git-repository/GitRepositoryToken.sol index 1cb70ff..3a9b81d 100644 --- a/contracts/src/git-repository/GitRepositoryToken.sol +++ b/contracts/src/git-repository/GitRepositoryToken.sol @@ -27,7 +27,7 @@ contract GitRepositoryToken is LockerToken { } function mint(address _who, uint256 _value) - only_owner when_locked(false)) { + only_owner when_locked(false) { _mint(_who,_value); } From 29c47c76bc7a3ac4493da0e42a54c13b914bfbe5 Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Sun, 26 Mar 2017 06:34:06 +0000 Subject: [PATCH 3/4] fixed not owner error, moved factories to library --- .../lib/ethereans/bank/CollaborationBank.sol | 4 +- contracts/lib/ethereans/management/Owned.sol | 6 +- contracts/src/GitHubOracle.sol | 20 +-- contracts/src/factory/DBFactory.sol | 18 +++ contracts/src/factory/GRFactory.sol | 20 +++ .../git-repository/GitRepositoryFactory.sol | 19 --- contracts/tests/index.test.js | 36 +++++ ethereum.json | 2 +- scenarios/DeployRegClaim.yaml | 143 ------------------ scenarios/RegisterClaim.yaml | 31 ++++ 10 files changed, 121 insertions(+), 178 deletions(-) create mode 100644 contracts/src/factory/DBFactory.sol create mode 100644 contracts/src/factory/GRFactory.sol delete mode 100644 contracts/src/git-repository/GitRepositoryFactory.sol create mode 100644 contracts/tests/index.test.js delete mode 100644 scenarios/DeployRegClaim.yaml create mode 100644 scenarios/RegisterClaim.yaml diff --git a/contracts/lib/ethereans/bank/CollaborationBank.sol b/contracts/lib/ethereans/bank/CollaborationBank.sol index 91031cd..cad9581 100644 --- a/contracts/lib/ethereans/bank/CollaborationBank.sol +++ b/contracts/lib/ethereans/bank/CollaborationBank.sol @@ -17,13 +17,13 @@ import "../management/EpochLocker.sol"; import "../token/LockerToken.sol"; contract CollaborationBank is Bank, EpochLocker { - + LockerToken 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 + //used for checking if account withdrawn mapping (address => uint) lastPaidOutEpoch; //events event Withdrawn(address tokenHolder, uint256 amountPaidOut); diff --git a/contracts/lib/ethereans/management/Owned.sol b/contracts/lib/ethereans/management/Owned.sol index 76683cc..141010d 100644 --- a/contracts/lib/ethereans/management/Owned.sol +++ b/contracts/lib/ethereans/management/Owned.sol @@ -3,7 +3,11 @@ pragma solidity ^0.4.8; contract Owned { address public owner= msg.sender; event NewOwner(address owner); - + + function Owned(){ + NewOwner(owner); + } + modifier only_owner { if (msg.sender != owner) throw; _; diff --git a/contracts/src/GitHubOracle.sol b/contracts/src/GitHubOracle.sol index f4a771f..83db21d 100644 --- a/contracts/src/GitHubOracle.sol +++ b/contracts/src/GitHubOracle.sol @@ -20,16 +20,15 @@ import "lib/JSONLib.sol"; import "lib/oraclize/oraclizeAPI_0.4.sol"; import "lib/ethereans/management/Owned.sol"; -import "./git-repository/GitRepositoryFactoryI.sol"; +import "./factory/GRFactory.sol"; +import "./factory/DBFactory.sol"; import "./storage/GitHubOracleStorageI.sol"; - contract GitHubOracle is Owned, usingOraclize { using StringLib for string; - GitRepositoryFactoryI public gitRepositoryFactoryI; GitHubOracleStorageI public db; enum OracleType { SET_REPOSITORY, SET_USER, CLAIM_COMMIT, UPDATE_ISSUE } @@ -53,9 +52,8 @@ contract GitHubOracle is Owned, usingOraclize { string commitid; } - function GitHubOracle(GitHubOracleStorageI _db, GitRepositoryFactoryI _gitRepositoryFactoryI){ // - gitRepositoryFactoryI = _gitRepositoryFactoryI; - db = _db; + function GitHubOracle(){ // + db = DBFactory.newStorage(); } //register or change a github user ethereum address 100000000000000000 @@ -79,7 +77,6 @@ contract GitHubOracle is Owned, usingOraclize { claimType[ocid] = OracleType.SET_REPOSITORY; } - function getRepository(uint projectId) constant returns (address){ return db.getRepositoryAddress(projectId); } @@ -105,14 +102,13 @@ contract GitHubOracle is Owned, usingOraclize { function bountyIssue(uint repositoryId, uint issueId) payable{ - + } //Internal Functions - - // + event OracleEvent(bytes32 myid, string result, bytes proof); //oraclize response callback @@ -148,7 +144,7 @@ contract GitHubOracle is Owned, usingOraclize { } event GitRepositoryRegistered(uint256 projectId, string full_name, uint256 watchers, uint256 subscribers); - function _setRepository(bytes32 myid, string result) //[83725290, "ethereans/github-token", 4, 2] + function _setRepository(bytes32 myid, string result) internal //[83725290, "ethereans/github-token", 4, 2] { uint256 projectId; string memory full_name; uint256 watchers; uint256 subscribers; uint256 ownerId; string memory name; //TODO @@ -161,7 +157,7 @@ contract GitHubOracle is Owned, usingOraclize { address repository = db.getRepositoryAddress(projectId); if(repository == 0x0){ GitRepositoryRegistered(projectId,full_name,watchers,subscribers); - repository = gitRepositoryFactoryI.newGitRepository(projectId,full_name); + repository = GRFactory.newGitRepository(projectId,full_name); db.addRepository(projectId,ownerId,name,full_name,repository); } GitRepositoryI(repository).setStats(subscribers,watchers); diff --git a/contracts/src/factory/DBFactory.sol b/contracts/src/factory/DBFactory.sol new file mode 100644 index 0000000..f9dd043 --- /dev/null +++ b/contracts/src/factory/DBFactory.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.4.8; + +/** + * By Ricardo Guilherme Schmidt + * Released under GPLv3 License + */ + +import "../storage/GitHubOracleStorage.sol"; + + +library DBFactory { + + function newStorage() returns (GitHubOracleStorageI){ + GitHubOracleStorage db = new GitHubOracleStorage(); + return db; + } + +} \ No newline at end of file diff --git a/contracts/src/factory/GRFactory.sol b/contracts/src/factory/GRFactory.sol new file mode 100644 index 0000000..26e799c --- /dev/null +++ b/contracts/src/factory/GRFactory.sol @@ -0,0 +1,20 @@ +pragma solidity ^0.4.8; + +/** + * By Ricardo Guilherme Schmidt + * Released under GPLv3 License + */ + +import "../git-repository/GitRepository.sol"; +//import "./GitRepositoryFactoryI.sol"; + +library GRFactory { + + function newGitRepository(uint256 _uid, string _name) returns (GitRepositoryI){ + GitRepository repo = new GitRepository(_uid,_name); + return repo; + } + + + +} \ No newline at end of file diff --git a/contracts/src/git-repository/GitRepositoryFactory.sol b/contracts/src/git-repository/GitRepositoryFactory.sol deleted file mode 100644 index 1c20269..0000000 --- a/contracts/src/git-repository/GitRepositoryFactory.sol +++ /dev/null @@ -1,19 +0,0 @@ -pragma solidity ^0.4.8; - -/** - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -import "./GitRepository.sol"; -import "./GitRepositoryFactoryI.sol"; - -contract GitRepositoryFactory is GitRepositoryFactoryI { - - function newGitRepository(uint256 _uid, string _name) external returns (GitRepositoryI){ - GitRepository repo = new GitRepository(_uid,_name); - repo.setOwner(msg.sender); - return GitRepositoryI(repo); - } - -} \ No newline at end of file diff --git a/contracts/tests/index.test.js b/contracts/tests/index.test.js new file mode 100644 index 0000000..9dc9a79 --- /dev/null +++ b/contracts/tests/index.test.js @@ -0,0 +1,36 @@ +var assert = require('assert'); +var helper = require('ethereum-sandbox-helper'); +var Workbench = require('ethereum-sandbox-workbench'); + +var workbench = new Workbench({ + contractsDirectory: 'contracts', + solcVersion: '0.4.2', + defaults: { + from: '0xcd2a3d9f938e13cd947ec05abc7fe734df8dd826' + } +}); + +var contract; + +workbench.startTesting('contract', function(contracts) { + it('Deploy Contract', function() { + return contracts.Contract.new() + .then(function(result) { + if (result.address) contract = result; + else throw new Error('Contract is not deployed'); + return true; + }); + }); + + it('Prints string', function() { + var str = "hello, ethereum!"; + return contract.test(str) + .then(function(txHash) { + return workbench.waitForReceipt(txHash); + }) + .then(function (receipt) { + assert.equal(helper.hexToString(receipt.logs[0].data), str); + return true; + }); + }); +}); diff --git a/ethereum.json b/ethereum.json index 5501975..4735066 100644 --- a/ethereum.json +++ b/ethereum.json @@ -1,7 +1,7 @@ { "contracts": "contracts", - "deploy": ["GitHubOracleStorage", "GitRepositoryFactory", "GitHubOracle"], + "deploy": ["GitHubOracle"], "plugins": { "oraclize": { diff --git a/scenarios/DeployRegClaim.yaml b/scenarios/DeployRegClaim.yaml deleted file mode 100644 index 9b70d55..0000000 --- a/scenarios/DeployRegClaim.yaml +++ /dev/null @@ -1,143 +0,0 @@ -# -# Scenario3 -# -# Created on: 20/03/2017 02:44:46 -# - -# Create contract GitRepositoryFactory -- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: null - value: '0x0' - contract: - name: GitRepositoryFactory - dir: contracts/ - sources: - - lib/ethereans/bank/Bank.sol - - lib/ethereans/management/Owned.sol - - lib/ethereans/management/Secret.sol - - lib/ethereans/token/AbstractToken.sol - - lib/ethereans/token/CollaborationToken.sol - - lib/ethereans/token/JustifiedCollaborationToken.sol - - lib/ethereans/token/Token.sol - - lib/ethereans/token/WrappedEthToken.sol - - lib/ethereans/util/Bytes32Lib.sol - - lib/ethereans/util/IntLib.sol - - lib/JSONLib.sol - - lib/StringLib.sol - - lib/oraclize/oraclizeAPI_0.4.sol - - src/AbstractBounty.sol - - src/GitHubIssues.sol - - src/GitHubOracle.sol - - src/git-repository/GitRepository.sol - - src/git-repository/GitRepositoryFactory.sol - - src/git-repository/GitRepositoryFactoryI.sol - - src/git-repository/GitRepositoryI.sol - - src/git-repository/GitRepositoryStorage.sol - - src/git-repository/GitRepositoryToken.sol - - src/storage/GitHubOracleStorage.sol - - src/storage/GitHubOracleStorageI.sol - args: [] - -# Create contract GitHubOracleStorage -- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: null - value: '0x0' - contract: - name: GitHubOracleStorage - dir: contracts/ - sources: - - lib/ethereans/bank/Bank.sol - - lib/ethereans/management/Owned.sol - - lib/ethereans/management/Secret.sol - - lib/ethereans/token/AbstractToken.sol - - lib/ethereans/token/CollaborationToken.sol - - lib/ethereans/token/JustifiedCollaborationToken.sol - - lib/ethereans/token/Token.sol - - lib/ethereans/token/WrappedEthToken.sol - - lib/ethereans/util/Bytes32Lib.sol - - lib/ethereans/util/IntLib.sol - - lib/JSONLib.sol - - lib/StringLib.sol - - lib/oraclize/oraclizeAPI_0.4.sol - - src/AbstractBounty.sol - - src/GitHubIssues.sol - - src/GitHubOracle.sol - - src/git-repository/GitRepository.sol - - src/git-repository/GitRepositoryFactory.sol - - src/git-repository/GitRepositoryFactoryI.sol - - src/git-repository/GitRepositoryI.sol - - src/git-repository/GitRepositoryStorage.sol - - src/git-repository/GitRepositoryToken.sol - - src/storage/GitHubOracleStorage.sol - - src/storage/GitHubOracleStorageI.sol - args: [] - -# Create contract GitHubOracle -- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: null - value: '0x0' - contract: - name: GitHubOracle - dir: contracts/ - sources: - - lib/ethereans/bank/Bank.sol - - lib/ethereans/management/Owned.sol - - lib/ethereans/management/Secret.sol - - lib/ethereans/token/AbstractToken.sol - - lib/ethereans/token/CollaborationToken.sol - - lib/ethereans/token/JustifiedCollaborationToken.sol - - lib/ethereans/token/Token.sol - - lib/ethereans/token/WrappedEthToken.sol - - lib/ethereans/util/Bytes32Lib.sol - - lib/ethereans/util/IntLib.sol - - lib/JSONLib.sol - - lib/StringLib.sol - - lib/oraclize/oraclizeAPI_0.4.sol - - src/AbstractBounty.sol - - src/GitHubIssues.sol - - src/GitHubOracle.sol - - src/git-repository/GitRepository.sol - - src/git-repository/GitRepositoryFactory.sol - - src/git-repository/GitRepositoryFactoryI.sol - - src/git-repository/GitRepositoryI.sol - - src/git-repository/GitRepositoryStorage.sol - - src/git-repository/GitRepositoryToken.sol - - src/storage/GitHubOracleStorage.sol - - src/storage/GitHubOracleStorageI.sol - args: - - '0xdf315f7485c3a86eb692487588735f224482abe3' - - '0x17956ba5f4291844bc25aedb27e69bc11b5bda39' - -# Call method setOwner(address) -- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: '0xdf315f7485c3a86eb692487588735f224482abe3' - value: '0x0' - call: setOwner(address) - args: - - '0x06b179aabf198ced0f98c8ceca905a920a137ef4' - -# Call method addRepository(string) -- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: '0x06b179aabf198ced0f98c8ceca905a920a137ef4' - value: '0x16345785d8a0000' - call: addRepository(string) - args: - - ethereans/github-token - -# Call method register(string,string) -- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: '0x06b179aabf198ced0f98c8ceca905a920a137ef4' - value: '0x38D7EA4C68000' - call: 'register(string,string)' - args: - - 3esmit - - 31a58f2ddf2258697cce1b969e7c298b - -# Call method claimCommit(string,string) -- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: '0x06b179aabf198ced0f98c8ceca905a920a137ef4' - value: '0x2386f26fc10000' - call: 'claimCommit(string,string)' - args: - - ethereans/github-token - - 09ba429f22eec6cefcfa7a862f60b9d4cc1cfa14 \ No newline at end of file diff --git a/scenarios/RegisterClaim.yaml b/scenarios/RegisterClaim.yaml new file mode 100644 index 0000000..14f63d8 --- /dev/null +++ b/scenarios/RegisterClaim.yaml @@ -0,0 +1,31 @@ +# +# Scenario1 +# +# Created on: 26/03/2017 03:32:05 +# + +# Call method addRepository(string) +- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' + to: '0xaefa01276783e1436e5b461c099edccb0448dcf6' + value: '0x16345785d8a0000' + call: addRepository(string) + args: + - status-im/github-oracle + +# Call method register(string,string) +- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' + to: '0xaefa01276783e1436e5b461c099edccb0448dcf6' + value: '0x0' + call: 'register(string,string)' + args: + - 3esmit + - 31a58f2ddf2258697cce1b969e7c298b + +# Call method claimCommit(string,string) +- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' + to: '0xaefa01276783e1436e5b461c099edccb0448dcf6' + value: '0x0' + call: 'claimCommit(string,string)' + args: + - status-im/github-oracle + - 3c461c5bfe3107923a13270f7037854f1ae8ca36 From b2ef721c03a79796437320afad06d9221a420ab4 Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Mon, 27 Mar 2017 06:42:15 +0000 Subject: [PATCH 4/4] isolated GitHubAPI --- .../src/{git-repository => }/BountyBank.sol | 0 .../{GitBountyBank.sol => BountyBank2.sol} | 0 contracts/src/DGit.sol | 86 +++++++++ .../GitHubOracleStorage.sol => DGitDB.sol} | 53 +++++- .../src/{GitHubOracle.sol => GitHubAPI.sol} | 168 ++++++++---------- contracts/src/GitHubIssues.sol | 45 ----- .../{git-repository => }/GitRepository.sol | 53 ++++-- .../GitRepositoryToken.sol | 0 contracts/src/factory/DBFactory.sol | 18 -- contracts/src/factory/GRFactory.sol | 20 --- .../git-repository/GitRepositoryFactoryI.sol | 12 -- .../src/git-repository/GitRepositoryI.sol | 12 -- .../git-repository/GitRepositoryStorage.sol | 41 ----- .../src/storage/GitHubOracleStorageI.sol | 27 --- contracts/tests/index.test.js | 36 ---- ethereum.json | 2 +- ...egisterClaim.yaml => InitRegAddClaim.yaml} | 25 ++- scripts/github-oracle/github_oracle.py | 101 +++++++++++ 18 files changed, 363 insertions(+), 336 deletions(-) rename contracts/src/{git-repository => }/BountyBank.sol (100%) rename contracts/src/{GitBountyBank.sol => BountyBank2.sol} (100%) create mode 100644 contracts/src/DGit.sol rename contracts/src/{storage/GitHubOracleStorage.sol => DGitDB.sol} (57%) rename contracts/src/{GitHubOracle.sol => GitHubAPI.sol} (58%) delete mode 100644 contracts/src/GitHubIssues.sol rename contracts/src/{git-repository => }/GitRepository.sol (63%) rename contracts/src/{git-repository => }/GitRepositoryToken.sol (100%) delete mode 100644 contracts/src/factory/DBFactory.sol delete mode 100644 contracts/src/factory/GRFactory.sol delete mode 100644 contracts/src/git-repository/GitRepositoryFactoryI.sol delete mode 100644 contracts/src/git-repository/GitRepositoryI.sol delete mode 100644 contracts/src/git-repository/GitRepositoryStorage.sol delete mode 100644 contracts/src/storage/GitHubOracleStorageI.sol delete mode 100644 contracts/tests/index.test.js rename scenarios/{RegisterClaim.yaml => InitRegAddClaim.yaml} (60%) create mode 100644 scripts/github-oracle/github_oracle.py diff --git a/contracts/src/git-repository/BountyBank.sol b/contracts/src/BountyBank.sol similarity index 100% rename from contracts/src/git-repository/BountyBank.sol rename to contracts/src/BountyBank.sol diff --git a/contracts/src/GitBountyBank.sol b/contracts/src/BountyBank2.sol similarity index 100% rename from contracts/src/GitBountyBank.sol rename to contracts/src/BountyBank2.sol diff --git a/contracts/src/DGit.sol b/contracts/src/DGit.sol new file mode 100644 index 0000000..e66792e --- /dev/null +++ b/contracts/src/DGit.sol @@ -0,0 +1,86 @@ +pragma solidity ^0.4.8; + +/** + * Contract that oracle github API + * + * GitHubOracle register users and create GitHubToken contracts + * Registration requires user create a gist with only their account address + * GitHubOracle will create one GitHubToken contract per repository + * GitHubToken mint tokens by commit only for registered users in GitHubOracle + * GitHubToken is a LockableCoin, that accept donatations and can be withdrawn by Token Holders + * The lookups are done by Oraclize that charge a small fee + * The contract itself will never charge any fee + * + * By Ricardo Guilherme Schmidt + * Released under GPLv3 License + */ + +import "lib/oraclize/oraclizeAPI_0.4.sol"; +import "lib/ethereans/management/Owned.sol"; +import "./GitHubAPI.sol"; +import "./DGitDB.sol"; +import "./GitRepository.sol"; + +contract DGit is Owned, DGitI { + + DGitDBI public db; + GitHubAPI public gitHubApi; + + function initialize() only_owner { + db = DBFactory.newStorage(); + gitHubApi = QueryFactory.newGitHubAPI(); + } + + function register(string _github_user, string _gistid) payable{ + gitHubApi.register.value(msg.value)(msg.sender,_github_user,_gistid); + } + function claimCommit(string _repository, string _commitid) payable{ + gitHubApi.claimCommit.value(msg.value)(_repository,_commitid); + } + function addRepository(string _repository) payable{ + gitHubApi.addRepository.value(msg.value)(_repository); + } + function updateIssue(string _repository, string issue) payable{ + gitHubApi.updateIssue.value(msg.value)(_repository,issue); + } + function getRepository(uint projectId) constant returns (address){ + return db.getRepositoryAddress(projectId); + } + function getRepository(string full_name) constant returns (address){ + return db.getRepositoryAddress(full_name); + } + + modifier only_gitapi{ + if (msg.sender != address(gitHubApi)) throw; + _; + } + + event UserSet(string githubLogin); + function __register(address addrLoaded, uint256 userId, string login) + only_gitapi { + UserSet(login); + db.addUser(userId, login, 0, addrLoaded); + } + + event GitRepositoryRegistered(uint256 projectId, string full_name, uint256 watchers, uint256 subscribers); + function __setRepository(uint256 projectId, string full_name, uint256 watchers, uint256 subscribers) only_gitapi //[83725290, "ethereans/github-token", 4, 2] + { + uint256 ownerId; string memory name; //TODO + address repository = db.getRepositoryAddress(projectId); + if(repository == 0x0){ + GitRepositoryRegistered(projectId,full_name,watchers,subscribers); + repository = GitFactory.newGitRepository(projectId,full_name); + db.addRepository(projectId,ownerId,name,full_name,repository); + } + GitRepositoryI(repository).setStats(subscribers,watchers); + } + + event NewClaim(string repository, bytes20 commitid, uint userId, uint total ); + function __claimCommit(string repository, bytes20 commitid, uint userId, uint total) + only_gitapi { + NewClaim(repository,commitid,userId,total); + GitRepositoryI repoaddr = GitRepositoryI(db.getRepositoryAddress(repository)); + repoaddr.claim(commitid, db.getUserAddress(userId), total); + } + +} \ No newline at end of file diff --git a/contracts/src/storage/GitHubOracleStorage.sol b/contracts/src/DGitDB.sol similarity index 57% rename from contracts/src/storage/GitHubOracleStorage.sol rename to contracts/src/DGitDB.sol index 12db397..71b3051 100644 --- a/contracts/src/storage/GitHubOracleStorage.sol +++ b/contracts/src/DGitDB.sol @@ -10,8 +10,25 @@ pragma solidity ^0.4.8; */ import "lib/ethereans/management/Owned.sol"; -import "./GitHubOracleStorageI.sol"; -contract GitHubOracleStorage is GitHubOracleStorageI, Owned { + +contract DGitDBI { + function addRepository(uint256 _id, uint256 _owner, string _name, string _full_name, address _addr); + function addUser(uint256 _id, string _login, uint8 _type, address _addr); + function setRepositoryAddress(uint256 _repositoryId, address _repositoryAddress); + function setRepositoryName(uint256 _repositoryId, string _full_name, string _name); + function setUserAddress(uint userId, address account); + function setUserName(uint256 _userId, string _name); + function getRepositoryId(string _full_name) constant returns (uint256); + function getRepositoryName(uint256 _id) constant returns (string); + function getRepositoryAddress(uint256 _id) constant returns(address); + function getRepositoryAddress(string _full_name) constant returns(address); + function getUserAddress(uint256 _id) constant returns(address); + function getUserAddress(string _login) constant returns(address); + function getClaimed(uint256 _repoid, bytes20 _commitid) constant returns (uint); + function setClaimed(uint256 _repoid, bytes20 _commitid, uint _userid, uint _points); +} + +contract DGitDB is DGitDBI, Owned { mapping (string => uint256) repositoryNames; mapping (string => uint256) userNames; @@ -23,24 +40,40 @@ contract GitHubOracleStorage is GitHubOracleStorageI, Owned { string name; string full_name; address addr; - uint256 claimed; + uint points; + mapping (bytes20 => Commit) commits; + } + struct Commit { + uint points; + uint userId; + } + struct User { string login; uint8 utype; address addr; - uint256 claimed; + } + + function setClaimed(uint256 _repoid, bytes20 _commitid, uint _userid, uint _points) + only_owner { + repositories[_repoid].commits[_commitid].userId = _userid; + repositories[_repoid].commits[_commitid].points = _points; + repositories[_repoid].points += _points; } + function getClaimed(uint256 _repoid, bytes20 _commitid) constant returns (uint){ + return repositories[_repoid].commits[_commitid].userId; + } function addRepository(uint256 _id, uint256 _owner, string _name, string _full_name, address _addr) only_owner { - repositories[_id] = Repository({owner:_owner,name:_name,full_name:_full_name,addr:_addr,claimed:0}); + repositories[_id] = Repository({owner:_owner,name:_name,full_name:_full_name,addr:_addr,points:0}); repositoryNames[_full_name] = _id; } function addUser(uint256 _id, string _login, uint8 _utype, address _addr) only_owner{ - users[_id] = User({login:_login,utype:_utype,addr:_addr, claimed:0}); + users[_id] = User({login:_login,utype:_utype,addr:_addr}); userNames[_login] = _id; } @@ -88,4 +121,12 @@ contract GitHubOracleStorage is GitHubOracleStorageI, Owned { return repositories[_id].full_name; } +} + +library DBFactory { + + function newStorage() returns (DGitDBI){ + return new DGitDB(); + } + } \ No newline at end of file diff --git a/contracts/src/GitHubOracle.sol b/contracts/src/GitHubAPI.sol similarity index 58% rename from contracts/src/GitHubOracle.sol rename to contracts/src/GitHubAPI.sol index 83db21d..2e786ba 100644 --- a/contracts/src/GitHubOracle.sol +++ b/contracts/src/GitHubAPI.sol @@ -1,46 +1,41 @@ -pragma solidity ^0.4.8; - -/** - * Contract that oracle github API - * - * GitHubOracle register users and create GitHubToken contracts - * Registration requires user create a gist with only their account address - * GitHubOracle will create one GitHubToken contract per repository - * GitHubToken mint tokens by commit only for registered users in GitHubOracle - * GitHubToken is a LockableCoin, that accept donatations and can be withdrawn by Token Holders - * The lookups are done by Oraclize that charge a small fee - * The contract itself will never charge any fee - * - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -import "lib/StringLib.sol"; -import "lib/JSONLib.sol"; +pragma solidity ^0.4.9; import "lib/oraclize/oraclizeAPI_0.4.sol"; +import "lib/StringLib.sol"; +import "lib/JSONLib.sol"; import "lib/ethereans/management/Owned.sol"; -import "./factory/GRFactory.sol"; -import "./factory/DBFactory.sol"; -import "./storage/GitHubOracleStorageI.sol"; -contract GitHubOracle is Owned, usingOraclize { +contract GitHubAPI{ + function register(address _sender, string _github_user, string _gistid) payable; + function claimCommit(string _repository, string _commitid) payable; + function addRepository(string _repository) payable; + function updateIssue(string _repository, string issue) payable; +} - using StringLib for string; - - GitHubOracleStorageI public db; +contract DGitI { + function __register(address addrLoaded, uint256 userId, string login); + function __setRepository(uint256 projectId, string full_name, uint256 watchers, uint256 subscribers); + function __claimCommit(string repository, bytes20 commitid, uint userid, uint total); +} +contract GitHubAPIOraclize is GitHubAPI, Owned, usingOraclize{ + using StringLib for string; + + DGitI dGit; + function GitHubAPIOraclize(){ + dGit = DGitI(msg.sender); + } + string private credentials = ""; //store encrypted values of api access credentials + string private secret = ""; + string private client = ""; + string private script = "QmS3kHrUQ12ovovKPk9vxKjDPm7kVWcieaMcZc9w8JbNQt"; + enum OracleType { SET_REPOSITORY, SET_USER, CLAIM_COMMIT, UPDATE_ISSUE } mapping (bytes32 => OracleType) claimType; //temporary db enumerating oraclize calls mapping (bytes32 => CommitClaim) commitClaim; //temporary db for oraclize commit token claim calls mapping (bytes32 => UserClaim) userClaim; //temporary db for oraclize user register queries - string private credentials = ""; //store encrypted values of api access credentials - string private secret = ""; - string private client = ""; - string private script = ""; - //stores temporary data for oraclize user register request struct UserClaim { address sender; @@ -49,66 +44,38 @@ contract GitHubOracle is Owned, usingOraclize { //stores temporary data for oraclize repository commit claim struct CommitClaim { string repository; - string commitid; + bytes20 commitid; } - - function GitHubOracle(){ // - db = DBFactory.newStorage(); - } - - //register or change a github user ethereum address 100000000000000000 - function register(string _github_user, string _gistid) - payable { + //register or change a github user ethereum address. 100000000000000000 + + function register(address _sender, string _github_user, string _gistid) + payable only_owner{ bytes32 ocid = oraclize_query("nested", StringLib.concat("[identity] ${[URL] https://gist.githubusercontent.com/",_github_user,"/",_gistid,"/raw/}, ${[URL] json(https://api.github.com/gists/").concat(_gistid,credentials,").owner.[id,login]}")); claimType[ocid] = OracleType.SET_USER; - userClaim[ocid] = UserClaim({sender: msg.sender, githubid: _github_user}); + userClaim[ocid] = UserClaim({sender: _sender, githubid: _github_user}); } function claimCommit(string _repository, string _commitid) - payable { + payable only_owner{ + //uint256 repoid = db.getRepositoryId(_repository); + //if (repoid == 0) throw; + bytes20 commitid = _commitid.parseBytes20(); + //if(db.getClaimed(repoid,commitid) == 0) throw; bytes32 ocid = oraclize_query("URL", StringLib.concat("json(https://api.github.com/repos/",_repository,"/commits/", _commitid, credentials).concat(").[author,stats].[id,total]")); claimType[ocid] = OracleType.CLAIM_COMMIT; - commitClaim[ocid] = CommitClaim( { repository: _repository, commitid:_commitid}); + commitClaim[ocid] = CommitClaim( { repository: _repository, commitid:commitid}); } function addRepository(string _repository) - payable { + payable only_owner{ bytes32 ocid = oraclize_query("URL", StringLib.concat("json(https://api.github.com/repos/",_repository,credentials,").$.id,full_name,watchers,subscribers_count"),4000000); claimType[ocid] = OracleType.SET_REPOSITORY; } - function getRepository(uint projectId) constant returns (address){ - return db.getRepositoryAddress(projectId); - } - - function getRepository(string full_name) constant returns (address){ - return db.getRepositoryAddress(full_name); - } - - function setScript(string _script){ - script = _script; - } - - //owner management - function setAPICredentials(string _client_id, string _client_secret) - only_owner { - credentials = StringLib.concat("?client_id=${[decrypt] ", _client_id,"}&client_secret=${[decrypt] ", _client_secret,"}"); + function updateIssue(string _repository, string issue) payable only_owner{ + bytes32 ocid = oraclize_query("computation", [script, StringLib.concat("--reponame ",_repository, " --issueid ", issue, " --script issue-status").concat(" --client ", client, " --secret ", secret)]); } - function clearAPICredentials() - only_owner { - credentials = ""; - } - - - function bountyIssue(uint repositoryId, uint issueId) payable{ - - } - - - //Internal Functions - // - event OracleEvent(bytes32 myid, string result, bytes proof); //oraclize response callback @@ -126,7 +93,6 @@ contract GitHubOracle is Owned, usingOraclize { delete claimType[myid]; //should always be deleted } - event UserSet(string githubLogin); function _register(bytes32 myid, string result) internal { uint256 userId; string memory login; address addrLoaded; @@ -136,34 +102,25 @@ contract GitHubOracle is Owned, usingOraclize { (addrLoaded,pos) = JSONLib.getNextAddr(v,pos); (userId,pos) = JSONLib.getNextUInt(v,pos); (login,pos) = JSONLib.getNextString(v,pos); - if(userClaim[myid].sender == addrLoaded && userClaim[myid].githubid.compare(login) == 0){ - UserSet(login); - db.addUser(userId, login, utype, addrLoaded); - } //TODO: update user login and address; + if(userClaim[myid].sender == addrLoaded){ + dGit.__register(addrLoaded, userId, login); + } delete userClaim[myid]; //should always be deleted } - event GitRepositoryRegistered(uint256 projectId, string full_name, uint256 watchers, uint256 subscribers); function _setRepository(bytes32 myid, string result) internal //[83725290, "ethereans/github-token", 4, 2] { uint256 projectId; string memory full_name; uint256 watchers; uint256 subscribers; - uint256 ownerId; string memory name; //TODO + //uint256 ownerId; string memory name; //TODO bytes memory v = bytes(result); uint8 pos = 0; (projectId,pos) = JSONLib.getNextUInt(v,pos); (full_name,pos) = JSONLib.getNextString(v,pos); (watchers,pos) = JSONLib.getNextUInt(v,pos); (subscribers,pos) = JSONLib.getNextUInt(v,pos); - address repository = db.getRepositoryAddress(projectId); - if(repository == 0x0){ - GitRepositoryRegistered(projectId,full_name,watchers,subscribers); - repository = GRFactory.newGitRepository(projectId,full_name); - db.addRepository(projectId,ownerId,name,full_name,repository); - } - GitRepositoryI(repository).setStats(subscribers,watchers); + dGit.__setRepository(projectId,full_name,watchers,subscribers); } - event NewClaim(string repository, string commitid, uint userid, uint total ); function _claimCommit(bytes32 myid, string result) internal { uint256 total; uint256 userId; @@ -171,13 +128,36 @@ contract GitHubOracle is Owned, usingOraclize { uint8 pos = 0; (userId,pos) = JSONLib.getNextUInt(v,pos); (total,pos) = JSONLib.getNextUInt(v,pos); - NewClaim(commitClaim[myid].repository,commitClaim[myid].commitid,userId,total); - GitRepositoryI repository = GitRepositoryI(db.getRepositoryAddress(commitClaim[myid].repository)); - repository.claim(commitClaim[myid].commitid.parseBytes20(), db.getUserAddress(userId), total); - delete commitClaim[myid]; //should always be deleted + dGit.__claimCommit(commitClaim[myid].repository,commitClaim[myid].commitid,userId,total); + delete commitClaim[myid]; + } + + //owner management + function setAPICredentials(string _client_id, string _client_secret) + only_owner { + client = _client_id; + secret = _client_secret; + credentials = StringLib.concat("?client_id=${[decrypt] ", _client_id,"}&client_secret=${[decrypt] ", _client_secret,"}"); + } + + + function setScript(string _script) only_owner{ + script = _script; } - + function clearAPICredentials() + only_owner { + credentials = ""; + } + +} + +library QueryFactory { + + function newGitHubAPI() returns (GitHubAPI){ + return new GitHubAPIOraclize(); + } + } \ No newline at end of file diff --git a/contracts/src/GitHubIssues.sol b/contracts/src/GitHubIssues.sol deleted file mode 100644 index a41c363..0000000 --- a/contracts/src/GitHubIssues.sol +++ /dev/null @@ -1,45 +0,0 @@ -pragma solidity ^0.4.8; - -/** - * DO NOT USE: under development - */ - import "./GitHubOracle.sol"; - - - contract GitHubIssues { - - //Address of the oracle, used for github login address lookup - GitHubOracle public oracle; - //stores repository name, used for claim calls - string private repository; - uint private uid; - mapping (uint => Issue) issues; - - struct Issue { - bool state; - uint balance; - uint unlock; - address claimer; - bool claimed; - } - - - modifier only_oracle { - if (msg.sender != address(oracle)) throw; - _; - } - - function GitHubIssues(uint _uid, string _repository, GitHubOracle _oracle) { - uid = _uid; - oracle = _oracle; - repository = _repository; - } - - function setState(uint num, bool open){ - //issues[num] = open; - } - - function placeBounty(uint num){ - - } - } \ No newline at end of file diff --git a/contracts/src/git-repository/GitRepository.sol b/contracts/src/GitRepository.sol similarity index 63% rename from contracts/src/git-repository/GitRepository.sol rename to contracts/src/GitRepository.sol index d91ba9d..aa74e43 100644 --- a/contracts/src/git-repository/GitRepository.sol +++ b/contracts/src/GitRepository.sol @@ -18,18 +18,25 @@ pragma solidity ^0.4.8; import "lib/ethereans/bank/CollaborationBank.sol"; import "lib/ethereans/management/Owned.sol"; import "./BountyBank.sol"; -import "./GitRepositoryI.sol"; import "./GitRepositoryToken.sol"; -import "./GitRepositoryStorage.sol"; + + +contract GitRepositoryI { + function isClaimed(bytes20 _commitid) constant returns (bool); + function claim(bytes20 _commitid, address _user, uint _total); + function setStats(uint256 _subscribers, uint256 _watchers); +} 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 public bountyBank; - mapping (address=>uint) beers; + mapping (address=>uint) donators; + + string public name; + uint256 public uid; + mapping (bytes20 => bool) public commits; uint256 public subscribers; uint256 public watchers; @@ -44,11 +51,12 @@ contract GitRepository is GitRepositoryI, Owned { function () payable { donationBank.deposit(); - beers[msg.sender] = msg.value; + donators[msg.sender] += msg.value; } function GitRepository(uint256 _uid, string _name) { - db = new GitRepositoryStorage(_uid,_name); + uid = _uid; + name = _name; token = new GitRepositoryToken(_name); donationBank = new CollaborationBank(token); token.linkLocker(donationBank); @@ -59,18 +67,16 @@ contract GitRepository is GitRepositoryI, Owned { function isClaimed(bytes20 _commitid) constant returns (bool) { - return db.commits(_commitid) != 0x0; + return commits[_commitid]; } //oracle claim request function claim(bytes20 _commitid, address _user, uint _total) only_owner { - if(_total > 0 && !token.lock()){ - if(_user != 0x0 && db.commits(_commitid) != 0x0){ - Claim(_commitid); - db.setClaimed(_commitid,_user); - token.mint(_user, _total); - } + if(_total > 0 && !token.lock() && _user != 0x0 && !commits[_commitid]){ + Claim(_commitid); + commits[_commitid] = true; + token.mint(_user, _total); } } @@ -79,6 +85,23 @@ contract GitRepository is GitRepositoryI, Owned { subscribers = _subscribers; watchers = _watchers; } - + + function bountyState(uint issue, bool open) only_owner { + if (open) bountyBank.open(issue); + else bountyBank.close(issue); + } + + function bountyState(uint issue, address claimer, uint points) only_owner { + bountyBank.setClaimer(issue,claimer,points); + } } + +library GitFactory { + + function newGitRepository(uint256 _uid, string _name) returns (GitRepositoryI){ + GitRepository repo = new GitRepository(_uid,_name); + return repo; + } + +} \ No newline at end of file diff --git a/contracts/src/git-repository/GitRepositoryToken.sol b/contracts/src/GitRepositoryToken.sol similarity index 100% rename from contracts/src/git-repository/GitRepositoryToken.sol rename to contracts/src/GitRepositoryToken.sol diff --git a/contracts/src/factory/DBFactory.sol b/contracts/src/factory/DBFactory.sol deleted file mode 100644 index f9dd043..0000000 --- a/contracts/src/factory/DBFactory.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.4.8; - -/** - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -import "../storage/GitHubOracleStorage.sol"; - - -library DBFactory { - - function newStorage() returns (GitHubOracleStorageI){ - GitHubOracleStorage db = new GitHubOracleStorage(); - return db; - } - -} \ No newline at end of file diff --git a/contracts/src/factory/GRFactory.sol b/contracts/src/factory/GRFactory.sol deleted file mode 100644 index 26e799c..0000000 --- a/contracts/src/factory/GRFactory.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.4.8; - -/** - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -import "../git-repository/GitRepository.sol"; -//import "./GitRepositoryFactoryI.sol"; - -library GRFactory { - - function newGitRepository(uint256 _uid, string _name) returns (GitRepositoryI){ - GitRepository repo = new GitRepository(_uid,_name); - return repo; - } - - - -} \ No newline at end of file diff --git a/contracts/src/git-repository/GitRepositoryFactoryI.sol b/contracts/src/git-repository/GitRepositoryFactoryI.sol deleted file mode 100644 index 1ec1469..0000000 --- a/contracts/src/git-repository/GitRepositoryFactoryI.sol +++ /dev/null @@ -1,12 +0,0 @@ -pragma solidity ^0.4.8; - -/** - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -import "./GitRepositoryI.sol"; - -contract GitRepositoryFactoryI { - function newGitRepository(uint256 _uid, string _name) external returns (GitRepositoryI); -} diff --git a/contracts/src/git-repository/GitRepositoryI.sol b/contracts/src/git-repository/GitRepositoryI.sol deleted file mode 100644 index bc26d63..0000000 --- a/contracts/src/git-repository/GitRepositoryI.sol +++ /dev/null @@ -1,12 +0,0 @@ -pragma solidity ^0.4.8; - -/** - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -contract GitRepositoryI { - function isClaimed(bytes20 _commitid) constant returns (bool); - function claim(bytes20 _commitid, address _user, uint _total); - function setStats(uint256 _subscribers, uint256 _watchers); -} \ No newline at end of file diff --git a/contracts/src/git-repository/GitRepositoryStorage.sol b/contracts/src/git-repository/GitRepositoryStorage.sol deleted file mode 100644 index a392ced..0000000 --- a/contracts/src/git-repository/GitRepositoryStorage.sol +++ /dev/null @@ -1,41 +0,0 @@ - pragma solidity ^0.4.8; - -/** - * Contract that oracle github API - * - * GitHubRegistry is a storage contract - * - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ -import "lib/ethereans/management/Owned.sol"; - -contract GitRepositoryStorage is Owned { - - string public name; - uint256 public uid; - - //storage of sha3(login) of github users - mapping (bytes32 => address) users; - - mapping (bytes20 => address) public commits; - - function setClaimed(bytes20 _commitid, address _claimer) - only_owner { - commits[_commitid] = _claimer; - } - - function setUser(bytes32 _user, address _account) - only_owner { - users[_user] = _account; - if(_account == 0x0){ - delete users[_user]; - } - } - - function GitRepositoryStorage(uint256 _uid, string _name){ - uid = _uid; - name = _name; - } - -} \ No newline at end of file diff --git a/contracts/src/storage/GitHubOracleStorageI.sol b/contracts/src/storage/GitHubOracleStorageI.sol deleted file mode 100644 index 9095ce5..0000000 --- a/contracts/src/storage/GitHubOracleStorageI.sol +++ /dev/null @@ -1,27 +0,0 @@ -pragma solidity ^0.4.8; - -/** - * Contract that oracle github API - * - * GitHubRegistry is a storage contract - * - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -contract GitHubOracleStorageI { - - function addRepository(uint256 _id, uint256 _owner, string _name, string _full_name, address _addr); - function addUser(uint256 _id, string _login, uint8 _type, address _addr); - function setRepositoryAddress(uint256 _repositoryId, address _repositoryAddress); - function setRepositoryName(uint256 _repositoryId, string _full_name, string _name); - function setUserAddress(uint userId, address account); - function setUserName(uint256 _userId, string _name); - function getRepositoryId(string _full_name) constant returns (uint256); - function getRepositoryName(uint256 _id) constant returns (string); - function getRepositoryAddress(uint256 _id) constant returns(address); - function getRepositoryAddress(string _full_name) constant returns(address); - function getUserAddress(uint256 _id) constant returns(address); - function getUserAddress(string _login) constant returns(address); - -} \ No newline at end of file diff --git a/contracts/tests/index.test.js b/contracts/tests/index.test.js deleted file mode 100644 index 9dc9a79..0000000 --- a/contracts/tests/index.test.js +++ /dev/null @@ -1,36 +0,0 @@ -var assert = require('assert'); -var helper = require('ethereum-sandbox-helper'); -var Workbench = require('ethereum-sandbox-workbench'); - -var workbench = new Workbench({ - contractsDirectory: 'contracts', - solcVersion: '0.4.2', - defaults: { - from: '0xcd2a3d9f938e13cd947ec05abc7fe734df8dd826' - } -}); - -var contract; - -workbench.startTesting('contract', function(contracts) { - it('Deploy Contract', function() { - return contracts.Contract.new() - .then(function(result) { - if (result.address) contract = result; - else throw new Error('Contract is not deployed'); - return true; - }); - }); - - it('Prints string', function() { - var str = "hello, ethereum!"; - return contract.test(str) - .then(function(txHash) { - return workbench.waitForReceipt(txHash); - }) - .then(function (receipt) { - assert.equal(helper.hexToString(receipt.logs[0].data), str); - return true; - }); - }); -}); diff --git a/ethereum.json b/ethereum.json index 4735066..43136e9 100644 --- a/ethereum.json +++ b/ethereum.json @@ -1,7 +1,7 @@ { "contracts": "contracts", - "deploy": ["GitHubOracle"], + "deploy": ["DGit"], "plugins": { "oraclize": { diff --git a/scenarios/RegisterClaim.yaml b/scenarios/InitRegAddClaim.yaml similarity index 60% rename from scenarios/RegisterClaim.yaml rename to scenarios/InitRegAddClaim.yaml index 14f63d8..fd5dbc5 100644 --- a/scenarios/RegisterClaim.yaml +++ b/scenarios/InitRegAddClaim.yaml @@ -1,29 +1,36 @@ # # Scenario1 # -# Created on: 26/03/2017 03:32:05 +# Created on: 27/03/2017 03:30:55 # -# Call method addRepository(string) +# Call method initialize() - from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: '0xaefa01276783e1436e5b461c099edccb0448dcf6' - value: '0x16345785d8a0000' - call: addRepository(string) - args: - - status-im/github-oracle + to: '0x086ca7abad7f9773db72e2efd83dd22f5f408862' + value: '0x0' + call: initialize() + args: [] # Call method register(string,string) - from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: '0xaefa01276783e1436e5b461c099edccb0448dcf6' + to: '0x086ca7abad7f9773db72e2efd83dd22f5f408862' value: '0x0' call: 'register(string,string)' args: - 3esmit - 31a58f2ddf2258697cce1b969e7c298b +# Call method addRepository(string) +- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' + to: '0x086ca7abad7f9773db72e2efd83dd22f5f408862' + value: '0x8ac7230489e80000' + call: addRepository(string) + args: + - status-im/github-oracle + # Call method claimCommit(string,string) - from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: '0xaefa01276783e1436e5b461c099edccb0448dcf6' + to: '0x086ca7abad7f9773db72e2efd83dd22f5f408862' value: '0x0' call: 'claimCommit(string,string)' args: diff --git a/scripts/github-oracle/github_oracle.py b/scripts/github-oracle/github_oracle.py new file mode 100644 index 0000000..37f5ea8 --- /dev/null +++ b/scripts/github-oracle/github_oracle.py @@ -0,0 +1,101 @@ +import os, argparse +import json, urllib2, datetime +from collections import defaultdict +start = '' + +script = os.environ['ARG0'] +args = os.environ['ARG1'] +auth = os.environ['ARG2'] + + +if(auth): + #check if is client secret or token + + + + +repo_link = "" +if(args): + repo_link = "https://api.github.com/repos/" + args.reponame +else: + repo_link = "https://api.github.com/repositories/" + args.repoid + + + + +if script == 'issue-status': + issueStatus(args.issueid) +elif script == 'issue-commits': + issueCommits(args.issueid) +elif script == 'related-issues': + relatedIssues(args.issueid) +elif script == 'commit-points': + pullCommitPoints(args.pullid) +elif script == 'commit-data': + commitData(args.commit) + + + + + + + +def relatedIssues(issue): + link_issue = repo_link + "/issues/" + issue + "/timeline" + auth + print link_issue + req = urllib2.Request(link_issue) + req.add_header("Accept", "application/vnd.github.mockingbird-preview") + issue = json.load(urllib2.urlopen(req)) + for elem in issue: + if(elem["event"] == "cross-referenced"): + if(elem["source"]["type"] == "issue"): + #print elem["source"]["issue"]["number"]; + pullCommitPoints(json.dumps(elem["source"]["issue"]["number"])) + + + +def issueStatus(issue): + link_issue = repo_link + "/issues/" + issue + auth + issue = json.load(urllib2.urlopen(link_issue)) + if(issue['state'] == "closed"): + print datetime.datetime.strptime( json.dumps(issue['closed_at'])[1:-1], "%Y-%m-%dT%H:%M:%SZ" ).strftime('%s') +","+ json.dumps(issue['closed_by']['login']) + else: + print "open" + + +def pullCommitPoints(pr): + link_pull = repo_link + "/pulls/" + pr + auth + pull = json.load(urllib2.urlopen(link_pull)) + if(pull['merged_at']): + link_pulls_commits = repo_link + "/pulls/" + pr + "/commits" +auth + points = defaultdict(int) + commits = json.load(urllib2.urlopen(link_pulls_commits)) + for commit in commits: + if(commit['url']): + link_commit = json.dumps(commit['url'])[1:-1] +auth + _commit = json.load(urllib2.urlopen(link_commit)) + author = json.dumps(_commit['author']['login'])[1:-1] + points[author] += int(json.dumps(_commit['stats']['total'])) + print points.items() + + +def issueCommits(args.issueid): + link_issue = repo_link + "/issues/" + issue + "/timeline" + auth + req = urllib2.Request(link_issue) + req.add_header("Accept", "application/vnd.github.mockingbird-preview") + issue = json.load(urllib2.urlopen(req)) + for elem in issue: + if(elem["event"] == "cross-referenced"): + if(elem["source"]["type"] == "issue"): + #print elem["source"]["issue"]["number"]; + pullCommitPoints(json.dumps(elem["source"]["issue"]["number"])) + +def commitData(commit): + link_commit = repo_link +"/commits/"+ commit; + req = urllib2.Request(link_commit) + req.add_header("Accept", "application/vnd.github.mockingbird-preview") + commit = json.load(urllib2.urlopen(req)) + print json.dumps(commit) + + +