0

I am using ERC725v1 and ERC735 Interfaces to add a contract which can deploy an ERC725 based Identity contract that can hold an Identity key and further Add Claims from that Identity for the verification purposes

The problem is that, once the Identity contract is deployed e.g. Remix, it doesn't allow me to deploy the claim holder contract in order to add a claim to the user identity

I am using the code structure from origin-protocol and have made modifications and updated it to solidity v0.5.11.

The code has been tested on Remix after flattening these files but I can only deploy the Identity Contract and even though the Claim Holder Contract is linked with Identity but after deployment, it doesn't provide any methods from Claims Contract e.g. addClaim()

Here are the contracts I am using

Claim Holder Contract

pragma solidity ^0.5.11;

import "./ERC735.sol";
import "./Identity.sol";


contract ClaimHolder is Identity, ERC735 {
    mapping(bytes32 => Claim) claims;
    mapping(uint256 => bytes32[]) claimsByType;

    function addClaim(
        uint256 _claimType,
        uint256 _scheme,
        address _issuer,
        bytes memory _signature,
        bytes memory _data,
        string memory _uri
    ) public returns (bytes32 claimRequestId) {
        bytes32 claimId = keccak256(abi.encodePacked(_issuer, _claimType));

        if (msg.sender != address(this)) {
            require(
                keyHasPurpose(keccak256(abi.encodePacked(msg.sender)), 3),
                "Sender does not have claim signer key"
            );
        }

        if (claims[claimId].issuer != _issuer) {
            claimsByType[_claimType].push(claimId);
        }

        claims[claimId].claimType = _claimType;
        claims[claimId].scheme = _scheme;
        claims[claimId].issuer = _issuer;
        claims[claimId].signature = _signature;
        claims[claimId].data = _data;
        claims[claimId].uri = _uri;

        emit ClaimAdded(
            claimId,
            _claimType,
            _scheme,
            _issuer,
            _signature,
            _data,
            _uri
        );

        return claimId;
    }

    function removeClaim(bytes32 _claimId) public returns (bool success) {
        if (msg.sender != address(this)) {
            require(
                keyHasPurpose(keccak256(abi.encodePacked(msg.sender)), 1),
                "Sender does not have management key"
            );
        }

        emit ClaimRemoved(
            _claimId,
            claims[_claimId].claimType,
            claims[_claimId].scheme,
            claims[_claimId].issuer,
            claims[_claimId].signature,
            claims[_claimId].data,
            claims[_claimId].uri
        );

        delete claims[_claimId];
        return true;
    }

    function getClaim(bytes32 _claimId)
        public
        view
        returns (
            uint256 claimType,
            uint256 scheme,
            address issuer,
            bytes memory signature,
            bytes memory data,
            string memory uri
        )
    {
        return (
            claims[_claimId].claimType,
            claims[_claimId].scheme,
            claims[_claimId].issuer,
            claims[_claimId].signature,
            claims[_claimId].data,
            claims[_claimId].uri
        );
    }

    function getClaimIdsByType(uint256 _claimType)
        public
        view
        returns (bytes32[] memory claimIds)
    {
        return claimsByType[_claimType];
    }

}

KEY Management Contract as Identity

pragma solidity ^0.5.11;

import "./ERC725.sol";

contract Identity is ERC725 {

    uint256 executionNonce;

    // Key Management
    struct Execution {
        address to;
        uint256 value;
        bytes data;
        bool approved;
        bool executed;
    }

    mapping(bytes32 => Key) keys;
    mapping(uint256 => bytes32[]) keysByPurpose;
    mapping(uint256 => Execution) executions;

    event ExecutionFailed(
        uint256 indexed executionId,
        address indexed to,
        uint256 indexed value,
        bytes data
    );

    constructor() public {
        bytes32 _key = keccak256(abi.encodePacked(msg.sender));
        keys[_key].key = _key;
        keys[_key].purpose = 1;
        keys[_key].keyType = 1;
        keysByPurpose[1].push(_key);

        emit KeyAdded(_key, keys[_key].purpose, 1);
    }

    modifier onlyOwner() {
        require(
            msg.sender == identityOwner,
            "Only owner can call this function."
        );
        _;
    }

    //Get User Key
    function getKey(bytes32 _key)
        public
        view
        returns (uint256 purpose, uint256 keyType, bytes32 key)
    {
        return (keys[_key].purpose, keys[_key].keyType, keys[_key].key);
    }

    function getKeyPurpose(bytes32 _key) public view returns (uint256 purpose) {
        return (keys[_key].purpose);
    }

    function getKeysByPurpose(uint256 _purpose)
        public
        view
        returns (
            bytes32[] memory
        )
    {
        return keysByPurpose[_purpose];
    }

    function addKey(bytes32 _key, uint256 _purpose, uint256 _type)
        public
        returns (bool success)
    {
        require(keys[_key].key != _key, "Key already exists"); // Key should not already exist
        if (msg.sender != address(this)) {
            require(
                keyHasPurpose(keccak256(abi.encodePacked(msg.sender)), 1),
                "Sender does not have Identity key"
            ); // Sender has IDENTITY KEY
        }

        keys[_key].key = _key;
        keys[_key].purpose = _purpose;
        keys[_key].keyType = _type;

        keysByPurpose[_purpose].push(_key);

        emit KeyAdded(_key, _purpose, _type);

        return true;
    }

    function approve(uint256 _id, bool _approve)
        public
        returns (bool _success)
    {
        require(
            keyHasPurpose(keccak256(abi.encodePacked(msg.sender)), 2),
            "Sender does not have action key"
        );

        emit Approved(_id, _approve);

        if (_approve == true) {
            executions[_id].approved = true;
            (bool success, ) = executions[_id].to.call(
                abi.encode(executions[_id].data, 0)
            );

            if (success) {
                executions[_id].executed = true;
                emit Executed(
                    _id,
                    executions[_id].to,
                    executions[_id].value,
                    executions[_id].data
                );
                return success;
            } else {
                emit ExecutionFailed(
                    _id,
                    executions[_id].to,
                    executions[_id].value,
                    executions[_id].data
                );
                return false;
            }
        } else {
            executions[_id].approved = false;
        }
        return true;
    }

    function execute(address _to, uint256 _value, bytes memory _data)
        public
        returns (uint256 executionId)
    {
        require(!executions[executionNonce].executed, "Already executed");
        executions[executionNonce].to = _to;
        executions[executionNonce].value = _value;
        executions[executionNonce].data = _data;

        emit ExecutionRequested(executionNonce, _to, _value, _data);

        if (
            keyHasPurpose(keccak256(abi.encodePacked(msg.sender)), 1) ||
            keyHasPurpose(keccak256(abi.encodePacked(msg.sender)), 2)
        ) {
            approve(executionNonce, true);
        }

        executionNonce++;
        return executionNonce - 1;
    }

    function removeKey(bytes32 _key) public returns (bool success) {
        require(keys[_key].key == _key, "No such key");
        emit KeyRemoved(keys[_key].key, keys[_key].purpose, keys[_key].keyType);

        /* uint index;
        (index,) = keysByPurpose[keys[_key].purpose.indexOf(_key);
        keysByPurpose[keys[_key].purpose.removeByIndex(index); */

        delete keys[_key];

        return true;
    }

    function keyHasPurpose(bytes32 _key, uint256 _purpose)
        public
        view
        returns (bool result)
    {
        bool isThere;
        if (keys[_key].key == 0) return false;
        isThere = keys[_key].purpose <= _purpose;
        return isThere;
    }

}

