Skip to content

Commit 9e88b6d

Browse files
authored
identity first draft (#1)
1 parent c069684 commit 9e88b6d

File tree

3 files changed

+261
-0
lines changed

3 files changed

+261
-0
lines changed

contracts/ERC725.sol

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
pragma solidity ^0.4.17;
2+
3+
contract ERC725 {
4+
5+
uint256 constant MANAGEMENT_KEY = 1;
6+
uint256 constant ACTION_KEY = 2;
7+
uint256 constant CLAIM_SIGNER_KEY = 3;
8+
uint256 constant ENCRYPTION_KEY = 4;
9+
10+
event KeyAdded(address indexed key, uint256 indexed keyType);
11+
event KeyRemoved(address indexed key, uint256 indexed keyType);
12+
event KeyReplaced(address indexed oldKey, address indexed newKey, uint256 indexed keyType);
13+
event ExecutionRequested(bytes32 indexed executionId, address indexed to, uint256 indexed value, bytes data);
14+
event Executed(bytes32 indexed executionId, address indexed to, uint256 indexed value, bytes data);
15+
event Approved(bytes32 indexed executionId, bool approved);
16+
17+
function getKeyType(address _key) public constant returns(uint256 keyType);
18+
function getKeysByType(uint256 _type) public constant returns(address[]);
19+
function addKey(address _key, uint256 _type) public returns (bool success);
20+
function removeKey(address _key) public returns (bool success);
21+
function replaceKey(address _oldKey, address _newKey) public returns (bool success);
22+
function execute(address _to, uint256 _value, bytes _data) public returns (bytes32 executionId);
23+
function approve(bytes32 _id, bool _approve) public returns (bool success);
24+
}

contracts/ERC735.sol

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
pragma solidity ^0.4.17;
2+
3+
contract ERC735 {
4+
5+
event ClaimRequested(bytes32 indexed claimId, uint256 indexed claimType, address indexed issuer, uint256 signatureType, bytes signature, bytes claim, string uri);
6+
event ClaimAdded(bytes32 indexed claimId, uint256 indexed claimType, address indexed issuer, uint256 signatureType, bytes signature, bytes claim, string uri);
7+
event ClaimRemoved(bytes32 indexed claimId, uint256 indexed claimType, address indexed issuer, uint256 signatureType, bytes signature, bytes claim, string uri);
8+
event ClaimChanged(bytes32 indexed claimId, uint256 indexed claimType, address indexed issuer, uint256 signatureType, bytes signature, bytes claim, string uri);
9+
10+
struct Claim {
11+
uint256 claimType;
12+
address issuer; // msg.sender
13+
uint256 signatureType; // The type of signature
14+
bytes signature; // this.address + claimType + claim
15+
bytes claim;
16+
string uri;
17+
}
18+
19+
function getClaim(bytes32 _claimId) public constant returns(uint256 claimType, address issuer, uint256 signatureType, bytes signature, bytes claim, string uri);
20+
function getClaimsIdByType(uint256 _claimType) public constant returns(bytes32[]);
21+
function addClaim(uint256 _claimType, address issuer, uint256 signatureType, bytes _signature, bytes _claim, string _uri) public returns (bytes32 claimId);
22+
function removeClaim(bytes32 _claimId) public returns (bool success);
23+
}

contracts/Identity.sol

+214
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
pragma solidity ^0.4.17;
2+
3+
import "./ERC725.sol";
4+
import "./ERC735.sol";
5+
6+
contract Identity is ERC725, ERC735 {
7+
8+
mapping (address => uint256) keys;
9+
mapping (bytes32 => Claim) claims;
10+
mapping (uint256 => address[]) keysByType;
11+
mapping (uint256 => bytes32[]) claimsByType;
12+
mapping (bytes32 => uint256) indexes;
13+
mapping (bytes32 => Transaction) txx;
14+
15+
uint nonce = 0;
16+
17+
struct Transaction {
18+
address to;
19+
uint value;
20+
bytes data;
21+
uint nonce;
22+
}
23+
24+
25+
modifier managerOnly {
26+
require(keys[msg.sender] == MANAGEMENT_KEY);
27+
_;
28+
}
29+
30+
modifier managerOrSelf {
31+
require(keys[msg.sender] == MANAGEMENT_KEY || msg.sender == address(this));
32+
_;
33+
}
34+
35+
modifier actorOnly {
36+
require(keys[msg.sender] == ACTION_KEY);
37+
_;
38+
}
39+
40+
modifier claimSignerOnly {
41+
require(keys[msg.sender] == CLAIM_SIGNER_KEY);
42+
_;
43+
}
44+
45+
46+
function Identity() public {
47+
_addKey(msg.sender, MANAGEMENT_KEY);
48+
}
49+
50+
51+
function addKey(address _key, uint256 _type) public managerOrSelf returns (bool success) {
52+
_addKey(_key, _type);
53+
}
54+
55+
56+
function removeKey(address _key) public managerOrSelf returns (bool success) {
57+
_removeKey(_key);
58+
}
59+
60+
61+
function replaceKey(address _oldKey, address _newKey) public managerOrSelf returns (bool success) {
62+
_addKey(_newKey, getKeyType(_oldKey));
63+
_removeKey(_oldKey);
64+
return true;
65+
}
66+
67+
68+
69+
function execute(
70+
address _to,
71+
uint256 _value,
72+
bytes _data
73+
)
74+
public
75+
returns (bytes32 executionId)
76+
{
77+
uint256 senderKey = keys[msg.sender];
78+
require(senderKey == MANAGEMENT_KEY || senderKey == ACTION_KEY);
79+
executionId = keccak256(_to, _value, _data, nonce);
80+
ExecutionRequested(executionId, _to, _value, _data);
81+
txx[executionId] = Transaction (
82+
{
83+
to: _to,
84+
value: _value,
85+
data: _data,
86+
nonce: nonce
87+
});
88+
if (senderKey == MANAGEMENT_KEY) {
89+
approve(executionId, true);
90+
}
91+
}
92+
93+
function approve(
94+
bytes32 _id,
95+
bool _approve
96+
)
97+
public
98+
managerOnly
99+
returns (bool success)
100+
{
101+
require(txx[_id].nonce == nonce);
102+
nonce++;
103+
if (_approve) {
104+
success = txx[_id].to.call.value(txx[_id].value)(txx[_id].data);
105+
}
106+
}
107+
108+
109+
function addClaim(
110+
uint256 _claimType,
111+
address _issuer,
112+
uint256 _signatureType,
113+
bytes _signature,
114+
bytes _claim,
115+
string _uri
116+
)
117+
public
118+
claimSignerOnly
119+
returns (bytes32 claimId)
120+
{
121+
claimId = keccak256(_issuer, _claimType);
122+
claims[claimId] = Claim(
123+
{
124+
claimType: _claimType,
125+
issuer: _issuer,
126+
signatureType: _signatureType,
127+
signature: _signature,
128+
claim: _claim,
129+
uri: _uri
130+
}
131+
);
132+
indexes[keccak256(_issuer, _claimType)] = claimsByType[_claimType].length;
133+
claimsByType[_claimType].push(claimId);
134+
}
135+
136+
137+
function removeClaim(bytes32 _claimId) public returns (bool success) {
138+
Claim memory c = claims[_claimId];
139+
require(msg.sender == c.issuer || keys[msg.sender] == MANAGEMENT_KEY || msg.sender == address(this));
140+
uint claimIdTypePos = indexes[_claimId];
141+
delete indexes[_claimId];
142+
bytes32[] storage claimsTypeArr = claimsByType[c.claimType];
143+
bytes32 replacer = claimsTypeArr[claimsTypeArr.length-1];
144+
claimsTypeArr[claimIdTypePos] = replacer;
145+
indexes[replacer] = claimIdTypePos;
146+
delete claims[_claimId];
147+
claimsTypeArr.length--;
148+
return true;
149+
}
150+
151+
152+
function _addKey(address _key, uint256 _type) private {
153+
require(keys[_key] == 0);
154+
KeyAdded(_key, _type);
155+
keys[_key] = _type;
156+
indexes[keccak256(_key, _type)] = keysByType[_type].length;
157+
keysByType[_type].push(_key);
158+
}
159+
160+
161+
function _removeKey(address _key) private {
162+
uint256 kType = keys[_key];
163+
KeyRemoved(_key, kType);
164+
address[] storage keyArr = keysByType[kType];
165+
if (msg.sender != address(this) && kType == MANAGEMENT_KEY && keyArr.length == 1) {
166+
revert();
167+
}
168+
bytes32 oldIndex = keccak256(_key, kType);
169+
uint index = indexes[oldIndex];
170+
delete indexes[oldIndex];
171+
address replacer = keyArr[keyArr.length-1];
172+
keyArr[index] = replacer;
173+
indexes[keccak256(replacer, keys[replacer])] = index;
174+
keyArr.length--;
175+
delete keys[_key];
176+
}
177+
178+
179+
function getKeyType(address _key) public constant returns(uint256 keyType) {
180+
return keys[_key];
181+
}
182+
183+
184+
function getKeysByType(uint256 _type) public constant returns(address[]) {
185+
return keysByType[_type];
186+
}
187+
188+
189+
function getClaim(
190+
bytes32 _claimId
191+
)
192+
public
193+
constant
194+
returns
195+
(uint256 claimType,
196+
address issuer,
197+
uint256 signatureType,
198+
bytes signature,
199+
bytes claim,
200+
string uri)
201+
{
202+
Claim memory _claim = claims[_claimId];
203+
return (_claim.claimType, _claim.issuer, _claim.signatureType, _claim.signature, _claim.claim, _claim.uri);
204+
}
205+
206+
207+
function getClaimsIdByType(uint256 _claimType) public constant returns(bytes32[]) {
208+
return claimsByType[_claimType];
209+
}
210+
211+
212+
}
213+
214+

0 commit comments

Comments
 (0)