refactor execution and multisig process
This commit is contained in:
parent
8938d03911
commit
a14485c0b0
|
@ -12,9 +12,10 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
mapping (uint256 => bytes32[]) claimsByType;
|
mapping (uint256 => bytes32[]) claimsByType;
|
||||||
|
|
||||||
mapping (bytes32 => uint256) indexes;
|
mapping (bytes32 => uint256) indexes;
|
||||||
mapping (uint256 => Transaction) txx;
|
mapping (uint256 => Transaction) multisigTx;
|
||||||
mapping (uint256 => uint256) purposeThreshold;
|
mapping (uint256 => uint256) purposeThreshold;
|
||||||
|
|
||||||
|
uint256 txCount;
|
||||||
uint256 nonce;
|
uint256 nonce;
|
||||||
address recoveryContract;
|
address recoveryContract;
|
||||||
bytes32 recoveryManager;
|
bytes32 recoveryManager;
|
||||||
|
@ -24,12 +25,11 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
address to;
|
address to;
|
||||||
uint256 value;
|
uint256 value;
|
||||||
bytes data;
|
bytes data;
|
||||||
uint256 nonce;
|
|
||||||
uint256 approverCount;
|
uint256 approverCount;
|
||||||
mapping(bytes32 => bool) approvals;
|
mapping(bytes32 => bool) approvals;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier requiredKey(uint256 keyPurpose) {
|
modifier msgSenderKey(uint256 keyPurpose) {
|
||||||
if(msg.sender == address(this)) {
|
if(msg.sender == address(this)) {
|
||||||
_;
|
_;
|
||||||
} else {
|
} else {
|
||||||
|
@ -58,7 +58,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier validECDSAKey (
|
modifier keyMessageSigned (
|
||||||
bytes32 _key,
|
bytes32 _key,
|
||||||
bytes32 _messageHash,
|
bytes32 _messageHash,
|
||||||
bytes _signature
|
bytes _signature
|
||||||
|
@ -128,7 +128,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
uint256 _type
|
uint256 _type
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
requiredKey(MANAGEMENT_KEY)
|
msgSenderKey(MANAGEMENT_KEY)
|
||||||
returns (bool success)
|
returns (bool success)
|
||||||
{
|
{
|
||||||
_addKey(_key, _purpose, _type);
|
_addKey(_key, _purpose, _type);
|
||||||
|
@ -141,7 +141,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
uint256 _newType
|
uint256 _newType
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
requiredKey(MANAGEMENT_KEY)
|
msgSenderKey(MANAGEMENT_KEY)
|
||||||
returns (bool success)
|
returns (bool success)
|
||||||
{
|
{
|
||||||
uint256 purpose = keys[_oldKey].purpose;
|
uint256 purpose = keys[_oldKey].purpose;
|
||||||
|
@ -155,7 +155,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
uint256 _purpose
|
uint256 _purpose
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
requiredKey(MANAGEMENT_KEY)
|
msgSenderKey(MANAGEMENT_KEY)
|
||||||
returns (bool success)
|
returns (bool success)
|
||||||
{
|
{
|
||||||
_removeKey(_key, _purpose);
|
_removeKey(_key, _purpose);
|
||||||
|
@ -168,27 +168,16 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
bytes _data
|
bytes _data
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
returns (uint256 executionId)
|
returns (uint256 txId)
|
||||||
{
|
{
|
||||||
uint256 requiredKey = _to == address(this) ? MANAGEMENT_KEY : ACTION_KEY;
|
txId = _execute(keccak256(msg.sender), _to, _value, _data);
|
||||||
if (purposeThreshold[requiredKey] == 1) {
|
|
||||||
executionId = nonce; //(?) useless in this case
|
|
||||||
nonce++; //(?) should increment
|
|
||||||
require(isKeyPurpose(keccak256(msg.sender), requiredKey));
|
|
||||||
_to.call.value(_value)(_data); //(?) success not used
|
|
||||||
emit Executed(executionId, _to, _value, _data); //no information on success
|
|
||||||
} else {
|
|
||||||
executionId = _execute(_to, _value, _data);
|
|
||||||
approve(executionId, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function approve(uint256 _id, bool _approval)
|
function approve(uint256 _id, bool _approval)
|
||||||
public
|
public
|
||||||
returns (bool success)
|
returns (bool success)
|
||||||
{
|
{
|
||||||
return _approve(keccak256(msg.sender), _id, _approval);
|
return _approveRequest(keccak256(msg.sender), _id, _approval);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setMinimumApprovalsByKeyType(
|
function setMinimumApprovalsByKeyType(
|
||||||
|
@ -196,14 +185,13 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
uint256 _minimumApprovals
|
uint256 _minimumApprovals
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
requiredKey(MANAGEMENT_KEY)
|
msgSenderKey(MANAGEMENT_KEY)
|
||||||
{
|
{
|
||||||
require(_minimumApprovals > 0);
|
require(_minimumApprovals > 0);
|
||||||
require(_minimumApprovals <= keysByPurpose[_purpose].length);
|
require(_minimumApprovals <= keysByPurpose[_purpose].length);
|
||||||
purposeThreshold[_purpose] = _minimumApprovals;
|
purposeThreshold[_purpose] = _minimumApprovals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function addClaim(
|
function addClaim(
|
||||||
uint256 _claimType,
|
uint256 _claimType,
|
||||||
uint256 _scheme,
|
uint256 _scheme,
|
||||||
|
@ -224,7 +212,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
require(isKeyPurpose(keccak256(msg.sender), CLAIM_SIGNER_KEY));
|
require(isKeyPurpose(keccak256(msg.sender), CLAIM_SIGNER_KEY));
|
||||||
_execute(address(this), 0, msg.data);
|
_requestApproval(address(this), 0, msg.data);
|
||||||
emit ClaimRequested(
|
emit ClaimRequested(
|
||||||
claimHash,
|
claimHash,
|
||||||
_claimType,
|
_claimType,
|
||||||
|
@ -352,14 +340,14 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
return claimsByType[_claimType];
|
return claimsByType[_claimType];
|
||||||
}
|
}
|
||||||
|
|
||||||
function approveECDSA(
|
function approveMessageSigned(
|
||||||
uint256 _id,
|
uint256 _id,
|
||||||
bool _approval,
|
bool _approval,
|
||||||
bytes32 _key,
|
bytes32 _key,
|
||||||
bytes _signature
|
bytes _signature
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
validECDSAKey(
|
keyMessageSigned(
|
||||||
_key,
|
_key,
|
||||||
keccak256(
|
keccak256(
|
||||||
address(this),
|
address(this),
|
||||||
|
@ -371,10 +359,10 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
)
|
)
|
||||||
returns (bool success)
|
returns (bool success)
|
||||||
{
|
{
|
||||||
return _approve(_key, _id, _approval);
|
return _approveRequest(_key, _id, _approval);
|
||||||
}
|
}
|
||||||
|
|
||||||
function executeECDSA(
|
function executeMessageSigned(
|
||||||
address _to,
|
address _to,
|
||||||
uint256 _value,
|
uint256 _value,
|
||||||
bytes _data,
|
bytes _data,
|
||||||
|
@ -383,7 +371,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
bytes _signature
|
bytes _signature
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
validECDSAKey(
|
keyMessageSigned(
|
||||||
_key,
|
_key,
|
||||||
keccak256(
|
keccak256(
|
||||||
address(this),
|
address(this),
|
||||||
|
@ -395,16 +383,14 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
),
|
),
|
||||||
_signature
|
_signature
|
||||||
)
|
)
|
||||||
requiredKey(_to == address(this) ? MANAGEMENT_KEY : ACTION_KEY)
|
returns (uint256 txId)
|
||||||
returns (uint256 executionId)
|
|
||||||
{
|
{
|
||||||
executionId = _execute(_to, _value, _data);
|
txId = _execute(_key, _to, _value, _data);
|
||||||
_approve(_key, executionId, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupRecovery(address _recoveryContract)
|
function setupRecovery(address _recoveryContract)
|
||||||
public
|
public
|
||||||
requiredKey(MANAGEMENT_KEY)
|
msgSenderKey(MANAGEMENT_KEY)
|
||||||
{
|
{
|
||||||
require(recoveryContract == address(0));
|
require(recoveryContract == address(0));
|
||||||
recoveryContract = _recoveryContract;
|
recoveryContract = _recoveryContract;
|
||||||
|
@ -423,27 +409,45 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
}
|
}
|
||||||
|
|
||||||
function _execute(
|
function _execute(
|
||||||
|
bytes32 _key,
|
||||||
address _to,
|
address _to,
|
||||||
uint256 _value,
|
uint256 _value,
|
||||||
bytes _data
|
bytes _data
|
||||||
)
|
)
|
||||||
private
|
internal
|
||||||
returns (uint256 executionId)
|
returns (uint256 txId)
|
||||||
{
|
{
|
||||||
executionId = nonce;
|
uint256 requiredPurpose = _to == address(this) ? MANAGEMENT_KEY : ACTION_KEY;
|
||||||
nonce++;
|
require(isKeyPurpose(_key, requiredPurpose));
|
||||||
txx[executionId] = Transaction({
|
if (purposeThreshold[requiredPurpose] == 1) {
|
||||||
|
txId = txCount++;
|
||||||
|
_commitCall(txId, _to, _value, _data);
|
||||||
|
} else {
|
||||||
|
txId = _requestApproval(_to, _value, _data);
|
||||||
|
_approveRequest(_key, txId, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _requestApproval(
|
||||||
|
address _to,
|
||||||
|
uint256 _value,
|
||||||
|
bytes _data
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
returns (uint256 txId)
|
||||||
|
{
|
||||||
|
txId = txCount++;
|
||||||
|
multisigTx[txCount] = Transaction({
|
||||||
valid: true,
|
valid: true,
|
||||||
to: _to,
|
to: _to,
|
||||||
value: _value,
|
value: _value,
|
||||||
data: _data,
|
data: _data,
|
||||||
nonce: nonce,
|
|
||||||
approverCount: 0
|
approverCount: 0
|
||||||
});
|
});
|
||||||
emit ExecutionRequested(executionId, _to, _value, _data);
|
emit ExecutionRequested(txId, _to, _value, _data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _approve(
|
function _approveRequest(
|
||||||
bytes32 _key,
|
bytes32 _key,
|
||||||
uint256 _id,
|
uint256 _id,
|
||||||
bool _approval
|
bool _approval
|
||||||
|
@ -452,33 +456,43 @@ contract Identity is ERC725, ERC735, MessageSigned {
|
||||||
returns(bool success) //(?) should return approved instead of success?
|
returns(bool success) //(?) should return approved instead of success?
|
||||||
{
|
{
|
||||||
|
|
||||||
Transaction memory trx = txx[_id];
|
Transaction memory approvedTx = multisigTx[_id];
|
||||||
require(trx.valid);
|
require(approvedTx.valid);
|
||||||
uint256 requiredKeyPurpose = trx.to == address(this) ? MANAGEMENT_KEY : ACTION_KEY;
|
uint256 requiredKeyPurpose = approvedTx.to == address(this) ? MANAGEMENT_KEY : ACTION_KEY;
|
||||||
require(isKeyPurpose(_key, requiredKeyPurpose));
|
require(isKeyPurpose(_key, requiredKeyPurpose));
|
||||||
bytes32 keyHash = keccak256(_key, requiredKeyPurpose);
|
require(multisigTx[_id].approvals[_key] != _approval);
|
||||||
require(txx[_id].approvals[keyHash] != _approval);
|
|
||||||
|
|
||||||
if (_approval) {
|
|
||||||
trx.approverCount++;
|
|
||||||
} else {
|
|
||||||
trx.approverCount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit Approved(_id, _approval);
|
emit Approved(_id, _approval);
|
||||||
|
|
||||||
if (trx.approverCount < purposeThreshold[requiredKeyPurpose]) {
|
if (_approval) {
|
||||||
txx[_id].approvals[keyHash] = _approval;
|
if (approvedTx.approverCount + 1 == purposeThreshold[requiredKeyPurpose]) {
|
||||||
txx[_id] = trx;
|
delete multisigTx[_id];
|
||||||
|
return _commitCall(_id, approvedTx.to, approvedTx.value, approvedTx.data);
|
||||||
} else {
|
} else {
|
||||||
delete txx[_id];
|
multisigTx[_id].approverCount++;
|
||||||
//(?) success should be included in event?
|
|
||||||
success = address(trx.to).call.value(trx.value)(trx.data);
|
|
||||||
if(success){
|
|
||||||
emit Executed(_id, trx.to, trx.value, trx.data);
|
|
||||||
} else {
|
|
||||||
emit ExecutionFailed(_id, trx.to, trx.value, trx.data));
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
multisigTx[_id].approverCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
multisigTx[_id].approvals[_key] = _approval;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _commitCall(
|
||||||
|
uint256 _txId,
|
||||||
|
address _to,
|
||||||
|
uint256 _value,
|
||||||
|
bytes _data
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
returns(bool success)
|
||||||
|
{
|
||||||
|
nonce++;
|
||||||
|
success = _to.call.value(_value)(_data);
|
||||||
|
if (success) {
|
||||||
|
emit Executed(_txId, _to, _value, _data);
|
||||||
|
} else {
|
||||||
|
emit ExecutionFailed(_txId, _to, _value, _data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue