mirror of
https://github.com/status-im/gitpivot.git
synced 2026-08-27 08:31:17 +00:00
gitpivot upgradability
This commit is contained in:
@@ -1,16 +1,12 @@
|
||||
# GitHubOracle
|
||||
# GitPivot
|
||||
|
||||
Ethereum application to incentive open-source development in GitHub by opening direct fair payment channels for bounties and indirect payments through tokenization of commits.
|
||||
|
||||
This project was formely known as GitHubTokens, created to tokenize contributions of [TheEtherian news platform](https://etherian.world/).
|
||||
|
||||
The project become embraced by [Status Network](status.im) that will integrate it as backend of a trustless [Commiteth](https://github.com/status-im/commiteth).
|
||||
|
||||
## System Features
|
||||
|
||||
### Configurable reward modes by project
|
||||
|
||||
For a project being accepted by GitHubOracle it must have a file in root of tree called `.gitpoints` with specifing `user-agent:` to `*` or `githuboracle`.
|
||||
For a project being accepted by GitPivot it must have a file in root of tree called `.gitpoints` with specifing `user-agent:` to `*` or `GitPivot`.
|
||||
|
||||
Example:
|
||||
|
||||
@@ -26,8 +22,8 @@ reactions-reward: heart, +1
|
||||
|
||||
### GitHub User Ethereum Address
|
||||
|
||||
To control GitHubOracle users need to link their GitHub user login to an ethereum address.
|
||||
User calls GitHubOracle and passes his username and the gistid, GitHubOracle registers users by loading gistid file called `register.txt` under user `login`. This file must contain only the ethereum address who made the register call, starting with `0x`.
|
||||
To control GitPivot users need to link their GitHub user login to an ethereum address.
|
||||
User calls GitPivot and passes his username and the gistid, GitPivot registers users by loading gistid file called `register.txt` under user `login`. This file must contain only the ethereum address who made the register call, starting with `0x`.
|
||||
|
||||
### Tokenize project merged contributions
|
||||
|
||||
@@ -43,7 +39,7 @@ Repositories that enabled tokenizations of contributions also have a DonationBan
|
||||
|
||||
### Reward bounties by contribuion in GitHub Issues.
|
||||
|
||||
Issues may be tracked by GitHubOracle, accept payments, depending on the `.gitpoints` configuration, positively reacted posts and merged pull requests/commits generate points that allow issue contributors to withdraw a fair share of balances related to the issue.
|
||||
Issues may be tracked by GitPivot, accept payments, depending on the `.gitpoints` configuration, positively reacted posts and merged pull requests/commits generate points that allow issue contributors to withdraw a fair share of balances related to the issue.
|
||||
|
||||
## Network Features
|
||||
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
import "./common/Controlled.sol";
|
||||
import "./common/oraclizeAPI_0.4.sol";
|
||||
import "./common/strings.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title GitHubAPIReg.sol
|
||||
* Abstract Logic for GitHubOracle Registries.
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
*/
|
||||
contract GitHubAPIReg is Controlled, usingOraclize {
|
||||
using strings for string;
|
||||
using strings for strings.slice;
|
||||
|
||||
string cred = "";
|
||||
|
||||
event OracleEvent(bytes32 myid, string result, bytes proof);
|
||||
|
||||
function GitHubAPIReg() {
|
||||
oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);
|
||||
}
|
||||
|
||||
//owner management
|
||||
function setAPICredentials(string _client_id, string _client_secret) public onlyController {
|
||||
strings.slice[] memory cm = new strings.slice[](5);
|
||||
cm[0] = strings.toSlice("?client_id=");
|
||||
cm[1] = _client_id.toSlice();
|
||||
cm[2] = strings.toSlice("&client_secret=");
|
||||
cm[4] = _client_secret.toSlice();
|
||||
cred = strings.toSlice("").join(cm);
|
||||
}
|
||||
|
||||
function clearAPICredentials() public onlyController {
|
||||
cred = "";
|
||||
}
|
||||
|
||||
function getNextString(bytes _str, uint8 _pos) internal returns (string, uint8) {
|
||||
uint8 start = 0;
|
||||
uint8 end = 0;
|
||||
uint strl =_str.length;
|
||||
for (;strl > _pos; _pos++) {
|
||||
if (_str[_pos] == "\"") { //Found quotation mark
|
||||
if (_str[_pos-1] != "\\") { //is not escaped
|
||||
end = start == 0 ? 0: _pos;
|
||||
start = start == 0 ? (_pos+1) : start;
|
||||
if(end > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bytes memory str = new bytes(end-start);
|
||||
for (_pos=0; _pos<str.length; _pos++) {
|
||||
str[_pos] = _str[start+_pos];
|
||||
}
|
||||
for (_pos = end + 1; _pos < _str.length; _pos++) {
|
||||
if (_str[_pos] == ',') {
|
||||
_pos++;
|
||||
break;
|
||||
}
|
||||
} //end
|
||||
return (string(str), _pos);
|
||||
}
|
||||
|
||||
function getNextUInt(bytes _str, uint8 _pos) internal returns (uint, uint8) {
|
||||
uint val = 0;
|
||||
uint strl =_str.length;
|
||||
for (; strl > _pos; _pos++) {
|
||||
byte bp = _str[_pos];
|
||||
if (bp == ",") {//Find ends
|
||||
_pos++; break;
|
||||
} else if ((bp >= 48) && (bp <= 57)) { //only ASCII numbers
|
||||
val *= 10;
|
||||
val += uint(bp) - 48;
|
||||
}
|
||||
}
|
||||
return (val, _pos);
|
||||
}
|
||||
|
||||
function getNextAddr(bytes _str, uint8 _pos) internal returns (address, uint8) {
|
||||
uint160 iaddr = 0;
|
||||
uint strl =_str.length;
|
||||
for (;strl > _pos; _pos++) {
|
||||
byte bp = _str[_pos];
|
||||
if (bp == "0") {
|
||||
if (_str[_pos+1] == "x") {
|
||||
for (_pos=_pos+2; _pos<2+2*20; _pos+=2) {
|
||||
iaddr *= 256;
|
||||
iaddr += (uint160(hexVal(uint160(_str[_pos])))*16+uint160(hexVal(uint160(_str[_pos+1]))));
|
||||
}
|
||||
_pos++;
|
||||
break;
|
||||
}
|
||||
}else if (bp == ",") {
|
||||
_pos++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (address(iaddr), _pos);
|
||||
}
|
||||
|
||||
function hexVal(uint val) internal returns (uint) {
|
||||
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
|
||||
}
|
||||
|
||||
}
|
||||
+7
-14
@@ -4,13 +4,13 @@ import "./common/Controlled.sol";
|
||||
import "./PointsOracle.sol";
|
||||
import "./UserOracle.sol";
|
||||
import "./RepositoryOracle.sol";
|
||||
|
||||
import "./IGitPivot.sol";
|
||||
|
||||
/**
|
||||
* @title GitPivot.sol
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
*/
|
||||
contract GitPivot is Controlled, DGitI {
|
||||
contract GitPivot is Controlled, IGitPivot {
|
||||
|
||||
UserOracle public userOracle;
|
||||
RepositoryOracle public repositoryOracle;
|
||||
@@ -40,7 +40,7 @@ contract GitPivot is Controlled, DGitI {
|
||||
function getRepository(string _repository, string _branch) public constant returns (uint repoId) {
|
||||
repoId = repositoryOracle.getId(_repository);
|
||||
require(repoId != 0);
|
||||
require(repositoryOracle.getBranch(repoId) == keccak256(_branch));
|
||||
require(repositoryOracle.branch(repoId) == keccak256(_branch));
|
||||
}
|
||||
|
||||
function start(string _repository, string _branch, string _token) public payable {
|
||||
@@ -96,7 +96,7 @@ contract GitPivot is Controlled, DGitI {
|
||||
|
||||
//claims pending points
|
||||
function claimPending(uint _repoId, uint _userId) public {
|
||||
GitRepositoryI repoaddr = GitRepositoryI(repositoryOracle.getAddr(_repoId));
|
||||
GitRepository repoaddr = GitRepository(repositoryOracle.getAddr(_repoId));
|
||||
uint total = pending[_userId][_repoId];
|
||||
delete pending[_userId][_repoId];
|
||||
require(repoaddr.claim(userOracle.getAddr(_userId), total));
|
||||
@@ -126,13 +126,6 @@ contract GitPivot is Controlled, DGitI {
|
||||
}
|
||||
}
|
||||
|
||||
function upgrade(uint[] _repoIds) public onlyUpgrading onlyController {
|
||||
uint len = _repoIds.length;
|
||||
for (uint i = 0; i < len; i++) {
|
||||
Controlled(repositoryOracle.getAddr(_repoIds[i])).changeController(newContract);
|
||||
}
|
||||
}
|
||||
|
||||
function pendingScan(uint256 _projectId, string _lastCommit, string _pendingTail) public package {
|
||||
repositories[_projectId].pending[_pendingTail] = _lastCommit;
|
||||
}
|
||||
@@ -154,7 +147,7 @@ contract GitPivot is Controlled, DGitI {
|
||||
public
|
||||
package
|
||||
{
|
||||
GitRepositoryI repo = GitRepositoryI(repositoryOracle.getAddr(_projectId));
|
||||
GitRepository repo = GitRepository(repositoryOracle.getAddr(_projectId));
|
||||
repo.setBounty(_issueId, _state, _closedAt);
|
||||
}
|
||||
|
||||
@@ -167,7 +160,7 @@ contract GitPivot is Controlled, DGitI {
|
||||
public
|
||||
package
|
||||
{
|
||||
GitRepositoryI repo = GitRepositoryI(repositoryOracle.getAddr(_projectId));
|
||||
GitRepository repo = GitRepository(repositoryOracle.getAddr(_projectId));
|
||||
uint len = _userId.length;
|
||||
for (uint i = 0; i < len; i++) {
|
||||
address addr = userOracle.getAddr(_userId[i]);
|
||||
@@ -176,7 +169,7 @@ contract GitPivot is Controlled, DGitI {
|
||||
}
|
||||
|
||||
function newPoints(uint _repoId, uint[] _userIds, uint[] _points) public package {
|
||||
GitRepositoryI repo = GitRepositoryI(repositoryOracle.getAddr(_repoId));
|
||||
GitRepository repo = GitRepository(repositoryOracle.getAddr(_repoId));
|
||||
uint len = _userIds.length;
|
||||
for (uint i = 0; i < len; i++) {
|
||||
uint _userId = _userIds[i];
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
pragma solidity ^0.4.17;
|
||||
|
||||
import "./deploy/AbstractRecoverer.sol";
|
||||
|
||||
contract ENS {
|
||||
function owner(bytes32 node) constant returns (address);
|
||||
function resolver(bytes32 node) constant returns (Resolver);
|
||||
function ttl(bytes32 node) constant returns (uint64);
|
||||
function setOwner(bytes32 node, address owner);
|
||||
function setSubnodeOwner(bytes32 node, bytes32 label, address owner);
|
||||
function setResolver(bytes32 node, address resolver);
|
||||
function setTTL(bytes32 node, uint64 ttl);
|
||||
}
|
||||
|
||||
contract Resolver {
|
||||
function addr(bytes32 node) constant returns (address);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @title GitPivotRecoverer
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
* @dev Common Recoverer for GitPivot.
|
||||
* address resolved from ens recover.gitpivot.eth can set new system.
|
||||
*/
|
||||
contract GitPivotRecoverer is BasicSystemStorage {
|
||||
|
||||
/**
|
||||
* @dev will be callable in emergency state of RecorverableSystem
|
||||
*/
|
||||
function recoverSystem(address newSystem) public {
|
||||
require(msg.sender == consensusContract());
|
||||
system = newSystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev resolves recover.gitpivot.eth
|
||||
*/
|
||||
function consensusContract() public constant returns(address) {
|
||||
bytes32 node = 0xa33a22622efdf12b4175a11fbc58ec45d4e93a0160952cc8e48867c5c50a3404; //recover.gitpivot.eth //bytes32 node = keccak256("recover", keccak256("gitpivot", keccak256("eth")));
|
||||
address ensAddress = 0x314159265dD8dbb310642f98f50C066173C1259b;
|
||||
if (codeSize(ensAddress) == 0) {
|
||||
return 0x41CaB970f931F2EC3195C416B8Fa65e99814e7aF; //ensAddress = 0x112234455C3a32FD11230C42E7Bccd4A84e02010;
|
||||
}
|
||||
return ENS(ensAddress).resolver(node).addr(node);
|
||||
}
|
||||
|
||||
function codeSize(address _addr) internal constant returns(uint size) {
|
||||
if (_addr == 0) {
|
||||
return 0;
|
||||
}
|
||||
assembly {
|
||||
size := extcodesize(_addr)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +1,16 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
import "./bank/CollaborationBank.sol";
|
||||
import "./bank/BountyBank.sol";
|
||||
import "./common/Controlled.sol";
|
||||
|
||||
|
||||
contract GitRepositoryI is Controlled {
|
||||
function claim(address _user, uint _total) returns (bool);
|
||||
function setBounty(uint256 _issueId, bool _state, uint256 _closedAt);
|
||||
function setBountyPoints(uint256 _issueId, address _claimer, uint256 _points);
|
||||
}
|
||||
|
||||
import "./IGitRepository.sol";
|
||||
|
||||
/**
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
*/
|
||||
contract GitRepository is TokenController, GitRepositoryI {
|
||||
contract GitRepository is IGitRepository, Controlled, TokenController {
|
||||
|
||||
MiniMeToken public token;
|
||||
CollaborationBank public donationBank;
|
||||
BountyBank public bountyBank;
|
||||
|
||||
string public name;
|
||||
uint256 public uid;
|
||||
@@ -27,7 +18,6 @@ contract GitRepository is TokenController, GitRepositoryI {
|
||||
function GitRepository(uint256 _uid, string _name) {
|
||||
uid = _uid;
|
||||
name = _name;
|
||||
bountyBank = new BountyBank();
|
||||
}
|
||||
|
||||
function setDonationBank(MiniMeToken _token, uint _epochLenght) public onlyController {
|
||||
@@ -44,14 +34,15 @@ contract GitRepository is TokenController, GitRepositoryI {
|
||||
}
|
||||
|
||||
function setBounty(uint256 _issueId, bool _state, uint256 _closedAt) public onlyController {
|
||||
if (_state)
|
||||
bountyBank.open(_issueId);
|
||||
else
|
||||
bountyBank.close(_issueId, _closedAt);
|
||||
if (_state) {
|
||||
//TODO: open issue
|
||||
} else {
|
||||
//TODO: close issue
|
||||
}
|
||||
}
|
||||
|
||||
function setBountyPoints(uint256 _issueId, address _claimer, uint256 _points) public onlyController {
|
||||
bountyBank.setClaimer(_issueId, _claimer, _points);
|
||||
//TODO: set points
|
||||
}
|
||||
|
||||
function proxyPayment(address) public payable returns(bool) {
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
*/
|
||||
contract IGitPivot {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function setHead(uint256 projectId, string head) public;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function setTail(uint256 projectId, string tail) public;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function newPoints(uint256 projectId, uint256[] userIds, uint[] totals) public;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function pendingScan(uint256 projectId, string lastCommit, string pendingTail) public;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function setIssue(
|
||||
uint256 projectId,
|
||||
uint256 issueId,
|
||||
bool state,
|
||||
uint256 closedAt) public;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function setIssuePoints(
|
||||
uint256 projectId,
|
||||
uint256 issueId,
|
||||
uint256[] userIds,
|
||||
uint256[] points) public;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
|
||||
contract IGitRepository {
|
||||
function claim(address _user, uint _total) returns (bool);
|
||||
function setBounty(uint256 _issueId, bool _state, uint256 _closedAt);
|
||||
function setBountyPoints(uint256 _issueId, address _claimer, uint256 _points);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
import "./common/strings.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title JSONHelper
|
||||
* Abstract Logic for JSON responses from Oracle
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
*/
|
||||
contract JSONHelper {
|
||||
|
||||
function getCredentialString(string _clientId, string _clientSecret) internal returns (string cred) {
|
||||
strings.slice[] memory cm = new strings.slice[](4);
|
||||
cm[0] = strings.toSlice("?client_id=");
|
||||
cm[1] = strings.toSlice(_clientId);
|
||||
cm[2] = strings.toSlice("&client_secret=");
|
||||
cm[3] = strings.toSlice(_clientSecret);
|
||||
cred = strings.join(cm);
|
||||
}
|
||||
|
||||
function getNextString(bytes _str, uint256 _pos) internal pure returns (string str, uint256 next) {
|
||||
var (start, end) = findStringBounds(_str, _pos);
|
||||
str = string(copyBytesPart(_str, start, end));
|
||||
next = findNextChar(_str, end, ",") + 1;
|
||||
}
|
||||
|
||||
function getNextAddr(bytes _str, uint256 _pos) internal pure returns (address, uint256) {
|
||||
uint160 iaddr = 0;
|
||||
uint len = _str.length;
|
||||
for (; len > _pos; _pos++) {
|
||||
byte bp = _str[_pos];
|
||||
if (bp == "0") {
|
||||
if (_str[_pos+1] == "x") {
|
||||
for (_pos = _pos+2; _pos < 2 + 2 * 20; _pos += 2) {
|
||||
iaddr *= 256;
|
||||
iaddr += (uint160(hexVal(uint160(_str[_pos])))*16+uint160(hexVal(uint160(_str[_pos+1]))));
|
||||
}
|
||||
_pos++;
|
||||
break;
|
||||
}
|
||||
}else if (bp == ",") {
|
||||
_pos++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (address(iaddr), _pos);
|
||||
}
|
||||
|
||||
function getNextUInt(bytes _str, uint256 _pos) internal pure returns (uint, uint256) {
|
||||
uint val = 0;
|
||||
uint len = _str.length;
|
||||
for (; len > _pos; _pos++) {
|
||||
byte bp = _str[_pos];
|
||||
if (bp == ",") {//Find ends
|
||||
_pos++;
|
||||
break;
|
||||
} else if ((bp >= 48) && (bp <= 57)) { //only ASCII numbers
|
||||
val *= 10;
|
||||
val += uint(bp) - 48;
|
||||
}
|
||||
}
|
||||
return (val, _pos);
|
||||
}
|
||||
|
||||
function hexVal(uint val) internal pure returns (uint) {
|
||||
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
|
||||
}
|
||||
|
||||
function copyBytesPart(bytes _src, uint256 _start, uint256 _end) private pure returns (bytes res) {
|
||||
uint256 len = _end - _start;
|
||||
res = new bytes(len);
|
||||
for (uint i = 0; i < len; i++) {
|
||||
res[i] = _src[_start + i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Finds next char. Retuns _str length case not found.
|
||||
*/
|
||||
function findNextChar(bytes _str, uint256 _start, byte _char) private pure returns(uint256 pos) {
|
||||
uint256 len = _str.length;
|
||||
for (pos = _start + 1; pos < len; pos++) {
|
||||
if (_str[pos] == _char) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Finds JSON string bounds: first unescaped " and next unescaped" . Returns 0,0 case not found.
|
||||
* @param _str The converted to bytes string.
|
||||
* @param _offset The search offset into _str
|
||||
*/
|
||||
function findStringBounds(bytes _str, uint256 _offset) private pure returns (uint256 start, uint256 end) {
|
||||
uint256 len = _str.length;
|
||||
for (uint256 _pos = _offset; _pos < len; _pos++) {
|
||||
if (_str[_pos] == "\"") {
|
||||
if (_pos == 0 || _str[_pos-1] != "\\") { //is not escaped
|
||||
end = start == 0 ? 0 : _pos;
|
||||
start = start == 0 ? (_pos+1) : start;
|
||||
if (end > 0) {
|
||||
return (start, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0, 0);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
pragma solidity ^0.4.4;
|
||||
|
||||
|
||||
contract Migrations {
|
||||
address public owner;
|
||||
uint public last_completed_migration;
|
||||
|
||||
modifier restricted() {
|
||||
if (msg.sender == owner) _;
|
||||
if (msg.sender == owner)
|
||||
_;
|
||||
}
|
||||
|
||||
function Migrations() {
|
||||
@@ -21,5 +21,4 @@ contract Migrations {
|
||||
Migrations upgraded = Migrations(new_address);
|
||||
upgraded.setCompleted(last_completed_migration);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-108
@@ -1,61 +1,17 @@
|
||||
pragma solidity ^0.4.10;
|
||||
|
||||
import "./common/oraclizeAPI_0.4.sol";
|
||||
import "./common/Controlled.sol";
|
||||
import "./common/strings.sol";
|
||||
import "./oraclize/oraclizeAPI_0.4.sol";
|
||||
import "./JSONHelper.sol";
|
||||
import "./IGitPivot.sol";
|
||||
import "./deploy/KillableModel.sol";
|
||||
|
||||
/**
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
*/
|
||||
contract GitPivotI {
|
||||
contract PointsOracle is KillableModel, Controlled, JSONHelper, usingOraclize {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function setHead(uint256 projectId, string head) public;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function setTail(uint256 projectId, string tail) public;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function newPoints(uint256 projectId, uint256[] userIds, uint[] totals) public;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function pendingScan(uint256 projectId, string lastCommit, string pendingTail) public;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function setIssue(
|
||||
uint256 projectId,
|
||||
uint256 issueId,
|
||||
bool state,
|
||||
uint256 closedAt) public;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function setIssuePoints(
|
||||
uint256 projectId,
|
||||
uint256 issueId,
|
||||
uint256[] userIds,
|
||||
uint256[] points) public;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
*/
|
||||
contract PointsOracle is Controlled, usingOraclize {
|
||||
|
||||
event OracleEvent(bytes32 myid, string result, bytes proof);
|
||||
using strings for string;
|
||||
using strings for strings.slice;
|
||||
|
||||
@@ -220,7 +176,6 @@ contract PointsOracle is Controlled, usingOraclize {
|
||||
*
|
||||
*/
|
||||
function __callback(bytes32 myid, string result, bytes proof) public {
|
||||
OracleEvent(myid, result, proof);
|
||||
require (msg.sender == oraclize.cbAddress());
|
||||
processRequest(bytes(result), request[myid]);
|
||||
delete request[myid];
|
||||
@@ -232,8 +187,8 @@ contract PointsOracle is Controlled, usingOraclize {
|
||||
function processRequest(bytes v, Request _request)
|
||||
internal
|
||||
{
|
||||
GitPivotI pivot = GitPivotI(controller);
|
||||
uint8 pos = 0;
|
||||
IGitPivot pivot = IGitPivot(controller);
|
||||
uint256 pos = 0;
|
||||
string memory temp;
|
||||
uint256 projectId;
|
||||
uint256 issueId;
|
||||
@@ -441,60 +396,4 @@ contract PointsOracle is Controlled, usingOraclize {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function getNextString(bytes _str, uint8 _pos)
|
||||
internal
|
||||
constant
|
||||
returns (string, uint8)
|
||||
{
|
||||
uint8 _start = 0;
|
||||
uint8 end = 0;
|
||||
uint strl = _str.length;
|
||||
for (;strl > _pos; _pos++) {
|
||||
if (_str[_pos] == "\"") { //Found quotation mark
|
||||
if (_str[_pos-1] != "\\") { //is not escaped
|
||||
end = _start == 0 ? 0 : _pos;
|
||||
_start = _start == 0 ? (_pos + 1) : _start;
|
||||
if (end > 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
bytes memory str = new bytes(end - _start);
|
||||
for (_pos = 0; _pos < str.length; _pos++) {
|
||||
str[_pos] = _str[_start + _pos];
|
||||
}
|
||||
for (_pos = end + 1; _pos < _str.length; _pos++) {
|
||||
if (_str[_pos] == ",") {
|
||||
_pos++;
|
||||
break;
|
||||
} //end
|
||||
}
|
||||
return (string(str), _pos);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function getNextUInt(bytes _str, uint8 _continue)
|
||||
internal
|
||||
constant
|
||||
returns (uint val, uint8 _pos)
|
||||
{
|
||||
val = 0;
|
||||
uint strl = _str.length;
|
||||
for (_pos = _continue; strl > _pos; _pos++) {
|
||||
byte bp = _str[_pos];
|
||||
if (bp == ",") { //Find ends
|
||||
_pos++;
|
||||
break;
|
||||
} else if ((bp >= 48)&&(bp <= 57)) { //only ASCII numbers
|
||||
val *= 10;
|
||||
val += uint(bp) - 48;
|
||||
}
|
||||
}
|
||||
return (val, _pos);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,22 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
import "./GitHubAPIReg.sol";
|
||||
import "./JSONHelper.sol";
|
||||
import "./management/RegistryIndex.sol";
|
||||
import "./GitRepository.sol";
|
||||
import "./common/strings.sol";
|
||||
|
||||
import "./common/Controlled.sol";
|
||||
import "./deploy/KillableModel.sol";
|
||||
import "./oraclize/oraclizeAPI_0.4.sol";
|
||||
|
||||
/**
|
||||
* @title RepositoryOracle
|
||||
* Registers the master branch of a Repository for GitHubOracle tracking.
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)]
|
||||
*/
|
||||
contract RepositoryOracle is GitHubAPIReg, RegistryIndex {
|
||||
contract RepositoryOracle is KillableModel, Controlled, RegistryIndex, JSONHelper, usingOraclize {
|
||||
using strings for string;
|
||||
using strings for strings.slice;
|
||||
|
||||
string private cred = "";
|
||||
mapping (uint256 => bytes32) public branch;
|
||||
|
||||
event NewRepository(address addr, uint256 projectId, string fullName, string defaultBranch);
|
||||
@@ -33,7 +35,7 @@ contract RepositoryOracle is GitHubAPIReg, RegistryIndex {
|
||||
|
||||
//oraclize response callback
|
||||
function __callback(bytes32 myid, string result, bytes proof) {
|
||||
OracleEvent(myid, result, proof);
|
||||
//OracleEvent(myid, result, proof);
|
||||
require(msg.sender == oraclize.cbAddress());
|
||||
_setRepository(result);
|
||||
}
|
||||
@@ -42,7 +44,7 @@ contract RepositoryOracle is GitHubAPIReg, RegistryIndex {
|
||||
internal //[85743750, "ethereans/TheEtherian", "master"]
|
||||
{
|
||||
bytes memory v = bytes(result);
|
||||
uint8 pos = 0;
|
||||
uint256 pos = 0;
|
||||
uint256 projectId;
|
||||
(projectId, pos) = getNextUInt(v, pos);
|
||||
string memory full_name;
|
||||
@@ -52,13 +54,14 @@ contract RepositoryOracle is GitHubAPIReg, RegistryIndex {
|
||||
address repoAddr = registry[projectId].addr;
|
||||
if (repoAddr == 0x0) {
|
||||
NewRepository(repoAddr, projectId, full_name, default_branch);
|
||||
GitRepositoryI repo = new GitRepository(projectId, full_name);
|
||||
GitRepository repo = new GitRepository(projectId, full_name);
|
||||
repo.changeController(controller);
|
||||
repoAddr = address(repo);
|
||||
branch[projectId] = keccak256(default_branch);
|
||||
setRegistry(repoAddr, projectId, full_name);
|
||||
setRegistry(projectId, repoAddr, full_name);
|
||||
} else {
|
||||
updateIndex(repositories[projectId].name, full_name);
|
||||
revert(); //TODO: update name
|
||||
//updateIndex(registry[projectId], full_name);
|
||||
}
|
||||
}
|
||||
//internal helper functions
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.17;
|
||||
|
||||
import "./GitHubAPIReg.sol";
|
||||
import "./common/strings.sol";
|
||||
import "./deploy/KillableModel.sol";
|
||||
import "./JSONHelper.sol";
|
||||
import "./oraclize/oraclizeAPI_0.4.sol";
|
||||
import "./common/Controlled.sol";
|
||||
import "./management/RegistryIndex.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title GitHubUserReg.sol
|
||||
* Registers GitHub user login to an address
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)]
|
||||
*/
|
||||
contract UserOracle is GitHubAPIReg, RegistryIndex {
|
||||
contract UserOracle is KillableModel, Controlled, RegistryIndex, JSONHelper, usingOraclize {
|
||||
using strings for string;
|
||||
using strings for strings.slice;
|
||||
|
||||
mapping (bytes32 => UserClaim) userClaim; //temporary db for oraclize user register queries
|
||||
string private cred = "";
|
||||
|
||||
mapping (bytes32 => UserClaim) userClaim; //temporary db for oraclize user register queries
|
||||
|
||||
event RegisterUpdated(string name);
|
||||
|
||||
@@ -24,8 +28,8 @@ contract UserOracle is GitHubAPIReg, RegistryIndex {
|
||||
string login;
|
||||
}
|
||||
|
||||
|
||||
function register(string _githubUser, string _gistId, string _cred) public payable {
|
||||
require(watchdog != 0x0);
|
||||
if (bytes(_cred).length == 0) {
|
||||
_cred = cred;
|
||||
}
|
||||
@@ -33,17 +37,16 @@ contract UserOracle is GitHubAPIReg, RegistryIndex {
|
||||
userClaim[ocid] = UserClaim({sender: msg.sender, login: _githubUser});
|
||||
}
|
||||
|
||||
|
||||
//oraclize response callback
|
||||
function __callback(bytes32 myid, string result, bytes proof) public {
|
||||
OracleEvent(myid, result, proof);
|
||||
//OracleEvent(myid, result, proof);
|
||||
require(msg.sender == oraclize.cbAddress());
|
||||
_register(myid, result);
|
||||
}
|
||||
|
||||
function _register(bytes32 myid, string result) internal {
|
||||
bytes memory v = bytes(result);
|
||||
uint8 pos = 0;
|
||||
uint256 pos = 0;
|
||||
address addrLoaded;
|
||||
string memory login;
|
||||
uint256 userId;
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
import "../common/Controlled.sol";
|
||||
|
||||
/**
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
*/
|
||||
contract BountyBank is Controlled {
|
||||
|
||||
enum State {CLOSED, OPEN, CLAIMED}
|
||||
|
||||
struct Bounty {
|
||||
State state;
|
||||
uint closedAt;
|
||||
mapping (address => uint) deposits;
|
||||
mapping (address => uint) claimers;
|
||||
uint balance;
|
||||
uint points;
|
||||
}
|
||||
|
||||
mapping (uint => Bounty) bounties;
|
||||
uint count = 0;
|
||||
|
||||
function deposit(uint num) payable {
|
||||
require(bounties[num].state == State.OPEN);
|
||||
require(msg.value > 0);
|
||||
bounties[num].deposits[msg.sender] += msg.value;
|
||||
bounties[num].balance += msg.value;
|
||||
}
|
||||
|
||||
function withdraw(uint num) {
|
||||
uint value = bounties[num].deposits[msg.sender];
|
||||
require(bounties[num].state == State.OPEN && value > 0);
|
||||
delete bounties[num].deposits[msg.sender];
|
||||
msg.sender.transfer(value);
|
||||
}
|
||||
|
||||
function open(uint num) onlyController {
|
||||
require(bounties[num].state != State.CLAIMED);
|
||||
bounties[num].state = State.OPEN;
|
||||
}
|
||||
|
||||
function setClaimer(uint num, address claimer, uint points) onlyController {
|
||||
require(bounties[num].state != State.CLAIMED);
|
||||
bounties[num].claimers[claimer] += points;
|
||||
bounties[num].points += points;
|
||||
}
|
||||
|
||||
function close(uint num, uint _closedAt) onlyController {
|
||||
require(bounties[num].state != State.CLAIMED);
|
||||
bounties[num].state = State.CLOSED;
|
||||
bounties[num].closedAt = _closedAt;
|
||||
}
|
||||
|
||||
function claim(uint num) {
|
||||
require (bounties[num].state != State.OPEN);
|
||||
uint totalPoints = bounties[num].points;
|
||||
require (totalPoints > 0);
|
||||
uint points = bounties[num].claimers[msg.sender];
|
||||
require (points > 0);
|
||||
delete bounties[num].claimers[msg.sender];
|
||||
uint award = (bounties[num].balance / totalPoints)*points;
|
||||
bounties[num].points -= points;
|
||||
bounties[num].balance -= award;
|
||||
msg.sender.transfer(award);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
pragma solidity ^0.4.10;
|
||||
|
||||
import "../common/MiniMeToken.sol";
|
||||
import "../common/Controlled.sol";
|
||||
import "../token/MiniMeToken.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title CollaborationBank
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
* @dev Share profit between tokenholders.
|
||||
*/
|
||||
contract CollaborationBank is Controlled {
|
||||
|
||||
@@ -21,7 +24,7 @@ contract CollaborationBank is Controlled {
|
||||
uint256 public epochLenght;
|
||||
uint256 public firstEpoch;
|
||||
|
||||
function CollaborationBank(MiniMeToken _token, uint _epochLenght) {
|
||||
function CollaborationBank(MiniMeToken _token, uint _epochLenght) public {
|
||||
epochLenght = _epochLenght;
|
||||
firstEpoch = currentEpoch();
|
||||
token = _token;
|
||||
|
||||
@@ -1,37 +1,51 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
import "../management/TokenLedger.sol";
|
||||
import "../token/TokenLedger.sol";
|
||||
import "../common/Controlled.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title IssueBank
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
* Enable deposits to be withdrawn by points recievers
|
||||
* @dev Model (library) contract to set agreement between a repository owner and GitPivot
|
||||
* about the bounty winners.
|
||||
**/
|
||||
contract IssueBank is Controlled, TokenLedger {
|
||||
enum State {OPEN, REFUND, REWARD, FINALIZED }
|
||||
State public state;
|
||||
uint public points;
|
||||
uint public refundNonce;
|
||||
mapping (address => Reward) public rewards;
|
||||
address public repoOwner;
|
||||
|
||||
contract IssueBankModel is Controlled, TokenLedger {
|
||||
|
||||
address public owner; //repository owner
|
||||
mapping (address => Reward) public rewards; //bounty winners candidates
|
||||
uint public points; //remaining points to be claimed
|
||||
State public state; //current issue state
|
||||
|
||||
enum State { OPEN, REFUND, REWARD, FINALIZED }
|
||||
|
||||
struct Reward {
|
||||
bool active;
|
||||
bool active; // repository owner can activate
|
||||
uint points;
|
||||
}
|
||||
|
||||
modifier onlyRepoOwner{
|
||||
require (msg.sender == repoOwner);
|
||||
modifier onlyOwner{
|
||||
require (msg.sender == owner);
|
||||
_;
|
||||
}
|
||||
|
||||
function IssueBank(address _repoOwner) {
|
||||
repoOwner = _repoOwner;
|
||||
/**
|
||||
* @dev Model Constructor: Generates a locked state for model being unusable
|
||||
**/
|
||||
function IssueBankModel() public {
|
||||
owner = 0x0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Instance Constructor: Actual agreement logic initialization.
|
||||
* @param _owner Repository owner which will accept bounty winners and finalize issue.
|
||||
**/
|
||||
function IssueBank(address _owner) public {
|
||||
require(controller == 0x0);
|
||||
controller = msg.sender;
|
||||
owner = _owner;
|
||||
state = State.OPEN;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @notice deposit ether in bank
|
||||
**/
|
||||
@@ -54,6 +68,16 @@ contract IssueBank is Controlled, TokenLedger {
|
||||
_reward(_tokens);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @notice Repository owner can replace his address
|
||||
* @param _newOwner
|
||||
**/
|
||||
function updateOwner(address _newOwner) onlyOwner {
|
||||
require(_newOwner != 0x0);
|
||||
owner = _newOwner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice only contoller may set reward to a single address.
|
||||
* @param _claimer the beneficiary
|
||||
@@ -84,7 +108,7 @@ contract IssueBank is Controlled, TokenLedger {
|
||||
* @notice only the repo owner may confirm reward of addresses
|
||||
* @param _claimers array of addresses that are eligible to reward
|
||||
**/
|
||||
function confirm(address[] _claimers) onlyRepoOwner {
|
||||
function confirm(address[] _claimers) onlyOwner {
|
||||
uint len = _claimers.length;
|
||||
uint nPoints = 0;
|
||||
for (uint i = 0; i < len; i++) {
|
||||
@@ -100,7 +124,7 @@ contract IssueBank is Controlled, TokenLedger {
|
||||
* @notice only the repo owner may confirm reward of single address
|
||||
* @param _claimer the address that is eligible to reward
|
||||
**/
|
||||
function confirm(address _claimer) onlyRepoOwner {
|
||||
function confirm(address _claimer) onlyOwner {
|
||||
require(!rewards[_claimer].active);
|
||||
rewards[_claimer].active = true;
|
||||
points += rewards[_claimer].points;
|
||||
@@ -110,7 +134,7 @@ contract IssueBank is Controlled, TokenLedger {
|
||||
* @notice only repo owner can close deposits and start reward or refund
|
||||
* If no points confirmed the system will start refund, otherwise reward
|
||||
*/
|
||||
function close() onlyRepoOwner {
|
||||
function close() onlyOwner {
|
||||
require(state == State.OPEN);
|
||||
state = points > 0 ? State.REWARD : State.REFUND;
|
||||
}
|
||||
@@ -128,47 +152,51 @@ contract IssueBank is Controlled, TokenLedger {
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Withdraw tokens
|
||||
* only avaliable in REWARD state and all points claimed.
|
||||
*
|
||||
* @notice withdraw remaining tokens and eth send them to repoOwner
|
||||
* this might be a case when some tokens were 'forgotten'
|
||||
* or simply sent after finalized.
|
||||
* @param _tokens the list of tokens to withdraw.
|
||||
**/
|
||||
function withdraw(address[] _tokens) onlyController {
|
||||
require(state == State.FINALIZED);
|
||||
if (this.balance > 0) {
|
||||
owner.send(this.balance);
|
||||
}
|
||||
uint len = _tokens.length;
|
||||
uint amount;
|
||||
for (uint i = 0; i < len; i++) {
|
||||
ERC20 token = ERC20(_tokens[i]);
|
||||
amount = token.balanceOf(this);
|
||||
address token = _tokens[i];
|
||||
amount = updateInternalBalance(token);
|
||||
if (amount > 0) {
|
||||
withdraw(
|
||||
token,
|
||||
repoOwner,
|
||||
owner,
|
||||
amount,
|
||||
0x0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice only controller may kill contract and send all remaining eth and tokens to repo owner
|
||||
* This can only be done when all rewards are claimed.
|
||||
**/
|
||||
function kill() onlyController {
|
||||
require(state == State.FINALIZED);
|
||||
withdraw(tokens);
|
||||
selfdestruct(repoOwner);
|
||||
}
|
||||
/**
|
||||
* @dev overwriten to only allow refund in correct state.
|
||||
* @dev overwriten to only allow refund in correct state and to refund eth
|
||||
**/
|
||||
function refund(address _token) returns (bool success) {
|
||||
require(state == State.REFUND);
|
||||
success = withdraw(
|
||||
_token,
|
||||
msg.sender,
|
||||
deposits[_token][msg.sender],
|
||||
msg.sender
|
||||
);
|
||||
if(_token == 0x0){
|
||||
uint v = deposits[0x0][msg.sender];
|
||||
if (v > 0) {
|
||||
delete deposits[0x0][msg.sender];
|
||||
success = msg.sender.send(v);
|
||||
}
|
||||
} else {
|
||||
success = withdraw(
|
||||
_token,
|
||||
msg.sender,
|
||||
deposits[_token][msg.sender],
|
||||
msg.sender
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,22 +277,4 @@ contract IssueBank is Controlled, TokenLedger {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @title IssueBankFactory
|
||||
* @author Ricado Guilherme Schmidt <3esmit>
|
||||
**/
|
||||
contract IssueBankFactory {
|
||||
|
||||
/**
|
||||
* @notice creates new IssueBank with repoOwner as moderator
|
||||
**/
|
||||
function create(address repoOwner) returns(IssueBank) {
|
||||
IssueBank bank = new IssueBank(repoOwner);
|
||||
bank.changeController(msg.sender);
|
||||
return bank;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
pragma solidity ^0.4.15;
|
||||
|
||||
// Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
|
||||
|
||||
library ECRecover {
|
||||
|
||||
// ECRecovery Methods
|
||||
|
||||
// Duplicate Solidity's ecrecover, but catching the CALL return value
|
||||
function safer_ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal returns (bool, address) {
|
||||
// We do our own memory management here. Solidity uses memory offset
|
||||
// 0x40 to store the current end of memory. We write past it (as
|
||||
// writes are memory extensions), but don't update the offset so
|
||||
// Solidity will reuse it. The memory used here is only needed for
|
||||
// this context.
|
||||
|
||||
// FIXME: inline assembly can't access return values
|
||||
bool ret;
|
||||
address addr;
|
||||
|
||||
assembly {
|
||||
let size := mload(0x40)
|
||||
mstore(size, hash)
|
||||
mstore(add(size, 32), v)
|
||||
mstore(add(size, 64), r)
|
||||
mstore(add(size, 96), s)
|
||||
|
||||
// NOTE: we can reuse the request memory because we deal with
|
||||
// the return code
|
||||
ret := call(3000, 1, 0, size, 128, size, 32)
|
||||
addr := mload(size)
|
||||
}
|
||||
|
||||
return (ret, addr);
|
||||
}
|
||||
|
||||
function ecrecovery(bytes32 hash, bytes sig) returns (address) {
|
||||
bytes32 r;
|
||||
bytes32 s;
|
||||
uint8 v;
|
||||
|
||||
if (sig.length != 65)
|
||||
return (address(0));
|
||||
|
||||
assembly {
|
||||
r := mload(add(sig, 32))
|
||||
s := mload(add(sig, 64))
|
||||
v := byte(0, mload(add(sig, 96)))
|
||||
|
||||
// Alternative solution:
|
||||
// 'byte' is not working due to the Solidity parser, so lets
|
||||
// use the second best option, 'and'
|
||||
// v := and(mload(add(sig, 65)), 255)
|
||||
}
|
||||
|
||||
// albeit non-transactional signatures are not specified by the YP, one would expect it
|
||||
// to match the YP range of [27, 28]
|
||||
//
|
||||
// geth uses [0, 1] and some clients have followed. This might change, see:
|
||||
// https://github.com/ethereum/go-ethereum/issues/2053
|
||||
if (v < 27)
|
||||
v += 27;
|
||||
|
||||
if (v != 27 && v != 28)
|
||||
return (address(0));
|
||||
|
||||
bool ret;
|
||||
address addr;
|
||||
(ret, addr) = safer_ecrecover(hash, v, r, s);
|
||||
return addr;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
pragma solidity ^0.4.14;
|
||||
|
||||
/**
|
||||
* @title TokenReceiver
|
||||
* @dev Used by ERC223
|
||||
*/
|
||||
contract ERC223Receiver {
|
||||
function tokenFallback(address _from, uint _value, bytes _data);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
pragma solidity ^0.4.14;
|
||||
|
||||
import "./ERC20.sol";
|
||||
import "./ERC677Receiver.sol";
|
||||
|
||||
contract ERC677 is ERC20 {
|
||||
function transferAndCall(address receiver, uint amount, bytes data) returns (bool success) {
|
||||
require(transfer(receiver, amount));
|
||||
return _postTransferCall(receiver, amount, data);
|
||||
}
|
||||
|
||||
function _postTransferCall(address receiver, uint amount, bytes data) internal returns (bool success) {
|
||||
return ERC677Receiver(receiver).tokenFallback(msg.sender, amount, data);
|
||||
}
|
||||
}
|
||||
@@ -691,14 +691,15 @@ library strings {
|
||||
return "";
|
||||
|
||||
uint _len = self._len * (parts.length - 1);
|
||||
for(uint i = 0; i < parts.length; i++)
|
||||
for (uint i = 0; i < parts.length; i++) {
|
||||
_len += parts[i]._len;
|
||||
}
|
||||
|
||||
var ret = new string(_len);
|
||||
uint retptr;
|
||||
assembly { retptr := add(ret, 32) }
|
||||
|
||||
for(i = 0; i < parts.length; i++) {
|
||||
for (i = 0; i < parts.length; i++) {
|
||||
memcpy(retptr, parts[i]._ptr, parts[i]._len);
|
||||
retptr += parts[i]._len;
|
||||
if (i < parts.length - 1) {
|
||||
@@ -709,4 +710,33 @@ library strings {
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* @dev Joins an array of slices, returning a
|
||||
* newly allocated string.
|
||||
* @param parts A list of slices to join.
|
||||
* @return A newly allocated string containing
|
||||
* all the slices in `parts` joined.
|
||||
*/
|
||||
function join(slice[] parts) internal returns (string) {
|
||||
uint partslen = parts.length;
|
||||
if (partslen == 0)
|
||||
return "";
|
||||
|
||||
uint _len;
|
||||
for (uint i = 0; i < partslen; i++) {
|
||||
_len += parts[i]._len;
|
||||
}
|
||||
|
||||
var ret = new string(_len);
|
||||
uint retptr;
|
||||
assembly { retptr := add(ret, 32) }
|
||||
|
||||
for (i = 0; i < partslen; i++) {
|
||||
memcpy(retptr, parts[i]._ptr, parts[i]._len);
|
||||
retptr += parts[i]._len;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
pragma solidity ^0.4.17;
|
||||
|
||||
import "./BasicSystemStorage.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title AbstractRecoverer
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
* @dev Abstract recoverer contract that should be crafted to alter `address system` storage
|
||||
* in delegated logic contracts.
|
||||
*/
|
||||
contract AnstractRecoverer is BasicSystemStorage {
|
||||
|
||||
/**
|
||||
* @dev will be callable in emergency state of RecorverableSystem
|
||||
*/
|
||||
function recoverSystem(address newSystem) public {
|
||||
require(msg.sender == consensusContract());
|
||||
system = newSystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev returns the consesus contract, can be a multisig or other DAO
|
||||
* should be implemented by a child contract
|
||||
*/
|
||||
function consensusContract() public constant returns(address);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
pragma solidity ^0.4.17;
|
||||
|
||||
|
||||
/**
|
||||
* @title BasicSystemStorage
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
* @dev Defines system vars in a shared library among Stub and SystemLibraries to
|
||||
* avoid overwriting wrong storage pointers
|
||||
*/
|
||||
contract BasicSystemStorage {
|
||||
/// protected zone start (RecorverableSystem vars)
|
||||
address system;
|
||||
address recover;
|
||||
address watchdog;
|
||||
/// protected zone end
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
pragma solidity ^0.4.17;
|
||||
|
||||
|
||||
/**
|
||||
* @title DelegatedCall
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
* @dev Abstract contract that delegates calls by `delegated` modifier to result of `_target()`
|
||||
*/
|
||||
contract DelegatedCall {
|
||||
/**
|
||||
* @dev delegates the call of this function
|
||||
*/
|
||||
modifier delegated {
|
||||
require(_target().delegatecall(msg.data)); //require successfull delegate call to remote `_target()`
|
||||
assembly {
|
||||
let outSize := returndatasize
|
||||
let outDataPtr := mload(0x40) //load memory
|
||||
returndatacopy(outDataPtr, 0, outSize) //copy last return into pointer
|
||||
return(outDataPtr, outSize)
|
||||
}
|
||||
assert(false); //should never reach here
|
||||
_; //never will execute local logic
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev defines the address for delegation of calls
|
||||
*/
|
||||
function _target()
|
||||
internal
|
||||
constant
|
||||
returns(address);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
pragma solidity ^0.4.17;
|
||||
|
||||
import "./BasicSystemStorage.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title KillableModel
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
* @dev A contract model that can be killed by a watchdog
|
||||
*/
|
||||
contract KillableModel is BasicSystemStorage {
|
||||
|
||||
/**
|
||||
* @dev Library contract constructor initialize watchdog, able to kill the Library in case of
|
||||
*/
|
||||
function KillableModel(address _watchdog) public {
|
||||
watchdog = _watchdog;
|
||||
}
|
||||
|
||||
function emergencyStop() public {
|
||||
require(msg.sender == watchdog);
|
||||
selfdestruct(watchdog);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
pragma solidity ^0.4.4;
|
||||
|
||||
|
||||
contract Migrations {
|
||||
address public owner;
|
||||
uint public last_completed_migration;
|
||||
|
||||
modifier restricted() {
|
||||
if (msg.sender == owner) _;
|
||||
}
|
||||
|
||||
function Migrations() public {
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
function setCompleted(uint _completed) public restricted {
|
||||
last_completed_migration = _completed;
|
||||
}
|
||||
|
||||
function upgrade(address _newAddress) public restricted {
|
||||
Migrations upgraded = Migrations(_newAddress);
|
||||
upgraded.setCompleted(last_completed_migration);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
pragma solidity ^0.4.17;
|
||||
|
||||
import "./BasicSystemStorage.sol";
|
||||
import "./DelegatedCall.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title RecoverableSystem
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
* @dev Contract that recovers from dead system to recoverer.
|
||||
*/
|
||||
contract RecoverableSystem is BasicSystemStorage, DelegatedCall {
|
||||
|
||||
function RecoverableSystem(address _system, address _recover) public {
|
||||
require(isOk(_recover));
|
||||
system = _system;
|
||||
recover = _recover;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev delegatecall everything (but declared functions) to `_target()`
|
||||
*/
|
||||
function () public delegated {
|
||||
//all goes to system (or recover)
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev checks if system contains code
|
||||
*/
|
||||
function isOk() public constant returns(bool a) {
|
||||
return isOk(system);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev checks if `_a` contains code
|
||||
*/
|
||||
function isOk(address _a) internal constant returns(bool r) {
|
||||
assembly{
|
||||
r := gt(extcodesize(_a), 0)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev returns system if system has code, otherwise return recover
|
||||
*/
|
||||
function _target()
|
||||
internal
|
||||
constant
|
||||
returns(address)
|
||||
{
|
||||
|
||||
return isOk() ? system : recover;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
pragma solidity ^0.4.15;
|
||||
|
||||
import "../common/Controlled.sol";
|
||||
|
||||
/**
|
||||
* @title Archive
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
*/
|
||||
contract Archive is Controlled {
|
||||
|
||||
mapping(bytes32 => address) addressMap;
|
||||
mapping(bytes32 => bytes32) bytes32Map;
|
||||
mapping(bytes32 => uint) uIntMap;
|
||||
mapping(bytes32 => int) intMap;
|
||||
mapping(bytes32 => bool) boolMap;
|
||||
mapping(bytes32 => string) stringMap;
|
||||
mapping(bytes32 => bytes) bytesMap;
|
||||
|
||||
/**
|
||||
* Getters
|
||||
*/
|
||||
|
||||
function getAddress(bytes32 _uid) public constant returns (address) {
|
||||
return addressMap[_uid];
|
||||
}
|
||||
|
||||
function getBytes32(bytes32 _uid) public constant returns (bytes32) {
|
||||
return bytes32Map[_uid];
|
||||
}
|
||||
|
||||
function getUInt(bytes32 _uid) public constant returns (uint) {
|
||||
return uIntMap[_uid];
|
||||
}
|
||||
|
||||
function getInt(bytes32 _uid) public constant returns (int) {
|
||||
return intMap[_uid];
|
||||
}
|
||||
|
||||
function getBoolean(bytes32 _uid) public constant returns (bool) {
|
||||
return boolMap[_uid];
|
||||
}
|
||||
|
||||
function getString(bytes32 _uid) public constant returns (string) {
|
||||
return stringMap[_uid];
|
||||
}
|
||||
|
||||
function getBytes(bytes32 _uid) public constant returns (bytes) {
|
||||
return bytesMap[_uid];
|
||||
}
|
||||
|
||||
/**
|
||||
* Setters
|
||||
*/
|
||||
|
||||
function putAddress(bytes32 _uid, address value) public onlyController {
|
||||
addressMap[_uid] = value;
|
||||
}
|
||||
|
||||
function putUInt(bytes32 _uid, uint value) public onlyController {
|
||||
uIntMap[_uid] = value;
|
||||
}
|
||||
|
||||
function putInt(bytes32 _uid, int value) public onlyController {
|
||||
intMap[_uid] = value;
|
||||
}
|
||||
|
||||
function putBoolean(bytes32 _uid, bool value) public onlyController {
|
||||
boolMap[_uid] = value;
|
||||
}
|
||||
|
||||
function putBytes32(bytes32 _uid, bytes32 value) public onlyController {
|
||||
bytes32Map[_uid] = value;
|
||||
}
|
||||
|
||||
function putString(bytes32 _uid, string value) public onlyController {
|
||||
stringMap[_uid] = value;
|
||||
}
|
||||
|
||||
function putBytes(bytes32 _uid, bytes value) public onlyController {
|
||||
bytesMap[_uid] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deleters
|
||||
*/
|
||||
|
||||
function deleteAddress(bytes32 _uid) public onlyController {
|
||||
delete addressMap[_uid];
|
||||
}
|
||||
|
||||
function deleteBytes32(bytes32 _uid) public onlyController {
|
||||
delete bytes32Map[_uid];
|
||||
}
|
||||
|
||||
function deleteUInt(bytes32 _uid) public onlyController {
|
||||
delete uIntMap[_uid];
|
||||
}
|
||||
|
||||
function deleteInt(bytes32 _uid) public onlyController {
|
||||
delete intMap[_uid];
|
||||
}
|
||||
|
||||
function deleteBoolean(bytes32 _uid) public onlyController {
|
||||
delete boolMap[_uid];
|
||||
}
|
||||
|
||||
function deleteString(bytes32 _uid) public onlyController {
|
||||
delete stringMap[_uid];
|
||||
}
|
||||
|
||||
function deleteBytes(bytes32 _uid) public onlyController {
|
||||
delete bytesMap[_uid];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
/**
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
* @title NameRegistry
|
||||
* Interface for Name Registries.
|
||||
*/
|
||||
contract NameRegistry {
|
||||
function getAddr(uint256 _id) public constant returns(address addr);
|
||||
function getAddr(string _name) public constant returns(address addr);
|
||||
function getName(address _addr) public constant returns(string name);
|
||||
|
||||
mapping (bytes32 => uint256) indexes;
|
||||
|
||||
function getId(address _addr) public constant returns(uint256 id){
|
||||
return indexes[keccak256(_addr)];
|
||||
}
|
||||
|
||||
function getId(string _name) public constant returns(uint256 id) {
|
||||
return indexes[keccak256(_name)];
|
||||
}
|
||||
|
||||
function _updateIndex(bytes32 _old, bytes32 _new) internal {
|
||||
indexes[_new] = indexes[_old];
|
||||
delete indexes[_old];
|
||||
}
|
||||
}
|
||||
@@ -69,8 +69,12 @@ contract usingOraclize {
|
||||
|
||||
OraclizeI oraclize;
|
||||
modifier oraclizeAPI {
|
||||
if((address(OAR)==0)||(getCodeSize(address(OAR))==0)) oraclize_setNetwork(networkID_auto);
|
||||
oraclize = OraclizeI(OAR.getAddress());
|
||||
if((address(OAR)==0)||(getCodeSize(address(OAR))==0))
|
||||
oraclize_setNetwork(networkID_auto);
|
||||
|
||||
if(address(oraclize) != OAR.getAddress())
|
||||
oraclize = OraclizeI(OAR.getAddress());
|
||||
|
||||
_;
|
||||
}
|
||||
modifier coupon(string code){
|
||||
@@ -79,7 +83,7 @@ contract usingOraclize {
|
||||
_;
|
||||
}
|
||||
|
||||
function oraclize_setNetwork(uint8 /*networkID*/) internal returns(bool){
|
||||
function oraclize_setNetwork(uint8 networkID) internal returns(bool){
|
||||
if (getCodeSize(0x1d3B2638a7cC9f2CB3D298A3DA7a90B67E5506ed)>0){ //mainnet
|
||||
OAR = OraclizeAddrResolverI(0x1d3B2638a7cC9f2CB3D298A3DA7a90B67E5506ed);
|
||||
oraclize_setNetworkName("eth_mainnet");
|
||||
@@ -773,7 +777,7 @@ contract usingOraclize {
|
||||
}
|
||||
bytes[3] memory args = [unonce, nbytes, sessionKeyHash];
|
||||
bytes32 queryId = oraclize_query(_delay, "random", args, _customGasLimit);
|
||||
oraclize_randomDS_setCommitment(queryId, keccak256(bytes8(_delay), args[1], sha256(args[0]), args[2]));
|
||||
oraclize_randomDS_setCommitment(queryId, sha3(bytes8(_delay), args[1], sha256(args[0]), args[2]));
|
||||
return queryId;
|
||||
}
|
||||
|
||||
@@ -805,10 +809,10 @@ contract usingOraclize {
|
||||
|
||||
|
||||
(sigok, signer) = safer_ecrecover(tosignh, 27, sigr, sigs);
|
||||
if (address(keccak256(pubkey)) == signer) return true;
|
||||
if (address(sha3(pubkey)) == signer) return true;
|
||||
else {
|
||||
(sigok, signer) = safer_ecrecover(tosignh, 28, sigr, sigs);
|
||||
return (address(keccak256(pubkey)) == signer);
|
||||
return (address(sha3(pubkey)) == signer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -857,6 +861,16 @@ contract usingOraclize {
|
||||
_;
|
||||
}
|
||||
|
||||
function oraclize_randomDS_proofVerify__returnCode(bytes32 _queryId, string _result, bytes _proof) internal returns (uint8){
|
||||
// Step 1: the prefix has to match 'LP\x01' (Ledger Proof version 1)
|
||||
if ((_proof[0] != "L")||(_proof[1] != "P")||(_proof[2] != 1)) return 1;
|
||||
|
||||
bool proofVerified = oraclize_randomDS_proofVerify__main(_proof, _queryId, bytes(_result), oraclize_getNetworkName());
|
||||
if (proofVerified == false) return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function matchBytes32Prefix(bytes32 content, bytes prefix) internal returns (bool){
|
||||
bool match_ = true;
|
||||
|
||||
@@ -875,7 +889,7 @@ contract usingOraclize {
|
||||
uint ledgerProofLength = 3+65+(uint(proof[3+65+1])+2)+32;
|
||||
bytes memory keyhash = new bytes(32);
|
||||
copyBytes(proof, ledgerProofLength, 32, keyhash, 0);
|
||||
checkok = (keccak256(keyhash) == keccak256(sha256(context_name, queryId)));
|
||||
checkok = (sha3(keyhash) == sha3(sha256(context_name, queryId)));
|
||||
if (checkok == false) return false;
|
||||
|
||||
bytes memory sig1 = new bytes(uint(proof[ledgerProofLength+(32+8+1+32)+1])+2);
|
||||
@@ -887,7 +901,7 @@ contract usingOraclize {
|
||||
if (checkok == false) return false;
|
||||
|
||||
|
||||
// Step 4: commitment match verification, keccak256(delay, nbytes, unonce, sessionKeyHash) == commitment in storage.
|
||||
// Step 4: commitment match verification, sha3(delay, nbytes, unonce, sessionKeyHash) == commitment in storage.
|
||||
// This is to verify that the computed args match with the ones specified in the query.
|
||||
bytes memory commitmentSlice1 = new bytes(8+1+32);
|
||||
copyBytes(proof, ledgerProofLength+32, 8+1+32, commitmentSlice1, 0);
|
||||
@@ -897,7 +911,7 @@ contract usingOraclize {
|
||||
copyBytes(proof, sig2offset-64, 64, sessionPubkey, 0);
|
||||
|
||||
bytes32 sessionPubkeyHash = sha256(sessionPubkey);
|
||||
if (oraclize_randomDS_args[queryId] == keccak256(commitmentSlice1, sessionPubkeyHash)){ //unonce, nbytes and sessionKeyHash match
|
||||
if (oraclize_randomDS_args[queryId] == sha3(commitmentSlice1, sessionPubkeyHash)){ //unonce, nbytes and sessionKeyHash match
|
||||
delete oraclize_randomDS_args[queryId];
|
||||
} else return false;
|
||||
|
||||
@@ -25,7 +25,7 @@ pragma solidity ^0.4.6;
|
||||
/// affecting the original token
|
||||
/// @dev It is ERC20 compliant, but still needs to under go further testing.
|
||||
|
||||
import "./Controlled.sol";
|
||||
import "../common/Controlled.sol";
|
||||
import "./TokenController.sol";
|
||||
import "./ApproveAndCallFallBack.sol";
|
||||
|
||||
@@ -37,13 +37,13 @@ contract MiniMeToken is Controlled {
|
||||
string public name; //The Token's name: e.g. DigixDAO Tokens
|
||||
uint8 public decimals; //Number of decimals of the smallest unit
|
||||
string public symbol; //An identifier: e.g. REP
|
||||
string public version = 'MMT_0.1'; //An arbitrary versioning scheme
|
||||
string public version = "MMT_0.1"; //An arbitrary versioning scheme
|
||||
|
||||
|
||||
/// @dev `Checkpoint` is the structure that attaches a block number to a
|
||||
/// given value, the block number attached is the one that last changed the
|
||||
/// value
|
||||
struct Checkpoint {
|
||||
struct Checkpoint {
|
||||
|
||||
// `fromBlock` is the block number that the value was generated from
|
||||
uint128 fromBlock;
|
||||
@@ -1,15 +1,17 @@
|
||||
pragma solidity ^0.4.14;
|
||||
pragma solidity ^0.4.17;
|
||||
|
||||
import "./ERC223.sol";
|
||||
import "./MiniMeToken.sol";
|
||||
import "./TokenReceiver.sol";
|
||||
|
||||
|
||||
import "../common/ERC223.sol";
|
||||
import "../common/MiniMeToken.sol";
|
||||
import "../common/ERC223Receiver.sol";
|
||||
/**
|
||||
* @title TokenLedger
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
* Abstract contract for tracking token deposits.
|
||||
* Token transfers that did not approved and called `receiveApproval` can be tracked by
|
||||
* Token transfers that did not approved and called `receiveApproval` can be tracked by updateInternalBalance
|
||||
**/
|
||||
contract TokenLedger is ERC223Receiver, ApproveAndCallFallBack {
|
||||
contract TokenLedger is TokenReceiver, ApproveAndCallFallBack {
|
||||
|
||||
event Withdrawn(address indexed token, address indexed reciever, uint value);
|
||||
event Deposited(address indexed token, address indexed sender, uint value, bytes data);
|
||||
@@ -27,9 +29,10 @@ contract TokenLedger is ERC223Receiver, ApproveAndCallFallBack {
|
||||
**/
|
||||
function updateInternalBalance(address _token)
|
||||
public
|
||||
returns (uint newBal)
|
||||
{
|
||||
uint oldBal = tokenBalances[_token];
|
||||
uint newBal = ERC20(_token).balanceOf(this);
|
||||
newBal = ERC20(_token).balanceOf(this);
|
||||
require(newBal != oldBal);
|
||||
if (newBal > oldBal) {
|
||||
register(_token, address(this), newBal - oldBal, new bytes(0));
|
||||
@@ -43,7 +46,10 @@ contract TokenLedger is ERC223Receiver, ApproveAndCallFallBack {
|
||||
* @param _from address incoming token
|
||||
* @param _amount incoming amount
|
||||
**/
|
||||
function tokenFallback(address _from, uint _amount, bytes _data) {
|
||||
function tokenFallback(address _from, uint _amount, bytes _data)
|
||||
public
|
||||
returns (bool)
|
||||
{
|
||||
register(msg.sender, _from, _amount, _data);
|
||||
}
|
||||
|
||||
@@ -58,7 +64,9 @@ contract TokenLedger is ERC223Receiver, ApproveAndCallFallBack {
|
||||
address _from,
|
||||
uint256 _amount,
|
||||
address _token,
|
||||
bytes _data)
|
||||
bytes _data
|
||||
)
|
||||
public
|
||||
{
|
||||
uint _nonce = nonce;
|
||||
ERC20 token = ERC20(_token);
|
||||
@@ -1,8 +1,8 @@
|
||||
pragma solidity ^0.4.14;
|
||||
pragma solidity ^0.4.17;
|
||||
|
||||
/**
|
||||
* @title TokenReceiver
|
||||
* @dev Used by ERC677
|
||||
* @dev ERC223 and ERC677
|
||||
*/
|
||||
contract TokenReceiver {
|
||||
function tokenFallback(address _from, uint _value, bytes _data) public returns (bool);
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"package_name": "githuboracle",
|
||||
"package_name": "gitpivot",
|
||||
"version": "0.0.1",
|
||||
"description": "Tokenize commits and issues",
|
||||
"authors": [
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "github-oracle",
|
||||
"name": "gitpivot",
|
||||
"version": "0.0.1",
|
||||
"description": "Tokenize commits and issues",
|
||||
"main": "index.js",
|
||||
|
||||
Reference in New Issue
Block a user