interface IIdentityRegistryStorage {

   /**
    *  this event is emitted when an Identity is registered into the storage contract.
    *  the event is emitted by the 'registerIdentity' function
    *  `investorAddress` is the address of the investor's wallet
    *  `identity` is the address of the Identity smart contract (onchainID)
    */
    event IdentityStored(address indexed investorAddress, IIdentity indexed identity);

   /**
    *  this event is emitted when an Identity is removed from the storage contract.
    *  the event is emitted by the 'deleteIdentity' function
    *  `investorAddress` is the address of the investor's wallet
    *  `identity` is the address of the Identity smart contract (onchainID)
    */
    event IdentityUnstored(address indexed investorAddress, IIdentity indexed identity);

   /**
    *  this event is emitted when an Identity has been updated
    *  the event is emitted by the 'updateIdentity' function
    *  `oldIdentity` is the old Identity contract's address to update
    *  `newIdentity` is the new Identity contract's
    */
    event IdentityModified(IIdentity indexed oldIdentity, IIdentity indexed newIdentity);

   /**
    *  this event is emitted when an Identity's country has been updated
    *  the event is emitted by the 'updateCountry' function
    *  `investorAddress` is the address on which the country has been updated
    *  `country` is the numeric code (ISO 3166-1) of the new country
    */
    event CountryModified(address indexed investorAddress, uint16 indexed country);

   /**
    *  this event is emitted when an Identity Registry is bound to the storage contract
    *  the event is emitted by the 'addIdentityRegistry' function
    *  `identityRegistry` is the address of the identity registry added
    */
    event IdentityRegistryBound(address indexed identityRegistry);

   /**
    *  this event is emitted when an Identity Registry is unbound from the storage contract
    *  the event is emitted by the 'removeIdentityRegistry' function
    *  `identityRegistry` is the address of the identity registry removed
    */
    event IdentityRegistryUnbound(address indexed identityRegistry);

   /**
    *  @dev Returns the identity registries linked to the storage contract
    */
    function linkedIdentityRegistries() external view returns (address[] memory);

   /**
    *  @dev Returns the onchainID of an investor.
    *  @param _userAddress The wallet of the investor
    */
    function storedIdentity(address _userAddress) external view returns (IIdentity);

   /**
    *  @dev Returns the country code of an investor.
    *  @param _userAddress The wallet of the investor
    */
    function storedInvestorCountry(address _userAddress) external view returns (uint16);

   /**
    *  @dev adds an identity contract corresponding to a user address in the storage.
    *  Requires that the user doesn't have an identity contract already registered.
    *  This function can only be called by an address set as agent of the smart contract
    *  @param _userAddress The address of the user
    *  @param _identity The address of the user's identity contract
    *  @param _country The country of the investor
    *  emits `IdentityStored` event
    */
    function addIdentityToStorage(address _userAddress, IIdentity _identity, uint16 _country) external;

   /**
    *  @dev Removes an user from the storage.
    *  Requires that the user have an identity contract already deployed that will be deleted.
    *  This function can only be called by an address set as agent of the smart contract
    *  @param _userAddress The address of the user to be removed
    *  emits `IdentityUnstored` event
    */
    function removeIdentityFromStorage(address _userAddress) external;

   /**
    *  @dev Updates the country corresponding to a user address.
    *  Requires that the user should have an identity contract already deployed that will be replaced.
    *  This function can only be called by an address set as agent of the smart contract
    *  @param _userAddress The address of the user
    *  @param _country The new country of the user
    *  emits `CountryModified` event
    */
    function modifyStoredInvestorCountry(address _userAddress, uint16 _country) external;

   /**
    *  @dev Updates an identity contract corresponding to a user address.
    *  Requires that the user address should be the owner of the identity contract.
    *  Requires that the user should have an identity contract already deployed that will be replaced.
    *  This function can only be called by an address set as agent of the smart contract
    *  @param _userAddress The address of the user
    *  @param _identity The address of the user's new identity contract
    *  emits `IdentityModified` event
    */
    function modifyStoredIdentity(address _userAddress, IIdentity _identity) external;

   /**
    *  @notice Transfers the Ownership of the Identity Registry Storage to a new Owner.
    *  This function can only be called by the wallet set as owner of the smart contract
    *  @param _newOwner The new owner of this contract.
    */
    function transferOwnershipOnIdentityRegistryStorage(address _newOwner) external;

   /**
    *  @notice Adds an identity registry as agent of the Identity Registry Storage Contract.
    *  This function can only be called by the wallet set as owner of the smart contract
    *  This function adds the identity registry to the list of identityRegistries linked to the storage contract
    *  @param _identityRegistry The identity registry address to add.
    */
    function bindIdentityRegistry(address _identityRegistry) external;

   /**
    *  @notice Removes an identity registry from being agent of the Identity Registry Storage Contract.
    *  This function can only be called by the wallet set as owner of the smart contract
    *  This function removes the identity registry from the list of identityRegistries linked to the storage contract
    *  @param _identityRegistry The identity registry address to remove.
    */
    function unbindIdentityRegistry(address _identityRegistry) external;
}
function modifyStoredIdentity(address _userAddress, IIdentity _identity) external;

/**
 *  @dev Updates an identity contract corresponding to a user address.
 *  Requires that the user address should be the owner of the identity contract.
 *  Requires that the user should have an identity contract already deployed that will be replaced.
 *  This function can only be called by an address set as agent of the smart contract
 *  @param _userAddress The address of the user
 *  @param _identity The address of the user's new identity contract
 *  emits `IdentityModified` event
 */