From 35b2b263db49ddf313aa3ff197cb24d8f8b412e8 Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Mon, 20 Mar 2017 06:33:13 +0000 Subject: [PATCH] storage enhanced, storage deploy splitted, dir tree enhanced --- contracts/lib/ethereans/bank/Bank.sol | 10 + .../{migrations => management}/Owned.sol | 0 .../{migrations => management}/Secret.sol | 0 contracts/lib/ethereans/token | 1 - .../lib/ethereans/token/AbstractToken.sol | 194 ++++++++++++++++++ .../ethereans/token/CollaborationToken.sol | 158 ++++++++++++++ .../token/JustifiedCollaborationToken.sol | 34 +++ contracts/lib/ethereans/token/Token.sol | 14 ++ .../lib/ethereans/token/WrappedEthToken.sol | 35 ++++ contracts/lib/ethereans/util/IntLib.sol | 2 +- contracts/lib/ethereans/util/JSONLib.sol | 10 +- contracts/lib/ethereans/util/StringLib.sol | 32 ++- contracts/src/GitHubOracle.sol | 75 +++---- contracts/src/GitHubOracleStorage.sol | 52 ----- contracts/src/GitRepositoryFactory.sol | 25 --- contracts/src/GitRepositoryFactoryI.sol | 13 -- .../{ => git-repository}/GitRepository.sol | 2 +- .../git-repository/GitRepositoryFactory.sol | 19 ++ .../git-repository/GitRepositoryFactoryI.sol | 12 ++ .../{ => git-repository}/GitRepositoryI.sol | 0 .../GitRepositoryStorage.sol | 2 +- .../GitRepositoryToken.sol | 3 +- contracts/src/storage/GitHubOracleStorage.sol | 91 ++++++++ .../src/storage/GitHubOracleStorageI.sol | 27 +++ ethereum.json | 2 +- scenarios/DeployRegClaim.yaml | 122 +++++++++-- 26 files changed, 752 insertions(+), 183 deletions(-) create mode 100644 contracts/lib/ethereans/bank/Bank.sol rename contracts/lib/ethereans/{migrations => management}/Owned.sol (100%) rename contracts/lib/ethereans/{migrations => management}/Secret.sol (100%) delete mode 120000 contracts/lib/ethereans/token create mode 100644 contracts/lib/ethereans/token/AbstractToken.sol create mode 100644 contracts/lib/ethereans/token/CollaborationToken.sol create mode 100644 contracts/lib/ethereans/token/JustifiedCollaborationToken.sol create mode 100644 contracts/lib/ethereans/token/Token.sol create mode 100644 contracts/lib/ethereans/token/WrappedEthToken.sol delete mode 100644 contracts/src/GitHubOracleStorage.sol delete mode 100644 contracts/src/GitRepositoryFactory.sol delete mode 100644 contracts/src/GitRepositoryFactoryI.sol rename contracts/src/{ => git-repository}/GitRepository.sol (97%) create mode 100644 contracts/src/git-repository/GitRepositoryFactory.sol create mode 100644 contracts/src/git-repository/GitRepositoryFactoryI.sol rename contracts/src/{ => git-repository}/GitRepositoryI.sol (100%) rename contracts/src/{ => git-repository}/GitRepositoryStorage.sol (94%) rename contracts/src/{ => git-repository}/GitRepositoryToken.sol (95%) create mode 100644 contracts/src/storage/GitHubOracleStorage.sol create mode 100644 contracts/src/storage/GitHubOracleStorageI.sol diff --git a/contracts/lib/ethereans/bank/Bank.sol b/contracts/lib/ethereans/bank/Bank.sol new file mode 100644 index 0000000..fa27df6 --- /dev/null +++ b/contracts/lib/ethereans/bank/Bank.sol @@ -0,0 +1,10 @@ +pragma solidity ^0.4.9; + + +contract Bank { + + + + + +} \ No newline at end of file diff --git a/contracts/lib/ethereans/migrations/Owned.sol b/contracts/lib/ethereans/management/Owned.sol similarity index 100% rename from contracts/lib/ethereans/migrations/Owned.sol rename to contracts/lib/ethereans/management/Owned.sol diff --git a/contracts/lib/ethereans/migrations/Secret.sol b/contracts/lib/ethereans/management/Secret.sol similarity index 100% rename from contracts/lib/ethereans/migrations/Secret.sol rename to contracts/lib/ethereans/management/Secret.sol diff --git a/contracts/lib/ethereans/token b/contracts/lib/ethereans/token deleted file mode 120000 index ebdc6cb..0000000 --- a/contracts/lib/ethereans/token +++ /dev/null @@ -1 +0,0 @@ -../../../../abstract-token/contracts/ \ No newline at end of file diff --git a/contracts/lib/ethereans/token/AbstractToken.sol b/contracts/lib/ethereans/token/AbstractToken.sol new file mode 100644 index 0000000..79e407b --- /dev/null +++ b/contracts/lib/ethereans/token/AbstractToken.sol @@ -0,0 +1,194 @@ +pragma solidity ^0.4.8; + +/** + * AbstractToken ECR20-compliant token contract + * Child should implement initial supply or minting and overwite base + * Based on BasicCoin by Parity Team (Ethcore), 2016. + * By Ricardo Guilherme Schmidt + * Released under the Apache Licence 2. + */ + +import "./Token.sol"; + +// AbstractToken, ECR20 tokens that all belong to the owner for sending around +contract AbstractToken is Token { + + uint256 private decimalBase = 0; + mapping (bytes => bytes) private attributes; + mapping (address => Account) private accounts; + event Base(uint256 decimalBase); + event SetAttribute(string name, string value); + event Mint(address to, uint256 value); + event Destroy(address from, uint256 value); + + + struct Decimal { + uint256 value; + uint256 base; + } + + struct Account { + Decimal balance; + mapping (address => Decimal) allowanceOf; + } + + // the balance should be available + modifier when_owns(address _owner, uint256 _amount) { + if (balanceOf(_owner) < _amount) throw; + _; + } + + // an allowance should be available + modifier when_has_allowance(address _owner, address _spender, uint256 _amount) { + if (allowance(_owner,_spender) < _amount) throw; + _; + } + + //correct base and balance if needed + function _safeDecimals(Decimal _decimal) + internal + constant returns(Decimal){ + if(_decimal.base != decimalBase) { + if(_decimal.value > 0){ + int256 baseDiff = int256(_decimal.base) - int256(decimalBase); + if(baseDiff > 0){ + _decimal.value *= 10**uint256(baseDiff); + }else if(baseDiff < 0){ + uint256 oldv = _decimal.value; + uint256 newv = _decimal.value/(10**uint256(baseDiff*-1)); + _decimal.value = oldv > newv ? newv : 0; + } + } + _decimal.base = decimalBase; //update base of account + } + return _decimal; + } + + //_safeDecimals wrapper for safe add; + function _safeDecimalsAdd(Decimal _decimal, uint256 _value) + internal + constant returns(Decimal){ + _decimal = _safeDecimals(_decimal); + _decimal.value += _value; + return _decimal; + } + + function _safeDecimalsSub(Decimal _decimal, uint256 _value) + internal + constant returns(Decimal){ + _decimal = _safeDecimals(_decimal); + _decimal.value -= _value; + return _decimal; + } + //_safeDecimals wrapper for safe sub; + function base() + constant returns(uint256) { + return decimalBase; + } + + //child may override this function to trigger changes in balance dependent storage + function _balanceUpdated(address _from) + internal { + + } + + /** + * changes the decimal base + * lowereing base remove precision of most significant digits + * rising base remove precision of last significant digits + */ + function setDecimalBase(uint256 _decimalBase) + internal { + Base(_decimalBase); + decimalBase = _decimalBase; + } + + //sets attributes for wallet usage + function setAttribute(string _name, string _value) + internal { + SetAttribute(_name,_value); + if (bytes(_value).length > 0) attributes[bytes(_name)] = bytes(_value); + else delete attributes[bytes(_name)]; + } + + //read an attribute from storage + function getAttribute(string _name) + constant returns (string){ + return string(attributes[bytes(_name)]); + } + + // add tokens to a balance + function _mint(address _to, uint256 _value) + internal { + if (totalSupply + _value < totalSupply) throw; //overflow: maximum totalSupply in the current base; + Mint(_to, _value); + totalSupply += _value; + accounts[_to].balance = _safeDecimalsAdd(accounts[_to].balance,_value); + _balanceUpdated(_to); + } + + // remove tokens from a balance + function _destroy(address _from, uint256 _value) + internal { + Destroy(_from, _value); + totalSupply -= _value; + accounts[_from].balance = _safeDecimalsSub(accounts[_from].balance,_value); + if(accounts[_from].balance.value == 0){ + delete accounts[_from]; //to reduce gas in mapping accounts + } + _balanceUpdated(_from); + } + + // balance of a specific address + function balanceOf(address _who) + constant + returns (uint256) { + return _safeDecimals(accounts[_who].balance).value; + } + + // transfer + function transfer(address _to, uint256 _value) + when_owns(msg.sender, _value) + returns (bool) { + Transfer(msg.sender, _to, _value); + accounts[msg.sender].balance = _safeDecimalsSub(accounts[msg.sender].balance, _value); + accounts[_to].balance = _safeDecimalsAdd(accounts[_to].balance, _value); + _balanceUpdated(msg.sender); + _balanceUpdated(_to); + return true; + } + + // transfer via allowance + function transferFrom(address _from, address _to, uint256 _value) + when_owns(_from, _value) + when_has_allowance(_from, msg.sender, _value) + returns (bool) { + Transfer(_from, _to, _value); + accounts[_from].allowanceOf[msg.sender] = _safeDecimalsSub(accounts[_from].allowanceOf[msg.sender], _value); + accounts[_from].balance = _safeDecimalsSub(accounts[msg.sender].balance, _value); + accounts[_to].balance = _safeDecimalsAdd(accounts[_to].balance, _value); + _balanceUpdated(_from); + _balanceUpdated(_to); + return true; + } + + // set allowance + function approve(address _spender, uint256 _totalAllowed) + returns (bool) { + Approval(msg.sender, _spender, _totalAllowed); + accounts[msg.sender].allowanceOf[_spender].value = _totalAllowed; + accounts[msg.sender].allowanceOf[_spender].base = decimalBase; + if(_totalAllowed == 0){ + delete accounts[msg.sender].allowanceOf[_spender]; //lower gas in interactions + } + return true; + } + + // available allowance + function allowance(address _owner, address _spender) + constant + returns (uint256) { + return _safeDecimals(accounts[_owner].allowanceOf[_spender]).value; + } + +} diff --git a/contracts/lib/ethereans/token/CollaborationToken.sol b/contracts/lib/ethereans/token/CollaborationToken.sol new file mode 100644 index 0000000..6a44312 --- /dev/null +++ b/contracts/lib/ethereans/token/CollaborationToken.sol @@ -0,0 +1,158 @@ +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/JustifiedCollaborationToken.sol b/contracts/lib/ethereans/token/JustifiedCollaborationToken.sol new file mode 100644 index 0000000..f2f19ea --- /dev/null +++ b/contracts/lib/ethereans/token/JustifiedCollaborationToken.sol @@ -0,0 +1,34 @@ +pragma solidity ^0.4.1; + +/** + * Mintable Collaboration coin with register of reason of minting + * + * By Ricardo Guilherme Schmidt + * Released under GPLv3 License + */ + +import "../management/Owned.sol"; +import "./CollaborationToken.sol"; + +contract JustifiedCollaborationToken is CollaborationToken, Owned { + event Claim(bytes32 _data); + mapping (bytes32 => Receipt) public receipts; + mapping (address => bool) public minters; + + // storage of minting reason + struct Receipt { + address beneficiary; + uint256 value; + bool claimed; + } + + 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}); + _mint(_beneficiary,_value); + Claim(_data); + } + +} diff --git a/contracts/lib/ethereans/token/Token.sol b/contracts/lib/ethereans/token/Token.sol new file mode 100644 index 0000000..bf66e03 --- /dev/null +++ b/contracts/lib/ethereans/token/Token.sol @@ -0,0 +1,14 @@ +pragma solidity ^0.4.8; + +// ECR20 standard token interface + +contract Token { + uint256 public totalSupply; + function balanceOf(address who) constant returns (uint256); + function allowance(address owner, address spender) constant returns (uint256); + function transfer(address to, uint256 value) returns (bool ok); + function transferFrom(address from, address to, uint256 value) returns (bool ok); + function approve(address spender, uint256 value) returns (bool ok); + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); +} \ No newline at end of file diff --git a/contracts/lib/ethereans/token/WrappedEthToken.sol b/contracts/lib/ethereans/token/WrappedEthToken.sol new file mode 100644 index 0000000..5ca4623 --- /dev/null +++ b/contracts/lib/ethereans/token/WrappedEthToken.sol @@ -0,0 +1,35 @@ +pragma solidity ^0.4.0; + +/** + * WrappedEthToken is a contract that creates 1 token por eth deposited. + * + * By Ricardo Guilherme Schmidt + * Released under GPLv3 License + */ + +import "./AbstractToken.sol"; + +contract WrappedEthToken is AbstractToken { + + //Minting is by depositing in the contract + function () + payable { + deposit(); + } + + function deposit() + payable { + _mint(msg.sender,msg.value); + } + + function withdraw(uint256 _amount) + when_owns (msg.sender, _amount) { + _destroy(msg.sender, _amount); + if(!msg.sender.send(_amount)) throw; + } + + function withdraw() { + withdraw(balanceOf(msg.sender)); + } + +} diff --git a/contracts/lib/ethereans/util/IntLib.sol b/contracts/lib/ethereans/util/IntLib.sol index a6c0424..1640e6c 100644 --- a/contracts/lib/ethereans/util/IntLib.sol +++ b/contracts/lib/ethereans/util/IntLib.sol @@ -6,7 +6,7 @@ pragma solidity ^0.4.0; uint constant week = 60*60*24*7; uint constant month = 60*60*24*30; - function uint2str(uint i) internal returns (string){ + function uint2str(uint i) internal constant returns (string){ if (i == 0) return "0"; uint j = i; uint len; diff --git a/contracts/lib/ethereans/util/JSONLib.sol b/contracts/lib/ethereans/util/JSONLib.sol index 8086eeb..a0bde5f 100644 --- a/contracts/lib/ethereans/util/JSONLib.sol +++ b/contracts/lib/ethereans/util/JSONLib.sol @@ -7,12 +7,12 @@ library JSONLib { uint8 scan; } - function json(string json) internal returns (JSON){ + function json(string json) internal constant returns (JSON){ return JSON({ b: bytes(json), scan: 0}); } - function getNextString(JSON self) internal returns (string,JSON) { + function getNextString(JSON self) internal constant returns (string,JSON) { uint8 start = 0; uint8 end = 0; for (;self.b.length > self.scan; self.scan++) { @@ -34,7 +34,7 @@ library JSONLib { } - function getNextUInt(JSON self) internal returns (uint,JSON) { + function getNextUInt(JSON self) internal constant returns (uint,JSON) { uint val = 0; for (; self.b.length > self.scan; self.scan++) { if (self.b[self.scan] == ','){ //Find ends @@ -47,7 +47,7 @@ library JSONLib { return (val,self); } - function getNextAddr(JSON self) internal returns (address, JSON){ + function getNextAddr(JSON self) internal constant returns (address, JSON){ uint160 iaddr = 0; for(;self.b.length > self.scan; self.scan++){ if (self.b[self.scan] == '0'){ @@ -67,7 +67,7 @@ library JSONLib { return (address(iaddr),self); } - function hexVal(uint val) internal returns (uint){ + function hexVal(uint val) internal constant returns (uint){ //return val - (val < 58 ? 48 : 55); //uppercase //return val - (val < 58 ? 48 : 87); //lowercase return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); //both diff --git a/contracts/lib/ethereans/util/StringLib.sol b/contracts/lib/ethereans/util/StringLib.sol index 7519ea4..fed7e38 100644 --- a/contracts/lib/ethereans/util/StringLib.sol +++ b/contracts/lib/ethereans/util/StringLib.sol @@ -2,24 +2,20 @@ pragma solidity ^0.4.9; library StringLib { - - function str(string self) internal returns (string){ - return self; - } - - function hexVal(uint val) internal returns (uint){ + + function hexVal(uint val) internal constant returns (uint){ //return val - (val < 58 ? 48 : 55); //uppercase //return val - (val < 58 ? 48 : 87); //lowercase return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); //both } - function toBytes32(string memory source) internal returns (bytes32 result) { + function toBytes32(string memory source) internal constant returns (bytes32 result) { assembly { result := mload(add(source, 32)) } } function parseBytes20(string self) - internal returns (bytes20 bs) { + internal constant returns (bytes20 bs) { bytes memory h = bytes(self); if (h.length>>1 != 20) throw;// new Exception("The binary need 20 digits"); @@ -30,7 +26,7 @@ library StringLib { return bs; } function parseBytes32(string self) - internal returns (bytes32 bs) { + internal constant returns (bytes32 bs) { bytes memory h = bytes(self); if (h.length>>1 != 32) throw;// new Exception("The binary need 20 digits"); @@ -40,7 +36,7 @@ library StringLib { } return bs; } - function parseAddr(string self) internal returns (address){ + function parseAddr(string self) internal constant returns (address){ bytes memory tmp = bytes(self); uint iaddr = 0; for (uint i=2; i<2+2*20; i+=2){ @@ -49,7 +45,7 @@ library StringLib { return address(iaddr); } - function compare(string self, string _b) internal returns (int) { + function compare(string self, string _b) internal constant returns (int) { bytes memory a = bytes(self); bytes memory b = bytes(_b); uint minLength = a.length; @@ -67,7 +63,7 @@ library StringLib { return 0; } - function indexOf(string _haystack, string _needle) internal returns (int) { + function indexOf(string _haystack, string _needle) internal constant returns (int) { bytes memory h = bytes(_haystack); bytes memory n = bytes(_needle); if(h.length < 1 || n.length < 1 || (n.length > h.length)) @@ -94,7 +90,7 @@ library StringLib { } } - function concat(string self, string _b, string _c, string _d, string _e) internal returns (string) { + function concat(string self, string _b, string _c, string _d, string _e) internal constant returns (string) { bytes memory _ba = bytes(self); bytes memory _bb = bytes(_b); bytes memory _bc = bytes(_c); @@ -111,25 +107,25 @@ library StringLib { return string(babcde); } - function concat(string self, string _b, string _c, string _d) internal returns (string) { + function concat(string self, string _b, string _c, string _d) internal constant returns (string) { return concat(self, _b, _c, _d, ""); } - function concat(string self, string _b, string _c) internal returns (string) { + function concat(string self, string _b, string _c) internal constant returns (string) { return concat(self, _b, _c, "", ""); } - function concat(string self, string _b) internal returns (string) { + function concat(string self, string _b) internal constant returns (string) { return concat(self, _b, "", "", ""); } // parseInt - function parseInt(string self) internal returns (uint) { + function parseInt(string self) internal constant returns (uint) { return parseInt(self, 0); } // parseInt(parseFloat*10^_b) - function parseInt(string self, uint _b) internal returns (uint) { + function parseInt(string self, uint _b) internal constant returns (uint) { bytes memory bresult = bytes(self); uint mint = 0; bool decimals = false; diff --git a/contracts/src/GitHubOracle.sol b/contracts/src/GitHubOracle.sol index 3232c42..090fc33 100644 --- a/contracts/src/GitHubOracle.sol +++ b/contracts/src/GitHubOracle.sol @@ -14,24 +14,25 @@ pragma solidity ^0.4.8; * By Ricardo Guilherme Schmidt * Released under GPLv3 License */ - -import "lib/oraclize/oraclizeAPI_0.4.sol"; + import "lib/ethereans/util/StringLib.sol"; import "lib/ethereans/util/JSONLib.sol"; -import "lib/ethereans/migrations/Owned.sol"; -import "./GitRepositoryFactoryI.sol"; -import "./GitHubOracleStorage.sol"; + +import "lib/oraclize/oraclizeAPI_0.4.sol"; +import "lib/ethereans/management/Owned.sol"; +import "./git-repository/GitRepositoryFactoryI.sol"; +import "./storage/GitHubOracleStorageI.sol"; contract GitHubOracle is Owned, usingOraclize { + using StringLib for string; using JSONLib for JSONLib.JSON; - + GitRepositoryFactoryI public gitRepositoryFactoryI; - GitHubOracleStorage public db; - - + GitHubOracleStorageI public db; + 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 @@ -50,35 +51,35 @@ contract GitHubOracle is Owned, usingOraclize { string commitid; } - function GitHubOracle(GitRepositoryFactoryI _gitRepositoryFactoryI){ - gitRepositoryFactoryI = _gitRepositoryFactoryI; // 0x17956bA5f4291844bc25aEDb27e69bc11B5Bda39; - db = new GitHubOracleStorage(); + function GitHubOracle(GitHubOracleStorageI _db, GitRepositoryFactoryI _gitRepositoryFactoryI){ // + gitRepositoryFactoryI = _gitRepositoryFactoryI; + db = _db; } //register or change a github user ethereum address 100000000000000000 function register(string _github_user, string _gistid) payable { - bytes32 ocid = oraclize_query("nested", StringLib.str("[identity] ${[URL] https://gist.githubusercontent.com/").concat(_github_user,"/",_gistid,"/raw/}, ${[URL] json(https://api.github.com/gists/").concat(_gistid,credentials,").owner.[id,login]}")); + 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}); } function claimCommit(string _repository, string _commitid) payable { - bytes32 ocid = oraclize_query("URL", StringLib.str("json(https://api.github.com/repos/").concat(_repository,"/commits/", _commitid, credentials).concat(").[author,stats].[id,total]")); + 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}); } function addRepository(string _repository) payable { - bytes32 ocid = oraclize_query("URL", StringLib.str("json(https://api.github.com/repos/").concat(_repository,").$.id,full_name,watchers,subscribers_count"),3000000); + 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 setAPICredentials(string _client_id, string _client_secret) only_owner { - credentials = StringLib.str("?client_id=${[decrypt] ").concat(_client_id,"}&client_secret=${[decrypt] ",_client_secret,"}"); + credentials = StringLib.concat("?client_id=${[decrypt] ", _client_id,"}&client_secret=${[decrypt] ", _client_secret,"}"); } function clearAPICredentials() @@ -107,36 +108,36 @@ contract GitHubOracle is Owned, usingOraclize { event UserSet(string githubLogin); function _register(bytes32 myid, string result) internal { - uint256 userId; string memory login; address addrLoaded; + uint256 userId; string memory login; address addrLoaded; + uint8 utype; //TODO JSONLib.JSON memory v = JSONLib.json(result); (addrLoaded,v) = v.getNextAddr(); (userId,v) = v.getNextUInt(); (login,v) = v.getNextString(); if(userClaim[myid].sender == addrLoaded && userClaim[myid].githubid.compare(login) == 0){ - UserSet(login); - db.setUserAddress(userId, addrLoaded); - db.setUserName(userId, login); - } + UserSet(login); + db.addUser(userId, login, utype, addrLoaded); + } //TODO: update user login and address; 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 { - uint256 projectId; string memory full_name; uint256 watchers; uint256 subscribers; + function _setRepository(bytes32 myid, string result) //[83725290, "ethereans/github-token", 4, 2] + { + uint256 projectId; string memory full_name; uint256 watchers; uint256 subscribers; + uint256 ownerId; string memory name; //TODO JSONLib.JSON memory v = JSONLib.json(result); (projectId,v) = v.getNextUInt(); (full_name,v) = v.getNextString(); (watchers,v) = v.getNextUInt(); (subscribers,v) = v.getNextUInt(); - GitRepositoryI repository = GitRepositoryI(db.repositories(projectId)); - if(address(repository) == 0x0){ + address repository = db.getRepositoryAddress(projectId); + if(repository == 0x0){ GitRepositoryRegistered(projectId,full_name,watchers,subscribers); - db.setRepositoryName(projectId,full_name); - if(!gitRepositoryFactoryI.delegatecall(bytes4(sha3("newGitRepository(address,uint256)")),db,projectId)) throw; - repository = GitRepositoryI(db.repositories(projectId)); + repository = gitRepositoryFactoryI.newGitRepository(projectId,full_name); + db.addRepository(projectId,ownerId,name,full_name,repository); } - repository.setStats(subscribers,watchers); + GitRepositoryI(repository).setStats(subscribers,watchers); } event NewClaim(string repository, string commitid, uint userid, uint total ); @@ -147,20 +148,10 @@ contract GitHubOracle is Owned, usingOraclize { (userId,v) = v.getNextUInt(); (total,v) = v.getNextUInt(); NewClaim(commitClaim[myid].repository,commitClaim[myid].commitid,userId,total); - GitRepositoryI repository = GitRepositoryI(db.repositories(db.getRepositoryId(commitClaim[myid].repository))); - repository.claim(commitClaim[myid].commitid.parseBytes20(), db.users(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 } - function getGitRepository(uint projectId) constant returns (address){ - return db.repositories(projectId); - } - function getGitRepository(string full_name) constant returns (address){ - return db.repositories(getGitRepositoryId(full_name)); - } - function getGitRepositoryId(string full_name) constant returns (uint256){ - return db.getRepositoryId(full_name); - } - } \ No newline at end of file diff --git a/contracts/src/GitHubOracleStorage.sol b/contracts/src/GitHubOracleStorage.sol deleted file mode 100644 index b9aa630..0000000 --- a/contracts/src/GitHubOracleStorage.sol +++ /dev/null @@ -1,52 +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 "./GitRepositoryI.sol"; -import "lib/ethereans/migrations/Owned.sol"; - -contract GitHubOracleStorage is Owned { - - mapping (string => uint256) repositoryNames; - mapping (uint256 => address) public repositories; - mapping (uint256 => address) public users; - mapping (string => uint256) userNames; - - - function setRepositoryAddress(uint256 _repositoryId, address _repositoryAddress) - external - only_owner { - repositories[_repositoryId] = _repositoryAddress; - } - - function setRepositoryName(uint256 _repositoryId, string _name) - external - only_owner { - repositoryNames[_name] = _repositoryId; - } - - function setUserAddress(uint userId, address account) - external - only_owner{ - users[userId] = account; - } - - function setUserName(uint256 _userId, string _name) - external - only_owner { - userNames[_name] = _userId; - } - - function getRepositoryId(string _full_name) - constant returns (uint256){ - return repositoryNames[_full_name]; - } - -} \ No newline at end of file diff --git a/contracts/src/GitRepositoryFactory.sol b/contracts/src/GitRepositoryFactory.sol deleted file mode 100644 index 87a487f..0000000 --- a/contracts/src/GitRepositoryFactory.sol +++ /dev/null @@ -1,25 +0,0 @@ -pragma solidity ^0.4.8; - -/** - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -import "./GitRepository.sol"; -import "./GitHubOracleStorage.sol"; -import "./GitRepositoryFactoryI.sol"; - -contract GitRepositoryFactory is GitRepositoryFactoryI { - - /*function newGitRepository(uint256 _uid, string _name) external returns (address){ - GitRepository repo = new GitRepository(_uid,_name); - return address(repo); - }*/ - - function newGitRepository(address db, uint256 _uid) external returns (bool) { - GitHubOracleStorage dbs = GitHubOracleStorage(db); - dbs.setRepositoryAddress(_uid, new GitRepository(_uid,"")); - return true; - } - -} \ No newline at end of file diff --git a/contracts/src/GitRepositoryFactoryI.sol b/contracts/src/GitRepositoryFactoryI.sol deleted file mode 100644 index e5493d1..0000000 --- a/contracts/src/GitRepositoryFactoryI.sol +++ /dev/null @@ -1,13 +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 (address); - function newGitRepository(address db, uint256 _uid) external returns (bool); -} diff --git a/contracts/src/GitRepository.sol b/contracts/src/git-repository/GitRepository.sol similarity index 97% rename from contracts/src/GitRepository.sol rename to contracts/src/git-repository/GitRepository.sol index 3ea45c7..6218503 100644 --- a/contracts/src/GitRepository.sol +++ b/contracts/src/git-repository/GitRepository.sol @@ -15,7 +15,7 @@ pragma solidity ^0.4.8; * Released under GPLv3 License */ -import "lib/ethereans/migrations/Owned.sol"; +import "lib/ethereans/management/Owned.sol"; import "./GitRepositoryI.sol"; import "./GitRepositoryToken.sol"; import "./GitRepositoryStorage.sol"; diff --git a/contracts/src/git-repository/GitRepositoryFactory.sol b/contracts/src/git-repository/GitRepositoryFactory.sol new file mode 100644 index 0000000..1c20269 --- /dev/null +++ b/contracts/src/git-repository/GitRepositoryFactory.sol @@ -0,0 +1,19 @@ +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/src/git-repository/GitRepositoryFactoryI.sol b/contracts/src/git-repository/GitRepositoryFactoryI.sol new file mode 100644 index 0000000..1ec1469 --- /dev/null +++ b/contracts/src/git-repository/GitRepositoryFactoryI.sol @@ -0,0 +1,12 @@ +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/GitRepositoryI.sol b/contracts/src/git-repository/GitRepositoryI.sol similarity index 100% rename from contracts/src/GitRepositoryI.sol rename to contracts/src/git-repository/GitRepositoryI.sol diff --git a/contracts/src/GitRepositoryStorage.sol b/contracts/src/git-repository/GitRepositoryStorage.sol similarity index 94% rename from contracts/src/GitRepositoryStorage.sol rename to contracts/src/git-repository/GitRepositoryStorage.sol index 8966450..a392ced 100644 --- a/contracts/src/GitRepositoryStorage.sol +++ b/contracts/src/git-repository/GitRepositoryStorage.sol @@ -8,7 +8,7 @@ * By Ricardo Guilherme Schmidt * Released under GPLv3 License */ -import "lib/ethereans/migrations/Owned.sol"; +import "lib/ethereans/management/Owned.sol"; contract GitRepositoryStorage is Owned { diff --git a/contracts/src/GitRepositoryToken.sol b/contracts/src/git-repository/GitRepositoryToken.sol similarity index 95% rename from contracts/src/GitRepositoryToken.sol rename to contracts/src/git-repository/GitRepositoryToken.sol index 777d656..7b7a9c6 100644 --- a/contracts/src/GitRepositoryToken.sol +++ b/contracts/src/git-repository/GitRepositoryToken.sol @@ -16,7 +16,8 @@ pragma solidity ^0.4.8; */ import "lib/ethereans/token/CollaborationToken.sol"; -import "lib/ethereans/migrations/Owned.sol"; +import "lib/ethereans/management/Owned.sol"; + contract GitRepositoryToken is CollaborationToken, Owned { function GitRepositoryToken(string _repository) { diff --git a/contracts/src/storage/GitHubOracleStorage.sol b/contracts/src/storage/GitHubOracleStorage.sol new file mode 100644 index 0000000..12db397 --- /dev/null +++ b/contracts/src/storage/GitHubOracleStorage.sol @@ -0,0 +1,91 @@ +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"; +import "./GitHubOracleStorageI.sol"; +contract GitHubOracleStorage is GitHubOracleStorageI, Owned { + + mapping (string => uint256) repositoryNames; + mapping (string => uint256) userNames; + mapping (uint256 => Repository) repositories; + mapping (uint256 => User) users; + + struct Repository { + uint256 owner; + string name; + string full_name; + address addr; + uint256 claimed; + } + + struct User { + string login; + uint8 utype; + address addr; + uint256 claimed; + } + + + 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}); + 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}); + userNames[_login] = _id; + } + + function setRepositoryAddress(uint256 _repositoryId, address _repositoryAddress) + only_owner { + repositories[_repositoryId].addr = _repositoryAddress; + } + + function setUserAddress(uint userId, address account) + only_owner{ + users[userId].addr = account; + } + function setRepositoryName(uint256 _repositoryId, string _full_name, string _name) + only_owner { + delete repositoryNames[repositories[_repositoryId].full_name]; + repositoryNames[_full_name] = _repositoryId; + repositories[_repositoryId].full_name = _full_name; + repositories[_repositoryId].name = _full_name; + } + + function setUserName(uint256 _userId, string _name) + only_owner { + delete userNames[users[_userId].login]; + userNames[_name] = _userId; + users[_userId].login = _name; + } + + + function getUserAddress(uint256 _id) constant returns(address){ + return users[_id].addr; + } + function getUserAddress(string _login) constant returns(address){ + return users[userNames[_login]].addr; + } + function getRepositoryAddress(uint256 _id) constant returns(address){ + return repositories[_id].addr; + } + function getRepositoryAddress(string _full_name) constant returns(address){ + return repositories[repositoryNames[_full_name]].addr; + } + function getRepositoryId(string _full_name) constant returns (uint256){ + return repositoryNames[_full_name]; + } + function getRepositoryName(uint256 _id) constant returns (string){ + return repositories[_id].full_name; + } + +} \ No newline at end of file diff --git a/contracts/src/storage/GitHubOracleStorageI.sol b/contracts/src/storage/GitHubOracleStorageI.sol new file mode 100644 index 0000000..9095ce5 --- /dev/null +++ b/contracts/src/storage/GitHubOracleStorageI.sol @@ -0,0 +1,27 @@ +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/ethereum.json b/ethereum.json index c2fcc35..d861d0e 100644 --- a/ethereum.json +++ b/ethereum.json @@ -1,7 +1,7 @@ { "contracts": "contracts", - "deploy": ["GitRepositoryFactory"], + "deploy": [], "plugins": { "oraclize": { diff --git a/scenarios/DeployRegClaim.yaml b/scenarios/DeployRegClaim.yaml index c74648a..c03c595 100644 --- a/scenarios/DeployRegClaim.yaml +++ b/scenarios/DeployRegClaim.yaml @@ -1,23 +1,23 @@ # -# Scenario1 +# Scenario3 # -# Created on: 16/03/2017 22:50:30 +# Created on: 20/03/2017 02:44:46 # -# Create contract GitHubOracle +# Create contract GitRepositoryFactory - from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' to: null value: '0x0' contract: - name: GitHubOracle + name: GitRepositoryFactory dir: contracts/ sources: - - lib/ethereans/migrations/Owned.sol - - lib/ethereans/migrations/Secret.sol + - 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/Owned.sol - lib/ethereans/token/Token.sol - lib/ethereans/token/WrappedEthToken.sol - lib/ethereans/util/Bytes32Lib.sol @@ -28,38 +28,116 @@ - src/AbstractBounty.sol - src/GitHubIssues.sol - src/GitHubOracle.sol - - src/GitHubOracleStorage.sol - - src/GitRepository.sol - - src/GitRepositoryFactory.sol - - src/GitRepositoryFactoryI.sol - - src/GitRepositoryI.sol - - src/GitRepositoryStorage.sol - - src/GitRepositoryToken.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/ethereans/util/JSONLib.sol + - lib/ethereans/util/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/ethereans/util/JSONLib.sol + - lib/ethereans/util/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 register(string,string) +# Call method setOwner(address) - from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' to: '0xdf315f7485c3a86eb692487588735f224482abe3' value: '0x0' - call: 'register(string,string)' + call: setOwner(address) args: - - 3esmit - - 31a58f2ddf2258697cce1b969e7c298b + - '0x06b179aabf198ced0f98c8ceca905a920a137ef4' # Call method addRepository(string) - from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: '0xdf315f7485c3a86eb692487588735f224482abe3' + 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: '0xdf315f7485c3a86eb692487588735f224482abe3' - value: '0x0' + to: '0x06b179aabf198ced0f98c8ceca905a920a137ef4' + value: '0x2386f26fc10000' call: 'claimCommit(string,string)' args: - ethereans/github-token - - 09ba429f22eec6cefcfa7a862f60b9d4cc1cfa14 + - 09ba429f22eec6cefcfa7a862f60b9d4cc1cfa14 \ No newline at end of file