ERC725 Interface

pragma solidity ^0.5.11;

contract ERC725 {
    uint256 constant MANAGEMENT_KEY = 1;



    //Key Management Events
    event KeyAdded(
        bytes32 indexed key,
        uint256 indexed purpose,
        uint256 indexed keyType
    );
    event KeyRemoved(
        bytes32 indexed key,
        uint256 indexed purpose,
        uint256 indexed keyType
    );
    event ExecutionRequested(
        uint256 indexed executionId,
        address indexed to,
        uint256 indexed value,
        bytes data
    );
    event Executed(
        uint256 indexed executionId,
        address indexed to,
        uint256 indexed value,
        bytes data
    );
    event Approved(uint256 indexed executionId, bool approved);

    struct Key {
        uint256 purpose;
        uint256 keyType;
        bytes32 key;
    }


    //View Key
    function getKey(bytes32 _key)
        public
        view
        returns (uint256 purpose, uint256 keyType, bytes32 key);

    // Fetch Key Purpose
    function getKeyPurpose(bytes32 _key) public view returns (uint256 purpose);

    // Fetch Keys by Purpose
    function getKeysByPurpose(uint256 _purpose)
        public
        view
        returns (bytes32[] memory keys);

    //Key Addition
    function addKey(bytes32 _key, uint256 _purpose, uint256 _keyType)
        public
        returns (bool success);

    function execute(address _to, uint256 _value, bytes memory _data)
        public
        returns (uint256 executionId);

    function approve(uint256 _id, bool _approve) public returns (bool success);

}

ERC735 Interface

pragma solidity ^0.5.11;

// The file provides the Interface for ERC735 Claims

contract ERC735 {


    event ClaimAdded(
        bytes32 indexed claimId,
        uint256 indexed claimType,
        uint256 scheme,
        address indexed issuer,
        bytes signature,
        bytes data,
        string uri
    );
    event ClaimRemoved(
        bytes32 indexed claimId,
        uint256 indexed claimType,
        uint256 scheme,
        address indexed issuer,
        bytes signature,
        bytes data,
        string uri
    );


    struct Claim {
        uint256 claimType;
        uint256 scheme;
        address issuer; // msg.sender
        bytes signature; // this.address + claimType + data
        bytes data;
        string uri;
    }

    function getClaim(bytes32 _claimId)
        public
        view
        returns (
            uint256 claimType,
            uint256 scheme,
            address issuer,
            bytes memory,
            bytes memory,
            string memory
        );
    function getClaimIdsByType(uint256 _claimType)
        public
        view
        returns (bytes32[] memory); 
    function addClaim(
        uint256 _claimType,
        uint256 _scheme,
        address issuer,
        bytes memory, 
        bytes memory, 
        string memory 
    ) public returns (bytes32 claimRequestId);
    function removeClaim(bytes32 _claimId) public returns (bool success); 
}

  • What is identityOwner? (your code doesn't compile). – goodvibration Mar 22 at 6:04
  • Other than that, contract ClaimHolder can be successfully deployed and function addClaim can be successfully executed on Ganache. So perhaps there is something else in your contract which you have removed for the sake of this question but forgot to tell us about. – goodvibration Mar 22 at 6:13
  • The identity contract did not compile as identityOwner was not defined, thus, I made some changes to your contract: Added: address public identityOwner; Inside constructor: identityOwner = msg.sender; before emitting the KeyAdded event Doing this I was able to compile and deploy both the contracts and was also able to invoke addClaim function – balajipachai Mar 22 at 7:44
  • @goodvibration, I was previously testing it with Remix but will check it with Gananche as well. Thanks – Qasid Labeed Mar 22 at 8:11
  • @balajipachai, Thanks for this, let me check the code with this update – Qasid Labeed Mar 22 at 8:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.